From e4c35c2eec665f3f74a2b2f587fd2a1324b31841 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 13 Jun 2026 11:30:18 -0700 Subject: [PATCH 001/228] mac80211: backport ath9k memset fixes from upstream Backport two upstream commits that replace memset() on coherent DMA descriptor rings with explicit WRITE_ONCE() status word stores. On 32-bit PowerPC platforms like apm821xx, coherent DMA memory may be mapped uncached. The optimized memset() path can use dcbz there, which triggers alignment warnings and spams the kernel log. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23776 Signed-off-by: Jonas Jelonek --- ...Clear-DMA-descriptors-without-memset.patch | 108 ++++++++++++++++++ ...9k-remove-TX99-power-array-zero-init.patch | 34 ++++++ 2 files changed, 142 insertions(+) create mode 100644 package/kernel/mac80211/patches/ath9k/600-wifi-ath9k-Clear-DMA-descriptors-without-memset.patch create mode 100644 package/kernel/mac80211/patches/ath9k/601-wifi-ath9k-remove-TX99-power-array-zero-init.patch diff --git a/package/kernel/mac80211/patches/ath9k/600-wifi-ath9k-Clear-DMA-descriptors-without-memset.patch b/package/kernel/mac80211/patches/ath9k/600-wifi-ath9k-Clear-DMA-descriptors-without-memset.patch new file mode 100644 index 0000000000..9c64ae2c03 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/600-wifi-ath9k-Clear-DMA-descriptors-without-memset.patch @@ -0,0 +1,108 @@ +From 3e14d832e30b10478d2b0945ff2651f6784385a7 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Sat, 16 May 2026 16:43:10 -0700 +Subject: [PATCH] wifi: ath9k: Clear DMA descriptors without memset + +Clear ath9k DMA descriptors with explicit status word stores instead of +memset(). The descriptor rings are coherent DMA memory, which may be +mapped uncached on 32-bit powerpc. The optimized memset() path can use +dcbz there and trigger an alignment warning. + +Use WRITE_ONCE() for the descriptor status words so the compiler keeps +the clears as ordinary stores instead of folding them back into bulk +memset(). This covers AR9003 TX status descriptors as well as the RX +status area cleared when setting up RX descriptors. + +Assisted-by: Codex:GPT-5.5 +Signed-off-by: Rosen Penev +--- + drivers/net/wireless/ath/ath9k/ar9002_mac.c | 15 +++++++++++++- + drivers/net/wireless/ath/ath9k/ar9003_mac.c | 23 +++++++++++++++++---- + 2 files changed, 33 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c ++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c +@@ -403,6 +403,19 @@ static int ar9002_hw_get_duration(struct + } + } + ++static void ath9k_hw_clear_rxdesc_status(struct ar5416_desc *ads) ++{ ++ WRITE_ONCE(ads->u.rx.status0, 0); ++ WRITE_ONCE(ads->u.rx.status1, 0); ++ WRITE_ONCE(ads->u.rx.status2, 0); ++ WRITE_ONCE(ads->u.rx.status3, 0); ++ WRITE_ONCE(ads->u.rx.status4, 0); ++ WRITE_ONCE(ads->u.rx.status5, 0); ++ WRITE_ONCE(ads->u.rx.status6, 0); ++ WRITE_ONCE(ads->u.rx.status7, 0); ++ WRITE_ONCE(ads->u.rx.status8, 0); ++} ++ + void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, + u32 size, u32 flags) + { +@@ -412,7 +425,7 @@ void ath9k_hw_setuprxdesc(struct ath_hw + if (flags & ATH9K_RXDESC_INTREQ) + ads->ds_ctl1 |= AR_RxIntrReq; + +- memset(&ads->u.rx, 0, sizeof(ads->u.rx)); ++ ath9k_hw_clear_rxdesc_status(ads); + } + EXPORT_SYMBOL(ath9k_hw_setuprxdesc); + +--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c +@@ -352,6 +352,19 @@ static bool ar9003_hw_get_isr(struct ath + return true; + } + ++static void ath9k_hw_clear_txstatus(struct ar9003_txs *ads) ++{ ++ WRITE_ONCE(ads->ds_info, 0); ++ WRITE_ONCE(ads->status1, 0); ++ WRITE_ONCE(ads->status2, 0); ++ WRITE_ONCE(ads->status3, 0); ++ WRITE_ONCE(ads->status4, 0); ++ WRITE_ONCE(ads->status5, 0); ++ WRITE_ONCE(ads->status6, 0); ++ WRITE_ONCE(ads->status7, 0); ++ WRITE_ONCE(ads->status8, 0); ++} ++ + static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, + struct ath_tx_status *ts) + { +@@ -370,7 +383,7 @@ static int ar9003_hw_proc_txdesc(struct + (MS(ads->ds_info, AR_TxRxDesc) != 1)) { + ath_dbg(ath9k_hw_common(ah), XMIT, + "Tx Descriptor error %x\n", ads->ds_info); +- memset(ads, 0, sizeof(*ads)); ++ ath9k_hw_clear_txstatus(ads); + return -EIO; + } + +@@ -427,7 +440,7 @@ static int ar9003_hw_proc_txdesc(struct + ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); + ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); + +- memset(ads, 0, sizeof(*ads)); ++ ath9k_hw_clear_txstatus(ads); + + return 0; + } +@@ -591,10 +604,12 @@ EXPORT_SYMBOL(ath9k_hw_process_rxdesc_ed + + void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) + { ++ int i; ++ + ah->ts_tail = 0; + +- memset((void *) ah->ts_ring, 0, +- ah->ts_size * sizeof(struct ar9003_txs)); ++ for (i = 0; i < ah->ts_size; i++) ++ ath9k_hw_clear_txstatus(&ah->ts_ring[i]); + + ath_dbg(ath9k_hw_common(ah), XMIT, + "TS Start 0x%x End 0x%x Virt %p, Size %d\n", diff --git a/package/kernel/mac80211/patches/ath9k/601-wifi-ath9k-remove-TX99-power-array-zero-init.patch b/package/kernel/mac80211/patches/ath9k/601-wifi-ath9k-remove-TX99-power-array-zero-init.patch new file mode 100644 index 0000000000..84c7e67fa9 --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/601-wifi-ath9k-remove-TX99-power-array-zero-init.patch @@ -0,0 +1,34 @@ +From 0da0cfb0840f7fe7df34bde4f787d3435e3db674 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Sat, 16 May 2026 20:28:16 -0700 +Subject: [PATCH] wifi: ath9k: remove TX99 power array zero init + +This array is fully initialized in the loop itself. No need to zero +initialize and then overwrite. + +Remove static from the array. This was a holdover from when the array +was a static global variable. It no longer confers any benefit. + +Also add a min() call to avoid the manual if/ternary operation. + +Assisted-by: Codex:GPT-5.5 +Signed-off-by: Rosen Penev +--- + drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -1737,10 +1737,10 @@ static void ar9003_hw_tx99_stop(struct a + + static void ar9003_hw_tx99_set_txpower(struct ath_hw *ah, u8 txpower) + { +- static u8 p_pwr_array[ar9300RateSize] = { 0 }; ++ u8 p_pwr_array[ar9300RateSize]; + unsigned int i; + +- txpower = txpower <= MAX_RATE_POWER ? txpower : MAX_RATE_POWER; ++ txpower = min(txpower, MAX_RATE_POWER); + for (i = 0; i < ar9300RateSize; i++) + p_pwr_array[i] = txpower; + From 7e7bd602ea8967858267c2a6929f4dbaffe90839 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 13 Jun 2026 01:17:23 +0200 Subject: [PATCH 002/228] fritz-tools: fix out-of-bounds memset in TFFS segment expansion When growing the segment array in find_entry(), the memset() that zeroes the newly allocated slots computed the destination with redundant sizeof scaling: memset(segments + (num_segments * sizeof(struct tffs_entry_segment)), ...) segments is a typed pointer, so pointer arithmetic already scales by the element size. Multiplying the offset by sizeof again advances the destination by num_segments * sizeof^2 bytes, landing far outside the realloc()'d buffer and zeroing unrelated heap memory whenever a TFFS entry spans multiple segments that require array expansion. Drop the redundant multiplication so the memset targets segments[num_segments]. This is a robustness fix for malformed/corrupt TFFS content; the parser only reads the on-device nand-tffs MTD partition as root, so it is not considered security relevant. Reported-by: @Vasco0x4 Assisted-by: Claude:claude-opus-4-8 Link: https://github.com/openwrt/openwrt/pull/23763 Signed-off-by: Hauke Mehrtens --- package/utils/fritz-tools/Makefile | 2 +- package/utils/fritz-tools/src/fritz_tffs_nand_read.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package/utils/fritz-tools/Makefile b/package/utils/fritz-tools/Makefile index b43fe20e9e..4cb196bbfe 100644 --- a/package/utils/fritz-tools/Makefile +++ b/package/utils/fritz-tools/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=fritz-tools -PKG_RELEASE:=3 +PKG_RELEASE:=4 CMAKE_INSTALL:=1 include $(INCLUDE_DIR)/package.mk diff --git a/package/utils/fritz-tools/src/fritz_tffs_nand_read.c b/package/utils/fritz-tools/src/fritz_tffs_nand_read.c index 05179bb423..65d405063e 100644 --- a/package/utils/fritz-tools/src/fritz_tffs_nand_read.c +++ b/package/utils/fritz-tools/src/fritz_tffs_nand_read.c @@ -245,7 +245,7 @@ static int find_entry(uint32_t id, struct tffs_entry *entry) uint32_t new_num_segs = next_seg == 0 ? seg + 1 : next_seg + 1; if (new_num_segs > num_segments) { segments = realloc(segments, new_num_segs * sizeof(struct tffs_entry_segment)); - memset(segments + (num_segments * sizeof(struct tffs_entry_segment)), 0x0, + memset(segments + num_segments, 0x0, (new_num_segs - num_segments) * sizeof(struct tffs_entry_segment)); num_segments = new_num_segs; } From 63c0767f3d02f7b10b0f0b5293366bd059a08ca5 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 13 Jun 2026 00:34:46 +0200 Subject: [PATCH 003/228] ead: fix integer underflow in handle_send_a() handle_send_a() computed the SRP "A" parameter length as len = ntohl(msg->len) - sizeof(struct ead_msg_number); sizeof(struct ead_msg_number) is 1, and the subtraction is evaluated in unsigned arithmetic. A packet with msg->len == 0 therefore wraps the result to a huge value which, assigned to the signed int len, becomes -1. The following bounds check is signed: if (len > MAXPARAMLEN + 1) return false; so -1 passes, and memcpy(A.data, number->data, len) runs with len cast to size_t (~SIZE_MAX) against the 257-byte abuf, crashing the daemon. Neither parse_message() nor handle_packet() validate msg->len (only the captured packet length), so an unauthenticated attacker on the local segment can reach this path and crash ead with a single crafted packet. Validate the claimed length in unsigned arithmetic before the subtraction and bound it on both sides. Doing the upper-bound check unsigned as well also closes a 32-bit-only variant where sizeof(ead_packet) + msg->len overflows in handle_packet(), letting a large msg->len reach the same negative-len path. Link: https://github.com/openwrt/openwrt/security/advisories/GHSA-9558-77jp-g3fw Reported-by: @Vasco0x4 Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Hauke Mehrtens --- package/network/services/ead/src/ead.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/package/network/services/ead/src/ead.c b/package/network/services/ead/src/ead.c index ad97c543c5..b065b4100a 100644 --- a/package/network/services/ead/src/ead.c +++ b/package/network/services/ead/src/ead.c @@ -428,11 +428,14 @@ handle_send_a(struct ead_packet *pkt, int len, int *nstate) { struct ead_msg *msg = &pkt->msg; struct ead_msg_number *number = EAD_DATA(msg, number); - len = ntohl(msg->len) - sizeof(struct ead_msg_number); + uint32_t msg_len = ntohl(msg->len); - if (len > MAXPARAMLEN + 1) + if (msg_len < sizeof(struct ead_msg_number) || + msg_len - sizeof(struct ead_msg_number) > MAXPARAMLEN + 1) return false; + len = msg_len - sizeof(struct ead_msg_number); + A.len = len; A.data = abuf; memcpy(A.data, number->data, len); From ecbb5f6e9f6ffe871aa63dc8b1548278ffc5d385 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 16 Jun 2026 01:39:41 +0200 Subject: [PATCH 004/228] uhttpd: update to Git HEAD (2026-06-16) ae015e099986 client: reject unhandled Transfer-Encoding values b78f51847879 client: close connection on invalid chunk length 7b1bec45826b ubus: close connection on POST body parse error Link: https://github.com/openwrt/uhttpd/security/advisories/GHSA-mcfg-c4r7-pjpf Link: https://github.com/openwrt/uhttpd/security/advisories/GHSA-p55c-rmhc-qfm5 Link: https://github.com/openwrt/uhttpd/security/advisories/GHSA-wgwp-64hh-f52p Signed-off-by: Hauke Mehrtens --- package/network/services/uhttpd/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/services/uhttpd/Makefile b/package/network/services/uhttpd/Makefile index 61a856a3b8..915baa07ab 100644 --- a/package/network/services/uhttpd/Makefile +++ b/package/network/services/uhttpd/Makefile @@ -9,9 +9,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/uhttpd.git -PKG_SOURCE_DATE:=2026-05-21 -PKG_SOURCE_VERSION:=1b624f8f814ed568608d756512892416e0431d77 -PKG_MIRROR_HASH:=7fb56c4aa2e67a8d6d90e0cbb91f8108a363d0242bb62a8880c41ad4c10ff5ff +PKG_SOURCE_DATE:=2026-06-16 +PKG_SOURCE_VERSION:=7b1bec45826bd78c8afc993435bdc0f1df2fe399 +PKG_MIRROR_HASH:=ee52821b04cc78f46875e9870b6ed41670606d6b90fb31b31312666c4ed809dd PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=ISC From 5b2c8f4ff94ef7c339586c8a59a684009f1b7194 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 16 Jun 2026 02:19:46 +0200 Subject: [PATCH 005/228] umdns: update to Git HEAD (2026-06-16) 1b5e7bf1cec7 cache: bound cache size and clamp hostile TTLs Link: https://github.com/openwrt/mdnsd/security/advisories/GHSA-jg8f-fhfw-jg46 Signed-off-by: Hauke Mehrtens --- package/network/services/umdns/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/services/umdns/Makefile b/package/network/services/umdns/Makefile index 60a56e2469..40ee5ed492 100644 --- a/package/network/services/umdns/Makefile +++ b/package/network/services/umdns/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_URL=$(PROJECT_GIT)/project/mdnsd.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2026-05-22 -PKG_SOURCE_VERSION:=bd7599d021571e785bd32a75469e7148eb1772e3 -PKG_MIRROR_HASH:=0e1942f8aacb730fa7a32642dbf812ed24f4929fe532039d48ace3cba46c040c +PKG_SOURCE_DATE:=2026-06-16 +PKG_SOURCE_VERSION:=1b5e7bf1cec775b89f1a6068dc0b9df3593b5986 +PKG_MIRROR_HASH:=7d9ec860af2b8217f65cd4af92a61be1925ad171dee9b536c4914cc0080e3303 PKG_MAINTAINER:=John Crispin PKG_LICENSE:=LGPL-2.1 From bd587778450269bdff410e6148a50ba73edceecc Mon Sep 17 00:00:00 2001 From: Daniel Tang Date: Sun, 5 Oct 2025 23:32:30 +0000 Subject: [PATCH 006/228] realtek: add support for V3 variant of SG2008P Add basic support for the TP-Link SG2008P V3 variant. The switch appears to be identical to the V1 variant, except that it uses the MP3924 instead of the TPS23861 PoE chip. Specifications: --------------- * SoC: Realtek RTL8380M * Flash: 32 MiB SPI flash (Vendor varies) * RAM: 256 MiB (Vendor varies) * Ethernet: 8x 10/100/1000 Mbps with PoE on 4 ports * Buttons: 1x "Reset" button on front panel * Power: 53.5V DC barrel jack * UART: 1x serial header, unpopulated * PoE: 1x MPS MP3924 I2C PoE controller Works: ------ - (8) RJ-45 ethernet ports - Switch functions - System LED - Basic PoE support (no driver, but a startup script puts the chip into AUTO mode) Not yet enabled: ---------------- - PoE, Link/Act, PoE max and System LEDs Install via web interface: ------------------------- Not supported at this time. Install via serial console/tftp: -------------------------------- The footprints R27 (0201) and R28 (0402) are not populated. To enable serial console, 50 ohm resistors should be soldered -- any value from 0 ohm to 50 ohm will work. R27 can be replaced by a solder bridge. The u-boot firmware drops to a TP-Link specific "BOOTUTIL" shell at 38400 baud. There is no known way to exit out of this shell, and no way to do anything useful. Ideally, one would trick the bootloader into flashing the sysupgrade image first. However, if the image exceeds 6MiB in size, it will not work. The sysupgrade image can also be flashed. To install OpenWRT: Prepare a tftp server with: 1. server address: 192.168.0.146 2. the image as: "uImage.img" Power on device, and stop boot by pressing any key. Once the shell is active: 1. Ground out the CLK (pin 16) of the ROM (U7) 2. Select option "3. Start" 3. Bootloader notes that "The kernel has been damaged!" 4. Release CLK as sson as bootloader thinks image is corrupted. 5. Bootloader enters automatic recovery -- details printed on console 6. Watch as the bootloader flashes and boots OpenWRT. Blind install via tftp: ----------------------- This method works when it's not feasible to install a serial header. Prepare a tftp server with: 1. server address: 192.168.0.146 2. the image as: "uImage.img" 3. Watch network traffic (tcpdump or wireshark works) 4. Power on the device. 5. Wait 1-2 seconds then ground out the CLK (pin 16) of the ROM (U7) 6. When 192.168.0.30 makes tftp requests, release pin 16 7. Wait 2-3 minutes for device to auto-flash and boot OpenWRT Signed-off-by: Daniel Tang Link: https://github.com/openwrt/openwrt/pull/20616 Signed-off-by: Jonas Jelonek --- .../uboot-tools/uboot-envtools/files/realtek | 1 + .../realtek/base-files/etc/board.d/02_network | 1 + .../realtek/base-files/etc/init.d/i2c_poe | 26 +++++++++++++++ .../base-files/lib/upgrade/platform.sh | 1 + .../realtek/dts/rtl8380_tplink_sg2008p-v3.dts | 33 +++++++++++++++++++ target/linux/realtek/image/rtl838x.mk | 11 +++++++ 6 files changed, 73 insertions(+) create mode 100755 target/linux/realtek/base-files/etc/init.d/i2c_poe create mode 100644 target/linux/realtek/dts/rtl8380_tplink_sg2008p-v3.dts diff --git a/package/boot/uboot-tools/uboot-envtools/files/realtek b/package/boot/uboot-tools/uboot-envtools/files/realtek index 826914e35d..2e4ce297d2 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/realtek +++ b/package/boot/uboot-tools/uboot-envtools/files/realtek @@ -37,6 +37,7 @@ iodata,bsh-g24mb) ubootenv_add_sys_mtd "u-boot-env2" "0x0" "0x3800" "0x10000" ;; tplink,sg2008p-v1|\ +tplink,sg2008p-v3|\ tplink,sg2210p-v3|\ tplink,sg2452p-v4) ubootenv_add_mtd "u-boot-env" "0x0" "0x20000" "0x10000" diff --git a/target/linux/realtek/base-files/etc/board.d/02_network b/target/linux/realtek/base-files/etc/board.d/02_network index a85fbfc173..cdd5ded1da 100644 --- a/target/linux/realtek/base-files/etc/board.d/02_network +++ b/target/linux/realtek/base-files/etc/board.d/02_network @@ -64,6 +64,7 @@ realtek_setup_macs() netgear,gs308t-v1|\ netgear,gs310tp-v1|\ tplink,sg2008p-v1|\ + tplink,sg2008p-v3|\ tplink,sg2210p-v3|\ tplink,sg2452p-v4|\ tplink,t1600g-28ts-v3|\ diff --git a/target/linux/realtek/base-files/etc/init.d/i2c_poe b/target/linux/realtek/base-files/etc/init.d/i2c_poe new file mode 100755 index 0000000000..99b612e71f --- /dev/null +++ b/target/linux/realtek/base-files/etc/init.d/i2c_poe @@ -0,0 +1,26 @@ +#!/bin/sh /etc/rc.common + +START=10 + +mp3924_auto_mode() { + local i2c_addr=0x21 + + # Set power limit to 60 Watts. + i2cset -y 0 ${i2c_addr?} 0x54 0x00 # PMAX[0] = 0 + i2cset -y 0 ${i2c_addr?} 0x55 0x4b # PMAX[1-8] = 0x4b + i2cset -y -m 0x04 0 ${i2c_addr?} 0x0f 0x04 # PMAXEN = 1 + + # Set all ports to AUTO mode. + i2cset -y 0 ${i2c_addr?} 0x03 0xff # MODE = AUTO + i2cset -y -m 0x0f 0 ${i2c_addr?} 0x0c 0x0f # 2EVNTEN = 1 + i2cset -y -m 0x0f 0 ${i2c_addr?} 0x07 0x0f # DISEN = 1 + i2cset -y 0 ${i2c_addr?} 0x06 0xff # DETEN = 1, CLSEN = 1 +} + +boot() { + case $(board_name) in + tplink,sg2008p-v3) + mp3924_auto_mode + ;; + esac +} diff --git a/target/linux/realtek/base-files/lib/upgrade/platform.sh b/target/linux/realtek/base-files/lib/upgrade/platform.sh index df128a825f..6df1d5cc52 100644 --- a/target/linux/realtek/base-files/lib/upgrade/platform.sh +++ b/target/linux/realtek/base-files/lib/upgrade/platform.sh @@ -36,6 +36,7 @@ platform_do_upgrade() { platform_do_upgrade_dualboot_plasmacloud "$1" ;; tplink,sg2008p-v1|\ + tplink,sg2008p-v3|\ tplink,sg2210p-v3) tplink_sg2xxx_fix_mtdparts default_do_upgrade "$1" diff --git a/target/linux/realtek/dts/rtl8380_tplink_sg2008p-v3.dts b/target/linux/realtek/dts/rtl8380_tplink_sg2008p-v3.dts new file mode 100644 index 0000000000..24efd6bd03 --- /dev/null +++ b/target/linux/realtek/dts/rtl8380_tplink_sg2008p-v3.dts @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl8380_tplink_sg2xxx.dtsi" + +/ { + compatible = "tplink,sg2008p-v3", "realtek,rtl838x-soc"; + model = "TP-Link SG2008P v3"; +}; + +&gpio0 { + poe-enable { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "poe-enable"; + }; +}; + +&tps23861_20 { + status = "disabled"; +}; + +&tps23861_28 { + status = "disabled"; +}; + +&port24 { + status = "disabled"; +}; + +&port26 { + status = "disabled"; +}; diff --git a/target/linux/realtek/image/rtl838x.mk b/target/linux/realtek/image/rtl838x.mk index 52a0f1bb46..73e282b6ed 100644 --- a/target/linux/realtek/image/rtl838x.mk +++ b/target/linux/realtek/image/rtl838x.mk @@ -353,6 +353,17 @@ define Device/tplink_sg2008p-v1 endef TARGET_DEVICES += tplink_sg2008p-v1 +define Device/tplink_sg2008p-v3 + SOC := rtl8380 + KERNEL_SIZE := 6m + IMAGE_SIZE := 26m + DEVICE_VENDOR := TP-Link + DEVICE_MODEL := SG2008P + DEVICE_VARIANT := v3 + DEVICE_PACKAGES := i2c-tools +endef +TARGET_DEVICES += tplink_sg2008p-v3 + define Device/tplink_sg2210p-v3 SOC := rtl8380 KERNEL_SIZE := 6m From fa846e7e64445ec470fde78b72a308ad4765529a Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 29 Apr 2026 13:52:15 -0700 Subject: [PATCH 007/228] mediatek: predator-w6x: set MAC in NVMEM Userspace handling is deprecated. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23764 Signed-off-by: Jonas Jelonek --- .../dts/mt7986a-acer-predator-w6x-stock.dts | 14 ++++++++++++++ .../dts/mt7986a-acer-predator-w6x-ubootmod.dts | 12 ++++++++++++ .../mediatek/dts/mt7986a-acer-predator-w6x.dtsi | 6 ++++++ .../base-files/lib/preinit/10_fix_eth_mac.sh | 10 ---------- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-stock.dts b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-stock.dts index 68b3481dd8..7c5c89b0a5 100644 --- a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-stock.dts +++ b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-stock.dts @@ -23,6 +23,20 @@ partition@800000 { label = "ubi"; reg = <0x800000 0x6400000>; + + volumes { + ubi-volume-ubootenv { + volname = "ubootenv"; + + nvmem-layout { + compatible = "u-boot,env-redundant-bool"; + + macaddr_uboot_ethaddr: ethaddr { + #nvmem-cell-cells = <1>; + }; + }; + }; + }; }; partition@6C00000 { diff --git a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-ubootmod.dts b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-ubootmod.dts index e7920f515d..851dbb80ca 100644 --- a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-ubootmod.dts +++ b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x-ubootmod.dts @@ -22,6 +22,18 @@ ubi_rootdisk: ubi-volume-fit { volname = "fit"; }; + + ubi-volume-ubootenv { + volname = "ubootenv"; + + nvmem-layout { + compatible = "u-boot,env-redundant-bool"; + + macaddr_uboot_ethaddr: ethaddr { + #nvmem-cell-cells = <1>; + }; + }; + }; }; }; }; diff --git a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x.dtsi b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x.dtsi index 1d299b70e1..fb5b5d63c2 100644 --- a/target/linux/mediatek/dts/mt7986a-acer-predator-w6x.dtsi +++ b/target/linux/mediatek/dts/mt7986a-acer-predator-w6x.dtsi @@ -77,6 +77,9 @@ reg = <0>; phy-mode = "2500base-x"; + nvmem-cells = <&macaddr_uboot_ethaddr 1>; + nvmem-cell-names = "mac-address"; + fixed-link { speed = <2500>; full-duplex; @@ -88,6 +91,9 @@ reg = <1>; phy-mode = "2500base-x"; phy-handle = <&phy6>; + + nvmem-cells = <&macaddr_uboot_ethaddr 0>; + nvmem-cell-names = "mac-address"; }; mdio-bus { diff --git a/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh b/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh index 0d4c165e48..ead84eca26 100644 --- a/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh +++ b/target/linux/mediatek/filogic/base-files/lib/preinit/10_fix_eth_mac.sh @@ -12,16 +12,6 @@ preinit_set_mac_address() { ip link set dev game address "$lan_mac" ip link set dev eth1 address "$wan_mac" ;; - acer,predator-w6x-stock|\ - acer,predator-w6x-ubootmod) - wan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) - lan_mac=$(macaddr_add "$wan_mac" 1) - ip link set dev lan1 address "$lan_mac" - ip link set dev lan2 address "$lan_mac" - ip link set dev lan3 address "$lan_mac" - ip link set dev lan4 address "$lan_mac" - ip link set dev eth1 address "$wan_mac" - ;; acer,vero-w6m) wan_mac=$(mmc_get_mac_ascii u-boot-env WANMAC) lan_mac=$(mmc_get_mac_ascii u-boot-env LANMAC) From a62ffbf3ac7fcadbfb0dc71206f674419b1a44e0 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 28 Nov 2024 14:52:14 -0800 Subject: [PATCH 008/228] prereq-build: add clang support The Apple g++ check is really clang in disguise. Furthermore, testing on Linux hosts reveals that clang can sufficiently replace gcc. Minimum version of clang is 12 because of ccache. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/17259 Signed-off-by: Jonas Jelonek --- include/prereq-build.mk | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/prereq-build.mk b/include/prereq-build.mk index 9a83d6b4c3..f37ea3bd08 100644 --- a/include/prereq-build.mk +++ b/include/prereq-build.mk @@ -35,7 +35,8 @@ $(eval $(call SetupHostCommand,gcc, \ Please install the GNU C Compiler (gcc) 10 or later, \ $(CC) -dumpversion | grep -E '^(1[0-9]|[2-9][0-9])\.?', \ gcc -dumpversion | grep -E '^(1[0-9]|[2-9][0-9])\.?', \ - gcc --version | grep -E 'Apple.(LLVM|clang)' )) + clang -dumpversion | grep -E '^(1[2-9]|[2-9][0-9])\.', \ + clang-12 -dumpversion | grep -E '^(1[2-9]|[2-9][0-9])\.' )) $(eval $(call TestHostCommand,working-gcc, \ Please reinstall the GNU C Compiler (10 or later) - \ @@ -47,7 +48,8 @@ $(eval $(call SetupHostCommand,g++, \ Please install the GNU C++ Compiler (g++) 10 or later, \ $(CXX) -dumpversion | grep -E '^(1[0-9]|[2-9][0-9])\.?', \ g++ -dumpversion | grep -E '^(1[0-9]|[2-9][0-9])\.?', \ - g++ --version | grep -E 'Apple.(LLVM|clang)' )) + clang++ -dumpversion | grep -E '^(1[2-9]|[2-9][0-9])\.', \ + clang++-12 -dumpversion | grep -E '^(1[2-9]|[2-9][0-9])\.' )) $(eval $(call TestHostCommand,working-g++, \ Please reinstall the GNU C++ Compiler (10 or later) - \ From baa020f6bfeedb6a0b8026d53ce3425e31d33473 Mon Sep 17 00:00:00 2001 From: Ryan Leung Date: Thu, 21 May 2026 15:31:31 +1000 Subject: [PATCH 009/228] uboot-mediatek: enable true RNG driver for recently added devices Enable the hardware true random number generator driver added in 2a9dce2d9e81 ("uboot-mediatek: port RNG drivers and enable them") for recently added devices. Fixes: d2fabb974c57 ("mediatek: add support for Wavlink WL-WNT100X3 ubootmod") Fixes: eb6dd61a8d4d ("mediatek: add cudy wr3000h-v1 ubootmod") Fixes: cfc17e81e1f8 ("mediatek: add cudy wr3000e-v1 ubootmod") Fixes: b7b4938303b7 ("mediatek: add cudy wr3000s-v1 ubootmod") Fixes: 6b3b7c7dc1e9 ("mediatek: add cudy wr3000p-v1 ubootmod") Signed-off-by: Ryan Leung Link: https://github.com/openwrt/openwrt/pull/23462 Signed-off-by: Jonas Jelonek --- .../uboot-mediatek/patches/468-add-cudy_wr3000e-v1.patch | 6 +++++- .../uboot-mediatek/patches/468-add-cudy_wr3000h-v1.patch | 6 +++++- .../uboot-mediatek/patches/468-add-cudy_wr3000p-v1.patch | 6 +++++- .../uboot-mediatek/patches/468-add-cudy_wr3000s-v1.patch | 6 +++++- .../patches/503-add-wavlink-wl-wnt100x3.patch | 6 +++++- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000e-v1.patch b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000e-v1.patch index cc002782bf..70992826a4 100644 --- a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000e-v1.patch +++ b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000e-v1.patch @@ -1,7 +1,8 @@ --- /dev/null +++ b/configs/mt7981_cudy_wr3000e-v1_defconfig -@@ -0,0 +1,108 @@ +@@ -0,0 +1,112 @@ +CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y +CONFIG_SYS_HAS_NONCACHED_MEMORY=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -34,6 +35,7 @@ +CONFIG_CMD_ASKENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y +CONFIG_CMD_STRINGS=y +CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y @@ -101,6 +103,8 @@ +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y +CONFIG_DM_SERIAL=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_MTK_SERIAL=y diff --git a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000h-v1.patch b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000h-v1.patch index c0cd313713..311eef5c46 100644 --- a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000h-v1.patch +++ b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000h-v1.patch @@ -1,7 +1,8 @@ --- /dev/null +++ b/configs/mt7981_cudy_wr3000h-v1_defconfig -@@ -0,0 +1,108 @@ +@@ -0,0 +1,112 @@ +CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y +CONFIG_SYS_HAS_NONCACHED_MEMORY=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -34,6 +35,7 @@ +CONFIG_CMD_ASKENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y +CONFIG_CMD_STRINGS=y +CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y @@ -101,6 +103,8 @@ +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y +CONFIG_DM_SERIAL=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_MTK_SERIAL=y diff --git a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000p-v1.patch b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000p-v1.patch index 9bba21ba6a..f61e66a57a 100644 --- a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000p-v1.patch +++ b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000p-v1.patch @@ -1,7 +1,8 @@ --- /dev/null +++ b/configs/mt7981_cudy_wr3000p-v1_defconfig -@@ -0,0 +1,108 @@ +@@ -0,0 +1,112 @@ +CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y +CONFIG_SYS_HAS_NONCACHED_MEMORY=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -34,6 +35,7 @@ +CONFIG_CMD_ASKENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y +CONFIG_CMD_STRINGS=y +CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y @@ -101,6 +103,8 @@ +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y +CONFIG_DM_SERIAL=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_MTK_SERIAL=y diff --git a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000s-v1.patch b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000s-v1.patch index 6f1e15e104..68fbfdb43b 100644 --- a/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000s-v1.patch +++ b/package/boot/uboot-mediatek/patches/468-add-cudy_wr3000s-v1.patch @@ -1,7 +1,8 @@ --- /dev/null +++ b/configs/mt7981_cudy_wr3000s-v1_defconfig -@@ -0,0 +1,108 @@ +@@ -0,0 +1,112 @@ +CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y +CONFIG_SYS_HAS_NONCACHED_MEMORY=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -34,6 +35,7 @@ +CONFIG_CMD_ASKENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y +CONFIG_CMD_STRINGS=y +CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y @@ -101,6 +103,8 @@ +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y +CONFIG_DM_SERIAL=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_MTK_SERIAL=y diff --git a/package/boot/uboot-mediatek/patches/503-add-wavlink-wl-wnt100x3.patch b/package/boot/uboot-mediatek/patches/503-add-wavlink-wl-wnt100x3.patch index b6221e0d2e..552f0adab5 100644 --- a/package/boot/uboot-mediatek/patches/503-add-wavlink-wl-wnt100x3.patch +++ b/package/boot/uboot-mediatek/patches/503-add-wavlink-wl-wnt100x3.patch @@ -1,7 +1,8 @@ --- /dev/null +++ b/configs/mt7981_wavlink_wl-wnt100x3_defconfig -@@ -0,0 +1,108 @@ +@@ -0,0 +1,112 @@ +CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y +CONFIG_SYS_HAS_NONCACHED_MEMORY=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_MEDIATEK=y @@ -34,6 +35,7 @@ +CONFIG_CMD_ASKENV=y +CONFIG_CMD_ERASEENV=y +CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y +CONFIG_CMD_STRINGS=y +CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y @@ -101,6 +103,8 @@ +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y +CONFIG_DM_SERIAL=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_MTK_SERIAL=y From d7c66d62415971ad306ffafd8bf44df51993c860 Mon Sep 17 00:00:00 2001 From: Ahmed Naseef Date: Thu, 11 Jun 2026 17:05:21 +0400 Subject: [PATCH 010/228] kernel/econet: create files for v6.18 (from v6.12) This is an automatically generated commit. When doing `git bisect`, consider `git bisect --skip`. Signed-off-by: Ahmed Naseef Link: https://github.com/openwrt/openwrt/pull/23755 Signed-off-by: Jonas Jelonek --- target/linux/econet/en751221/{config-6.12 => config-6.18} | 0 target/linux/econet/en751627/{config-6.12 => config-6.18} | 0 target/linux/econet/en7528/{config-6.12 => config-6.18} | 0 ....16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch | 0 .../002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch | 0 .../003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch | 0 ...6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch | 0 ...05-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch | 0 .../006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch | 0 .../007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch | 0 .../008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch | 0 ....16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch | 0 ....16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch | 0 ...011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch | 0 ....13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch | 0 .../013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch | 0 ....14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch | 0 ....14-clk-en7523-Rework-clock-handling-for-different-clock.patch | 0 .../016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch | 0 ...rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch | 0 ...rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch | 0 ....13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch | 0 ...rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch | 0 ...6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch | 0 .../022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch | 0 ...5-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch | 0 ....19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch | 0 .../029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch | 0 ....19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch | 0 ....19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch | 0 ....19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch | 0 ....19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch | 0 ....19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch | 0 ...3-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch | 0 .../100-econet-add-en7528-soc.patch | 0 .../101-econet-timer-add-en7528-support.patch | 0 ...300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch | 0 .../301-spi-Airoha-adapt-to-support-en75-mips.patch | 0 .../303-spi-airoha-snfi-enable-for-econet.patch | 0 .../310-usb-enable-econet-usb.patch | 0 .../320-gpio-en7523-enable-for-econet-mips.patch | 0 .../886-uart-add-en7523-support.patch | 0 .../887-uart-airoha-add-econet-support.patch | 0 .../{patches-6.12 => patches-6.18}/901-nand-enable-en75-bbt.patch | 0 .../902-snand-mtk-bmt-support.patch | 0 ...910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch | 0 ...911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch | 0 .../912-pcie-add-en7528-pcie-and-phy-support.patch | 0 .../913-pcie-fix-bogus-prefetch-window.patch | 0 .../914-phy-add-en7528-usb-phy-driver.patch | 0 .../915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch | 0 51 files changed, 0 insertions(+), 0 deletions(-) rename target/linux/econet/en751221/{config-6.12 => config-6.18} (100%) rename target/linux/econet/en751627/{config-6.12 => config-6.18} (100%) rename target/linux/econet/en7528/{config-6.12 => config-6.18} (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/100-econet-add-en7528-soc.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/101-econet-timer-add-en7528-support.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/301-spi-Airoha-adapt-to-support-en75-mips.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/303-spi-airoha-snfi-enable-for-econet.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/310-usb-enable-econet-usb.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/320-gpio-en7523-enable-for-econet-mips.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/886-uart-add-en7523-support.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/887-uart-airoha-add-econet-support.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/901-nand-enable-en75-bbt.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/902-snand-mtk-bmt-support.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/912-pcie-add-en7528-pcie-and-phy-support.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/913-pcie-fix-bogus-prefetch-window.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/914-phy-add-en7528-usb-phy-driver.patch (100%) rename target/linux/econet/{patches-6.12 => patches-6.18}/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch (100%) diff --git a/target/linux/econet/en751221/config-6.12 b/target/linux/econet/en751221/config-6.18 similarity index 100% rename from target/linux/econet/en751221/config-6.12 rename to target/linux/econet/en751221/config-6.18 diff --git a/target/linux/econet/en751627/config-6.12 b/target/linux/econet/en751627/config-6.18 similarity index 100% rename from target/linux/econet/en751627/config-6.12 rename to target/linux/econet/en751627/config-6.18 diff --git a/target/linux/econet/en7528/config-6.12 b/target/linux/econet/en7528/config-6.18 similarity index 100% rename from target/linux/econet/en7528/config-6.12 rename to target/linux/econet/en7528/config-6.18 diff --git a/target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch b/target/linux/econet/patches-6.18/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch similarity index 100% rename from target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch rename to target/linux/econet/patches-6.18/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch diff --git a/target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch b/target/linux/econet/patches-6.18/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch similarity index 100% rename from target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch rename to target/linux/econet/patches-6.18/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch diff --git a/target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch b/target/linux/econet/patches-6.18/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch similarity index 100% rename from target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch rename to target/linux/econet/patches-6.18/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch diff --git a/target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch b/target/linux/econet/patches-6.18/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch similarity index 100% rename from target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch rename to target/linux/econet/patches-6.18/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch diff --git a/target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch b/target/linux/econet/patches-6.18/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch similarity index 100% rename from target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch rename to target/linux/econet/patches-6.18/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch diff --git a/target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch b/target/linux/econet/patches-6.18/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch similarity index 100% rename from target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch rename to target/linux/econet/patches-6.18/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch diff --git a/target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch b/target/linux/econet/patches-6.18/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch similarity index 100% rename from target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch rename to target/linux/econet/patches-6.18/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch diff --git a/target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch b/target/linux/econet/patches-6.18/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch similarity index 100% rename from target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch rename to target/linux/econet/patches-6.18/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch diff --git a/target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch b/target/linux/econet/patches-6.18/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch similarity index 100% rename from target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch rename to target/linux/econet/patches-6.18/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch diff --git a/target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch b/target/linux/econet/patches-6.18/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch similarity index 100% rename from target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch rename to target/linux/econet/patches-6.18/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch diff --git a/target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch b/target/linux/econet/patches-6.18/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch similarity index 100% rename from target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch rename to target/linux/econet/patches-6.18/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch diff --git a/target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch b/target/linux/econet/patches-6.18/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch similarity index 100% rename from target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch rename to target/linux/econet/patches-6.18/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch diff --git a/target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch b/target/linux/econet/patches-6.18/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch similarity index 100% rename from target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch rename to target/linux/econet/patches-6.18/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch diff --git a/target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch b/target/linux/econet/patches-6.18/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch similarity index 100% rename from target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch rename to target/linux/econet/patches-6.18/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch diff --git a/target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch b/target/linux/econet/patches-6.18/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch similarity index 100% rename from target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch rename to target/linux/econet/patches-6.18/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch diff --git a/target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch b/target/linux/econet/patches-6.18/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch similarity index 100% rename from target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch rename to target/linux/econet/patches-6.18/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch diff --git a/target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch b/target/linux/econet/patches-6.18/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch similarity index 100% rename from target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch rename to target/linux/econet/patches-6.18/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch diff --git a/target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch b/target/linux/econet/patches-6.18/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch similarity index 100% rename from target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch rename to target/linux/econet/patches-6.18/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch diff --git a/target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch b/target/linux/econet/patches-6.18/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch similarity index 100% rename from target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch rename to target/linux/econet/patches-6.18/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch diff --git a/target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch b/target/linux/econet/patches-6.18/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch similarity index 100% rename from target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch rename to target/linux/econet/patches-6.18/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch diff --git a/target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch b/target/linux/econet/patches-6.18/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch similarity index 100% rename from target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch rename to target/linux/econet/patches-6.18/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch diff --git a/target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch b/target/linux/econet/patches-6.18/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch similarity index 100% rename from target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch rename to target/linux/econet/patches-6.18/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch diff --git a/target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch b/target/linux/econet/patches-6.18/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch rename to target/linux/econet/patches-6.18/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch diff --git a/target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch b/target/linux/econet/patches-6.18/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch rename to target/linux/econet/patches-6.18/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch diff --git a/target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch b/target/linux/econet/patches-6.18/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch rename to target/linux/econet/patches-6.18/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch diff --git a/target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch b/target/linux/econet/patches-6.18/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch rename to target/linux/econet/patches-6.18/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch diff --git a/target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch b/target/linux/econet/patches-6.18/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch rename to target/linux/econet/patches-6.18/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch diff --git a/target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch b/target/linux/econet/patches-6.18/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch rename to target/linux/econet/patches-6.18/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch diff --git a/target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch b/target/linux/econet/patches-6.18/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch rename to target/linux/econet/patches-6.18/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch diff --git a/target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch b/target/linux/econet/patches-6.18/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch rename to target/linux/econet/patches-6.18/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch diff --git a/target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch b/target/linux/econet/patches-6.18/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch similarity index 100% rename from target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch rename to target/linux/econet/patches-6.18/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch diff --git a/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch b/target/linux/econet/patches-6.18/100-econet-add-en7528-soc.patch similarity index 100% rename from target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch rename to target/linux/econet/patches-6.18/100-econet-add-en7528-soc.patch diff --git a/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch b/target/linux/econet/patches-6.18/101-econet-timer-add-en7528-support.patch similarity index 100% rename from target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch rename to target/linux/econet/patches-6.18/101-econet-timer-add-en7528-support.patch diff --git a/target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch b/target/linux/econet/patches-6.18/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch similarity index 100% rename from target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch rename to target/linux/econet/patches-6.18/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch diff --git a/target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch b/target/linux/econet/patches-6.18/301-spi-Airoha-adapt-to-support-en75-mips.patch similarity index 100% rename from target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch rename to target/linux/econet/patches-6.18/301-spi-Airoha-adapt-to-support-en75-mips.patch diff --git a/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch b/target/linux/econet/patches-6.18/303-spi-airoha-snfi-enable-for-econet.patch similarity index 100% rename from target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch rename to target/linux/econet/patches-6.18/303-spi-airoha-snfi-enable-for-econet.patch diff --git a/target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch b/target/linux/econet/patches-6.18/310-usb-enable-econet-usb.patch similarity index 100% rename from target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch rename to target/linux/econet/patches-6.18/310-usb-enable-econet-usb.patch diff --git a/target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch b/target/linux/econet/patches-6.18/320-gpio-en7523-enable-for-econet-mips.patch similarity index 100% rename from target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch rename to target/linux/econet/patches-6.18/320-gpio-en7523-enable-for-econet-mips.patch diff --git a/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch b/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch similarity index 100% rename from target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch rename to target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch diff --git a/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch b/target/linux/econet/patches-6.18/887-uart-airoha-add-econet-support.patch similarity index 100% rename from target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch rename to target/linux/econet/patches-6.18/887-uart-airoha-add-econet-support.patch diff --git a/target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch b/target/linux/econet/patches-6.18/901-nand-enable-en75-bbt.patch similarity index 100% rename from target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch rename to target/linux/econet/patches-6.18/901-nand-enable-en75-bbt.patch diff --git a/target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch b/target/linux/econet/patches-6.18/902-snand-mtk-bmt-support.patch similarity index 100% rename from target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch rename to target/linux/econet/patches-6.18/902-snand-mtk-bmt-support.patch diff --git a/target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch b/target/linux/econet/patches-6.18/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch similarity index 100% rename from target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch rename to target/linux/econet/patches-6.18/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch diff --git a/target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch b/target/linux/econet/patches-6.18/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch similarity index 100% rename from target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch rename to target/linux/econet/patches-6.18/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch diff --git a/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch b/target/linux/econet/patches-6.18/912-pcie-add-en7528-pcie-and-phy-support.patch similarity index 100% rename from target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch rename to target/linux/econet/patches-6.18/912-pcie-add-en7528-pcie-and-phy-support.patch diff --git a/target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch b/target/linux/econet/patches-6.18/913-pcie-fix-bogus-prefetch-window.patch similarity index 100% rename from target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch rename to target/linux/econet/patches-6.18/913-pcie-fix-bogus-prefetch-window.patch diff --git a/target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch b/target/linux/econet/patches-6.18/914-phy-add-en7528-usb-phy-driver.patch similarity index 100% rename from target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch rename to target/linux/econet/patches-6.18/914-phy-add-en7528-usb-phy-driver.patch diff --git a/target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch b/target/linux/econet/patches-6.18/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch similarity index 100% rename from target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch rename to target/linux/econet/patches-6.18/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch From 0619a10834bb73956f1a2bf8bc296a8efd43a1db Mon Sep 17 00:00:00 2001 From: Ahmed Naseef Date: Thu, 11 Jun 2026 17:05:21 +0400 Subject: [PATCH 011/228] kernel/econet: restore files for v6.12 This is an automatically generated commit which aids following Kernel patch history, as git will see the move and copy as a rename thus defeating the purpose. For the original discussion see: https://lists.openwrt.org/pipermail/openwrt-devel/2023-October/041673.html Signed-off-by: Ahmed Naseef Link: https://github.com/openwrt/openwrt/pull/23755 Signed-off-by: Jonas Jelonek --- target/linux/econet/en751221/config-6.12 | 209 ++++++++++ target/linux/econet/en751627/config-6.12 | 239 +++++++++++ target/linux/econet/en7528/config-6.12 | 241 +++++++++++ ...rrupt-controller-Add-EcoNet-EN751221.patch | 98 +++++ ....16-irqchip-Add-EcoNet-EN751221-INTC.patch | 353 +++++++++++++++++ ...-bindings-vendor-prefixes-Add-EcoNet.patch | 26 ++ ...er-Add-EcoNet-EN751221-HPT-CPU-Timer.patch | 100 +++++ ...-drivers-Add-EcoNet-Timer-HPT-driver.patch | 276 +++++++++++++ ...ngs-mips-Add-EcoNet-platform-binding.patch | 44 +++ ...ips-Add-EcoNet-MIPS-platform-support.patch | 222 +++++++++++ ...dings-vendor-prefixes-Add-SmartFiber.patch | 29 ++ ...Net-DTS-with-EN751221-and-SmartFiber.patch | 149 +++++++ ...entry-for-newly-added-EcoNet-platfor.patch | 38 ++ ...t-Fix-incorrect-Kconfig-dependencies.patch | 32 ++ ...en7581_reset_register-in-en7581_clk_.patch | 174 ++++++++ ...7523-map-io-region-in-a-single-block.patch | 84 ++++ ...3-Move-reset-delay-in-mtk_pcie_en758.patch | 42 ++ ...k-clock-handling-for-different-clock.patch | 83 ++++ ...en7523-Add-clock-for-eMMC-for-EN7581.patch | 41 ++ ...eset-controller-support-for-EN7523-S.patch | 133 +++++++ ...k-airoha-Add-reset-support-to-EN7523.patch | 35 ++ ...k-airoha-Update-reg-mapping-for-EN75.patch | 74 ++++ ...k-airoha-Add-reset-support-to-EN7523.patch | 81 ++++ ...ck-drop-NUM_CLOCKS-define-for-EN7581.patch | 26 ++ ...ngs-clock-add-ID-for-eMMC-for-EN7581.patch | 25 ++ ...emove-unnecessary-restriction-length.patch | 33 ++ ...e-unnecessary-switch-to-non-dma-mode.patch | 30 ++ ...-airoha-unify-dirmap-read-write-code.patch | 137 +++++++ ...rt-of-dualio-quadio-flash-reading-co.patch | 94 +++++ ...-setting-of-page-oob-sizes-in-REG_SP.patch | 64 +++ ...e-the-number-of-modification-of-REG_.patch | 199 ++++++++++ ...ustom-sector-size-equal-to-flash-pag.patch | 142 +++++++ ...-reading-flash-page-settings-from-SN.patch | 206 ++++++++++ ...uffer-must-be-0xff-ed-before-writing.patch | 32 ++ .../100-econet-add-en7528-soc.patch | 119 ++++++ .../101-econet-timer-add-en7528-support.patch | 264 +++++++++++++ ...for-the-Airoha-EN7523-SoC-SPI-contro.patch | 341 ++++++++++++++++ ...pi-Airoha-adapt-to-support-en75-mips.patch | 56 +++ ...03-spi-airoha-snfi-enable-for-econet.patch | 21 + .../310-usb-enable-econet-usb.patch | 21 + ...0-gpio-en7523-enable-for-econet-mips.patch | 17 + .../886-uart-add-en7523-support.patch | 206 ++++++++++ .../887-uart-airoha-add-econet-support.patch | 18 + .../901-nand-enable-en75-bbt.patch | 40 ++ .../902-snand-mtk-bmt-support.patch | 34 ++ ...k-reset-add-econet-en751221-bindings.patch | 176 +++++++++ ...conet-en751221-clock-reset-support-t.patch | 364 +++++++++++++++++ ...pcie-add-en7528-pcie-and-phy-support.patch | 373 ++++++++++++++++++ .../913-pcie-fix-bogus-prefetch-window.patch | 38 ++ .../914-phy-add-en7528-usb-phy-driver.patch | 358 +++++++++++++++++ ...-usb-xhci-mtk-add-en7528-ltssm-quirk.patch | 58 +++ 51 files changed, 6295 insertions(+) create mode 100644 target/linux/econet/en751221/config-6.12 create mode 100644 target/linux/econet/en751627/config-6.12 create mode 100644 target/linux/econet/en7528/config-6.12 create mode 100644 target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch create mode 100644 target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch create mode 100644 target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch create mode 100644 target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch create mode 100644 target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch create mode 100644 target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch create mode 100644 target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch create mode 100644 target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch create mode 100644 target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch create mode 100644 target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch create mode 100644 target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch create mode 100644 target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch create mode 100644 target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch create mode 100644 target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch create mode 100644 target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch create mode 100644 target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch create mode 100644 target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch create mode 100644 target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch create mode 100644 target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch create mode 100644 target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch create mode 100644 target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch create mode 100644 target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch create mode 100644 target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch create mode 100644 target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch create mode 100644 target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch create mode 100644 target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch create mode 100644 target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch create mode 100644 target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch create mode 100644 target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch create mode 100644 target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch create mode 100644 target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch create mode 100644 target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch create mode 100644 target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch create mode 100644 target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch create mode 100644 target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch create mode 100644 target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch create mode 100644 target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch create mode 100644 target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch create mode 100644 target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch create mode 100644 target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch create mode 100644 target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch create mode 100644 target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch create mode 100644 target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch create mode 100644 target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch create mode 100644 target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch create mode 100644 target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch create mode 100644 target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch create mode 100644 target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch diff --git a/target/linux/econet/en751221/config-6.12 b/target/linux/econet/en751221/config-6.12 new file mode 100644 index 0000000000..fe69f10c74 --- /dev/null +++ b/target/linux/econet/en751221/config-6.12 @@ -0,0 +1,209 @@ +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +CONFIG_BLK_MQ_PCI=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_EN7523=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_DIEI=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_RIXI=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_MITIGATIONS=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CRC16=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_ZBOOT=y +CONFIG_DMA_NEED_SYNC=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DTB_ECONET_NONE=y +# CONFIG_DTB_ECONET_SMARTFIBER_XP8421_B is not set +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_EARLY_PRINTK_8250=y +CONFIG_ECONET=y +CONFIG_ECONET_EN751221_INTC=y +CONFIG_ECONET_EN751221_TIMER=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_FS_IOMAP=y +CONFIG_FUNCTION_ALIGNMENT=0 +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_LIB_ASHLDI3=y +CONFIG_GENERIC_LIB_ASHRDI3=y +CONFIG_GENERIC_LIB_CMPDI2=y +CONFIG_GENERIC_LIB_LSHRDI3=y +CONFIG_GENERIC_LIB_UCMPDI2=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIO_CDEV=y +# CONFIG_GPIO_EN7523 is not set +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_WORK=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MIGRATION=y +CONFIG_MIPS=y +CONFIG_MIPS_ASID_BITS=8 +CONFIG_MIPS_ASID_SHIFT=0 +# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set +CONFIG_MIPS_CMDLINE_FROM_DTB=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_NO_APPENDED_DTB is not set +CONFIG_MIPS_NR_CPU_NR_MAP=2 +CONFIG_MIPS_RAW_APPENDED_DTB=y +CONFIG_MIPS_SPRAM=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=13 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SRCU_NMI_SAFE=y +CONFIG_NET_EGRESS=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_XGRESS=y +CONFIG_NR_CPUS=2 +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_DRIVERS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_ARCH_FALLBACKS=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHY_EN7528_PCIE=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +# CONFIG_SERIAL_8250_AIROHA is not set +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SMP=y +CONFIG_SMP_UP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_ECONET_EN751221=y +# CONFIG_SOC_ECONET_EN7528 is not set +CONFIG_SPI=y +CONFIG_SPI_AIROHA_EN7523=y +# CONFIG_SPI_AIROHA_SNFI is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_SYS_SUPPORTS_SMP=y +CONFIG_SYS_SUPPORTS_ZBOOT=y +CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y +CONFIG_TARGET_ISA_REV=2 +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y +CONFIG_USE_OF=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZBOOT_LOAD_ADDRESS=0x80020000 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/econet/en751627/config-6.12 b/target/linux/econet/en751627/config-6.12 new file mode 100644 index 0000000000..5e7b280d72 --- /dev/null +++ b/target/linux/econet/en751627/config-6.12 @@ -0,0 +1,239 @@ +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BOARD_SCACHE=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_EN7523=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_DIEI=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_RIXI=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_MIPSR2_IRQ_EI=y +CONFIG_CPU_MIPSR2_IRQ_VI=y +CONFIG_CPU_MITIGATIONS=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CRC16=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_ZBOOT=y +CONFIG_DMA_NEED_SYNC=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DTB_ECONET_NONE=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_EARLY_PRINTK_8250=y +CONFIG_ECONET=y +CONFIG_ECONET_EN751221_TIMER=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_FS_IOMAP=y +CONFIG_FUNCTION_ALIGNMENT=0 +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_LIB_ASHLDI3=y +CONFIG_GENERIC_LIB_ASHRDI3=y +CONFIG_GENERIC_LIB_CMPDI2=y +CONFIG_GENERIC_LIB_LSHRDI3=y +CONFIG_GENERIC_LIB_UCMPDI2=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_EN7523=y +CONFIG_GPIO_GENERIC=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_WORK=y +# CONFIG_JFFS2_FS is not set +CONFIG_LEDS_GPIO=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MIPS=y +CONFIG_MIPS_ASID_BITS=8 +CONFIG_MIPS_ASID_SHIFT=0 +CONFIG_MIPS_CM=y +# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set +CONFIG_MIPS_CMDLINE_FROM_DTB=y +CONFIG_MIPS_CPC=y +CONFIG_MIPS_CPS=y +# CONFIG_MIPS_CPS_NS16550_BOOL is not set +CONFIG_MIPS_CPU_SCACHE=y +CONFIG_MIPS_GIC=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_MIPS_MT=y +CONFIG_MIPS_MT_FPAFF=y +CONFIG_MIPS_MT_SMP=y +# CONFIG_MIPS_NO_APPENDED_DTB is not set +CONFIG_MIPS_NR_CPU_NR_MAP=4 +CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y +CONFIG_MIPS_RAW_APPENDED_DTB=y +CONFIG_MIPS_SPRAM=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=13 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SRCU_NMI_SAFE=y +CONFIG_NET_EGRESS=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PCI=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_DRIVERS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_ARCH_FALLBACKS=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHY_EN7528_PCIE=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +# CONFIG_SCHED_CORE is not set +CONFIG_SCHED_SMT=y +CONFIG_SERIAL_8250_AIROHA=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SMP=y +CONFIG_SMP_UP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +# CONFIG_SOC_ECONET_EN751221 is not set +CONFIG_SOC_ECONET_EN7528=y +CONFIG_SPI=y +# CONFIG_SPI_AIROHA_EN7523 is not set +CONFIG_SPI_AIROHA_SNFI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPLIT_PTE_PTLOCKS=y +CONFIG_SYNC_R4K=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_HIGHMEM=y +CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_SYS_SUPPORTS_MIPS_CPS=y +CONFIG_SYS_SUPPORTS_MULTITHREADING=y +CONFIG_SYS_SUPPORTS_SCHED_SMT=y +CONFIG_SYS_SUPPORTS_SMP=y +CONFIG_SYS_SUPPORTS_ZBOOT=y +CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y +CONFIG_TARGET_ISA_REV=2 +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MTK=y +# CONFIG_USB_XHCI_PLATFORM is not set +CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y +CONFIG_USE_OF=y +CONFIG_WEAK_ORDERING=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZBOOT_LOAD_ADDRESS=0x80020000 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/econet/en7528/config-6.12 b/target/linux/econet/en7528/config-6.12 new file mode 100644 index 0000000000..f577834028 --- /dev/null +++ b/target/linux/econet/en7528/config-6.12 @@ -0,0 +1,241 @@ +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BOARD_SCACHE=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_EN7523=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_DIEI=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_RIXI=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_MIPSR2_IRQ_EI=y +CONFIG_CPU_MIPSR2_IRQ_VI=y +CONFIG_CPU_MITIGATIONS=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CRC16=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_ZBOOT=y +CONFIG_DMA_NEED_SYNC=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DTB_ECONET_NONE=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_EARLY_PRINTK_8250=y +CONFIG_ECONET=y +CONFIG_ECONET_EN751221_TIMER=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_FS_IOMAP=y +CONFIG_FUNCTION_ALIGNMENT=0 +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_LIB_ASHLDI3=y +CONFIG_GENERIC_LIB_ASHRDI3=y +CONFIG_GENERIC_LIB_CMPDI2=y +CONFIG_GENERIC_LIB_LSHRDI3=y +CONFIG_GENERIC_LIB_UCMPDI2=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_EN7523=y +CONFIG_GPIO_GENERIC=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_WORK=y +# CONFIG_JFFS2_FS is not set +CONFIG_LEDS_GPIO=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MIPS=y +CONFIG_MIPS_ASID_BITS=8 +CONFIG_MIPS_ASID_SHIFT=0 +CONFIG_MIPS_CM=y +# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set +CONFIG_MIPS_CMDLINE_FROM_DTB=y +CONFIG_MIPS_CPC=y +CONFIG_MIPS_CPS=y +# CONFIG_MIPS_CPS_NS16550_BOOL is not set +CONFIG_MIPS_CPU_SCACHE=y +CONFIG_MIPS_GIC=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_MIPS_MT=y +CONFIG_MIPS_MT_FPAFF=y +CONFIG_MIPS_MT_SMP=y +# CONFIG_MIPS_NO_APPENDED_DTB is not set +CONFIG_MIPS_NR_CPU_NR_MAP=4 +CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y +CONFIG_MIPS_RAW_APPENDED_DTB=y +CONFIG_MIPS_SPRAM=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=13 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SRCU_NMI_SAFE=y +CONFIG_NET_EGRESS=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PCI=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_DRIVERS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_ARCH_FALLBACKS=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHY_EN7528_PCIE=y +CONFIG_PHY_EN7528_USB=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +# CONFIG_SCHED_CORE is not set +CONFIG_SCHED_SMT=y +CONFIG_SERIAL_8250_AIROHA=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SMP=y +CONFIG_SMP_UP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +# CONFIG_SOC_ECONET_EN751221 is not set +CONFIG_SOC_ECONET_EN7528=y +CONFIG_SPI=y +# CONFIG_SPI_AIROHA_EN7523 is not set +CONFIG_SPI_AIROHA_SNFI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPLIT_PTE_PTLOCKS=y +CONFIG_SYNC_R4K=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_HIGHMEM=y +CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_SYS_SUPPORTS_MIPS_CPS=y +CONFIG_SYS_SUPPORTS_MULTITHREADING=y +CONFIG_SYS_SUPPORTS_SCHED_SMT=y +CONFIG_SYS_SUPPORTS_SMP=y +CONFIG_SYS_SUPPORTS_ZBOOT=y +CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y +CONFIG_TARGET_ISA_REV=2 +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MTK=y +# CONFIG_USB_XHCI_PLATFORM is not set +CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y +CONFIG_USE_OF=y +CONFIG_WEAK_ORDERING=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZBOOT_LOAD_ADDRESS=0x80020000 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch b/target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch new file mode 100644 index 0000000000..c146af679a --- /dev/null +++ b/target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch @@ -0,0 +1,98 @@ +From 9773c540441c6ae15aefb49e67142e94369dbbc0 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Sun, 30 Mar 2025 17:02:58 +0000 +Subject: [PATCH] dt-bindings: interrupt-controller: Add EcoNet EN751221 INTC + +Document the device tree binding for the interrupt controller in the +EcoNet EN751221 MIPS SoC. + +Signed-off-by: Caleb James DeLisle +Signed-off-by: Thomas Gleixner +Reviewed-by: Rob Herring (Arm) +Link: https://lore.kernel.org/all/20250330170306.2584136-3-cjd@cjdns.fr +--- + .../econet,en751221-intc.yaml | 78 +++++++++++++++++++ + 1 file changed, 78 insertions(+) + create mode 100644 Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml +@@ -0,0 +1,78 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/interrupt-controller/econet,en751221-intc.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: EcoNet EN751221 Interrupt Controller ++ ++maintainers: ++ - Caleb James DeLisle ++ ++description: ++ The EcoNet EN751221 Interrupt Controller is a simple interrupt controller ++ designed for the MIPS 34Kc MT SMP processor with 2 VPEs. Each interrupt can ++ be routed to either VPE but not both, so to support per-CPU interrupts, a ++ secondary IRQ number is allocated to control masking/unmasking on VPE#1. For ++ lack of a better term we call these "shadow interrupts". The assignment of ++ shadow interrupts is defined by the SoC integrator when wiring the interrupt ++ lines, so they are configurable in the device tree. ++ ++allOf: ++ - $ref: /schemas/interrupt-controller.yaml# ++ ++properties: ++ compatible: ++ const: econet,en751221-intc ++ ++ reg: ++ maxItems: 1 ++ ++ "#interrupt-cells": ++ const: 1 ++ ++ interrupt-controller: true ++ ++ interrupts: ++ maxItems: 1 ++ description: Interrupt line connecting this controller to its parent. ++ ++ econet,shadow-interrupts: ++ $ref: /schemas/types.yaml#/definitions/uint32-matrix ++ description: ++ An array of interrupt number pairs where each pair represents a shadow ++ interrupt relationship. The first number in each pair is the primary IRQ, ++ and the second is its shadow IRQ used for VPE#1 control. For example, ++ <8 3> means IRQ 8 is shadowed by IRQ 3, so IRQ 3 cannot be mapped, but ++ when VPE#1 requests IRQ 8, it will manipulate the IRQ 3 mask bit. ++ minItems: 1 ++ maxItems: 20 ++ items: ++ items: ++ - description: primary per-CPU IRQ ++ - description: shadow IRQ number ++ ++required: ++ - compatible ++ - reg ++ - interrupt-controller ++ - "#interrupt-cells" ++ - interrupts ++ ++additionalProperties: false ++ ++examples: ++ - | ++ interrupt-controller@1fb40000 { ++ compatible = "econet,en751221-intc"; ++ reg = <0x1fb40000 0x100>; ++ ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ interrupt-parent = <&cpuintc>; ++ interrupts = <2>; ++ ++ econet,shadow-interrupts = <7 2>, <8 3>, <13 12>, <30 29>; ++ }; ++... diff --git a/target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch b/target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch new file mode 100644 index 0000000000..d3f57f4e7f --- /dev/null +++ b/target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch @@ -0,0 +1,353 @@ +From 1902a59cf5f9d8b99ecf0cb8f122cb00ef7a3f13 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Sun, 30 Mar 2025 17:02:59 +0000 +Subject: [PATCH] irqchip: Add EcoNet EN751221 INTC + +Add a driver for the interrupt controller in the EcoNet EN751221 MIPS SoC. + +Signed-off-by: Caleb James DeLisle +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/all/20250330170306.2584136-4-cjd@cjdns.fr +--- + drivers/irqchip/Kconfig | 5 + + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-econet-en751221.c | 309 ++++++++++++++++++++++++++ + 3 files changed, 315 insertions(+) + create mode 100644 drivers/irqchip/irq-econet-en751221.c + +--- a/drivers/irqchip/Kconfig ++++ b/drivers/irqchip/Kconfig +@@ -148,6 +148,11 @@ config DW_APB_ICTL + select GENERIC_IRQ_CHIP + select IRQ_DOMAIN_HIERARCHY + ++config ECONET_EN751221_INTC ++ bool ++ select GENERIC_IRQ_CHIP ++ select IRQ_DOMAIN ++ + config FARADAY_FTINTC010 + bool + select IRQ_DOMAIN +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -10,6 +10,7 @@ obj-$(CONFIG_ARCH_BCM2835) += irq-bcm28 + obj-$(CONFIG_ARCH_ACTIONS) += irq-owl-sirq.o + obj-$(CONFIG_DAVINCI_CP_INTC) += irq-davinci-cp-intc.o + obj-$(CONFIG_EXYNOS_IRQ_COMBINER) += exynos-combiner.o ++obj-$(CONFIG_ECONET_EN751221_INTC) += irq-econet-en751221.o + obj-$(CONFIG_FARADAY_FTINTC010) += irq-ftintc010.o + obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o + obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o +--- /dev/null ++++ b/drivers/irqchip/irq-econet-en751221.c +@@ -0,0 +1,309 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * EN751221 Interrupt Controller Driver. ++ * ++ * The EcoNet EN751221 Interrupt Controller is a simple interrupt controller ++ * designed for the MIPS 34Kc MT SMP processor with 2 VPEs. Each interrupt can ++ * be routed to either VPE but not both, so to support per-CPU interrupts, a ++ * secondary IRQ number is allocated to control masking/unmasking on VPE#1. In ++ * this driver, these are called "shadow interrupts". The assignment of shadow ++ * interrupts is defined by the SoC integrator when wiring the interrupt lines, ++ * so they are configurable in the device tree. ++ * ++ * If an interrupt (say 30) needs per-CPU capability, the SoC integrator ++ * allocates another IRQ number (say 29) to be its shadow. The device tree ++ * reflects this by adding the pair <30 29> to the "econet,shadow-interrupts" ++ * property. ++ * ++ * When VPE#1 requests IRQ 30, the driver manipulates the mask bit for IRQ 29, ++ * telling the hardware to mask VPE#1's view of IRQ 30. ++ * ++ * Copyright (C) 2025 Caleb James DeLisle ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define IRQ_COUNT 40 ++ ++#define NOT_PERCPU 0xff ++#define IS_SHADOW 0xfe ++ ++#define REG_MASK0 0x04 ++#define REG_MASK1 0x50 ++#define REG_PENDING0 0x08 ++#define REG_PENDING1 0x54 ++ ++/** ++ * @membase: Base address of the interrupt controller registers ++ * @interrupt_shadows: Array of all interrupts, for each value, ++ * - NOT_PERCPU: This interrupt is not per-cpu, so it has no shadow ++ * - IS_SHADOW: This interrupt is a shadow of another per-cpu interrupt ++ * - else: This is a per-cpu interrupt whose shadow is the value ++ */ ++static struct { ++ void __iomem *membase; ++ u8 interrupt_shadows[IRQ_COUNT]; ++} econet_intc __ro_after_init; ++ ++static DEFINE_RAW_SPINLOCK(irq_lock); ++ ++/* IRQs must be disabled */ ++static void econet_wreg(u32 reg, u32 val, u32 mask) ++{ ++ u32 v; ++ ++ guard(raw_spinlock)(&irq_lock); ++ ++ v = ioread32(econet_intc.membase + reg); ++ v &= ~mask; ++ v |= val & mask; ++ iowrite32(v, econet_intc.membase + reg); ++} ++ ++/* IRQs must be disabled */ ++static void econet_chmask(u32 hwirq, bool unmask) ++{ ++ u32 reg, mask; ++ u8 shadow; ++ ++ /* ++ * If the IRQ is a shadow, it should never be manipulated directly. ++ * It should only be masked/unmasked as a result of the "real" per-cpu ++ * irq being manipulated by a thread running on VPE#1. ++ * If it is per-cpu (has a shadow), and we're on VPE#1, the shadow is what we mask. ++ * This is single processor only, so smp_processor_id() never exceeds 1. ++ */ ++ shadow = econet_intc.interrupt_shadows[hwirq]; ++ if (WARN_ON_ONCE(shadow == IS_SHADOW)) ++ return; ++ else if (shadow != NOT_PERCPU && smp_processor_id() == 1) ++ hwirq = shadow; ++ ++ if (hwirq >= 32) { ++ reg = REG_MASK1; ++ mask = BIT(hwirq - 32); ++ } else { ++ reg = REG_MASK0; ++ mask = BIT(hwirq); ++ } ++ ++ econet_wreg(reg, unmask ? mask : 0, mask); ++} ++ ++/* IRQs must be disabled */ ++static void econet_intc_mask(struct irq_data *d) ++{ ++ econet_chmask(d->hwirq, false); ++} ++ ++/* IRQs must be disabled */ ++static void econet_intc_unmask(struct irq_data *d) ++{ ++ econet_chmask(d->hwirq, true); ++} ++ ++static void econet_mask_all(void) ++{ ++ /* IRQs are generally disabled during init, but guarding here makes it non-obligatory. */ ++ guard(irqsave)(); ++ econet_wreg(REG_MASK0, 0, ~0); ++ econet_wreg(REG_MASK1, 0, ~0); ++} ++ ++static void econet_intc_handle_pending(struct irq_domain *d, u32 pending, u32 offset) ++{ ++ int hwirq; ++ ++ while (pending) { ++ hwirq = fls(pending) - 1; ++ generic_handle_domain_irq(d, hwirq + offset); ++ pending &= ~BIT(hwirq); ++ } ++} ++ ++static void econet_intc_from_parent(struct irq_desc *desc) ++{ ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ struct irq_domain *domain; ++ u32 pending0, pending1; ++ ++ chained_irq_enter(chip, desc); ++ ++ pending0 = ioread32(econet_intc.membase + REG_PENDING0); ++ pending1 = ioread32(econet_intc.membase + REG_PENDING1); ++ ++ if (unlikely(!(pending0 | pending1))) { ++ spurious_interrupt(); ++ } else { ++ domain = irq_desc_get_handler_data(desc); ++ econet_intc_handle_pending(domain, pending0, 0); ++ econet_intc_handle_pending(domain, pending1, 32); ++ } ++ ++ chained_irq_exit(chip, desc); ++} ++ ++static const struct irq_chip econet_irq_chip; ++ ++static int econet_intc_map(struct irq_domain *d, u32 irq, irq_hw_number_t hwirq) ++{ ++ int ret; ++ ++ if (hwirq >= IRQ_COUNT) { ++ pr_err("%s: hwirq %lu out of range\n", __func__, hwirq); ++ return -EINVAL; ++ } else if (econet_intc.interrupt_shadows[hwirq] == IS_SHADOW) { ++ pr_err("%s: can't map hwirq %lu, it is a shadow interrupt\n", __func__, hwirq); ++ return -EINVAL; ++ } ++ ++ if (econet_intc.interrupt_shadows[hwirq] == NOT_PERCPU) { ++ irq_set_chip_and_handler(irq, &econet_irq_chip, handle_level_irq); ++ } else { ++ irq_set_chip_and_handler(irq, &econet_irq_chip, handle_percpu_devid_irq); ++ ret = irq_set_percpu_devid(irq); ++ if (ret) ++ pr_warn("%s: Failed irq_set_percpu_devid for %u: %d\n", d->name, irq, ret); ++ } ++ ++ irq_set_chip_data(irq, NULL); ++ return 0; ++} ++ ++static const struct irq_chip econet_irq_chip = { ++ .name = "en751221-intc", ++ .irq_unmask = econet_intc_unmask, ++ .irq_mask = econet_intc_mask, ++ .irq_mask_ack = econet_intc_mask, ++}; ++ ++static const struct irq_domain_ops econet_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = econet_intc_map ++}; ++ ++static int __init get_shadow_interrupts(struct device_node *node) ++{ ++ const char *field = "econet,shadow-interrupts"; ++ int num_shadows; ++ ++ num_shadows = of_property_count_u32_elems(node, field); ++ ++ memset(econet_intc.interrupt_shadows, NOT_PERCPU, ++ sizeof(econet_intc.interrupt_shadows)); ++ ++ if (num_shadows <= 0) { ++ return 0; ++ } else if (num_shadows % 2) { ++ pr_err("%pOF: %s count is odd, ignoring\n", node, field); ++ return 0; ++ } ++ ++ u32 *shadows __free(kfree) = kmalloc_array(num_shadows, sizeof(u32), GFP_KERNEL); ++ if (!shadows) ++ return -ENOMEM; ++ ++ if (of_property_read_u32_array(node, field, shadows, num_shadows)) { ++ pr_err("%pOF: Failed to read %s\n", node, field); ++ return -EINVAL; ++ } ++ ++ for (int i = 0; i < num_shadows; i += 2) { ++ u32 shadow = shadows[i + 1]; ++ u32 target = shadows[i]; ++ ++ if (shadow > IRQ_COUNT) { ++ pr_err("%pOF: %s[%d] shadow(%d) out of range\n", ++ node, field, i + 1, shadow); ++ continue; ++ } ++ ++ if (target >= IRQ_COUNT) { ++ pr_err("%pOF: %s[%d] target(%d) out of range\n", node, field, i, target); ++ continue; ++ } ++ ++ if (econet_intc.interrupt_shadows[target] != NOT_PERCPU) { ++ pr_err("%pOF: %s[%d] target(%d) already has a shadow\n", ++ node, field, i, target); ++ continue; ++ } ++ ++ if (econet_intc.interrupt_shadows[shadow] != NOT_PERCPU) { ++ pr_err("%pOF: %s[%d] shadow(%d) already has a target\n", ++ node, field, i + 1, shadow); ++ continue; ++ } ++ ++ econet_intc.interrupt_shadows[target] = shadow; ++ econet_intc.interrupt_shadows[shadow] = IS_SHADOW; ++ } ++ ++ return 0; ++} ++ ++static int __init econet_intc_of_init(struct device_node *node, struct device_node *parent) ++{ ++ struct irq_domain *domain; ++ struct resource res; ++ int ret, irq; ++ ++ ret = get_shadow_interrupts(node); ++ if (ret) ++ return ret; ++ ++ irq = irq_of_parse_and_map(node, 0); ++ if (!irq) { ++ pr_err("%pOF: DT: Failed to get IRQ from 'interrupts'\n", node); ++ return -EINVAL; ++ } ++ ++ if (of_address_to_resource(node, 0, &res)) { ++ pr_err("%pOF: DT: Failed to get 'reg'\n", node); ++ ret = -EINVAL; ++ goto err_dispose_mapping; ++ } ++ ++ if (!request_mem_region(res.start, resource_size(&res), res.name)) { ++ pr_err("%pOF: Failed to request memory\n", node); ++ ret = -EBUSY; ++ goto err_dispose_mapping; ++ } ++ ++ econet_intc.membase = ioremap(res.start, resource_size(&res)); ++ if (!econet_intc.membase) { ++ pr_err("%pOF: Failed to remap membase\n", node); ++ ret = -ENOMEM; ++ goto err_release; ++ } ++ ++ econet_mask_all(); ++ ++ domain = irq_domain_add_linear(node, IRQ_COUNT, &econet_domain_ops, NULL); ++ if (!domain) { ++ pr_err("%pOF: Failed to add irqdomain\n", node); ++ ret = -ENOMEM; ++ goto err_unmap; ++ } ++ ++ irq_set_chained_handler_and_data(irq, econet_intc_from_parent, domain); ++ ++ return 0; ++ ++err_unmap: ++ iounmap(econet_intc.membase); ++err_release: ++ release_mem_region(res.start, resource_size(&res)); ++err_dispose_mapping: ++ irq_dispose_mapping(irq); ++ return ret; ++} ++ ++IRQCHIP_DECLARE(econet_en751221_intc, "econet,en751221-intc", econet_intc_of_init); diff --git a/target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch b/target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch new file mode 100644 index 0000000000..e2466782d1 --- /dev/null +++ b/target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch @@ -0,0 +1,26 @@ +From 9e0dd98654a528735d2b363d0dc73f7904108652 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Sun, 30 Mar 2025 17:02:57 +0000 +Subject: [PATCH] dt-bindings: vendor-prefixes: Add EcoNet + +Add the "econet" vendor prefix for SoC maker + +Signed-off-by: Caleb James DeLisle +Acked-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20250330170306.2584136-2-cjd@cjdns.fr +Signed-off-by: Rob Herring (Arm) +--- + Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml ++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml +@@ -420,6 +420,8 @@ patternProperties: + description: EBV Elektronik + "^eckelmann,.*": + description: Eckelmann AG ++ "^econet,.*": ++ description: EcoNet (HK) Limited + "^edgeble,.*": + description: Edgeble AI Technologies Pvt. Ltd. + "^edimax,.*": diff --git a/target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch b/target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch new file mode 100644 index 0000000000..92f8604ea2 --- /dev/null +++ b/target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch @@ -0,0 +1,100 @@ +From 30fddbd5325459102e448c9a26a1bc15ef563381 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Wed, 7 May 2025 13:44:54 +0000 +Subject: [PATCH] dt-bindings: timer: Add EcoNet EN751221 "HPT" CPU Timer + +Add device tree bindings for the so-called high-precision timer (HPT) +in the EcoNet EN751221 SoC. + +Signed-off-by: Caleb James DeLisle +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20250507134500.390547-2-cjd@cjdns.fr +Signed-off-by: Daniel Lezcano +--- + .../bindings/timer/econet,en751221-timer.yaml | 80 +++++++++++++++++++ + 1 file changed, 80 insertions(+) + create mode 100644 Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml +@@ -0,0 +1,80 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/timer/econet,en751221-timer.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: EcoNet EN751221 High Precision Timer (HPT) ++ ++maintainers: ++ - Caleb James DeLisle ++ ++description: ++ The EcoNet High Precision Timer (HPT) is a timer peripheral found in various ++ EcoNet SoCs, including the EN751221 and EN751627 families. It provides per-VPE ++ count/compare registers and a per-CPU control register, with a single interrupt ++ line using a percpu-devid interrupt mechanism. ++ ++properties: ++ compatible: ++ oneOf: ++ - const: econet,en751221-timer ++ - items: ++ - const: econet,en751627-timer ++ - const: econet,en751221-timer ++ ++ reg: ++ minItems: 1 ++ maxItems: 2 ++ ++ interrupts: ++ maxItems: 1 ++ description: A percpu-devid timer interrupt shared across CPUs. ++ ++ clocks: ++ maxItems: 1 ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ ++allOf: ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: econet,en751627-timer ++ then: ++ properties: ++ reg: ++ items: ++ - description: VPE timers 0 and 1 ++ - description: VPE timers 2 and 3 ++ else: ++ properties: ++ reg: ++ items: ++ - description: VPE timers 0 and 1 ++ ++additionalProperties: false ++ ++examples: ++ - | ++ timer@1fbf0400 { ++ compatible = "econet,en751627-timer", "econet,en751221-timer"; ++ reg = <0x1fbf0400 0x100>, <0x1fbe0000 0x100>; ++ interrupt-parent = <&intc>; ++ interrupts = <30>; ++ clocks = <&hpt_clock>; ++ }; ++ - | ++ timer@1fbf0400 { ++ compatible = "econet,en751221-timer"; ++ reg = <0x1fbe0400 0x100>; ++ interrupt-parent = <&intc>; ++ interrupts = <30>; ++ clocks = <&hpt_clock>; ++ }; ++... diff --git a/target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch b/target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch new file mode 100644 index 0000000000..dcd4bb15e3 --- /dev/null +++ b/target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch @@ -0,0 +1,276 @@ +From 3b4c33ac87d0d11308f4445ecec2a124e2e77724 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Wed, 7 May 2025 13:44:55 +0000 +Subject: [PATCH] clocksource/drivers: Add EcoNet Timer HPT driver + +Introduce a clocksource driver for the so-called high-precision timer (HPT) +in the EcoNet EN751221 and EN751627 MIPS SoCs. + +It's a 32 bit upward-counting one-shot timer which relies on the crystal so it +is unaffected by CPU power mode. On MIPS 34K devices (single core) there is +one timer, and on 1004K devices (dual core) there are two. + +Each timer has two sets of count/compare registers so that there is one for +each of the VPEs on the core. Because each core has 2 VPEs, register selection +takes the CPU number / 2 for the timer corrisponding to the core, then CPU +number % 2 for the register corrisponding to the VPE. + +These timers use a percpu-devid IRQ to route interrupts to the VPE which set +the event. + +Signed-off-by: Caleb James DeLisle +Link: https://lore.kernel.org/r/20250507134500.390547-3-cjd@cjdns.fr +Signed-off-by: Daniel Lezcano +--- + drivers/clocksource/Kconfig | 8 + + drivers/clocksource/Makefile | 1 + + drivers/clocksource/timer-econet-en751221.c | 216 ++++++++++++++++++++ + 3 files changed, 225 insertions(+) + create mode 100644 drivers/clocksource/timer-econet-en751221.c + +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -73,6 +73,14 @@ config DW_APB_TIMER_OF + select DW_APB_TIMER + select TIMER_OF + ++config ECONET_EN751221_TIMER ++ bool "EcoNet EN751221 High Precision Timer" if COMPILE_TEST ++ depends on HAS_IOMEM ++ select CLKSRC_MMIO ++ select TIMER_OF ++ help ++ Support for CPU timer found on EcoNet MIPS based SoCs. ++ + config FTTMR010_TIMER + bool "Faraday Technology timer driver" if COMPILE_TEST + depends on HAS_IOMEM +--- a/drivers/clocksource/Makefile ++++ b/drivers/clocksource/Makefile +@@ -17,6 +17,7 @@ obj-$(CONFIG_CLKBLD_I8253) += i8253.o + obj-$(CONFIG_CLKSRC_MMIO) += mmio.o + obj-$(CONFIG_DAVINCI_TIMER) += timer-davinci.o + obj-$(CONFIG_DIGICOLOR_TIMER) += timer-digicolor.o ++obj-$(CONFIG_ECONET_EN751221_TIMER) += timer-econet-en751221.o + obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o + obj-$(CONFIG_OMAP_DM_SYSTIMER) += timer-ti-dm-systimer.o + obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o +--- /dev/null ++++ b/drivers/clocksource/timer-econet-en751221.c +@@ -0,0 +1,216 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Timer present on EcoNet EN75xx MIPS based SoCs. ++ * ++ * Copyright (C) 2025 by Caleb James DeLisle ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define ECONET_BITS 32 ++#define ECONET_MIN_DELTA 0x00001000 ++#define ECONET_MAX_DELTA GENMASK(ECONET_BITS - 2, 0) ++/* 34Kc hardware has 1 block and 1004Kc has 2. */ ++#define ECONET_NUM_BLOCKS DIV_ROUND_UP(NR_CPUS, 2) ++ ++static struct { ++ void __iomem *membase[ECONET_NUM_BLOCKS]; ++ u32 freq_hz; ++} econet_timer __ro_after_init; ++ ++static DEFINE_PER_CPU(struct clock_event_device, econet_timer_pcpu); ++ ++/* Each memory block has 2 timers, the order of registers is: ++ * CTL, CMR0, CNT0, CMR1, CNT1 ++ */ ++static inline void __iomem *reg_ctl(u32 timer_n) ++{ ++ return econet_timer.membase[timer_n >> 1]; ++} ++ ++static inline void __iomem *reg_compare(u32 timer_n) ++{ ++ return econet_timer.membase[timer_n >> 1] + (timer_n & 1) * 0x08 + 0x04; ++} ++ ++static inline void __iomem *reg_count(u32 timer_n) ++{ ++ return econet_timer.membase[timer_n >> 1] + (timer_n & 1) * 0x08 + 0x08; ++} ++ ++static inline u32 ctl_bit_enabled(u32 timer_n) ++{ ++ return 1U << (timer_n & 1); ++} ++ ++static inline u32 ctl_bit_pending(u32 timer_n) ++{ ++ return 1U << ((timer_n & 1) + 16); ++} ++ ++static bool cevt_is_pending(int cpu_id) ++{ ++ return ioread32(reg_ctl(cpu_id)) & ctl_bit_pending(cpu_id); ++} ++ ++static irqreturn_t cevt_interrupt(int irq, void *dev_id) ++{ ++ struct clock_event_device *dev = this_cpu_ptr(&econet_timer_pcpu); ++ int cpu = cpumask_first(dev->cpumask); ++ ++ /* Each VPE has its own events, ++ * so this will only happen on spurious interrupt. ++ */ ++ if (!cevt_is_pending(cpu)) ++ return IRQ_NONE; ++ ++ iowrite32(ioread32(reg_count(cpu)), reg_compare(cpu)); ++ dev->event_handler(dev); ++ return IRQ_HANDLED; ++} ++ ++static int cevt_set_next_event(ulong delta, struct clock_event_device *dev) ++{ ++ u32 next; ++ int cpu; ++ ++ cpu = cpumask_first(dev->cpumask); ++ next = ioread32(reg_count(cpu)) + delta; ++ iowrite32(next, reg_compare(cpu)); ++ ++ if ((s32)(next - ioread32(reg_count(cpu))) < ECONET_MIN_DELTA / 2) ++ return -ETIME; ++ ++ return 0; ++} ++ ++static int cevt_init_cpu(uint cpu) ++{ ++ struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, cpu); ++ u32 reg; ++ ++ pr_debug("%s: Setting up clockevent for CPU %d\n", cd->name, cpu); ++ ++ reg = ioread32(reg_ctl(cpu)) | ctl_bit_enabled(cpu); ++ iowrite32(reg, reg_ctl(cpu)); ++ ++ enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); ++ ++ /* Do this last because it synchronously configures the timer */ ++ clockevents_config_and_register(cd, econet_timer.freq_hz, ++ ECONET_MIN_DELTA, ECONET_MAX_DELTA); ++ ++ return 0; ++} ++ ++static u64 notrace sched_clock_read(void) ++{ ++ /* Always read from clock zero no matter the CPU */ ++ return (u64)ioread32(reg_count(0)); ++} ++ ++/* Init */ ++ ++static void __init cevt_dev_init(uint cpu) ++{ ++ iowrite32(0, reg_count(cpu)); ++ iowrite32(U32_MAX, reg_compare(cpu)); ++} ++ ++static int __init cevt_init(struct device_node *np) ++{ ++ int i, irq, ret; ++ ++ irq = irq_of_parse_and_map(np, 0); ++ if (irq <= 0) { ++ pr_err("%pOFn: irq_of_parse_and_map failed", np); ++ return -EINVAL; ++ } ++ ++ ret = request_percpu_irq(irq, cevt_interrupt, np->name, &econet_timer_pcpu); ++ ++ if (ret < 0) { ++ pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, irq, ret); ++ goto err_unmap_irq; ++ } ++ ++ for_each_possible_cpu(i) { ++ struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i); ++ ++ cd->rating = 310, ++ cd->features = CLOCK_EVT_FEAT_ONESHOT | ++ CLOCK_EVT_FEAT_C3STOP | ++ CLOCK_EVT_FEAT_PERCPU; ++ cd->set_next_event = cevt_set_next_event; ++ cd->irq = irq; ++ cd->cpumask = cpumask_of(i); ++ cd->name = np->name; ++ ++ cevt_dev_init(i); ++ } ++ ++ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, ++ "clockevents/econet/timer:starting", ++ cevt_init_cpu, NULL); ++ return 0; ++ ++err_unmap_irq: ++ irq_dispose_mapping(irq); ++ return ret; ++} ++ ++static int __init timer_init(struct device_node *np) ++{ ++ int num_blocks = DIV_ROUND_UP(num_possible_cpus(), 2); ++ struct clk *clk; ++ int ret; ++ ++ clk = of_clk_get(np, 0); ++ if (IS_ERR(clk)) { ++ pr_err("%pOFn: Failed to get CPU clock from DT %ld\n", np, PTR_ERR(clk)); ++ return PTR_ERR(clk); ++ } ++ ++ econet_timer.freq_hz = clk_get_rate(clk); ++ ++ for (int i = 0; i < num_blocks; i++) { ++ econet_timer.membase[i] = of_iomap(np, i); ++ if (!econet_timer.membase[i]) { ++ pr_err("%pOFn: failed to map register [%d]\n", np, i); ++ return -ENXIO; ++ } ++ } ++ ++ /* For clocksource purposes always read clock zero, whatever the CPU */ ++ ret = clocksource_mmio_init(reg_count(0), np->name, ++ econet_timer.freq_hz, 301, ECONET_BITS, ++ clocksource_mmio_readl_up); ++ if (ret) { ++ pr_err("%pOFn: clocksource_mmio_init failed: %d", np, ret); ++ return ret; ++ } ++ ++ ret = cevt_init(np); ++ if (ret < 0) ++ return ret; ++ ++ sched_clock_register(sched_clock_read, ECONET_BITS, ++ econet_timer.freq_hz); ++ ++ pr_info("%pOFn: using %u.%03u MHz high precision timer\n", np, ++ econet_timer.freq_hz / 1000000, ++ (econet_timer.freq_hz / 1000) % 1000); ++ ++ return 0; ++} ++ ++TIMER_OF_DECLARE(econet_timer_hpt, "econet,en751221-timer", timer_init); diff --git a/target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch b/target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch new file mode 100644 index 0000000000..64714dc8a2 --- /dev/null +++ b/target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch @@ -0,0 +1,44 @@ +From be8b4173719a61fdd8379e86895d855775cf5f91 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Wed, 7 May 2025 13:44:56 +0000 +Subject: [PATCH] dt-bindings: mips: Add EcoNet platform binding + +Document the top-level device tree binding for EcoNet MIPS-based SoCs. + +Signed-off-by: Caleb James DeLisle +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Thomas Bogendoerfer +--- + .../devicetree/bindings/mips/econet.yaml | 26 +++++++++++++++++++ + 1 file changed, 26 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mips/econet.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mips/econet.yaml +@@ -0,0 +1,26 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mips/econet.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: EcoNet MIPS SoCs ++ ++maintainers: ++ - Caleb James DeLisle ++ ++properties: ++ $nodename: ++ const: '/' ++ ++ compatible: ++ oneOf: ++ - description: Boards with EcoNet EN751221 family SoC ++ items: ++ - enum: ++ - smartfiber,xp8421-b ++ - const: econet,en751221 ++ ++additionalProperties: true ++ ++... diff --git a/target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch b/target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch new file mode 100644 index 0000000000..86b05b07a1 --- /dev/null +++ b/target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch @@ -0,0 +1,222 @@ +From 35fb26f94dfa1b291086b84b2421f957214824d1 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Wed, 7 May 2025 13:44:57 +0000 +Subject: [PATCH] mips: Add EcoNet MIPS platform support + +Add platform support for EcoNet MIPS SoCs. + +Signed-off-by: Caleb James DeLisle +Signed-off-by: Thomas Bogendoerfer +--- + arch/mips/Kbuild.platforms | 1 + + arch/mips/Kconfig | 25 +++++++++ + arch/mips/boot/compressed/uart-16550.c | 5 ++ + arch/mips/econet/Kconfig | 37 ++++++++++++ + arch/mips/econet/Makefile | 2 + + arch/mips/econet/Platform | 5 ++ + arch/mips/econet/init.c | 78 ++++++++++++++++++++++++++ + 7 files changed, 153 insertions(+) + create mode 100644 arch/mips/econet/Kconfig + create mode 100644 arch/mips/econet/Makefile + create mode 100644 arch/mips/econet/Platform + create mode 100644 arch/mips/econet/init.c + +--- a/arch/mips/Kbuild.platforms ++++ b/arch/mips/Kbuild.platforms +@@ -11,6 +11,7 @@ platform-$(CONFIG_CAVIUM_OCTEON_SOC) += + platform-$(CONFIG_EYEQ) += mobileye/ + platform-$(CONFIG_MIPS_COBALT) += cobalt/ + platform-$(CONFIG_MACH_DECSTATION) += dec/ ++platform-$(CONFIG_ECONET) += econet/ + platform-$(CONFIG_MIPS_GENERIC) += generic/ + platform-$(CONFIG_MACH_JAZZ) += jazz/ + platform-$(CONFIG_LANTIQ) += lantiq/ +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -388,6 +388,30 @@ config MACH_DECSTATION + + otherwise choose R3000. + ++config ECONET ++ bool "EcoNet MIPS family" ++ select BOOT_RAW ++ select CPU_BIG_ENDIAN ++ select DEBUG_ZBOOT ++ select EARLY_PRINTK_8250 ++ select ECONET_EN751221_TIMER ++ select SERIAL_OF_PLATFORM ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_HAS_CPU_MIPS32_R2 ++ select SYS_HAS_EARLY_PRINTK ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select SYS_SUPPORTS_MIPS16 ++ select SYS_SUPPORTS_ZBOOT_UART16550 ++ select USE_GENERIC_EARLY_PRINTK_8250 ++ select USE_OF ++ help ++ EcoNet EN75xx MIPS devices are big endian MIPS machines used ++ in XPON (fiber) and DSL applications. They have SPI, PCI, USB, ++ GPIO, and Ethernet, with optional XPON, DSL, and VoIP DSP cores. ++ Don't confuse these with the Airoha ARM devices sometimes referred ++ to as "EcoNet", this family is for MIPS based devices only. ++ + config MACH_JAZZ + bool "Jazz family of machines" + select ARC_MEMORY +@@ -1017,6 +1041,7 @@ source "arch/mips/ath79/Kconfig" + source "arch/mips/bcm47xx/Kconfig" + source "arch/mips/bcm63xx/Kconfig" + source "arch/mips/bmips/Kconfig" ++source "arch/mips/econet/Kconfig" + source "arch/mips/generic/Kconfig" + source "arch/mips/ingenic/Kconfig" + source "arch/mips/jazz/Kconfig" +--- a/arch/mips/boot/compressed/uart-16550.c ++++ b/arch/mips/boot/compressed/uart-16550.c +@@ -20,6 +20,11 @@ + #define PORT(offset) (CKSEG1ADDR(INGENIC_UART_BASE_ADDR) + (4 * offset)) + #endif + ++#ifdef CONFIG_ECONET ++#define EN75_UART_BASE 0x1fbf0003 ++#define PORT(offset) (CKSEG1ADDR(EN75_UART_BASE) + (4 * (offset))) ++#endif ++ + #ifndef IOTYPE + #define IOTYPE char + #endif +--- /dev/null ++++ b/arch/mips/econet/Kconfig +@@ -0,0 +1,37 @@ ++# SPDX-License-Identifier: GPL-2.0 ++if ECONET ++ ++choice ++ prompt "EcoNet SoC selection" ++ default SOC_ECONET_EN751221 ++ help ++ Select EcoNet MIPS SoC type. Individual SoCs within a family are ++ very similar, so is it enough to select the right family, and ++ then customize to the specific SoC using the device tree only. ++ ++ config SOC_ECONET_EN751221 ++ bool "EN751221 family" ++ select COMMON_CLK ++ select ECONET_EN751221_INTC ++ select IRQ_MIPS_CPU ++ select SMP ++ select SMP_UP ++ select SYS_SUPPORTS_SMP ++ help ++ The EN751221 family includes EN7512, RN7513, EN7521, EN7526. ++ They are based on single core MIPS 34Kc processors. To boot ++ this kernel, you will need a device tree such as ++ MIPS_RAW_APPENDED_DTB=y, and a root filesystem. ++endchoice ++ ++choice ++ prompt "Devicetree selection" ++ default DTB_ECONET_NONE ++ help ++ Select the devicetree. ++ ++ config DTB_ECONET_NONE ++ bool "None" ++endchoice ++ ++endif +--- /dev/null ++++ b/arch/mips/econet/Makefile +@@ -0,0 +1,2 @@ ++ ++obj-y := init.o +--- /dev/null ++++ b/arch/mips/econet/Platform +@@ -0,0 +1,5 @@ ++# To address a 7.2MB kernel size limit in the EcoNet SDK bootloader, ++# we put the load address well above where the bootloader loads and then use ++# zboot. So please set CONFIG_ZBOOT_LOAD_ADDRESS to the address where your ++# bootloader actually places the kernel. ++load-$(CONFIG_ECONET) += 0xffffffff81000000 +--- /dev/null ++++ b/arch/mips/econet/init.c +@@ -0,0 +1,78 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * EcoNet setup code ++ * ++ * Copyright (C) 2025 Caleb James DeLisle ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define CR_AHB_RSTCR ((void __iomem *)CKSEG1ADDR(0x1fb00040)) ++#define RESET BIT(31) ++ ++#define UART_BASE CKSEG1ADDR(0x1fbf0003) ++#define UART_REG_SHIFT 2 ++ ++static void hw_reset(char *command) ++{ ++ iowrite32(RESET, CR_AHB_RSTCR); ++} ++ ++/* 1. Bring up early printk. */ ++void __init prom_init(void) ++{ ++ setup_8250_early_printk_port(UART_BASE, UART_REG_SHIFT, 0); ++ _machine_restart = hw_reset; ++} ++ ++/* 2. Parse the DT and find memory */ ++void __init plat_mem_setup(void) ++{ ++ void *dtb; ++ ++ set_io_port_base(KSEG1); ++ ++ dtb = get_fdt(); ++ if (!dtb) ++ panic("no dtb found"); ++ ++ __dt_setup_arch(dtb); ++ ++ early_init_dt_scan_memory(); ++} ++ ++/* 3. Overload __weak device_tree_init(), add SMP_UP ops */ ++void __init device_tree_init(void) ++{ ++ unflatten_and_copy_device_tree(); ++ ++ register_up_smp_ops(); ++} ++ ++const char *get_system_type(void) ++{ ++ return "EcoNet-EN75xx"; ++} ++ ++/* 4. Initialize the IRQ subsystem */ ++void __init arch_init_irq(void) ++{ ++ irqchip_init(); ++} ++ ++/* 5. Timers */ ++void __init plat_time_init(void) ++{ ++ of_clk_init(NULL); ++ timer_probe(); ++} diff --git a/target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch b/target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch new file mode 100644 index 0000000000..6d51af0231 --- /dev/null +++ b/target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch @@ -0,0 +1,29 @@ +From abc2d0bc2cb7c1412b8b254c0446f94b3e203c7c Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Wed, 7 May 2025 13:44:58 +0000 +Subject: [PATCH] dt-bindings: vendor-prefixes: Add SmartFiber +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add "smartfiber" vendor prefix for manufactorer of EcoNet based boards. + +Signed-off-by: Caleb James DeLisle +Acked-by: Krzysztof Kozlowski +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Thomas Bogendoerfer +--- + Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml ++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml +@@ -1370,6 +1370,8 @@ patternProperties: + description: SKOV A/S + "^skyworks,.*": + description: Skyworks Solutions, Inc. ++ "^smartfiber,.*": ++ description: ShenZhen Smartfiber Technology Co, Ltd. + "^smartlabs,.*": + description: SmartLabs LLC + "^smartrg,.*": diff --git a/target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch b/target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch new file mode 100644 index 0000000000..cb5b457137 --- /dev/null +++ b/target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch @@ -0,0 +1,149 @@ +From 0ec4887009729297f7c10368084e41a8a9fbbd0e Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Wed, 7 May 2025 13:44:59 +0000 +Subject: [PATCH] mips: dts: Add EcoNet DTS with EN751221 and SmartFiber + XP8421-B board + +Add DTS files in support of EcoNet platform, including SmartFiber XP8421-B, +a low cost commercially available board based on EN751221. + +Signed-off-by: Caleb James DeLisle +Signed-off-by: Thomas Bogendoerfer +--- + arch/mips/boot/dts/Makefile | 1 + + arch/mips/boot/dts/econet/Makefile | 2 + + arch/mips/boot/dts/econet/en751221.dtsi | 67 +++++++++++++++++++ + .../econet/en751221_smartfiber_xp8421-b.dts | 19 ++++++ + arch/mips/econet/Kconfig | 11 +++ + 5 files changed, 100 insertions(+) + create mode 100644 arch/mips/boot/dts/econet/Makefile + create mode 100644 arch/mips/boot/dts/econet/en751221.dtsi + create mode 100644 arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts + +--- a/arch/mips/boot/dts/Makefile ++++ b/arch/mips/boot/dts/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + subdir-$(CONFIG_BMIPS_GENERIC) += brcm + subdir-$(CONFIG_CAVIUM_OCTEON_SOC) += cavium-octeon ++subdir-$(CONFIG_ECONET) += econet + subdir-$(CONFIG_EYEQ) += mobileye + subdir-$(CONFIG_FIT_IMAGE_FDT_MARDUK) += img + subdir-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += img +--- /dev/null ++++ b/arch/mips/boot/dts/econet/Makefile +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0 ++dtb-$(CONFIG_DTB_ECONET_SMARTFIBER_XP8421_B) += en751221_smartfiber_xp8421-b.dtb +--- /dev/null ++++ b/arch/mips/boot/dts/econet/en751221.dtsi +@@ -0,0 +1,67 @@ ++// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++/dts-v1/; ++ ++/ { ++ compatible = "econet,en751221"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ hpt_clock: clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <200000000>; /* 200 MHz */ ++ }; ++ ++ cpus: cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu@0 { ++ device_type = "cpu"; ++ compatible = "mips,mips24KEc"; ++ reg = <0>; ++ }; ++ }; ++ ++ cpuintc: interrupt-controller { ++ compatible = "mti,cpu-interrupt-controller"; ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ }; ++ ++ intc: interrupt-controller@1fb40000 { ++ compatible = "econet,en751221-intc"; ++ reg = <0x1fb40000 0x100>; ++ interrupt-parent = <&cpuintc>; ++ interrupts = <2>; ++ ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ econet,shadow-interrupts = <7 2>, <8 3>, <13 12>, <30 29>; ++ }; ++ ++ uart: serial@1fbf0000 { ++ compatible = "ns16550"; ++ reg = <0x1fbf0000 0x30>; ++ reg-io-width = <4>; ++ reg-shift = <2>; ++ interrupt-parent = <&intc>; ++ interrupts = <0>; ++ /* ++ * Conversion of baud rate to clock frequency requires a ++ * computation that is not in the ns16550 driver, so this ++ * uart is fixed at 115200 baud. ++ */ ++ clock-frequency = <1843200>; ++ }; ++ ++ timer_hpt: timer@1fbf0400 { ++ compatible = "econet,en751221-timer"; ++ reg = <0x1fbf0400 0x100>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <30>; ++ clocks = <&hpt_clock>; ++ }; ++}; +--- /dev/null ++++ b/arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts +@@ -0,0 +1,19 @@ ++// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++/dts-v1/; ++ ++#include "en751221.dtsi" ++ ++/ { ++ model = "SmartFiber XP8421-B"; ++ compatible = "smartfiber,xp8421-b", "econet,en751221"; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x00000000 0x1c000000>; ++ }; ++ ++ chosen { ++ stdout-path = "/serial@1fbf0000:115200"; ++ linux,usable-memory-range = <0x00020000 0x1bfe0000>; ++ }; ++}; +--- a/arch/mips/econet/Kconfig ++++ b/arch/mips/econet/Kconfig +@@ -32,6 +32,17 @@ choice + + config DTB_ECONET_NONE + bool "None" ++ ++ config DTB_ECONET_SMARTFIBER_XP8421_B ++ bool "EN751221 SmartFiber XP8421-B" ++ depends on SOC_ECONET_EN751221 ++ select BUILTIN_DTB ++ help ++ The SmartFiber XP8421-B is a device based on the EN751221 SoC. ++ It has 512MB of memory and 256MB of NAND flash. This kernel ++ needs only an appended initramfs to boot. It can be loaded ++ through XMODEM and booted from memory in the bootloader, or ++ it can be packed in tclinux.trx format and written to flash. + endchoice + + endif diff --git a/target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch b/target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch new file mode 100644 index 0000000000..e4230573c2 --- /dev/null +++ b/target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch @@ -0,0 +1,38 @@ +From faefb0a59c5914b7b8f737e2ec5c82822e5bc4c7 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Wed, 7 May 2025 13:45:00 +0000 +Subject: [PATCH] MAINTAINERS: Add entry for newly added EcoNet platform. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add a MAINTAINERS entry as part of integration of the EcoNet MIPS platform. + +Signed-off-by: Caleb James DeLisle +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Thomas Bogendoerfer +--- + MAINTAINERS | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -8025,6 +8025,18 @@ W: https://linuxtv.org + Q: http://patchwork.linuxtv.org/project/linux-media/list/ + F: drivers/media/dvb-frontends/ec100* + ++ECONET MIPS PLATFORM ++M: Caleb James DeLisle ++L: linux-mips@vger.kernel.org ++S: Maintained ++F: Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml ++F: Documentation/devicetree/bindings/mips/econet.yaml ++F: Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml ++F: arch/mips/boot/dts/econet/ ++F: arch/mips/econet/ ++F: drivers/clocksource/timer-econet-en751221.c ++F: drivers/irqchip/irq-econet-en751221.c ++ + ECRYPT FILE SYSTEM + M: Tyler Hicks + L: ecryptfs@vger.kernel.org diff --git a/target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch b/target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch new file mode 100644 index 0000000000..fe9e6792eb --- /dev/null +++ b/target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch @@ -0,0 +1,32 @@ +From 79ee1d20e37cd553cc961962fca8107e69a0c293 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Wed, 21 May 2025 21:33:33 +0000 +Subject: [PATCH] mips: econet: Fix incorrect Kconfig dependencies + +config ECONET selects SERIAL_OF_PLATFORM and that depends on SERIAL_8250 +so we need to select SERIAL_8250 directly. +Also do not enable DEBUG_ZBOOT unless DEBUG_KERNEL is set. + +Signed-off-by: Caleb James DeLisle +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202505211654.CBdIsoTq-lkp@intel.com/ +Closes: https://lore.kernel.org/oe-kbuild-all/202505211451.WRjyf3a9-lkp@intel.com/ +Signed-off-by: Thomas Bogendoerfer +--- + arch/mips/Kconfig | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -392,9 +392,10 @@ config ECONET + bool "EcoNet MIPS family" + select BOOT_RAW + select CPU_BIG_ENDIAN +- select DEBUG_ZBOOT ++ select DEBUG_ZBOOT if DEBUG_KERNEL + select EARLY_PRINTK_8250 + select ECONET_EN751221_TIMER ++ select SERIAL_8250 + select SERIAL_OF_PLATFORM + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_HAS_CPU_MIPS32_R1 diff --git a/target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch b/target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch new file mode 100644 index 0000000000..26b3da9c4d --- /dev/null +++ b/target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch @@ -0,0 +1,174 @@ +From 82e6bf912d5846646892becea659b39d178d79e3 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 12 Nov 2024 01:08:53 +0100 +Subject: [PATCH 5/8] clk: en7523: move en7581_reset_register() in + en7581_clk_hw_init() + +Move en7581_reset_register routine in en7581_clk_hw_init() since reset +feature is supported just by EN7581 SoC. +Get rid of reset struct in en_clk_soc_data data struct. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-6-8ada5e394ae4@kernel.org +Signed-off-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 93 ++++++++++++++-------------------------- + 1 file changed, 33 insertions(+), 60 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -76,11 +76,6 @@ struct en_rst_data { + + struct en_clk_soc_data { + const struct clk_ops pcie_ops; +- struct { +- const u16 *bank_ofs; +- const u16 *idx_map; +- u16 idx_map_nr; +- } reset; + int (*hw_init)(struct platform_device *pdev, + struct clk_hw_onecell_data *clk_data); + }; +@@ -596,32 +591,6 @@ static void en7581_register_clocks(struc + clk_data->num = EN7523_NUM_CLOCKS; + } + +-static int en7581_clk_hw_init(struct platform_device *pdev, +- struct clk_hw_onecell_data *clk_data) +-{ +- void __iomem *np_base; +- struct regmap *map; +- u32 val; +- +- map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); +- if (IS_ERR(map)) +- return PTR_ERR(map); +- +- np_base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(np_base)) +- return PTR_ERR(np_base); +- +- en7581_register_clocks(&pdev->dev, clk_data, map, np_base); +- +- val = readl(np_base + REG_NP_SCU_SSTR); +- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); +- writel(val, np_base + REG_NP_SCU_SSTR); +- val = readl(np_base + REG_NP_SCU_PCIC); +- writel(val | 3, np_base + REG_NP_SCU_PCIC); +- +- return 0; +-} +- + static int en7523_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) + { +@@ -671,23 +640,18 @@ static int en7523_reset_xlate(struct res + return rst_data->idx_map[reset_spec->args[0]]; + } + +-static const struct reset_control_ops en7523_reset_ops = { ++static const struct reset_control_ops en7581_reset_ops = { + .assert = en7523_reset_assert, + .deassert = en7523_reset_deassert, + .status = en7523_reset_status, + }; + +-static int en7523_reset_register(struct platform_device *pdev, +- const struct en_clk_soc_data *soc_data) ++static int en7581_reset_register(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct en_rst_data *rst_data; + void __iomem *base; + +- /* no reset lines available */ +- if (!soc_data->reset.idx_map_nr) +- return 0; +- + base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(base)) + return PTR_ERR(base); +@@ -696,13 +660,13 @@ static int en7523_reset_register(struct + if (!rst_data) + return -ENOMEM; + +- rst_data->bank_ofs = soc_data->reset.bank_ofs; +- rst_data->idx_map = soc_data->reset.idx_map; ++ rst_data->bank_ofs = en7581_rst_ofs; ++ rst_data->idx_map = en7581_rst_map; + rst_data->base = base; + +- rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr; ++ rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); + rst_data->rcdev.of_xlate = en7523_reset_xlate; +- rst_data->rcdev.ops = &en7523_reset_ops; ++ rst_data->rcdev.ops = &en7581_reset_ops; + rst_data->rcdev.of_node = dev->of_node; + rst_data->rcdev.of_reset_n_cells = 1; + rst_data->rcdev.owner = THIS_MODULE; +@@ -711,6 +675,32 @@ static int en7523_reset_register(struct + return devm_reset_controller_register(dev, &rst_data->rcdev); + } + ++static int en7581_clk_hw_init(struct platform_device *pdev, ++ struct clk_hw_onecell_data *clk_data) ++{ ++ void __iomem *np_base; ++ struct regmap *map; ++ u32 val; ++ ++ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); ++ if (IS_ERR(map)) ++ return PTR_ERR(map); ++ ++ np_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(np_base)) ++ return PTR_ERR(np_base); ++ ++ en7581_register_clocks(&pdev->dev, clk_data, map, np_base); ++ ++ val = readl(np_base + REG_NP_SCU_SSTR); ++ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); ++ writel(val, np_base + REG_NP_SCU_SSTR); ++ val = readl(np_base + REG_NP_SCU_PCIC); ++ writel(val | 3, np_base + REG_NP_SCU_PCIC); ++ ++ return en7581_reset_register(pdev); ++} ++ + static int en7523_clk_probe(struct platform_device *pdev) + { + struct device_node *node = pdev->dev.of_node; +@@ -729,19 +719,7 @@ static int en7523_clk_probe(struct platf + if (r) + return r; + +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) +- return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n", +- pdev->name); +- +- r = en7523_reset_register(pdev, soc_data); +- if (r) { +- of_clk_del_provider(node); +- return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n", +- pdev->name); +- } +- +- return 0; ++ return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + } + + static const struct en_clk_soc_data en7523_data = { +@@ -759,11 +737,6 @@ static const struct en_clk_soc_data en75 + .enable = en7581_pci_enable, + .disable = en7581_pci_disable, + }, +- .reset = { +- .bank_ofs = en7581_rst_ofs, +- .idx_map = en7581_rst_map, +- .idx_map_nr = ARRAY_SIZE(en7581_rst_map), +- }, + .hw_init = en7581_clk_hw_init, + }; + diff --git a/target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch b/target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch new file mode 100644 index 0000000000..4e4952d8a6 --- /dev/null +++ b/target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch @@ -0,0 +1,84 @@ +From a9eaf305017a5ebe73ab34e85bd5414055a88f29 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 12 Nov 2024 01:08:54 +0100 +Subject: [PATCH 6/8] clk: en7523: map io region in a single block + +Map all clock-controller memory region in a single block. +This patch does not introduce any backward incompatibility since the dts +for EN7581 SoC is not upstream yet. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-7-8ada5e394ae4@kernel.org +Signed-off-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 32 +++++++++++++------------------- + 1 file changed, 13 insertions(+), 19 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -39,8 +39,8 @@ + #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) + #define REG_CRYPTO_CLKSRC2 0x20c + +-#define REG_RST_CTRL2 0x00 +-#define REG_RST_CTRL1 0x04 ++#define REG_RST_CTRL2 0x830 ++#define REG_RST_CTRL1 0x834 + + struct en_clk_desc { + int id; +@@ -646,15 +646,9 @@ static const struct reset_control_ops en + .status = en7523_reset_status, + }; + +-static int en7581_reset_register(struct platform_device *pdev) ++static int en7581_reset_register(struct device *dev, void __iomem *base) + { +- struct device *dev = &pdev->dev; + struct en_rst_data *rst_data; +- void __iomem *base; +- +- base = devm_platform_ioremap_resource(pdev, 1); +- if (IS_ERR(base)) +- return PTR_ERR(base); + + rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); + if (!rst_data) +@@ -678,27 +672,27 @@ static int en7581_reset_register(struct + static int en7581_clk_hw_init(struct platform_device *pdev, + struct clk_hw_onecell_data *clk_data) + { +- void __iomem *np_base; + struct regmap *map; ++ void __iomem *base; + u32 val; + + map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); + if (IS_ERR(map)) + return PTR_ERR(map); + +- np_base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(np_base)) +- return PTR_ERR(np_base); ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); + +- en7581_register_clocks(&pdev->dev, clk_data, map, np_base); ++ en7581_register_clocks(&pdev->dev, clk_data, map, base); + +- val = readl(np_base + REG_NP_SCU_SSTR); ++ val = readl(base + REG_NP_SCU_SSTR); + val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); +- writel(val, np_base + REG_NP_SCU_SSTR); +- val = readl(np_base + REG_NP_SCU_PCIC); +- writel(val | 3, np_base + REG_NP_SCU_PCIC); ++ writel(val, base + REG_NP_SCU_SSTR); ++ val = readl(base + REG_NP_SCU_PCIC); ++ writel(val | 3, base + REG_NP_SCU_PCIC); + +- return en7581_reset_register(pdev); ++ return en7581_reset_register(&pdev->dev, base); + } + + static int en7523_clk_probe(struct platform_device *pdev) diff --git a/target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch b/target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch new file mode 100644 index 0000000000..44664202a8 --- /dev/null +++ b/target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch @@ -0,0 +1,42 @@ +From 90d4e466c9ea2010f33880a36317a8486ccbe082 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 8 Jan 2025 10:50:43 +0100 +Subject: [PATCH 1/3] PCI: mediatek-gen3: Move reset delay in + mtk_pcie_en7581_power_up() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal +causing occasional PCIe link down issues. In order to overcome the +problem, PCIe block is reset using REG_PCI_CONTROL (0x88) and +REG_RESET_CONTROL (0x834) registers available in the clock module +running clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up(). + +In order to make the code more readable, move the wait for the time +needed to complete the PCIe reset from en7581_pci_enable() to +mtk_pcie_en7581_power_up(). + +Reduce reset timeout from 250ms to the standard PCIE_T_PVPERL_MS value +(100ms) since it has no impact on the driver behavior. + +Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-4-21ac939a3b9b@kernel.org +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Manivannan Sadhasivam +Acked-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -478,7 +478,6 @@ static int en7581_pci_enable(struct clk_ + REG_PCI_CONTROL_PERSTOUT; + val = readl(np_base + REG_PCI_CONTROL); + writel(val | mask, np_base + REG_PCI_CONTROL); +- msleep(250); + + return 0; + } diff --git a/target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch b/target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch new file mode 100644 index 0000000000..a33e842b9e --- /dev/null +++ b/target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch @@ -0,0 +1,83 @@ +From e4a9748e7103c47e575459db2b6a77d14f34da2b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Jan 2025 00:10:02 +0100 +Subject: [PATCH 2/3] clk: en7523: Rework clock handling for different clock + numbers + +Airoha EN7581 SoC have additional clock compared to EN7523 but current +driver permits to only support up to EN7523 clock numbers. + +To handle this, rework the clock handling and permit to declare the +clocks number in match_data and alloca clk_data based on the compatible +match_data. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20250113231030.6735-2-ansuelsmth@gmail.com +Signed-off-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -75,6 +75,7 @@ struct en_rst_data { + }; + + struct en_clk_soc_data { ++ u32 num_clocks; + const struct clk_ops pcie_ops; + int (*hw_init)(struct platform_device *pdev, + struct clk_hw_onecell_data *clk_data); +@@ -503,8 +504,6 @@ static void en7523_register_clocks(struc + u32 rate; + int i; + +- clk_data->num = EN7523_NUM_CLOCKS; +- + for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { + const struct en_clk_desc *desc = &en7523_base_clks[i]; + u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg; +@@ -586,8 +585,6 @@ static void en7581_register_clocks(struc + + hw = en7523_register_pcie_clk(dev, base); + clk_data->hws[EN7523_CLK_PCIE] = hw; +- +- clk_data->num = EN7523_NUM_CLOCKS; + } + + static int en7523_reset_update(struct reset_controller_dev *rcdev, +@@ -701,13 +698,15 @@ static int en7523_clk_probe(struct platf + struct clk_hw_onecell_data *clk_data; + int r; + ++ soc_data = device_get_match_data(&pdev->dev); ++ + clk_data = devm_kzalloc(&pdev->dev, +- struct_size(clk_data, hws, EN7523_NUM_CLOCKS), ++ struct_size(clk_data, hws, soc_data->num_clocks), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + +- soc_data = device_get_match_data(&pdev->dev); ++ clk_data->num = soc_data->num_clocks; + r = soc_data->hw_init(pdev, clk_data); + if (r) + return r; +@@ -716,6 +715,7 @@ static int en7523_clk_probe(struct platf + } + + static const struct en_clk_soc_data en7523_data = { ++ .num_clocks = ARRAY_SIZE(en7523_base_clks) + 1, + .pcie_ops = { + .is_enabled = en7523_pci_is_enabled, + .prepare = en7523_pci_prepare, +@@ -725,6 +725,8 @@ static const struct en_clk_soc_data en75 + }; + + static const struct en_clk_soc_data en7581_data = { ++ /* We increment num_clocks by 1 to account for additional PCIe clock */ ++ .num_clocks = ARRAY_SIZE(en7581_base_clks) + 1, + .pcie_ops = { + .is_enabled = en7581_pci_is_enabled, + .enable = en7581_pci_enable, diff --git a/target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch b/target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch new file mode 100644 index 0000000000..35d34a5ccf --- /dev/null +++ b/target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch @@ -0,0 +1,41 @@ +From bfe257f9780d8f77045a7da6ec959ee0659d2f98 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Jan 2025 00:10:05 +0100 +Subject: [PATCH 3/3] clk: en7523: Add clock for eMMC for EN7581 + +Add clock for eMMC for EN7581. This is used to give info of the current +eMMC source clock and to switch it from 200MHz or 150MHz. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20250113231030.6735-5-ansuelsmth@gmail.com +Signed-off-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -91,6 +91,7 @@ static const u32 emi7581_base[] = { 5400 + static const u32 bus7581_base[] = { 600000000, 540000000 }; + static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; + static const u32 crypto_base[] = { 540000000, 480000000 }; ++static const u32 emmc7581_base[] = { 200000000, 150000000 }; + + static const struct en_clk_desc en7523_base_clks[] = { + { +@@ -281,6 +282,15 @@ static const struct en_clk_desc en7581_b + .base_shift = 0, + .base_values = crypto_base, + .n_base_values = ARRAY_SIZE(crypto_base), ++ }, { ++ .id = EN7581_CLK_EMMC, ++ .name = "emmc", ++ ++ .base_reg = REG_CRYPTO_CLKSRC2, ++ .base_bits = 1, ++ .base_shift = 12, ++ .base_values = emmc7581_base, ++ .n_base_values = ARRAY_SIZE(emmc7581_base), + } + }; + diff --git a/target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch b/target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch new file mode 100644 index 0000000000..c332cef387 --- /dev/null +++ b/target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch @@ -0,0 +1,133 @@ +From 1c0608d860db973ad09b5a9ccb19b76ae07622a3 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Mon, 10 Nov 2025 06:56:44 +0300 +Subject: [PATCH] clk: en7523: Add reset-controller support for EN7523 SoC + +Introduce reset API support to EN7523 clock driver. EN7523 uses the +same reset logic as EN7581, so just reuse existing code. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Philipp Zabel +Signed-off-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 64 ++++++++++++++++++++++++++++++++++++---- + 1 file changed, 59 insertions(+), 5 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + + #define RST_NR_PER_BANK 32 +@@ -299,6 +300,53 @@ static const u16 en7581_rst_ofs[] = { + REG_RST_CTRL1, + }; + ++static const u16 en7523_rst_map[] = { ++ /* RST_CTRL2 */ ++ [EN7523_XPON_PHY_RST] = 0, ++ [EN7523_XSI_MAC_RST] = 7, ++ [EN7523_XSI_PHY_RST] = 8, ++ [EN7523_NPU_RST] = 9, ++ [EN7523_I2S_RST] = 10, ++ [EN7523_TRNG_RST] = 11, ++ [EN7523_TRNG_MSTART_RST] = 12, ++ [EN7523_DUAL_HSI0_RST] = 13, ++ [EN7523_DUAL_HSI1_RST] = 14, ++ [EN7523_HSI_RST] = 15, ++ [EN7523_DUAL_HSI0_MAC_RST] = 16, ++ [EN7523_DUAL_HSI1_MAC_RST] = 17, ++ [EN7523_HSI_MAC_RST] = 18, ++ [EN7523_WDMA_RST] = 19, ++ [EN7523_WOE0_RST] = 20, ++ [EN7523_WOE1_RST] = 21, ++ [EN7523_HSDMA_RST] = 22, ++ [EN7523_I2C2RBUS_RST] = 23, ++ [EN7523_TDMA_RST] = 24, ++ /* RST_CTRL1 */ ++ [EN7523_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0, ++ [EN7523_FE_PDMA_RST] = RST_NR_PER_BANK + 1, ++ [EN7523_FE_QDMA_RST] = RST_NR_PER_BANK + 2, ++ [EN7523_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4, ++ [EN7523_CRYPTO_RST] = RST_NR_PER_BANK + 6, ++ [EN7523_TIMER_RST] = RST_NR_PER_BANK + 8, ++ [EN7523_PCM1_RST] = RST_NR_PER_BANK + 11, ++ [EN7523_UART_RST] = RST_NR_PER_BANK + 12, ++ [EN7523_GPIO_RST] = RST_NR_PER_BANK + 13, ++ [EN7523_GDMA_RST] = RST_NR_PER_BANK + 14, ++ [EN7523_I2C_MASTER_RST] = RST_NR_PER_BANK + 16, ++ [EN7523_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17, ++ [EN7523_SFC_RST] = RST_NR_PER_BANK + 18, ++ [EN7523_UART2_RST] = RST_NR_PER_BANK + 19, ++ [EN7523_GDMP_RST] = RST_NR_PER_BANK + 20, ++ [EN7523_FE_RST] = RST_NR_PER_BANK + 21, ++ [EN7523_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22, ++ [EN7523_GSW_RST] = RST_NR_PER_BANK + 23, ++ [EN7523_SFC2_PCM_RST] = RST_NR_PER_BANK + 25, ++ [EN7523_PCIE0_RST] = RST_NR_PER_BANK + 26, ++ [EN7523_PCIE1_RST] = RST_NR_PER_BANK + 27, ++ [EN7523_PCIE_HB_RST] = RST_NR_PER_BANK + 29, ++ [EN7523_XPON_MAC_RST] = RST_NR_PER_BANK + 31, ++}; ++ + static const u16 en7581_rst_map[] = { + /* RST_CTRL2 */ + [EN7581_XPON_PHY_RST] = 0, +@@ -357,6 +405,9 @@ static const u16 en7581_rst_map[] = { + [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31, + }; + ++static int en7581_reset_register(struct device *dev, void __iomem *base, ++ const u16 *rst_map, int nr_resets); ++ + static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) + { + if (!desc->base_bits) +@@ -552,7 +603,8 @@ static int en7523_clk_hw_init(struct pla + + en7523_register_clocks(&pdev->dev, clk_data, base, np_base); + +- return 0; ++ return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map, ++ ARRAY_SIZE(en7523_rst_map)); + } + + static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, +@@ -652,7 +704,8 @@ static const struct reset_control_ops en + .status = en7523_reset_status, + }; + +-static int en7581_reset_register(struct device *dev, void __iomem *base) ++static int en7581_reset_register(struct device *dev, void __iomem *base, ++ const u16 *rst_map, int nr_resets) + { + struct en_rst_data *rst_data; + +@@ -661,10 +714,10 @@ static int en7581_reset_register(struct + return -ENOMEM; + + rst_data->bank_ofs = en7581_rst_ofs; +- rst_data->idx_map = en7581_rst_map; ++ rst_data->idx_map = rst_map; + rst_data->base = base; + +- rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); ++ rst_data->rcdev.nr_resets = nr_resets; + rst_data->rcdev.of_xlate = en7523_reset_xlate; + rst_data->rcdev.ops = &en7581_reset_ops; + rst_data->rcdev.of_node = dev->of_node; +@@ -698,7 +751,8 @@ static int en7581_clk_hw_init(struct pla + val = readl(base + REG_NP_SCU_PCIC); + writel(val | 3, base + REG_NP_SCU_PCIC); + +- return en7581_reset_register(&pdev->dev, base); ++ return en7581_reset_register(&pdev->dev, base, en7581_rst_map, ++ ARRAY_SIZE(en7581_rst_map)); + } + + static int en7523_clk_probe(struct platform_device *pdev) diff --git a/target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch b/target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch new file mode 100644 index 0000000000..ef56753c9b --- /dev/null +++ b/target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch @@ -0,0 +1,35 @@ +From 947643509279a605a09959a06d332bf027e8be57 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Mon, 10 Nov 2025 06:56:43 +0300 +Subject: [PATCH] dt-bindings: clock: airoha: Add reset support to EN7523 clock + binding + +Introduce reset capability to EN7523 device-tree clock binding +documentation. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: Rob Herring (Arm) +Signed-off-by: Stephen Boyd +--- + Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml ++++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +@@ -64,8 +64,6 @@ allOf: + - description: scu base address + - description: misc scu base address + +- '#reset-cells': false +- + - if: + properties: + compatible: +@@ -89,6 +87,7 @@ examples: + reg = <0x1fa20000 0x400>, + <0x1fb00000 0x1000>; + #clock-cells = <1>; ++ #reset-cells = <1>; + }; + + - | diff --git a/target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch b/target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch new file mode 100644 index 0000000000..a4af01dd20 --- /dev/null +++ b/target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch @@ -0,0 +1,74 @@ +From 0f7c637d1103d79829dec198e5f1b678c1feb5f2 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 12 Nov 2024 01:08:48 +0100 +Subject: [PATCH] dt-bindings: clock: airoha: Update reg mapping for EN7581 + SoC. + +clk-en7523 driver for EN7581 SoC is mapping all the scu memory region +while it is configuring the chip-scu one via a syscon. Update the reg +mapping definition for this device. This patch does not introduce any +backward incompatibility since the dts for EN7581 SoC is not upstream +yet. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-1-8ada5e394ae4@kernel.org +Reviewed-by: Rob Herring (Arm) +Signed-off-by: Stephen Boyd +--- + .../bindings/clock/airoha,en7523-scu.yaml | 23 +++++++------------ + 1 file changed, 8 insertions(+), 15 deletions(-) + +--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml ++++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +@@ -34,8 +34,10 @@ properties: + - airoha,en7581-scu + + reg: +- minItems: 2 +- maxItems: 4 ++ items: ++ - description: scu base address ++ - description: misc scu base address ++ minItems: 1 + + "#clock-cells": + description: +@@ -60,9 +62,7 @@ allOf: + then: + properties: + reg: +- items: +- - description: scu base address +- - description: misc scu base address ++ minItems: 2 + + - if: + properties: +@@ -71,11 +71,7 @@ allOf: + then: + properties: + reg: +- items: +- - description: scu base address +- - description: misc scu base address +- - description: reset base address +- - description: pb scu base address ++ maxItems: 1 + + additionalProperties: false + +@@ -95,12 +91,9 @@ examples: + #address-cells = <2>; + #size-cells = <2>; + +- scuclk: clock-controller@1fa20000 { ++ scuclk: clock-controller@1fb00000 { + compatible = "airoha,en7581-scu"; +- reg = <0x0 0x1fa20000 0x0 0x400>, +- <0x0 0x1fb00000 0x0 0x90>, +- <0x0 0x1fb00830 0x0 0x8>, +- <0x0 0x1fbe3400 0x0 0xfc>; ++ reg = <0x0 0x1fb00000 0x0 0x970>; + #clock-cells = <1>; + #reset-cells = <1>; + }; diff --git a/target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch b/target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch new file mode 100644 index 0000000000..135fcced63 --- /dev/null +++ b/target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch @@ -0,0 +1,81 @@ +From 947643509279a605a09959a06d332bf027e8be57 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Mon, 10 Nov 2025 06:56:43 +0300 +Subject: [PATCH] dt-bindings: clock: airoha: Add reset support to EN7523 clock + binding + +Introduce reset capability to EN7523 device-tree clock binding +documentation. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: Rob Herring (Arm) +Signed-off-by: Stephen Boyd +--- + .../dt-bindings/reset/airoha,en7523-reset.h | 61 +++++++++++++++++++ + 1 file changed, 61 insertions(+) + create mode 100644 include/dt-bindings/reset/airoha,en7523-reset.h + +--- /dev/null ++++ b/include/dt-bindings/reset/airoha,en7523-reset.h +@@ -0,0 +1,61 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (C) 2024 iopsys Software Solutions AB. ++ * Copyright (C) 2025 Genexis AB. ++ * ++ * Author: Mikhail Kshevetskiy ++ * ++ * based on ++ * include/dt-bindings/reset/airoha,en7581-reset.h ++ * by Lorenzo Bianconi ++ */ ++ ++#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ ++#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ ++ ++/* RST_CTRL2 */ ++#define EN7523_XPON_PHY_RST 0 ++#define EN7523_XSI_MAC_RST 1 ++#define EN7523_XSI_PHY_RST 2 ++#define EN7523_NPU_RST 3 ++#define EN7523_I2S_RST 4 ++#define EN7523_TRNG_RST 5 ++#define EN7523_TRNG_MSTART_RST 6 ++#define EN7523_DUAL_HSI0_RST 7 ++#define EN7523_DUAL_HSI1_RST 8 ++#define EN7523_HSI_RST 9 ++#define EN7523_DUAL_HSI0_MAC_RST 10 ++#define EN7523_DUAL_HSI1_MAC_RST 11 ++#define EN7523_HSI_MAC_RST 12 ++#define EN7523_WDMA_RST 13 ++#define EN7523_WOE0_RST 14 ++#define EN7523_WOE1_RST 15 ++#define EN7523_HSDMA_RST 16 ++#define EN7523_I2C2RBUS_RST 17 ++#define EN7523_TDMA_RST 18 ++/* RST_CTRL1 */ ++#define EN7523_PCM1_ZSI_ISI_RST 19 ++#define EN7523_FE_PDMA_RST 20 ++#define EN7523_FE_QDMA_RST 21 ++#define EN7523_PCM_SPIWP_RST 22 ++#define EN7523_CRYPTO_RST 23 ++#define EN7523_TIMER_RST 24 ++#define EN7523_PCM1_RST 25 ++#define EN7523_UART_RST 26 ++#define EN7523_GPIO_RST 27 ++#define EN7523_GDMA_RST 28 ++#define EN7523_I2C_MASTER_RST 29 ++#define EN7523_PCM2_ZSI_ISI_RST 30 ++#define EN7523_SFC_RST 31 ++#define EN7523_UART2_RST 32 ++#define EN7523_GDMP_RST 33 ++#define EN7523_FE_RST 34 ++#define EN7523_USB_HOST_P0_RST 35 ++#define EN7523_GSW_RST 36 ++#define EN7523_SFC2_PCM_RST 37 ++#define EN7523_PCIE0_RST 38 ++#define EN7523_PCIE1_RST 39 ++#define EN7523_PCIE_HB_RST 40 ++#define EN7523_XPON_MAC_RST 41 ++ ++#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ */ diff --git a/target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch b/target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch new file mode 100644 index 0000000000..a6594ebac8 --- /dev/null +++ b/target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch @@ -0,0 +1,26 @@ +From 02d3b7557ce28c373ea1e925ae16ab5988284313 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Jan 2025 00:10:03 +0100 +Subject: [PATCH 1/2] dt-bindings: clock: drop NUM_CLOCKS define for EN7581 + +Drop NUM_CLOCKS define for EN7581 include. This is not a binding and +should not be placed here. Value is derived internally in the user +driver. + +Signed-off-by: Christian Marangi +Acked-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20250113231030.6735-3-ansuelsmth@gmail.com +Signed-off-by: Stephen Boyd +--- + include/dt-bindings/clock/en7523-clk.h | 2 -- + 1 file changed, 2 deletions(-) + +--- a/include/dt-bindings/clock/en7523-clk.h ++++ b/include/dt-bindings/clock/en7523-clk.h +@@ -12,6 +12,4 @@ + #define EN7523_CLK_CRYPTO 6 + #define EN7523_CLK_PCIE 7 + +-#define EN7523_NUM_CLOCKS 8 +- + #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ diff --git a/target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch b/target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch new file mode 100644 index 0000000000..f500a79808 --- /dev/null +++ b/target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch @@ -0,0 +1,25 @@ +From 82108ad3285f58f314ad41398f44017c7dbe44de Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Jan 2025 00:10:04 +0100 +Subject: [PATCH 2/2] dt-bindings: clock: add ID for eMMC for EN7581 + +Add ID for eMMC for EN7581. This is to control clock selection of eMMC +between 200MHz and 150MHz. + +Signed-off-by: Christian Marangi +Acked-by: Conor Dooley +Link: https://lore.kernel.org/r/20250113231030.6735-4-ansuelsmth@gmail.com +Signed-off-by: Stephen Boyd +--- + include/dt-bindings/clock/en7523-clk.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/dt-bindings/clock/en7523-clk.h ++++ b/include/dt-bindings/clock/en7523-clk.h +@@ -12,4 +12,6 @@ + #define EN7523_CLK_CRYPTO 6 + #define EN7523_CLK_PCIE 7 + ++#define EN7581_CLK_EMMC 8 ++ + #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ diff --git a/target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch b/target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch new file mode 100644 index 0000000000..c99c25921c --- /dev/null +++ b/target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch @@ -0,0 +1,33 @@ +From 661856ca131c8bf6724905966e02149805660abe Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sun, 12 Oct 2025 15:16:53 +0300 +Subject: [PATCH 05/14] spi: airoha: remove unnecessary restriction length + +The "length < 160" restriction is not needed because airoha_snand_write_data() +and airoha_snand_read_data() will properly handle data transfers above +SPI_MAX_TRANSFER_SIZE. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20251012121707.2296160-3-mikhail.kshevetskiy@iopsys.eu +Signed-off-by: Mark Brown +--- + drivers/spi/spi-airoha-snfi.c | 7 ------- + 1 file changed, 7 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -619,13 +619,6 @@ static int airoha_snand_adjust_op_size(s + + if (op->data.nbytes > max_len) + op->data.nbytes = max_len; +- } else { +- max_len = 1 + op->addr.nbytes + op->dummy.nbytes; +- if (max_len >= 160) +- return -EOPNOTSUPP; +- +- if (op->data.nbytes > 160 - max_len) +- op->data.nbytes = 160 - max_len; + } + + return 0; diff --git a/target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch b/target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch new file mode 100644 index 0000000000..afe496c968 --- /dev/null +++ b/target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch @@ -0,0 +1,30 @@ +From 7350f8dc15bfbb7abf1ce4babea6fcace1c574c5 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sun, 12 Oct 2025 15:16:55 +0300 +Subject: [PATCH 06/14] spi: airoha: remove unnecessary switch to non-dma mode + +The code switches to dma at the start of dirmap operation and returns +to non-dma at the end of dirmap operation, so an additional switch to +non-dma at the start of dirmap write is not required. + +Signed-off-by: Mikhail Kshevetskiy +Acked-by: Lorenzo Bianconi +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20251012121707.2296160-5-mikhail.kshevetskiy@iopsys.eu +Signed-off-by: Mark Brown +--- + drivers/spi/spi-airoha-snfi.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -815,9 +815,6 @@ static ssize_t airoha_snand_dirmap_write + int err; + + as_ctrl = spi_controller_get_devdata(spi->controller); +- err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); +- if (err < 0) +- return err; + + memcpy(txrx_buf + offs, buf, len); + dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE, diff --git a/target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch b/target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch new file mode 100644 index 0000000000..c85c6861fc --- /dev/null +++ b/target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch @@ -0,0 +1,137 @@ +From 233a22687411ea053a4b169c07324ee6aa33bf38 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sun, 12 Oct 2025 15:16:58 +0300 +Subject: [PATCH 07/14] spi: airoha: unify dirmap read/write code + +Makes dirmap writing looks similar to dirmap reading. Just a minor +refactoring, no behavior change is expected. + +Signed-off-by: Mikhail Kshevetskiy +Link: https://patch.msgid.link/20251012121707.2296160-8-mikhail.kshevetskiy@iopsys.eu +Signed-off-by: Mark Brown +--- + drivers/spi/spi-airoha-snfi.c | 50 ++++++++++++++++++++++------------- + 1 file changed, 32 insertions(+), 18 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -672,6 +672,8 @@ static ssize_t airoha_snand_dirmap_read( + u32 val, rd_mode; + int err; + ++ as_ctrl = spi_controller_get_devdata(spi->controller); ++ + switch (op->cmd.opcode) { + case SPI_NAND_OP_READ_FROM_CACHE_DUAL: + rd_mode = 1; +@@ -684,7 +686,6 @@ static ssize_t airoha_snand_dirmap_read( + break; + } + +- as_ctrl = spi_controller_get_devdata(spi->controller); + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); + if (err < 0) + return err; +@@ -748,7 +749,7 @@ static ssize_t airoha_snand_dirmap_read( + if (err) + goto error_dma_unmap; + +- /* trigger dma start read */ ++ /* trigger dma reading */ + err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, + SPI_NFI_RD_TRIG); + if (err) +@@ -806,37 +807,47 @@ error_dma_mode_off: + static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, const void *buf) + { +- struct spi_mem_op *op = &desc->info.op_tmpl; + struct spi_device *spi = desc->mem->spi; + u8 *txrx_buf = spi_get_ctldata(spi); + struct airoha_snand_ctrl *as_ctrl; + dma_addr_t dma_addr; +- u32 wr_mode, val; ++ u32 wr_mode, val, opcode; + int err; + + as_ctrl = spi_controller_get_devdata(spi->controller); + ++ opcode = desc->info.op_tmpl.cmd.opcode; ++ switch (opcode) { ++ case SPI_NAND_OP_PROGRAM_LOAD_SINGLE: ++ case SPI_NAND_OP_PROGRAM_LOAD_RAMDOM_SINGLE: ++ wr_mode = 0; ++ break; ++ case SPI_NAND_OP_PROGRAM_LOAD_QUAD: ++ case SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD: ++ wr_mode = 2; ++ break; ++ default: ++ /* unknown opcode */ ++ return -EOPNOTSUPP; ++ } ++ + memcpy(txrx_buf + offs, buf, len); +- dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE, +- DMA_TO_DEVICE); +- err = dma_mapping_error(as_ctrl->dev, dma_addr); +- if (err) +- return err; + + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); + if (err < 0) +- goto error_dma_unmap; ++ return err; + + err = airoha_snand_nfi_config(as_ctrl); + if (err) +- goto error_dma_unmap; ++ goto error_dma_mode_off; + +- if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD || +- op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD) +- wr_mode = BIT(1); +- else +- wr_mode = 0; ++ dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE, ++ DMA_TO_DEVICE); ++ err = dma_mapping_error(as_ctrl->dev, dma_addr); ++ if (err) ++ goto error_dma_mode_off; + ++ /* set dma addr */ + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR, + dma_addr); + if (err) +@@ -850,12 +861,13 @@ static ssize_t airoha_snand_dirmap_write + if (err) + goto error_dma_unmap; + ++ /* set write command */ + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1, +- FIELD_PREP(SPI_NFI_PG_LOAD_CMD, +- op->cmd.opcode)); ++ FIELD_PREP(SPI_NFI_PG_LOAD_CMD, opcode)); + if (err) + goto error_dma_unmap; + ++ /* set write mode */ + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL, + FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode)); + if (err) +@@ -887,6 +899,7 @@ static ssize_t airoha_snand_dirmap_write + if (err) + goto error_dma_unmap; + ++ /* trigger dma writing */ + err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, + SPI_NFI_WR_TRIG); + if (err) +@@ -931,6 +944,7 @@ static ssize_t airoha_snand_dirmap_write + error_dma_unmap: + dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE, + DMA_TO_DEVICE); ++error_dma_mode_off: + airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); + return err; + } diff --git a/target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch b/target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch new file mode 100644 index 0000000000..7e3fcb4764 --- /dev/null +++ b/target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch @@ -0,0 +1,94 @@ +From 80b09137aeab27e59004383058f8cc696a9ee048 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sun, 12 Oct 2025 15:16:59 +0300 +Subject: [PATCH 08/14] spi: airoha: support of dualio/quadio flash reading + commands + +Airoha snfi spi controller supports acceleration of DUAL/QUAD +operations, but does not supports DUAL_IO/QUAD_IO operations. +Luckily DUAL/QUAD operations do the same as DUAL_IO/QUAD_IO ones, +so we can issue corresponding DUAL/QUAD operation instead of +DUAL_IO/QUAD_IO one. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20251012121707.2296160-9-mikhail.kshevetskiy@iopsys.eu +Signed-off-by: Mark Brown +--- + drivers/spi/spi-airoha-snfi.c | 28 ++++++++++++++++++++++------ + 1 file changed, 22 insertions(+), 6 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -147,6 +147,8 @@ + #define SPI_NFI_CUS_SEC_SIZE_EN BIT(16) + + #define REG_SPI_NFI_RD_CTL2 0x0510 ++#define SPI_NFI_DATA_READ_CMD GENMASK(7, 0) ++ + #define REG_SPI_NFI_RD_CTL3 0x0514 + + #define REG_SPI_NFI_PG_CTL1 0x0524 +@@ -179,7 +181,9 @@ + #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE 0x03 + #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST 0x0b + #define SPI_NAND_OP_READ_FROM_CACHE_DUAL 0x3b ++#define SPI_NAND_OP_READ_FROM_CACHE_DUALIO 0xbb + #define SPI_NAND_OP_READ_FROM_CACHE_QUAD 0x6b ++#define SPI_NAND_OP_READ_FROM_CACHE_QUADIO 0xeb + #define SPI_NAND_OP_WRITE_ENABLE 0x06 + #define SPI_NAND_OP_WRITE_DISABLE 0x04 + #define SPI_NAND_OP_PROGRAM_LOAD_SINGLE 0x02 +@@ -664,26 +668,38 @@ static int airoha_snand_dirmap_create(st + static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, void *buf) + { +- struct spi_mem_op *op = &desc->info.op_tmpl; + struct spi_device *spi = desc->mem->spi; + struct airoha_snand_ctrl *as_ctrl; + u8 *txrx_buf = spi_get_ctldata(spi); + dma_addr_t dma_addr; +- u32 val, rd_mode; ++ u32 val, rd_mode, opcode; + int err; + + as_ctrl = spi_controller_get_devdata(spi->controller); + +- switch (op->cmd.opcode) { ++ /* ++ * DUALIO and QUADIO opcodes are not supported by the spi controller, ++ * replace them with supported opcodes. ++ */ ++ opcode = desc->info.op_tmpl.cmd.opcode; ++ switch (opcode) { ++ case SPI_NAND_OP_READ_FROM_CACHE_SINGLE: ++ case SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST: ++ rd_mode = 0; ++ break; + case SPI_NAND_OP_READ_FROM_CACHE_DUAL: ++ case SPI_NAND_OP_READ_FROM_CACHE_DUALIO: ++ opcode = SPI_NAND_OP_READ_FROM_CACHE_DUAL; + rd_mode = 1; + break; + case SPI_NAND_OP_READ_FROM_CACHE_QUAD: ++ case SPI_NAND_OP_READ_FROM_CACHE_QUADIO: ++ opcode = SPI_NAND_OP_READ_FROM_CACHE_QUAD; + rd_mode = 2; + break; + default: +- rd_mode = 0; +- break; ++ /* unknown opcode */ ++ return -EOPNOTSUPP; + } + + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); +@@ -717,7 +733,7 @@ static ssize_t airoha_snand_dirmap_read( + + /* set read command */ + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2, +- op->cmd.opcode); ++ FIELD_PREP(SPI_NFI_DATA_READ_CMD, opcode)); + if (err) + goto error_dma_unmap; + diff --git a/target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch b/target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch new file mode 100644 index 0000000000..f8902f7e57 --- /dev/null +++ b/target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch @@ -0,0 +1,64 @@ +From 70eec454f2d6cdfab547c262781acd38328e11a1 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sun, 12 Oct 2025 15:17:00 +0300 +Subject: [PATCH 09/14] spi: airoha: avoid setting of page/oob sizes in + REG_SPI_NFI_PAGEFMT + +spi-airoha-snfi uses custom sector size in REG_SPI_NFI_SECCUS_SIZE +register, so setting of page/oob sizes in REG_SPI_NFI_PAGEFMT is not +required. + +Signed-off-by: Mikhail Kshevetskiy +Link: https://patch.msgid.link/20251012121707.2296160-10-mikhail.kshevetskiy@iopsys.eu +Signed-off-by: Mark Brown +--- + drivers/spi/spi-airoha-snfi.c | 38 ----------------------------------- + 1 file changed, 38 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -518,44 +518,6 @@ static int airoha_snand_nfi_config(struc + if (err) + return err; + +- /* page format */ +- switch (as_ctrl->nfi_cfg.spare_size) { +- case 26: +- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x1); +- break; +- case 27: +- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x2); +- break; +- case 28: +- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x3); +- break; +- default: +- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x0); +- break; +- } +- +- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT, +- SPI_NFI_SPARE_SIZE, val); +- if (err) +- return err; +- +- switch (as_ctrl->nfi_cfg.page_size) { +- case 2048: +- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x1); +- break; +- case 4096: +- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x2); +- break; +- default: +- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x0); +- break; +- } +- +- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT, +- SPI_NFI_PAGE_SIZE, val); +- if (err) +- return err; +- + /* sec num */ + val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, diff --git a/target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch b/target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch new file mode 100644 index 0000000000..40e2f6ea21 --- /dev/null +++ b/target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch @@ -0,0 +1,199 @@ +From d1ff30df1d9a4eb4c067795abb5e2a66910fd108 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sun, 12 Oct 2025 15:17:01 +0300 +Subject: [PATCH 10/14] spi: airoha: reduce the number of modification of + REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers + +This just reduce the number of modification of REG_SPI_NFI_CNFG and +REG_SPI_NFI_SECCUS_SIZE registers during dirmap operation. + +This patch is a necessary step to avoid reading flash page settings +from SNFI registers during driver startup. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20251012121707.2296160-11-mikhail.kshevetskiy@iopsys.eu +Signed-off-by: Mark Brown +--- + drivers/spi/spi-airoha-snfi.c | 135 +++++++++++++++++++++++++--------- + 1 file changed, 102 insertions(+), 33 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -668,7 +668,48 @@ static ssize_t airoha_snand_dirmap_read( + if (err < 0) + return err; + +- err = airoha_snand_nfi_config(as_ctrl); ++ /* NFI reset */ ++ err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, ++ SPI_NFI_FIFO_FLUSH | SPI_NFI_RST); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* NFI configure: ++ * - No AutoFDM (custom sector size (SECCUS) register will be used) ++ * - No SoC's hardware ECC (flash internal ECC will be used) ++ * - Use burst mode (faster, but requires 16 byte alignment for addresses) ++ * - Setup for reading (SPI_NFI_READ_MODE) ++ * - Setup reading command: FIELD_PREP(SPI_NFI_OPMODE, 6) ++ * - Use DMA instead of PIO for data reading ++ */ ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, ++ SPI_NFI_DMA_MODE | ++ SPI_NFI_READ_MODE | ++ SPI_NFI_DMA_BURST_EN | ++ SPI_NFI_HW_ECC_EN | ++ SPI_NFI_AUTO_FDM_EN | ++ SPI_NFI_OPMODE, ++ SPI_NFI_DMA_MODE | ++ SPI_NFI_READ_MODE | ++ SPI_NFI_DMA_BURST_EN | ++ FIELD_PREP(SPI_NFI_OPMODE, 6)); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* Set number of sector will be read */ ++ val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, ++ SPI_NFI_SEC_NUM, val); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* Set custom sector size */ ++ val = as_ctrl->nfi_cfg.sec_size; ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, ++ SPI_NFI_CUS_SEC_SIZE | ++ SPI_NFI_CUS_SEC_SIZE_EN, ++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | ++ SPI_NFI_CUS_SEC_SIZE_EN); + if (err) + goto error_dma_mode_off; + +@@ -684,7 +725,14 @@ static ssize_t airoha_snand_dirmap_read( + if (err) + goto error_dma_unmap; + +- /* set cust sec size */ ++ /* ++ * Setup transfer length ++ * --------------------- ++ * The following rule MUST be met: ++ * transfer_length = ++ * = NFI_SNF_MISC_CTL2.read_data_byte_number = ++ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size ++ */ + val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; + val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val); + err = regmap_update_bits(as_ctrl->regmap_nfi, +@@ -711,18 +759,6 @@ static ssize_t airoha_snand_dirmap_read( + if (err) + goto error_dma_unmap; + +- /* set nfi read */ +- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_OPMODE, +- FIELD_PREP(SPI_NFI_OPMODE, 6)); +- if (err) +- goto error_dma_unmap; +- +- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE); +- if (err) +- goto error_dma_unmap; +- + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0); + if (err) + goto error_dma_unmap; +@@ -815,7 +851,48 @@ static ssize_t airoha_snand_dirmap_write + if (err < 0) + return err; + +- err = airoha_snand_nfi_config(as_ctrl); ++ /* NFI reset */ ++ err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, ++ SPI_NFI_FIFO_FLUSH | SPI_NFI_RST); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* ++ * NFI configure: ++ * - No AutoFDM (custom sector size (SECCUS) register will be used) ++ * - No SoC's hardware ECC (flash internal ECC will be used) ++ * - Use burst mode (faster, but requires 16 byte alignment for addresses) ++ * - Setup for writing (SPI_NFI_READ_MODE bit is cleared) ++ * - Setup writing command: FIELD_PREP(SPI_NFI_OPMODE, 3) ++ * - Use DMA instead of PIO for data writing ++ */ ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, ++ SPI_NFI_DMA_MODE | ++ SPI_NFI_READ_MODE | ++ SPI_NFI_DMA_BURST_EN | ++ SPI_NFI_HW_ECC_EN | ++ SPI_NFI_AUTO_FDM_EN | ++ SPI_NFI_OPMODE, ++ SPI_NFI_DMA_MODE | ++ SPI_NFI_DMA_BURST_EN | ++ FIELD_PREP(SPI_NFI_OPMODE, 3)); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* Set number of sector will be written */ ++ val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, ++ SPI_NFI_SEC_NUM, val); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* Set custom sector size */ ++ val = as_ctrl->nfi_cfg.sec_size; ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, ++ SPI_NFI_CUS_SEC_SIZE | ++ SPI_NFI_CUS_SEC_SIZE_EN, ++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | ++ SPI_NFI_CUS_SEC_SIZE_EN); + if (err) + goto error_dma_mode_off; + +@@ -831,8 +908,16 @@ static ssize_t airoha_snand_dirmap_write + if (err) + goto error_dma_unmap; + +- val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, +- as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num); ++ /* ++ * Setup transfer length ++ * --------------------- ++ * The following rule MUST be met: ++ * transfer_length = ++ * = NFI_SNF_MISC_CTL2.write_data_byte_number = ++ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size ++ */ ++ val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; ++ val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val); + err = regmap_update_bits(as_ctrl->regmap_nfi, + REG_SPI_NFI_SNF_MISC_CTL2, + SPI_NFI_PROG_LOAD_BYTE_NUM, val); +@@ -857,22 +942,6 @@ static ssize_t airoha_snand_dirmap_write + if (err) + goto error_dma_unmap; + +- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_READ_MODE); +- if (err) +- goto error_dma_unmap; +- +- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_OPMODE, +- FIELD_PREP(SPI_NFI_OPMODE, 3)); +- if (err) +- goto error_dma_unmap; +- +- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_DMA_MODE); +- if (err) +- goto error_dma_unmap; +- + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80); + if (err) + goto error_dma_unmap; diff --git a/target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch b/target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch new file mode 100644 index 0000000000..514212835c --- /dev/null +++ b/target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch @@ -0,0 +1,142 @@ +From fb81b5cecb8553e3ca2b45288cf340d43c9c2991 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sun, 12 Oct 2025 15:17:02 +0300 +Subject: [PATCH 11/14] spi: airoha: set custom sector size equal to flash page + size + +Set custom sector size equal to flash page size including oob. Thus we +will always read a single sector. The maximum custom sector size is +8187, so all possible flash sector sizes are supported. + +This patch is a necessary step to avoid reading flash page settings +from SNFI registers during driver startup. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20251012121707.2296160-12-mikhail.kshevetskiy@iopsys.eu +Signed-off-by: Mark Brown +--- + drivers/spi/spi-airoha-snfi.c | 35 +++++++++++++++++++---------------- + 1 file changed, 19 insertions(+), 16 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -519,7 +519,7 @@ static int airoha_snand_nfi_config(struc + return err; + + /* sec num */ +- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); ++ val = FIELD_PREP(SPI_NFI_SEC_NUM, 1); + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, + SPI_NFI_SEC_NUM, val); + if (err) +@@ -532,7 +532,8 @@ static int airoha_snand_nfi_config(struc + return err; + + /* set cust sec size */ +- val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, as_ctrl->nfi_cfg.sec_size); ++ val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, ++ as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num); + return regmap_update_bits(as_ctrl->regmap_nfi, + REG_SPI_NFI_SECCUS_SIZE, + SPI_NFI_CUS_SEC_SIZE, val); +@@ -635,10 +636,13 @@ static ssize_t airoha_snand_dirmap_read( + u8 *txrx_buf = spi_get_ctldata(spi); + dma_addr_t dma_addr; + u32 val, rd_mode, opcode; ++ size_t bytes; + int err; + + as_ctrl = spi_controller_get_devdata(spi->controller); + ++ bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; ++ + /* + * DUALIO and QUADIO opcodes are not supported by the spi controller, + * replace them with supported opcodes. +@@ -697,18 +701,17 @@ static ssize_t airoha_snand_dirmap_read( + goto error_dma_mode_off; + + /* Set number of sector will be read */ +- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, +- SPI_NFI_SEC_NUM, val); ++ SPI_NFI_SEC_NUM, ++ FIELD_PREP(SPI_NFI_SEC_NUM, 1)); + if (err) + goto error_dma_mode_off; + + /* Set custom sector size */ +- val = as_ctrl->nfi_cfg.sec_size; + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, + SPI_NFI_CUS_SEC_SIZE | + SPI_NFI_CUS_SEC_SIZE_EN, +- FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | ++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) | + SPI_NFI_CUS_SEC_SIZE_EN); + if (err) + goto error_dma_mode_off; +@@ -733,11 +736,10 @@ static ssize_t airoha_snand_dirmap_read( + * = NFI_SNF_MISC_CTL2.read_data_byte_number = + * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size + */ +- val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; +- val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val); + err = regmap_update_bits(as_ctrl->regmap_nfi, + REG_SPI_NFI_SNF_MISC_CTL2, +- SPI_NFI_READ_DATA_BYTE_NUM, val); ++ SPI_NFI_READ_DATA_BYTE_NUM, ++ FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, bytes)); + if (err) + goto error_dma_unmap; + +@@ -826,10 +828,13 @@ static ssize_t airoha_snand_dirmap_write + struct airoha_snand_ctrl *as_ctrl; + dma_addr_t dma_addr; + u32 wr_mode, val, opcode; ++ size_t bytes; + int err; + + as_ctrl = spi_controller_get_devdata(spi->controller); + ++ bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; ++ + opcode = desc->info.op_tmpl.cmd.opcode; + switch (opcode) { + case SPI_NAND_OP_PROGRAM_LOAD_SINGLE: +@@ -880,18 +885,17 @@ static ssize_t airoha_snand_dirmap_write + goto error_dma_mode_off; + + /* Set number of sector will be written */ +- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, +- SPI_NFI_SEC_NUM, val); ++ SPI_NFI_SEC_NUM, ++ FIELD_PREP(SPI_NFI_SEC_NUM, 1)); + if (err) + goto error_dma_mode_off; + + /* Set custom sector size */ +- val = as_ctrl->nfi_cfg.sec_size; + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, + SPI_NFI_CUS_SEC_SIZE | + SPI_NFI_CUS_SEC_SIZE_EN, +- FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | ++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) | + SPI_NFI_CUS_SEC_SIZE_EN); + if (err) + goto error_dma_mode_off; +@@ -916,11 +920,10 @@ static ssize_t airoha_snand_dirmap_write + * = NFI_SNF_MISC_CTL2.write_data_byte_number = + * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size + */ +- val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; +- val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val); + err = regmap_update_bits(as_ctrl->regmap_nfi, + REG_SPI_NFI_SNF_MISC_CTL2, +- SPI_NFI_PROG_LOAD_BYTE_NUM, val); ++ SPI_NFI_PROG_LOAD_BYTE_NUM, ++ FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, bytes)); + if (err) + goto error_dma_unmap; + diff --git a/target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch b/target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch new file mode 100644 index 0000000000..00fd100bc3 --- /dev/null +++ b/target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch @@ -0,0 +1,206 @@ +From 902c0ea18a97b1a6eeee5799cb1fd9a79ef9208e Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sun, 12 Oct 2025 15:17:03 +0300 +Subject: [PATCH 12/14] spi: airoha: avoid reading flash page settings from + SNFI registers during driver startup + +The spinand driver do 3 type of dirmap requests: + * read/write whole flash page without oob + (offs = 0, len = page_size) + * read/write whole flash page including oob + (offs = 0, len = page_size + oob_size) + * read/write oob area only + (offs = page_size, len = oob_size) + +The trick is: + * read/write a single "sector" + * set a custom sector size equal to offs + len. It's a bit safer to + rounded up "sector size" value 64. + * set the transfer length equal to custom sector size + +And it works! + +Thus we can remove a dirty hack that reads flash page settings from +SNFI registers during driver startup. Also airoha_snand_adjust_op_size() +function becomes unnecessary. + +Signed-off-by: Mikhail Kshevetskiy +Link: https://patch.msgid.link/20251012121707.2296160-13-mikhail.kshevetskiy@iopsys.eu +Signed-off-by: Mark Brown +--- + drivers/spi/spi-airoha-snfi.c | 115 ++-------------------------------- + 1 file changed, 5 insertions(+), 110 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -223,13 +223,6 @@ struct airoha_snand_ctrl { + struct regmap *regmap_ctrl; + struct regmap *regmap_nfi; + struct clk *spi_clk; +- +- struct { +- size_t page_size; +- size_t sec_size; +- u8 sec_num; +- u8 spare_size; +- } nfi_cfg; + }; + + static int airoha_snand_set_fifo_op(struct airoha_snand_ctrl *as_ctrl, +@@ -490,55 +483,6 @@ static int airoha_snand_nfi_init(struct + SPI_NFI_ALL_IRQ_EN, SPI_NFI_AHB_DONE_EN); + } + +-static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl) +-{ +- int err; +- u32 val; +- +- err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, +- SPI_NFI_FIFO_FLUSH | SPI_NFI_RST); +- if (err) +- return err; +- +- /* auto FDM */ +- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_AUTO_FDM_EN); +- if (err) +- return err; +- +- /* HW ECC */ +- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_HW_ECC_EN); +- if (err) +- return err; +- +- /* DMA Burst */ +- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_DMA_BURST_EN); +- if (err) +- return err; +- +- /* sec num */ +- val = FIELD_PREP(SPI_NFI_SEC_NUM, 1); +- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, +- SPI_NFI_SEC_NUM, val); +- if (err) +- return err; +- +- /* enable cust sec size */ +- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, +- SPI_NFI_CUS_SEC_SIZE_EN); +- if (err) +- return err; +- +- /* set cust sec size */ +- val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, +- as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num); +- return regmap_update_bits(as_ctrl->regmap_nfi, +- REG_SPI_NFI_SECCUS_SIZE, +- SPI_NFI_CUS_SEC_SIZE, val); +-} +- + static bool airoha_snand_is_page_ops(const struct spi_mem_op *op) + { + if (op->addr.nbytes != 2) +@@ -571,26 +515,6 @@ static bool airoha_snand_is_page_ops(con + } + } + +-static int airoha_snand_adjust_op_size(struct spi_mem *mem, +- struct spi_mem_op *op) +-{ +- size_t max_len; +- +- if (airoha_snand_is_page_ops(op)) { +- struct airoha_snand_ctrl *as_ctrl; +- +- as_ctrl = spi_controller_get_devdata(mem->spi->controller); +- max_len = as_ctrl->nfi_cfg.sec_size; +- max_len += as_ctrl->nfi_cfg.spare_size; +- max_len *= as_ctrl->nfi_cfg.sec_num; +- +- if (op->data.nbytes > max_len) +- op->data.nbytes = max_len; +- } +- +- return 0; +-} +- + static bool airoha_snand_supports_op(struct spi_mem *mem, + const struct spi_mem_op *op) + { +@@ -641,7 +565,8 @@ static ssize_t airoha_snand_dirmap_read( + + as_ctrl = spi_controller_get_devdata(spi->controller); + +- bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; ++ /* minimum oob size is 64 */ ++ bytes = round_up(offs + len, 64); + + /* + * DUALIO and QUADIO opcodes are not supported by the spi controller, +@@ -833,7 +758,8 @@ static ssize_t airoha_snand_dirmap_write + + as_ctrl = spi_controller_get_devdata(spi->controller); + +- bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; ++ /* minimum oob size is 64 */ ++ bytes = round_up(offs + len, 64); + + opcode = desc->info.op_tmpl.cmd.opcode; + switch (opcode) { +@@ -1076,7 +1002,6 @@ static int airoha_snand_exec_op(struct s + } + + static const struct spi_controller_mem_ops airoha_snand_mem_ops = { +- .adjust_op_size = airoha_snand_adjust_op_size, + .supports_op = airoha_snand_supports_op, + .exec_op = airoha_snand_exec_op, + .dirmap_create = airoha_snand_dirmap_create, +@@ -1106,36 +1031,6 @@ static int airoha_snand_setup(struct spi + return 0; + } + +-static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl) +-{ +- u32 val, sec_size, sec_num; +- int err; +- +- err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, &val); +- if (err) +- return err; +- +- sec_num = FIELD_GET(SPI_NFI_SEC_NUM, val); +- +- err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, &val); +- if (err) +- return err; +- +- sec_size = FIELD_GET(SPI_NFI_CUS_SEC_SIZE, val); +- +- /* init default value */ +- as_ctrl->nfi_cfg.sec_size = sec_size; +- as_ctrl->nfi_cfg.sec_num = sec_num; +- as_ctrl->nfi_cfg.page_size = round_down(sec_size * sec_num, 1024); +- as_ctrl->nfi_cfg.spare_size = 16; +- +- err = airoha_snand_nfi_init(as_ctrl); +- if (err) +- return err; +- +- return airoha_snand_nfi_config(as_ctrl); +-} +- + static const struct regmap_config spi_ctrl_regmap_config = { + .name = "ctrl", + .reg_bits = 32, +@@ -1227,7 +1122,7 @@ static int airoha_snand_probe(struct pla + ctrl->setup = airoha_snand_setup; + device_set_node(&ctrl->dev, dev_fwnode(dev)); + +- err = airoha_snand_nfi_setup(as_ctrl); ++ err = airoha_snand_nfi_init(as_ctrl); + if (err) + return err; + diff --git a/target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch b/target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch new file mode 100644 index 0000000000..669f9b2dd4 --- /dev/null +++ b/target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch @@ -0,0 +1,32 @@ +From 0743acf746a81e0460a56fd5ff847d97fa7eb370 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sun, 12 Oct 2025 15:17:04 +0300 +Subject: [PATCH 13/14] spi: airoha: buffer must be 0xff-ed before writing + +During writing, the entire flash page (including OOB) will be updated +with the values from the temporary buffer, so we need to fill the +untouched areas of the buffer with 0xff value to prevent accidental +data overwriting. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patch.msgid.link/20251012121707.2296160-14-mikhail.kshevetskiy@iopsys.eu +Signed-off-by: Mark Brown +--- + drivers/spi/spi-airoha-snfi.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -776,7 +776,11 @@ static ssize_t airoha_snand_dirmap_write + return -EOPNOTSUPP; + } + ++ if (offs > 0) ++ memset(txrx_buf, 0xff, offs); + memcpy(txrx_buf + offs, buf, len); ++ if (bytes > offs + len) ++ memset(txrx_buf + offs + len, 0xff, bytes - offs - len); + + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); + if (err < 0) diff --git a/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch b/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch new file mode 100644 index 0000000000..f11c6d329d --- /dev/null +++ b/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch @@ -0,0 +1,119 @@ +From: Ahmed Naseef +Subject: mips: econet: add EN7528 SoC support + +The EN7528 is a little endian dual-core MIPS 1004Kc SoC used in xPON +devices. Unlike the big endian EN751221, EN7528 uses the MIPS GIC +interrupt controller for SMP. + +This adds boot support for the EN7528 SoC family: +- New SOC_ECONET_EN7528 Kconfig option +- Little endian support for ECONET platform +- UART base address adjustment for endianness +- CPS SMP ops registration for multi-core support + +Signed-off-by: Ahmed Naseef +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -391,13 +391,13 @@ config MACH_DECSTATION + config ECONET + bool "EcoNet MIPS family" + select BOOT_RAW +- select CPU_BIG_ENDIAN + select DEBUG_ZBOOT if DEBUG_KERNEL + select EARLY_PRINTK_8250 + select ECONET_EN751221_TIMER + select SERIAL_8250 + select SERIAL_OF_PLATFORM + select SYS_SUPPORTS_BIG_ENDIAN ++ select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_MIPS32_R2 + select SYS_HAS_EARLY_PRINTK +--- a/arch/mips/econet/Kconfig ++++ b/arch/mips/econet/Kconfig +@@ -12,6 +12,7 @@ choice + config SOC_ECONET_EN751221 + bool "EN751221 family" + select COMMON_CLK ++ select CPU_BIG_ENDIAN + select ECONET_EN751221_INTC + select IRQ_MIPS_CPU + select SMP +@@ -22,6 +23,23 @@ choice + They are based on single core MIPS 34Kc processors. To boot + this kernel, you will need a device tree such as + MIPS_RAW_APPENDED_DTB=y, and a root filesystem. ++ ++ config SOC_ECONET_EN7528 ++ bool "EN7528 family" ++ select COMMON_CLK ++ select CPU_LITTLE_ENDIAN ++ select IRQ_MIPS_CPU ++ select MIPS_CPU_SCACHE ++ select MIPS_GIC ++ select SMP ++ select SMP_UP ++ select SYS_SUPPORTS_HIGHMEM ++ select SYS_SUPPORTS_MIPS_CPS ++ select SYS_SUPPORTS_MULTITHREADING ++ select SYS_SUPPORTS_SMP ++ help ++ The EN7528 family with dual-core MIPS 1004Kc. ++ Requires MIPS_RAW_APPENDED_DTB=y for boot. + endchoice + + choice +--- a/arch/mips/econet/init.c ++++ b/arch/mips/econet/init.c +@@ -16,11 +16,16 @@ + #include + #include + #include ++#include + + #define CR_AHB_RSTCR ((void __iomem *)CKSEG1ADDR(0x1fb00040)) + #define RESET BIT(31) + +-#define UART_BASE CKSEG1ADDR(0x1fbf0003) ++#ifdef CONFIG_CPU_LITTLE_ENDIAN ++#define UART_BASE CKSEG1ADDR(0x1fbf0000) /* LE: byte at offset 0 */ ++#else ++#define UART_BASE CKSEG1ADDR(0x1fbf0003) /* BE: byte at offset 3 */ ++#endif + #define UART_REG_SHIFT 2 + + static void hw_reset(char *command) +@@ -51,11 +56,18 @@ void __init plat_mem_setup(void) + early_init_dt_scan_memory(); + } + +-/* 3. Overload __weak device_tree_init(), add SMP_UP ops */ ++/* 3. Overload __weak device_tree_init(), register SMP ops */ + void __init device_tree_init(void) + { + unflatten_and_copy_device_tree(); + ++ /* EN7528 dual-core: probe CM/CPC and register CPS SMP ops */ ++ mips_cm_probe(); ++ mips_cpc_probe(); ++ ++ if (!register_cps_smp_ops()) ++ return; ++ + register_up_smp_ops(); + } + +--- a/arch/mips/boot/compressed/uart-16550.c ++++ b/arch/mips/boot/compressed/uart-16550.c +@@ -21,7 +21,11 @@ + #endif + + #ifdef CONFIG_ECONET ++#ifdef CONFIG_CPU_LITTLE_ENDIAN ++#define EN75_UART_BASE 0x1fbf0000 ++#else + #define EN75_UART_BASE 0x1fbf0003 ++#endif + #define PORT(offset) (CKSEG1ADDR(EN75_UART_BASE) + (4 * (offset))) + #endif + diff --git a/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch b/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch new file mode 100644 index 0000000000..3d86414591 --- /dev/null +++ b/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch @@ -0,0 +1,264 @@ +From: Ahmed Naseef +Subject: mips: econet: timer: add EN7528 support to EN751221 timer driver + +Extend the existing EN751221 timer driver to support EN7528/EN751627 SoCs. +The driver now auto-detects the IRQ mode based on device tree: +- EN751221: Single percpu IRQ (legacy interrupt controller) +- EN7528/EN751627: Separate IRQ per CPU (GIC shared interrupts) + +Signed-off-by: Ahmed Naseef +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -79,7 +79,10 @@ config ECONET_EN751221_TIMER + select CLKSRC_MMIO + select TIMER_OF + help +- Support for CPU timer found on EcoNet MIPS based SoCs. ++ Support for CPU timer found on EcoNet EN75xx MIPS based SoCs ++ (EN751221, EN751627, EN7528). The driver supports both GIC-based ++ (separate IRQ per CPU) and legacy interrupt controller (percpu IRQ) ++ modes. + + config FTTMR010_TIMER + bool "Faraday Technology timer driver" if COMPILE_TEST +--- a/drivers/clocksource/timer-econet-en751221.c ++++ b/drivers/clocksource/timer-econet-en751221.c +@@ -2,12 +2,20 @@ + /* + * Timer present on EcoNet EN75xx MIPS based SoCs. + * ++ * This driver supports both: ++ * - EN751221: Single percpu IRQ mode (legacy interrupt controller) ++ * - EN7528/EN751627: Separate IRQ per CPU mode (GIC shared interrupts) ++ * ++ * The mode is auto-detected based on IRQ count in device tree. ++ * + * Copyright (C) 2025 by Caleb James DeLisle ++ * Copyright (C) 2025 by Ahmed Naseef + */ + + #include + #include + #include ++#include + #include + #include + #include +@@ -21,10 +29,14 @@ + #define ECONET_MAX_DELTA GENMASK(ECONET_BITS - 2, 0) + /* 34Kc hardware has 1 block and 1004Kc has 2. */ + #define ECONET_NUM_BLOCKS DIV_ROUND_UP(NR_CPUS, 2) ++#define ECONET_MAX_IRQS 4 + + static struct { + void __iomem *membase[ECONET_NUM_BLOCKS]; + u32 freq_hz; ++ int irqs[ECONET_MAX_IRQS]; ++ int num_irqs; ++ bool use_percpu_irq; + } econet_timer __ro_after_init; + + static DEFINE_PER_CPU(struct clock_event_device, econet_timer_pcpu); +@@ -98,12 +110,21 @@ static int cevt_init_cpu(uint cpu) + struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, cpu); + u32 reg; + ++ if (!econet_timer.use_percpu_irq && cpu >= econet_timer.num_irqs) ++ return -EINVAL; ++ + pr_debug("%s: Setting up clockevent for CPU %d\n", cd->name, cpu); + + reg = ioread32(reg_ctl(cpu)) | ctl_bit_enabled(cpu); + iowrite32(reg, reg_ctl(cpu)); + +- enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); ++ if (econet_timer.use_percpu_irq) { ++ enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); ++ } else { ++ if (irq_force_affinity(econet_timer.irqs[cpu], cpumask_of(cpu))) ++ pr_warn("%s: failed to set IRQ %d affinity to CPU %d\n", ++ cd->name, econet_timer.irqs[cpu], cpu); ++ } + + /* Do this last because it synchronously configures the timer */ + clockevents_config_and_register(cd, econet_timer.freq_hz, +@@ -126,7 +147,21 @@ static void __init cevt_dev_init(uint cp + iowrite32(U32_MAX, reg_compare(cpu)); + } + +-static int __init cevt_init(struct device_node *np) ++static void __init cevt_setup_clockevent(struct clock_event_device *cd, ++ struct device_node *np, ++ int irq, int cpu) ++{ ++ cd->rating = 310; ++ cd->features = CLOCK_EVT_FEAT_ONESHOT | ++ CLOCK_EVT_FEAT_C3STOP | ++ CLOCK_EVT_FEAT_PERCPU; ++ cd->set_next_event = cevt_set_next_event; ++ cd->irq = irq; ++ cd->cpumask = cpumask_of(cpu); ++ cd->name = np->name; ++} ++ ++static int __init cevt_init_percpu(struct device_node *np) + { + int i, irq, ret; + +@@ -137,42 +172,85 @@ static int __init cevt_init(struct devic + } + + ret = request_percpu_irq(irq, cevt_interrupt, np->name, &econet_timer_pcpu); +- + if (ret < 0) { + pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, irq, ret); +- goto err_unmap_irq; ++ irq_dispose_mapping(irq); ++ return ret; + } + + for_each_possible_cpu(i) { + struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i); + +- cd->rating = 310, +- cd->features = CLOCK_EVT_FEAT_ONESHOT | +- CLOCK_EVT_FEAT_C3STOP | +- CLOCK_EVT_FEAT_PERCPU; +- cd->set_next_event = cevt_set_next_event; +- cd->irq = irq; +- cd->cpumask = cpumask_of(i); +- cd->name = np->name; ++ cevt_setup_clockevent(cd, np, irq, i); ++ cevt_dev_init(i); ++ } ++ ++ return 0; ++} ++ ++static int __init cevt_init_separate(struct device_node *np) ++{ ++ int i, ret; ++ ++ for (i = 0; i < econet_timer.num_irqs; i++) { ++ struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i); ++ ++ econet_timer.irqs[i] = irq_of_parse_and_map(np, i); ++ if (econet_timer.irqs[i] <= 0) { ++ pr_err("%pOFn: irq_of_parse_and_map failed", np); ++ ret = -EINVAL; ++ goto err_free_irqs; ++ } ++ ++ ret = request_irq(econet_timer.irqs[i], cevt_interrupt, ++ IRQF_TIMER | IRQF_NOBALANCING, ++ np->name, NULL); ++ if (ret < 0) { ++ pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, ++ econet_timer.irqs[i], ret); ++ irq_dispose_mapping(econet_timer.irqs[i]); ++ goto err_free_irqs; ++ } + ++ cevt_setup_clockevent(cd, np, econet_timer.irqs[i], i); + cevt_dev_init(i); + } + +- cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, +- "clockevents/econet/timer:starting", +- cevt_init_cpu, NULL); + return 0; + +-err_unmap_irq: +- irq_dispose_mapping(irq); ++err_free_irqs: ++ while (--i >= 0) { ++ free_irq(econet_timer.irqs[i], NULL); ++ irq_dispose_mapping(econet_timer.irqs[i]); ++ } + return ret; + } + ++static int __init cevt_init(struct device_node *np) ++{ ++ econet_timer.num_irqs = of_irq_count(np); ++ if (econet_timer.num_irqs <= 0 || econet_timer.num_irqs > ECONET_MAX_IRQS) { ++ pr_err("%pOFn: invalid IRQ count %d\n", np, econet_timer.num_irqs); ++ return -EINVAL; ++ } ++ ++ /* Auto-detect mode based on IRQ count: ++ * 1 IRQ = percpu mode (EN751221) ++ * N IRQs = separate IRQ per CPU (EN7528/EN751627) ++ */ ++ econet_timer.use_percpu_irq = (econet_timer.num_irqs == 1); ++ ++ if (econet_timer.use_percpu_irq) ++ return cevt_init_percpu(np); ++ else ++ return cevt_init_separate(np); ++} ++ + static int __init timer_init(struct device_node *np) + { + int num_blocks = DIV_ROUND_UP(num_possible_cpus(), 2); + struct clk *clk; +- int ret; ++ int ret, i; + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { +@@ -182,11 +260,12 @@ static int __init timer_init(struct devi + + econet_timer.freq_hz = clk_get_rate(clk); + +- for (int i = 0; i < num_blocks; i++) { ++ for (i = 0; i < num_blocks; i++) { + econet_timer.membase[i] = of_iomap(np, i); + if (!econet_timer.membase[i]) { + pr_err("%pOFn: failed to map register [%d]\n", np, i); +- return -ENXIO; ++ ret = -ENXIO; ++ goto err_unmap; + } + } + +@@ -196,21 +275,34 @@ static int __init timer_init(struct devi + clocksource_mmio_readl_up); + if (ret) { + pr_err("%pOFn: clocksource_mmio_init failed: %d", np, ret); +- return ret; ++ goto err_unmap; + } + + ret = cevt_init(np); + if (ret < 0) +- return ret; ++ goto err_unmap; ++ ++ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, ++ "clockevents/econet/timer:starting", ++ cevt_init_cpu, NULL); + + sched_clock_register(sched_clock_read, ECONET_BITS, + econet_timer.freq_hz); + +- pr_info("%pOFn: using %u.%03u MHz high precision timer\n", np, ++ pr_info("%pOFn: using %u.%03u MHz high precision timer (%s mode)\n", np, + econet_timer.freq_hz / 1000000, +- (econet_timer.freq_hz / 1000) % 1000); ++ (econet_timer.freq_hz / 1000) % 1000, ++ econet_timer.use_percpu_irq ? "percpu" : "separate IRQ"); + + return 0; ++ ++err_unmap: ++ for (i = 0; i < num_blocks; i++) { ++ if (econet_timer.membase[i]) ++ iounmap(econet_timer.membase[i]); ++ } ++ return ret; + } + +-TIMER_OF_DECLARE(econet_timer_hpt, "econet,en751221-timer", timer_init); ++TIMER_OF_DECLARE(econet_en751221_timer, "econet,en751221-timer", timer_init); ++TIMER_OF_DECLARE(econet_en7528_timer, "econet,en7528-timer", timer_init); diff --git a/target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch b/target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch new file mode 100644 index 0000000000..d3f3054fe7 --- /dev/null +++ b/target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch @@ -0,0 +1,341 @@ +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -370,6 +370,12 @@ config SPI_DLN2 + This driver can also be built as a module. If so, the module + will be called spi-dln2. + ++config SPI_AIROHA_EN7523 ++ bool "Airoha EN7523 SPI controller support" ++ depends on ARCH_AIROHA ++ help ++ This enables SPI controller support for the Airoha EN7523 SoC. ++ + config SPI_EP93XX + tristate "Cirrus Logic EP93xx SPI controller" + depends on ARCH_EP93XX || COMPILE_TEST +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -52,6 +52,7 @@ obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1. + obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o + obj-$(CONFIG_SPI_DW_PCI) += spi-dw-pci.o + obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o ++obj-$(CONFIG_SPI_AIROHA_EN7523) += spi-en7523.o + obj-$(CONFIG_SPI_FALCON) += spi-falcon.o + obj-$(CONFIG_SPI_FSI) += spi-fsi.o + obj-$(CONFIG_SPI_FSL_CPM) += spi-fsl-cpm.o +--- /dev/null ++++ b/drivers/spi/spi-en7523.c +@@ -0,0 +1,313 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++ ++ ++#define ENSPI_READ_IDLE_EN 0x0004 ++#define ENSPI_MTX_MODE_TOG 0x0014 ++#define ENSPI_RDCTL_FSM 0x0018 ++#define ENSPI_MANUAL_EN 0x0020 ++#define ENSPI_MANUAL_OPFIFO_EMPTY 0x0024 ++#define ENSPI_MANUAL_OPFIFO_WDATA 0x0028 ++#define ENSPI_MANUAL_OPFIFO_FULL 0x002C ++#define ENSPI_MANUAL_OPFIFO_WR 0x0030 ++#define ENSPI_MANUAL_DFIFO_FULL 0x0034 ++#define ENSPI_MANUAL_DFIFO_WDATA 0x0038 ++#define ENSPI_MANUAL_DFIFO_EMPTY 0x003C ++#define ENSPI_MANUAL_DFIFO_RD 0x0040 ++#define ENSPI_MANUAL_DFIFO_RDATA 0x0044 ++#define ENSPI_IER 0x0090 ++#define ENSPI_NFI2SPI_EN 0x0130 ++ ++// TODO not in spi block ++#define ENSPI_CLOCK_DIVIDER ((void __iomem *)0x1fa201c4) ++ ++#define OP_CSH 0x00 ++#define OP_CSL 0x01 ++#define OP_CK 0x02 ++#define OP_OUTS 0x08 ++#define OP_OUTD 0x09 ++#define OP_OUTQ 0x0A ++#define OP_INS 0x0C ++#define OP_INS0 0x0D ++#define OP_IND 0x0E ++#define OP_INQ 0x0F ++#define OP_OS2IS 0x10 ++#define OP_OS2ID 0x11 ++#define OP_OS2IQ 0x12 ++#define OP_OD2IS 0x13 ++#define OP_OD2ID 0x14 ++#define OP_OD2IQ 0x15 ++#define OP_OQ2IS 0x16 ++#define OP_OQ2ID 0x17 ++#define OP_OQ2IQ 0x18 ++#define OP_OSNIS 0x19 ++#define OP_ODNID 0x1A ++ ++#define MATRIX_MODE_AUTO 1 ++#define CONF_MTX_MODE_AUTO 0 ++#define MANUALEN_AUTO 0 ++#define MATRIX_MODE_MANUAL 0 ++#define CONF_MTX_MODE_MANUAL 9 ++#define MANUALEN_MANUAL 1 ++ ++#define _ENSPI_MAX_XFER 0x1ff ++ ++#define REG(x) (iobase + x) ++ ++ ++static void __iomem *iobase; ++ ++ ++static void opfifo_write(u32 cmd, u32 len) ++{ ++ u32 tmp = ((cmd & 0x1f) << 9) | (len & 0x1ff); ++ ++ writel(tmp, REG(ENSPI_MANUAL_OPFIFO_WDATA)); ++ ++ /* Wait for room in OPFIFO */ ++ while (readl(REG(ENSPI_MANUAL_OPFIFO_FULL))) ++ ; ++ ++ /* Shift command into OPFIFO */ ++ writel(1, REG(ENSPI_MANUAL_OPFIFO_WR)); ++ ++ /* Wait for command to finish */ ++ while (!readl(REG(ENSPI_MANUAL_OPFIFO_EMPTY))) ++ ; ++} ++ ++static void set_cs(int state) ++{ ++ if (state) ++ opfifo_write(OP_CSH, 1); ++ else ++ opfifo_write(OP_CSL, 1); ++} ++ ++static void manual_begin_cmd(void) ++{ ++ /* Disable read idle state */ ++ writel(0, REG(ENSPI_READ_IDLE_EN)); ++ ++ /* Wait for FSM to reach idle state */ ++ while (readl(REG(ENSPI_RDCTL_FSM))) ++ ; ++ ++ /* Set SPI core to manual mode */ ++ writel(CONF_MTX_MODE_MANUAL, REG(ENSPI_MTX_MODE_TOG)); ++ writel(MANUALEN_MANUAL, REG(ENSPI_MANUAL_EN)); ++} ++ ++static void manual_end_cmd(void) ++{ ++ /* Set SPI core to auto mode */ ++ writel(CONF_MTX_MODE_AUTO, REG(ENSPI_MTX_MODE_TOG)); ++ writel(MANUALEN_AUTO, REG(ENSPI_MANUAL_EN)); ++ ++ /* Enable read idle state */ ++ writel(1, REG(ENSPI_READ_IDLE_EN)); ++} ++ ++static void dfifo_read(u8 *buf, int len) ++{ ++ int i; ++ ++ for (i = 0; i < len; i++) { ++ /* Wait for requested data to show up in DFIFO */ ++ while (readl(REG(ENSPI_MANUAL_DFIFO_EMPTY))) ++ ; ++ buf[i] = readl(REG(ENSPI_MANUAL_DFIFO_RDATA)); ++ /* Queue up next byte */ ++ writel(1, REG(ENSPI_MANUAL_DFIFO_RD)); ++ } ++} ++ ++static void dfifo_write(const u8 *buf, int len) ++{ ++ int i; ++ ++ for (i = 0; i < len; i++) { ++ /* Wait for room in DFIFO */ ++ while (readl(REG(ENSPI_MANUAL_DFIFO_FULL))) ++ ; ++ writel(buf[i], REG(ENSPI_MANUAL_DFIFO_WDATA)); ++ } ++} ++ ++#if 0 ++static void set_spi_clock_speed(int freq_mhz) ++{ ++ u32 tmp, val; ++ ++ tmp = readl(ENSPI_CLOCK_DIVIDER); ++ tmp &= 0xffff0000; ++ writel(tmp, ENSPI_CLOCK_DIVIDER); ++ ++ val = (400 / (freq_mhz * 2)); ++ tmp |= (val << 8) | 1; ++ writel(tmp, ENSPI_CLOCK_DIVIDER); ++} ++#endif ++ ++static void init_hw(void) ++{ ++ /* Disable manual/auto mode clash interrupt */ ++ writel(0, REG(ENSPI_IER)); ++ ++ // TODO via clk framework ++ // set_spi_clock_speed(50); ++ ++ /* Disable DMA */ ++ writel(0, REG(ENSPI_NFI2SPI_EN)); ++} ++ ++static int xfer_read(struct spi_transfer *xfer) ++{ ++ int opcode; ++ uint8_t *buf = xfer->rx_buf; ++ ++ switch (xfer->rx_nbits) { ++ case SPI_NBITS_SINGLE: ++ opcode = OP_INS; ++ break; ++ case SPI_NBITS_DUAL: ++ opcode = OP_IND; ++ break; ++ case SPI_NBITS_QUAD: ++ opcode = OP_INQ; ++ break; ++ } ++ ++ opfifo_write(opcode, xfer->len); ++ dfifo_read(buf, xfer->len); ++ ++ return xfer->len; ++} ++ ++static int xfer_write(struct spi_transfer *xfer, int next_xfer_is_rx) ++{ ++ int opcode; ++ const uint8_t *buf = xfer->tx_buf; ++ ++ if (next_xfer_is_rx) { ++ /* need to use Ox2Ix opcode to set the core to input afterwards */ ++ switch (xfer->tx_nbits) { ++ case SPI_NBITS_SINGLE: ++ opcode = OP_OS2IS; ++ break; ++ case SPI_NBITS_DUAL: ++ opcode = OP_OS2ID; ++ break; ++ case SPI_NBITS_QUAD: ++ opcode = OP_OS2IQ; ++ break; ++ } ++ } else { ++ switch (xfer->tx_nbits) { ++ case SPI_NBITS_SINGLE: ++ opcode = OP_OUTS; ++ break; ++ case SPI_NBITS_DUAL: ++ opcode = OP_OUTD; ++ break; ++ case SPI_NBITS_QUAD: ++ opcode = OP_OUTQ; ++ break; ++ } ++ } ++ ++ opfifo_write(opcode, xfer->len); ++ dfifo_write(buf, xfer->len); ++ ++ return xfer->len; ++} ++ ++size_t max_transfer_size(struct spi_device *spi) ++{ ++ return _ENSPI_MAX_XFER; ++} ++ ++int transfer_one_message(struct spi_controller *ctrl, struct spi_message *msg) ++{ ++ struct spi_transfer *xfer; ++ int next_xfer_is_rx = 0; ++ ++ manual_begin_cmd(); ++ set_cs(0); ++ list_for_each_entry(xfer, &msg->transfers, transfer_list) { ++ if (xfer->tx_buf) { ++ if (!list_is_last(&xfer->transfer_list, &msg->transfers) ++ && list_next_entry(xfer, transfer_list)->rx_buf != NULL) ++ next_xfer_is_rx = 1; ++ else ++ next_xfer_is_rx = 0; ++ msg->actual_length += xfer_write(xfer, next_xfer_is_rx); ++ } else if (xfer->rx_buf) { ++ msg->actual_length += xfer_read(xfer); ++ } ++ } ++ set_cs(1); ++ manual_end_cmd(); ++ ++ msg->status = 0; ++ spi_finalize_current_message(ctrl); ++ ++ return 0; ++} ++ ++static int spi_probe(struct platform_device *pdev) ++{ ++ struct spi_controller *ctrl; ++ int err; ++ ++ ctrl = devm_spi_alloc_master(&pdev->dev, 0); ++ if (!ctrl) { ++ dev_err(&pdev->dev, "Error allocating SPI controller\n"); ++ return -ENOMEM; ++ } ++ ++ iobase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); ++ if (IS_ERR(iobase)) { ++ dev_err(&pdev->dev, "Could not map SPI register address"); ++ return -ENOMEM; ++ } ++ ++ init_hw(); ++ ++ ctrl->dev.of_node = pdev->dev.of_node; ++ ctrl->flags = SPI_CONTROLLER_HALF_DUPLEX; ++ ctrl->mode_bits = SPI_RX_DUAL | SPI_TX_DUAL; ++ ctrl->max_transfer_size = max_transfer_size; ++ ctrl->transfer_one_message = transfer_one_message; ++ err = devm_spi_register_controller(&pdev->dev, ctrl); ++ if (err) { ++ dev_err(&pdev->dev, "Could not register SPI controller\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id spi_of_ids[] = { ++ { .compatible = "airoha,en7523-spi" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, spi_of_ids); ++ ++static struct platform_driver spi_driver = { ++ .probe = spi_probe, ++ .driver = { ++ .name = "airoha-en7523-spi", ++ .of_match_table = spi_of_ids, ++ }, ++}; ++ ++module_platform_driver(spi_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Bert Vermeulen "); ++MODULE_DESCRIPTION("Airoha EN7523 SPI driver"); diff --git a/target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch b/target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch new file mode 100644 index 0000000000..888df7552e --- /dev/null +++ b/target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch @@ -0,0 +1,56 @@ +Subject: Adapt Airoha EN7523 SPI to work with EcoNet EN751221 + +The SPI driver from Airoha EN7523 is copied here in it's original form +so this patch makes three updates to it in order to make it work +correctly in the EcoNet EN751221 context. + +The main change here is that the chip select operation is sent twice. +This pattern is borrowed from the vendor code and it prevents write +operations from being lost sporadically on the EN751221. + +Signed-off-by: Caleb James DeLisle +--- +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -372,7 +372,7 @@ config SPI_DLN2 + + config SPI_AIROHA_EN7523 + bool "Airoha EN7523 SPI controller support" +- depends on ARCH_AIROHA ++ depends on ARCH_AIROHA || ECONET + help + This enables SPI controller support for the Airoha EN7523 SoC. + +--- a/drivers/spi/spi-en7523.c ++++ b/drivers/spi/spi-en7523.c +@@ -82,10 +82,11 @@ static void opfifo_write(u32 cmd, u32 le + + static void set_cs(int state) + { +- if (state) +- opfifo_write(OP_CSH, 1); +- else +- opfifo_write(OP_CSL, 1); ++ u32 cmd = state ? OP_CSH : OP_CSL; ++ ++ /* EN751221 drops writes if we don't send this twice. */ ++ opfifo_write(cmd, 1); ++ opfifo_write(cmd, 1); + } + + static void manual_begin_cmd(void) +@@ -226,12 +227,12 @@ static int xfer_write(struct spi_transfe + return xfer->len; + } + +-size_t max_transfer_size(struct spi_device *spi) ++static size_t max_transfer_size(struct spi_device *spi) + { + return _ENSPI_MAX_XFER; + } + +-int transfer_one_message(struct spi_controller *ctrl, struct spi_message *msg) ++static int transfer_one_message(struct spi_controller *ctrl, struct spi_message *msg) + { + struct spi_transfer *xfer; + int next_xfer_is_rx = 0; diff --git a/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch b/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch new file mode 100644 index 0000000000..8556633d01 --- /dev/null +++ b/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch @@ -0,0 +1,21 @@ +spi: airoha-snfi: enable for EcoNet EN7528 + +Enable the Airoha SNFI (SPI NAND Flash Interface) driver for EcoNet +EN7528 SoC. The EN7528 shares the same SPI controller and NFI DMA +engine as the Airoha EN7523/EN7581, with identical register layouts. + +Using the DMA-capable SNFI driver provides significantly better +performance compared to the manual mode spi-en7523 driver. + +Signed-off-by: Ahmed Naseef +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -59,7 +59,7 @@ comment "SPI Master Controller Drivers" + + config SPI_AIROHA_SNFI + tristate "Airoha SPI NAND Flash Interface" +- depends on ARCH_AIROHA || COMPILE_TEST ++ depends on ARCH_AIROHA || ECONET || COMPILE_TEST + depends on SPI_MASTER + select REGMAP_MMIO + help diff --git a/target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch b/target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch new file mode 100644 index 0000000000..a550bbfae5 --- /dev/null +++ b/target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch @@ -0,0 +1,21 @@ +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -391,6 +391,7 @@ config MACH_DECSTATION + config ECONET + bool "EcoNet MIPS family" + select BOOT_RAW ++ select DMA_NONCOHERENT + select DEBUG_ZBOOT if DEBUG_KERNEL + select EARLY_PRINTK_8250 + select ECONET_EN751221_TIMER +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -71,7 +71,7 @@ config USB_XHCI_HISTB + config USB_XHCI_MTK + tristate "xHCI support for MediaTek SoCs" + select MFD_SYSCON +- depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || COMPILE_TEST ++ depends on (MIPS && SOC_MT7621) || ECONET || ARCH_MEDIATEK || COMPILE_TEST + help + Say 'Y' to enable the support for the xHCI host controller + found in MediaTek SoCs. diff --git a/target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch b/target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch new file mode 100644 index 0000000000..09e86ff5c9 --- /dev/null +++ b/target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch @@ -0,0 +1,17 @@ +gpio: en7523: enable for EcoNet MIPS platform + +The Airoha EN7523 GPIO controller is also found on EcoNet EN7528 +MIPS SoC. Allow building the driver when ECONET is selected. + +Signed-off-by: Ahmed Naseef +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -271,7 +271,7 @@ config GPIO_EM + + config GPIO_EN7523 + tristate "Airoha GPIO support" +- depends on ARCH_AIROHA ++ depends on ARCH_AIROHA || ECONET + default ARCH_AIROHA + select GPIO_GENERIC + select GPIOLIB_IRQCHIP diff --git a/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch b/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch new file mode 100644 index 0000000000..486208f71a --- /dev/null +++ b/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch @@ -0,0 +1,206 @@ +--- /dev/null ++++ b/drivers/tty/serial/8250/8250_en7523.c +@@ -0,0 +1,94 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Airoha EN7523 driver. ++ * ++ * Copyright (c) 2022 Genexis Sweden AB ++ * Author: Benjamin Larsson ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "8250.h" ++ ++ ++/* The Airoha UART is 16550-compatible except for the baud rate calculation. ++ * ++ * crystal_clock = 20 MHz ++ * xindiv_clock = crystal_clock / clock_div ++ * (x/y) = XYD, 32 bit register with 16 bits of x and and then 16 bits of y ++ * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), ++ * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] ++ * ++ * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) ++ * ++ * XYD_y seems to need to be larger then XYD_x for things to work. ++ * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values ++ * for usual baud rates. ++ * ++ * Selecting divider needs to fulfill ++ * 1.8432 MHz <= xindiv_clk <= APB clock / 2 ++ * The clocks are unknown but a divider of value 1 did not work. ++ * ++ * Optimally the XYD, BRD and XINCLK_DIVCNT registers could be searched to ++ * find values that gives the least error for every baud rate. But searching ++ * the space takes time and in practise only a few rates are of interest. ++ * With some value combinations not working a tested subset is used giving ++ * a usable range from 110 to 460800 baud. ++ */ ++ ++#define CLOCK_DIV_TAB_ELEMS 3 ++#define XYD_Y 65000 ++#define XINDIV_CLOCK 20000000 ++#define UART_BRDL_20M 0x01 ++#define UART_BRDH_20M 0x00 ++ ++static int clock_div_tab[] = { 10, 4, 2}; ++static int clock_div_reg[] = { 4, 2, 1}; ++ ++ ++int en7523_set_uart_baud_rate (struct uart_port *port, unsigned int baud) ++{ ++ struct uart_8250_port *up = up_to_u8250p(port); ++ unsigned int xyd_x, nom, denom; ++ int i; ++ ++ /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */ ++ serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); ++ ++ /* set baud rate calculation defaults */ ++ ++ /* set BRDIV ([BRDH,BRDL]) to 1 */ ++ serial_port_out(port, UART_BRDL, UART_BRDL_20M); ++ serial_port_out(port, UART_BRDH, UART_BRDH_20M); ++ ++ /* calculate XYD_x and XINCLKDR register */ ++ ++ for (i = 0 ; i < CLOCK_DIV_TAB_ELEMS ; i++) { ++ denom = (XINDIV_CLOCK/40) / clock_div_tab[i]; ++ nom = (baud * (XYD_Y/40)); ++ xyd_x = ((nom/denom) << 4); ++ if (xyd_x < XYD_Y) break; ++ } ++ ++ serial_port_out(port, UART_XINCLKDR, clock_div_reg[i]); ++ serial_port_out(port, UART_XYD, (xyd_x<<16) | XYD_Y); ++ ++ /* unset DLAB */ ++ serial_port_out(port, UART_LCR, up->lcr); ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL_GPL(en7523_set_uart_baud_rate); +--- a/drivers/tty/serial/8250/8250_of.c ++++ b/drivers/tty/serial/8250/8250_of.c +@@ -341,6 +341,7 @@ static const struct of_device_id of_plat + { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, + { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, + { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, ++ { .compatible = "airoha,en7523-uart", .data = (void *)PORT_AIROHA, }, + { /* end of list */ }, + }; + MODULE_DEVICE_TABLE(of, of_platform_serial_table); +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -319,6 +319,14 @@ static const struct serial8250_config ua + .rxtrig_bytes = {1, 8, 16, 30}, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, ++ [PORT_AIROHA] = { ++ .name = "Airoha 16550", ++ .fifo_size = 8, ++ .tx_loadsz = 1, ++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01, ++ .rxtrig_bytes = {1, 4}, ++ .flags = UART_CAP_FIFO, ++ }, + }; + + /* Uart divisor latch read */ +@@ -2841,6 +2849,12 @@ serial8250_do_set_termios(struct uart_po + + serial8250_set_divisor(port, baud, quot, frac); + ++#ifdef CONFIG_SERIAL_8250_AIROHA ++ /* Airoha SoCs have custom registers for baud rate settings */ ++ if (port->type == PORT_AIROHA) ++ en7523_set_uart_baud_rate(port, baud); ++#endif ++ + /* + * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR + * is written without DLAB set, this mode will be disabled. +--- a/drivers/tty/serial/8250/Kconfig ++++ b/drivers/tty/serial/8250/Kconfig +@@ -355,6 +355,16 @@ config SERIAL_8250_ACORN + system, say Y to this option. The driver can handle 1, 2, or 3 port + cards. If unsure, say N. + ++config SERIAL_8250_AIROHA ++ tristate "Airoha UART support" ++ depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250 ++ help ++ Selecting this option enables an Airoha SoC specific baud rate ++ calculation routine on an otherwise 16550 compatible UART hardware. ++ ++ If you have an Airoha based board and want to use the serial port, ++ say Y to this option. If unsure, say N. ++ + config SERIAL_8250_BCM2835AUX + tristate "BCM2835 auxiliar mini UART support" + depends on ARCH_BCM2835 || COMPILE_TEST +--- a/drivers/tty/serial/8250/Makefile ++++ b/drivers/tty/serial/8250/Makefile +@@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 825 + + obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o + obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o ++obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_en7523.o + obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o + obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o + obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o +--- a/include/uapi/linux/serial_reg.h ++++ b/include/uapi/linux/serial_reg.h +@@ -383,5 +383,17 @@ + #define UART_ALTR_EN_TXFIFO_LW 0x01 /* Enable the TX FIFO Low Watermark */ + #define UART_ALTR_TX_LOW 0x41 /* Tx FIFO Low Watermark */ + ++/* ++ * These are definitions for the Airoha EN75XX uart registers ++ * Normalized because of 32 bits registers. ++ */ ++#define UART_BRDL 0 ++#define UART_BRDH 1 ++#define UART_XINCLKDR 10 ++#define UART_XYD 11 ++#define UART_TXLVLCNT 12 ++#define UART_RXLVLCNT 13 ++#define UART_FINTLVL 14 ++ + #endif /* _LINUX_SERIAL_REG_H */ + +--- a/include/uapi/linux/serial_core.h ++++ b/include/uapi/linux/serial_core.h +@@ -31,6 +31,7 @@ + #define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */ + #define PORT_RT2880 29 /* Ralink RT2880 internal UART */ + #define PORT_16550A_FSL64 30 /* Freescale 16550 UART with 64 FIFOs */ ++#define PORT_AIROHA 31 /* Airoha 16550 UART */ + + /* + * ARM specific type numbers. These are not currently guaranteed +--- a/include/linux/serial_8250.h ++++ b/include/linux/serial_8250.h +@@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart + void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, + unsigned int quot); + int fsl8250_handle_irq(struct uart_port *port); ++int en7523_set_uart_baud_rate(struct uart_port *port, unsigned int baud); + int serial8250_handle_irq(struct uart_port *port, unsigned int iir); + u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); + void serial8250_read_char(struct uart_8250_port *up, u16 lsr); diff --git a/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch b/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch new file mode 100644 index 0000000000..b25d02e969 --- /dev/null +++ b/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch @@ -0,0 +1,18 @@ +serial: 8250: airoha: add EcoNet platform support + +The EcoNet EN75xx SoCs use the same UART IP core as the Airoha +AN7523 SoCs. Add ECONET to the Kconfig dependency to enable +the Airoha UART driver for EcoNet platforms. + +Signed-off-by: Ahmed Naseef +--- a/drivers/tty/serial/8250/Kconfig ++++ b/drivers/tty/serial/8250/Kconfig +@@ -357,7 +357,7 @@ config SERIAL_8250_ACORN + + config SERIAL_8250_AIROHA + tristate "Airoha UART support" +- depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250 ++ depends on (ARCH_AIROHA || ECONET || COMPILE_TEST) && OF && SERIAL_8250 + help + Selecting this option enables an Airoha SoC specific baud rate + calculation routine on an otherwise 16550 compatible UART hardware. diff --git a/target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch b/target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch new file mode 100644 index 0000000000..91e184bd96 --- /dev/null +++ b/target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch @@ -0,0 +1,40 @@ +Subject: Add EcoNet bad block table + +The EcoNet BBT/BMT is used for resolving bad blocks in the flash. +It is implemented in the EcoNet bootloader so you cannot safely +access flash without using it. + +Signed-off-by: Caleb James DeLisle +--- +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -3,7 +3,7 @@ + nandcore-objs := core.o bbt.o + obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o + obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o +-obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o ++obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o en75_bmt.o + obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o + obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o + obj-y += onenand/ +--- a/drivers/mtd/nand/mtk_bmt.h ++++ b/drivers/mtd/nand/mtk_bmt.h +@@ -77,6 +77,7 @@ extern struct bmt_desc bmtd; + extern const struct mtk_bmt_ops mtk_bmt_v2_ops; + extern const struct mtk_bmt_ops mtk_bmt_bbt_ops; + extern const struct mtk_bmt_ops mtk_bmt_nmbm_ops; ++extern const struct mtk_bmt_ops en75_bmt_ops; + + static inline u32 blk_pg(u16 block) + { +--- a/drivers/mtd/nand/mtk_bmt.c ++++ b/drivers/mtd/nand/mtk_bmt.c +@@ -421,6 +421,8 @@ int mtk_bmt_attach(struct mtd_info *mtd) + bmtd.ops = &mtk_bmt_nmbm_ops; + else if (of_property_read_bool(np, "mediatek,bbt")) + bmtd.ops = &mtk_bmt_bbt_ops; ++ else if (of_property_read_bool(np, "econet,bmt")) ++ bmtd.ops = &en75_bmt_ops; + else + return 0; + diff --git a/target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch b/target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch new file mode 100644 index 0000000000..2dc81292ec --- /dev/null +++ b/target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch @@ -0,0 +1,34 @@ +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) + { +@@ -1604,6 +1605,7 @@ static int spinand_probe(struct spi_mem + if (ret) + return ret; + ++ mtk_bmt_attach(mtd); + ret = mtd_device_register(mtd, NULL, 0); + if (ret) + goto err_spinand_cleanup; +@@ -1611,6 +1613,7 @@ static int spinand_probe(struct spi_mem + return 0; + + err_spinand_cleanup: ++ mtk_bmt_detach(mtd); + spinand_cleanup(spinand); + + return ret; +@@ -1629,6 +1632,7 @@ static int spinand_remove(struct spi_mem + if (ret) + return ret; + ++ mtk_bmt_detach(mtd); + spinand_cleanup(spinand); + + return 0; diff --git a/target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch b/target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch new file mode 100644 index 0000000000..37dc36cacc --- /dev/null +++ b/target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch @@ -0,0 +1,176 @@ +From f3fa5911b1f094e164c497f7b10d94d92852e285 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Wed, 14 Jan 2026 17:54:05 +0000 +Subject: [PATCH] dt-bindings: clock, reset: Add econet EN751221 bindings + +Add clock and reset bindings for EN751221 based on the Airoha EN7523 SCU +driver. + +Signed-off-by: Caleb James DeLisle +--- +The EN751221 has the same bifurcation of SCU as EN7581 so we use +the same chip-scu as airoha,en7581-chip-scu. +--- + .../bindings/clock/airoha,en7523-scu.yaml | 17 +++++++- + .../mips/econet,en751221-chip-scu.yaml | 42 +++++++++++++++++++ + .../dt-bindings/clock/econet,en751221-scu.h | 14 +++++++ + .../dt-bindings/reset/econet,en751221-scu.h | 41 ++++++++++++++++++ + 4 files changed, 113 insertions(+), 1 deletion(-) + create mode 100644 Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml + create mode 100644 include/dt-bindings/clock/econet,en751221-scu.h + create mode 100644 include/dt-bindings/reset/econet,en751221-scu.h + +--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml ++++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +@@ -32,6 +32,7 @@ properties: + - enum: + - airoha,en7523-scu + - airoha,en7581-scu ++ - econet,en751221-scu + + reg: + items: +@@ -67,7 +68,10 @@ allOf: + - if: + properties: + compatible: +- const: airoha,en7581-scu ++ items: ++ - enum: ++ - airoha,en7581-scu ++ - econet,en751221-scu + then: + properties: + reg: +@@ -98,3 +102,14 @@ examples: + #reset-cells = <1>; + }; + }; ++ ++ - | ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ scuclk: clock-controller@1fb00000 { ++ compatible = "econet,en751221-scu"; ++ reg = <0x1fb00000 0x970>; ++ }; ++ }; +\ No newline at end of file +--- /dev/null ++++ b/Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml +@@ -0,0 +1,42 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/arm/airoha,en7581-chip-scu.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: EcoNet Chip SCU Controller for EN751221 SoC ++ ++maintainers: ++ - Caleb James DeLisle ++ ++description: ++ The EcoNet chip-scu block provides a configuration interface for clock, ++ io-muxing and other functionalities used by multiple controllers (e.g. clock, ++ pinctrl, ecc) on EN751221 SoC. ++ ++properties: ++ compatible: ++ items: ++ - enum: ++ - econet,en751221-chip-scu ++ - const: syscon ++ ++ reg: ++ maxItems: 1 ++ ++required: ++ - compatible ++ - reg ++ ++additionalProperties: false ++ ++examples: ++ - | ++ soc { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ syscon@1fa20000 { ++ compatible = "econet,en751221-chip-scu", "syscon"; ++ reg = <0x1fa20000 0x388>; ++ }; ++ }; +--- /dev/null ++++ b/include/dt-bindings/clock/econet,en751221-scu.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ ++ ++#ifndef _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ ++#define _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ ++ ++#define EN751221_CLK_PCIE 0 ++#define EN751221_CLK_SPI 1 ++#define EN751221_CLK_BUS 2 ++#define EN751221_CLK_CPU 3 ++#define EN751221_CLK_HPT 4 ++#define EN751221_CLK_GSW 5 ++ ++#define EN751221_MAX_CLKS 6 ++ ++#endif /* _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ */ +\ No newline at end of file +--- /dev/null ++++ b/include/dt-bindings/reset/econet,en751221-scu.h +@@ -0,0 +1,49 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ ++ ++#ifndef __DT_BINDINGS_RESET_CONTROLLER_ECONET_EN751221_H_ ++#define __DT_BINDINGS_RESET_CONTROLLER_ECONET_EN751221_H_ ++ ++#define EN751221_XPON_PHY_RST 0 ++#define EN751221_PCM1_ZSI_ISI_RST 1 ++#define EN751221_FE_QDMA1_RST 2 ++#define EN751221_FE_QDMA2_RST 3 ++#define EN751221_FE_UNZIP_RST 4 ++#define EN751221_PCM2_RST 5 ++#define EN751221_PTM_MAC_RST 6 ++#define EN751221_CRYPTO_RST 7 ++#define EN751221_SAR_RST 8 ++#define EN751221_TIMER_RST 9 ++#define EN751221_INTC_RST 10 ++#define EN751221_BONDING_RST 11 ++#define EN751221_PCM1_RST 12 ++#define EN751221_UART_RST 13 ++#define EN751221_GPIO_RST 14 ++#define EN751221_GDMA_RST 15 ++#define EN751221_I2C_MASTER_RST 16 ++#define EN751221_PCM2_ZSI_ISI_RST 17 ++#define EN751221_SFC_RST 18 ++#define EN751221_UART2_RST 19 ++#define EN751221_GDMP_RST 20 ++#define EN751221_FE_RST 21 ++#define EN751221_USB_HOST_P0_RST 22 ++#define EN751221_GSW_RST 23 ++#define EN751221_SFC2_PCM_RST 24 ++#define EN751221_PCIE0_RST 25 ++#define EN751221_PCIE1_RST 26 ++#define EN751221_CPU_TIMER_RST 27 ++#define EN751221_PCIE_HB_RST 28 ++#define EN751221_SIMIF_RST 29 ++#define EN751221_XPON_MAC_RST 30 ++#define EN751221_GFAST_RST 31 ++#define EN751221_CPU_TIMER2_RST 32 ++#define EN751221_UART3_RST 33 ++#define EN751221_UART4_RST 34 ++#define EN751221_UART5_RST 35 ++#define EN751221_I2C2_RST 36 ++#define EN751221_XSI_MAC_RST 37 ++#define EN751221_XSI_PHY_RST 38 ++#define EN751221_DMT_RST 39 ++#define EN751221_USB_PHY_P0_RST 40 ++#define EN751221_USB_PHY_P1_RST 41 ++ ++#endif /* __DT_BINDINGS_RESET_CONTROLLER_ECONET_EN751221_H_ */ diff --git a/target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch b/target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch new file mode 100644 index 0000000000..021043a13d --- /dev/null +++ b/target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch @@ -0,0 +1,364 @@ +From 1dfb29374a040ba80d378b3465f4e0bcb67f4ba3 Mon Sep 17 00:00:00 2001 +From: Caleb James DeLisle +Date: Wed, 14 Jan 2026 18:06:13 +0000 +Subject: [PATCH] clk: airoha: Add econet EN751221 clock/reset support to + en7523-scu + +EcoNet EN751221 clock/reset driver is significantly similar to the +EN7523 / EN7581, however the EN751221 does not have a neat batch of clock +divider registers so there are fewer known clocks, and the frequency of +each clock is derived differently. This clock driver will probably work +correctly on EN751627, EN7528, and EN7580. + +Signed-off-by: Caleb James DeLisle +--- + drivers/clk/Kconfig | 6 +- + drivers/clk/clk-en7523.c | 182 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 185 insertions(+), 3 deletions(-) + +--- a/drivers/clk/Kconfig ++++ b/drivers/clk/Kconfig +@@ -210,13 +210,13 @@ config COMMON_CLK_CS2000_CP + If you say yes here you get support for the CS2000 clock multiplier. + + config COMMON_CLK_EN7523 +- bool "Clock driver for Airoha EN7523 SoC system clocks" ++ bool "Clock driver for Airoha/EcoNet SoC system clocks" + depends on OF +- depends on ARCH_AIROHA || COMPILE_TEST ++ depends on ARCH_AIROHA || ECONET || COMPILE_TEST + default ARCH_AIROHA + help + This driver provides the fixed clocks and gates present on Airoha +- ARM silicon. ++ and EcoNet silicon. + + config COMMON_CLK_EP93XX + tristate "Clock driver for Cirrus Logic ep93xx SoC" +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only + ++#include + #include + #include + #include +@@ -11,6 +12,8 @@ + #include + #include + #include ++#include ++#include + + #define RST_NR_PER_BANK 32 + +@@ -33,15 +36,47 @@ + #define REG_RESET_CONTROL_PCIEHB BIT(29) + #define REG_RESET_CONTROL_PCIE1 BIT(27) + #define REG_RESET_CONTROL_PCIE2 BIT(26) ++#define REG_HIR 0x064 ++#define REG_HIR_MASK GENMASK(31, 16) + /* EN7581 */ + #define REG_NP_SCU_PCIC 0x88 + #define REG_NP_SCU_SSTR 0x9c + #define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13) + #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) + #define REG_CRYPTO_CLKSRC2 0x20c ++/* EN751221 */ ++#define EN751221_REG_SPI_DIV 0x0cc ++#define EN751221_REG_SPI_DIV_MASK GENMASK(31,8) ++#define EN751221_SPI_BASE 500000000 ++#define EN751221_SPI_BASE_EN7526C 400000000 ++#define EN751221_REG_BUS 0x284 ++#define EN751221_REG_BUS_MASK GENMASK(21,12) ++#define EN751221_REG_SSR3 0x094 ++#define EN751221_REG_SSR3_GSW_MASK GENMASK(9,8) + + #define REG_RST_CTRL2 0x830 + #define REG_RST_CTRL1 0x834 ++#define EN751221_REG_RST_DMT 0x84 ++#define EN751221_REG_RST_USB 0xec ++ ++enum en_hir { ++ HIR_UNKNOWN = -1, ++ HIR_TC3169 = 0, ++ HIR_TC3182 = 1, ++ HIR_RT65168 = 2, ++ HIR_RT63165 = 3, ++ HIR_RT63365 = 4, ++ HIR_MT751020 = 5, ++ HIR_MT7505 = 6, ++ HIR_EN751221 = 7, ++ HIR_EN7526C = 8, ++ HIR_EN751627 = 9, ++ HIR_EN7580 = 10, ++ HIR_EN7528 = 11, ++ HIR_EN7523 = 12, ++ HIR_EN7581 = 13, ++ HIR_MAX = 14, ++}; + + struct en_clk_desc { + int id; +@@ -93,6 +128,8 @@ static const u32 bus7581_base[] = { 6000 + static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; + static const u32 crypto_base[] = { 540000000, 480000000 }; + static const u32 emmc7581_base[] = { 200000000, 150000000 }; ++/* EN751221 */ ++static const u32 gsw751221_base[] = { 500000000, 250000000, 400000000, 200000000 }; + + static const struct en_clk_desc en7523_base_clks[] = { + { +@@ -300,6 +337,13 @@ static const u16 en7581_rst_ofs[] = { + REG_RST_CTRL1, + }; + ++static const u16 en751221_rst_ofs[] = { ++ REG_RST_CTRL2, ++ REG_RST_CTRL1, ++ EN751221_REG_RST_DMT, ++ EN751221_REG_RST_USB, ++}; ++ + static const u16 en7523_rst_map[] = { + /* RST_CTRL2 */ + [EN7523_XPON_PHY_RST] = 0, +@@ -405,8 +449,61 @@ static const u16 en7581_rst_map[] = { + [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31, + }; + ++static const u16 en751221_rst_map[] = { ++ /* RST_CTRL2 */ ++ [EN751221_XPON_PHY_RST] = 0, ++ [EN751221_GFAST_RST] = 1, ++ [EN751221_CPU_TIMER2_RST] = 2, ++ [EN751221_UART3_RST] = 3, ++ [EN751221_UART4_RST] = 4, ++ [EN751221_UART5_RST] = 5, ++ [EN751221_I2C2_RST] = 6, ++ [EN751221_XSI_MAC_RST] = 7, ++ [EN751221_XSI_PHY_RST] = 8, ++ ++ /* RST_CTRL1 */ ++ [EN751221_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0, ++ [EN751221_FE_QDMA1_RST] = RST_NR_PER_BANK + 1, ++ [EN751221_FE_QDMA2_RST] = RST_NR_PER_BANK + 2, ++ [EN751221_FE_UNZIP_RST] = RST_NR_PER_BANK + 3, ++ [EN751221_PCM2_RST] = RST_NR_PER_BANK + 4, ++ [EN751221_PTM_MAC_RST] = RST_NR_PER_BANK + 5, ++ [EN751221_CRYPTO_RST] = RST_NR_PER_BANK + 6, ++ [EN751221_SAR_RST] = RST_NR_PER_BANK + 7, ++ [EN751221_TIMER_RST] = RST_NR_PER_BANK + 8, ++ [EN751221_INTC_RST] = RST_NR_PER_BANK + 9, ++ [EN751221_BONDING_RST] = RST_NR_PER_BANK + 10, ++ [EN751221_PCM1_RST] = RST_NR_PER_BANK + 11, ++ [EN751221_UART_RST] = RST_NR_PER_BANK + 12, ++ [EN751221_GPIO_RST] = RST_NR_PER_BANK + 13, ++ [EN751221_GDMA_RST] = RST_NR_PER_BANK + 14, ++ [EN751221_I2C_MASTER_RST] = RST_NR_PER_BANK + 16, ++ [EN751221_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17, ++ [EN751221_SFC_RST] = RST_NR_PER_BANK + 18, ++ [EN751221_UART2_RST] = RST_NR_PER_BANK + 19, ++ [EN751221_GDMP_RST] = RST_NR_PER_BANK + 20, ++ [EN751221_FE_RST] = RST_NR_PER_BANK + 21, ++ [EN751221_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22, ++ [EN751221_GSW_RST] = RST_NR_PER_BANK + 23, ++ [EN751221_SFC2_PCM_RST] = RST_NR_PER_BANK + 25, ++ [EN751221_PCIE0_RST] = RST_NR_PER_BANK + 26, ++ [EN751221_PCIE1_RST] = RST_NR_PER_BANK + 27, ++ [EN751221_CPU_TIMER_RST] = RST_NR_PER_BANK + 28, ++ [EN751221_PCIE_HB_RST] = RST_NR_PER_BANK + 29, ++ [EN751221_SIMIF_RST] = RST_NR_PER_BANK + 30, ++ [EN751221_XPON_MAC_RST] = RST_NR_PER_BANK + 31, ++ ++ /* RST_DMT */ ++ [EN751221_DMT_RST] = 2 * RST_NR_PER_BANK + 0, ++ ++ /* RST_USB */ ++ [EN751221_USB_PHY_P0_RST] = 3 * RST_NR_PER_BANK + 6, ++ [EN751221_USB_PHY_P1_RST] = 3 * RST_NR_PER_BANK + 7, ++}; ++ + static int en7581_reset_register(struct device *dev, void __iomem *base, +- const u16 *rst_map, int nr_resets); ++ const u16 *rst_map, int nr_resets, ++ const u16 *rst_reg_ofs); + + static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) + { +@@ -604,7 +701,8 @@ static int en7523_clk_hw_init(struct pla + en7523_register_clocks(&pdev->dev, clk_data, base, np_base); + + return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map, +- ARRAY_SIZE(en7523_rst_map)); ++ ARRAY_SIZE(en7523_rst_map), ++ en7581_rst_ofs); + } + + static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, +@@ -705,7 +803,8 @@ static const struct reset_control_ops en + }; + + static int en7581_reset_register(struct device *dev, void __iomem *base, +- const u16 *rst_map, int nr_resets) ++ const u16 *rst_map, int nr_resets, ++ const u16 *rst_reg_ofs) + { + struct en_rst_data *rst_data; + +@@ -713,7 +812,7 @@ static int en7581_reset_register(struct + if (!rst_data) + return -ENOMEM; + +- rst_data->bank_ofs = en7581_rst_ofs; ++ rst_data->bank_ofs = rst_reg_ofs; + rst_data->idx_map = rst_map; + rst_data->base = base; + +@@ -752,7 +851,123 @@ static int en7581_clk_hw_init(struct pla + writel(val | 3, base + REG_NP_SCU_PCIC); + + return en7581_reset_register(&pdev->dev, base, en7581_rst_map, +- ARRAY_SIZE(en7581_rst_map)); ++ ARRAY_SIZE(en7581_rst_map), ++ en7581_rst_ofs); ++} ++ ++static enum en_hir get_hw_id(void __iomem *np_base) ++{ ++ u32 val = FIELD_GET(REG_HIR_MASK, readl(np_base + REG_HIR)); ++ ++ if (val < HIR_MAX) ++ return (enum en_hir) val; ++ ++ return HIR_UNKNOWN; ++} ++ ++static void en751221_try_register_clk(struct device *dev, int key, ++ struct clk_hw_onecell_data *clk_data, ++ const char *name, u32 rate) ++{ ++ struct clk_hw *hw; ++ ++ hw = clk_hw_register_fixed_rate(dev, name, NULL, 0, rate); ++ if (IS_ERR(hw)) ++ pr_err("Failed to register clk %s: %pe\n", name, hw); ++ else ++ clk_data->hws[key] = hw; ++} ++ ++static void en751221_register_clocks(struct device *dev, ++ struct clk_hw_onecell_data *clk_data, ++ struct regmap *map, void __iomem *np_base) ++{ ++ enum en_hir hid = get_hw_id(np_base); ++ struct clk_hw *hw; ++ u32 rate; ++ u32 div; ++ int err; ++ ++ /* PCI */ ++ hw = en7523_register_pcie_clk(dev, np_base); ++ clk_data->hws[EN751221_CLK_PCIE] = hw; ++ ++ /* SPI */ ++ rate = EN751221_SPI_BASE; ++ if (hid == HIR_EN7526C) ++ rate = EN751221_SPI_BASE_EN7526C; ++ ++ err = regmap_read(map, EN751221_REG_SPI_DIV, &div); ++ if (err) { ++ pr_err("Failed reading fixed clk div %s: %d\n", ++ "spi", err); ++ } else { ++ div = FIELD_GET(EN751221_REG_SPI_DIV_MASK, div) * 2; ++ if (!div) ++ div = 40; ++ ++ en751221_try_register_clk(dev, EN751221_CLK_SPI, clk_data, ++ "spi", rate / div); ++ } ++ ++ /* BUS */ ++ rate = FIELD_GET(EN751221_REG_BUS_MASK, ++ readl(np_base + EN751221_REG_BUS)); ++ rate *= 1000000; ++ en751221_try_register_clk(dev, EN751221_CLK_BUS, clk_data, "bus", ++ rate); ++ ++ /* CPU */ ++ en751221_try_register_clk(dev, EN751221_CLK_CPU, clk_data, "cpu", ++ rate * 4); ++ ++ /* HPT */ ++ switch (hid) { ++ case HIR_EN751221: ++ case HIR_EN751627: ++ case HIR_EN7526C: ++ case HIR_EN7580: ++ case HIR_EN7528: ++ rate = 200000000; ++ break; ++ case HIR_MT7505: ++ rate = 100000000; ++ break; ++ case HIR_MT751020: ++ rate = 800000000 / 3; ++ break; ++ default: ++ rate = 250000000; ++ } ++ en751221_try_register_clk(dev, EN751221_CLK_HPT, clk_data, "hpt", ++ rate); ++ ++ /* GSW */ ++ rate = FIELD_GET(EN751221_REG_SSR3_GSW_MASK, ++ readl(np_base + EN751221_REG_SSR3)); ++ en751221_try_register_clk(dev, EN751221_CLK_GSW, clk_data, "gsw", ++ gsw751221_base[rate]); ++} ++ ++static int en751221_clk_hw_init(struct platform_device *pdev, ++ struct clk_hw_onecell_data *clk_data) ++{ ++ struct regmap *map; ++ void __iomem *base; ++ ++ map = syscon_regmap_lookup_by_compatible("econet,en751221-chip-scu"); ++ if (IS_ERR(map)) ++ return PTR_ERR(map); ++ ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ en751221_register_clocks(&pdev->dev, clk_data, map, base); ++ ++ return en7581_reset_register(&pdev->dev, base, en751221_rst_map, ++ ARRAY_SIZE(en751221_rst_map), ++ en751221_rst_ofs); + } + + static int en7523_clk_probe(struct platform_device *pdev) +@@ -799,9 +1014,20 @@ static const struct en_clk_soc_data en75 + .hw_init = en7581_clk_hw_init, + }; + ++static const struct en_clk_soc_data en751221_data = { ++ .num_clocks = EN751221_MAX_CLKS, ++ .pcie_ops = { ++ .is_enabled = en7523_pci_is_enabled, ++ .prepare = en7523_pci_prepare, ++ .unprepare = en7523_pci_unprepare, ++ }, ++ .hw_init = en751221_clk_hw_init, ++}; ++ + static const struct of_device_id of_match_clk_en7523[] = { + { .compatible = "airoha,en7523-scu", .data = &en7523_data }, + { .compatible = "airoha,en7581-scu", .data = &en7581_data }, ++ { .compatible = "econet,en751221-scu", .data = &en751221_data }, + { /* sentinel */ } + }; + diff --git a/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch b/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch new file mode 100644 index 0000000000..ee8d1bdab9 --- /dev/null +++ b/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch @@ -0,0 +1,373 @@ +--- a/drivers/pci/controller/Kconfig ++++ b/drivers/pci/controller/Kconfig +@@ -187,7 +187,7 @@ config PCI_MVEBU + + config PCIE_MEDIATEK + tristate "MediaTek PCIe controller" +- depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST ++ depends on ARCH_AIROHA || ARCH_MEDIATEK || ECONET || COMPILE_TEST + depends on OF + depends on PCI_MSI + help +--- a/arch/mips/econet/Kconfig ++++ b/arch/mips/econet/Kconfig +@@ -14,7 +14,9 @@ choice + select COMMON_CLK + select CPU_BIG_ENDIAN + select ECONET_EN751221_INTC ++ select HAVE_PCI + select IRQ_MIPS_CPU ++ select PCI_DRIVERS_GENERIC + select SMP + select SMP_UP + select SYS_SUPPORTS_SMP +@@ -28,9 +30,11 @@ choice + bool "EN7528 family" + select COMMON_CLK + select CPU_LITTLE_ENDIAN ++ select HAVE_PCI + select IRQ_MIPS_CPU + select MIPS_CPU_SCACHE + select MIPS_GIC ++ select PCI_DRIVERS_GENERIC + select SMP + select SMP_UP + select SYS_SUPPORTS_HIGHMEM +--- a/drivers/pci/controller/pcie-mediatek.c ++++ b/drivers/pci/controller/pcie-mediatek.c +@@ -76,6 +76,7 @@ + + #define PCIE_CONF_VEND_ID 0x100 + #define PCIE_CONF_DEVICE_ID 0x102 ++#define PCIE_CONF_REV_CLASS 0x104 + #define PCIE_CONF_CLASS_ID 0x106 + + #define PCIE_INT_MASK 0x420 +@@ -88,6 +89,11 @@ + #define MSI_MASK BIT(23) + #define MTK_MSI_IRQS_NUM 32 + ++#define EN7528_HOST_MODE 0x00804201 ++#define EN7528_LINKUP_REG 0x50 ++#define EN7528_RC0_LINKUP BIT(1) ++#define EN7528_RC1_LINKUP BIT(2) ++ + #define PCIE_AHB_TRANS_BASE0_L 0x438 + #define PCIE_AHB_TRANS_BASE0_H 0x43c + #define AHB2PCIE_SIZE(x) ((x) & GENMASK(4, 0)) +@@ -750,6 +756,86 @@ static int mtk_pcie_startup_port_v2(stru + return 0; + } + ++static int mtk_pcie_startup_port_en7528(struct mtk_pcie_port *port) ++{ ++ struct mtk_pcie *pcie = port->pcie; ++ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); ++ struct resource *mem = NULL; ++ struct resource_entry *entry; ++ u32 val, link_mask; ++ int err; ++ ++ entry = resource_list_first_type(&host->windows, IORESOURCE_MEM); ++ if (entry) ++ mem = entry->res; ++ if (!mem) ++ return -EINVAL; ++ ++ if (!pcie->cfg) { ++ dev_err(pcie->dev, "EN7528: pciecfg syscon not available\n"); ++ return -EINVAL; ++ } ++ ++ /* Assert all reset signals */ ++ writel(0, port->base + PCIE_RST_CTRL); ++ ++ /* ++ * Enable PCIe link down reset, if link status changed from link up to ++ * link down, this will reset MAC control registers and configuration ++ * space. ++ */ ++ writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL); ++ ++ /* ++ * Described in PCIe CEM specification sections 2.2 (PERST# Signal) and ++ * 2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# ++ * should be delayed 100ms (TPVPERL) for the power and clock to become ++ * stable. ++ */ ++ msleep(100); ++ ++ /* De-assert PHY, PE, PIPE, MAC and configuration reset */ ++ val = readl(port->base + PCIE_RST_CTRL); ++ val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB | ++ PCIE_MAC_SRSTB | PCIE_CRSTB; ++ writel(val, port->base + PCIE_RST_CTRL); ++ ++ writel(PCIE_CLASS_CODE | PCIE_REVISION_ID, ++ port->base + PCIE_CONF_REV_CLASS); ++ writel(EN7528_HOST_MODE, port->base); ++ ++ link_mask = (port->slot == 0) ? EN7528_RC0_LINKUP : EN7528_RC1_LINKUP; ++ ++ /* 100ms timeout value should be enough for Gen1/2 training */ ++ err = regmap_read_poll_timeout(pcie->cfg, EN7528_LINKUP_REG, val, ++ !!(val & link_mask), 20, ++ 100 * USEC_PER_MSEC); ++ if (err) { ++ dev_err(pcie->dev, "EN7528: port%d link timeout\n", port->slot); ++ return -ETIMEDOUT; ++ } ++ ++ /* Set INTx mask */ ++ val = readl(port->base + PCIE_INT_MASK); ++ val &= ~INTX_MASK; ++ writel(val, port->base + PCIE_INT_MASK); ++ ++ if (IS_ENABLED(CONFIG_PCI_MSI)) ++ mtk_pcie_enable_msi(port); ++ ++ /* Set AHB to PCIe translation windows */ ++ val = lower_32_bits(mem->start) | ++ AHB2PCIE_SIZE(fls(resource_size(mem))); ++ writel(val, port->base + PCIE_AHB_TRANS_BASE0_L); ++ ++ val = upper_32_bits(mem->start); ++ writel(val, port->base + PCIE_AHB_TRANS_BASE0_H); ++ ++ writel(WIN_ENABLE, port->base + PCIE_AXI_WINDOW0); ++ ++ return 0; ++} ++ + static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus, + unsigned int devfn, int where) + { +@@ -1116,6 +1202,20 @@ static int mtk_pcie_probe(struct platfor + if (err) + goto put_resources; + ++ /* Retrain Gen1 links to reach Gen2 where supported */ ++ if (pcie->soc->startup == mtk_pcie_startup_port_en7528) { ++ struct pci_bus *bus = host->bus; ++ struct pci_dev *rc = NULL; ++ ++ while ((rc = pci_get_class(PCI_CLASS_BRIDGE_PCI << 8, rc))) { ++ if (rc->bus != bus) ++ continue; ++ if (!pcie_retrain_link(rc, true)) ++ dev_info(dev, "port%d link retrained\n", ++ PCI_SLOT(rc->devfn)); ++ } ++ } ++ + return 0; + + put_resources: +@@ -1225,12 +1325,19 @@ static const struct mtk_pcie_soc mtk_pci + .setup_irq = mtk_pcie_setup_irq, + }; + ++static const struct mtk_pcie_soc mtk_pcie_soc_en7528 = { ++ .ops = &mtk_pcie_ops_v2, ++ .startup = mtk_pcie_startup_port_en7528, ++ .setup_irq = mtk_pcie_setup_irq, ++}; ++ + static const struct of_device_id mtk_pcie_ids[] = { + { .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 }, + { .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 }, + { .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_mt2712 }, + { .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_mt7622 }, + { .compatible = "mediatek,mt7629-pcie", .data = &mtk_pcie_soc_mt7629 }, ++ { .compatible = "econet,en7528-pcie", .data = &mtk_pcie_soc_en7528 }, + {}, + }; + MODULE_DEVICE_TABLE(of, mtk_pcie_ids); +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -82,6 +82,17 @@ config PHY_AIROHA_PCIE + This driver create the basic PHY instance and provides initialize + callback for PCIe GEN3 port. + ++config PHY_EN7528_PCIE ++ tristate "EcoNet EN7528 PCIe PHY Driver" ++ depends on ECONET || COMPILE_TEST ++ depends on OF ++ select GENERIC_PHY ++ select REGMAP_MMIO ++ help ++ Say Y here to add support for EcoNet EN7528 PCIe PHY driver. ++ This driver provides PHY initialization for the two PCIe ports ++ on EN7528 SoC. ++ + source "drivers/phy/allwinner/Kconfig" + source "drivers/phy/amlogic/Kconfig" + source "drivers/phy/broadcom/Kconfig" +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_PHY_XGENE) += phy-xgene.o + obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o + obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o + obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o ++obj-$(CONFIG_PHY_EN7528_PCIE) += phy-en7528-pcie.o + obj-y += allwinner/ \ + amlogic/ \ + broadcom/ \ +--- /dev/null ++++ b/drivers/phy/phy-en7528-pcie.c +@@ -0,0 +1,155 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (C) 2026 Ahmed Naseef ++ * ++ * EcoNet EN7528 PCIe PHY Driver ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct en7528_pcie_phy_op { ++ u32 reg; ++ u32 mask; ++ u32 val; ++}; ++ ++struct en7528_pcie_phy { ++ struct regmap *regmap; ++ const struct en7528_pcie_phy_op *data; ++}; ++ ++/* Port 0 PHY: set LCDDS_CLK_PH_INV for PLL operation */ ++static const struct en7528_pcie_phy_op en7528_phy_port0[] = { ++ { ++ .reg = 0x4a0, ++ .mask = BIT(5), ++ .val = BIT(5), ++ }, ++ { /* sentinel */ } ++}; ++ ++/* Port 1 PHY: Rx impedance tuning, target R -5 Ohm */ ++static const struct en7528_pcie_phy_op en7528_phy_port1[] = { ++ { ++ .reg = 0xb2c, ++ .mask = GENMASK(13, 12), ++ .val = BIT(12), ++ }, ++ { /* sentinel */ } ++}; ++ ++/* EN751221 Port 1 PHY */ ++static const struct en7528_pcie_phy_op en751221_phy_port1[] = { ++ /* Rx Detection Timing for 7512 E1, 16*8 clock cycles */ ++ { ++ .reg = 0xa28, ++ .mask = GENMASK(17, 9), ++ .val = 16 << 9, ++ }, ++ /* Same for different power mode */ ++ { ++ .reg = 0xa2c, ++ .mask = GENMASK(8, 0), ++ .val = 16, ++ }, ++ { /* sentinel */ } ++}; ++ ++static int en7528_pcie_phy_init(struct phy *phy) ++{ ++ struct en7528_pcie_phy *ephy = phy_get_drvdata(phy); ++ const struct en7528_pcie_phy_op *data = ephy->data; ++ int i, ret; ++ ++ for (i = 0; data[i].mask || data[i].val; i++) { ++ if (i) ++ usleep_range(1000, 2000); ++ ++ ret = regmap_update_bits(ephy->regmap, data[i].reg, ++ data[i].mask, data[i].val); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static const struct phy_ops en7528_pcie_phy_ops = { ++ .init = en7528_pcie_phy_init, ++ .owner = THIS_MODULE, ++}; ++ ++static int en7528_pcie_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ const struct en7528_pcie_phy_op *data; ++ struct regmap_config regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++ }; ++ struct phy_provider *provider; ++ struct en7528_pcie_phy *ephy; ++ void __iomem *base; ++ struct phy *phy; ++ int i; ++ ++ data = of_device_get_match_data(dev); ++ if (!data) ++ return -EINVAL; ++ ++ ephy = devm_kzalloc(dev, sizeof(*ephy), GFP_KERNEL); ++ if (!ephy) ++ return -ENOMEM; ++ ++ ephy->data = data; ++ ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ for (i = 0; data[i].mask || data[i].val; i++) ++ if (data[i].reg > regmap_config.max_register) ++ regmap_config.max_register = data[i].reg; ++ ++ ephy->regmap = devm_regmap_init_mmio(dev, base, ®map_config); ++ if (IS_ERR(ephy->regmap)) ++ return PTR_ERR(ephy->regmap); ++ ++ phy = devm_phy_create(dev, dev->of_node, &en7528_pcie_phy_ops); ++ if (IS_ERR(phy)) ++ return PTR_ERR(phy); ++ ++ phy_set_drvdata(phy, ephy); ++ ++ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(provider); ++} ++ ++static const struct of_device_id en7528_pcie_phy_ids[] = { ++ { .compatible = "econet,en7528-pcie-phy0", .data = en7528_phy_port0 }, ++ { .compatible = "econet,en7528-pcie-phy1", .data = en7528_phy_port1 }, ++ { .compatible = "econet,en751221-pcie-phy0", .data = en7528_phy_port0 }, ++ { .compatible = "econet,en751221-pcie-phy1", .data = en751221_phy_port1 }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, en7528_pcie_phy_ids); ++ ++static struct platform_driver en7528_pcie_phy_driver = { ++ .probe = en7528_pcie_phy_probe, ++ .driver = { ++ .name = "en7528-pcie-phy", ++ .of_match_table = en7528_pcie_phy_ids, ++ }, ++}; ++module_platform_driver(en7528_pcie_phy_driver); ++ ++MODULE_AUTHOR("Ahmed Naseef "); ++MODULE_DESCRIPTION("EcoNet EN7528 PCIe PHY driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch b/target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch new file mode 100644 index 0000000000..872843549d --- /dev/null +++ b/target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch @@ -0,0 +1,38 @@ +Subject: [PATCH] PCI: Skip bridge window reads when window is not supported + +pci_read_bridge_io() and pci_read_bridge_mmio_pref() read bridge window +registers unconditionally. If the registers are hardwired to zero +(not implemented), both base and limit will be 0. Since (0 <= 0) is +true, a bogus window [mem 0x00000000-0x000fffff] or [io 0x0000-0x0fff] +gets created. + +pci_read_bridge_windows() already detects unsupported windows by +testing register writability and sets io_window/pref_window flags +accordingly. Check these flags at the start of pci_read_bridge_io() +and pci_read_bridge_mmio_pref() to skip reading registers when the +window is not supported. + +Suggested-by: Bjorn Helgaas +Signed-off-by: Ahmed Naseef +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -349,6 +349,9 @@ static void pci_read_bridge_io(struct pc + unsigned long io_mask, io_granularity, base, limit; + struct pci_bus_region region; + ++ if (!dev->io_window) ++ return; ++ + io_mask = PCI_IO_RANGE_MASK; + io_granularity = 0x1000; + if (dev->io_window_1k) { +@@ -410,6 +413,9 @@ static void pci_read_bridge_mmio_pref(st + pci_bus_addr_t base, limit; + struct pci_bus_region region; + ++ if (!dev->pref_window) ++ return; ++ + pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); + pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); + base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; diff --git a/target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch b/target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch new file mode 100644 index 0000000000..308703c630 --- /dev/null +++ b/target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch @@ -0,0 +1,358 @@ +From: Ahmed Naseef +Subject: phy: add EN7528 USB PHY driver + +Add USB PHY driver for EcoNet EN7528 SoC. + +Based on GPL vendor code at https://github.com/keenetic/kernel-49 +and the Airoha AN7581 USB PHY driver by Christian Marangi. + +Signed-off-by: Ahmed Naseef +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -93,6 +93,17 @@ config PHY_EN7528_PCIE + This driver provides PHY initialization for the two PCIe ports + on EN7528 SoC. + ++config PHY_EN7528_USB ++ tristate "EcoNet EN7528 USB PHY Driver" ++ depends on ECONET || COMPILE_TEST ++ depends on OF ++ select GENERIC_PHY ++ select REGMAP_MMIO ++ help ++ Say 'Y' here to add support for EcoNet EN7528 USB PHY driver. ++ This driver creates the basic PHY instance and provides ++ initialization callback for the USB port. ++ + source "drivers/phy/allwinner/Kconfig" + source "drivers/phy/amlogic/Kconfig" + source "drivers/phy/broadcom/Kconfig" +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -12,6 +12,7 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy- + obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o + obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o + obj-$(CONFIG_PHY_EN7528_PCIE) += phy-en7528-pcie.o ++obj-$(CONFIG_PHY_EN7528_USB) += phy-en7528-usb.o + obj-y += allwinner/ \ + amlogic/ \ + broadcom/ \ +--- /dev/null ++++ b/drivers/phy/phy-en7528-usb.c +@@ -0,0 +1,316 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * EcoNet EN7528 USB PHY driver ++ * ++ * Based on GPL vendor code at https://github.com/keenetic/kernel-49 ++ * and the Airoha AN7581 USB PHY driver by ++ * Christian Marangi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Frequency Meter registers (shared across ports) */ ++#define EN7528_USB_PHY_FMCR0 0x100 ++#define EN7528_USB_PHY_MONCLK_SEL GENMASK(27, 26) ++#define EN7528_USB_PHY_FREQDET_EN BIT(24) ++#define EN7528_USB_PHY_CYCLECNT GENMASK(23, 0) ++#define EN7528_USB_PHY_FMMONR0 0x10c ++#define EN7528_USB_PHY_FMMONR1 0x110 ++#define EN7528_USB_PHY_FRCK_EN BIT(8) ++ ++/* U2 PHY port bases */ ++#define EN7528_USB_PHY_U2_P0_BASE 0x300 ++#define EN7528_USB_PHY_U2_P1_BASE 0x1300 ++#define EN7528_USB_PHY_NUM_U2_PORTS 2 ++ ++/* U2 PHY register offsets (relative to port base) */ ++#define EN7528_USB_PHY_ACR0 0x10 ++#define EN7528_USB_PHY_HSTX_SRCAL_EN BIT(23) ++#define EN7528_USB_PHY_HSTX_SRCTRL GENMASK(18, 16) ++#define EN7528_USB_PHY_ACR3 0x1c ++#define EN7528_USB_PHY_ACR3_ENABLE 0xC0240000 ++ ++/* U3 PHYA registers (base at +0xb00) */ ++#define EN7528_USB_PHY_U3_PHYA_REG11 0xb2c ++#define EN7528_USB_PHY_RX_IMPSEL GENMASK(13, 12) ++ ++#define EN7528_USB_PHY_FM_DET_CYCLE_CNT 1024 ++#define EN7528_USB_PHY_REF_CK 20 /* MHz */ ++#define EN7528_USB_PHY_SR_COEF 28 ++#define EN7528_USB_PHY_SR_COEF_DIVISOR 1000 ++#define EN7528_USB_PHY_DEFAULT_SR 4 ++ ++#define EN7528_USB_PHY_FREQDET_SLEEP 1000 /* 1ms */ ++#define EN7528_USB_PHY_FREQDET_TIMEOUT (EN7528_USB_PHY_FREQDET_SLEEP * 10) ++ ++static const unsigned int en7528_u2_port_bases[EN7528_USB_PHY_NUM_U2_PORTS] = { ++ EN7528_USB_PHY_U2_P0_BASE, ++ EN7528_USB_PHY_U2_P1_BASE, ++}; ++ ++struct en7528_usb_phy_instance { ++ struct phy *phy; ++ u32 type; ++}; ++ ++enum en7528_usb_phy_type { ++ EN7528_PHY_USB2, ++ EN7528_PHY_USB3, ++ ++ EN7528_PHY_USB_MAX, ++}; ++ ++struct en7528_usb_phy_priv { ++ struct device *dev; ++ struct regmap *regmap; ++ ++ struct en7528_usb_phy_instance *phys[EN7528_PHY_USB_MAX]; ++}; ++ ++static void en7528_usb_phy_slew_rate_calibration(struct en7528_usb_phy_priv *priv, ++ unsigned int port_id, ++ unsigned int port_base) ++{ ++ unsigned int acr0 = port_base + EN7528_USB_PHY_ACR0; ++ u32 fm_out; ++ u32 srctrl; ++ ++ /* Enable HS TX SR calibration */ ++ regmap_set_bits(priv->regmap, acr0, ++ EN7528_USB_PHY_HSTX_SRCAL_EN); ++ ++ usleep_range(1000, 1500); ++ ++ /* Enable free run clock */ ++ regmap_set_bits(priv->regmap, EN7528_USB_PHY_FMMONR1, ++ EN7528_USB_PHY_FRCK_EN); ++ ++ /* Select monitor clock: port 0 = MONCLK_SEL 0, port 1 = MONCLK_SEL 1 */ ++ regmap_update_bits(priv->regmap, EN7528_USB_PHY_FMCR0, ++ EN7528_USB_PHY_MONCLK_SEL, ++ FIELD_PREP(EN7528_USB_PHY_MONCLK_SEL, port_id)); ++ ++ /* Set cycle count */ ++ regmap_update_bits(priv->regmap, EN7528_USB_PHY_FMCR0, ++ EN7528_USB_PHY_CYCLECNT, ++ FIELD_PREP(EN7528_USB_PHY_CYCLECNT, ++ EN7528_USB_PHY_FM_DET_CYCLE_CNT)); ++ ++ /* Enable frequency meter */ ++ regmap_set_bits(priv->regmap, EN7528_USB_PHY_FMCR0, ++ EN7528_USB_PHY_FREQDET_EN); ++ ++ /* Timeout can happen and we will apply default value at the end */ ++ (void)regmap_read_poll_timeout(priv->regmap, EN7528_USB_PHY_FMMONR0, ++ fm_out, fm_out, ++ EN7528_USB_PHY_FREQDET_SLEEP, ++ EN7528_USB_PHY_FREQDET_TIMEOUT); ++ ++ /* Disable frequency meter */ ++ regmap_clear_bits(priv->regmap, EN7528_USB_PHY_FMCR0, ++ EN7528_USB_PHY_FREQDET_EN); ++ ++ /* Disable free run clock */ ++ regmap_clear_bits(priv->regmap, EN7528_USB_PHY_FMMONR1, ++ EN7528_USB_PHY_FRCK_EN); ++ ++ /* Disable HS TX SR calibration */ ++ regmap_clear_bits(priv->regmap, acr0, ++ EN7528_USB_PHY_HSTX_SRCAL_EN); ++ ++ usleep_range(1000, 1500); ++ ++ if (!fm_out) { ++ srctrl = EN7528_USB_PHY_DEFAULT_SR; ++ dev_err(priv->dev, "port%u: frequency not detected, using default SR calibration.\n", ++ port_id); ++ } else { ++ /* (1024 / FM_OUT) * REF_CK * SR_COEF */ ++ srctrl = EN7528_USB_PHY_REF_CK * EN7528_USB_PHY_SR_COEF; ++ srctrl = (srctrl * EN7528_USB_PHY_FM_DET_CYCLE_CNT) / fm_out; ++ srctrl = DIV_ROUND_CLOSEST(srctrl, EN7528_USB_PHY_SR_COEF_DIVISOR); ++ dev_dbg(priv->dev, "port%u: SR calibration applied: %x\n", ++ port_id, srctrl); ++ } ++ ++ regmap_update_bits(priv->regmap, acr0, ++ EN7528_USB_PHY_HSTX_SRCTRL, ++ FIELD_PREP(EN7528_USB_PHY_HSTX_SRCTRL, srctrl)); ++} ++ ++static int en7528_usb_phy_init(struct phy *phy) ++{ ++ struct en7528_usb_phy_instance *instance = phy_get_drvdata(phy); ++ struct en7528_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent); ++ unsigned int i; ++ ++ switch (instance->type) { ++ case PHY_TYPE_USB2: ++ /* Enable both U2 PHY ports before calibration */ ++ for (i = 0; i < EN7528_USB_PHY_NUM_U2_PORTS; i++) ++ regmap_write(priv->regmap, ++ en7528_u2_port_bases[i] + EN7528_USB_PHY_ACR3, ++ EN7528_USB_PHY_ACR3_ENABLE); ++ break; ++ case PHY_TYPE_USB3: ++ /* Combo PHY Rx R mean value too high, tune -5 Ohm */ ++ regmap_update_bits(priv->regmap, ++ EN7528_USB_PHY_U3_PHYA_REG11, ++ EN7528_USB_PHY_RX_IMPSEL, ++ FIELD_PREP(EN7528_USB_PHY_RX_IMPSEL, 0x1)); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int en7528_usb_phy_power_on(struct phy *phy) ++{ ++ struct en7528_usb_phy_instance *instance = phy_get_drvdata(phy); ++ struct en7528_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent); ++ unsigned int i; ++ ++ if (instance->type != PHY_TYPE_USB2) ++ return 0; ++ ++ /* Calibrate slew rate for both U2 PHY ports */ ++ for (i = 0; i < EN7528_USB_PHY_NUM_U2_PORTS; i++) ++ en7528_usb_phy_slew_rate_calibration(priv, i, ++ en7528_u2_port_bases[i]); ++ ++ return 0; ++} ++ ++static const struct phy_ops en7528_usb_phy_ops = { ++ .init = en7528_usb_phy_init, ++ .power_on = en7528_usb_phy_power_on, ++ .owner = THIS_MODULE, ++}; ++ ++static struct phy *en7528_usb_phy_xlate(struct device *dev, ++ const struct of_phandle_args *args) ++{ ++ struct en7528_usb_phy_priv *priv = dev_get_drvdata(dev); ++ struct en7528_usb_phy_instance *instance = NULL; ++ unsigned int index, phy_type; ++ ++ if (args->args_count != 1) { ++ dev_err(dev, "invalid number of cells in 'phy' property\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ phy_type = args->args[0]; ++ if (!(phy_type == PHY_TYPE_USB2 || phy_type == PHY_TYPE_USB3)) { ++ dev_err(dev, "unsupported device type: %d\n", phy_type); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ for (index = 0; index < EN7528_PHY_USB_MAX; index++) ++ if (priv->phys[index] && ++ phy_type == priv->phys[index]->type) { ++ instance = priv->phys[index]; ++ break; ++ } ++ ++ if (!instance) { ++ dev_err(dev, "failed to find appropriate phy\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ return instance->phy; ++} ++ ++static const struct regmap_config en7528_usb_phy_regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .max_register = EN7528_USB_PHY_U2_P1_BASE + EN7528_USB_PHY_ACR3, ++}; ++ ++static int en7528_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct en7528_usb_phy_priv *priv; ++ struct device *dev = &pdev->dev; ++ unsigned int index; ++ void *base; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dev = dev; ++ ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ priv->regmap = devm_regmap_init_mmio(dev, base, ++ &en7528_usb_phy_regmap_config); ++ if (IS_ERR(priv->regmap)) ++ return PTR_ERR(priv->regmap); ++ ++ platform_set_drvdata(pdev, priv); ++ ++ for (index = 0; index < EN7528_PHY_USB_MAX; index++) { ++ struct en7528_usb_phy_instance *instance; ++ enum en7528_usb_phy_type phy_type; ++ ++ switch (index) { ++ case EN7528_PHY_USB2: ++ phy_type = PHY_TYPE_USB2; ++ break; ++ case EN7528_PHY_USB3: ++ phy_type = PHY_TYPE_USB3; ++ break; ++ default: ++ continue; ++ } ++ ++ instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); ++ if (!instance) ++ return -ENOMEM; ++ ++ instance->type = phy_type; ++ priv->phys[index] = instance; ++ ++ instance->phy = devm_phy_create(dev, NULL, &en7528_usb_phy_ops); ++ if (IS_ERR(instance->phy)) ++ return dev_err_probe(dev, PTR_ERR(instance->phy), ++ "failed to create phy\n"); ++ ++ phy_set_drvdata(instance->phy, instance); ++ } ++ ++ phy_provider = devm_of_phy_provider_register(dev, ++ en7528_usb_phy_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id en7528_usb_phy_match[] = { ++ { .compatible = "econet,en7528-usb-phy" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, en7528_usb_phy_match); ++ ++static struct platform_driver en7528_usb_phy_driver = { ++ .probe = en7528_usb_phy_probe, ++ .driver = { ++ .name = "en7528-usb-phy", ++ .of_match_table = en7528_usb_phy_match, ++ }, ++}; ++ ++module_platform_driver(en7528_usb_phy_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("EcoNet EN7528 USB PHY driver"); diff --git a/target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch b/target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch new file mode 100644 index 0000000000..78e5ca5d4c --- /dev/null +++ b/target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch @@ -0,0 +1,58 @@ +From: Ahmed Naseef +Subject: usb: xhci-mtk: add EN7528 LTSSM timing quirk + +EN7528 needs LTSSM Timing Parameter 5 configured to fix +TD 6.5 compliance test failures. + +Based on GPL vendor code: +https://github.com/keenetic/kernel-49/commit/ee0e0b7cf28c208cd5b892ea96180ffae0de9b7f + +Signed-off-by: Ahmed Naseef +--- a/drivers/usb/host/xhci-mtk.c ++++ b/drivers/usb/host/xhci-mtk.c +@@ -80,6 +80,8 @@ + #define SS_GEN2_EOF_CFG 0x990 + #define SSG2EOF_OFFSET 0x3c + ++#define XHCI_MTK_LTSSM_TIMING_PARAMETER5 0x251c ++ + #define XSEOF_OFFSET_MASK GENMASK(11, 0) + + /* usb remote wakeup registers in syscon */ +@@ -191,6 +193,18 @@ static void xhci_mtk_rxfifo_depth_set(st + writel(value, hcd->regs + HSCH_CFG1); + } + ++/* EN7528: fix TD 6.5 compliance test failure */ ++static void xhci_mtk_ltssm_quirk(struct xhci_hcd_mtk *mtk) ++{ ++ struct device *dev = mtk->dev; ++ struct usb_hcd *hcd = mtk->hcd; ++ ++ if (!of_device_is_compatible(dev->of_node, "econet,en7528-xhci")) ++ return; ++ ++ writel(0x203e8, hcd->regs + XHCI_MTK_LTSSM_TIMING_PARAMETER5); ++} ++ + static void xhci_mtk_init_quirk(struct xhci_hcd_mtk *mtk) + { + /* workaround only for mt8195 */ +@@ -198,6 +212,9 @@ static void xhci_mtk_init_quirk(struct x + + /* workaround for SoCs using SSUSB about before IPM v1.6.0 */ + xhci_mtk_rxfifo_depth_set(mtk); ++ ++ /* EN7528 LTSSM timing fix */ ++ xhci_mtk_ltssm_quirk(mtk); + } + + static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) +@@ -846,6 +863,7 @@ static const struct dev_pm_ops xhci_mtk_ + static const struct of_device_id mtk_xhci_of_match[] = { + { .compatible = "mediatek,mt8173-xhci"}, + { .compatible = "mediatek,mt8195-xhci"}, ++ { .compatible = "econet,en7528-xhci"}, + { .compatible = "mediatek,mtk-xhci"}, + { }, + }; From 3644ab9fead898dec41518e702ccda32e370a1c3 Mon Sep 17 00:00:00 2001 From: Ahmed Naseef Date: Thu, 11 Jun 2026 18:19:00 +0400 Subject: [PATCH 012/228] econet: remove upstreamed patches for 6.18 Remove all patches that have already been upstreamed for kernel 6.18. The remaining v6.19/v6.19rc1 backports are kept, in sync with the airoha target these patches are shared with. Signed-off-by: Ahmed Naseef Link: https://github.com/openwrt/openwrt/pull/23755 Signed-off-by: Jonas Jelonek --- ...rrupt-controller-Add-EcoNet-EN751221.patch | 98 ----- ....16-irqchip-Add-EcoNet-EN751221-INTC.patch | 353 ------------------ ...-bindings-vendor-prefixes-Add-EcoNet.patch | 26 -- ...er-Add-EcoNet-EN751221-HPT-CPU-Timer.patch | 100 ----- ...-drivers-Add-EcoNet-Timer-HPT-driver.patch | 276 -------------- ...ngs-mips-Add-EcoNet-platform-binding.patch | 44 --- ...ips-Add-EcoNet-MIPS-platform-support.patch | 222 ----------- ...dings-vendor-prefixes-Add-SmartFiber.patch | 29 -- ...Net-DTS-with-EN751221-and-SmartFiber.patch | 149 -------- ...entry-for-newly-added-EcoNet-platfor.patch | 38 -- ...t-Fix-incorrect-Kconfig-dependencies.patch | 32 -- ...en7581_reset_register-in-en7581_clk_.patch | 174 --------- ...7523-map-io-region-in-a-single-block.patch | 84 ----- ...3-Move-reset-delay-in-mtk_pcie_en758.patch | 42 --- ...k-clock-handling-for-different-clock.patch | 83 ---- ...en7523-Add-clock-for-eMMC-for-EN7581.patch | 41 -- ...k-airoha-Update-reg-mapping-for-EN75.patch | 74 ---- ...ck-drop-NUM_CLOCKS-define-for-EN7581.patch | 26 -- ...ngs-clock-add-ID-for-eMMC-for-EN7581.patch | 25 -- 19 files changed, 1916 deletions(-) delete mode 100644 target/linux/econet/patches-6.18/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch delete mode 100644 target/linux/econet/patches-6.18/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch delete mode 100644 target/linux/econet/patches-6.18/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch delete mode 100644 target/linux/econet/patches-6.18/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch delete mode 100644 target/linux/econet/patches-6.18/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch delete mode 100644 target/linux/econet/patches-6.18/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch delete mode 100644 target/linux/econet/patches-6.18/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch delete mode 100644 target/linux/econet/patches-6.18/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch delete mode 100644 target/linux/econet/patches-6.18/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch delete mode 100644 target/linux/econet/patches-6.18/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch delete mode 100644 target/linux/econet/patches-6.18/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch delete mode 100644 target/linux/econet/patches-6.18/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch delete mode 100644 target/linux/econet/patches-6.18/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch delete mode 100644 target/linux/econet/patches-6.18/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch delete mode 100644 target/linux/econet/patches-6.18/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch delete mode 100644 target/linux/econet/patches-6.18/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch delete mode 100644 target/linux/econet/patches-6.18/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch delete mode 100644 target/linux/econet/patches-6.18/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch delete mode 100644 target/linux/econet/patches-6.18/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch diff --git a/target/linux/econet/patches-6.18/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch b/target/linux/econet/patches-6.18/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch deleted file mode 100644 index c146af679a..0000000000 --- a/target/linux/econet/patches-6.18/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 9773c540441c6ae15aefb49e67142e94369dbbc0 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Sun, 30 Mar 2025 17:02:58 +0000 -Subject: [PATCH] dt-bindings: interrupt-controller: Add EcoNet EN751221 INTC - -Document the device tree binding for the interrupt controller in the -EcoNet EN751221 MIPS SoC. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Gleixner -Reviewed-by: Rob Herring (Arm) -Link: https://lore.kernel.org/all/20250330170306.2584136-3-cjd@cjdns.fr ---- - .../econet,en751221-intc.yaml | 78 +++++++++++++++++++ - 1 file changed, 78 insertions(+) - create mode 100644 Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml -@@ -0,0 +1,78 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/interrupt-controller/econet,en751221-intc.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet EN751221 Interrupt Controller -+ -+maintainers: -+ - Caleb James DeLisle -+ -+description: -+ The EcoNet EN751221 Interrupt Controller is a simple interrupt controller -+ designed for the MIPS 34Kc MT SMP processor with 2 VPEs. Each interrupt can -+ be routed to either VPE but not both, so to support per-CPU interrupts, a -+ secondary IRQ number is allocated to control masking/unmasking on VPE#1. For -+ lack of a better term we call these "shadow interrupts". The assignment of -+ shadow interrupts is defined by the SoC integrator when wiring the interrupt -+ lines, so they are configurable in the device tree. -+ -+allOf: -+ - $ref: /schemas/interrupt-controller.yaml# -+ -+properties: -+ compatible: -+ const: econet,en751221-intc -+ -+ reg: -+ maxItems: 1 -+ -+ "#interrupt-cells": -+ const: 1 -+ -+ interrupt-controller: true -+ -+ interrupts: -+ maxItems: 1 -+ description: Interrupt line connecting this controller to its parent. -+ -+ econet,shadow-interrupts: -+ $ref: /schemas/types.yaml#/definitions/uint32-matrix -+ description: -+ An array of interrupt number pairs where each pair represents a shadow -+ interrupt relationship. The first number in each pair is the primary IRQ, -+ and the second is its shadow IRQ used for VPE#1 control. For example, -+ <8 3> means IRQ 8 is shadowed by IRQ 3, so IRQ 3 cannot be mapped, but -+ when VPE#1 requests IRQ 8, it will manipulate the IRQ 3 mask bit. -+ minItems: 1 -+ maxItems: 20 -+ items: -+ items: -+ - description: primary per-CPU IRQ -+ - description: shadow IRQ number -+ -+required: -+ - compatible -+ - reg -+ - interrupt-controller -+ - "#interrupt-cells" -+ - interrupts -+ -+additionalProperties: false -+ -+examples: -+ - | -+ interrupt-controller@1fb40000 { -+ compatible = "econet,en751221-intc"; -+ reg = <0x1fb40000 0x100>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ -+ interrupt-parent = <&cpuintc>; -+ interrupts = <2>; -+ -+ econet,shadow-interrupts = <7 2>, <8 3>, <13 12>, <30 29>; -+ }; -+... diff --git a/target/linux/econet/patches-6.18/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch b/target/linux/econet/patches-6.18/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch deleted file mode 100644 index d3f57f4e7f..0000000000 --- a/target/linux/econet/patches-6.18/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch +++ /dev/null @@ -1,353 +0,0 @@ -From 1902a59cf5f9d8b99ecf0cb8f122cb00ef7a3f13 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Sun, 30 Mar 2025 17:02:59 +0000 -Subject: [PATCH] irqchip: Add EcoNet EN751221 INTC - -Add a driver for the interrupt controller in the EcoNet EN751221 MIPS SoC. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Gleixner -Link: https://lore.kernel.org/all/20250330170306.2584136-4-cjd@cjdns.fr ---- - drivers/irqchip/Kconfig | 5 + - drivers/irqchip/Makefile | 1 + - drivers/irqchip/irq-econet-en751221.c | 309 ++++++++++++++++++++++++++ - 3 files changed, 315 insertions(+) - create mode 100644 drivers/irqchip/irq-econet-en751221.c - ---- a/drivers/irqchip/Kconfig -+++ b/drivers/irqchip/Kconfig -@@ -148,6 +148,11 @@ config DW_APB_ICTL - select GENERIC_IRQ_CHIP - select IRQ_DOMAIN_HIERARCHY - -+config ECONET_EN751221_INTC -+ bool -+ select GENERIC_IRQ_CHIP -+ select IRQ_DOMAIN -+ - config FARADAY_FTINTC010 - bool - select IRQ_DOMAIN ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -10,6 +10,7 @@ obj-$(CONFIG_ARCH_BCM2835) += irq-bcm28 - obj-$(CONFIG_ARCH_ACTIONS) += irq-owl-sirq.o - obj-$(CONFIG_DAVINCI_CP_INTC) += irq-davinci-cp-intc.o - obj-$(CONFIG_EXYNOS_IRQ_COMBINER) += exynos-combiner.o -+obj-$(CONFIG_ECONET_EN751221_INTC) += irq-econet-en751221.o - obj-$(CONFIG_FARADAY_FTINTC010) += irq-ftintc010.o - obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o - obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o ---- /dev/null -+++ b/drivers/irqchip/irq-econet-en751221.c -@@ -0,0 +1,309 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * EN751221 Interrupt Controller Driver. -+ * -+ * The EcoNet EN751221 Interrupt Controller is a simple interrupt controller -+ * designed for the MIPS 34Kc MT SMP processor with 2 VPEs. Each interrupt can -+ * be routed to either VPE but not both, so to support per-CPU interrupts, a -+ * secondary IRQ number is allocated to control masking/unmasking on VPE#1. In -+ * this driver, these are called "shadow interrupts". The assignment of shadow -+ * interrupts is defined by the SoC integrator when wiring the interrupt lines, -+ * so they are configurable in the device tree. -+ * -+ * If an interrupt (say 30) needs per-CPU capability, the SoC integrator -+ * allocates another IRQ number (say 29) to be its shadow. The device tree -+ * reflects this by adding the pair <30 29> to the "econet,shadow-interrupts" -+ * property. -+ * -+ * When VPE#1 requests IRQ 30, the driver manipulates the mask bit for IRQ 29, -+ * telling the hardware to mask VPE#1's view of IRQ 30. -+ * -+ * Copyright (C) 2025 Caleb James DeLisle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define IRQ_COUNT 40 -+ -+#define NOT_PERCPU 0xff -+#define IS_SHADOW 0xfe -+ -+#define REG_MASK0 0x04 -+#define REG_MASK1 0x50 -+#define REG_PENDING0 0x08 -+#define REG_PENDING1 0x54 -+ -+/** -+ * @membase: Base address of the interrupt controller registers -+ * @interrupt_shadows: Array of all interrupts, for each value, -+ * - NOT_PERCPU: This interrupt is not per-cpu, so it has no shadow -+ * - IS_SHADOW: This interrupt is a shadow of another per-cpu interrupt -+ * - else: This is a per-cpu interrupt whose shadow is the value -+ */ -+static struct { -+ void __iomem *membase; -+ u8 interrupt_shadows[IRQ_COUNT]; -+} econet_intc __ro_after_init; -+ -+static DEFINE_RAW_SPINLOCK(irq_lock); -+ -+/* IRQs must be disabled */ -+static void econet_wreg(u32 reg, u32 val, u32 mask) -+{ -+ u32 v; -+ -+ guard(raw_spinlock)(&irq_lock); -+ -+ v = ioread32(econet_intc.membase + reg); -+ v &= ~mask; -+ v |= val & mask; -+ iowrite32(v, econet_intc.membase + reg); -+} -+ -+/* IRQs must be disabled */ -+static void econet_chmask(u32 hwirq, bool unmask) -+{ -+ u32 reg, mask; -+ u8 shadow; -+ -+ /* -+ * If the IRQ is a shadow, it should never be manipulated directly. -+ * It should only be masked/unmasked as a result of the "real" per-cpu -+ * irq being manipulated by a thread running on VPE#1. -+ * If it is per-cpu (has a shadow), and we're on VPE#1, the shadow is what we mask. -+ * This is single processor only, so smp_processor_id() never exceeds 1. -+ */ -+ shadow = econet_intc.interrupt_shadows[hwirq]; -+ if (WARN_ON_ONCE(shadow == IS_SHADOW)) -+ return; -+ else if (shadow != NOT_PERCPU && smp_processor_id() == 1) -+ hwirq = shadow; -+ -+ if (hwirq >= 32) { -+ reg = REG_MASK1; -+ mask = BIT(hwirq - 32); -+ } else { -+ reg = REG_MASK0; -+ mask = BIT(hwirq); -+ } -+ -+ econet_wreg(reg, unmask ? mask : 0, mask); -+} -+ -+/* IRQs must be disabled */ -+static void econet_intc_mask(struct irq_data *d) -+{ -+ econet_chmask(d->hwirq, false); -+} -+ -+/* IRQs must be disabled */ -+static void econet_intc_unmask(struct irq_data *d) -+{ -+ econet_chmask(d->hwirq, true); -+} -+ -+static void econet_mask_all(void) -+{ -+ /* IRQs are generally disabled during init, but guarding here makes it non-obligatory. */ -+ guard(irqsave)(); -+ econet_wreg(REG_MASK0, 0, ~0); -+ econet_wreg(REG_MASK1, 0, ~0); -+} -+ -+static void econet_intc_handle_pending(struct irq_domain *d, u32 pending, u32 offset) -+{ -+ int hwirq; -+ -+ while (pending) { -+ hwirq = fls(pending) - 1; -+ generic_handle_domain_irq(d, hwirq + offset); -+ pending &= ~BIT(hwirq); -+ } -+} -+ -+static void econet_intc_from_parent(struct irq_desc *desc) -+{ -+ struct irq_chip *chip = irq_desc_get_chip(desc); -+ struct irq_domain *domain; -+ u32 pending0, pending1; -+ -+ chained_irq_enter(chip, desc); -+ -+ pending0 = ioread32(econet_intc.membase + REG_PENDING0); -+ pending1 = ioread32(econet_intc.membase + REG_PENDING1); -+ -+ if (unlikely(!(pending0 | pending1))) { -+ spurious_interrupt(); -+ } else { -+ domain = irq_desc_get_handler_data(desc); -+ econet_intc_handle_pending(domain, pending0, 0); -+ econet_intc_handle_pending(domain, pending1, 32); -+ } -+ -+ chained_irq_exit(chip, desc); -+} -+ -+static const struct irq_chip econet_irq_chip; -+ -+static int econet_intc_map(struct irq_domain *d, u32 irq, irq_hw_number_t hwirq) -+{ -+ int ret; -+ -+ if (hwirq >= IRQ_COUNT) { -+ pr_err("%s: hwirq %lu out of range\n", __func__, hwirq); -+ return -EINVAL; -+ } else if (econet_intc.interrupt_shadows[hwirq] == IS_SHADOW) { -+ pr_err("%s: can't map hwirq %lu, it is a shadow interrupt\n", __func__, hwirq); -+ return -EINVAL; -+ } -+ -+ if (econet_intc.interrupt_shadows[hwirq] == NOT_PERCPU) { -+ irq_set_chip_and_handler(irq, &econet_irq_chip, handle_level_irq); -+ } else { -+ irq_set_chip_and_handler(irq, &econet_irq_chip, handle_percpu_devid_irq); -+ ret = irq_set_percpu_devid(irq); -+ if (ret) -+ pr_warn("%s: Failed irq_set_percpu_devid for %u: %d\n", d->name, irq, ret); -+ } -+ -+ irq_set_chip_data(irq, NULL); -+ return 0; -+} -+ -+static const struct irq_chip econet_irq_chip = { -+ .name = "en751221-intc", -+ .irq_unmask = econet_intc_unmask, -+ .irq_mask = econet_intc_mask, -+ .irq_mask_ack = econet_intc_mask, -+}; -+ -+static const struct irq_domain_ops econet_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = econet_intc_map -+}; -+ -+static int __init get_shadow_interrupts(struct device_node *node) -+{ -+ const char *field = "econet,shadow-interrupts"; -+ int num_shadows; -+ -+ num_shadows = of_property_count_u32_elems(node, field); -+ -+ memset(econet_intc.interrupt_shadows, NOT_PERCPU, -+ sizeof(econet_intc.interrupt_shadows)); -+ -+ if (num_shadows <= 0) { -+ return 0; -+ } else if (num_shadows % 2) { -+ pr_err("%pOF: %s count is odd, ignoring\n", node, field); -+ return 0; -+ } -+ -+ u32 *shadows __free(kfree) = kmalloc_array(num_shadows, sizeof(u32), GFP_KERNEL); -+ if (!shadows) -+ return -ENOMEM; -+ -+ if (of_property_read_u32_array(node, field, shadows, num_shadows)) { -+ pr_err("%pOF: Failed to read %s\n", node, field); -+ return -EINVAL; -+ } -+ -+ for (int i = 0; i < num_shadows; i += 2) { -+ u32 shadow = shadows[i + 1]; -+ u32 target = shadows[i]; -+ -+ if (shadow > IRQ_COUNT) { -+ pr_err("%pOF: %s[%d] shadow(%d) out of range\n", -+ node, field, i + 1, shadow); -+ continue; -+ } -+ -+ if (target >= IRQ_COUNT) { -+ pr_err("%pOF: %s[%d] target(%d) out of range\n", node, field, i, target); -+ continue; -+ } -+ -+ if (econet_intc.interrupt_shadows[target] != NOT_PERCPU) { -+ pr_err("%pOF: %s[%d] target(%d) already has a shadow\n", -+ node, field, i, target); -+ continue; -+ } -+ -+ if (econet_intc.interrupt_shadows[shadow] != NOT_PERCPU) { -+ pr_err("%pOF: %s[%d] shadow(%d) already has a target\n", -+ node, field, i + 1, shadow); -+ continue; -+ } -+ -+ econet_intc.interrupt_shadows[target] = shadow; -+ econet_intc.interrupt_shadows[shadow] = IS_SHADOW; -+ } -+ -+ return 0; -+} -+ -+static int __init econet_intc_of_init(struct device_node *node, struct device_node *parent) -+{ -+ struct irq_domain *domain; -+ struct resource res; -+ int ret, irq; -+ -+ ret = get_shadow_interrupts(node); -+ if (ret) -+ return ret; -+ -+ irq = irq_of_parse_and_map(node, 0); -+ if (!irq) { -+ pr_err("%pOF: DT: Failed to get IRQ from 'interrupts'\n", node); -+ return -EINVAL; -+ } -+ -+ if (of_address_to_resource(node, 0, &res)) { -+ pr_err("%pOF: DT: Failed to get 'reg'\n", node); -+ ret = -EINVAL; -+ goto err_dispose_mapping; -+ } -+ -+ if (!request_mem_region(res.start, resource_size(&res), res.name)) { -+ pr_err("%pOF: Failed to request memory\n", node); -+ ret = -EBUSY; -+ goto err_dispose_mapping; -+ } -+ -+ econet_intc.membase = ioremap(res.start, resource_size(&res)); -+ if (!econet_intc.membase) { -+ pr_err("%pOF: Failed to remap membase\n", node); -+ ret = -ENOMEM; -+ goto err_release; -+ } -+ -+ econet_mask_all(); -+ -+ domain = irq_domain_add_linear(node, IRQ_COUNT, &econet_domain_ops, NULL); -+ if (!domain) { -+ pr_err("%pOF: Failed to add irqdomain\n", node); -+ ret = -ENOMEM; -+ goto err_unmap; -+ } -+ -+ irq_set_chained_handler_and_data(irq, econet_intc_from_parent, domain); -+ -+ return 0; -+ -+err_unmap: -+ iounmap(econet_intc.membase); -+err_release: -+ release_mem_region(res.start, resource_size(&res)); -+err_dispose_mapping: -+ irq_dispose_mapping(irq); -+ return ret; -+} -+ -+IRQCHIP_DECLARE(econet_en751221_intc, "econet,en751221-intc", econet_intc_of_init); diff --git a/target/linux/econet/patches-6.18/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch b/target/linux/econet/patches-6.18/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch deleted file mode 100644 index e2466782d1..0000000000 --- a/target/linux/econet/patches-6.18/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 9e0dd98654a528735d2b363d0dc73f7904108652 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Sun, 30 Mar 2025 17:02:57 +0000 -Subject: [PATCH] dt-bindings: vendor-prefixes: Add EcoNet - -Add the "econet" vendor prefix for SoC maker - -Signed-off-by: Caleb James DeLisle -Acked-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250330170306.2584136-2-cjd@cjdns.fr -Signed-off-by: Rob Herring (Arm) ---- - Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/Documentation/devicetree/bindings/vendor-prefixes.yaml -+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml -@@ -420,6 +420,8 @@ patternProperties: - description: EBV Elektronik - "^eckelmann,.*": - description: Eckelmann AG -+ "^econet,.*": -+ description: EcoNet (HK) Limited - "^edgeble,.*": - description: Edgeble AI Technologies Pvt. Ltd. - "^edimax,.*": diff --git a/target/linux/econet/patches-6.18/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch b/target/linux/econet/patches-6.18/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch deleted file mode 100644 index 92f8604ea2..0000000000 --- a/target/linux/econet/patches-6.18/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 30fddbd5325459102e448c9a26a1bc15ef563381 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:54 +0000 -Subject: [PATCH] dt-bindings: timer: Add EcoNet EN751221 "HPT" CPU Timer - -Add device tree bindings for the so-called high-precision timer (HPT) -in the EcoNet EN751221 SoC. - -Signed-off-by: Caleb James DeLisle -Reviewed-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250507134500.390547-2-cjd@cjdns.fr -Signed-off-by: Daniel Lezcano ---- - .../bindings/timer/econet,en751221-timer.yaml | 80 +++++++++++++++++++ - 1 file changed, 80 insertions(+) - create mode 100644 Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml -@@ -0,0 +1,80 @@ -+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/timer/econet,en751221-timer.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet EN751221 High Precision Timer (HPT) -+ -+maintainers: -+ - Caleb James DeLisle -+ -+description: -+ The EcoNet High Precision Timer (HPT) is a timer peripheral found in various -+ EcoNet SoCs, including the EN751221 and EN751627 families. It provides per-VPE -+ count/compare registers and a per-CPU control register, with a single interrupt -+ line using a percpu-devid interrupt mechanism. -+ -+properties: -+ compatible: -+ oneOf: -+ - const: econet,en751221-timer -+ - items: -+ - const: econet,en751627-timer -+ - const: econet,en751221-timer -+ -+ reg: -+ minItems: 1 -+ maxItems: 2 -+ -+ interrupts: -+ maxItems: 1 -+ description: A percpu-devid timer interrupt shared across CPUs. -+ -+ clocks: -+ maxItems: 1 -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ - clocks -+ -+allOf: -+ - if: -+ properties: -+ compatible: -+ contains: -+ const: econet,en751627-timer -+ then: -+ properties: -+ reg: -+ items: -+ - description: VPE timers 0 and 1 -+ - description: VPE timers 2 and 3 -+ else: -+ properties: -+ reg: -+ items: -+ - description: VPE timers 0 and 1 -+ -+additionalProperties: false -+ -+examples: -+ - | -+ timer@1fbf0400 { -+ compatible = "econet,en751627-timer", "econet,en751221-timer"; -+ reg = <0x1fbf0400 0x100>, <0x1fbe0000 0x100>; -+ interrupt-parent = <&intc>; -+ interrupts = <30>; -+ clocks = <&hpt_clock>; -+ }; -+ - | -+ timer@1fbf0400 { -+ compatible = "econet,en751221-timer"; -+ reg = <0x1fbe0400 0x100>; -+ interrupt-parent = <&intc>; -+ interrupts = <30>; -+ clocks = <&hpt_clock>; -+ }; -+... diff --git a/target/linux/econet/patches-6.18/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch b/target/linux/econet/patches-6.18/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch deleted file mode 100644 index dcd4bb15e3..0000000000 --- a/target/linux/econet/patches-6.18/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch +++ /dev/null @@ -1,276 +0,0 @@ -From 3b4c33ac87d0d11308f4445ecec2a124e2e77724 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:55 +0000 -Subject: [PATCH] clocksource/drivers: Add EcoNet Timer HPT driver - -Introduce a clocksource driver for the so-called high-precision timer (HPT) -in the EcoNet EN751221 and EN751627 MIPS SoCs. - -It's a 32 bit upward-counting one-shot timer which relies on the crystal so it -is unaffected by CPU power mode. On MIPS 34K devices (single core) there is -one timer, and on 1004K devices (dual core) there are two. - -Each timer has two sets of count/compare registers so that there is one for -each of the VPEs on the core. Because each core has 2 VPEs, register selection -takes the CPU number / 2 for the timer corrisponding to the core, then CPU -number % 2 for the register corrisponding to the VPE. - -These timers use a percpu-devid IRQ to route interrupts to the VPE which set -the event. - -Signed-off-by: Caleb James DeLisle -Link: https://lore.kernel.org/r/20250507134500.390547-3-cjd@cjdns.fr -Signed-off-by: Daniel Lezcano ---- - drivers/clocksource/Kconfig | 8 + - drivers/clocksource/Makefile | 1 + - drivers/clocksource/timer-econet-en751221.c | 216 ++++++++++++++++++++ - 3 files changed, 225 insertions(+) - create mode 100644 drivers/clocksource/timer-econet-en751221.c - ---- a/drivers/clocksource/Kconfig -+++ b/drivers/clocksource/Kconfig -@@ -73,6 +73,14 @@ config DW_APB_TIMER_OF - select DW_APB_TIMER - select TIMER_OF - -+config ECONET_EN751221_TIMER -+ bool "EcoNet EN751221 High Precision Timer" if COMPILE_TEST -+ depends on HAS_IOMEM -+ select CLKSRC_MMIO -+ select TIMER_OF -+ help -+ Support for CPU timer found on EcoNet MIPS based SoCs. -+ - config FTTMR010_TIMER - bool "Faraday Technology timer driver" if COMPILE_TEST - depends on HAS_IOMEM ---- a/drivers/clocksource/Makefile -+++ b/drivers/clocksource/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_CLKBLD_I8253) += i8253.o - obj-$(CONFIG_CLKSRC_MMIO) += mmio.o - obj-$(CONFIG_DAVINCI_TIMER) += timer-davinci.o - obj-$(CONFIG_DIGICOLOR_TIMER) += timer-digicolor.o -+obj-$(CONFIG_ECONET_EN751221_TIMER) += timer-econet-en751221.o - obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o - obj-$(CONFIG_OMAP_DM_SYSTIMER) += timer-ti-dm-systimer.o - obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o ---- /dev/null -+++ b/drivers/clocksource/timer-econet-en751221.c -@@ -0,0 +1,216 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Timer present on EcoNet EN75xx MIPS based SoCs. -+ * -+ * Copyright (C) 2025 by Caleb James DeLisle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ECONET_BITS 32 -+#define ECONET_MIN_DELTA 0x00001000 -+#define ECONET_MAX_DELTA GENMASK(ECONET_BITS - 2, 0) -+/* 34Kc hardware has 1 block and 1004Kc has 2. */ -+#define ECONET_NUM_BLOCKS DIV_ROUND_UP(NR_CPUS, 2) -+ -+static struct { -+ void __iomem *membase[ECONET_NUM_BLOCKS]; -+ u32 freq_hz; -+} econet_timer __ro_after_init; -+ -+static DEFINE_PER_CPU(struct clock_event_device, econet_timer_pcpu); -+ -+/* Each memory block has 2 timers, the order of registers is: -+ * CTL, CMR0, CNT0, CMR1, CNT1 -+ */ -+static inline void __iomem *reg_ctl(u32 timer_n) -+{ -+ return econet_timer.membase[timer_n >> 1]; -+} -+ -+static inline void __iomem *reg_compare(u32 timer_n) -+{ -+ return econet_timer.membase[timer_n >> 1] + (timer_n & 1) * 0x08 + 0x04; -+} -+ -+static inline void __iomem *reg_count(u32 timer_n) -+{ -+ return econet_timer.membase[timer_n >> 1] + (timer_n & 1) * 0x08 + 0x08; -+} -+ -+static inline u32 ctl_bit_enabled(u32 timer_n) -+{ -+ return 1U << (timer_n & 1); -+} -+ -+static inline u32 ctl_bit_pending(u32 timer_n) -+{ -+ return 1U << ((timer_n & 1) + 16); -+} -+ -+static bool cevt_is_pending(int cpu_id) -+{ -+ return ioread32(reg_ctl(cpu_id)) & ctl_bit_pending(cpu_id); -+} -+ -+static irqreturn_t cevt_interrupt(int irq, void *dev_id) -+{ -+ struct clock_event_device *dev = this_cpu_ptr(&econet_timer_pcpu); -+ int cpu = cpumask_first(dev->cpumask); -+ -+ /* Each VPE has its own events, -+ * so this will only happen on spurious interrupt. -+ */ -+ if (!cevt_is_pending(cpu)) -+ return IRQ_NONE; -+ -+ iowrite32(ioread32(reg_count(cpu)), reg_compare(cpu)); -+ dev->event_handler(dev); -+ return IRQ_HANDLED; -+} -+ -+static int cevt_set_next_event(ulong delta, struct clock_event_device *dev) -+{ -+ u32 next; -+ int cpu; -+ -+ cpu = cpumask_first(dev->cpumask); -+ next = ioread32(reg_count(cpu)) + delta; -+ iowrite32(next, reg_compare(cpu)); -+ -+ if ((s32)(next - ioread32(reg_count(cpu))) < ECONET_MIN_DELTA / 2) -+ return -ETIME; -+ -+ return 0; -+} -+ -+static int cevt_init_cpu(uint cpu) -+{ -+ struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, cpu); -+ u32 reg; -+ -+ pr_debug("%s: Setting up clockevent for CPU %d\n", cd->name, cpu); -+ -+ reg = ioread32(reg_ctl(cpu)) | ctl_bit_enabled(cpu); -+ iowrite32(reg, reg_ctl(cpu)); -+ -+ enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); -+ -+ /* Do this last because it synchronously configures the timer */ -+ clockevents_config_and_register(cd, econet_timer.freq_hz, -+ ECONET_MIN_DELTA, ECONET_MAX_DELTA); -+ -+ return 0; -+} -+ -+static u64 notrace sched_clock_read(void) -+{ -+ /* Always read from clock zero no matter the CPU */ -+ return (u64)ioread32(reg_count(0)); -+} -+ -+/* Init */ -+ -+static void __init cevt_dev_init(uint cpu) -+{ -+ iowrite32(0, reg_count(cpu)); -+ iowrite32(U32_MAX, reg_compare(cpu)); -+} -+ -+static int __init cevt_init(struct device_node *np) -+{ -+ int i, irq, ret; -+ -+ irq = irq_of_parse_and_map(np, 0); -+ if (irq <= 0) { -+ pr_err("%pOFn: irq_of_parse_and_map failed", np); -+ return -EINVAL; -+ } -+ -+ ret = request_percpu_irq(irq, cevt_interrupt, np->name, &econet_timer_pcpu); -+ -+ if (ret < 0) { -+ pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, irq, ret); -+ goto err_unmap_irq; -+ } -+ -+ for_each_possible_cpu(i) { -+ struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i); -+ -+ cd->rating = 310, -+ cd->features = CLOCK_EVT_FEAT_ONESHOT | -+ CLOCK_EVT_FEAT_C3STOP | -+ CLOCK_EVT_FEAT_PERCPU; -+ cd->set_next_event = cevt_set_next_event; -+ cd->irq = irq; -+ cd->cpumask = cpumask_of(i); -+ cd->name = np->name; -+ -+ cevt_dev_init(i); -+ } -+ -+ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, -+ "clockevents/econet/timer:starting", -+ cevt_init_cpu, NULL); -+ return 0; -+ -+err_unmap_irq: -+ irq_dispose_mapping(irq); -+ return ret; -+} -+ -+static int __init timer_init(struct device_node *np) -+{ -+ int num_blocks = DIV_ROUND_UP(num_possible_cpus(), 2); -+ struct clk *clk; -+ int ret; -+ -+ clk = of_clk_get(np, 0); -+ if (IS_ERR(clk)) { -+ pr_err("%pOFn: Failed to get CPU clock from DT %ld\n", np, PTR_ERR(clk)); -+ return PTR_ERR(clk); -+ } -+ -+ econet_timer.freq_hz = clk_get_rate(clk); -+ -+ for (int i = 0; i < num_blocks; i++) { -+ econet_timer.membase[i] = of_iomap(np, i); -+ if (!econet_timer.membase[i]) { -+ pr_err("%pOFn: failed to map register [%d]\n", np, i); -+ return -ENXIO; -+ } -+ } -+ -+ /* For clocksource purposes always read clock zero, whatever the CPU */ -+ ret = clocksource_mmio_init(reg_count(0), np->name, -+ econet_timer.freq_hz, 301, ECONET_BITS, -+ clocksource_mmio_readl_up); -+ if (ret) { -+ pr_err("%pOFn: clocksource_mmio_init failed: %d", np, ret); -+ return ret; -+ } -+ -+ ret = cevt_init(np); -+ if (ret < 0) -+ return ret; -+ -+ sched_clock_register(sched_clock_read, ECONET_BITS, -+ econet_timer.freq_hz); -+ -+ pr_info("%pOFn: using %u.%03u MHz high precision timer\n", np, -+ econet_timer.freq_hz / 1000000, -+ (econet_timer.freq_hz / 1000) % 1000); -+ -+ return 0; -+} -+ -+TIMER_OF_DECLARE(econet_timer_hpt, "econet,en751221-timer", timer_init); diff --git a/target/linux/econet/patches-6.18/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch b/target/linux/econet/patches-6.18/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch deleted file mode 100644 index 64714dc8a2..0000000000 --- a/target/linux/econet/patches-6.18/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch +++ /dev/null @@ -1,44 +0,0 @@ -From be8b4173719a61fdd8379e86895d855775cf5f91 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:56 +0000 -Subject: [PATCH] dt-bindings: mips: Add EcoNet platform binding - -Document the top-level device tree binding for EcoNet MIPS-based SoCs. - -Signed-off-by: Caleb James DeLisle -Reviewed-by: Krzysztof Kozlowski -Signed-off-by: Thomas Bogendoerfer ---- - .../devicetree/bindings/mips/econet.yaml | 26 +++++++++++++++++++ - 1 file changed, 26 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mips/econet.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/mips/econet.yaml -@@ -0,0 +1,26 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mips/econet.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet MIPS SoCs -+ -+maintainers: -+ - Caleb James DeLisle -+ -+properties: -+ $nodename: -+ const: '/' -+ -+ compatible: -+ oneOf: -+ - description: Boards with EcoNet EN751221 family SoC -+ items: -+ - enum: -+ - smartfiber,xp8421-b -+ - const: econet,en751221 -+ -+additionalProperties: true -+ -+... diff --git a/target/linux/econet/patches-6.18/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch b/target/linux/econet/patches-6.18/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch deleted file mode 100644 index 86b05b07a1..0000000000 --- a/target/linux/econet/patches-6.18/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 35fb26f94dfa1b291086b84b2421f957214824d1 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:57 +0000 -Subject: [PATCH] mips: Add EcoNet MIPS platform support - -Add platform support for EcoNet MIPS SoCs. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/Kbuild.platforms | 1 + - arch/mips/Kconfig | 25 +++++++++ - arch/mips/boot/compressed/uart-16550.c | 5 ++ - arch/mips/econet/Kconfig | 37 ++++++++++++ - arch/mips/econet/Makefile | 2 + - arch/mips/econet/Platform | 5 ++ - arch/mips/econet/init.c | 78 ++++++++++++++++++++++++++ - 7 files changed, 153 insertions(+) - create mode 100644 arch/mips/econet/Kconfig - create mode 100644 arch/mips/econet/Makefile - create mode 100644 arch/mips/econet/Platform - create mode 100644 arch/mips/econet/init.c - ---- a/arch/mips/Kbuild.platforms -+++ b/arch/mips/Kbuild.platforms -@@ -11,6 +11,7 @@ platform-$(CONFIG_CAVIUM_OCTEON_SOC) += - platform-$(CONFIG_EYEQ) += mobileye/ - platform-$(CONFIG_MIPS_COBALT) += cobalt/ - platform-$(CONFIG_MACH_DECSTATION) += dec/ -+platform-$(CONFIG_ECONET) += econet/ - platform-$(CONFIG_MIPS_GENERIC) += generic/ - platform-$(CONFIG_MACH_JAZZ) += jazz/ - platform-$(CONFIG_LANTIQ) += lantiq/ ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -388,6 +388,30 @@ config MACH_DECSTATION - - otherwise choose R3000. - -+config ECONET -+ bool "EcoNet MIPS family" -+ select BOOT_RAW -+ select CPU_BIG_ENDIAN -+ select DEBUG_ZBOOT -+ select EARLY_PRINTK_8250 -+ select ECONET_EN751221_TIMER -+ select SERIAL_OF_PLATFORM -+ select SYS_SUPPORTS_BIG_ENDIAN -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_HAS_CPU_MIPS32_R2 -+ select SYS_HAS_EARLY_PRINTK -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_MIPS16 -+ select SYS_SUPPORTS_ZBOOT_UART16550 -+ select USE_GENERIC_EARLY_PRINTK_8250 -+ select USE_OF -+ help -+ EcoNet EN75xx MIPS devices are big endian MIPS machines used -+ in XPON (fiber) and DSL applications. They have SPI, PCI, USB, -+ GPIO, and Ethernet, with optional XPON, DSL, and VoIP DSP cores. -+ Don't confuse these with the Airoha ARM devices sometimes referred -+ to as "EcoNet", this family is for MIPS based devices only. -+ - config MACH_JAZZ - bool "Jazz family of machines" - select ARC_MEMORY -@@ -1017,6 +1041,7 @@ source "arch/mips/ath79/Kconfig" - source "arch/mips/bcm47xx/Kconfig" - source "arch/mips/bcm63xx/Kconfig" - source "arch/mips/bmips/Kconfig" -+source "arch/mips/econet/Kconfig" - source "arch/mips/generic/Kconfig" - source "arch/mips/ingenic/Kconfig" - source "arch/mips/jazz/Kconfig" ---- a/arch/mips/boot/compressed/uart-16550.c -+++ b/arch/mips/boot/compressed/uart-16550.c -@@ -20,6 +20,11 @@ - #define PORT(offset) (CKSEG1ADDR(INGENIC_UART_BASE_ADDR) + (4 * offset)) - #endif - -+#ifdef CONFIG_ECONET -+#define EN75_UART_BASE 0x1fbf0003 -+#define PORT(offset) (CKSEG1ADDR(EN75_UART_BASE) + (4 * (offset))) -+#endif -+ - #ifndef IOTYPE - #define IOTYPE char - #endif ---- /dev/null -+++ b/arch/mips/econet/Kconfig -@@ -0,0 +1,37 @@ -+# SPDX-License-Identifier: GPL-2.0 -+if ECONET -+ -+choice -+ prompt "EcoNet SoC selection" -+ default SOC_ECONET_EN751221 -+ help -+ Select EcoNet MIPS SoC type. Individual SoCs within a family are -+ very similar, so is it enough to select the right family, and -+ then customize to the specific SoC using the device tree only. -+ -+ config SOC_ECONET_EN751221 -+ bool "EN751221 family" -+ select COMMON_CLK -+ select ECONET_EN751221_INTC -+ select IRQ_MIPS_CPU -+ select SMP -+ select SMP_UP -+ select SYS_SUPPORTS_SMP -+ help -+ The EN751221 family includes EN7512, RN7513, EN7521, EN7526. -+ They are based on single core MIPS 34Kc processors. To boot -+ this kernel, you will need a device tree such as -+ MIPS_RAW_APPENDED_DTB=y, and a root filesystem. -+endchoice -+ -+choice -+ prompt "Devicetree selection" -+ default DTB_ECONET_NONE -+ help -+ Select the devicetree. -+ -+ config DTB_ECONET_NONE -+ bool "None" -+endchoice -+ -+endif ---- /dev/null -+++ b/arch/mips/econet/Makefile -@@ -0,0 +1,2 @@ -+ -+obj-y := init.o ---- /dev/null -+++ b/arch/mips/econet/Platform -@@ -0,0 +1,5 @@ -+# To address a 7.2MB kernel size limit in the EcoNet SDK bootloader, -+# we put the load address well above where the bootloader loads and then use -+# zboot. So please set CONFIG_ZBOOT_LOAD_ADDRESS to the address where your -+# bootloader actually places the kernel. -+load-$(CONFIG_ECONET) += 0xffffffff81000000 ---- /dev/null -+++ b/arch/mips/econet/init.c -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * EcoNet setup code -+ * -+ * Copyright (C) 2025 Caleb James DeLisle -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CR_AHB_RSTCR ((void __iomem *)CKSEG1ADDR(0x1fb00040)) -+#define RESET BIT(31) -+ -+#define UART_BASE CKSEG1ADDR(0x1fbf0003) -+#define UART_REG_SHIFT 2 -+ -+static void hw_reset(char *command) -+{ -+ iowrite32(RESET, CR_AHB_RSTCR); -+} -+ -+/* 1. Bring up early printk. */ -+void __init prom_init(void) -+{ -+ setup_8250_early_printk_port(UART_BASE, UART_REG_SHIFT, 0); -+ _machine_restart = hw_reset; -+} -+ -+/* 2. Parse the DT and find memory */ -+void __init plat_mem_setup(void) -+{ -+ void *dtb; -+ -+ set_io_port_base(KSEG1); -+ -+ dtb = get_fdt(); -+ if (!dtb) -+ panic("no dtb found"); -+ -+ __dt_setup_arch(dtb); -+ -+ early_init_dt_scan_memory(); -+} -+ -+/* 3. Overload __weak device_tree_init(), add SMP_UP ops */ -+void __init device_tree_init(void) -+{ -+ unflatten_and_copy_device_tree(); -+ -+ register_up_smp_ops(); -+} -+ -+const char *get_system_type(void) -+{ -+ return "EcoNet-EN75xx"; -+} -+ -+/* 4. Initialize the IRQ subsystem */ -+void __init arch_init_irq(void) -+{ -+ irqchip_init(); -+} -+ -+/* 5. Timers */ -+void __init plat_time_init(void) -+{ -+ of_clk_init(NULL); -+ timer_probe(); -+} diff --git a/target/linux/econet/patches-6.18/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch b/target/linux/econet/patches-6.18/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch deleted file mode 100644 index 6d51af0231..0000000000 --- a/target/linux/econet/patches-6.18/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch +++ /dev/null @@ -1,29 +0,0 @@ -From abc2d0bc2cb7c1412b8b254c0446f94b3e203c7c Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:58 +0000 -Subject: [PATCH] dt-bindings: vendor-prefixes: Add SmartFiber -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add "smartfiber" vendor prefix for manufactorer of EcoNet based boards. - -Signed-off-by: Caleb James DeLisle -Acked-by: Krzysztof Kozlowski -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Thomas Bogendoerfer ---- - Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/Documentation/devicetree/bindings/vendor-prefixes.yaml -+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml -@@ -1370,6 +1370,8 @@ patternProperties: - description: SKOV A/S - "^skyworks,.*": - description: Skyworks Solutions, Inc. -+ "^smartfiber,.*": -+ description: ShenZhen Smartfiber Technology Co, Ltd. - "^smartlabs,.*": - description: SmartLabs LLC - "^smartrg,.*": diff --git a/target/linux/econet/patches-6.18/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch b/target/linux/econet/patches-6.18/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch deleted file mode 100644 index cb5b457137..0000000000 --- a/target/linux/econet/patches-6.18/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0ec4887009729297f7c10368084e41a8a9fbbd0e Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:59 +0000 -Subject: [PATCH] mips: dts: Add EcoNet DTS with EN751221 and SmartFiber - XP8421-B board - -Add DTS files in support of EcoNet platform, including SmartFiber XP8421-B, -a low cost commercially available board based on EN751221. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/boot/dts/Makefile | 1 + - arch/mips/boot/dts/econet/Makefile | 2 + - arch/mips/boot/dts/econet/en751221.dtsi | 67 +++++++++++++++++++ - .../econet/en751221_smartfiber_xp8421-b.dts | 19 ++++++ - arch/mips/econet/Kconfig | 11 +++ - 5 files changed, 100 insertions(+) - create mode 100644 arch/mips/boot/dts/econet/Makefile - create mode 100644 arch/mips/boot/dts/econet/en751221.dtsi - create mode 100644 arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts - ---- a/arch/mips/boot/dts/Makefile -+++ b/arch/mips/boot/dts/Makefile -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - subdir-$(CONFIG_BMIPS_GENERIC) += brcm - subdir-$(CONFIG_CAVIUM_OCTEON_SOC) += cavium-octeon -+subdir-$(CONFIG_ECONET) += econet - subdir-$(CONFIG_EYEQ) += mobileye - subdir-$(CONFIG_FIT_IMAGE_FDT_MARDUK) += img - subdir-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += img ---- /dev/null -+++ b/arch/mips/boot/dts/econet/Makefile -@@ -0,0 +1,2 @@ -+# SPDX-License-Identifier: GPL-2.0 -+dtb-$(CONFIG_DTB_ECONET_SMARTFIBER_XP8421_B) += en751221_smartfiber_xp8421-b.dtb ---- /dev/null -+++ b/arch/mips/boot/dts/econet/en751221.dtsi -@@ -0,0 +1,67 @@ -+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+/dts-v1/; -+ -+/ { -+ compatible = "econet,en751221"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ hpt_clock: clock { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <200000000>; /* 200 MHz */ -+ }; -+ -+ cpus: cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "mips,mips24KEc"; -+ reg = <0>; -+ }; -+ }; -+ -+ cpuintc: interrupt-controller { -+ compatible = "mti,cpu-interrupt-controller"; -+ interrupt-controller; -+ #address-cells = <0>; -+ #interrupt-cells = <1>; -+ }; -+ -+ intc: interrupt-controller@1fb40000 { -+ compatible = "econet,en751221-intc"; -+ reg = <0x1fb40000 0x100>; -+ interrupt-parent = <&cpuintc>; -+ interrupts = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ econet,shadow-interrupts = <7 2>, <8 3>, <13 12>, <30 29>; -+ }; -+ -+ uart: serial@1fbf0000 { -+ compatible = "ns16550"; -+ reg = <0x1fbf0000 0x30>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ interrupt-parent = <&intc>; -+ interrupts = <0>; -+ /* -+ * Conversion of baud rate to clock frequency requires a -+ * computation that is not in the ns16550 driver, so this -+ * uart is fixed at 115200 baud. -+ */ -+ clock-frequency = <1843200>; -+ }; -+ -+ timer_hpt: timer@1fbf0400 { -+ compatible = "econet,en751221-timer"; -+ reg = <0x1fbf0400 0x100>; -+ -+ interrupt-parent = <&intc>; -+ interrupts = <30>; -+ clocks = <&hpt_clock>; -+ }; -+}; ---- /dev/null -+++ b/arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts -@@ -0,0 +1,19 @@ -+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+/dts-v1/; -+ -+#include "en751221.dtsi" -+ -+/ { -+ model = "SmartFiber XP8421-B"; -+ compatible = "smartfiber,xp8421-b", "econet,en751221"; -+ -+ memory@0 { -+ device_type = "memory"; -+ reg = <0x00000000 0x1c000000>; -+ }; -+ -+ chosen { -+ stdout-path = "/serial@1fbf0000:115200"; -+ linux,usable-memory-range = <0x00020000 0x1bfe0000>; -+ }; -+}; ---- a/arch/mips/econet/Kconfig -+++ b/arch/mips/econet/Kconfig -@@ -32,6 +32,17 @@ choice - - config DTB_ECONET_NONE - bool "None" -+ -+ config DTB_ECONET_SMARTFIBER_XP8421_B -+ bool "EN751221 SmartFiber XP8421-B" -+ depends on SOC_ECONET_EN751221 -+ select BUILTIN_DTB -+ help -+ The SmartFiber XP8421-B is a device based on the EN751221 SoC. -+ It has 512MB of memory and 256MB of NAND flash. This kernel -+ needs only an appended initramfs to boot. It can be loaded -+ through XMODEM and booted from memory in the bootloader, or -+ it can be packed in tclinux.trx format and written to flash. - endchoice - - endif diff --git a/target/linux/econet/patches-6.18/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch b/target/linux/econet/patches-6.18/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch deleted file mode 100644 index e4230573c2..0000000000 --- a/target/linux/econet/patches-6.18/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch +++ /dev/null @@ -1,38 +0,0 @@ -From faefb0a59c5914b7b8f737e2ec5c82822e5bc4c7 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:45:00 +0000 -Subject: [PATCH] MAINTAINERS: Add entry for newly added EcoNet platform. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add a MAINTAINERS entry as part of integration of the EcoNet MIPS platform. - -Signed-off-by: Caleb James DeLisle -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Thomas Bogendoerfer ---- - MAINTAINERS | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -8025,6 +8025,18 @@ W: https://linuxtv.org - Q: http://patchwork.linuxtv.org/project/linux-media/list/ - F: drivers/media/dvb-frontends/ec100* - -+ECONET MIPS PLATFORM -+M: Caleb James DeLisle -+L: linux-mips@vger.kernel.org -+S: Maintained -+F: Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml -+F: Documentation/devicetree/bindings/mips/econet.yaml -+F: Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml -+F: arch/mips/boot/dts/econet/ -+F: arch/mips/econet/ -+F: drivers/clocksource/timer-econet-en751221.c -+F: drivers/irqchip/irq-econet-en751221.c -+ - ECRYPT FILE SYSTEM - M: Tyler Hicks - L: ecryptfs@vger.kernel.org diff --git a/target/linux/econet/patches-6.18/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch b/target/linux/econet/patches-6.18/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch deleted file mode 100644 index fe9e6792eb..0000000000 --- a/target/linux/econet/patches-6.18/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 79ee1d20e37cd553cc961962fca8107e69a0c293 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 21 May 2025 21:33:33 +0000 -Subject: [PATCH] mips: econet: Fix incorrect Kconfig dependencies - -config ECONET selects SERIAL_OF_PLATFORM and that depends on SERIAL_8250 -so we need to select SERIAL_8250 directly. -Also do not enable DEBUG_ZBOOT unless DEBUG_KERNEL is set. - -Signed-off-by: Caleb James DeLisle -Reported-by: kernel test robot -Closes: https://lore.kernel.org/oe-kbuild-all/202505211654.CBdIsoTq-lkp@intel.com/ -Closes: https://lore.kernel.org/oe-kbuild-all/202505211451.WRjyf3a9-lkp@intel.com/ -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/Kconfig | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -392,9 +392,10 @@ config ECONET - bool "EcoNet MIPS family" - select BOOT_RAW - select CPU_BIG_ENDIAN -- select DEBUG_ZBOOT -+ select DEBUG_ZBOOT if DEBUG_KERNEL - select EARLY_PRINTK_8250 - select ECONET_EN751221_TIMER -+ select SERIAL_8250 - select SERIAL_OF_PLATFORM - select SYS_SUPPORTS_BIG_ENDIAN - select SYS_HAS_CPU_MIPS32_R1 diff --git a/target/linux/econet/patches-6.18/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch b/target/linux/econet/patches-6.18/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch deleted file mode 100644 index 26b3da9c4d..0000000000 --- a/target/linux/econet/patches-6.18/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 82e6bf912d5846646892becea659b39d178d79e3 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 12 Nov 2024 01:08:53 +0100 -Subject: [PATCH 5/8] clk: en7523: move en7581_reset_register() in - en7581_clk_hw_init() - -Move en7581_reset_register routine in en7581_clk_hw_init() since reset -feature is supported just by EN7581 SoC. -Get rid of reset struct in en_clk_soc_data data struct. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-6-8ada5e394ae4@kernel.org -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 93 ++++++++++++++-------------------------- - 1 file changed, 33 insertions(+), 60 deletions(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -76,11 +76,6 @@ struct en_rst_data { - - struct en_clk_soc_data { - const struct clk_ops pcie_ops; -- struct { -- const u16 *bank_ofs; -- const u16 *idx_map; -- u16 idx_map_nr; -- } reset; - int (*hw_init)(struct platform_device *pdev, - struct clk_hw_onecell_data *clk_data); - }; -@@ -596,32 +591,6 @@ static void en7581_register_clocks(struc - clk_data->num = EN7523_NUM_CLOCKS; - } - --static int en7581_clk_hw_init(struct platform_device *pdev, -- struct clk_hw_onecell_data *clk_data) --{ -- void __iomem *np_base; -- struct regmap *map; -- u32 val; -- -- map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); -- if (IS_ERR(map)) -- return PTR_ERR(map); -- -- np_base = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(np_base)) -- return PTR_ERR(np_base); -- -- en7581_register_clocks(&pdev->dev, clk_data, map, np_base); -- -- val = readl(np_base + REG_NP_SCU_SSTR); -- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); -- writel(val, np_base + REG_NP_SCU_SSTR); -- val = readl(np_base + REG_NP_SCU_PCIC); -- writel(val | 3, np_base + REG_NP_SCU_PCIC); -- -- return 0; --} -- - static int en7523_reset_update(struct reset_controller_dev *rcdev, - unsigned long id, bool assert) - { -@@ -671,23 +640,18 @@ static int en7523_reset_xlate(struct res - return rst_data->idx_map[reset_spec->args[0]]; - } - --static const struct reset_control_ops en7523_reset_ops = { -+static const struct reset_control_ops en7581_reset_ops = { - .assert = en7523_reset_assert, - .deassert = en7523_reset_deassert, - .status = en7523_reset_status, - }; - --static int en7523_reset_register(struct platform_device *pdev, -- const struct en_clk_soc_data *soc_data) -+static int en7581_reset_register(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; - struct en_rst_data *rst_data; - void __iomem *base; - -- /* no reset lines available */ -- if (!soc_data->reset.idx_map_nr) -- return 0; -- - base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(base)) - return PTR_ERR(base); -@@ -696,13 +660,13 @@ static int en7523_reset_register(struct - if (!rst_data) - return -ENOMEM; - -- rst_data->bank_ofs = soc_data->reset.bank_ofs; -- rst_data->idx_map = soc_data->reset.idx_map; -+ rst_data->bank_ofs = en7581_rst_ofs; -+ rst_data->idx_map = en7581_rst_map; - rst_data->base = base; - -- rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr; -+ rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); - rst_data->rcdev.of_xlate = en7523_reset_xlate; -- rst_data->rcdev.ops = &en7523_reset_ops; -+ rst_data->rcdev.ops = &en7581_reset_ops; - rst_data->rcdev.of_node = dev->of_node; - rst_data->rcdev.of_reset_n_cells = 1; - rst_data->rcdev.owner = THIS_MODULE; -@@ -711,6 +675,32 @@ static int en7523_reset_register(struct - return devm_reset_controller_register(dev, &rst_data->rcdev); - } - -+static int en7581_clk_hw_init(struct platform_device *pdev, -+ struct clk_hw_onecell_data *clk_data) -+{ -+ void __iomem *np_base; -+ struct regmap *map; -+ u32 val; -+ -+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); -+ if (IS_ERR(map)) -+ return PTR_ERR(map); -+ -+ np_base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(np_base)) -+ return PTR_ERR(np_base); -+ -+ en7581_register_clocks(&pdev->dev, clk_data, map, np_base); -+ -+ val = readl(np_base + REG_NP_SCU_SSTR); -+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); -+ writel(val, np_base + REG_NP_SCU_SSTR); -+ val = readl(np_base + REG_NP_SCU_PCIC); -+ writel(val | 3, np_base + REG_NP_SCU_PCIC); -+ -+ return en7581_reset_register(pdev); -+} -+ - static int en7523_clk_probe(struct platform_device *pdev) - { - struct device_node *node = pdev->dev.of_node; -@@ -729,19 +719,7 @@ static int en7523_clk_probe(struct platf - if (r) - return r; - -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n", -- pdev->name); -- -- r = en7523_reset_register(pdev, soc_data); -- if (r) { -- of_clk_del_provider(node); -- return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n", -- pdev->name); -- } -- -- return 0; -+ return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - } - - static const struct en_clk_soc_data en7523_data = { -@@ -759,11 +737,6 @@ static const struct en_clk_soc_data en75 - .enable = en7581_pci_enable, - .disable = en7581_pci_disable, - }, -- .reset = { -- .bank_ofs = en7581_rst_ofs, -- .idx_map = en7581_rst_map, -- .idx_map_nr = ARRAY_SIZE(en7581_rst_map), -- }, - .hw_init = en7581_clk_hw_init, - }; - diff --git a/target/linux/econet/patches-6.18/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch b/target/linux/econet/patches-6.18/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch deleted file mode 100644 index 4e4952d8a6..0000000000 --- a/target/linux/econet/patches-6.18/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch +++ /dev/null @@ -1,84 +0,0 @@ -From a9eaf305017a5ebe73ab34e85bd5414055a88f29 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 12 Nov 2024 01:08:54 +0100 -Subject: [PATCH 6/8] clk: en7523: map io region in a single block - -Map all clock-controller memory region in a single block. -This patch does not introduce any backward incompatibility since the dts -for EN7581 SoC is not upstream yet. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-7-8ada5e394ae4@kernel.org -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 32 +++++++++++++------------------- - 1 file changed, 13 insertions(+), 19 deletions(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -39,8 +39,8 @@ - #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) - #define REG_CRYPTO_CLKSRC2 0x20c - --#define REG_RST_CTRL2 0x00 --#define REG_RST_CTRL1 0x04 -+#define REG_RST_CTRL2 0x830 -+#define REG_RST_CTRL1 0x834 - - struct en_clk_desc { - int id; -@@ -646,15 +646,9 @@ static const struct reset_control_ops en - .status = en7523_reset_status, - }; - --static int en7581_reset_register(struct platform_device *pdev) -+static int en7581_reset_register(struct device *dev, void __iomem *base) - { -- struct device *dev = &pdev->dev; - struct en_rst_data *rst_data; -- void __iomem *base; -- -- base = devm_platform_ioremap_resource(pdev, 1); -- if (IS_ERR(base)) -- return PTR_ERR(base); - - rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); - if (!rst_data) -@@ -678,27 +672,27 @@ static int en7581_reset_register(struct - static int en7581_clk_hw_init(struct platform_device *pdev, - struct clk_hw_onecell_data *clk_data) - { -- void __iomem *np_base; - struct regmap *map; -+ void __iomem *base; - u32 val; - - map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); - if (IS_ERR(map)) - return PTR_ERR(map); - -- np_base = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(np_base)) -- return PTR_ERR(np_base); -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); - -- en7581_register_clocks(&pdev->dev, clk_data, map, np_base); -+ en7581_register_clocks(&pdev->dev, clk_data, map, base); - -- val = readl(np_base + REG_NP_SCU_SSTR); -+ val = readl(base + REG_NP_SCU_SSTR); - val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); -- writel(val, np_base + REG_NP_SCU_SSTR); -- val = readl(np_base + REG_NP_SCU_PCIC); -- writel(val | 3, np_base + REG_NP_SCU_PCIC); -+ writel(val, base + REG_NP_SCU_SSTR); -+ val = readl(base + REG_NP_SCU_PCIC); -+ writel(val | 3, base + REG_NP_SCU_PCIC); - -- return en7581_reset_register(pdev); -+ return en7581_reset_register(&pdev->dev, base); - } - - static int en7523_clk_probe(struct platform_device *pdev) diff --git a/target/linux/econet/patches-6.18/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch b/target/linux/econet/patches-6.18/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch deleted file mode 100644 index 44664202a8..0000000000 --- a/target/linux/econet/patches-6.18/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 90d4e466c9ea2010f33880a36317a8486ccbe082 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Wed, 8 Jan 2025 10:50:43 +0100 -Subject: [PATCH 1/3] PCI: mediatek-gen3: Move reset delay in - mtk_pcie_en7581_power_up() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal -causing occasional PCIe link down issues. In order to overcome the -problem, PCIe block is reset using REG_PCI_CONTROL (0x88) and -REG_RESET_CONTROL (0x834) registers available in the clock module -running clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up(). - -In order to make the code more readable, move the wait for the time -needed to complete the PCIe reset from en7581_pci_enable() to -mtk_pcie_en7581_power_up(). - -Reduce reset timeout from 250ms to the standard PCIE_T_PVPERL_MS value -(100ms) since it has no impact on the driver behavior. - -Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-4-21ac939a3b9b@kernel.org -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Krzysztof Wilczyński -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Manivannan Sadhasivam -Acked-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -478,7 +478,6 @@ static int en7581_pci_enable(struct clk_ - REG_PCI_CONTROL_PERSTOUT; - val = readl(np_base + REG_PCI_CONTROL); - writel(val | mask, np_base + REG_PCI_CONTROL); -- msleep(250); - - return 0; - } diff --git a/target/linux/econet/patches-6.18/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch b/target/linux/econet/patches-6.18/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch deleted file mode 100644 index a33e842b9e..0000000000 --- a/target/linux/econet/patches-6.18/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch +++ /dev/null @@ -1,83 +0,0 @@ -From e4a9748e7103c47e575459db2b6a77d14f34da2b Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:02 +0100 -Subject: [PATCH 2/3] clk: en7523: Rework clock handling for different clock - numbers - -Airoha EN7581 SoC have additional clock compared to EN7523 but current -driver permits to only support up to EN7523 clock numbers. - -To handle this, rework the clock handling and permit to declare the -clocks number in match_data and alloca clk_data based on the compatible -match_data. - -Signed-off-by: Christian Marangi -Link: https://lore.kernel.org/r/20250113231030.6735-2-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 14 ++++++++------ - 1 file changed, 8 insertions(+), 6 deletions(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -75,6 +75,7 @@ struct en_rst_data { - }; - - struct en_clk_soc_data { -+ u32 num_clocks; - const struct clk_ops pcie_ops; - int (*hw_init)(struct platform_device *pdev, - struct clk_hw_onecell_data *clk_data); -@@ -503,8 +504,6 @@ static void en7523_register_clocks(struc - u32 rate; - int i; - -- clk_data->num = EN7523_NUM_CLOCKS; -- - for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { - const struct en_clk_desc *desc = &en7523_base_clks[i]; - u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg; -@@ -586,8 +585,6 @@ static void en7581_register_clocks(struc - - hw = en7523_register_pcie_clk(dev, base); - clk_data->hws[EN7523_CLK_PCIE] = hw; -- -- clk_data->num = EN7523_NUM_CLOCKS; - } - - static int en7523_reset_update(struct reset_controller_dev *rcdev, -@@ -701,13 +698,15 @@ static int en7523_clk_probe(struct platf - struct clk_hw_onecell_data *clk_data; - int r; - -+ soc_data = device_get_match_data(&pdev->dev); -+ - clk_data = devm_kzalloc(&pdev->dev, -- struct_size(clk_data, hws, EN7523_NUM_CLOCKS), -+ struct_size(clk_data, hws, soc_data->num_clocks), - GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - -- soc_data = device_get_match_data(&pdev->dev); -+ clk_data->num = soc_data->num_clocks; - r = soc_data->hw_init(pdev, clk_data); - if (r) - return r; -@@ -716,6 +715,7 @@ static int en7523_clk_probe(struct platf - } - - static const struct en_clk_soc_data en7523_data = { -+ .num_clocks = ARRAY_SIZE(en7523_base_clks) + 1, - .pcie_ops = { - .is_enabled = en7523_pci_is_enabled, - .prepare = en7523_pci_prepare, -@@ -725,6 +725,8 @@ static const struct en_clk_soc_data en75 - }; - - static const struct en_clk_soc_data en7581_data = { -+ /* We increment num_clocks by 1 to account for additional PCIe clock */ -+ .num_clocks = ARRAY_SIZE(en7581_base_clks) + 1, - .pcie_ops = { - .is_enabled = en7581_pci_is_enabled, - .enable = en7581_pci_enable, diff --git a/target/linux/econet/patches-6.18/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch b/target/linux/econet/patches-6.18/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch deleted file mode 100644 index 35d34a5ccf..0000000000 --- a/target/linux/econet/patches-6.18/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch +++ /dev/null @@ -1,41 +0,0 @@ -From bfe257f9780d8f77045a7da6ec959ee0659d2f98 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:05 +0100 -Subject: [PATCH 3/3] clk: en7523: Add clock for eMMC for EN7581 - -Add clock for eMMC for EN7581. This is used to give info of the current -eMMC source clock and to switch it from 200MHz or 150MHz. - -Signed-off-by: Christian Marangi -Link: https://lore.kernel.org/r/20250113231030.6735-5-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -91,6 +91,7 @@ static const u32 emi7581_base[] = { 5400 - static const u32 bus7581_base[] = { 600000000, 540000000 }; - static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; - static const u32 crypto_base[] = { 540000000, 480000000 }; -+static const u32 emmc7581_base[] = { 200000000, 150000000 }; - - static const struct en_clk_desc en7523_base_clks[] = { - { -@@ -281,6 +282,15 @@ static const struct en_clk_desc en7581_b - .base_shift = 0, - .base_values = crypto_base, - .n_base_values = ARRAY_SIZE(crypto_base), -+ }, { -+ .id = EN7581_CLK_EMMC, -+ .name = "emmc", -+ -+ .base_reg = REG_CRYPTO_CLKSRC2, -+ .base_bits = 1, -+ .base_shift = 12, -+ .base_values = emmc7581_base, -+ .n_base_values = ARRAY_SIZE(emmc7581_base), - } - }; - diff --git a/target/linux/econet/patches-6.18/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch b/target/linux/econet/patches-6.18/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch deleted file mode 100644 index a4af01dd20..0000000000 --- a/target/linux/econet/patches-6.18/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0f7c637d1103d79829dec198e5f1b678c1feb5f2 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 12 Nov 2024 01:08:48 +0100 -Subject: [PATCH] dt-bindings: clock: airoha: Update reg mapping for EN7581 - SoC. - -clk-en7523 driver for EN7581 SoC is mapping all the scu memory region -while it is configuring the chip-scu one via a syscon. Update the reg -mapping definition for this device. This patch does not introduce any -backward incompatibility since the dts for EN7581 SoC is not upstream -yet. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-1-8ada5e394ae4@kernel.org -Reviewed-by: Rob Herring (Arm) -Signed-off-by: Stephen Boyd ---- - .../bindings/clock/airoha,en7523-scu.yaml | 23 +++++++------------ - 1 file changed, 8 insertions(+), 15 deletions(-) - ---- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml -+++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml -@@ -34,8 +34,10 @@ properties: - - airoha,en7581-scu - - reg: -- minItems: 2 -- maxItems: 4 -+ items: -+ - description: scu base address -+ - description: misc scu base address -+ minItems: 1 - - "#clock-cells": - description: -@@ -60,9 +62,7 @@ allOf: - then: - properties: - reg: -- items: -- - description: scu base address -- - description: misc scu base address -+ minItems: 2 - - - if: - properties: -@@ -71,11 +71,7 @@ allOf: - then: - properties: - reg: -- items: -- - description: scu base address -- - description: misc scu base address -- - description: reset base address -- - description: pb scu base address -+ maxItems: 1 - - additionalProperties: false - -@@ -95,12 +91,9 @@ examples: - #address-cells = <2>; - #size-cells = <2>; - -- scuclk: clock-controller@1fa20000 { -+ scuclk: clock-controller@1fb00000 { - compatible = "airoha,en7581-scu"; -- reg = <0x0 0x1fa20000 0x0 0x400>, -- <0x0 0x1fb00000 0x0 0x90>, -- <0x0 0x1fb00830 0x0 0x8>, -- <0x0 0x1fbe3400 0x0 0xfc>; -+ reg = <0x0 0x1fb00000 0x0 0x970>; - #clock-cells = <1>; - #reset-cells = <1>; - }; diff --git a/target/linux/econet/patches-6.18/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch b/target/linux/econet/patches-6.18/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch deleted file mode 100644 index a6594ebac8..0000000000 --- a/target/linux/econet/patches-6.18/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 02d3b7557ce28c373ea1e925ae16ab5988284313 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:03 +0100 -Subject: [PATCH 1/2] dt-bindings: clock: drop NUM_CLOCKS define for EN7581 - -Drop NUM_CLOCKS define for EN7581 include. This is not a binding and -should not be placed here. Value is derived internally in the user -driver. - -Signed-off-by: Christian Marangi -Acked-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250113231030.6735-3-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - include/dt-bindings/clock/en7523-clk.h | 2 -- - 1 file changed, 2 deletions(-) - ---- a/include/dt-bindings/clock/en7523-clk.h -+++ b/include/dt-bindings/clock/en7523-clk.h -@@ -12,6 +12,4 @@ - #define EN7523_CLK_CRYPTO 6 - #define EN7523_CLK_PCIE 7 - --#define EN7523_NUM_CLOCKS 8 -- - #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ diff --git a/target/linux/econet/patches-6.18/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch b/target/linux/econet/patches-6.18/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch deleted file mode 100644 index f500a79808..0000000000 --- a/target/linux/econet/patches-6.18/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 82108ad3285f58f314ad41398f44017c7dbe44de Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:04 +0100 -Subject: [PATCH 2/2] dt-bindings: clock: add ID for eMMC for EN7581 - -Add ID for eMMC for EN7581. This is to control clock selection of eMMC -between 200MHz and 150MHz. - -Signed-off-by: Christian Marangi -Acked-by: Conor Dooley -Link: https://lore.kernel.org/r/20250113231030.6735-4-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - include/dt-bindings/clock/en7523-clk.h | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/include/dt-bindings/clock/en7523-clk.h -+++ b/include/dt-bindings/clock/en7523-clk.h -@@ -12,4 +12,6 @@ - #define EN7523_CLK_CRYPTO 6 - #define EN7523_CLK_PCIE 7 - -+#define EN7581_CLK_EMMC 8 -+ - #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ From 2dde2efd228ed5df407075b4644f7550aa034240 Mon Sep 17 00:00:00 2001 From: Ahmed Naseef Date: Thu, 11 Jun 2026 18:19:40 +0400 Subject: [PATCH 013/228] econet: update patches for 6.18 Fix patch compatibility for kernel 6.18 on econet and refresh with `make target/linux/refresh V=s`. The shared airoha clk/spi/uart and the econet-local timer, nand and phy patches are rebased onto the 6.18 upstream code. Signed-off-by: Ahmed Naseef Link: https://github.com/openwrt/openwrt/pull/23755 Signed-off-by: Jonas Jelonek --- ...k-airoha-Add-reset-support-to-EN7523.patch | 6 ++-- .../100-econet-add-en7528-soc.patch | 2 +- .../101-econet-timer-add-en7528-support.patch | 2 +- ...for-the-Airoha-EN7523-SoC-SPI-contro.patch | 6 ++-- ...pi-Airoha-adapt-to-support-en75-mips.patch | 2 +- ...03-spi-airoha-snfi-enable-for-econet.patch | 2 +- .../310-usb-enable-econet-usb.patch | 2 +- ...0-gpio-en7523-enable-for-econet-mips.patch | 2 +- .../886-uart-add-en7523-support.patch | 29 +++++++++---------- .../887-uart-airoha-add-econet-support.patch | 2 +- .../901-nand-enable-en75-bbt.patch | 2 +- .../902-snand-mtk-bmt-support.patch | 8 ++--- ...conet-en751221-clock-reset-support-t.patch | 2 +- ...pcie-add-en7528-pcie-and-phy-support.patch | 28 +++++++++--------- .../913-pcie-fix-bogus-prefetch-window.patch | 4 +-- .../914-phy-add-en7528-usb-phy-driver.patch | 8 ++--- 16 files changed, 53 insertions(+), 54 deletions(-) diff --git a/target/linux/econet/patches-6.18/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch b/target/linux/econet/patches-6.18/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch index ef56753c9b..cf8041c111 100644 --- a/target/linux/econet/patches-6.18/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch +++ b/target/linux/econet/patches-6.18/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch @@ -17,15 +17,15 @@ Signed-off-by: Stephen Boyd --- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml @@ -64,8 +64,6 @@ allOf: - - description: scu base address - - description: misc scu base address + reg: + minItems: 2 - '#reset-cells': false - - if: properties: compatible: -@@ -89,6 +87,7 @@ examples: +@@ -85,6 +83,7 @@ examples: reg = <0x1fa20000 0x400>, <0x1fb00000 0x1000>; #clock-cells = <1>; diff --git a/target/linux/econet/patches-6.18/100-econet-add-en7528-soc.patch b/target/linux/econet/patches-6.18/100-econet-add-en7528-soc.patch index f11c6d329d..edff2c57a6 100644 --- a/target/linux/econet/patches-6.18/100-econet-add-en7528-soc.patch +++ b/target/linux/econet/patches-6.18/100-econet-add-en7528-soc.patch @@ -14,7 +14,7 @@ This adds boot support for the EN7528 SoC family: Signed-off-by: Ahmed Naseef --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -391,13 +391,13 @@ config MACH_DECSTATION +@@ -392,13 +392,13 @@ config MACH_DECSTATION config ECONET bool "EcoNet MIPS family" select BOOT_RAW diff --git a/target/linux/econet/patches-6.18/101-econet-timer-add-en7528-support.patch b/target/linux/econet/patches-6.18/101-econet-timer-add-en7528-support.patch index 3d86414591..f0d6ec59a6 100644 --- a/target/linux/econet/patches-6.18/101-econet-timer-add-en7528-support.patch +++ b/target/linux/econet/patches-6.18/101-econet-timer-add-en7528-support.patch @@ -120,7 +120,7 @@ Signed-off-by: Ahmed Naseef for_each_possible_cpu(i) { struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i); -- cd->rating = 310, +- cd->rating = 310; - cd->features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_C3STOP | - CLOCK_EVT_FEAT_PERCPU; diff --git a/target/linux/econet/patches-6.18/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch b/target/linux/econet/patches-6.18/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch index d3f3054fe7..a312ff0ad6 100644 --- a/target/linux/econet/patches-6.18/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch +++ b/target/linux/econet/patches-6.18/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch @@ -1,6 +1,6 @@ --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -370,6 +370,12 @@ config SPI_DLN2 +@@ -404,6 +404,12 @@ config SPI_DLN2 This driver can also be built as a module. If so, the module will be called spi-dln2. @@ -15,7 +15,7 @@ depends on ARCH_EP93XX || COMPILE_TEST --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile -@@ -52,6 +52,7 @@ obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1. +@@ -56,6 +56,7 @@ obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1. obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o obj-$(CONFIG_SPI_DW_PCI) += spi-dw-pci.o obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o @@ -292,7 +292,7 @@ + struct spi_controller *ctrl; + int err; + -+ ctrl = devm_spi_alloc_master(&pdev->dev, 0); ++ ctrl = devm_spi_alloc_host(&pdev->dev, 0); + if (!ctrl) { + dev_err(&pdev->dev, "Error allocating SPI controller\n"); + return -ENOMEM; diff --git a/target/linux/econet/patches-6.18/301-spi-Airoha-adapt-to-support-en75-mips.patch b/target/linux/econet/patches-6.18/301-spi-Airoha-adapt-to-support-en75-mips.patch index 888df7552e..12d511466a 100644 --- a/target/linux/econet/patches-6.18/301-spi-Airoha-adapt-to-support-en75-mips.patch +++ b/target/linux/econet/patches-6.18/301-spi-Airoha-adapt-to-support-en75-mips.patch @@ -12,7 +12,7 @@ Signed-off-by: Caleb James DeLisle --- --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -372,7 +372,7 @@ config SPI_DLN2 +@@ -406,7 +406,7 @@ config SPI_DLN2 config SPI_AIROHA_EN7523 bool "Airoha EN7523 SPI controller support" diff --git a/target/linux/econet/patches-6.18/303-spi-airoha-snfi-enable-for-econet.patch b/target/linux/econet/patches-6.18/303-spi-airoha-snfi-enable-for-econet.patch index 8556633d01..ec80c11804 100644 --- a/target/linux/econet/patches-6.18/303-spi-airoha-snfi-enable-for-econet.patch +++ b/target/linux/econet/patches-6.18/303-spi-airoha-snfi-enable-for-econet.patch @@ -10,7 +10,7 @@ performance compared to the manual mode spi-en7523 driver. Signed-off-by: Ahmed Naseef --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -59,7 +59,7 @@ comment "SPI Master Controller Drivers" +@@ -62,7 +62,7 @@ comment "SPI Master Controller Drivers" config SPI_AIROHA_SNFI tristate "Airoha SPI NAND Flash Interface" diff --git a/target/linux/econet/patches-6.18/310-usb-enable-econet-usb.patch b/target/linux/econet/patches-6.18/310-usb-enable-econet-usb.patch index a550bbfae5..a81f957ceb 100644 --- a/target/linux/econet/patches-6.18/310-usb-enable-econet-usb.patch +++ b/target/linux/econet/patches-6.18/310-usb-enable-econet-usb.patch @@ -1,6 +1,6 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -391,6 +391,7 @@ config MACH_DECSTATION +@@ -392,6 +392,7 @@ config MACH_DECSTATION config ECONET bool "EcoNet MIPS family" select BOOT_RAW diff --git a/target/linux/econet/patches-6.18/320-gpio-en7523-enable-for-econet-mips.patch b/target/linux/econet/patches-6.18/320-gpio-en7523-enable-for-econet-mips.patch index 09e86ff5c9..307b5c0b79 100644 --- a/target/linux/econet/patches-6.18/320-gpio-en7523-enable-for-econet-mips.patch +++ b/target/linux/econet/patches-6.18/320-gpio-en7523-enable-for-econet-mips.patch @@ -6,7 +6,7 @@ MIPS SoC. Allow building the driver when ECONET is selected. Signed-off-by: Ahmed Naseef --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig -@@ -271,7 +271,7 @@ config GPIO_EM +@@ -293,7 +293,7 @@ config GPIO_EM config GPIO_EN7523 tristate "Airoha GPIO support" diff --git a/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch b/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch index 486208f71a..f143e33695 100644 --- a/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch +++ b/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch @@ -97,7 +97,7 @@ +EXPORT_SYMBOL_GPL(en7523_set_uart_baud_rate); --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c -@@ -341,6 +341,7 @@ static const struct of_device_id of_plat +@@ -353,6 +353,7 @@ static const struct of_device_id of_plat { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, @@ -107,7 +107,7 @@ MODULE_DEVICE_TABLE(of, of_platform_serial_table); --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c -@@ -319,6 +319,14 @@ static const struct serial8250_config ua +@@ -311,6 +311,14 @@ static const struct serial8250_config ua .rxtrig_bytes = {1, 8, 16, 30}, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, @@ -122,22 +122,21 @@ }; /* Uart divisor latch read */ -@@ -2841,6 +2849,12 @@ serial8250_do_set_termios(struct uart_po - - serial8250_set_divisor(port, baud, quot, frac); - +@@ -2782,6 +2790,11 @@ serial8250_do_set_termios(struct uart_po + serial8250_set_ier(port, termios); + serial8250_set_efr(port, termios); + serial8250_set_divisor(port, baud, quot, frac); +#ifdef CONFIG_SERIAL_8250_AIROHA -+ /* Airoha SoCs have custom registers for baud rate settings */ -+ if (port->type == PORT_AIROHA) -+ en7523_set_uart_baud_rate(port, baud); ++ /* Airoha SoCs have custom registers for baud rate settings */ ++ if (port->type == PORT_AIROHA) ++ en7523_set_uart_baud_rate(port, baud); +#endif -+ - /* - * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR - * is written without DLAB set, this mode will be disabled. + serial8250_set_fcr(port, termios); + serial8250_set_mctrl(port, port->mctrl); + } --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig -@@ -355,6 +355,16 @@ config SERIAL_8250_ACORN +@@ -356,6 +356,16 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. @@ -201,6 +200,6 @@ unsigned int quot); int fsl8250_handle_irq(struct uart_port *port); +int en7523_set_uart_baud_rate(struct uart_port *port, unsigned int baud); + void serial8250_handle_irq_locked(struct uart_port *port, unsigned int iir); int serial8250_handle_irq(struct uart_port *port, unsigned int iir); u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); - void serial8250_read_char(struct uart_8250_port *up, u16 lsr); diff --git a/target/linux/econet/patches-6.18/887-uart-airoha-add-econet-support.patch b/target/linux/econet/patches-6.18/887-uart-airoha-add-econet-support.patch index b25d02e969..560b020ab6 100644 --- a/target/linux/econet/patches-6.18/887-uart-airoha-add-econet-support.patch +++ b/target/linux/econet/patches-6.18/887-uart-airoha-add-econet-support.patch @@ -7,7 +7,7 @@ the Airoha UART driver for EcoNet platforms. Signed-off-by: Ahmed Naseef --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig -@@ -357,7 +357,7 @@ config SERIAL_8250_ACORN +@@ -358,7 +358,7 @@ config SERIAL_8250_ACORN config SERIAL_8250_AIROHA tristate "Airoha UART support" diff --git a/target/linux/econet/patches-6.18/901-nand-enable-en75-bbt.patch b/target/linux/econet/patches-6.18/901-nand-enable-en75-bbt.patch index 91e184bd96..569e37d736 100644 --- a/target/linux/econet/patches-6.18/901-nand-enable-en75-bbt.patch +++ b/target/linux/econet/patches-6.18/901-nand-enable-en75-bbt.patch @@ -14,9 +14,9 @@ Signed-off-by: Caleb James DeLisle obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o -obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o +obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o en75_bmt.o + obj-$(CONFIG_MTD_NAND_ECC_REALTEK) += ecc-realtek.o obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o - obj-y += onenand/ --- a/drivers/mtd/nand/mtk_bmt.h +++ b/drivers/mtd/nand/mtk_bmt.h @@ -77,6 +77,7 @@ extern struct bmt_desc bmtd; diff --git a/target/linux/econet/patches-6.18/902-snand-mtk-bmt-support.patch b/target/linux/econet/patches-6.18/902-snand-mtk-bmt-support.patch index 2dc81292ec..804542b9f5 100644 --- a/target/linux/econet/patches-6.18/902-snand-mtk-bmt-support.patch +++ b/target/linux/econet/patches-6.18/902-snand-mtk-bmt-support.patch @@ -6,9 +6,9 @@ #include +#include - static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) + int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) { -@@ -1604,6 +1605,7 @@ static int spinand_probe(struct spi_mem +@@ -1718,6 +1719,7 @@ static int spinand_probe(struct spi_mem if (ret) return ret; @@ -16,7 +16,7 @@ ret = mtd_device_register(mtd, NULL, 0); if (ret) goto err_spinand_cleanup; -@@ -1611,6 +1613,7 @@ static int spinand_probe(struct spi_mem +@@ -1725,6 +1727,7 @@ static int spinand_probe(struct spi_mem return 0; err_spinand_cleanup: @@ -24,7 +24,7 @@ spinand_cleanup(spinand); return ret; -@@ -1629,6 +1632,7 @@ static int spinand_remove(struct spi_mem +@@ -1743,6 +1746,7 @@ static int spinand_remove(struct spi_mem if (ret) return ret; diff --git a/target/linux/econet/patches-6.18/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch b/target/linux/econet/patches-6.18/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch index 021043a13d..61fd157b5c 100644 --- a/target/linux/econet/patches-6.18/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch +++ b/target/linux/econet/patches-6.18/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch @@ -18,7 +18,7 @@ Signed-off-by: Caleb James DeLisle --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig -@@ -210,13 +210,13 @@ config COMMON_CLK_CS2000_CP +@@ -218,13 +218,13 @@ config COMMON_CLK_CS2000_CP If you say yes here you get support for the CS2000 clock multiplier. config COMMON_CLK_EN7523 diff --git a/target/linux/econet/patches-6.18/912-pcie-add-en7528-pcie-and-phy-support.patch b/target/linux/econet/patches-6.18/912-pcie-add-en7528-pcie-and-phy-support.patch index ee8d1bdab9..0a320436cf 100644 --- a/target/linux/econet/patches-6.18/912-pcie-add-en7528-pcie-and-phy-support.patch +++ b/target/linux/econet/patches-6.18/912-pcie-add-en7528-pcie-and-phy-support.patch @@ -1,6 +1,6 @@ --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig -@@ -187,7 +187,7 @@ config PCI_MVEBU +@@ -193,7 +193,7 @@ config PCI_MVEBU config PCIE_MEDIATEK tristate "MediaTek PCIe controller" @@ -8,7 +8,7 @@ + depends on ARCH_AIROHA || ARCH_MEDIATEK || ECONET || COMPILE_TEST depends on OF depends on PCI_MSI - help + select IRQ_MSI_LIB --- a/arch/mips/econet/Kconfig +++ b/arch/mips/econet/Kconfig @@ -14,7 +14,9 @@ choice @@ -35,7 +35,7 @@ select SYS_SUPPORTS_HIGHMEM --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c -@@ -76,6 +76,7 @@ +@@ -77,6 +77,7 @@ #define PCIE_CONF_VEND_ID 0x100 #define PCIE_CONF_DEVICE_ID 0x102 @@ -43,7 +43,7 @@ #define PCIE_CONF_CLASS_ID 0x106 #define PCIE_INT_MASK 0x420 -@@ -88,6 +89,11 @@ +@@ -89,6 +90,11 @@ #define MSI_MASK BIT(23) #define MTK_MSI_IRQS_NUM 32 @@ -55,7 +55,7 @@ #define PCIE_AHB_TRANS_BASE0_L 0x438 #define PCIE_AHB_TRANS_BASE0_H 0x43c #define AHB2PCIE_SIZE(x) ((x) & GENMASK(4, 0)) -@@ -750,6 +756,86 @@ static int mtk_pcie_startup_port_v2(stru +@@ -746,6 +752,86 @@ static int mtk_pcie_startup_port_v2(stru return 0; } @@ -142,7 +142,7 @@ static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, int where) { -@@ -1116,6 +1202,20 @@ static int mtk_pcie_probe(struct platfor +@@ -1107,6 +1193,20 @@ static int mtk_pcie_probe(struct platfor if (err) goto put_resources; @@ -163,7 +163,7 @@ return 0; put_resources: -@@ -1225,12 +1325,19 @@ static const struct mtk_pcie_soc mtk_pci +@@ -1216,12 +1316,19 @@ static const struct mtk_pcie_soc mtk_pci .setup_irq = mtk_pcie_setup_irq, }; @@ -185,9 +185,9 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_ids); --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig -@@ -82,6 +82,17 @@ config PHY_AIROHA_PCIE - This driver create the basic PHY instance and provides initialize - callback for PCIe GEN3 port. +@@ -123,6 +123,17 @@ config PHY_NXP_PTN3222 + schemes. It supports all three USB 2.0 data rates: Low Speed, Full + Speed and High Speed. +config PHY_EN7528_PCIE + tristate "EcoNet EN7528 PCIe PHY Driver" @@ -205,14 +205,14 @@ source "drivers/phy/broadcom/Kconfig" --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile -@@ -11,6 +11,7 @@ obj-$(CONFIG_PHY_XGENE) += phy-xgene.o - obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o +@@ -14,6 +14,7 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy- + obj-$(CONFIG_PHY_SNPS_EUSB2) += phy-snps-eusb2.o obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o +obj-$(CONFIG_PHY_EN7528_PCIE) += phy-en7528-pcie.o - obj-y += allwinner/ \ + obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o + obj-$(CONFIG_GENERIC_PHY) += allwinner/ \ amlogic/ \ - broadcom/ \ --- /dev/null +++ b/drivers/phy/phy-en7528-pcie.c @@ -0,0 +1,155 @@ diff --git a/target/linux/econet/patches-6.18/913-pcie-fix-bogus-prefetch-window.patch b/target/linux/econet/patches-6.18/913-pcie-fix-bogus-prefetch-window.patch index 872843549d..306db192f0 100644 --- a/target/linux/econet/patches-6.18/913-pcie-fix-bogus-prefetch-window.patch +++ b/target/linux/econet/patches-6.18/913-pcie-fix-bogus-prefetch-window.patch @@ -16,7 +16,7 @@ Suggested-by: Bjorn Helgaas Signed-off-by: Ahmed Naseef --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c -@@ -349,6 +349,9 @@ static void pci_read_bridge_io(struct pc +@@ -396,6 +396,9 @@ static void pci_read_bridge_io(struct pc unsigned long io_mask, io_granularity, base, limit; struct pci_bus_region region; @@ -26,7 +26,7 @@ Signed-off-by: Ahmed Naseef io_mask = PCI_IO_RANGE_MASK; io_granularity = 0x1000; if (dev->io_window_1k) { -@@ -410,6 +413,9 @@ static void pci_read_bridge_mmio_pref(st +@@ -466,6 +469,9 @@ static void pci_read_bridge_mmio_pref(st pci_bus_addr_t base, limit; struct pci_bus_region region; diff --git a/target/linux/econet/patches-6.18/914-phy-add-en7528-usb-phy-driver.patch b/target/linux/econet/patches-6.18/914-phy-add-en7528-usb-phy-driver.patch index 308703c630..0d3f4506f4 100644 --- a/target/linux/econet/patches-6.18/914-phy-add-en7528-usb-phy-driver.patch +++ b/target/linux/econet/patches-6.18/914-phy-add-en7528-usb-phy-driver.patch @@ -9,7 +9,7 @@ and the Airoha AN7581 USB PHY driver by Christian Marangi. Signed-off-by: Ahmed Naseef --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig -@@ -93,6 +93,17 @@ config PHY_EN7528_PCIE +@@ -134,6 +134,17 @@ config PHY_EN7528_PCIE This driver provides PHY initialization for the two PCIe ports on EN7528 SoC. @@ -29,14 +29,14 @@ Signed-off-by: Ahmed Naseef source "drivers/phy/broadcom/Kconfig" --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy- +@@ -15,6 +15,7 @@ obj-$(CONFIG_PHY_SNPS_EUSB2) += phy-snp obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o obj-$(CONFIG_PHY_EN7528_PCIE) += phy-en7528-pcie.o +obj-$(CONFIG_PHY_EN7528_USB) += phy-en7528-usb.o - obj-y += allwinner/ \ + obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o + obj-$(CONFIG_GENERIC_PHY) += allwinner/ \ amlogic/ \ - broadcom/ \ --- /dev/null +++ b/drivers/phy/phy-en7528-usb.c @@ -0,0 +1,316 @@ From 16d10338cc889dc8997da7261fd7fef16bf4a98d Mon Sep 17 00:00:00 2001 From: Ahmed Naseef Date: Thu, 11 Jun 2026 18:20:06 +0400 Subject: [PATCH 014/228] econet: update config for 6.18 Regenerated with `make kernel_oldconfig` for all subtargets. Signed-off-by: Ahmed Naseef Link: https://github.com/openwrt/openwrt/pull/23755 Signed-off-by: Jonas Jelonek --- target/linux/econet/en751221/config-6.18 | 8 +++----- target/linux/econet/en751627/config-6.18 | 9 +++------ target/linux/econet/en7528/config-6.18 | 7 ++----- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/target/linux/econet/en751221/config-6.18 b/target/linux/econet/en751221/config-6.18 index fe69f10c74..523f5454dd 100644 --- a/target/linux/econet/en751221/config-6.18 +++ b/target/linux/econet/en751221/config-6.18 @@ -2,7 +2,6 @@ CONFIG_ARCH_32BIT_OFF_T=y CONFIG_ARCH_KEEP_MEMBLOCK=y CONFIG_ARCH_MMAP_RND_BITS_MAX=15 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_BLK_MQ_PCI=y CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y CONFIG_COMMON_CLK=y @@ -32,7 +31,6 @@ CONFIG_CRC16=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_GF128MUL=y CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 CONFIG_CRYPTO_LIB_UTILS=y @@ -61,7 +59,6 @@ CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_GETTIMEOFDAY=y CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IRQ_CHIP=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y @@ -90,8 +87,8 @@ CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_MSI_LIB=y CONFIG_IRQ_WORK=y -CONFIG_JFFS2_FS=y CONFIG_JFFS2_ZLIB=y CONFIG_LIBFDT=y CONFIG_LOCK_DEBUGGING_SUPPORT=y @@ -136,6 +133,7 @@ CONFIG_OF_GPIO=y CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y CONFIG_PADATA=y +CONFIG_PAGE_BLOCK_MAX_ORDER=11 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y @@ -152,6 +150,7 @@ CONFIG_PCI_MSI_ARCH_FALLBACKS=y CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_LEVELS=2 CONFIG_PHY_EN7528_PCIE=y +# CONFIG_PHY_EN7528_USB is not set CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y @@ -166,7 +165,6 @@ CONFIG_RPS=y # CONFIG_SERIAL_8250_AIROHA is not set CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y CONFIG_SMP=y CONFIG_SMP_UP=y CONFIG_SOCK_RX_QUEUE_MAPPING=y diff --git a/target/linux/econet/en751627/config-6.18 b/target/linux/econet/en751627/config-6.18 index 5e7b280d72..a078662c73 100644 --- a/target/linux/econet/en751627/config-6.18 +++ b/target/linux/econet/en751627/config-6.18 @@ -4,7 +4,6 @@ CONFIG_ARCH_KEEP_MEMBLOCK=y CONFIG_ARCH_MMAP_RND_BITS_MAX=15 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_BLK_MQ_PCI=y CONFIG_BOARD_SCACHE=y CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y @@ -37,10 +36,8 @@ CONFIG_CRC16=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_GF128MUL=y CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LIB_SHA1=y CONFIG_CRYPTO_LIB_UTILS=y CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_ZSTD=y @@ -66,7 +63,6 @@ CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_GETTIMEOFDAY=y CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IRQ_CHIP=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y @@ -97,6 +93,7 @@ CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_MSI_LIB=y CONFIG_IRQ_WORK=y # CONFIG_JFFS2_FS is not set CONFIG_LEDS_GPIO=y @@ -155,6 +152,7 @@ CONFIG_OF_GPIO=y CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y CONFIG_PADATA=y +CONFIG_PAGE_BLOCK_MAX_ORDER=11 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y @@ -168,6 +166,7 @@ CONFIG_PCI_MSI_ARCH_FALLBACKS=y CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_LEVELS=2 CONFIG_PHY_EN7528_PCIE=y +# CONFIG_PHY_EN7528_USB is not set CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y @@ -183,7 +182,6 @@ CONFIG_SCHED_SMT=y CONFIG_SERIAL_8250_AIROHA=y CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y CONFIG_SMP=y CONFIG_SMP_UP=y CONFIG_SOCK_RX_QUEUE_MAPPING=y @@ -209,7 +207,6 @@ CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_MIPS16=y CONFIG_SYS_SUPPORTS_MIPS_CPS=y CONFIG_SYS_SUPPORTS_MULTITHREADING=y -CONFIG_SYS_SUPPORTS_SCHED_SMT=y CONFIG_SYS_SUPPORTS_SMP=y CONFIG_SYS_SUPPORTS_ZBOOT=y CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y diff --git a/target/linux/econet/en7528/config-6.18 b/target/linux/econet/en7528/config-6.18 index f577834028..cef1186274 100644 --- a/target/linux/econet/en7528/config-6.18 +++ b/target/linux/econet/en7528/config-6.18 @@ -4,7 +4,6 @@ CONFIG_ARCH_KEEP_MEMBLOCK=y CONFIG_ARCH_MMAP_RND_BITS_MAX=15 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_BLK_MQ_PCI=y CONFIG_BOARD_SCACHE=y CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y @@ -37,7 +36,6 @@ CONFIG_CRC16=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_GF128MUL=y CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 CONFIG_CRYPTO_LIB_UTILS=y @@ -65,7 +63,6 @@ CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_GETTIMEOFDAY=y CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IRQ_CHIP=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_SHOW=y @@ -96,6 +93,7 @@ CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_MSI_LIB=y CONFIG_IRQ_WORK=y # CONFIG_JFFS2_FS is not set CONFIG_LEDS_GPIO=y @@ -154,6 +152,7 @@ CONFIG_OF_GPIO=y CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y CONFIG_PADATA=y +CONFIG_PAGE_BLOCK_MAX_ORDER=11 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y @@ -185,7 +184,6 @@ CONFIG_SCHED_SMT=y CONFIG_SERIAL_8250_AIROHA=y CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y CONFIG_SMP=y CONFIG_SMP_UP=y CONFIG_SOCK_RX_QUEUE_MAPPING=y @@ -211,7 +209,6 @@ CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_SYS_SUPPORTS_MIPS16=y CONFIG_SYS_SUPPORTS_MIPS_CPS=y CONFIG_SYS_SUPPORTS_MULTITHREADING=y -CONFIG_SYS_SUPPORTS_SCHED_SMT=y CONFIG_SYS_SUPPORTS_SMP=y CONFIG_SYS_SUPPORTS_ZBOOT=y CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y From 7ed3c81248def6886e6034d2272d4b13a3fad7d8 Mon Sep 17 00:00:00 2001 From: Ahmed Naseef Date: Thu, 11 Jun 2026 18:20:06 +0400 Subject: [PATCH 015/228] econet: enable 6.18 testing kernel Add building the 6.18 kernel for econet as testing. Signed-off-by: Ahmed Naseef Link: https://github.com/openwrt/openwrt/pull/23755 Signed-off-by: Jonas Jelonek --- target/linux/econet/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/econet/Makefile b/target/linux/econet/Makefile index c0318ef85d..2341f6b70d 100644 --- a/target/linux/econet/Makefile +++ b/target/linux/econet/Makefile @@ -10,6 +10,7 @@ FEATURES:=dt source-only squashfs nand usb SUBTARGETS:=en751221 en751627 en7528 KERNEL_PATCHVER:=6.12 +KERNEL_TESTING_PATCHVER:=6.18 define Target/Description Build firmware image for EcoNet EN75xx MIPS based boards. From 45b8cb0ce4fe9c12ce1e7fac03db2346e76e0f6d Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 16 Jun 2026 11:20:05 +0200 Subject: [PATCH 016/228] mtd: bump package release This commit fixes "a5107ad58c6 mtd: fix buffer leak and fd leak in mtd_dump()" which changed the code but did not increase the release. This causes two packages with the same version to have different content and thereby hashes. Signed-off-by: Paul Spooren Link: https://github.com/openwrt/openwrt/pull/23827 Signed-off-by: Christian Marangi --- package/system/mtd/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/system/mtd/Makefile b/package/system/mtd/Makefile index d83e3599d8..adc4a3d218 100644 --- a/package/system/mtd/Makefile +++ b/package/system/mtd/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mtd -PKG_RELEASE:=27 +PKG_RELEASE:=28 PKG_BUILD_DIR := $(KERNEL_BUILD_DIR)/$(PKG_NAME) STAMP_PREPARED := $(STAMP_PREPARED)_$(call confvar,CONFIG_MTD_REDBOOT_PARTS) From 4315c52a9fa215a5d0066055b195bf6f8b28208e Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 16 Jun 2026 11:24:16 +0200 Subject: [PATCH 017/228] button-hotplug: bump package release This commit fixes "286f377389a button-hotplug: add KEY_SETUP and KEY_VENDOR handling" which changed the code without bumping the PKG_RELEASE, resulting in different binaries under the same version. Signed-off-by: Paul Spooren Link: https://github.com/openwrt/openwrt/pull/23826 Signed-off-by: Christian Marangi --- package/kernel/button-hotplug/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/kernel/button-hotplug/Makefile b/package/kernel/button-hotplug/Makefile index 8e8c02609c..2908e5b030 100644 --- a/package/kernel/button-hotplug/Makefile +++ b/package/kernel/button-hotplug/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=button-hotplug -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_LICENSE:=GPL-2.0 include $(INCLUDE_DIR)/package.mk From 86cc4d84bb988436dfeb3e7befefa3ebff7b5940 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Apr 2026 18:07:20 -0700 Subject: [PATCH 018/228] ath79: move intc driver out of patch This driver has been attempted to be upstreamed once and never again. Keep it local to make modification easier. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- .../files/drivers/irqchip/irq-ath79-intc.c | 142 +++++++++++++++++ ...9-intc-add-irq-cascade-driver-for-QC.patch | 145 ------------------ ...9-intc-add-irq-cascade-driver-for-QC.patch | 145 ------------------ 3 files changed, 142 insertions(+), 290 deletions(-) create mode 100644 target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c new file mode 100644 index 0000000000..4d06a3e829 --- /dev/null +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -0,0 +1,142 @@ +/* + * Atheros AR71xx/AR724x/AR913x specific interrupt handling + * + * Copyright (C) 2018 John Crispin + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define ATH79_MAX_INTC_CASCADE 3 + +struct ath79_intc { + struct irq_chip chip; + u32 irq; + u32 pending_mask; + u32 int_status; + u32 irq_mask[ATH79_MAX_INTC_CASCADE]; + u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; +}; + +static void ath79_intc_irq_handler(struct irq_desc *desc) +{ + struct irq_domain *domain = irq_desc_get_handler_data(desc); + struct ath79_intc *intc = domain->host_data; + u32 pending; + + pending = ath79_reset_rr(intc->int_status); + pending &= intc->pending_mask; + + if (pending) { + int i; + + for (i = 0; i < domain->hwirq_max; i++) + if (pending & intc->irq_mask[i]) { + if (intc->irq_wb_chan[i] != 0xffffffff) + ath79_ddr_wb_flush(intc->irq_wb_chan[i]); + generic_handle_irq(irq_find_mapping(domain, i)); + } + } else { + spurious_interrupt(); + } +} + +static void ath79_intc_irq_enable(struct irq_data *d) +{ + struct ath79_intc *intc = d->domain->host_data; + enable_irq(intc->irq); +} + +static void ath79_intc_irq_disable(struct irq_data *d) +{ + struct ath79_intc *intc = d->domain->host_data; + disable_irq(intc->irq); +} + +static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) +{ + struct ath79_intc *intc = d->host_data; + + irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); + + return 0; +} + +static const struct irq_domain_ops ath79_irq_domain_ops = { + .xlate = irq_domain_xlate_onecell, + .map = ath79_intc_map, +}; + +static int __init ath79_intc_of_init( + struct device_node *node, struct device_node *parent) +{ + struct irq_domain *domain; + struct ath79_intc *intc; + int cnt, cntwb, i, err; + + cnt = of_property_count_u32_elems(node, "qca,pending-bits"); + if (cnt > ATH79_MAX_INTC_CASCADE) + panic("Too many INTC pending bits\n"); + + intc = kzalloc(sizeof(*intc), GFP_KERNEL); + if (!intc) + panic("Failed to allocate INTC memory\n"); + intc->chip = dummy_irq_chip; + intc->chip.name = "INTC"; + intc->chip.irq_disable = ath79_intc_irq_disable; + intc->chip.irq_enable = ath79_intc_irq_enable; + + if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { + panic("Missing address of interrupt status register\n"); + } + + of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); + for (i = 0; i < cnt; i++) { + intc->pending_mask |= intc->irq_mask[i]; + intc->irq_wb_chan[i] = 0xffffffff; + } + + cntwb = of_count_phandle_with_args( + node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); + + for (i = 0; i < cntwb; i++) { + struct of_phandle_args args; + u32 irq = i; + + of_property_read_u32_index( + node, "qca,ddr-wb-channel-interrupts", i, &irq); + if (irq >= ATH79_MAX_INTC_CASCADE) + continue; + + err = of_parse_phandle_with_args( + node, "qca,ddr-wb-channels", + "#qca,ddr-wb-channel-cells", + i, &args); + if (err) + return err; + + intc->irq_wb_chan[irq] = args.args[0]; + } + + intc->irq = irq_of_parse_and_map(node, 0); + if (!intc->irq) + panic("Failed to get INTC IRQ"); + + domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); + irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); + + return 0; +} +IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", + ath79_intc_of_init); diff --git a/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch index ceda511c21..4d0cadc7e6 100644 --- a/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch +++ b/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch @@ -21,148 +21,3 @@ Signed-off-by: John Crispin obj-$(CONFIG_ATH79) += irq-ath79-misc.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o ---- /dev/null -+++ b/drivers/irqchip/irq-ath79-intc.c -@@ -0,0 +1,142 @@ -+/* -+ * Atheros AR71xx/AR724x/AR913x specific interrupt handling -+ * -+ * Copyright (C) 2018 John Crispin -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define ATH79_MAX_INTC_CASCADE 3 -+ -+struct ath79_intc { -+ struct irq_chip chip; -+ u32 irq; -+ u32 pending_mask; -+ u32 int_status; -+ u32 irq_mask[ATH79_MAX_INTC_CASCADE]; -+ u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; -+}; -+ -+static void ath79_intc_irq_handler(struct irq_desc *desc) -+{ -+ struct irq_domain *domain = irq_desc_get_handler_data(desc); -+ struct ath79_intc *intc = domain->host_data; -+ u32 pending; -+ -+ pending = ath79_reset_rr(intc->int_status); -+ pending &= intc->pending_mask; -+ -+ if (pending) { -+ int i; -+ -+ for (i = 0; i < domain->hwirq_max; i++) -+ if (pending & intc->irq_mask[i]) { -+ if (intc->irq_wb_chan[i] != 0xffffffff) -+ ath79_ddr_wb_flush(intc->irq_wb_chan[i]); -+ generic_handle_irq(irq_find_mapping(domain, i)); -+ } -+ } else { -+ spurious_interrupt(); -+ } -+} -+ -+static void ath79_intc_irq_enable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ enable_irq(intc->irq); -+} -+ -+static void ath79_intc_irq_disable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ disable_irq(intc->irq); -+} -+ -+static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -+{ -+ struct ath79_intc *intc = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops ath79_irq_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = ath79_intc_map, -+}; -+ -+static int __init ath79_intc_of_init( -+ struct device_node *node, struct device_node *parent) -+{ -+ struct irq_domain *domain; -+ struct ath79_intc *intc; -+ int cnt, cntwb, i, err; -+ -+ cnt = of_property_count_u32_elems(node, "qca,pending-bits"); -+ if (cnt > ATH79_MAX_INTC_CASCADE) -+ panic("Too many INTC pending bits\n"); -+ -+ intc = kzalloc(sizeof(*intc), GFP_KERNEL); -+ if (!intc) -+ panic("Failed to allocate INTC memory\n"); -+ intc->chip = dummy_irq_chip; -+ intc->chip.name = "INTC"; -+ intc->chip.irq_disable = ath79_intc_irq_disable; -+ intc->chip.irq_enable = ath79_intc_irq_enable; -+ -+ if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { -+ panic("Missing address of interrupt status register\n"); -+ } -+ -+ of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); -+ for (i = 0; i < cnt; i++) { -+ intc->pending_mask |= intc->irq_mask[i]; -+ intc->irq_wb_chan[i] = 0xffffffff; -+ } -+ -+ cntwb = of_count_phandle_with_args( -+ node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); -+ -+ for (i = 0; i < cntwb; i++) { -+ struct of_phandle_args args; -+ u32 irq = i; -+ -+ of_property_read_u32_index( -+ node, "qca,ddr-wb-channel-interrupts", i, &irq); -+ if (irq >= ATH79_MAX_INTC_CASCADE) -+ continue; -+ -+ err = of_parse_phandle_with_args( -+ node, "qca,ddr-wb-channels", -+ "#qca,ddr-wb-channel-cells", -+ i, &args); -+ if (err) -+ return err; -+ -+ intc->irq_wb_chan[irq] = args.args[0]; -+ } -+ -+ intc->irq = irq_of_parse_and_map(node, 0); -+ if (!intc->irq) -+ panic("Failed to get INTC IRQ"); -+ -+ domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); -+ irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); -+ -+ return 0; -+} -+IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", -+ ath79_intc_of_init); diff --git a/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch index ceda511c21..4d0cadc7e6 100644 --- a/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch +++ b/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch @@ -21,148 +21,3 @@ Signed-off-by: John Crispin obj-$(CONFIG_ATH79) += irq-ath79-misc.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o ---- /dev/null -+++ b/drivers/irqchip/irq-ath79-intc.c -@@ -0,0 +1,142 @@ -+/* -+ * Atheros AR71xx/AR724x/AR913x specific interrupt handling -+ * -+ * Copyright (C) 2018 John Crispin -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define ATH79_MAX_INTC_CASCADE 3 -+ -+struct ath79_intc { -+ struct irq_chip chip; -+ u32 irq; -+ u32 pending_mask; -+ u32 int_status; -+ u32 irq_mask[ATH79_MAX_INTC_CASCADE]; -+ u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; -+}; -+ -+static void ath79_intc_irq_handler(struct irq_desc *desc) -+{ -+ struct irq_domain *domain = irq_desc_get_handler_data(desc); -+ struct ath79_intc *intc = domain->host_data; -+ u32 pending; -+ -+ pending = ath79_reset_rr(intc->int_status); -+ pending &= intc->pending_mask; -+ -+ if (pending) { -+ int i; -+ -+ for (i = 0; i < domain->hwirq_max; i++) -+ if (pending & intc->irq_mask[i]) { -+ if (intc->irq_wb_chan[i] != 0xffffffff) -+ ath79_ddr_wb_flush(intc->irq_wb_chan[i]); -+ generic_handle_irq(irq_find_mapping(domain, i)); -+ } -+ } else { -+ spurious_interrupt(); -+ } -+} -+ -+static void ath79_intc_irq_enable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ enable_irq(intc->irq); -+} -+ -+static void ath79_intc_irq_disable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ disable_irq(intc->irq); -+} -+ -+static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -+{ -+ struct ath79_intc *intc = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops ath79_irq_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = ath79_intc_map, -+}; -+ -+static int __init ath79_intc_of_init( -+ struct device_node *node, struct device_node *parent) -+{ -+ struct irq_domain *domain; -+ struct ath79_intc *intc; -+ int cnt, cntwb, i, err; -+ -+ cnt = of_property_count_u32_elems(node, "qca,pending-bits"); -+ if (cnt > ATH79_MAX_INTC_CASCADE) -+ panic("Too many INTC pending bits\n"); -+ -+ intc = kzalloc(sizeof(*intc), GFP_KERNEL); -+ if (!intc) -+ panic("Failed to allocate INTC memory\n"); -+ intc->chip = dummy_irq_chip; -+ intc->chip.name = "INTC"; -+ intc->chip.irq_disable = ath79_intc_irq_disable; -+ intc->chip.irq_enable = ath79_intc_irq_enable; -+ -+ if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { -+ panic("Missing address of interrupt status register\n"); -+ } -+ -+ of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); -+ for (i = 0; i < cnt; i++) { -+ intc->pending_mask |= intc->irq_mask[i]; -+ intc->irq_wb_chan[i] = 0xffffffff; -+ } -+ -+ cntwb = of_count_phandle_with_args( -+ node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); -+ -+ for (i = 0; i < cntwb; i++) { -+ struct of_phandle_args args; -+ u32 irq = i; -+ -+ of_property_read_u32_index( -+ node, "qca,ddr-wb-channel-interrupts", i, &irq); -+ if (irq >= ATH79_MAX_INTC_CASCADE) -+ continue; -+ -+ err = of_parse_phandle_with_args( -+ node, "qca,ddr-wb-channels", -+ "#qca,ddr-wb-channel-cells", -+ i, &args); -+ if (err) -+ return err; -+ -+ intc->irq_wb_chan[irq] = args.args[0]; -+ } -+ -+ intc->irq = irq_of_parse_and_map(node, 0); -+ if (!intc->irq) -+ panic("Failed to get INTC IRQ"); -+ -+ domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); -+ irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); -+ -+ return 0; -+} -+IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", -+ ath79_intc_of_init); From 03543454933b937b1a36dceb878cd30ac6ce7ae8 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Apr 2026 18:17:45 -0700 Subject: [PATCH 019/228] irq-ath79-intc: remove panic and add kfree Panic like this was recommended against in the original review of the upstream submission. Remove it and add missing kfree calls. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- .../files/drivers/irqchip/irq-ath79-intc.c | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index 4d06a3e829..17df8fd07c 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -86,19 +86,26 @@ static int __init ath79_intc_of_init( int cnt, cntwb, i, err; cnt = of_property_count_u32_elems(node, "qca,pending-bits"); - if (cnt > ATH79_MAX_INTC_CASCADE) - panic("Too many INTC pending bits\n"); + if (cnt > ATH79_MAX_INTC_CASCADE) { + pr_err("Too many INTC pending bits\n"); + return -ENOMEM; + } intc = kzalloc(sizeof(*intc), GFP_KERNEL); - if (!intc) - panic("Failed to allocate INTC memory\n"); + if (!intc) { + pr_err("Failed to allocate INTC memory\n"); + return -EINVAL; + } + intc->chip = dummy_irq_chip; intc->chip.name = "INTC"; intc->chip.irq_disable = ath79_intc_irq_disable; intc->chip.irq_enable = ath79_intc_irq_enable; if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { - panic("Missing address of interrupt status register\n"); + pr_err("Missing address of interrupt status register\n"); + err = -EINVAL; + goto err; } of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); @@ -124,19 +131,26 @@ static int __init ath79_intc_of_init( "#qca,ddr-wb-channel-cells", i, &args); if (err) - return err; + goto err; intc->irq_wb_chan[irq] = args.args[0]; } intc->irq = irq_of_parse_and_map(node, 0); - if (!intc->irq) - panic("Failed to get INTC IRQ"); + if (!intc->irq) { + pr_err("Failed to get INTC IRQ"); + err = -EINVAL; + goto err; + } domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); return 0; + +err: + kfree(intc); + return err; } IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", ath79_intc_of_init); From 122ea336de25271c2f7329ca3b69801ff85420e3 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Apr 2026 18:56:31 -0700 Subject: [PATCH 020/228] irq-ath79-intc: switch from add to create Upstream Linux wants to remove the add APIs. Get ahead of this and make the switch as was done upstream in affdc0d1bdfa544fed26ae07c4e136af86465507 Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index 17df8fd07c..a9d633e9e5 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -143,7 +143,7 @@ static int __init ath79_intc_of_init( goto err; } - domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); + domain = irq_domain_create_linear(of_fwnode_handle(node), cnt, &ath79_irq_domain_ops, intc); irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); return 0; From e46cc54e9d82019354d43fa72cf1ab7c69ac16d8 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Apr 2026 18:59:36 -0700 Subject: [PATCH 021/228] irq-ath79-intc: add SPDX license License boilerplate was deprecated by upstream in d2912cb15bdda8ba4a5dd73396ad62641af2f520 Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index a9d633e9e5..ae32a4ae06 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Atheros AR71xx/AR724x/AR913x specific interrupt handling * * Copyright (C) 2018 John Crispin - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. */ #include From 20275da9cdb6d4c552171a16fb44d6802833d641 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Apr 2026 19:02:28 -0700 Subject: [PATCH 022/228] irq-ath79-intc: use generic_handle_domain_irq Combines irq_find_mapping and generic_handle_irq. Matches upstream commit 046a6ee2343bb26d85a9973a39ccdb9764236fa4 Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index ae32a4ae06..fd34894f76 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -42,7 +42,7 @@ static void ath79_intc_irq_handler(struct irq_desc *desc) if (pending & intc->irq_mask[i]) { if (intc->irq_wb_chan[i] != 0xffffffff) ath79_ddr_wb_flush(intc->irq_wb_chan[i]); - generic_handle_irq(irq_find_mapping(domain, i)); + generic_handle_domain_irq(domain, i); } } else { spurious_interrupt(); From 10d7a164add7cb928e4dab7622a3fd4f2300db7f Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Apr 2026 19:07:32 -0700 Subject: [PATCH 023/228] irq-ath79-intc: don't use hwirq_max Original review said: Don't. This is an implementation detail of the irq domain, and you're not supposed to access that field. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index fd34894f76..90e7ab8d91 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -20,6 +20,7 @@ struct ath79_intc { struct irq_chip chip; u32 irq; + u32 num_irqs; u32 pending_mask; u32 int_status; u32 irq_mask[ATH79_MAX_INTC_CASCADE]; @@ -38,7 +39,7 @@ static void ath79_intc_irq_handler(struct irq_desc *desc) if (pending) { int i; - for (i = 0; i < domain->hwirq_max; i++) + for (i = 0; i < intc->num_irqs; i++) if (pending & intc->irq_mask[i]) { if (intc->irq_wb_chan[i] != 0xffffffff) ath79_ddr_wb_flush(intc->irq_wb_chan[i]); @@ -98,6 +99,7 @@ static int __init ath79_intc_of_init( intc->chip.name = "INTC"; intc->chip.irq_disable = ath79_intc_irq_disable; intc->chip.irq_enable = ath79_intc_irq_enable; + intc->num_irqs = cnt; if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { pr_err("Missing address of interrupt status register\n"); From 5ed10923f98a617274165caae6be11cc44de9143 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Apr 2026 19:23:02 -0700 Subject: [PATCH 024/228] irq-ath79-intc: rename pending_mask to enable_mask Original review said: Isn't this "pending_mask" more of an "enabled"? Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index 90e7ab8d91..4945215d12 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -21,7 +21,7 @@ struct ath79_intc { struct irq_chip chip; u32 irq; u32 num_irqs; - u32 pending_mask; + u32 enable_mask; u32 int_status; u32 irq_mask[ATH79_MAX_INTC_CASCADE]; u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; @@ -34,7 +34,7 @@ static void ath79_intc_irq_handler(struct irq_desc *desc) u32 pending; pending = ath79_reset_rr(intc->int_status); - pending &= intc->pending_mask; + pending &= intc->enable_mask; if (pending) { int i; @@ -109,7 +109,7 @@ static int __init ath79_intc_of_init( of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); for (i = 0; i < cnt; i++) { - intc->pending_mask |= intc->irq_mask[i]; + intc->enable_mask |= intc->irq_mask[i]; intc->irq_wb_chan[i] = 0xffffffff; } From 3c2e7b3eee03c62ae51e5fb5797ffbf312386def Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Apr 2026 19:12:59 -0700 Subject: [PATCH 025/228] irq-ath79-intc: add chained_irq_enter/exit Original review said: Missing chained_irq_enter/exit calls. Also rework slightly to reduce indentation. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- .../files/drivers/irqchip/irq-ath79-intc.c | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index 4945215d12..fc938ad482 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -30,24 +31,30 @@ struct ath79_intc { static void ath79_intc_irq_handler(struct irq_desc *desc) { struct irq_domain *domain = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); struct ath79_intc *intc = domain->host_data; u32 pending; + int i; + + chained_irq_enter(chip, desc); pending = ath79_reset_rr(intc->int_status); pending &= intc->enable_mask; - if (pending) { - int i; - - for (i = 0; i < intc->num_irqs; i++) - if (pending & intc->irq_mask[i]) { - if (intc->irq_wb_chan[i] != 0xffffffff) - ath79_ddr_wb_flush(intc->irq_wb_chan[i]); - generic_handle_domain_irq(domain, i); - } - } else { + if (!pending) { spurious_interrupt(); + chained_irq_exit(chip, desc); + return; } + + for (i = 0; i < intc->num_irqs; i++) + if (pending & intc->irq_mask[i]) { + if (intc->irq_wb_chan[i] != 0xffffffff) + ath79_ddr_wb_flush(intc->irq_wb_chan[i]); + generic_handle_domain_irq(domain, i); + } + + chained_irq_exit(chip, desc); } static void ath79_intc_irq_enable(struct irq_data *d) From 4ae9c7bdc1f9bc904be8c69b5fe9e7d30e23f9b0 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Apr 2026 21:25:50 -0700 Subject: [PATCH 026/228] irq-ath79-intc: statically allocate irq_chip No need for dynamic allocation. static is fine. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- .../files/drivers/irqchip/irq-ath79-intc.c | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index fc938ad482..c7a5148425 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -19,7 +19,6 @@ #define ATH79_MAX_INTC_CASCADE 3 struct ath79_intc { - struct irq_chip chip; u32 irq; u32 num_irqs; u32 enable_mask; @@ -69,12 +68,15 @@ static void ath79_intc_irq_disable(struct irq_data *d) disable_irq(intc->irq); } +static const struct irq_chip ath79_intc_irq_chip = { + .name = "INTC", + .irq_enable = ath79_intc_irq_enable, + .irq_disable = ath79_intc_irq_disable, +}; + static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { - struct ath79_intc *intc = d->host_data; - - irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); - + irq_set_chip_and_handler(irq, &ath79_intc_irq_chip, handle_level_irq); return 0; } @@ -91,21 +93,15 @@ static int __init ath79_intc_of_init( int cnt, cntwb, i, err; cnt = of_property_count_u32_elems(node, "qca,pending-bits"); - if (cnt > ATH79_MAX_INTC_CASCADE) { - pr_err("Too many INTC pending bits\n"); - return -ENOMEM; - } - - intc = kzalloc(sizeof(*intc), GFP_KERNEL); - if (!intc) { - pr_err("Failed to allocate INTC memory\n"); + if (cnt < 0 || cnt > ATH79_MAX_INTC_CASCADE) { + pr_err("Invalid number of INTC pending bits (%d)\n", cnt); return -EINVAL; } - intc->chip = dummy_irq_chip; - intc->chip.name = "INTC"; - intc->chip.irq_disable = ath79_intc_irq_disable; - intc->chip.irq_enable = ath79_intc_irq_enable; + intc = kzalloc(sizeof(*intc), GFP_KERNEL); + if (!intc) + return -ENOMEM; + intc->num_irqs = cnt; if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { @@ -129,7 +125,7 @@ static int __init ath79_intc_of_init( of_property_read_u32_index( node, "qca,ddr-wb-channel-interrupts", i, &irq); - if (irq >= ATH79_MAX_INTC_CASCADE) + if (irq >= intc->num_irqs) continue; err = of_parse_phandle_with_args( @@ -150,6 +146,11 @@ static int __init ath79_intc_of_init( } domain = irq_domain_create_linear(of_fwnode_handle(node), cnt, &ath79_irq_domain_ops, intc); + if (!domain) { + err = -EINVAL; + goto err; + } + irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); return 0; From dbb4ac9342d44c0990cf7ec48961f05aa3ae508c Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 23 Apr 2026 13:00:25 -0700 Subject: [PATCH 027/228] irq-ath79-intc: add irq_dispose_mapping Avoids a resource leak on failure. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index c7a5148425..ae15695e92 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -148,13 +148,15 @@ static int __init ath79_intc_of_init( domain = irq_domain_create_linear(of_fwnode_handle(node), cnt, &ath79_irq_domain_ops, intc); if (!domain) { err = -EINVAL; - goto err; + goto err_irq; } irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); return 0; +err_irq: + irq_dispose_mapping(intc->irq); err: kfree(intc); return err; From 00841615f1dcb81045b069d7a1d2778d2d483e34 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 23 Apr 2026 13:06:47 -0700 Subject: [PATCH 028/228] irq-ath79-intc: avoid negative values of_count_phandle_with_args can return negative. We don't want that. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index ae15695e92..fdec0d39c7 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -118,6 +118,7 @@ static int __init ath79_intc_of_init( cntwb = of_count_phandle_with_args( node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); + cntwb = max(0, cntwb); for (i = 0; i < cntwb; i++) { struct of_phandle_args args; From faf8f3760d2b7f4d6a393d71f581ba53afb838cd Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 23 Apr 2026 13:09:36 -0700 Subject: [PATCH 029/228] irq-ath79-intc: add missing \n Needed to make the dmesg output normal. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index fdec0d39c7..565c2a5fde 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -141,7 +141,7 @@ static int __init ath79_intc_of_init( intc->irq = irq_of_parse_and_map(node, 0); if (!intc->irq) { - pr_err("Failed to get INTC IRQ"); + pr_err("Failed to get INTC IRQ\n"); err = -EINVAL; goto err; } From 0a9fcdf5715ffd6cd384775f4a98494026543061 Mon Sep 17 00:00:00 2001 From: Etienne Champetier Date: Sat, 24 Jan 2026 16:31:03 -0500 Subject: [PATCH 030/228] prereq-build/u-boot: add Python 3.14 support Python 3.14 is the default version on Fedora 43/44. Signed-off-by: Etienne Champetier Link: https://github.com/openwrt/openwrt/pull/23243 Signed-off-by: Test Dev --- include/prereq-build.mk | 2 ++ include/u-boot.mk | 1 + 2 files changed, 3 insertions(+) diff --git a/include/prereq-build.mk b/include/prereq-build.mk index f37ea3bd08..686bfab2ba 100644 --- a/include/prereq-build.mk +++ b/include/prereq-build.mk @@ -187,6 +187,7 @@ $(eval $(call SetupHostCommand,perl,Please install Perl 5.x, \ perl --version | grep "perl.*v5")) $(eval $(call SetupHostCommand,python,Please install Python >= 3.8, \ + python3.14 -V 2>&1 | grep 'Python 3', \ python3.13 -V 2>&1 | grep 'Python 3', \ python3.12 -V 2>&1 | grep 'Python 3', \ python3.11 -V 2>&1 | grep 'Python 3', \ @@ -196,6 +197,7 @@ $(eval $(call SetupHostCommand,python,Please install Python >= 3.8, \ python3 -V 2>&1 | grep -E 'Python 3\.([8-9]|[0-9][0-9])\.?')) $(eval $(call SetupHostCommand,python3,Please install Python >= 3.8, \ + python3.14 -V 2>&1 | grep 'Python 3', \ python3.13 -V 2>&1 | grep 'Python 3', \ python3.12 -V 2>&1 | grep 'Python 3', \ python3.11 -V 2>&1 | grep 'Python 3', \ diff --git a/include/u-boot.mk b/include/u-boot.mk index 37ce68e7e7..bdf77f1612 100644 --- a/include/u-boot.mk +++ b/include/u-boot.mk @@ -29,6 +29,7 @@ endif ifdef UBOOT_USE_INTREE_DTC $(eval $(call TestHostCommand,python3-dev, \ Please install the python3-dev package, \ + python3.14-config --includes 2>&1 | grep 'python3', \ python3.13-config --includes 2>&1 | grep 'python3', \ python3.12-config --includes 2>&1 | grep 'python3', \ python3.11-config --includes 2>&1 | grep 'python3', \ From 13fc688f033895e0ba91c1d752ffd63a06760ef5 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 2 May 2026 19:31:43 +0200 Subject: [PATCH 031/228] base-files: support rootfs_data on its own partition The current code assumes that the rootfs_data UBI volume is on the same MTD partition as the rootfs. Unfortunately, this does not work on the Aruba AP-325 (and variants), since the bootloader enforces a particular UBI volume layout. Therefore, this adds a separate variable to set the rootfs_data partition, and updates all existing devices with a non-default rootfs partition to also specify the new variable. Signed-off-by: Lukas Stockner Link: https://github.com/openwrt/openwrt/pull/20738 Signed-off-by: Test Dev --- package/base-files/files/lib/upgrade/nand.sh | 40 +++++++++---------- .../base-files/lib/upgrade/platform.sh | 1 + .../base-files/lib/upgrade/platform.sh | 1 + .../base-files/lib/upgrade/platform.sh | 1 + .../base-files/lib/upgrade/platform.sh | 3 ++ 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh index 22f9cce42a..e4a255b9c0 100644 --- a/package/base-files/files/lib/upgrade/nand.sh +++ b/package/base-files/files/lib/upgrade/nand.sh @@ -7,8 +7,9 @@ CI_KERNPART="${CI_KERNPART:-kernel}" # 'ubi' partition on NAND contains UBI -# There are also CI_KERN_UBIPART and CI_ROOT_UBIPART if kernel -# and rootfs are on separated UBIs. +# If individual UBI volumes are on different partitions, +# they can be set with CI_KERN_UBIPART, CI_ROOT_UBIPART and/or +# CI_DATA_UBIPART. CI_UBIPART="${CI_UBIPART:-ubi}" # 'rootfs' UBI volume on NAND contains the rootfs @@ -77,9 +78,10 @@ identify_if_gzip() { } nand_restore_config() { - local ubidev=$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" ) + local ubidev=$( nand_find_ubi "${CI_DATA_UBIPART:-$CI_UBIPART}" ) local ubivol="$( nand_find_volume $ubidev rootfs_data )" if [ ! "$ubivol" ]; then + local ubidev=$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" ) ubivol="$( nand_find_volume $ubidev "$CI_ROOTPART" )" if [ ! "$ubivol" ]; then echo "cannot find ubifs data volume" @@ -188,23 +190,21 @@ nand_upgrade_prepare_ubi() { local has_env="${4:-0}" local kern_ubidev local root_ubidev + local data_ubidev [ -n "$rootfs_length" -o -n "$kernel_length" ] || return 1 - if [ -n "$CI_KERN_UBIPART" -a -n "$CI_ROOT_UBIPART" ]; then - kern_ubidev="$( nand_attach_ubi "$CI_KERN_UBIPART" "$has_env" )" - [ -n "$kern_ubidev" ] || return 1 - root_ubidev="$( nand_attach_ubi "$CI_ROOT_UBIPART" )" - [ -n "$root_ubidev" ] || return 1 - else - kern_ubidev="$( nand_attach_ubi "$CI_UBIPART" "$has_env" )" - [ -n "$kern_ubidev" ] || return 1 - root_ubidev="$kern_ubidev" - fi + # Attach UBI partitions (might be identical, but nand_attach_ubi handles that) + kern_ubidev="$( nand_attach_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}" "$has_env" )" + [ -n "$kern_ubidev" ] || return 1 + root_ubidev="$( nand_attach_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )" + [ -n "$root_ubidev" ] || return 1 + data_ubidev="$( nand_attach_ubi "${CI_DATA_UBIPART:-$CI_UBIPART}" )" + [ -n "$data_ubidev" ] || return 1 local kern_ubivol="$( nand_find_volume $kern_ubidev "$CI_KERNPART" )" local root_ubivol="$( nand_find_volume $root_ubidev "$CI_ROOTPART" )" - local data_ubivol="$( nand_find_volume $root_ubidev rootfs_data )" + local data_ubivol="$( nand_find_volume $data_ubidev rootfs_data )" [ "$root_ubivol" = "$kern_ubivol" ] && root_ubivol= # remove ubiblocks @@ -215,7 +215,7 @@ nand_upgrade_prepare_ubi() { # kill volumes [ "$kern_ubivol" ] && ubirmvol /dev/$kern_ubidev -N "$CI_KERNPART" || : [ "$root_ubivol" ] && ubirmvol /dev/$root_ubidev -N "$CI_ROOTPART" || : - [ "$data_ubivol" ] && ubirmvol /dev/$root_ubidev -N rootfs_data || : + [ "$data_ubivol" ] && ubirmvol /dev/$data_ubidev -N rootfs_data || : # create provisioning vol if [ "${UPGRADE_OPT_ADD_PROVISIONING:-0}" -gt 0 ]; then @@ -255,8 +255,8 @@ nand_upgrade_prepare_ubi() { if [ -n "$rootfs_data_max" ]; then rootfs_data_size_param="-s $rootfs_data_max" fi - if ! ubimkvol /dev/$root_ubidev -N rootfs_data $rootfs_data_size_param; then - if ! ubimkvol /dev/$root_ubidev -N rootfs_data -m; then + if ! ubimkvol /dev/$data_ubidev -N rootfs_data $rootfs_data_size_param; then + if ! ubimkvol /dev/$data_ubidev -N rootfs_data -m; then echo "cannot initialize rootfs_data volume" return 1 fi @@ -288,8 +288,8 @@ nand_upgrade_ubifs() { nand_upgrade_prepare_ubi "$ubifs_length" "ubifs" "" "" || return 1 - local ubidev="$( nand_find_ubi "$CI_UBIPART" )" - local root_ubivol="$(nand_find_volume $ubidev "$CI_ROOTPART")" + local root_ubidev="$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )" + local root_ubivol="$(nand_find_volume $root_ubidev "$CI_ROOTPART")" $cmd < "$ubifs_file" | ubiupdatevol /dev/$root_ubivol -s "$ubifs_length" - } @@ -302,7 +302,7 @@ nand_upgrade_fit() { nand_upgrade_prepare_ubi "" "" "$fit_length" "1" || return 1 - local fit_ubidev="$(nand_find_ubi "$CI_UBIPART")" + local fit_ubidev="$(nand_find_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}")" local fit_ubivol="$(nand_find_volume $fit_ubidev "$CI_KERNPART")" $cmd < "$fit_file" | ubiupdatevol /dev/$fit_ubivol -s "$fit_length" - } diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index 8bd2084f6b..80fbfb24c8 100644 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -228,6 +228,7 @@ platform_do_upgrade() { xiaomi,redmi-router-ax6000-stock) CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="ubi" + CI_DATA_UBIPART="ubi" nand_do_upgrade "$1" ;; buffalo,wsr-6000ax8|\ diff --git a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh index a30f4bc1e2..10078eec9a 100755 --- a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh +++ b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh @@ -29,6 +29,7 @@ platform_do_upgrade() { CI_KERNPART=boot CI_KERN_UBIPART=ubi_kernel CI_ROOT_UBIPART=ubi + CI_DATA_UBIPART=ubi nand_do_upgrade "$1" ;; buffalo,ls421de|\ diff --git a/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh index a5a4dc5bbb..13ccc3986e 100644 --- a/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh @@ -229,6 +229,7 @@ platform_do_upgrade() { # Kernel and rootfs are placed in 2 different UBI CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" + CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; yuncore,ax830|\ diff --git a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh index 9bece63345..f4963e1b3b 100644 --- a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh @@ -200,6 +200,7 @@ platform_do_upgrade() { buffalo,wxr-5950ax12) CI_KERN_UBIPART="rootfs" CI_ROOT_UBIPART="user_property" + CI_DATA_UBIPART="user_property" buffalo_upgrade_prepare nand_do_flash_file "$1" || nand_do_upgrade_failed nand_do_restore_config || nand_do_upgrade_failed @@ -258,6 +259,7 @@ platform_do_upgrade() { # Kernel and rootfs are placed in 2 different UBI CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" + CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; spectrum,sax1v1k) @@ -302,6 +304,7 @@ platform_do_upgrade() { zte,mf269) CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" + CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; zyxel,nbg7815) From eef8c718b474aff652b42c2e96b55b1b310f7f56 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 2 May 2026 19:32:23 +0200 Subject: [PATCH 032/228] base-files: handle name collision between kernel UBI volume and MTD partition On the AP-325 (and variants), the bootloader enforces a particular UBI volume layout and naming, so unfortunately the kernel's UBI volume and MTD partition end up with the name, which confuses the current logic. Therefore, add an option to ignore the MTD partition. Signed-off-by: Lukas Stockner Link: https://github.com/openwrt/openwrt/pull/20738 Signed-off-by: Test Dev --- package/base-files/files/lib/upgrade/nand.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh index e4a255b9c0..4bf9fc993e 100644 --- a/package/base-files/files/lib/upgrade/nand.sh +++ b/package/base-files/files/lib/upgrade/nand.sh @@ -328,6 +328,10 @@ nand_upgrade_tar() { local rootfs_type [ "$rootfs_length" ] && rootfs_type="$(identify_tar "$tar_file" "$cmd" "$board_dir/root")" + # If CI_SKIP_KERNEL_MTD is set, ignore any potential kernel MTD partition that was found. + # This is needed if there's an MTD partition with the same name as the kernel's UBI volume. + [ "${CI_SKIP_KERNEL_MTD:-}" ] && kernel_mtd= + local ubi_kernel_length if [ "$kernel_length" ]; then if [ "$kernel_mtd" ]; then From 69a2b3b31865615f71793067b1c891067b66e8a4 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 2 May 2026 20:11:04 +0200 Subject: [PATCH 033/228] ipq806x: add CONFIG_GPIO_WATCHDOG The AP-325 (and variants) has an external watchdog, so this is needed to regularly toggle the GPIO and keep the watchdog happy. Signed-off-by: Lukas Stockner Link: https://github.com/openwrt/openwrt/pull/20738 Signed-off-by: Test Dev --- target/linux/ipq806x/config-6.12 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/ipq806x/config-6.12 b/target/linux/ipq806x/config-6.12 index 74c32dbdc6..d4fc4a2779 100644 --- a/target/linux/ipq806x/config-6.12 +++ b/target/linux/ipq806x/config-6.12 @@ -184,6 +184,8 @@ CONFIG_GENERIC_VDSO_32=y CONFIG_GLOB=y CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_CDEV=y +CONFIG_GPIO_WATCHDOG=y +CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y CONFIG_GRO_CELLS=y CONFIG_HARDEN_BRANCH_PREDICTOR=y CONFIG_HARDIRQS_SW_RESEND=y From e912d6aeb4c017a30b86acd3a8cf4ec4b53b87a8 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Wed, 5 Nov 2025 23:41:57 +0100 Subject: [PATCH 034/228] ipq806x: add support for Aruba AP-32x This is a dual-radio 802.11a/b/g/n/ac access point with dual Gigabit Ethernet. There are two closely related models: The AP-324, which has external antenna connectors, and the AP-325, which has internal antennas. The board appears to be identical, and the same image works on both. Additionally, the Siemens Scalance W1750D is an OEM variant using the same board, so the image also works on that. Unfortunately the factory APBoot bootloader enforces cryptographic signatures on the firmware before booting, so a modified version must be flashed via the serial port. See [^1] for details. Specifications ============== * Device: Aruba AP-325 / AP-324 * SoC: Qualcomm IPQ8068 2x1.4GHz ARMv7-A * RAM: 512MiB (2x Winbond W632GU6MB-12) * SPI flash: 4MiB Macronix MX25U3235F * NAND flash: 128MiB Winbond W29N01HZBINF * WiFi: 2x Qualcomm QCA9990 (one 2.4G, one 5G) * Ethernet: 2x 1000BASE-T (Marvell 88E1514 PHY), both PoE-capable * Power: PoE 802.3at or 12V DC jack * LEDs: Red/Amber/Green status LED, Amber/Green WiFi LED * Buttons: 1x, behind hole next to DC jack * Console: RJ45 connector, Cisco pinout * USB: 1x USB 2.0 Type A, 1x internal to BLE, SoC has USB 3.0 host but board is only wired for 2.0 * BLE: TI CC2540 SoC, connected to USB and UART, unpopulated debug header on PCB * TPM: Atmel AT97SC3205T How to install ============== The stock bootloader APBoot appears to be vendor fork of U-Boot, which disables much of the usual functionality and comes with its own booting and firmware upgrade logic. Unfortunately, this logic enforces RSA signatures on images, even for the default boot from NAND. Therefore, a patched bootloader is needed, which is built as a package. In addition to the signature check removal, this also changes the serial baudrate to 115200. Luckily, the stock firmware does not disable the `sf` command (it just hides it until you run `diag`), so the patched bootloader can be fetched via TFTP and then flashed via console. Flashing patched APBoot ----------------------- * Build OpenWrt, or download `openwrt-ipq806x-generic-aruba_ap-32x-apboot.mbn` * Connect serial cable and wired ethernet * Access stock APBoot console at Baud 9600 * Flash patched bootloader: ``` setenv serverip setenv autostart n netget 44000000 openwrt-ipq806x-generic-aruba_ap-32x-apboot.mbn sf probe 0 sf erase 220000 100000 sf write 44000000 220000 100000 reset ``` Booting OpenWrt --------------- * Connect serial cable and wired ethernet * Access patched APBoot console at Baud 115200 * Run `setenv serverip ` * Run `tftpboot openwrt-ipq806x-generic-aruba_ap-32x-initramfs.ari` Installing OpenWrt ------------------ * Connect serial cable and wired ethernet * Access patched APBoot console at Baud 115200 * Consider backing up stock firmware(s) (UBI volumes `aos0` and/or `aos1`) by booting into OpenWrt via initramfs (see above) and dumping them * Wipe and repartition NAND flash (see below for explanation): ``` nand device 0 nand erase.chip reset ubi part ubifs ubi remove ubifs ubi create ubifs 1 ubi create rootfs_data ``` * Follow steps above to boot OpenWrt via initramfs * From OpenWrt, persist installation via sysupgrade Reverting to stock FW --------------------- The patched bootloader remains compatible with the original firmware, so you can just wipe the NAND, let APBoot recreate the partitions, and flash back the `aos0`/`aos1` backup from above. Current status ============== Tested and working ------------------ * Console * Wired GbE (both ports) * WiFi (both 2.4G and 5G) * LEDs * Restart Button * USB port * External watchdog * TPM * BLE SoC Future work ----------- * GPIOs for: * power source (8 indicates DC jack, 59 indicates 802.3at) * reset source (64 for warm reset, 65 for watchdog) * USB overcurrent (63) * BLE SoC reflashing * CC2540 comes with Aruba-specific FW out of the box * Debug header is exposed on PCB (pinout GND-VCC-Clock-Data-Reset), but that requires disassembly * Stock BLE FW appears to support reflashing via UART, but protocol would need to be reverse-engineered * ramoops/pstore * It appears that APBoot clears the RAM on boot, might be something we can patch out as well * Porting a modern U-Boot Flash layout ============ SPI flash --------- ``` 0x000000-0x020000 sbl1 0x020000-0x040000 mibib 0x040000-0x080000 sbl2 0x080000-0x100000 sbl3 0x100000-0x110000 ddrconfig 0x110000-0x120000 ssd 0x120000-0x1a0000 tz 0x1a0000-0x220000 rpm 0x220000-0x320000 appsbl 0x320000-0x330000 appsblenv 0x330000-0x370000 art 0x370000-0x380000 panicdump 0x380000-0x390000 certificate 0x390000-0x3a0000 mfginfo 0x3a0000-0x3b0000 flashcache 0x3b0000-0x400000 aosspare ``` Factory NAND flash ------------------ * 32MiB MTD partition `aos0`, formatted as UBI * 32MiB UBI volume `aos0` * contains kernel+initrd of the primary firmware, initrd contains the entire root FS * 32MiB MTD partition `aos1`, formatted as UBI * 32MiB UBI volume `aos1` * contains kernel+initrd of the secondary firmware, initrd contains the entire root FS * 64MiB MTD partition `ubifs`, formatted as UBI * 64MiB UBI volume `ubifs` * Contains UBIFS, overlay-mounted on top of the initrd, shared between firmware slots APBoot understands UBI, and will read the kernel from the `aos0` or `aos1` volume (depending on `os_partition`) with fallback to the other one in case a check fails. Kernels are expected to have a vendor-specific header, the included script will add that header with the correct checksum but no signature. OpenWrt NAND flash ------------------ OpenWrt assumes separate UBI volumes for kernel and rootfs, as well as a volume that must be named `rootfs_data` for the UBIFS. Unfortunately, APBoot actively checks the UBI volumes at boot, and will repartition if it doesn't find the volumes that it expects (listed above). Luckily, it doesn't check their size, only their existence. Therefore, we can use the following layout: * 32MiB MTD partition `aos0`, formatted as UBI * 32MiB UBI volume `aos0` * contains OpenWrt kernel+initrd * 32MiB MTD partition `aos1`, formatted as UBI * 32MiB UBI volume `aos1` * contains OpenWrt root squashfs * 64MiB MTD partition `ubifs`, formatted as UBI * small (single-LEB) UBI volume `ubifs` * Dummy volume, only there to satisfy APBoot * almost 64MiB UBI volume `rootfs_data` * contains UBIFS, overlay-mounted on top of the rootfs [^1]: https://github.com/lukasstockner/ap325-apboot-openwrt Signed-off-by: Lukas Stockner Link: https://github.com/openwrt/openwrt/pull/20738 Signed-off-by: Test Dev --- .../uboot-tools/uboot-envtools/files/ipq806x | 11 +- scripts/aruba-header.py | 225 +++++++++++ .../ipq806x/base-files/etc/board.d/02_network | 9 +- .../ipq806x/base-files/etc/init.d/bootcount | 7 +- .../base-files/lib/upgrade/platform.sh | 15 + .../linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts | 377 ++++++++++++++++++ target/linux/ipq806x/image/generic.mk | 31 ++ 7 files changed, 663 insertions(+), 12 deletions(-) create mode 100755 scripts/aruba-header.py create mode 100644 target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts diff --git a/package/boot/uboot-tools/uboot-envtools/files/ipq806x b/package/boot/uboot-tools/uboot-envtools/files/ipq806x index 44dae17c1b..a018d0d7e5 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/ipq806x +++ b/package/boot/uboot-tools/uboot-envtools/files/ipq806x @@ -35,6 +35,12 @@ arris,tr4400-v2|\ askey,rt4230w-rev6) ubootenv_add_uci_config "/dev/mtd9" "0x0" "0x40000" "0x20000" ;; +aruba,ap-32x|\ +ignitenet,ss-w2-ac2600|\ +qcom,ipq8064-ap148|\ +qcom,ipq8064-db149) + ubootenv_add_uci_config $(ubootenv_mtdinfo) + ;; edgecore,ecw5410) ubootenv_add_uci_config "/dev/mtd11" "0x0" "0x10000" "0x10000" ;; @@ -42,11 +48,6 @@ extreme,ap3935) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x10000" "0x10000" ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x10000" "0x10000" ;; -ignitenet,ss-w2-ac2600|\ -qcom,ipq8064-ap148|\ -qcom,ipq8064-db149) - ubootenv_add_uci_config $(ubootenv_mtdinfo) - ;; linksys,ea7500-v1|\ linksys,ea8500) ubootenv_add_uci_config "/dev/mtd10" "0x0" "0x20000" "0x20000" diff --git a/scripts/aruba-header.py b/scripts/aruba-header.py new file mode 100755 index 0000000000..e7dfa62e14 --- /dev/null +++ b/scripts/aruba-header.py @@ -0,0 +1,225 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2025 Lukas Stockner +# +# ./aruba-header.py +# +# Generates a header for use with the APBoot bootloader on (some?) Aruba APs. + +import argparse + +LEN_BUILD = 256 +LEN_VERSION = 24 +LEN_OEM = 32 + +HEADER_MAGIC = b'ARUBA\0\0\0' + + +class ValidFlag: + YES = 1 + + +class FormatVersion: + CURRENT = 2 + + +class ImageType: + ELF = 0 + FPGA_BINARY = 1 + CPBOOT_BINARY = 2 + APBOOT_BINARY = 3 + TPMINFO = 4 + APBOOT_STAGE1_BINARY = 5 + APBOOT_STAGE2_BINARY = 6 + APBOOT_COMBINED_BINARY = 7 + OS_ANCILLARY_IMAGE = 8 + XLOADER_BINARY = 9 + GRUB_BIN = 10 + LSM_PACKAGE = 11 + + +class CompressionType: + NONE = 0 + BZIP2 = 1 + GZIP = 2 + + +MACHINE_TYPES = { + 'MSWITCH': 0, + 'CABERNET': 1, + 'SYRAH': 2, + 'MERLOT': 3, + 'MUSCAT': 4, + 'NEBBIOLO': 5, + 'MALBEC': 6, + 'PALOMINO': 7, + 'GRENACHE': 8, + 'MOSCATO': 9, + 'TALISKER': 10, + 'JURA_R': 11, + 'SCAPA': 12, + 'JURA_O': 13, + 'CORVINA': 14, + 'ARRAN': 15, + 'BLUEBLOOD': 16, + 'MSR2K': 17, + 'PORFIDIO': 18, + 'CAZULO': 19, + 'SCAPA_H': 20, + 'CARDHU': 21, + 'BOWMORE': 22, + 'TAMDHU': 23, + 'ARDBEG': 24, + 'ARDMORE': 25, + 'DALMORE': 26, + 'K2': 27, + 'GRAPPA': 28, + 'SHUMWAY': 29, + 'SPRINGBANK': 30, + 'OUZO': 31, + 'AMARULA': 32, + 'GROZDOVA': 33, + 'PALINKA': 34, + 'HAZELBURN': 35, + 'TOMATIN': 36, + 'HAZELBURN_H': 37, + 'TOMATIN_16': 38, + 'SPRINGBANK_16': 39, + 'OCTOMORE': 40, + 'BALVENIE': 41, + 'OUZO_PLUS': 42, + 'X4': 43, + 'EINAR': 44, + 'GLENFARCLAS': 45, + 'GLENFIDDICH': 46, + 'EIGER': 47, + 'GLENMORANGIE': 48, + 'MILAGRO': 49, + 'OPUSONE': 50, + 'ABERLOUR': 51, + 'MILLSTONE': 52, + 'DEWARS': 53, + 'BUNKER': 54, + 'MASTERSON': 55, + 'SIERRA': 56, + 'KILCHOMAN': 57, + 'SPEYBURN': 58, + 'LAGAVULIN': 59, + 'LAPHROAIG': 60, + 'TOBA': 61, + 'ARRANTA': 62, +} + + +class NextHeader: + NONE = 0x00000000 + SIGN = 0x01111111 + + +class Flags: + C_TEST_BUILD = 0x00000001 + SWATCH = 0x00000002 + # Preserves the image with "clear all" + DONT_CLEAR_ON_PURGE = 0x00000004 + SECURE_BOOTLOADER = 0x00000008 + FACTORY_IMAGE = 0x00000010 + FIPS_CERTIFIED = 0x00000020 + + +def make_header(data: bytes, build: str, version: str, oem: str, imageType: int, machine: int) -> bytes: + buildBytes = build.encode(encoding='ascii') + assert len(buildBytes) < LEN_BUILD + buildBytes += b'\0' * (LEN_BUILD - len(buildBytes)) + + versionBytes = version.encode(encoding='ascii') + assert len(versionBytes) < LEN_VERSION + versionBytes += b'\0' * (LEN_VERSION - len(versionBytes)) + + oemBytes = oem.encode(encoding='ascii') + assert len(oemBytes) < LEN_OEM + oemBytes += b'\0' * (LEN_OEM - len(oemBytes)) + + header = b'' + # Payload size, image plus optional signature (which we don't use) + header += len(data).to_bytes(4, 'big') + # Use what appears to be the current version + header += FormatVersion.CURRENT.to_bytes(4, 'big') + # Checksum is computed later + header += b'\0\0\0\0' + # Vendor magic number + header += HEADER_MAGIC + # Long build information string + header += buildBytes + # Short version information string + header += versionBytes + # Image is valid + header += ValidFlag.YES.to_bytes(1, 'big') + # Image type + header += imageType.to_bytes(1, 'big') + # APBoot doesn't appear to actually support compression + header += CompressionType.NONE.to_bytes(1, 'big') + # Machine type + header += machine.to_bytes(1, 'big') + # Image size + header += len(data).to_bytes(4, 'big') + # Next header (we don't support signing) + header += NextHeader.NONE.to_bytes(4, 'big') + # MD5 checksum plus fudge factor (to ensure non-zero hash), appears unused + header += b'\0' * 16 + header += b'\0' * 4 + # No flags are set + header += int(0).to_bytes(4, 'big') + # No next header is used + header += b'\0' * 12 + # Padding + header += b'\0' * 36 + # OEM string + header += oemBytes + # Padding + header += b'\0' * 96 + + assert len(header) == 512 + assert len(data) % 4 == 0 + + # Compute checksum such that the big-endian sum of all 32-bit integers becomes zero. + curSum = sum(int.from_bytes(header[i : i + 4], 'big') for i in range(0, 512, 4)) + curSum += sum(int.from_bytes(data[i : i + 4], 'big') for i in range(0, len(data), 4)) + + # Set checksum + checksum = 0x100000000 - (curSum % 0x100000000) + header = header[:8] + checksum.to_bytes(4, 'big') + header[12:] + + return header + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Generate Aruba header.') + parser.add_argument('source') + parser.add_argument('dest') + parser.add_argument('build') + parser.add_argument('version') + parser.add_argument('oem') + parser.add_argument('type', choices=['os', 'boot']) + parser.add_argument('machine', choices=MACHINE_TYPES.keys(), type=str.upper) + args = parser.parse_args() + + # Parse image type. + # The OS image must be type "ELF" even though it's not an ELF file... + imageType = {'os': ImageType.ELF, 'boot': ImageType.APBOOT_BINARY}[args.type] + # Parse machine type. + machineType = MACHINE_TYPES[args.machine] + + source = open(args.source, 'rb') + image = source.read() + # Pad image. + if len(image) % 4 != 0: + image += b'\0' * (4 - len(image) % 4) + + # Generate header. + header = make_header(image, args.build, args.version, args.oem, imageType, machineType) + + # Write output. + dest = open(args.dest, 'wb') + dest.write(header) + dest.write(image) diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network index 6f490cb55d..e034172886 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -14,6 +14,11 @@ ipq806x_setup_interfaces() arris,tr4400-v2) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "eth2" ;; + aruba,ap-32x|\ + edgecore,ecw5410|\ + extreme,ap3935) + ucidef_set_interfaces_lan_wan "eth1" "eth0" + ;; askey,rt4230w-rev6|\ asrock,g10|\ buffalo,wxr-2533dhp|\ @@ -47,10 +52,6 @@ ipq806x_setup_interfaces() ucidef_set_network_device_conduit "lan1" "eth1" ucidef_set_network_device_conduit "wan" "eth0" ;; - edgecore,ecw5410|\ - extreme,ap3935) - ucidef_set_interfaces_lan_wan "eth1" "eth0" - ;; fortinet,fap-421e|\ ignitenet,ss-w2-ac2600|\ ubnt,unifi-ac-hd|\ diff --git a/target/linux/ipq806x/base-files/etc/init.d/bootcount b/target/linux/ipq806x/base-files/etc/init.d/bootcount index 669b815e39..1b9ace9f63 100755 --- a/target/linux/ipq806x/base-files/etc/init.d/bootcount +++ b/target/linux/ipq806x/base-files/etc/init.d/bootcount @@ -6,13 +6,14 @@ START=99 boot() { case $(board_name) in - asrock,g10) - asrock_bootconfig_mangle "bootcheck" && reboot - ;; + aruba,ap-32x|\ edgecore,ecw5410|\ ignitenet,ss-w2-ac2600) fw_setenv bootcount 0 ;; + asrock,g10) + asrock_bootconfig_mangle "bootcheck" && reboot + ;; extreme,ap3935) fw_setenv WATCHDOG_COUNT 0x00000000 ;; diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index 972aa41a85..e980598a38 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -26,6 +26,21 @@ platform_do_upgrade() { qcom,ipq8064-ap161) nand_do_upgrade "$1" ;; + aruba,ap-32x) + # The bootloader on this device unfortunately enforces a particular set of UBI volumes, + # and will mess with the partitioning if it doesn't find it. + # Therefore, we have to make do with the stock layout, which is a set of three + # MTD partitions, each containing a single UBI volume with the same name. + # Luckily, it doesn't check size, so we can have a "rootfs_data" volume next to a dummy + # "ubifs" volume on the "ubifs" partition. + CI_KERNPART="aos0" + CI_ROOTPART="aos1" + CI_KERN_UBIPART="aos0" + CI_ROOT_UBIPART="aos1" + CI_DATA_UBIPART="ubifs" + CI_SKIP_KERNEL_MTD=1 + nand_do_upgrade "$1" + ;; asrock,g10) asrock_upgrade_prepare nand_do_upgrade "$1" diff --git a/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts b/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts new file mode 100644 index 0000000000..b6f1b7b110 --- /dev/null +++ b/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq8064-v2.0.dtsi" + +#include +#include +#include + +/ { + model = "Aruba AP-32x"; + compatible = "aruba,ap-32x", "qcom,ipq8064"; + + memory@0 { + reg = <0x41500000 0x1eb00000>; + device_type = "memory"; + }; + + aliases { + serial0 = &gsbi4_serial; + serial1 = &gsbi2_serial; + + ethernet0 = &gmac2; + ethernet1 = &gmac3; + + led-boot = &led_power_amber; + led-failsafe = &led_power_red; + led-running = &led_power_green; + led-upgrade = &led_power_amber; + + label-mac-device = &gmac2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " ubi.mtd=aos1 ubi.mtd=ubifs ubi.block=0,aos1 root=/dev/ubiblock0_0"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&qcom_pinmux 9 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + led_power_green: power_green { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&qcom_pinmux 28 GPIO_ACTIVE_HIGH>; + }; + + led_power_amber: power_amber { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&qcom_pinmux 29 GPIO_ACTIVE_HIGH>; + }; + + led_power_red: power_red { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&qcom_pinmux 30 GPIO_ACTIVE_HIGH>; + }; + + led_wlan_green { + function = LED_FUNCTION_WLAN; + color = ; + gpios = <&qcom_pinmux 31 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + led_wlan_amber { + function = LED_FUNCTION_WLAN; + color = ; + gpios = <&qcom_pinmux 32 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&qcom_pinmux 61 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + hw_margin_ms = <1000>; + always-running; + + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + }; + + i2c { + compatible = "i2c-gpio"; + + sda-gpios = <&qcom_pinmux 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&qcom_pinmux 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + + #address-cells = <1>; + #size-cells = <0>; + + tpm@29 { + compatible = "atmel,at97sc3204t"; + reg = <0x29>; + }; + }; +}; + +&qcom_pinmux { + led_pins: led_pins { + mux { + pins = "gpio28", "gpio29", "gpio30", "gpio31", "gpio32"; + function = "gpio"; + drive-strength = <12>; + bias-pull-up; + }; + }; + + button_pins: button_pins { + mux { + pins = "gpio9"; + function = "gpio"; + bias-pull-up; + }; + }; + + uart0_pins: uart0_pins { + mux { + pins = "gpio10", "gpio11"; + function = "gsbi4"; + drive-strength = <10>; + bias-disable; + }; + }; + + uart1_pins: uart1_pins { + mux { + pins = "gpio22", "gpio23"; + function = "gsbi2"; + drive-strength = <10>; + bias-disable; + }; + }; + + watchdog_pins: watchdog_pins { + mux { + pins = "gpio61"; + function = "gpio"; + drive-strength = <10>; + bias-disable; + }; + }; + /* used for USB over-current detection instead */ + /delete-node/ pcie2_pins; +}; + +&gsbi4 { + status = "okay"; + qcom,mode = ; +}; + +&gsbi4_serial { + status = "okay"; + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; +}; + +&gsbi2 { + status = "okay"; + qcom,mode = ; +}; + +&gsbi2_serial { + status = "okay"; + pinctrl-0 = <&uart1_pins>; + pinctrl-names = "default"; +}; + +&gsbi5 { + qcom,mode = ; + status = "okay"; + + spi@1a280000 { + status = "okay"; + spi-max-frequency = <50000000>; + + pinctrl-0 = <&spi_pins>; + pinctrl-names = "default"; + + cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_LOW>; + + mx25u3235f@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + reg = <0>; + + partitions { + compatible = "qcom,smem-part"; + + partition-art { + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + label = "0:art"; + + precal_art_1000: precal@1000 { + reg = <0x1000 0x2f20>; + }; + + precal_art_5000: precal@5000 { + reg = <0x5000 0x2f20>; + }; + }; + + partition-appsblenv { + label = "0:appsblenv"; + + nvmem-layout { + compatible = "u-boot,env"; + + macaddr_lan: ethaddr { + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; + }; +}; + +&pcie0 { + status = "okay"; +}; + +&pcie_bridge0 { + wifi@0,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x10000 0 0 0 0>; + + nvmem-cells = <&precal_art_1000>; + nvmem-cell-names = "pre-calibration"; + }; +}; + +&pcie1 { + status = "okay"; +}; + +&pcie_bridge1 { + wifi@0,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x10000 0 0 0 0>; + + nvmem-cells = <&precal_art_5000>; + nvmem-cell-names = "pre-calibration"; + }; +}; + +&nand { + status = "okay"; + + nand@0 { + compatible = "qcom,nandcs"; + + reg = <0>; + + nand-ecc-strength = <4>; + nand-bus-width = <8>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + aos0@0 { + label = "aos0"; + reg = <0x0 0x2000000>; + }; + + aos1@2000000 { + label = "aos1"; + reg = <0x2000000 0x2000000>; + }; + + ubifs@4000000 { + label = "ubifs"; + reg = <0x4000000 0x4000000>; + }; + }; + }; +}; + +&mdio0 { + status = "okay"; + + pinctrl-0 = <&mdio0_pins>; + pinctrl-names = "default"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&gmac2 { + status = "okay"; + + qcom,id = <2>; + mdiobus = <&mdio0>; + + phy-mode = "sgmii"; + phy-handle = <&phy0>; + + nvmem-cells = <&macaddr_lan 0>; + nvmem-cell-names = "mac-address"; +}; + +&gmac3 { + status = "okay"; + + qcom,id = <3>; + mdiobus = <&mdio0>; + + phy-mode = "sgmii"; + phy-handle = <&phy1>; + + nvmem-cells = <&macaddr_lan 1>; + nvmem-cell-names = "mac-address"; +}; + +&adm_dma { + status = "okay"; +}; + +/* USB Port 0 is connected to the onboard BLE SoC. + * The stock FW on that doesn't implement USB, so to prevent errors from + * being logged when the host fails to initialize it, it's disabled by + * default here. */ +&hs_phy_0 { + status = "disabled"; +}; + +&ss_phy_0 { + status = "disabled"; +}; + +&usb3_0 { + status = "disabled"; +}; + +&hs_phy_1 { + status = "okay"; +}; + +&ss_phy_1 { + status = "okay"; +}; + +&usb3_1 { + status = "okay"; +}; diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index 5fbb3a79e6..9da73c4c03 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -48,6 +48,18 @@ define Build/linksys-addfwhdr ;mv "$@.new" "$@" endef +define Build/apboot-addfwhdr + $(SCRIPT_DIR)/aruba-header.py \ + $@ $@.new \ + "$(call toupper,$(LINUX_KARCH)) $(VERSION_DIST) Linux-$(LINUX_VERSION), $(VERSION_NUMBER) $(VERSION_CODE)"\ + "$(VERSION_NUMBER)" \ + "$(VERSION_DIST)" \ + os \ + "$(word 1,$(1))" + + mv "$@.new" "$@" +endef + define Device/DniImage KERNEL_SUFFIX := -uImage KERNEL = kernel-bin | append-dtb | uImage none @@ -102,6 +114,25 @@ define Device/arris_tr4400-v2 endef TARGET_DEVICES += arris_tr4400-v2 +define Device/aruba_ap-32x + $(call Device/LegacyImage) + DEVICE_VENDOR := Aruba + DEVICE_MODEL := AP-325 + DEVICE_ALT0_VENDOR := Aruba + DEVICE_ALT0_MODEL := AP-324 + DEVICE_ALT1_VENDOR := Siemens + DEVICE_ALT1_MODEL := Scalance W1750D + SOC := qcom-ipq8068 + PAGESIZE := 2048 + BLOCKSIZE := 128k + KERNEL_SUFFIX := .ari + KERNEL = kernel-bin | append-dtb | uImage none | apboot-addfwhdr Octomore + KERNEL_LOADADDR = 0x41508000 + KERNEL_SIZE := 30720k + DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct kmod-i2c-gpio kmod-tpm-i2c-atmel +endef +TARGET_DEVICES += aruba_ap-32x + define Device/askey_rt4230w-rev6 $(call Device/LegacyImage) $(Device/dsa-migration) From 0823ad47ff3068476da4e5035575b4923bcc1fec Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Fri, 12 Jun 2026 17:05:20 +0200 Subject: [PATCH 035/228] ipq806x: add apboot package for AP-32x This is unfortunately needed to disable the signature verification in the stock bootloader. Co-authored-by: Paul Spooren Signed-off-by: Lukas Stockner Link: https://github.com/openwrt/openwrt/pull/20738 Signed-off-by: Test Dev --- package/boot/apboot-aruba-ipq806x/Makefile | 77 ++++++++++++++++++++++ target/linux/ipq806x/image/generic.mk | 6 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 package/boot/apboot-aruba-ipq806x/Makefile diff --git a/package/boot/apboot-aruba-ipq806x/Makefile b/package/boot/apboot-aruba-ipq806x/Makefile new file mode 100644 index 0000000000..141b359b23 --- /dev/null +++ b/package/boot/apboot-aruba-ipq806x/Makefile @@ -0,0 +1,77 @@ +# +# Copyright (C) 2026 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=apboot-aruba-ipq806x +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/lukasstockner/ap325-apboot-openwrt.git +PKG_MIRROR_HASH:=ef91bc1539d50c19c35ae5d38eab1a4944692d3f651952f58800ea1f7ffd4878 +PKG_SOURCE_DATE:=2026-06-12 +PKG_SOURCE_VERSION:=d36bb7270a8a8a5c5988ff778e55de12e0c40745 + +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING +PKG_MAINTAINER:=Lukas Stockner + +# Legacy U-Boot tree, not Kbuild-parallel safe. +PKG_BUILD_PARALLEL:=0 +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk + +# Aruba/QCA board name in the APBoot tree (Makefile.releng target): +# octomore -> AP-324 / AP-325 (and Siemens Scalance W1750D) +APBOOT_BOARD:=octomore + +# Stamped into the version banner; the upstream Dockerfile uses the short hash. +APBOOT_LABELID:=$(call version_abbrev,$(PKG_SOURCE_VERSION)) + +define Package/apboot-aruba-ipq806x + SECTION:=boot + CATEGORY:=Boot Loaders + DEPENDS:=@TARGET_ipq806x + TITLE:=Patched Aruba APBoot for AP-32x + URL:=https://github.com/lukasstockner/ap325-apboot-openwrt +endef + +define Package/apboot-aruba-ipq806x/description + Patched build of the Aruba APBoot bootloader (a vendor fork of U-Boot) for + the Aruba AP-324 / AP-325 access points (board "octomore"). The factory + bootloader enforces RSA signatures on the firmware; this build removes the + signature check and switches the console to 115200 baud so that OpenWrt can + be booted. The resulting "u-boot.mbn" is meant to be flashed to the APPSBL + SPI-flash partition via the serial console. +endef + +# APBoot is a freestanding U-Boot, so build it with OpenWrt's target +# cross-toolchain instead of the bare-metal arm-none-eabi- default. The legacy +# Makefile honours an externally supplied CROSS_COMPILE. +define Build/Compile + +$(MAKE) -C $(PKG_BUILD_DIR) -f Makefile.releng $(APBOOT_BOARD) \ + SHELL=/bin/bash \ + CROSS_COMPILE=$(TARGET_CROSS) \ + HOSTCC="$(HOSTCC)" \ + LABELID=$(APBOOT_LABELID) \ + ARUBA_MAKE_VERBOSE=1 +endef + +# The bootloader is flashed by hand and is not part of the root filesystem. +# Stage the image so the ipq806x image build can emit it as a device artifact. +define Build/InstallDev + $(INSTALL_DIR) $(STAGING_DIR_IMAGE) + $(INSTALL_DATA) $(PKG_BUILD_DIR)/u-boot.mbn \ + $(STAGING_DIR_IMAGE)/aruba_ap-32x-apboot.mbn +endef + +define Package/apboot-aruba-ipq806x/install + : +endef + +$(eval $(call BuildPackage,apboot-aruba-ipq806x)) diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index 9da73c4c03..17a4078c5b 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -129,7 +129,11 @@ define Device/aruba_ap-32x KERNEL = kernel-bin | append-dtb | uImage none | apboot-addfwhdr Octomore KERNEL_LOADADDR = 0x41508000 KERNEL_SIZE := 30720k - DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct kmod-i2c-gpio kmod-tpm-i2c-atmel + UBOOT_PATH := $$(STAGING_DIR_IMAGE)/aruba_ap-32x-apboot.mbn + ARTIFACTS := apboot.mbn + ARTIFACT/apboot.mbn := append-uboot + DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct kmod-i2c-gpio kmod-tpm-i2c-atmel \ + apboot-aruba-ipq806x endef TARGET_DEVICES += aruba_ap-32x From eccf49c9f896721894d1c684449dba50ef55849c Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 16 Jun 2026 16:03:24 +0200 Subject: [PATCH 036/228] Revert "ipq806x: add apboot package for AP-32x" This reverts commit 0823ad47ff3068476da4e5035575b4923bcc1fec. Wrong Signed-off-by line was used, reverting and re-applying. Signed-off-by: Paul Spooren --- package/boot/apboot-aruba-ipq806x/Makefile | 77 ---------------------- target/linux/ipq806x/image/generic.mk | 6 +- 2 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 package/boot/apboot-aruba-ipq806x/Makefile diff --git a/package/boot/apboot-aruba-ipq806x/Makefile b/package/boot/apboot-aruba-ipq806x/Makefile deleted file mode 100644 index 141b359b23..0000000000 --- a/package/boot/apboot-aruba-ipq806x/Makefile +++ /dev/null @@ -1,77 +0,0 @@ -# -# Copyright (C) 2026 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=apboot-aruba-ipq806x -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/lukasstockner/ap325-apboot-openwrt.git -PKG_MIRROR_HASH:=ef91bc1539d50c19c35ae5d38eab1a4944692d3f651952f58800ea1f7ffd4878 -PKG_SOURCE_DATE:=2026-06-12 -PKG_SOURCE_VERSION:=d36bb7270a8a8a5c5988ff778e55de12e0c40745 - -PKG_LICENSE:=GPL-2.0-or-later -PKG_LICENSE_FILES:=COPYING -PKG_MAINTAINER:=Lukas Stockner - -# Legacy U-Boot tree, not Kbuild-parallel safe. -PKG_BUILD_PARALLEL:=0 -PKG_FLAGS:=nonshared - -include $(INCLUDE_DIR)/package.mk - -# Aruba/QCA board name in the APBoot tree (Makefile.releng target): -# octomore -> AP-324 / AP-325 (and Siemens Scalance W1750D) -APBOOT_BOARD:=octomore - -# Stamped into the version banner; the upstream Dockerfile uses the short hash. -APBOOT_LABELID:=$(call version_abbrev,$(PKG_SOURCE_VERSION)) - -define Package/apboot-aruba-ipq806x - SECTION:=boot - CATEGORY:=Boot Loaders - DEPENDS:=@TARGET_ipq806x - TITLE:=Patched Aruba APBoot for AP-32x - URL:=https://github.com/lukasstockner/ap325-apboot-openwrt -endef - -define Package/apboot-aruba-ipq806x/description - Patched build of the Aruba APBoot bootloader (a vendor fork of U-Boot) for - the Aruba AP-324 / AP-325 access points (board "octomore"). The factory - bootloader enforces RSA signatures on the firmware; this build removes the - signature check and switches the console to 115200 baud so that OpenWrt can - be booted. The resulting "u-boot.mbn" is meant to be flashed to the APPSBL - SPI-flash partition via the serial console. -endef - -# APBoot is a freestanding U-Boot, so build it with OpenWrt's target -# cross-toolchain instead of the bare-metal arm-none-eabi- default. The legacy -# Makefile honours an externally supplied CROSS_COMPILE. -define Build/Compile - +$(MAKE) -C $(PKG_BUILD_DIR) -f Makefile.releng $(APBOOT_BOARD) \ - SHELL=/bin/bash \ - CROSS_COMPILE=$(TARGET_CROSS) \ - HOSTCC="$(HOSTCC)" \ - LABELID=$(APBOOT_LABELID) \ - ARUBA_MAKE_VERBOSE=1 -endef - -# The bootloader is flashed by hand and is not part of the root filesystem. -# Stage the image so the ipq806x image build can emit it as a device artifact. -define Build/InstallDev - $(INSTALL_DIR) $(STAGING_DIR_IMAGE) - $(INSTALL_DATA) $(PKG_BUILD_DIR)/u-boot.mbn \ - $(STAGING_DIR_IMAGE)/aruba_ap-32x-apboot.mbn -endef - -define Package/apboot-aruba-ipq806x/install - : -endef - -$(eval $(call BuildPackage,apboot-aruba-ipq806x)) diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index 17a4078c5b..9da73c4c03 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -129,11 +129,7 @@ define Device/aruba_ap-32x KERNEL = kernel-bin | append-dtb | uImage none | apboot-addfwhdr Octomore KERNEL_LOADADDR = 0x41508000 KERNEL_SIZE := 30720k - UBOOT_PATH := $$(STAGING_DIR_IMAGE)/aruba_ap-32x-apboot.mbn - ARTIFACTS := apboot.mbn - ARTIFACT/apboot.mbn := append-uboot - DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct kmod-i2c-gpio kmod-tpm-i2c-atmel \ - apboot-aruba-ipq806x + DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct kmod-i2c-gpio kmod-tpm-i2c-atmel endef TARGET_DEVICES += aruba_ap-32x From b85b7fd14cb34953966bbeda4ca5712391fb8e8d Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 16 Jun 2026 16:04:22 +0200 Subject: [PATCH 037/228] Revert "ipq806x: add support for Aruba AP-32x" This reverts commit e912d6aeb4c017a30b86acd3a8cf4ec4b53b87a8. Wrong Signed-off-by line was used, reverting and re-applying. Signed-off-by: Paul Spooren --- .../uboot-tools/uboot-envtools/files/ipq806x | 11 +- scripts/aruba-header.py | 225 ----------- .../ipq806x/base-files/etc/board.d/02_network | 9 +- .../ipq806x/base-files/etc/init.d/bootcount | 7 +- .../base-files/lib/upgrade/platform.sh | 15 - .../linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts | 377 ------------------ target/linux/ipq806x/image/generic.mk | 31 -- 7 files changed, 12 insertions(+), 663 deletions(-) delete mode 100755 scripts/aruba-header.py delete mode 100644 target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts diff --git a/package/boot/uboot-tools/uboot-envtools/files/ipq806x b/package/boot/uboot-tools/uboot-envtools/files/ipq806x index a018d0d7e5..44dae17c1b 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/ipq806x +++ b/package/boot/uboot-tools/uboot-envtools/files/ipq806x @@ -35,12 +35,6 @@ arris,tr4400-v2|\ askey,rt4230w-rev6) ubootenv_add_uci_config "/dev/mtd9" "0x0" "0x40000" "0x20000" ;; -aruba,ap-32x|\ -ignitenet,ss-w2-ac2600|\ -qcom,ipq8064-ap148|\ -qcom,ipq8064-db149) - ubootenv_add_uci_config $(ubootenv_mtdinfo) - ;; edgecore,ecw5410) ubootenv_add_uci_config "/dev/mtd11" "0x0" "0x10000" "0x10000" ;; @@ -48,6 +42,11 @@ extreme,ap3935) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x10000" "0x10000" ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x10000" "0x10000" ;; +ignitenet,ss-w2-ac2600|\ +qcom,ipq8064-ap148|\ +qcom,ipq8064-db149) + ubootenv_add_uci_config $(ubootenv_mtdinfo) + ;; linksys,ea7500-v1|\ linksys,ea8500) ubootenv_add_uci_config "/dev/mtd10" "0x0" "0x20000" "0x20000" diff --git a/scripts/aruba-header.py b/scripts/aruba-header.py deleted file mode 100755 index e7dfa62e14..0000000000 --- a/scripts/aruba-header.py +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/python3 -# SPDX-License-Identifier: GPL-2.0-or-later -# -# Copyright (C) 2025 Lukas Stockner -# -# ./aruba-header.py -# -# Generates a header for use with the APBoot bootloader on (some?) Aruba APs. - -import argparse - -LEN_BUILD = 256 -LEN_VERSION = 24 -LEN_OEM = 32 - -HEADER_MAGIC = b'ARUBA\0\0\0' - - -class ValidFlag: - YES = 1 - - -class FormatVersion: - CURRENT = 2 - - -class ImageType: - ELF = 0 - FPGA_BINARY = 1 - CPBOOT_BINARY = 2 - APBOOT_BINARY = 3 - TPMINFO = 4 - APBOOT_STAGE1_BINARY = 5 - APBOOT_STAGE2_BINARY = 6 - APBOOT_COMBINED_BINARY = 7 - OS_ANCILLARY_IMAGE = 8 - XLOADER_BINARY = 9 - GRUB_BIN = 10 - LSM_PACKAGE = 11 - - -class CompressionType: - NONE = 0 - BZIP2 = 1 - GZIP = 2 - - -MACHINE_TYPES = { - 'MSWITCH': 0, - 'CABERNET': 1, - 'SYRAH': 2, - 'MERLOT': 3, - 'MUSCAT': 4, - 'NEBBIOLO': 5, - 'MALBEC': 6, - 'PALOMINO': 7, - 'GRENACHE': 8, - 'MOSCATO': 9, - 'TALISKER': 10, - 'JURA_R': 11, - 'SCAPA': 12, - 'JURA_O': 13, - 'CORVINA': 14, - 'ARRAN': 15, - 'BLUEBLOOD': 16, - 'MSR2K': 17, - 'PORFIDIO': 18, - 'CAZULO': 19, - 'SCAPA_H': 20, - 'CARDHU': 21, - 'BOWMORE': 22, - 'TAMDHU': 23, - 'ARDBEG': 24, - 'ARDMORE': 25, - 'DALMORE': 26, - 'K2': 27, - 'GRAPPA': 28, - 'SHUMWAY': 29, - 'SPRINGBANK': 30, - 'OUZO': 31, - 'AMARULA': 32, - 'GROZDOVA': 33, - 'PALINKA': 34, - 'HAZELBURN': 35, - 'TOMATIN': 36, - 'HAZELBURN_H': 37, - 'TOMATIN_16': 38, - 'SPRINGBANK_16': 39, - 'OCTOMORE': 40, - 'BALVENIE': 41, - 'OUZO_PLUS': 42, - 'X4': 43, - 'EINAR': 44, - 'GLENFARCLAS': 45, - 'GLENFIDDICH': 46, - 'EIGER': 47, - 'GLENMORANGIE': 48, - 'MILAGRO': 49, - 'OPUSONE': 50, - 'ABERLOUR': 51, - 'MILLSTONE': 52, - 'DEWARS': 53, - 'BUNKER': 54, - 'MASTERSON': 55, - 'SIERRA': 56, - 'KILCHOMAN': 57, - 'SPEYBURN': 58, - 'LAGAVULIN': 59, - 'LAPHROAIG': 60, - 'TOBA': 61, - 'ARRANTA': 62, -} - - -class NextHeader: - NONE = 0x00000000 - SIGN = 0x01111111 - - -class Flags: - C_TEST_BUILD = 0x00000001 - SWATCH = 0x00000002 - # Preserves the image with "clear all" - DONT_CLEAR_ON_PURGE = 0x00000004 - SECURE_BOOTLOADER = 0x00000008 - FACTORY_IMAGE = 0x00000010 - FIPS_CERTIFIED = 0x00000020 - - -def make_header(data: bytes, build: str, version: str, oem: str, imageType: int, machine: int) -> bytes: - buildBytes = build.encode(encoding='ascii') - assert len(buildBytes) < LEN_BUILD - buildBytes += b'\0' * (LEN_BUILD - len(buildBytes)) - - versionBytes = version.encode(encoding='ascii') - assert len(versionBytes) < LEN_VERSION - versionBytes += b'\0' * (LEN_VERSION - len(versionBytes)) - - oemBytes = oem.encode(encoding='ascii') - assert len(oemBytes) < LEN_OEM - oemBytes += b'\0' * (LEN_OEM - len(oemBytes)) - - header = b'' - # Payload size, image plus optional signature (which we don't use) - header += len(data).to_bytes(4, 'big') - # Use what appears to be the current version - header += FormatVersion.CURRENT.to_bytes(4, 'big') - # Checksum is computed later - header += b'\0\0\0\0' - # Vendor magic number - header += HEADER_MAGIC - # Long build information string - header += buildBytes - # Short version information string - header += versionBytes - # Image is valid - header += ValidFlag.YES.to_bytes(1, 'big') - # Image type - header += imageType.to_bytes(1, 'big') - # APBoot doesn't appear to actually support compression - header += CompressionType.NONE.to_bytes(1, 'big') - # Machine type - header += machine.to_bytes(1, 'big') - # Image size - header += len(data).to_bytes(4, 'big') - # Next header (we don't support signing) - header += NextHeader.NONE.to_bytes(4, 'big') - # MD5 checksum plus fudge factor (to ensure non-zero hash), appears unused - header += b'\0' * 16 - header += b'\0' * 4 - # No flags are set - header += int(0).to_bytes(4, 'big') - # No next header is used - header += b'\0' * 12 - # Padding - header += b'\0' * 36 - # OEM string - header += oemBytes - # Padding - header += b'\0' * 96 - - assert len(header) == 512 - assert len(data) % 4 == 0 - - # Compute checksum such that the big-endian sum of all 32-bit integers becomes zero. - curSum = sum(int.from_bytes(header[i : i + 4], 'big') for i in range(0, 512, 4)) - curSum += sum(int.from_bytes(data[i : i + 4], 'big') for i in range(0, len(data), 4)) - - # Set checksum - checksum = 0x100000000 - (curSum % 0x100000000) - header = header[:8] + checksum.to_bytes(4, 'big') + header[12:] - - return header - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Generate Aruba header.') - parser.add_argument('source') - parser.add_argument('dest') - parser.add_argument('build') - parser.add_argument('version') - parser.add_argument('oem') - parser.add_argument('type', choices=['os', 'boot']) - parser.add_argument('machine', choices=MACHINE_TYPES.keys(), type=str.upper) - args = parser.parse_args() - - # Parse image type. - # The OS image must be type "ELF" even though it's not an ELF file... - imageType = {'os': ImageType.ELF, 'boot': ImageType.APBOOT_BINARY}[args.type] - # Parse machine type. - machineType = MACHINE_TYPES[args.machine] - - source = open(args.source, 'rb') - image = source.read() - # Pad image. - if len(image) % 4 != 0: - image += b'\0' * (4 - len(image) % 4) - - # Generate header. - header = make_header(image, args.build, args.version, args.oem, imageType, machineType) - - # Write output. - dest = open(args.dest, 'wb') - dest.write(header) - dest.write(image) diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network index e034172886..6f490cb55d 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -14,11 +14,6 @@ ipq806x_setup_interfaces() arris,tr4400-v2) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "eth2" ;; - aruba,ap-32x|\ - edgecore,ecw5410|\ - extreme,ap3935) - ucidef_set_interfaces_lan_wan "eth1" "eth0" - ;; askey,rt4230w-rev6|\ asrock,g10|\ buffalo,wxr-2533dhp|\ @@ -52,6 +47,10 @@ ipq806x_setup_interfaces() ucidef_set_network_device_conduit "lan1" "eth1" ucidef_set_network_device_conduit "wan" "eth0" ;; + edgecore,ecw5410|\ + extreme,ap3935) + ucidef_set_interfaces_lan_wan "eth1" "eth0" + ;; fortinet,fap-421e|\ ignitenet,ss-w2-ac2600|\ ubnt,unifi-ac-hd|\ diff --git a/target/linux/ipq806x/base-files/etc/init.d/bootcount b/target/linux/ipq806x/base-files/etc/init.d/bootcount index 1b9ace9f63..669b815e39 100755 --- a/target/linux/ipq806x/base-files/etc/init.d/bootcount +++ b/target/linux/ipq806x/base-files/etc/init.d/bootcount @@ -6,14 +6,13 @@ START=99 boot() { case $(board_name) in - aruba,ap-32x|\ + asrock,g10) + asrock_bootconfig_mangle "bootcheck" && reboot + ;; edgecore,ecw5410|\ ignitenet,ss-w2-ac2600) fw_setenv bootcount 0 ;; - asrock,g10) - asrock_bootconfig_mangle "bootcheck" && reboot - ;; extreme,ap3935) fw_setenv WATCHDOG_COUNT 0x00000000 ;; diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index e980598a38..972aa41a85 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -26,21 +26,6 @@ platform_do_upgrade() { qcom,ipq8064-ap161) nand_do_upgrade "$1" ;; - aruba,ap-32x) - # The bootloader on this device unfortunately enforces a particular set of UBI volumes, - # and will mess with the partitioning if it doesn't find it. - # Therefore, we have to make do with the stock layout, which is a set of three - # MTD partitions, each containing a single UBI volume with the same name. - # Luckily, it doesn't check size, so we can have a "rootfs_data" volume next to a dummy - # "ubifs" volume on the "ubifs" partition. - CI_KERNPART="aos0" - CI_ROOTPART="aos1" - CI_KERN_UBIPART="aos0" - CI_ROOT_UBIPART="aos1" - CI_DATA_UBIPART="ubifs" - CI_SKIP_KERNEL_MTD=1 - nand_do_upgrade "$1" - ;; asrock,g10) asrock_upgrade_prepare nand_do_upgrade "$1" diff --git a/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts b/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts deleted file mode 100644 index b6f1b7b110..0000000000 --- a/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts +++ /dev/null @@ -1,377 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT - -#include "qcom-ipq8064-v2.0.dtsi" - -#include -#include -#include - -/ { - model = "Aruba AP-32x"; - compatible = "aruba,ap-32x", "qcom,ipq8064"; - - memory@0 { - reg = <0x41500000 0x1eb00000>; - device_type = "memory"; - }; - - aliases { - serial0 = &gsbi4_serial; - serial1 = &gsbi2_serial; - - ethernet0 = &gmac2; - ethernet1 = &gmac3; - - led-boot = &led_power_amber; - led-failsafe = &led_power_red; - led-running = &led_power_green; - led-upgrade = &led_power_amber; - - label-mac-device = &gmac2; - }; - - chosen { - stdout-path = "serial0:115200n8"; - bootargs-append = " ubi.mtd=aos1 ubi.mtd=ubifs ubi.block=0,aos1 root=/dev/ubiblock0_0"; - }; - - keys { - compatible = "gpio-keys"; - pinctrl-0 = <&button_pins>; - pinctrl-names = "default"; - - reset { - label = "reset"; - gpios = <&qcom_pinmux 9 GPIO_ACTIVE_LOW>; - linux,code = ; - debounce-interval = <60>; - wakeup-source; - }; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-0 = <&led_pins>; - pinctrl-names = "default"; - - led_power_green: power_green { - function = LED_FUNCTION_POWER; - color = ; - gpios = <&qcom_pinmux 28 GPIO_ACTIVE_HIGH>; - }; - - led_power_amber: power_amber { - function = LED_FUNCTION_POWER; - color = ; - gpios = <&qcom_pinmux 29 GPIO_ACTIVE_HIGH>; - }; - - led_power_red: power_red { - function = LED_FUNCTION_POWER; - color = ; - gpios = <&qcom_pinmux 30 GPIO_ACTIVE_HIGH>; - }; - - led_wlan_green { - function = LED_FUNCTION_WLAN; - color = ; - gpios = <&qcom_pinmux 31 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "phy0tpt"; - }; - - led_wlan_amber { - function = LED_FUNCTION_WLAN; - color = ; - gpios = <&qcom_pinmux 32 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "phy1tpt"; - }; - }; - - watchdog { - compatible = "linux,wdt-gpio"; - gpios = <&qcom_pinmux 61 GPIO_ACTIVE_LOW>; - hw_algo = "toggle"; - hw_margin_ms = <1000>; - always-running; - - pinctrl-names = "default"; - pinctrl-0 = <&watchdog_pins>; - }; - - i2c { - compatible = "i2c-gpio"; - - sda-gpios = <&qcom_pinmux 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; - scl-gpios = <&qcom_pinmux 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; - - #address-cells = <1>; - #size-cells = <0>; - - tpm@29 { - compatible = "atmel,at97sc3204t"; - reg = <0x29>; - }; - }; -}; - -&qcom_pinmux { - led_pins: led_pins { - mux { - pins = "gpio28", "gpio29", "gpio30", "gpio31", "gpio32"; - function = "gpio"; - drive-strength = <12>; - bias-pull-up; - }; - }; - - button_pins: button_pins { - mux { - pins = "gpio9"; - function = "gpio"; - bias-pull-up; - }; - }; - - uart0_pins: uart0_pins { - mux { - pins = "gpio10", "gpio11"; - function = "gsbi4"; - drive-strength = <10>; - bias-disable; - }; - }; - - uart1_pins: uart1_pins { - mux { - pins = "gpio22", "gpio23"; - function = "gsbi2"; - drive-strength = <10>; - bias-disable; - }; - }; - - watchdog_pins: watchdog_pins { - mux { - pins = "gpio61"; - function = "gpio"; - drive-strength = <10>; - bias-disable; - }; - }; - /* used for USB over-current detection instead */ - /delete-node/ pcie2_pins; -}; - -&gsbi4 { - status = "okay"; - qcom,mode = ; -}; - -&gsbi4_serial { - status = "okay"; - pinctrl-0 = <&uart0_pins>; - pinctrl-names = "default"; -}; - -&gsbi2 { - status = "okay"; - qcom,mode = ; -}; - -&gsbi2_serial { - status = "okay"; - pinctrl-0 = <&uart1_pins>; - pinctrl-names = "default"; -}; - -&gsbi5 { - qcom,mode = ; - status = "okay"; - - spi@1a280000 { - status = "okay"; - spi-max-frequency = <50000000>; - - pinctrl-0 = <&spi_pins>; - pinctrl-names = "default"; - - cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_LOW>; - - mx25u3235f@0 { - compatible = "jedec,spi-nor"; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; - reg = <0>; - - partitions { - compatible = "qcom,smem-part"; - - partition-art { - compatible = "nvmem-cells"; - #address-cells = <1>; - #size-cells = <1>; - label = "0:art"; - - precal_art_1000: precal@1000 { - reg = <0x1000 0x2f20>; - }; - - precal_art_5000: precal@5000 { - reg = <0x5000 0x2f20>; - }; - }; - - partition-appsblenv { - label = "0:appsblenv"; - - nvmem-layout { - compatible = "u-boot,env"; - - macaddr_lan: ethaddr { - #nvmem-cell-cells = <1>; - }; - }; - }; - }; - }; - }; -}; - -&pcie0 { - status = "okay"; -}; - -&pcie_bridge0 { - wifi@0,0 { - compatible = "qcom,ath10k"; - status = "okay"; - reg = <0x10000 0 0 0 0>; - - nvmem-cells = <&precal_art_1000>; - nvmem-cell-names = "pre-calibration"; - }; -}; - -&pcie1 { - status = "okay"; -}; - -&pcie_bridge1 { - wifi@0,0 { - compatible = "qcom,ath10k"; - status = "okay"; - reg = <0x10000 0 0 0 0>; - - nvmem-cells = <&precal_art_5000>; - nvmem-cell-names = "pre-calibration"; - }; -}; - -&nand { - status = "okay"; - - nand@0 { - compatible = "qcom,nandcs"; - - reg = <0>; - - nand-ecc-strength = <4>; - nand-bus-width = <8>; - nand-ecc-step-size = <512>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - aos0@0 { - label = "aos0"; - reg = <0x0 0x2000000>; - }; - - aos1@2000000 { - label = "aos1"; - reg = <0x2000000 0x2000000>; - }; - - ubifs@4000000 { - label = "ubifs"; - reg = <0x4000000 0x4000000>; - }; - }; - }; -}; - -&mdio0 { - status = "okay"; - - pinctrl-0 = <&mdio0_pins>; - pinctrl-names = "default"; - - phy0: ethernet-phy@0 { - reg = <0>; - }; - - phy1: ethernet-phy@1 { - reg = <1>; - }; -}; - -&gmac2 { - status = "okay"; - - qcom,id = <2>; - mdiobus = <&mdio0>; - - phy-mode = "sgmii"; - phy-handle = <&phy0>; - - nvmem-cells = <&macaddr_lan 0>; - nvmem-cell-names = "mac-address"; -}; - -&gmac3 { - status = "okay"; - - qcom,id = <3>; - mdiobus = <&mdio0>; - - phy-mode = "sgmii"; - phy-handle = <&phy1>; - - nvmem-cells = <&macaddr_lan 1>; - nvmem-cell-names = "mac-address"; -}; - -&adm_dma { - status = "okay"; -}; - -/* USB Port 0 is connected to the onboard BLE SoC. - * The stock FW on that doesn't implement USB, so to prevent errors from - * being logged when the host fails to initialize it, it's disabled by - * default here. */ -&hs_phy_0 { - status = "disabled"; -}; - -&ss_phy_0 { - status = "disabled"; -}; - -&usb3_0 { - status = "disabled"; -}; - -&hs_phy_1 { - status = "okay"; -}; - -&ss_phy_1 { - status = "okay"; -}; - -&usb3_1 { - status = "okay"; -}; diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index 9da73c4c03..5fbb3a79e6 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -48,18 +48,6 @@ define Build/linksys-addfwhdr ;mv "$@.new" "$@" endef -define Build/apboot-addfwhdr - $(SCRIPT_DIR)/aruba-header.py \ - $@ $@.new \ - "$(call toupper,$(LINUX_KARCH)) $(VERSION_DIST) Linux-$(LINUX_VERSION), $(VERSION_NUMBER) $(VERSION_CODE)"\ - "$(VERSION_NUMBER)" \ - "$(VERSION_DIST)" \ - os \ - "$(word 1,$(1))" - - mv "$@.new" "$@" -endef - define Device/DniImage KERNEL_SUFFIX := -uImage KERNEL = kernel-bin | append-dtb | uImage none @@ -114,25 +102,6 @@ define Device/arris_tr4400-v2 endef TARGET_DEVICES += arris_tr4400-v2 -define Device/aruba_ap-32x - $(call Device/LegacyImage) - DEVICE_VENDOR := Aruba - DEVICE_MODEL := AP-325 - DEVICE_ALT0_VENDOR := Aruba - DEVICE_ALT0_MODEL := AP-324 - DEVICE_ALT1_VENDOR := Siemens - DEVICE_ALT1_MODEL := Scalance W1750D - SOC := qcom-ipq8068 - PAGESIZE := 2048 - BLOCKSIZE := 128k - KERNEL_SUFFIX := .ari - KERNEL = kernel-bin | append-dtb | uImage none | apboot-addfwhdr Octomore - KERNEL_LOADADDR = 0x41508000 - KERNEL_SIZE := 30720k - DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct kmod-i2c-gpio kmod-tpm-i2c-atmel -endef -TARGET_DEVICES += aruba_ap-32x - define Device/askey_rt4230w-rev6 $(call Device/LegacyImage) $(Device/dsa-migration) From 6c8aeb9bb729710d6774ad130f8c4bcc30968a39 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 16 Jun 2026 16:04:30 +0200 Subject: [PATCH 038/228] Revert "ipq806x: add CONFIG_GPIO_WATCHDOG" This reverts commit 69a2b3b31865615f71793067b1c891067b66e8a4. Wrong Signed-off-by line was used, reverting and re-applying. Signed-off-by: Paul Spooren --- target/linux/ipq806x/config-6.12 | 2 -- 1 file changed, 2 deletions(-) diff --git a/target/linux/ipq806x/config-6.12 b/target/linux/ipq806x/config-6.12 index d4fc4a2779..74c32dbdc6 100644 --- a/target/linux/ipq806x/config-6.12 +++ b/target/linux/ipq806x/config-6.12 @@ -184,8 +184,6 @@ CONFIG_GENERIC_VDSO_32=y CONFIG_GLOB=y CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_CDEV=y -CONFIG_GPIO_WATCHDOG=y -CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y CONFIG_GRO_CELLS=y CONFIG_HARDEN_BRANCH_PREDICTOR=y CONFIG_HARDIRQS_SW_RESEND=y From 7ef7a3581a3ff34cab2f59e1f6295fc23de46072 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 16 Jun 2026 16:04:37 +0200 Subject: [PATCH 039/228] Revert "base-files: handle name collision between kernel UBI volume and MTD partition" This reverts commit eef8c718b474aff652b42c2e96b55b1b310f7f56. Wrong Signed-off-by line was used, reverting and re-applying. Signed-off-by: Paul Spooren --- package/base-files/files/lib/upgrade/nand.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh index 4bf9fc993e..e4a255b9c0 100644 --- a/package/base-files/files/lib/upgrade/nand.sh +++ b/package/base-files/files/lib/upgrade/nand.sh @@ -328,10 +328,6 @@ nand_upgrade_tar() { local rootfs_type [ "$rootfs_length" ] && rootfs_type="$(identify_tar "$tar_file" "$cmd" "$board_dir/root")" - # If CI_SKIP_KERNEL_MTD is set, ignore any potential kernel MTD partition that was found. - # This is needed if there's an MTD partition with the same name as the kernel's UBI volume. - [ "${CI_SKIP_KERNEL_MTD:-}" ] && kernel_mtd= - local ubi_kernel_length if [ "$kernel_length" ]; then if [ "$kernel_mtd" ]; then From 3ee64a736cda7ff8d5e92a5f4baf2d9ae612261b Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 16 Jun 2026 16:04:48 +0200 Subject: [PATCH 040/228] Revert "base-files: support rootfs_data on its own partition" This reverts commit 13fc688f033895e0ba91c1d752ffd63a06760ef5. Wrong Signed-off-by line was used, reverting and re-applying. Signed-off-by: Paul Spooren --- package/base-files/files/lib/upgrade/nand.sh | 40 +++++++++---------- .../base-files/lib/upgrade/platform.sh | 1 - .../base-files/lib/upgrade/platform.sh | 1 - .../base-files/lib/upgrade/platform.sh | 1 - .../base-files/lib/upgrade/platform.sh | 3 -- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh index e4a255b9c0..22f9cce42a 100644 --- a/package/base-files/files/lib/upgrade/nand.sh +++ b/package/base-files/files/lib/upgrade/nand.sh @@ -7,9 +7,8 @@ CI_KERNPART="${CI_KERNPART:-kernel}" # 'ubi' partition on NAND contains UBI -# If individual UBI volumes are on different partitions, -# they can be set with CI_KERN_UBIPART, CI_ROOT_UBIPART and/or -# CI_DATA_UBIPART. +# There are also CI_KERN_UBIPART and CI_ROOT_UBIPART if kernel +# and rootfs are on separated UBIs. CI_UBIPART="${CI_UBIPART:-ubi}" # 'rootfs' UBI volume on NAND contains the rootfs @@ -78,10 +77,9 @@ identify_if_gzip() { } nand_restore_config() { - local ubidev=$( nand_find_ubi "${CI_DATA_UBIPART:-$CI_UBIPART}" ) + local ubidev=$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" ) local ubivol="$( nand_find_volume $ubidev rootfs_data )" if [ ! "$ubivol" ]; then - local ubidev=$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" ) ubivol="$( nand_find_volume $ubidev "$CI_ROOTPART" )" if [ ! "$ubivol" ]; then echo "cannot find ubifs data volume" @@ -190,21 +188,23 @@ nand_upgrade_prepare_ubi() { local has_env="${4:-0}" local kern_ubidev local root_ubidev - local data_ubidev [ -n "$rootfs_length" -o -n "$kernel_length" ] || return 1 - # Attach UBI partitions (might be identical, but nand_attach_ubi handles that) - kern_ubidev="$( nand_attach_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}" "$has_env" )" - [ -n "$kern_ubidev" ] || return 1 - root_ubidev="$( nand_attach_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )" - [ -n "$root_ubidev" ] || return 1 - data_ubidev="$( nand_attach_ubi "${CI_DATA_UBIPART:-$CI_UBIPART}" )" - [ -n "$data_ubidev" ] || return 1 + if [ -n "$CI_KERN_UBIPART" -a -n "$CI_ROOT_UBIPART" ]; then + kern_ubidev="$( nand_attach_ubi "$CI_KERN_UBIPART" "$has_env" )" + [ -n "$kern_ubidev" ] || return 1 + root_ubidev="$( nand_attach_ubi "$CI_ROOT_UBIPART" )" + [ -n "$root_ubidev" ] || return 1 + else + kern_ubidev="$( nand_attach_ubi "$CI_UBIPART" "$has_env" )" + [ -n "$kern_ubidev" ] || return 1 + root_ubidev="$kern_ubidev" + fi local kern_ubivol="$( nand_find_volume $kern_ubidev "$CI_KERNPART" )" local root_ubivol="$( nand_find_volume $root_ubidev "$CI_ROOTPART" )" - local data_ubivol="$( nand_find_volume $data_ubidev rootfs_data )" + local data_ubivol="$( nand_find_volume $root_ubidev rootfs_data )" [ "$root_ubivol" = "$kern_ubivol" ] && root_ubivol= # remove ubiblocks @@ -215,7 +215,7 @@ nand_upgrade_prepare_ubi() { # kill volumes [ "$kern_ubivol" ] && ubirmvol /dev/$kern_ubidev -N "$CI_KERNPART" || : [ "$root_ubivol" ] && ubirmvol /dev/$root_ubidev -N "$CI_ROOTPART" || : - [ "$data_ubivol" ] && ubirmvol /dev/$data_ubidev -N rootfs_data || : + [ "$data_ubivol" ] && ubirmvol /dev/$root_ubidev -N rootfs_data || : # create provisioning vol if [ "${UPGRADE_OPT_ADD_PROVISIONING:-0}" -gt 0 ]; then @@ -255,8 +255,8 @@ nand_upgrade_prepare_ubi() { if [ -n "$rootfs_data_max" ]; then rootfs_data_size_param="-s $rootfs_data_max" fi - if ! ubimkvol /dev/$data_ubidev -N rootfs_data $rootfs_data_size_param; then - if ! ubimkvol /dev/$data_ubidev -N rootfs_data -m; then + if ! ubimkvol /dev/$root_ubidev -N rootfs_data $rootfs_data_size_param; then + if ! ubimkvol /dev/$root_ubidev -N rootfs_data -m; then echo "cannot initialize rootfs_data volume" return 1 fi @@ -288,8 +288,8 @@ nand_upgrade_ubifs() { nand_upgrade_prepare_ubi "$ubifs_length" "ubifs" "" "" || return 1 - local root_ubidev="$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )" - local root_ubivol="$(nand_find_volume $root_ubidev "$CI_ROOTPART")" + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + local root_ubivol="$(nand_find_volume $ubidev "$CI_ROOTPART")" $cmd < "$ubifs_file" | ubiupdatevol /dev/$root_ubivol -s "$ubifs_length" - } @@ -302,7 +302,7 @@ nand_upgrade_fit() { nand_upgrade_prepare_ubi "" "" "$fit_length" "1" || return 1 - local fit_ubidev="$(nand_find_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}")" + local fit_ubidev="$(nand_find_ubi "$CI_UBIPART")" local fit_ubivol="$(nand_find_volume $fit_ubidev "$CI_KERNPART")" $cmd < "$fit_file" | ubiupdatevol /dev/$fit_ubivol -s "$fit_length" - } diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index 80fbfb24c8..8bd2084f6b 100644 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -228,7 +228,6 @@ platform_do_upgrade() { xiaomi,redmi-router-ax6000-stock) CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="ubi" - CI_DATA_UBIPART="ubi" nand_do_upgrade "$1" ;; buffalo,wsr-6000ax8|\ diff --git a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh index 10078eec9a..a30f4bc1e2 100755 --- a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh +++ b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh @@ -29,7 +29,6 @@ platform_do_upgrade() { CI_KERNPART=boot CI_KERN_UBIPART=ubi_kernel CI_ROOT_UBIPART=ubi - CI_DATA_UBIPART=ubi nand_do_upgrade "$1" ;; buffalo,ls421de|\ diff --git a/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh index 13ccc3986e..a5a4dc5bbb 100644 --- a/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh @@ -229,7 +229,6 @@ platform_do_upgrade() { # Kernel and rootfs are placed in 2 different UBI CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" - CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; yuncore,ax830|\ diff --git a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh index f4963e1b3b..9bece63345 100644 --- a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh @@ -200,7 +200,6 @@ platform_do_upgrade() { buffalo,wxr-5950ax12) CI_KERN_UBIPART="rootfs" CI_ROOT_UBIPART="user_property" - CI_DATA_UBIPART="user_property" buffalo_upgrade_prepare nand_do_flash_file "$1" || nand_do_upgrade_failed nand_do_restore_config || nand_do_upgrade_failed @@ -259,7 +258,6 @@ platform_do_upgrade() { # Kernel and rootfs are placed in 2 different UBI CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" - CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; spectrum,sax1v1k) @@ -304,7 +302,6 @@ platform_do_upgrade() { zte,mf269) CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" - CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; zyxel,nbg7815) From bf770bc4e3eb150b9496314992d8baed97067848 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 2 May 2026 19:31:43 +0200 Subject: [PATCH 041/228] base-files: support rootfs_data on its own partition The current code assumes that the rootfs_data UBI volume is on the same MTD partition as the rootfs. Unfortunately, this does not work on the Aruba AP-325 (and variants), since the bootloader enforces a particular UBI volume layout. Therefore, this adds a separate variable to set the rootfs_data partition, and updates all existing devices with a non-default rootfs partition to also specify the new variable. Signed-off-by: Lukas Stockner Link: https://github.com/openwrt/openwrt/pull/20738 Signed-off-by: Paul Spooren --- package/base-files/files/lib/upgrade/nand.sh | 40 +++++++++---------- .../base-files/lib/upgrade/platform.sh | 1 + .../base-files/lib/upgrade/platform.sh | 1 + .../base-files/lib/upgrade/platform.sh | 1 + .../base-files/lib/upgrade/platform.sh | 3 ++ 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh index 22f9cce42a..e4a255b9c0 100644 --- a/package/base-files/files/lib/upgrade/nand.sh +++ b/package/base-files/files/lib/upgrade/nand.sh @@ -7,8 +7,9 @@ CI_KERNPART="${CI_KERNPART:-kernel}" # 'ubi' partition on NAND contains UBI -# There are also CI_KERN_UBIPART and CI_ROOT_UBIPART if kernel -# and rootfs are on separated UBIs. +# If individual UBI volumes are on different partitions, +# they can be set with CI_KERN_UBIPART, CI_ROOT_UBIPART and/or +# CI_DATA_UBIPART. CI_UBIPART="${CI_UBIPART:-ubi}" # 'rootfs' UBI volume on NAND contains the rootfs @@ -77,9 +78,10 @@ identify_if_gzip() { } nand_restore_config() { - local ubidev=$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" ) + local ubidev=$( nand_find_ubi "${CI_DATA_UBIPART:-$CI_UBIPART}" ) local ubivol="$( nand_find_volume $ubidev rootfs_data )" if [ ! "$ubivol" ]; then + local ubidev=$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" ) ubivol="$( nand_find_volume $ubidev "$CI_ROOTPART" )" if [ ! "$ubivol" ]; then echo "cannot find ubifs data volume" @@ -188,23 +190,21 @@ nand_upgrade_prepare_ubi() { local has_env="${4:-0}" local kern_ubidev local root_ubidev + local data_ubidev [ -n "$rootfs_length" -o -n "$kernel_length" ] || return 1 - if [ -n "$CI_KERN_UBIPART" -a -n "$CI_ROOT_UBIPART" ]; then - kern_ubidev="$( nand_attach_ubi "$CI_KERN_UBIPART" "$has_env" )" - [ -n "$kern_ubidev" ] || return 1 - root_ubidev="$( nand_attach_ubi "$CI_ROOT_UBIPART" )" - [ -n "$root_ubidev" ] || return 1 - else - kern_ubidev="$( nand_attach_ubi "$CI_UBIPART" "$has_env" )" - [ -n "$kern_ubidev" ] || return 1 - root_ubidev="$kern_ubidev" - fi + # Attach UBI partitions (might be identical, but nand_attach_ubi handles that) + kern_ubidev="$( nand_attach_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}" "$has_env" )" + [ -n "$kern_ubidev" ] || return 1 + root_ubidev="$( nand_attach_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )" + [ -n "$root_ubidev" ] || return 1 + data_ubidev="$( nand_attach_ubi "${CI_DATA_UBIPART:-$CI_UBIPART}" )" + [ -n "$data_ubidev" ] || return 1 local kern_ubivol="$( nand_find_volume $kern_ubidev "$CI_KERNPART" )" local root_ubivol="$( nand_find_volume $root_ubidev "$CI_ROOTPART" )" - local data_ubivol="$( nand_find_volume $root_ubidev rootfs_data )" + local data_ubivol="$( nand_find_volume $data_ubidev rootfs_data )" [ "$root_ubivol" = "$kern_ubivol" ] && root_ubivol= # remove ubiblocks @@ -215,7 +215,7 @@ nand_upgrade_prepare_ubi() { # kill volumes [ "$kern_ubivol" ] && ubirmvol /dev/$kern_ubidev -N "$CI_KERNPART" || : [ "$root_ubivol" ] && ubirmvol /dev/$root_ubidev -N "$CI_ROOTPART" || : - [ "$data_ubivol" ] && ubirmvol /dev/$root_ubidev -N rootfs_data || : + [ "$data_ubivol" ] && ubirmvol /dev/$data_ubidev -N rootfs_data || : # create provisioning vol if [ "${UPGRADE_OPT_ADD_PROVISIONING:-0}" -gt 0 ]; then @@ -255,8 +255,8 @@ nand_upgrade_prepare_ubi() { if [ -n "$rootfs_data_max" ]; then rootfs_data_size_param="-s $rootfs_data_max" fi - if ! ubimkvol /dev/$root_ubidev -N rootfs_data $rootfs_data_size_param; then - if ! ubimkvol /dev/$root_ubidev -N rootfs_data -m; then + if ! ubimkvol /dev/$data_ubidev -N rootfs_data $rootfs_data_size_param; then + if ! ubimkvol /dev/$data_ubidev -N rootfs_data -m; then echo "cannot initialize rootfs_data volume" return 1 fi @@ -288,8 +288,8 @@ nand_upgrade_ubifs() { nand_upgrade_prepare_ubi "$ubifs_length" "ubifs" "" "" || return 1 - local ubidev="$( nand_find_ubi "$CI_UBIPART" )" - local root_ubivol="$(nand_find_volume $ubidev "$CI_ROOTPART")" + local root_ubidev="$( nand_find_ubi "${CI_ROOT_UBIPART:-$CI_UBIPART}" )" + local root_ubivol="$(nand_find_volume $root_ubidev "$CI_ROOTPART")" $cmd < "$ubifs_file" | ubiupdatevol /dev/$root_ubivol -s "$ubifs_length" - } @@ -302,7 +302,7 @@ nand_upgrade_fit() { nand_upgrade_prepare_ubi "" "" "$fit_length" "1" || return 1 - local fit_ubidev="$(nand_find_ubi "$CI_UBIPART")" + local fit_ubidev="$(nand_find_ubi "${CI_KERN_UBIPART:-$CI_UBIPART}")" local fit_ubivol="$(nand_find_volume $fit_ubidev "$CI_KERNPART")" $cmd < "$fit_file" | ubiupdatevol /dev/$fit_ubivol -s "$fit_length" - } diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index 8bd2084f6b..80fbfb24c8 100644 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -228,6 +228,7 @@ platform_do_upgrade() { xiaomi,redmi-router-ax6000-stock) CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="ubi" + CI_DATA_UBIPART="ubi" nand_do_upgrade "$1" ;; buffalo,wsr-6000ax8|\ diff --git a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh index a30f4bc1e2..10078eec9a 100755 --- a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh +++ b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh @@ -29,6 +29,7 @@ platform_do_upgrade() { CI_KERNPART=boot CI_KERN_UBIPART=ubi_kernel CI_ROOT_UBIPART=ubi + CI_DATA_UBIPART=ubi nand_do_upgrade "$1" ;; buffalo,ls421de|\ diff --git a/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh index a5a4dc5bbb..13ccc3986e 100644 --- a/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq50xx/base-files/lib/upgrade/platform.sh @@ -229,6 +229,7 @@ platform_do_upgrade() { # Kernel and rootfs are placed in 2 different UBI CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" + CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; yuncore,ax830|\ diff --git a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh index 9bece63345..f4963e1b3b 100644 --- a/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh +++ b/target/linux/qualcommax/ipq807x/base-files/lib/upgrade/platform.sh @@ -200,6 +200,7 @@ platform_do_upgrade() { buffalo,wxr-5950ax12) CI_KERN_UBIPART="rootfs" CI_ROOT_UBIPART="user_property" + CI_DATA_UBIPART="user_property" buffalo_upgrade_prepare nand_do_flash_file "$1" || nand_do_upgrade_failed nand_do_restore_config || nand_do_upgrade_failed @@ -258,6 +259,7 @@ platform_do_upgrade() { # Kernel and rootfs are placed in 2 different UBI CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" + CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; spectrum,sax1v1k) @@ -302,6 +304,7 @@ platform_do_upgrade() { zte,mf269) CI_KERN_UBIPART="ubi_kernel" CI_ROOT_UBIPART="rootfs" + CI_DATA_UBIPART="rootfs" nand_do_upgrade "$1" ;; zyxel,nbg7815) From 5497d5ba23dc24f5b8eee2f62f7613decce4d248 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 2 May 2026 19:32:23 +0200 Subject: [PATCH 042/228] base-files: handle name collision between kernel UBI volume and MTD partition On the AP-325 (and variants), the bootloader enforces a particular UBI volume layout and naming, so unfortunately the kernel's UBI volume and MTD partition end up with the name, which confuses the current logic. Therefore, add an option to ignore the MTD partition. Signed-off-by: Lukas Stockner Link: https://github.com/openwrt/openwrt/pull/20738 Signed-off-by: Paul Spooren --- package/base-files/files/lib/upgrade/nand.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh index e4a255b9c0..4bf9fc993e 100644 --- a/package/base-files/files/lib/upgrade/nand.sh +++ b/package/base-files/files/lib/upgrade/nand.sh @@ -328,6 +328,10 @@ nand_upgrade_tar() { local rootfs_type [ "$rootfs_length" ] && rootfs_type="$(identify_tar "$tar_file" "$cmd" "$board_dir/root")" + # If CI_SKIP_KERNEL_MTD is set, ignore any potential kernel MTD partition that was found. + # This is needed if there's an MTD partition with the same name as the kernel's UBI volume. + [ "${CI_SKIP_KERNEL_MTD:-}" ] && kernel_mtd= + local ubi_kernel_length if [ "$kernel_length" ]; then if [ "$kernel_mtd" ]; then From 58015a1c2a1508094c057b1e0946eb9ccc8139ad Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 2 May 2026 20:11:04 +0200 Subject: [PATCH 043/228] ipq806x: add CONFIG_GPIO_WATCHDOG The AP-325 (and variants) has an external watchdog, so this is needed to regularly toggle the GPIO and keep the watchdog happy. Signed-off-by: Lukas Stockner Link: https://github.com/openwrt/openwrt/pull/20738 Signed-off-by: Paul Spooren --- target/linux/ipq806x/config-6.12 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/ipq806x/config-6.12 b/target/linux/ipq806x/config-6.12 index 74c32dbdc6..d4fc4a2779 100644 --- a/target/linux/ipq806x/config-6.12 +++ b/target/linux/ipq806x/config-6.12 @@ -184,6 +184,8 @@ CONFIG_GENERIC_VDSO_32=y CONFIG_GLOB=y CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_CDEV=y +CONFIG_GPIO_WATCHDOG=y +CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y CONFIG_GRO_CELLS=y CONFIG_HARDEN_BRANCH_PREDICTOR=y CONFIG_HARDIRQS_SW_RESEND=y From d2a75029a5f8e54e1fd2f252f73b9a430a030116 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Wed, 5 Nov 2025 23:41:57 +0100 Subject: [PATCH 044/228] ipq806x: add support for Aruba AP-32x This is a dual-radio 802.11a/b/g/n/ac access point with dual Gigabit Ethernet. There are two closely related models: The AP-324, which has external antenna connectors, and the AP-325, which has internal antennas. The board appears to be identical, and the same image works on both. Additionally, the Siemens Scalance W1750D is an OEM variant using the same board, so the image also works on that. Unfortunately the factory APBoot bootloader enforces cryptographic signatures on the firmware before booting, so a modified version must be flashed via the serial port. See [^1] for details. Specifications ============== * Device: Aruba AP-325 / AP-324 * SoC: Qualcomm IPQ8068 2x1.4GHz ARMv7-A * RAM: 512MiB (2x Winbond W632GU6MB-12) * SPI flash: 4MiB Macronix MX25U3235F * NAND flash: 128MiB Winbond W29N01HZBINF * WiFi: 2x Qualcomm QCA9990 (one 2.4G, one 5G) * Ethernet: 2x 1000BASE-T (Marvell 88E1514 PHY), both PoE-capable * Power: PoE 802.3at or 12V DC jack * LEDs: Red/Amber/Green status LED, Amber/Green WiFi LED * Buttons: 1x, behind hole next to DC jack * Console: RJ45 connector, Cisco pinout * USB: 1x USB 2.0 Type A, 1x internal to BLE, SoC has USB 3.0 host but board is only wired for 2.0 * BLE: TI CC2540 SoC, connected to USB and UART, unpopulated debug header on PCB * TPM: Atmel AT97SC3205T How to install ============== The stock bootloader APBoot appears to be vendor fork of U-Boot, which disables much of the usual functionality and comes with its own booting and firmware upgrade logic. Unfortunately, this logic enforces RSA signatures on images, even for the default boot from NAND. Therefore, a patched bootloader is needed, which is built as a package. In addition to the signature check removal, this also changes the serial baudrate to 115200. Luckily, the stock firmware does not disable the `sf` command (it just hides it until you run `diag`), so the patched bootloader can be fetched via TFTP and then flashed via console. Flashing patched APBoot ----------------------- * Build OpenWrt, or download `openwrt-ipq806x-generic-aruba_ap-32x-apboot.mbn` * Connect serial cable and wired ethernet * Access stock APBoot console at Baud 9600 * Flash patched bootloader: ``` setenv serverip setenv autostart n netget 44000000 openwrt-ipq806x-generic-aruba_ap-32x-apboot.mbn sf probe 0 sf erase 220000 100000 sf write 44000000 220000 100000 reset ``` Booting OpenWrt --------------- * Connect serial cable and wired ethernet * Access patched APBoot console at Baud 115200 * Run `setenv serverip ` * Run `tftpboot openwrt-ipq806x-generic-aruba_ap-32x-initramfs.ari` Installing OpenWrt ------------------ * Connect serial cable and wired ethernet * Access patched APBoot console at Baud 115200 * Consider backing up stock firmware(s) (UBI volumes `aos0` and/or `aos1`) by booting into OpenWrt via initramfs (see above) and dumping them * Wipe and repartition NAND flash (see below for explanation): ``` nand device 0 nand erase.chip reset ubi part ubifs ubi remove ubifs ubi create ubifs 1 ubi create rootfs_data ``` * Follow steps above to boot OpenWrt via initramfs * From OpenWrt, persist installation via sysupgrade Reverting to stock FW --------------------- The patched bootloader remains compatible with the original firmware, so you can just wipe the NAND, let APBoot recreate the partitions, and flash back the `aos0`/`aos1` backup from above. Current status ============== Tested and working ------------------ * Console * Wired GbE (both ports) * WiFi (both 2.4G and 5G) * LEDs * Restart Button * USB port * External watchdog * TPM * BLE SoC Future work ----------- * GPIOs for: * power source (8 indicates DC jack, 59 indicates 802.3at) * reset source (64 for warm reset, 65 for watchdog) * USB overcurrent (63) * BLE SoC reflashing * CC2540 comes with Aruba-specific FW out of the box * Debug header is exposed on PCB (pinout GND-VCC-Clock-Data-Reset), but that requires disassembly * Stock BLE FW appears to support reflashing via UART, but protocol would need to be reverse-engineered * ramoops/pstore * It appears that APBoot clears the RAM on boot, might be something we can patch out as well * Porting a modern U-Boot Flash layout ============ SPI flash --------- ``` 0x000000-0x020000 sbl1 0x020000-0x040000 mibib 0x040000-0x080000 sbl2 0x080000-0x100000 sbl3 0x100000-0x110000 ddrconfig 0x110000-0x120000 ssd 0x120000-0x1a0000 tz 0x1a0000-0x220000 rpm 0x220000-0x320000 appsbl 0x320000-0x330000 appsblenv 0x330000-0x370000 art 0x370000-0x380000 panicdump 0x380000-0x390000 certificate 0x390000-0x3a0000 mfginfo 0x3a0000-0x3b0000 flashcache 0x3b0000-0x400000 aosspare ``` Factory NAND flash ------------------ * 32MiB MTD partition `aos0`, formatted as UBI * 32MiB UBI volume `aos0` * contains kernel+initrd of the primary firmware, initrd contains the entire root FS * 32MiB MTD partition `aos1`, formatted as UBI * 32MiB UBI volume `aos1` * contains kernel+initrd of the secondary firmware, initrd contains the entire root FS * 64MiB MTD partition `ubifs`, formatted as UBI * 64MiB UBI volume `ubifs` * Contains UBIFS, overlay-mounted on top of the initrd, shared between firmware slots APBoot understands UBI, and will read the kernel from the `aos0` or `aos1` volume (depending on `os_partition`) with fallback to the other one in case a check fails. Kernels are expected to have a vendor-specific header, the included script will add that header with the correct checksum but no signature. OpenWrt NAND flash ------------------ OpenWrt assumes separate UBI volumes for kernel and rootfs, as well as a volume that must be named `rootfs_data` for the UBIFS. Unfortunately, APBoot actively checks the UBI volumes at boot, and will repartition if it doesn't find the volumes that it expects (listed above). Luckily, it doesn't check their size, only their existence. Therefore, we can use the following layout: * 32MiB MTD partition `aos0`, formatted as UBI * 32MiB UBI volume `aos0` * contains OpenWrt kernel+initrd * 32MiB MTD partition `aos1`, formatted as UBI * 32MiB UBI volume `aos1` * contains OpenWrt root squashfs * 64MiB MTD partition `ubifs`, formatted as UBI * small (single-LEB) UBI volume `ubifs` * Dummy volume, only there to satisfy APBoot * almost 64MiB UBI volume `rootfs_data` * contains UBIFS, overlay-mounted on top of the rootfs [^1]: https://github.com/lukasstockner/ap325-apboot-openwrt Signed-off-by: Lukas Stockner Link: https://github.com/openwrt/openwrt/pull/20738 Signed-off-by: Paul Spooren --- .../uboot-tools/uboot-envtools/files/ipq806x | 11 +- scripts/aruba-header.py | 225 +++++++++++ .../ipq806x/base-files/etc/board.d/02_network | 9 +- .../ipq806x/base-files/etc/init.d/bootcount | 7 +- .../base-files/lib/upgrade/platform.sh | 15 + .../linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts | 377 ++++++++++++++++++ target/linux/ipq806x/image/generic.mk | 31 ++ 7 files changed, 663 insertions(+), 12 deletions(-) create mode 100755 scripts/aruba-header.py create mode 100644 target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts diff --git a/package/boot/uboot-tools/uboot-envtools/files/ipq806x b/package/boot/uboot-tools/uboot-envtools/files/ipq806x index 44dae17c1b..a018d0d7e5 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/ipq806x +++ b/package/boot/uboot-tools/uboot-envtools/files/ipq806x @@ -35,6 +35,12 @@ arris,tr4400-v2|\ askey,rt4230w-rev6) ubootenv_add_uci_config "/dev/mtd9" "0x0" "0x40000" "0x20000" ;; +aruba,ap-32x|\ +ignitenet,ss-w2-ac2600|\ +qcom,ipq8064-ap148|\ +qcom,ipq8064-db149) + ubootenv_add_uci_config $(ubootenv_mtdinfo) + ;; edgecore,ecw5410) ubootenv_add_uci_config "/dev/mtd11" "0x0" "0x10000" "0x10000" ;; @@ -42,11 +48,6 @@ extreme,ap3935) ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x10000" "0x10000" ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x10000" "0x10000" ;; -ignitenet,ss-w2-ac2600|\ -qcom,ipq8064-ap148|\ -qcom,ipq8064-db149) - ubootenv_add_uci_config $(ubootenv_mtdinfo) - ;; linksys,ea7500-v1|\ linksys,ea8500) ubootenv_add_uci_config "/dev/mtd10" "0x0" "0x20000" "0x20000" diff --git a/scripts/aruba-header.py b/scripts/aruba-header.py new file mode 100755 index 0000000000..e7dfa62e14 --- /dev/null +++ b/scripts/aruba-header.py @@ -0,0 +1,225 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2025 Lukas Stockner +# +# ./aruba-header.py +# +# Generates a header for use with the APBoot bootloader on (some?) Aruba APs. + +import argparse + +LEN_BUILD = 256 +LEN_VERSION = 24 +LEN_OEM = 32 + +HEADER_MAGIC = b'ARUBA\0\0\0' + + +class ValidFlag: + YES = 1 + + +class FormatVersion: + CURRENT = 2 + + +class ImageType: + ELF = 0 + FPGA_BINARY = 1 + CPBOOT_BINARY = 2 + APBOOT_BINARY = 3 + TPMINFO = 4 + APBOOT_STAGE1_BINARY = 5 + APBOOT_STAGE2_BINARY = 6 + APBOOT_COMBINED_BINARY = 7 + OS_ANCILLARY_IMAGE = 8 + XLOADER_BINARY = 9 + GRUB_BIN = 10 + LSM_PACKAGE = 11 + + +class CompressionType: + NONE = 0 + BZIP2 = 1 + GZIP = 2 + + +MACHINE_TYPES = { + 'MSWITCH': 0, + 'CABERNET': 1, + 'SYRAH': 2, + 'MERLOT': 3, + 'MUSCAT': 4, + 'NEBBIOLO': 5, + 'MALBEC': 6, + 'PALOMINO': 7, + 'GRENACHE': 8, + 'MOSCATO': 9, + 'TALISKER': 10, + 'JURA_R': 11, + 'SCAPA': 12, + 'JURA_O': 13, + 'CORVINA': 14, + 'ARRAN': 15, + 'BLUEBLOOD': 16, + 'MSR2K': 17, + 'PORFIDIO': 18, + 'CAZULO': 19, + 'SCAPA_H': 20, + 'CARDHU': 21, + 'BOWMORE': 22, + 'TAMDHU': 23, + 'ARDBEG': 24, + 'ARDMORE': 25, + 'DALMORE': 26, + 'K2': 27, + 'GRAPPA': 28, + 'SHUMWAY': 29, + 'SPRINGBANK': 30, + 'OUZO': 31, + 'AMARULA': 32, + 'GROZDOVA': 33, + 'PALINKA': 34, + 'HAZELBURN': 35, + 'TOMATIN': 36, + 'HAZELBURN_H': 37, + 'TOMATIN_16': 38, + 'SPRINGBANK_16': 39, + 'OCTOMORE': 40, + 'BALVENIE': 41, + 'OUZO_PLUS': 42, + 'X4': 43, + 'EINAR': 44, + 'GLENFARCLAS': 45, + 'GLENFIDDICH': 46, + 'EIGER': 47, + 'GLENMORANGIE': 48, + 'MILAGRO': 49, + 'OPUSONE': 50, + 'ABERLOUR': 51, + 'MILLSTONE': 52, + 'DEWARS': 53, + 'BUNKER': 54, + 'MASTERSON': 55, + 'SIERRA': 56, + 'KILCHOMAN': 57, + 'SPEYBURN': 58, + 'LAGAVULIN': 59, + 'LAPHROAIG': 60, + 'TOBA': 61, + 'ARRANTA': 62, +} + + +class NextHeader: + NONE = 0x00000000 + SIGN = 0x01111111 + + +class Flags: + C_TEST_BUILD = 0x00000001 + SWATCH = 0x00000002 + # Preserves the image with "clear all" + DONT_CLEAR_ON_PURGE = 0x00000004 + SECURE_BOOTLOADER = 0x00000008 + FACTORY_IMAGE = 0x00000010 + FIPS_CERTIFIED = 0x00000020 + + +def make_header(data: bytes, build: str, version: str, oem: str, imageType: int, machine: int) -> bytes: + buildBytes = build.encode(encoding='ascii') + assert len(buildBytes) < LEN_BUILD + buildBytes += b'\0' * (LEN_BUILD - len(buildBytes)) + + versionBytes = version.encode(encoding='ascii') + assert len(versionBytes) < LEN_VERSION + versionBytes += b'\0' * (LEN_VERSION - len(versionBytes)) + + oemBytes = oem.encode(encoding='ascii') + assert len(oemBytes) < LEN_OEM + oemBytes += b'\0' * (LEN_OEM - len(oemBytes)) + + header = b'' + # Payload size, image plus optional signature (which we don't use) + header += len(data).to_bytes(4, 'big') + # Use what appears to be the current version + header += FormatVersion.CURRENT.to_bytes(4, 'big') + # Checksum is computed later + header += b'\0\0\0\0' + # Vendor magic number + header += HEADER_MAGIC + # Long build information string + header += buildBytes + # Short version information string + header += versionBytes + # Image is valid + header += ValidFlag.YES.to_bytes(1, 'big') + # Image type + header += imageType.to_bytes(1, 'big') + # APBoot doesn't appear to actually support compression + header += CompressionType.NONE.to_bytes(1, 'big') + # Machine type + header += machine.to_bytes(1, 'big') + # Image size + header += len(data).to_bytes(4, 'big') + # Next header (we don't support signing) + header += NextHeader.NONE.to_bytes(4, 'big') + # MD5 checksum plus fudge factor (to ensure non-zero hash), appears unused + header += b'\0' * 16 + header += b'\0' * 4 + # No flags are set + header += int(0).to_bytes(4, 'big') + # No next header is used + header += b'\0' * 12 + # Padding + header += b'\0' * 36 + # OEM string + header += oemBytes + # Padding + header += b'\0' * 96 + + assert len(header) == 512 + assert len(data) % 4 == 0 + + # Compute checksum such that the big-endian sum of all 32-bit integers becomes zero. + curSum = sum(int.from_bytes(header[i : i + 4], 'big') for i in range(0, 512, 4)) + curSum += sum(int.from_bytes(data[i : i + 4], 'big') for i in range(0, len(data), 4)) + + # Set checksum + checksum = 0x100000000 - (curSum % 0x100000000) + header = header[:8] + checksum.to_bytes(4, 'big') + header[12:] + + return header + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Generate Aruba header.') + parser.add_argument('source') + parser.add_argument('dest') + parser.add_argument('build') + parser.add_argument('version') + parser.add_argument('oem') + parser.add_argument('type', choices=['os', 'boot']) + parser.add_argument('machine', choices=MACHINE_TYPES.keys(), type=str.upper) + args = parser.parse_args() + + # Parse image type. + # The OS image must be type "ELF" even though it's not an ELF file... + imageType = {'os': ImageType.ELF, 'boot': ImageType.APBOOT_BINARY}[args.type] + # Parse machine type. + machineType = MACHINE_TYPES[args.machine] + + source = open(args.source, 'rb') + image = source.read() + # Pad image. + if len(image) % 4 != 0: + image += b'\0' * (4 - len(image) % 4) + + # Generate header. + header = make_header(image, args.build, args.version, args.oem, imageType, machineType) + + # Write output. + dest = open(args.dest, 'wb') + dest.write(header) + dest.write(image) diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network index 6f490cb55d..e034172886 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -14,6 +14,11 @@ ipq806x_setup_interfaces() arris,tr4400-v2) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "eth2" ;; + aruba,ap-32x|\ + edgecore,ecw5410|\ + extreme,ap3935) + ucidef_set_interfaces_lan_wan "eth1" "eth0" + ;; askey,rt4230w-rev6|\ asrock,g10|\ buffalo,wxr-2533dhp|\ @@ -47,10 +52,6 @@ ipq806x_setup_interfaces() ucidef_set_network_device_conduit "lan1" "eth1" ucidef_set_network_device_conduit "wan" "eth0" ;; - edgecore,ecw5410|\ - extreme,ap3935) - ucidef_set_interfaces_lan_wan "eth1" "eth0" - ;; fortinet,fap-421e|\ ignitenet,ss-w2-ac2600|\ ubnt,unifi-ac-hd|\ diff --git a/target/linux/ipq806x/base-files/etc/init.d/bootcount b/target/linux/ipq806x/base-files/etc/init.d/bootcount index 669b815e39..1b9ace9f63 100755 --- a/target/linux/ipq806x/base-files/etc/init.d/bootcount +++ b/target/linux/ipq806x/base-files/etc/init.d/bootcount @@ -6,13 +6,14 @@ START=99 boot() { case $(board_name) in - asrock,g10) - asrock_bootconfig_mangle "bootcheck" && reboot - ;; + aruba,ap-32x|\ edgecore,ecw5410|\ ignitenet,ss-w2-ac2600) fw_setenv bootcount 0 ;; + asrock,g10) + asrock_bootconfig_mangle "bootcheck" && reboot + ;; extreme,ap3935) fw_setenv WATCHDOG_COUNT 0x00000000 ;; diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index 972aa41a85..e980598a38 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -26,6 +26,21 @@ platform_do_upgrade() { qcom,ipq8064-ap161) nand_do_upgrade "$1" ;; + aruba,ap-32x) + # The bootloader on this device unfortunately enforces a particular set of UBI volumes, + # and will mess with the partitioning if it doesn't find it. + # Therefore, we have to make do with the stock layout, which is a set of three + # MTD partitions, each containing a single UBI volume with the same name. + # Luckily, it doesn't check size, so we can have a "rootfs_data" volume next to a dummy + # "ubifs" volume on the "ubifs" partition. + CI_KERNPART="aos0" + CI_ROOTPART="aos1" + CI_KERN_UBIPART="aos0" + CI_ROOT_UBIPART="aos1" + CI_DATA_UBIPART="ubifs" + CI_SKIP_KERNEL_MTD=1 + nand_do_upgrade "$1" + ;; asrock,g10) asrock_upgrade_prepare nand_do_upgrade "$1" diff --git a/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts b/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts new file mode 100644 index 0000000000..b6f1b7b110 --- /dev/null +++ b/target/linux/ipq806x/dts/qcom-ipq8068-ap-32x.dts @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq8064-v2.0.dtsi" + +#include +#include +#include + +/ { + model = "Aruba AP-32x"; + compatible = "aruba,ap-32x", "qcom,ipq8064"; + + memory@0 { + reg = <0x41500000 0x1eb00000>; + device_type = "memory"; + }; + + aliases { + serial0 = &gsbi4_serial; + serial1 = &gsbi2_serial; + + ethernet0 = &gmac2; + ethernet1 = &gmac3; + + led-boot = &led_power_amber; + led-failsafe = &led_power_red; + led-running = &led_power_green; + led-upgrade = &led_power_amber; + + label-mac-device = &gmac2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs-append = " ubi.mtd=aos1 ubi.mtd=ubifs ubi.block=0,aos1 root=/dev/ubiblock0_0"; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&button_pins>; + pinctrl-names = "default"; + + reset { + label = "reset"; + gpios = <&qcom_pinmux 9 GPIO_ACTIVE_LOW>; + linux,code = ; + debounce-interval = <60>; + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&led_pins>; + pinctrl-names = "default"; + + led_power_green: power_green { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&qcom_pinmux 28 GPIO_ACTIVE_HIGH>; + }; + + led_power_amber: power_amber { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&qcom_pinmux 29 GPIO_ACTIVE_HIGH>; + }; + + led_power_red: power_red { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&qcom_pinmux 30 GPIO_ACTIVE_HIGH>; + }; + + led_wlan_green { + function = LED_FUNCTION_WLAN; + color = ; + gpios = <&qcom_pinmux 31 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy0tpt"; + }; + + led_wlan_amber { + function = LED_FUNCTION_WLAN; + color = ; + gpios = <&qcom_pinmux 32 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "phy1tpt"; + }; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&qcom_pinmux 61 GPIO_ACTIVE_LOW>; + hw_algo = "toggle"; + hw_margin_ms = <1000>; + always-running; + + pinctrl-names = "default"; + pinctrl-0 = <&watchdog_pins>; + }; + + i2c { + compatible = "i2c-gpio"; + + sda-gpios = <&qcom_pinmux 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios = <&qcom_pinmux 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + + #address-cells = <1>; + #size-cells = <0>; + + tpm@29 { + compatible = "atmel,at97sc3204t"; + reg = <0x29>; + }; + }; +}; + +&qcom_pinmux { + led_pins: led_pins { + mux { + pins = "gpio28", "gpio29", "gpio30", "gpio31", "gpio32"; + function = "gpio"; + drive-strength = <12>; + bias-pull-up; + }; + }; + + button_pins: button_pins { + mux { + pins = "gpio9"; + function = "gpio"; + bias-pull-up; + }; + }; + + uart0_pins: uart0_pins { + mux { + pins = "gpio10", "gpio11"; + function = "gsbi4"; + drive-strength = <10>; + bias-disable; + }; + }; + + uart1_pins: uart1_pins { + mux { + pins = "gpio22", "gpio23"; + function = "gsbi2"; + drive-strength = <10>; + bias-disable; + }; + }; + + watchdog_pins: watchdog_pins { + mux { + pins = "gpio61"; + function = "gpio"; + drive-strength = <10>; + bias-disable; + }; + }; + /* used for USB over-current detection instead */ + /delete-node/ pcie2_pins; +}; + +&gsbi4 { + status = "okay"; + qcom,mode = ; +}; + +&gsbi4_serial { + status = "okay"; + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; +}; + +&gsbi2 { + status = "okay"; + qcom,mode = ; +}; + +&gsbi2_serial { + status = "okay"; + pinctrl-0 = <&uart1_pins>; + pinctrl-names = "default"; +}; + +&gsbi5 { + qcom,mode = ; + status = "okay"; + + spi@1a280000 { + status = "okay"; + spi-max-frequency = <50000000>; + + pinctrl-0 = <&spi_pins>; + pinctrl-names = "default"; + + cs-gpios = <&qcom_pinmux 20 GPIO_ACTIVE_LOW>; + + mx25u3235f@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; + reg = <0>; + + partitions { + compatible = "qcom,smem-part"; + + partition-art { + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + label = "0:art"; + + precal_art_1000: precal@1000 { + reg = <0x1000 0x2f20>; + }; + + precal_art_5000: precal@5000 { + reg = <0x5000 0x2f20>; + }; + }; + + partition-appsblenv { + label = "0:appsblenv"; + + nvmem-layout { + compatible = "u-boot,env"; + + macaddr_lan: ethaddr { + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; + }; +}; + +&pcie0 { + status = "okay"; +}; + +&pcie_bridge0 { + wifi@0,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x10000 0 0 0 0>; + + nvmem-cells = <&precal_art_1000>; + nvmem-cell-names = "pre-calibration"; + }; +}; + +&pcie1 { + status = "okay"; +}; + +&pcie_bridge1 { + wifi@0,0 { + compatible = "qcom,ath10k"; + status = "okay"; + reg = <0x10000 0 0 0 0>; + + nvmem-cells = <&precal_art_5000>; + nvmem-cell-names = "pre-calibration"; + }; +}; + +&nand { + status = "okay"; + + nand@0 { + compatible = "qcom,nandcs"; + + reg = <0>; + + nand-ecc-strength = <4>; + nand-bus-width = <8>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + aos0@0 { + label = "aos0"; + reg = <0x0 0x2000000>; + }; + + aos1@2000000 { + label = "aos1"; + reg = <0x2000000 0x2000000>; + }; + + ubifs@4000000 { + label = "ubifs"; + reg = <0x4000000 0x4000000>; + }; + }; + }; +}; + +&mdio0 { + status = "okay"; + + pinctrl-0 = <&mdio0_pins>; + pinctrl-names = "default"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&gmac2 { + status = "okay"; + + qcom,id = <2>; + mdiobus = <&mdio0>; + + phy-mode = "sgmii"; + phy-handle = <&phy0>; + + nvmem-cells = <&macaddr_lan 0>; + nvmem-cell-names = "mac-address"; +}; + +&gmac3 { + status = "okay"; + + qcom,id = <3>; + mdiobus = <&mdio0>; + + phy-mode = "sgmii"; + phy-handle = <&phy1>; + + nvmem-cells = <&macaddr_lan 1>; + nvmem-cell-names = "mac-address"; +}; + +&adm_dma { + status = "okay"; +}; + +/* USB Port 0 is connected to the onboard BLE SoC. + * The stock FW on that doesn't implement USB, so to prevent errors from + * being logged when the host fails to initialize it, it's disabled by + * default here. */ +&hs_phy_0 { + status = "disabled"; +}; + +&ss_phy_0 { + status = "disabled"; +}; + +&usb3_0 { + status = "disabled"; +}; + +&hs_phy_1 { + status = "okay"; +}; + +&ss_phy_1 { + status = "okay"; +}; + +&usb3_1 { + status = "okay"; +}; diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index 5fbb3a79e6..9da73c4c03 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -48,6 +48,18 @@ define Build/linksys-addfwhdr ;mv "$@.new" "$@" endef +define Build/apboot-addfwhdr + $(SCRIPT_DIR)/aruba-header.py \ + $@ $@.new \ + "$(call toupper,$(LINUX_KARCH)) $(VERSION_DIST) Linux-$(LINUX_VERSION), $(VERSION_NUMBER) $(VERSION_CODE)"\ + "$(VERSION_NUMBER)" \ + "$(VERSION_DIST)" \ + os \ + "$(word 1,$(1))" + + mv "$@.new" "$@" +endef + define Device/DniImage KERNEL_SUFFIX := -uImage KERNEL = kernel-bin | append-dtb | uImage none @@ -102,6 +114,25 @@ define Device/arris_tr4400-v2 endef TARGET_DEVICES += arris_tr4400-v2 +define Device/aruba_ap-32x + $(call Device/LegacyImage) + DEVICE_VENDOR := Aruba + DEVICE_MODEL := AP-325 + DEVICE_ALT0_VENDOR := Aruba + DEVICE_ALT0_MODEL := AP-324 + DEVICE_ALT1_VENDOR := Siemens + DEVICE_ALT1_MODEL := Scalance W1750D + SOC := qcom-ipq8068 + PAGESIZE := 2048 + BLOCKSIZE := 128k + KERNEL_SUFFIX := .ari + KERNEL = kernel-bin | append-dtb | uImage none | apboot-addfwhdr Octomore + KERNEL_LOADADDR = 0x41508000 + KERNEL_SIZE := 30720k + DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct kmod-i2c-gpio kmod-tpm-i2c-atmel +endef +TARGET_DEVICES += aruba_ap-32x + define Device/askey_rt4230w-rev6 $(call Device/LegacyImage) $(Device/dsa-migration) From 68ef94cb25d8aa97ca04bda93befe4b0c87b590c Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Fri, 12 Jun 2026 17:05:20 +0200 Subject: [PATCH 045/228] ipq806x: add apboot package for AP-32x This is unfortunately needed to disable the signature verification in the stock bootloader. Co-authored-by: Paul Spooren Signed-off-by: Lukas Stockner Link: https://github.com/openwrt/openwrt/pull/20738 Signed-off-by: Paul Spooren --- package/boot/apboot-aruba-ipq806x/Makefile | 77 ++++++++++++++++++++++ target/linux/ipq806x/image/generic.mk | 6 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 package/boot/apboot-aruba-ipq806x/Makefile diff --git a/package/boot/apboot-aruba-ipq806x/Makefile b/package/boot/apboot-aruba-ipq806x/Makefile new file mode 100644 index 0000000000..141b359b23 --- /dev/null +++ b/package/boot/apboot-aruba-ipq806x/Makefile @@ -0,0 +1,77 @@ +# +# Copyright (C) 2026 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=apboot-aruba-ipq806x +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/lukasstockner/ap325-apboot-openwrt.git +PKG_MIRROR_HASH:=ef91bc1539d50c19c35ae5d38eab1a4944692d3f651952f58800ea1f7ffd4878 +PKG_SOURCE_DATE:=2026-06-12 +PKG_SOURCE_VERSION:=d36bb7270a8a8a5c5988ff778e55de12e0c40745 + +PKG_LICENSE:=GPL-2.0-or-later +PKG_LICENSE_FILES:=COPYING +PKG_MAINTAINER:=Lukas Stockner + +# Legacy U-Boot tree, not Kbuild-parallel safe. +PKG_BUILD_PARALLEL:=0 +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk + +# Aruba/QCA board name in the APBoot tree (Makefile.releng target): +# octomore -> AP-324 / AP-325 (and Siemens Scalance W1750D) +APBOOT_BOARD:=octomore + +# Stamped into the version banner; the upstream Dockerfile uses the short hash. +APBOOT_LABELID:=$(call version_abbrev,$(PKG_SOURCE_VERSION)) + +define Package/apboot-aruba-ipq806x + SECTION:=boot + CATEGORY:=Boot Loaders + DEPENDS:=@TARGET_ipq806x + TITLE:=Patched Aruba APBoot for AP-32x + URL:=https://github.com/lukasstockner/ap325-apboot-openwrt +endef + +define Package/apboot-aruba-ipq806x/description + Patched build of the Aruba APBoot bootloader (a vendor fork of U-Boot) for + the Aruba AP-324 / AP-325 access points (board "octomore"). The factory + bootloader enforces RSA signatures on the firmware; this build removes the + signature check and switches the console to 115200 baud so that OpenWrt can + be booted. The resulting "u-boot.mbn" is meant to be flashed to the APPSBL + SPI-flash partition via the serial console. +endef + +# APBoot is a freestanding U-Boot, so build it with OpenWrt's target +# cross-toolchain instead of the bare-metal arm-none-eabi- default. The legacy +# Makefile honours an externally supplied CROSS_COMPILE. +define Build/Compile + +$(MAKE) -C $(PKG_BUILD_DIR) -f Makefile.releng $(APBOOT_BOARD) \ + SHELL=/bin/bash \ + CROSS_COMPILE=$(TARGET_CROSS) \ + HOSTCC="$(HOSTCC)" \ + LABELID=$(APBOOT_LABELID) \ + ARUBA_MAKE_VERBOSE=1 +endef + +# The bootloader is flashed by hand and is not part of the root filesystem. +# Stage the image so the ipq806x image build can emit it as a device artifact. +define Build/InstallDev + $(INSTALL_DIR) $(STAGING_DIR_IMAGE) + $(INSTALL_DATA) $(PKG_BUILD_DIR)/u-boot.mbn \ + $(STAGING_DIR_IMAGE)/aruba_ap-32x-apboot.mbn +endef + +define Package/apboot-aruba-ipq806x/install + : +endef + +$(eval $(call BuildPackage,apboot-aruba-ipq806x)) diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index 9da73c4c03..17a4078c5b 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -129,7 +129,11 @@ define Device/aruba_ap-32x KERNEL = kernel-bin | append-dtb | uImage none | apboot-addfwhdr Octomore KERNEL_LOADADDR = 0x41508000 KERNEL_SIZE := 30720k - DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct kmod-i2c-gpio kmod-tpm-i2c-atmel + UBOOT_PATH := $$(STAGING_DIR_IMAGE)/aruba_ap-32x-apboot.mbn + ARTIFACTS := apboot.mbn + ARTIFACT/apboot.mbn := append-uboot + DEVICE_PACKAGES := ath10k-firmware-qca99x0-ct kmod-i2c-gpio kmod-tpm-i2c-atmel \ + apboot-aruba-ipq806x endef TARGET_DEVICES += aruba_ap-32x From 24ec5ff687f2b45abcf06400766420ecc46e0535 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Tue, 16 Jun 2026 08:20:52 +0000 Subject: [PATCH 046/228] realtek: replace pending SFP patches with backport The SFP SMBus patches to access SFP modules with more than just byte access have finally been accepted upstream. Replace them with the upstreamed version, reorder them before our still downstream SMBus MDIO patches and refresh all. Link: https://github.com/openwrt/openwrt/pull/23825 Signed-off-by: Jonas Jelonek --- ...ze-i2c_block_size-at-adapter-configu.patch | 41 +++ ...-adapter-quirks-to-limit-block-size.patch} | 15 +- ...02-v7.2-net-sfp-extend-SMBus-support.patch | 249 ++++++++++++++++++ ...14-net-phy-sfp-add-support-for-SMBus.patch | 4 +- .../742-net-sfp-extend-SMBus-support.patch | 204 -------------- 5 files changed, 299 insertions(+), 214 deletions(-) create mode 100644 target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch rename target/linux/realtek/patches-6.18/{741-net-sfp-apply-I2C-adapter-quirks-to-limit-blocks.patch => 706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch} (81%) create mode 100644 target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch delete mode 100644 target/linux/realtek/patches-6.18/742-net-sfp-extend-SMBus-support.patch diff --git a/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch b/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch new file mode 100644 index 0000000000..c252aa95a0 --- /dev/null +++ b/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch @@ -0,0 +1,41 @@ +From 56d0885514491e5ed8f7593400879ab77c52504c Mon Sep 17 00:00:00 2001 +From: Jonas Jelonek +Date: Thu, 28 May 2026 20:52:40 +0000 +Subject: [PATCH] net: sfp: initialize i2c_block_size at adapter configure time + +sfp->i2c_block_size is only assigned in sfp_sm_mod_probe(), which runs +from the state machine timer after SFP_F_PRESENT has been set. Between +those two points, sfp_module_eeprom() (the ethtool -m callback) gates +only on SFP_F_PRESENT and can be entered with i2c_block_size still at +its kzalloc'd value of 0. + +On a pure-I2C adapter, sfp_i2c_read() then issues an i2c_transfer() +with msgs[1].len = 0 inside a loop that subtracts this_len from len +each iteration; on adapters that succeed a zero-length read the loop +never advances, spinning while holding rtnl_lock. + +This was previously addressed by initializing i2c_block_size in +sfp_alloc() (commit 813c2dd78618), but the initialization was dropped +when i2c_block_size was split from i2c_max_block_size. + +Initialize sfp->i2c_block_size from sfp->i2c_max_block_size in +sfp_i2c_configure(), so the field is valid as soon as the adapter is +known. sfp_sm_mod_probe() still reassigns it on each module insertion +to recover from a per-module clamp to 1 (sfp_id_needs_byte_io). + +Fixes: 7662abf4db94 ("net: phy: sfp: Add support for SMBus module access") +Cc: stable@vger.kernel.org +Signed-off-by: Jonas Jelonek +Link: https://patch.msgid.link/20260528205242.971410-2-jelonek.jonas@gmail.com +Signed-off-by: Jakub Kicinski + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -824,6 +824,7 @@ static int sfp_i2c_configure(struct sfp + return -EINVAL; + } + ++ sfp->i2c_block_size = sfp->i2c_max_block_size; + return 0; + } + diff --git a/target/linux/realtek/patches-6.18/741-net-sfp-apply-I2C-adapter-quirks-to-limit-blocks.patch b/target/linux/realtek/patches-6.18/706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch similarity index 81% rename from target/linux/realtek/patches-6.18/741-net-sfp-apply-I2C-adapter-quirks-to-limit-blocks.patch rename to target/linux/realtek/patches-6.18/706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch index 7e575141d2..7516450646 100644 --- a/target/linux/realtek/patches-6.18/741-net-sfp-apply-I2C-adapter-quirks-to-limit-blocks.patch +++ b/target/linux/realtek/patches-6.18/706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch @@ -1,8 +1,7 @@ -From 572304faf8c1d30f142060c76a3e731438fc5975 Mon Sep 17 00:00:00 2001 +From f2a138abfb719a3bfd370ca79f00055ec81e4f59 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek -Date: Thu, 22 Jan 2026 10:59:20 +0000 -Subject: [PATCH net-next v6 1/2] net: sfp: apply I2C adapter quirks to limit - block size +Date: Sun, 14 Jun 2026 13:34:17 +0000 +Subject: [PATCH 1/2] net: sfp: apply I2C adapter quirks to limit block size The SFP driver assumes all I2C adapters support reading and writing the pre-defined block size SFP_EEPROM_BLOCK_SIZE of 16 bytes. This constant @@ -19,9 +18,9 @@ max_read_len and max_write_len in struct i2c_adapter_quirks into account to further limit the maximum block size if needed. Signed-off-by: Jonas Jelonek ---- - drivers/net/phy/sfp.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260614133418.2068201-2-jelonek.jonas@gmail.com +Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -54,6 +53,6 @@ Signed-off-by: Jonas Jelonek + max_block_size = min(max_block_size, i2c->quirks->max_write_len); + + sfp->i2c_max_block_size = max_block_size; + sfp->i2c_block_size = sfp->i2c_max_block_size; return 0; } - diff --git a/target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch b/target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch new file mode 100644 index 0000000000..e092443707 --- /dev/null +++ b/target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch @@ -0,0 +1,249 @@ +From 58b29bdf6186a8c3f2d725619c0b17cf602ac4e0 Mon Sep 17 00:00:00 2001 +From: Jonas Jelonek +Date: Sun, 14 Jun 2026 13:34:18 +0000 +Subject: [PATCH 2/2] net: sfp: extend SMBus support + +Commit 7662abf4db94 ("net: phy: sfp: Add support for SMBus module access") +added SMBus access for SFP modules, but limited it to single-byte +transfers. As a side effect, hwmon is disabled (16-bit reads cannot be +guaranteed atomic) and a warning is printed. + +Many SMBus-only I2C controllers in the wild support more than just +byte access, and SFP cages are often wired to such controllers +rather than to a full-featured I2C controller -- e.g. the SMBus +controllers in the Realtek longan and mango SoCs, which advertise +word access and I2C block reads. Today, they cannot drive an SFP at +all without falling back to the byte-only path. + +Extend sfp_smbus_read()/sfp_smbus_write() so that, in addition to +the existing byte access, they also use SMBus word access and SMBus +I2C block access whenever the adapter advertises them. Both +directions are handled in a single read and a single write helper +that pick the largest supported transfer per chunk and fall back as +needed. + +I2C-block is preferred unconditionally when available: the protocol +carries any length 1..32, so it can serve every chunk -- including +the 1- and 2-byte tails -- without help from word or byte access. +Note that this requires I2C_FUNC_SMBUS_I2C_BLOCK, which reads a +caller-specified number of bytes. This deviates from the official +SMBus Block Read (length is supplied by the slave) but is widely +supported by Linux I2C controllers/drivers. + +Capability matrix this implementation supports: + + - BYTE only: works (unchanged behaviour); 1-byte + xfers, hwmon disabled. + - BYTE + WORD: word for >=2-byte chunks, byte for + trailing odd byte. + - I2C_BLOCK present (with or + without BYTE/WORD): block as the universal transport for + every chunk. + - WORD only (no BYTE/BLOCK): accepted with WARN_ONCE. Even-length + transfers work; odd-length transfers + (e.g. the 3-byte cotsworks fixup + write) hit the BYTE branch which the + adapter does not implement, so the + xfer returns an error and the + operation is aborted. No mainline + I2C driver was found to advertise + WORD without BYTE; the warning lets + us learn about it if it ever shows + up. + +Adapters with asymmetric R/W capabilities (e.g. only READ_I2C_BLOCK +but not WRITE_I2C_BLOCK) remain functionally correct -- the +per-iteration fallback uses the direction-specific bits -- but the +shared i2c_max_block_size is sized by the all-bits-set check, so a +transfer in the better-supported direction is not upgraded. None of +the mainline I2C bus drivers surveyed during review advertise such +asymmetry; promoting i2c_max_block_size to per-direction sizes can +be revisited if needed. + +Signed-off-by: Jonas Jelonek +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260614133418.2068201-3-jelonek.jonas@gmail.com +Signed-off-by: Jakub Kicinski + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + + #include "sfp.h" +@@ -758,50 +759,113 @@ static int sfp_i2c_write(struct sfp *sfp + return ret == ARRAY_SIZE(msgs) ? len : 0; + } + +-static int sfp_smbus_byte_read(struct sfp *sfp, bool a2, u8 dev_addr, +- void *buf, size_t len) ++static int sfp_smbus_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf, ++ size_t len) + { +- union i2c_smbus_data smbus_data; ++ union i2c_smbus_data smbus_data = {0}; + u8 bus_addr = a2 ? 0x51 : 0x50; ++ size_t this_len, transferred; ++ u32 functionality; + u8 *data = buf; + int ret; + +- while (len) { +- ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, +- I2C_SMBUS_READ, dev_addr, +- I2C_SMBUS_BYTE_DATA, &smbus_data); +- if (ret < 0) +- return ret; ++ functionality = i2c_get_functionality(sfp->i2c); + +- *data = smbus_data.byte; ++ while (len) { ++ this_len = min(len, sfp->i2c_block_size); + +- len--; +- data++; +- dev_addr++; ++ if (functionality & I2C_FUNC_SMBUS_READ_I2C_BLOCK) { ++ smbus_data.block[0] = this_len; ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_READ, dev_addr, ++ I2C_SMBUS_I2C_BLOCK_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ transferred = min_t(size_t, smbus_data.block[0], this_len); ++ if (!transferred) ++ return -EIO; ++ ++ memcpy(data, &smbus_data.block[1], transferred); ++ } else if (this_len >= 2 && ++ (functionality & I2C_FUNC_SMBUS_READ_WORD_DATA)) { ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_READ, dev_addr, ++ I2C_SMBUS_WORD_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ put_unaligned_le16(smbus_data.word, data); ++ transferred = 2; ++ } else { ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_READ, dev_addr, ++ I2C_SMBUS_BYTE_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ *data = smbus_data.byte; ++ transferred = 1; ++ } ++ ++ data += transferred; ++ len -= transferred; ++ dev_addr += transferred; + } + + return data - (u8 *)buf; + } + +-static int sfp_smbus_byte_write(struct sfp *sfp, bool a2, u8 dev_addr, +- void *buf, size_t len) ++static int sfp_smbus_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf, ++ size_t len) + { + union i2c_smbus_data smbus_data; + u8 bus_addr = a2 ? 0x51 : 0x50; ++ size_t this_len, transferred; ++ u32 functionality; + u8 *data = buf; + int ret; + ++ functionality = i2c_get_functionality(sfp->i2c); ++ + while (len) { +- smbus_data.byte = *data; +- ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, +- I2C_SMBUS_WRITE, dev_addr, +- I2C_SMBUS_BYTE_DATA, &smbus_data); +- if (ret) +- return ret; ++ this_len = min(len, sfp->i2c_block_size); + +- len--; +- data++; +- dev_addr++; ++ if (functionality & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) { ++ smbus_data.block[0] = this_len; ++ memcpy(&smbus_data.block[1], data, this_len); ++ ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_WRITE, dev_addr, ++ I2C_SMBUS_I2C_BLOCK_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ transferred = this_len; ++ } else if (this_len >= 2 && ++ (functionality & I2C_FUNC_SMBUS_WRITE_WORD_DATA)) { ++ smbus_data.word = get_unaligned_le16(data); ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_WRITE, dev_addr, ++ I2C_SMBUS_WORD_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ transferred = 2; ++ } else { ++ smbus_data.byte = *data; ++ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, ++ I2C_SMBUS_WRITE, dev_addr, ++ I2C_SMBUS_BYTE_DATA, &smbus_data); ++ if (ret < 0) ++ return ret; ++ ++ transferred = 1; ++ } ++ ++ data += transferred; ++ len -= transferred; ++ dev_addr += transferred; + } + + return data - (u8 *)buf; +@@ -817,10 +881,29 @@ static int sfp_i2c_configure(struct sfp + sfp->read = sfp_i2c_read; + sfp->write = sfp_i2c_write; + max_block_size = SFP_EEPROM_BLOCK_SIZE; +- } else if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA)) { +- sfp->read = sfp_smbus_byte_read; +- sfp->write = sfp_smbus_byte_write; +- max_block_size = 1; ++ } else if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA) || ++ i2c_check_functionality(i2c, I2C_FUNC_SMBUS_I2C_BLOCK)) { ++ /* Either protocol alone covers any length: I2C-block carries ++ * 1..32 bytes per xfer, byte iterates one byte at a time. ++ */ ++ sfp->read = sfp_smbus_read; ++ sfp->write = sfp_smbus_write; ++ ++ if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_I2C_BLOCK)) ++ max_block_size = SFP_EEPROM_BLOCK_SIZE; ++ else if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_WORD_DATA)) ++ max_block_size = 2; ++ else ++ max_block_size = 1; ++ } else if (WARN_ONCE(i2c_check_functionality(i2c, I2C_FUNC_SMBUS_WORD_DATA), ++ "SMBus word-only adapter; odd-length transfers will fail\n")) { ++ /* Word-only: even-length xfers work; odd-length xfers fall ++ * to BYTE, which the adapter does not advertise and will ++ * likely fail. ++ */ ++ sfp->read = sfp_smbus_read; ++ sfp->write = sfp_smbus_write; ++ max_block_size = 2; + } else { + sfp->i2c = NULL; + return -EINVAL; diff --git a/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch b/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch index 390ffabb99..cc6283f0a7 100644 --- a/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch +++ b/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch @@ -10,7 +10,7 @@ Signed-off-by: Antoine Tenart --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -850,6 +850,29 @@ static int sfp_i2c_mdiobus_create(struct +@@ -942,6 +942,29 @@ static int sfp_i2c_mdiobus_create(struct return 0; } @@ -40,7 +40,7 @@ Signed-off-by: Antoine Tenart static void sfp_i2c_mdiobus_destroy(struct sfp *sfp) { mdiobus_unregister(sfp->i2c_mii); -@@ -2024,9 +2047,15 @@ static void sfp_sm_fault(struct sfp *sfp +@@ -2116,9 +2139,15 @@ static void sfp_sm_fault(struct sfp *sfp static int sfp_sm_add_mdio_bus(struct sfp *sfp) { diff --git a/target/linux/realtek/patches-6.18/742-net-sfp-extend-SMBus-support.patch b/target/linux/realtek/patches-6.18/742-net-sfp-extend-SMBus-support.patch deleted file mode 100644 index da94989670..0000000000 --- a/target/linux/realtek/patches-6.18/742-net-sfp-extend-SMBus-support.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 475b0dd976de6db975bfef7d6fdb978d2d64c535 Mon Sep 17 00:00:00 2001 -From: Jonas Jelonek -Date: Fri, 9 Jan 2026 21:04:02 +0000 -Subject: [PATCH net-next v6 2/2] net: sfp: extend SMBus support - -Commit 7662abf4db94 ("net: phy: sfp: Add support for SMBus module access") -added support for SMBus-only controllers for module access. However, this -is restricted to single-byte accesses and has the implication that hwmon -is disabled (due to missing atomicity of 16-bit accesses) and warnings -are printed. - -There are probably a lot of SMBus-only I2C controllers out in the wild -which support more than just byte access. And it also seems that in -several devices, SFP slots are attached to these SMBus controllers -instead of full-featured I2C controllers. Right now, they don't work -with SFP modules. This applies - amongst others - to I2C/SMBus-only -controllers in Realtek longan and mango SoCs. They also support word -access and I2C block reads. - -Extend the current read/write SMBus operations to support SMBus I2C -block and SMBus word access. To avoid having dedicated operations for -each kind of transfer, provide generic read and write operations that -covers all kinds of access depending on whats supported. - -For block access, this requires I2C_FUNC_SMBUS_I2C_BLOCK to be -supported as it relies on reading a pre-defined amount of bytes. -This isn't intended by the official SMBus Block Read but supported by -several I2C controllers/drivers. - -Signed-off-by: Jonas Jelonek ---- - drivers/net/phy/sfp.c | 117 +++++++++++++++++++++++++++++++++--------- - 1 file changed, 92 insertions(+), 25 deletions(-) - ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - - #include "sfp.h" -@@ -758,50 +759,101 @@ static int sfp_i2c_write(struct sfp *sfp - return ret == ARRAY_SIZE(msgs) ? len : 0; - } - --static int sfp_smbus_byte_read(struct sfp *sfp, bool a2, u8 dev_addr, -- void *buf, size_t len) -+static int sfp_smbus_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf, -+ size_t len) - { - union i2c_smbus_data smbus_data; - u8 bus_addr = a2 ? 0x51 : 0x50; -+ size_t this_len, transferred; -+ u32 functionality; - u8 *data = buf; - int ret; - -+ functionality = i2c_get_functionality(sfp->i2c); -+ - while (len) { -- ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -- I2C_SMBUS_READ, dev_addr, -- I2C_SMBUS_BYTE_DATA, &smbus_data); -+ this_len = min(len, sfp->i2c_max_block_size); -+ -+ if (functionality & I2C_FUNC_SMBUS_READ_I2C_BLOCK) { -+ smbus_data.block[0] = this_len; -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_READ, dev_addr, -+ I2C_SMBUS_I2C_BLOCK_DATA, &smbus_data); -+ -+ memcpy(data, &smbus_data.block[1], this_len); -+ transferred = this_len; -+ } else if (this_len >= 2 && -+ functionality & I2C_FUNC_SMBUS_READ_WORD_DATA) { -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_READ, dev_addr, -+ I2C_SMBUS_WORD_DATA, &smbus_data); -+ -+ put_unaligned_le16(smbus_data.word, data); -+ transferred = 2; -+ } else { -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_READ, dev_addr, -+ I2C_SMBUS_BYTE_DATA, &smbus_data); -+ -+ *data = smbus_data.byte; -+ transferred = 1; -+ } -+ - if (ret < 0) - return ret; - -- *data = smbus_data.byte; -- -- len--; -- data++; -- dev_addr++; -+ data += transferred; -+ len -= transferred; -+ dev_addr += transferred; - } - - return data - (u8 *)buf; - } - --static int sfp_smbus_byte_write(struct sfp *sfp, bool a2, u8 dev_addr, -- void *buf, size_t len) -+static int sfp_smbus_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf, -+ size_t len) - { - union i2c_smbus_data smbus_data; - u8 bus_addr = a2 ? 0x51 : 0x50; -+ size_t this_len, transferred; -+ u32 functionality; - u8 *data = buf; - int ret; - -+ functionality = i2c_get_functionality(sfp->i2c); -+ - while (len) { -- smbus_data.byte = *data; -- ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -- I2C_SMBUS_WRITE, dev_addr, -- I2C_SMBUS_BYTE_DATA, &smbus_data); -- if (ret) -+ this_len = min(len, sfp->i2c_max_block_size); -+ -+ if (functionality & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) { -+ smbus_data.block[0] = this_len; -+ memcpy(&smbus_data.block[1], data, this_len); -+ -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_WRITE, dev_addr, -+ I2C_SMBUS_I2C_BLOCK_DATA, &smbus_data); -+ transferred = this_len; -+ } else if (this_len >= 2 && -+ functionality & I2C_FUNC_SMBUS_WRITE_WORD_DATA) { -+ smbus_data.word = get_unaligned_le16(data); -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_WRITE, dev_addr, -+ I2C_SMBUS_WORD_DATA, &smbus_data); -+ transferred = 2; -+ } else { -+ smbus_data.byte = *data; -+ ret = i2c_smbus_xfer(sfp->i2c, bus_addr, 0, -+ I2C_SMBUS_WRITE, dev_addr, -+ I2C_SMBUS_BYTE_DATA, &smbus_data); -+ transferred = 1; -+ } -+ -+ if (ret < 0) - return ret; - -- len--; -- data++; -- dev_addr++; -+ data += transferred; -+ len -= transferred; -+ dev_addr += transferred; - } - - return data - (u8 *)buf; -@@ -810,17 +862,32 @@ static int sfp_smbus_byte_write(struct s - static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c) - { - size_t max_block_size; -+ u32 functionality; - - sfp->i2c = i2c; -+ functionality = i2c_get_functionality(i2c); - -- if (i2c_check_functionality(i2c, I2C_FUNC_I2C)) { -+ if (functionality & I2C_FUNC_I2C) { - sfp->read = sfp_i2c_read; - sfp->write = sfp_i2c_write; - max_block_size = SFP_EEPROM_BLOCK_SIZE; -- } else if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA)) { -- sfp->read = sfp_smbus_byte_read; -- sfp->write = sfp_smbus_byte_write; -- max_block_size = 1; -+ } else if ((functionality & I2C_FUNC_SMBUS_BYTE_DATA) == I2C_FUNC_SMBUS_BYTE_DATA || -+ (functionality & I2C_FUNC_SMBUS_I2C_BLOCK) == I2C_FUNC_SMBUS_I2C_BLOCK) { -+ sfp->read = sfp_smbus_read; -+ sfp->write = sfp_smbus_write; -+ -+ if ((functionality & I2C_FUNC_SMBUS_I2C_BLOCK) == I2C_FUNC_SMBUS_I2C_BLOCK) -+ max_block_size = SFP_EEPROM_BLOCK_SIZE; -+ else if ((functionality & I2C_FUNC_SMBUS_WORD_DATA) == I2C_FUNC_SMBUS_WORD_DATA) -+ max_block_size = 2; -+ else -+ max_block_size = 1; -+ } else if ((functionality & I2C_FUNC_SMBUS_WORD_DATA) == I2C_FUNC_SMBUS_WORD_DATA) { -+ WARN(1, "SMBus adapter only supports word access, odd reads/writes will fail!\n"); -+ -+ sfp->read = sfp_smbus_read; -+ sfp->write = sfp_smbus_write; -+ max_block_size = 2; - } else { - sfp->i2c = NULL; - return -EINVAL; From 4a0e6aa95c122cb33c7828fd27ea0dbf56abca5c Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Tue, 16 Jun 2026 10:47:25 +0000 Subject: [PATCH 047/228] generic: mips: replace pending patch with backport The pending patch fixing reboot behavior on Realtek MIPS (and possibly other MIPS targets) has been accepted upstream. Replace with a proper backport. Link: https://github.com/openwrt/openwrt/pull/23831 Signed-off-by: Jonas Jelonek --- ...rt-dying-CPU-to-RCU-in-stop_this_cpu.patch | 66 +++++++++++++++++++ ...rt-dying-CPU-to-RCU-in-stop_this_cpu.patch | 53 --------------- 2 files changed, 66 insertions(+), 53 deletions(-) create mode 100644 target/linux/generic/backport-6.18/300-v7.2-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch delete mode 100644 target/linux/generic/pending-6.18/331-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch diff --git a/target/linux/generic/backport-6.18/300-v7.2-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch b/target/linux/generic/backport-6.18/300-v7.2-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch new file mode 100644 index 0000000000..8f419e2fe4 --- /dev/null +++ b/target/linux/generic/backport-6.18/300-v7.2-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch @@ -0,0 +1,66 @@ +From 9f3f3bdc6d9dac1a5a8262ee7ad0f2ff1527a7e7 Mon Sep 17 00:00:00 2001 +From: Jonas Jelonek +Date: Mon, 8 Jun 2026 09:37:29 +0000 +Subject: MIPS: smp: report dying CPU to RCU in stop_this_cpu() + +smp_send_stop() parks all secondary CPUs in stop_this_cpu(). The function +marks the CPU offline for the scheduler via set_cpu_online(false) but +never informs RCU, so RCU keeps expecting a quiescent state from CPUs +that are now spinning forever with interrupts disabled. + +As long as nothing waits for an RCU grace period after smp_send_stop() +this is harmless, which is why it went unnoticed. Since commit +91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +however, irq_work_sync() calls synchronize_rcu() on architectures without +an irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns +false. That is the asm-generic default used by MIPS. Any irq_work_sync() +issued in the reboot/shutdown path after smp_send_stop() then blocks on +a grace period that can never complete, hanging the reboot: + + WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on + ... + rcu: INFO: rcu_sched detected stalls on CPUs/tasks: + rcu: Offline CPU 1 blocking current GP. + rcu: Offline CPU 2 blocking current GP. + rcu: Offline CPU 3 blocking current GP. + +This issue was noticed on several Realtek MIPS switch SoCs (MIPS +interAptiv) and came up during kernel bump downstream in OpenWrt from +6.18.33 to 6.18.34, after the backport of the patch to the 6.18 stable +branch. The patch also has been backported all the way back to 6.1. + +Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring the +generic CPU-hotplug offline path, so RCU stops waiting on the parked CPUs +and grace periods can still complete. MIPS shuts down all CPUs here +without going through the CPU-hotplug mechanism, so this report is not +otherwise issued. Reporting a dying CPU to RCU outside the regular hotplug +offline path is not unprecedented: arm64 does the same in cpu_die_early(). +There it is an exception for a CPU that was coming online and is aborting +bringup, rather than the default shutdown action as on MIPS. + +Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") +CC: stable@vger.kernel.org +Signed-off-by: Jonas Jelonek +Signed-off-by: Thomas Bogendoerfer +--- + arch/mips/kernel/smp.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/mips/kernel/smp.c ++++ b/arch/mips/kernel/smp.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -422,6 +423,7 @@ static void stop_this_cpu(void *dummy) + set_cpu_online(smp_processor_id(), false); + calculate_cpu_foreign_map(); + local_irq_disable(); ++ rcutree_report_cpu_dead(); + while (1); + } + diff --git a/target/linux/generic/pending-6.18/331-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch b/target/linux/generic/pending-6.18/331-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch deleted file mode 100644 index fc8cf0f5da..0000000000 --- a/target/linux/generic/pending-6.18/331-MIPS-smp-report-dying-CPU-to-RCU-in-stop_this_cpu.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jonas Jelonek -Date: Thu, 04 Jun 2026 00:00:00 +0200 -Subject: [PATCH] MIPS: smp: report dying CPU to RCU in stop_this_cpu() - -smp_send_stop() parks all secondary CPUs in stop_this_cpu(). The function -marks the CPU offline for the scheduler via set_cpu_online(false) but never -informs RCU, so RCU keeps expecting a quiescent state from CPUs that are -now spinning forever with interrupts disabled. - -As long as nothing waits for an RCU grace period after smp_send_stop() this -is harmless, which is why it went unnoticed. Since v6.18.34, however, -irq_work_sync() calls synchronize_rcu() on architectures without an -irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns false. -That is the asm-generic default used by MIPS. Any irq_work_sync() issued in -the reboot/shutdown path after smp_send_stop() then blocks on a grace period -that can never complete, hanging the reboot: - - WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on - ... - rcu: INFO: rcu_sched detected stalls on CPUs/tasks: - rcu: Offline CPU 1 blocking current GP. - rcu: Offline CPU 2 blocking current GP. - rcu: Offline CPU 3 blocking current GP. - -Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring the -generic CPU-hotplug offline path (and arm64's stop handling), so RCU stops -waiting on the parked CPUs and grace periods can still complete. - -Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") -Signed-off-by: Jonas Jelonek ---- - arch/mips/kernel/smp.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/mips/kernel/smp.c -+++ b/arch/mips/kernel/smp.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -422,6 +423,7 @@ static void stop_this_cpu(void *dummy) - set_cpu_online(smp_processor_id(), false); - calculate_cpu_foreign_map(); - local_irq_disable(); -+ rcutree_report_cpu_dead(); - while (1); - } - From fa55634872674a4c951db902771c472180106e37 Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Sun, 14 Jun 2026 19:33:28 +0200 Subject: [PATCH 048/228] uboot-zynq: fix boot process on MMC A regression was introduced when upgrading to 2019.07, whereas the bootloader did not proceed to load the FIT image. A fix was reported but not upstreamed here [1]. Patch the uEnv file to bring back these boards to an operational state. [1] https://forum.openwrt.org/t/bugreport-regression-in-zynq-cpu-platform-not-bootiing-any-more-zedboard-zybo/182609/7 Fixes: https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=5ca243153b110ceddffecb70ba8a8cd0e33c8f0b Signed-off-by: Zoltan HERPAI --- package/boot/uboot-zynq/files/uEnv-default.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/package/boot/uboot-zynq/files/uEnv-default.txt b/package/boot/uboot-zynq/files/uEnv-default.txt index 5030b07784..ec15c820e2 100644 --- a/package/boot/uboot-zynq/files/uEnv-default.txt +++ b/package/boot/uboot-zynq/files/uEnv-default.txt @@ -1 +1,2 @@ bootargs=console=ttyPS0,115200n8 root=/dev/mmcblk0p2 rootwait earlyprintk +bootcmd=run sdboot From e050bb79462219a535018c0e8022a9bcbd58b791 Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Sun, 14 Jun 2026 19:37:54 +0200 Subject: [PATCH 049/228] zynq: add Bitmain Antminer S9 control board support This board is the control board for the Antminer S9 miners. SoC: Xilinx XC7Z010 - dual-core Cortex-A9 with FPGA stack Memory: 512Mb DDR3 NIC: 1Gbit ethernet (BCM B50612E PHY) Flash: 256Mb NAND (Micron MT29F2G08ABAEAWP) Storage: SD-card slot Other: control pins available via FPGA stack Admittedly, there is a limited number of use cases available for these boards outside of the miners and the lack of FPGA tooling in OpenWrt. However, for one, they are easily and cheaply available, for two, the reason for adding this is to provide an easy addition to the boardfarm for continuous testing of this target. Notes: For u-boot, an additional patch is required to support booting from SD-cards. This is because EXTRA_ENV_SETTINGS is already defined in the board's u-boot config, which is the same place where the zynq-common.dtsi defines the required envvars. Signed-off-by: Zoltan HERPAI --- package/boot/uboot-zynq/Makefile | 7 ++ ...ntminer-s9-restore-sdboot-capability.patch | 37 +++++++ .../zynq/base-files/etc/board.d/02_network | 1 + target/linux/zynq/image/Makefile | 7 ++ .../patches/0001-dts-add-antminer-s9.patch | 102 ++++++++++++++++++ .../0002-dts-antminer-s9-led-aliases.patch | 23 ++++ 6 files changed, 177 insertions(+) create mode 100644 package/boot/uboot-zynq/patches/120-antminer-s9-restore-sdboot-capability.patch create mode 100644 target/linux/zynq/patches/0001-dts-add-antminer-s9.patch create mode 100644 target/linux/zynq/patches/0002-dts-antminer-s9-led-aliases.patch diff --git a/package/boot/uboot-zynq/Makefile b/package/boot/uboot-zynq/Makefile index 0f93c4f453..c376e93d51 100644 --- a/package/boot/uboot-zynq/Makefile +++ b/package/boot/uboot-zynq/Makefile @@ -30,6 +30,12 @@ define U-Boot/zc702 BUILD_DEVICES:=xlnx_zynq-zc702 endef +define U-Boot/antminer-s9 + NAME:=Bitmain Antminer S9 control board + BUILD_DEVICES:=bitmain_zynq-antminer-s9 + UBOOT_CONFIG:=bitmain_antminer_s9 +endef + define U-Boot/zed NAME:=Avnet Digilent ZedBoard Dev Board BUILD_DEVICES:=avnet_zynq-zed @@ -46,6 +52,7 @@ define U-Boot/zybo_z7 endef UBOOT_TARGETS := \ + antminer-s9 \ zc702 \ zed \ zybo \ diff --git a/package/boot/uboot-zynq/patches/120-antminer-s9-restore-sdboot-capability.patch b/package/boot/uboot-zynq/patches/120-antminer-s9-restore-sdboot-capability.patch new file mode 100644 index 0000000000..cd90fd22c9 --- /dev/null +++ b/package/boot/uboot-zynq/patches/120-antminer-s9-restore-sdboot-capability.patch @@ -0,0 +1,37 @@ +--- a/include/configs/bitmain_antminer_s9.h ++++ b/include/configs/bitmain_antminer_s9.h +@@ -20,6 +20,34 @@ + "initrd_high=0xefff000\0" \ + "devnum=0\0" \ + "wdstop=mw f8005000 ABC000\0" \ ++ "scriptaddr=0x3000000\0" \ ++ "loadbootenv_addr=0x2000000\0" \ ++ "fit_image=fit.itb\0" \ ++ "load_addr=0x2000000\0" \ ++ "bootenv=uEnv.txt\0" \ ++ "bootenv_dev=mmc\0" \ ++ "loadbootenv=load ${bootenv_dev} 0 ${loadbootenv_addr} ${bootenv}\0" \ ++ "importbootenv=echo Importing environment from ${bootenv_dev} ...; " \ ++ "env import -t ${loadbootenv_addr} $filesize\0" \ ++ "bootenv_existence_test=test -e ${bootenv_dev} 0 /${bootenv}\0" \ ++ "setbootenv=if env run bootenv_existence_test; then " \ ++ "if env run loadbootenv; then " \ ++ "env run importbootenv; " \ ++ "fi; " \ ++ "fi; \0" \ ++ "sd_loadbootenv=setenv bootenv_dev mmc && " \ ++ "run setbootenv \0" \ ++ "preboot=if test $modeboot = sdboot; then " \ ++ "run sd_loadbootenv; " \ ++ "echo Checking if uenvcmd is set ...; " \ ++ "if test -n $uenvcmd; then " \ ++ "echo Running uenvcmd ...; " \ ++ "run uenvcmd; " \ ++ "fi; " \ ++ "fi; \0" \ ++ "sdboot=echo Copying FIT from SD to RAM... && " \ ++ "load mmc 0 ${load_addr} ${fit_image} && " \ ++ "bootm ${load_addr}\0" \ + BOOTENV + + #include diff --git a/target/linux/zynq/base-files/etc/board.d/02_network b/target/linux/zynq/base-files/etc/board.d/02_network index 159b457682..63ff77dacd 100644 --- a/target/linux/zynq/base-files/etc/board.d/02_network +++ b/target/linux/zynq/base-files/etc/board.d/02_network @@ -6,6 +6,7 @@ board_config_update case "$(board_name)" in avnet,zynq-zed | \ +bitmain,antminer-s9 | \ digilent,zynq-zybo | \ digilent,zynq-zybo-z7 | \ xlnx,zynq-zc702) diff --git a/target/linux/zynq/image/Makefile b/target/linux/zynq/image/Makefile index 4a9c2f047d..dca6068a12 100644 --- a/target/linux/zynq/image/Makefile +++ b/target/linux/zynq/image/Makefile @@ -54,6 +54,13 @@ define Device/avnet_zynq-zed endef TARGET_DEVICES += avnet_zynq-zed +define Device/bitmain_zynq-antminer-s9 + $(call Device/FitImageGzip) + DEVICE_VENDOR := Bitmain + DEVICE_MODEL := Antminer S9 control board +endef +TARGET_DEVICES += bitmain_zynq-antminer-s9 + define Device/digilent_zynq-zybo $(call Device/FitImageGzip) DEVICE_VENDOR := Digilent diff --git a/target/linux/zynq/patches/0001-dts-add-antminer-s9.patch b/target/linux/zynq/patches/0001-dts-add-antminer-s9.patch new file mode 100644 index 0000000000..86eac89766 --- /dev/null +++ b/target/linux/zynq/patches/0001-dts-add-antminer-s9.patch @@ -0,0 +1,102 @@ +--- a/arch/arm/boot/dts/xilinx/Makefile ++++ b/arch/arm/boot/dts/xilinx/Makefile +@@ -1,5 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0 + dtb-$(CONFIG_ARCH_ZYNQ) += \ ++ zynq-antminer-s9.dtb \ + zynq-cc108.dtb \ + zynq-ebaz4205.dtb \ + zynq-microzed.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/xilinx/zynq-antminer-s9.dts +@@ -0,0 +1,90 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2011 - 2014 Xilinx ++ * Copyright (C) 2012 National Instruments Corp. ++ */ ++/dts-v1/; ++#include "zynq-7000.dtsi" ++ ++/ { ++ model = "Bitmain Antminer S9 control board"; ++ compatible = "bitmain,antminer-s9", "xlnx,zynq-7000"; ++ ++ aliases { ++ ethernet0 = &gem0; ++ serial0 = &uart1; ++ mmc0 = &sdhci0; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x20000000>; ++ }; ++ ++ chosen { ++ bootargs = ""; ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ usb_phy0: phy0 { ++ compatible = "usb-nop-xceiv"; ++ #phy-cells = <0>; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ led_red { ++ label = "s9:red:usr"; ++ gpios = <&gpio0 37 0x0>; ++ default-state = "off"; ++ }; ++ ++ led_green { ++ label = "s9:green:usr"; ++ gpios = <&gpio0 38 0x0>; ++ default-state = "off"; ++ }; ++ }; ++}; ++ ++&clkc { ++ ps-clk-frequency = <33333333>; ++}; ++ ++&gem0 { ++ status = "okay"; ++ phy-mode = "rgmii-id"; ++ phy-handle = <ðernet_phy>; ++ ++ ethernet_phy: ethernet-phy@1 { ++ reg = <1>; ++ device_type = "ethernet-phy"; ++ }; ++}; ++ ++&nfc0 { ++ status = "okay"; ++ ++ nand@0 { ++ reg = <0>; ++ }; ++}; ++ ++&sdhci0 { ++ status = "okay"; ++}; ++ ++&smcc { ++ status = "okay"; ++}; ++ ++&uart1 { ++ status = "okay"; ++}; ++ ++&usb0 { ++ status = "okay"; ++ dr_mode = "host"; ++ usb-phy = <&usb_phy0>; ++}; diff --git a/target/linux/zynq/patches/0002-dts-antminer-s9-led-aliases.patch b/target/linux/zynq/patches/0002-dts-antminer-s9-led-aliases.patch new file mode 100644 index 0000000000..66210d1f99 --- /dev/null +++ b/target/linux/zynq/patches/0002-dts-antminer-s9-led-aliases.patch @@ -0,0 +1,23 @@ +--- a/arch/arm/boot/dts/xilinx/zynq-antminer-s9.dts ++++ b/arch/arm/boot/dts/xilinx/zynq-antminer-s9.dts +@@ -14,6 +14,11 @@ + ethernet0 = &gem0; + serial0 = &uart1; + mmc0 = &sdhci0; ++ ++ led-boot = &led_green; ++ led-failsafe = &led_green; ++ led-running = &led_green; ++ led-upgrade = &led_green; + }; + + memory@0 { +@@ -40,7 +45,7 @@ + default-state = "off"; + }; + +- led_green { ++ led_green: led_green { + label = "s9:green:usr"; + gpios = <&gpio0 38 0x0>; + default-state = "off"; From 3aeaeb563ff8dc40caae50d8ad74646921a70660 Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Sun, 14 Jun 2026 19:40:26 +0200 Subject: [PATCH 050/228] zynq: enable NAND support Enable NAND support. Signed-off-by: Zoltan HERPAI --- target/linux/zynq/config-6.12 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/target/linux/zynq/config-6.12 b/target/linux/zynq/config-6.12 index b9453b663d..6fcb884999 100644 --- a/target/linux/zynq/config-6.12 +++ b/target/linux/zynq/config-6.12 @@ -334,7 +334,10 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_PL35X=y CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_RAW_NAND=y CONFIG_MTD_SPI_NOR=y CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y CONFIG_MTD_SPLIT_FIRMWARE=y @@ -411,7 +414,7 @@ CONFIG_PL310_ERRATA_727915=y CONFIG_PL310_ERRATA_753970=y CONFIG_PL310_ERRATA_769419=y CONFIG_PL330_DMA=y -# CONFIG_PL353_SMC is not set +CONFIG_PL353_SMC=y CONFIG_PLAT_VERSATILE=y CONFIG_PM=y CONFIG_PMBUS=y From d6f5c2685ff3fa97405c2d565f913deef86bebff Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Mon, 15 Jun 2026 20:27:24 +0200 Subject: [PATCH 051/228] realtek: rt-loader increase gcc optimization level Switch from -O2 to -O3. This increases the loader code size by 5KB and brings down the decompression time on RTL838x from ~6.5 seconds to ~3.5 seconds. Link: https://github.com/openwrt/openwrt/pull/23811 Signed-off-by: Markus Stockhausen --- target/linux/realtek/image/rt-loader/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/realtek/image/rt-loader/Makefile b/target/linux/realtek/image/rt-loader/Makefile index 198506bce8..90f8349c96 100644 --- a/target/linux/realtek/image/rt-loader/Makefile +++ b/target/linux/realtek/image/rt-loader/Makefile @@ -73,7 +73,7 @@ LD := $(CROSS_COMPILE)ld OBJCOPY := $(CROSS_COMPILE)objcopy OBJDUMP := $(CROSS_COMPILE)objdump -CFLAGS = -fpic -mabicalls -O2 -fno-builtin-printf -Iinclude +CFLAGS = -fpic -mabicalls -O3 -fno-builtin-printf -Iinclude CFLAGS += -DFLASH_ADDR=$(FLASH_ADDR) CFLAGS += -DKERNEL_ADDR=$(KERNEL_ADDR) From 3a35c19e8e81fbf35e23a2bffc891e3dc88c5f30 Mon Sep 17 00:00:00 2001 From: Konstantin Demin Date: Wed, 17 Jun 2026 03:27:03 +0300 Subject: [PATCH 052/228] toolchain: binutils: update to 2.46.1 Release Notes: https://sourceware.org/pipermail/binutils/2026-June/149568.html Signed-off-by: Konstantin Demin Link: https://github.com/openwrt/openwrt/pull/23773 Signed-off-by: Jonas Jelonek --- toolchain/binutils/Config.in | 2 +- toolchain/binutils/Config.version | 2 +- toolchain/binutils/Makefile | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/toolchain/binutils/Config.in b/toolchain/binutils/Config.in index a3687af7fc..7cad4d6c06 100644 --- a/toolchain/binutils/Config.in +++ b/toolchain/binutils/Config.in @@ -15,7 +15,7 @@ choice select BINUTILS_VERSION_2_45 config BINUTILS_USE_VERSION_2_46 - bool "Binutils 2.46" + bool "Binutils 2.46.1" select BINUTILS_VERSION_2_46 endchoice diff --git a/toolchain/binutils/Config.version b/toolchain/binutils/Config.version index 4102dd6dd3..c706c5a111 100644 --- a/toolchain/binutils/Config.version +++ b/toolchain/binutils/Config.version @@ -13,4 +13,4 @@ config BINUTILS_VERSION string default "2.44" if BINUTILS_VERSION_2_44 default "2.45.1" if BINUTILS_VERSION_2_45 - default "2.46.0" if BINUTILS_VERSION_2_46 + default "2.46.1" if BINUTILS_VERSION_2_46 diff --git a/toolchain/binutils/Makefile b/toolchain/binutils/Makefile index 74d7c3c4d6..68ec1c24de 100644 --- a/toolchain/binutils/Makefile +++ b/toolchain/binutils/Makefile @@ -24,8 +24,8 @@ ifeq ($(PKG_VERSION),2.45.1) PKG_HASH:=5fe101e6fe9d18fdec95962d81ed670fdee5f37e3f48f0bef87bddf862513aa5 endif -ifeq ($(PKG_VERSION),2.46.0) - PKG_HASH:=d75a94f4d73e7a4086f7513e67e439e8fcdcbb726ffe63f4661744e6256b2cf2 +ifeq ($(PKG_VERSION),2.46.1) + PKG_HASH:=e127a709cba24c76de8936cb7083dd768f28cd37eb010492e2f19b71eb1294e4 endif HOST_BUILD_PARALLEL:=1 From 279ad9292328155d31690459894b8570d8b7ce8a Mon Sep 17 00:00:00 2001 From: Konstantin Demin Date: Wed, 17 Jun 2026 03:27:03 +0300 Subject: [PATCH 053/228] toolchain: binutils: partially revert commit 525a1e94b343 "fix update to 2.45.1" Commit eac927fadf07 "toolchain: binutils: simplify patch management" being applied after commit 525a1e94b343 "toolchain: binutils: fix update to 2.45.1" effectively disables patching binutils 2.45.1 in OpenWrt. Fixes: 525a1e94b343 "toolchain: binutils: fix update to 2.45.1" Signed-off-by: Konstantin Demin Link: https://github.com/openwrt/openwrt/pull/23773 Signed-off-by: Jonas Jelonek --- .../patches/{2.45.1 => 2.45}/300-001_ld_makefile_patch.patch | 0 .../{2.45.1 => 2.45}/400-mips_no_dynamic_linking_sym.patch | 0 .../500-Change-default-emulation-for-mips64-linux.patch | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename toolchain/binutils/patches/{2.45.1 => 2.45}/300-001_ld_makefile_patch.patch (100%) rename toolchain/binutils/patches/{2.45.1 => 2.45}/400-mips_no_dynamic_linking_sym.patch (100%) rename toolchain/binutils/patches/{2.45.1 => 2.45}/500-Change-default-emulation-for-mips64-linux.patch (100%) diff --git a/toolchain/binutils/patches/2.45.1/300-001_ld_makefile_patch.patch b/toolchain/binutils/patches/2.45/300-001_ld_makefile_patch.patch similarity index 100% rename from toolchain/binutils/patches/2.45.1/300-001_ld_makefile_patch.patch rename to toolchain/binutils/patches/2.45/300-001_ld_makefile_patch.patch diff --git a/toolchain/binutils/patches/2.45.1/400-mips_no_dynamic_linking_sym.patch b/toolchain/binutils/patches/2.45/400-mips_no_dynamic_linking_sym.patch similarity index 100% rename from toolchain/binutils/patches/2.45.1/400-mips_no_dynamic_linking_sym.patch rename to toolchain/binutils/patches/2.45/400-mips_no_dynamic_linking_sym.patch diff --git a/toolchain/binutils/patches/2.45.1/500-Change-default-emulation-for-mips64-linux.patch b/toolchain/binutils/patches/2.45/500-Change-default-emulation-for-mips64-linux.patch similarity index 100% rename from toolchain/binutils/patches/2.45.1/500-Change-default-emulation-for-mips64-linux.patch rename to toolchain/binutils/patches/2.45/500-Change-default-emulation-for-mips64-linux.patch From cc5e8c5af5e3dd4fb12c76e2f3a16f5c0a772a88 Mon Sep 17 00:00:00 2001 From: Carlo Szelinsky Date: Tue, 16 Jun 2026 21:12:23 +0200 Subject: [PATCH 054/228] generic: 6.18: backport SFP I2C presence detection without MOD_DEF0 GPIO Backport upstream net-next commit 8ac44d24c3a1. An SFP cage whose MOD_DEF0 signal is not wired to a readable GPIO currently uses sff_gpio_get_state(), which always reports the module present: an empty cage gets stuck in MOD_ERROR, hot-insertion is never detected and empty cages spam -EIO at boot. Derive presence from a throttled single-byte I2C read of the module EEPROM instead, so hot-plug works and the boot spam stops. A soldered-down "sff,sff" module stays always-present. This helps RTL93xx SFP boards that route no cage presence signal to a GPIO. Remaining sfp.c patches refreshed. Link: https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=8ac44d24c3a1 Signed-off-by: Carlo Szelinsky Link: https://github.com/openwrt/openwrt/pull/23836 Signed-off-by: Jonas Jelonek --- ...esence-via-I2C-when-no-MOD_DEF0-GPIO.patch | 156 ++++++++++++++++++ ...k-for-QINIYEK-BJ-SFP-10G-T-copper-SF.patch | 2 +- ...net-sfp-add-quirk-for-TP-LINK-SM410U.patch | 2 +- ...ze-i2c_block_size-at-adapter-configu.patch | 2 +- ...C-adapter-quirks-to-limit-block-size.patch | 2 +- ...02-v7.2-net-sfp-extend-SMBus-support.patch | 4 +- ...14-net-phy-sfp-add-support-for-SMBus.patch | 4 +- 7 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch diff --git a/target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch b/target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch new file mode 100644 index 0000000000..aca784e753 --- /dev/null +++ b/target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch @@ -0,0 +1,156 @@ +From 8ac44d24c3a148c4177bd3ad790c377279f4674f Mon Sep 17 00:00:00 2001 +From: Greg Patrick +Date: Thu, 11 Jun 2026 17:53:41 +0000 +Subject: [PATCH] net: phy: sfp: detect presence via I2C when no MOD_DEF0 GPIO + +An SFP cage (compatible "sff,sfp") whose MOD_DEF0 signal is not wired to a +GPIO currently falls back to sff_gpio_get_state(), which unconditionally +reports the module as present. An empty cage therefore fails its probe and +is parked in SFP_MOD_ERROR forever; because SFP_F_PRESENT never deasserts +there is no REMOVE event to recover the state machine, so a module inserted +after boot is never detected, and empty cages spam -EIO at boot. + +This affects boards that route none of the cage presence signal to a +software-readable input. On the NicGiga S100-0800S-M (RTL9303, 8x SFP+) the +cage I2C bus is the switch's SMBus master; TX_DISABLE is driven via a +PCA9534 I/O expander, but no MOD_ABS/MOD_DEF0 line reaches a readable GPIO +(the RTL9303 gpio0 lines read stuck-low, the single PCA9534 is fully +consumed by TX_DISABLE, and there is no RTL8231). The Horaco ZX-SW82TS-L2P +(RTL9302D, 2x SFP+) is independently affected in the same way. + +For such an SFP cage, derive presence from a throttled single-byte I2C read +of the module EEPROM instead: a successful read asserts SFP_F_PRESENT, +R_PROBE_ABSENT consecutive failures clear it (to ride out a transient error +on a live module). The existing poll then emits SFP_E_INSERT / SFP_E_REMOVE +normally, giving working hot-plug and silencing the boot-time -EIO spam on +empty cages. Presence is re-probed every T_PROBE_PRESENT, so insertion is +detected within that interval and removal within +T_PROBE_PRESENT * R_PROBE_ABSENT. + +A soldered-down module (compatible "sff,sff") has no presence signal and is +genuinely always present, so it continues to use sff_gpio_get_state(); the +new path is gated on the cage type advertising SFP_F_PRESENT. + +Signed-off-by: Greg Patrick +Tested-by: Manuel Stocker +Reviewed-by: Maxime Chevallier +Tested-by: Maxime Chevallier +Link: https://patch.msgid.link/20260611175341.2223184-1-gregspatrick@hotmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/sfp.c | 83 +++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 80 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -206,6 +206,16 @@ static const enum gpiod_flags gpio_flags + #define T_PROBE_RETRY_SLOW msecs_to_jiffies(5000) + #define R_PROBE_RETRY_SLOW 12 + ++/* Polling interval and consecutive-failure threshold for the I2C presence ++ * probe used on boards without a MOD_DEF0 GPIO (see sfp_i2c_get_state()). ++ * A single successful read asserts presence immediately; R_PROBE_ABSENT ++ * consecutive failures are required to declare a live module removed, to ride ++ * out a transient I2C error. Insertion is thus detected within ++ * T_PROBE_PRESENT and removal within T_PROBE_PRESENT * R_PROBE_ABSENT. ++ */ ++#define T_PROBE_PRESENT msecs_to_jiffies(500) ++#define R_PROBE_ABSENT 3 ++ + /* SFP modules appear to always have their PHY configured for bus address + * 0x56 (which with mdio-i2c, translates to a PHY address of 22). + * RollBall SFPs access phy via SFP Enhanced Digital Diagnostic Interface +@@ -249,6 +259,13 @@ struct sfp { + + bool need_poll; + ++ /* I2C-probed presence, for boards without a MOD_DEF0 GPIO. ++ * Access rules: st_mutex held (updated from the poll/state machine). ++ */ ++ bool i2c_present; ++ u8 i2c_present_nak; ++ unsigned long i2c_present_next; ++ + /* Access rules: + * state_hw_drive: st_mutex held + * state_hw_mask: st_mutex held +@@ -860,6 +877,45 @@ static int sfp_read(struct sfp *sfp, boo + return sfp->read(sfp, a2, addr, buf, len); + } + ++/* Probe whether a module is physically present by attempting a single-byte ++ * I2C read of the EEPROM identifier (an empty cage NAKs). Used as the presence ++ * source on boards that do not wire MOD_DEF0 to a GPIO. ++ */ ++static bool sfp_module_present_i2c(struct sfp *sfp) ++{ ++ u8 id; ++ ++ return sfp_read(sfp, false, SFP_PHYS_ID, &id, sizeof(id)) == sizeof(id); ++} ++ ++/* get_state variant for boards without a MOD_DEF0 GPIO. Instead of assuming ++ * the module is always present, derive SFP_F_PRESENT from a throttled I2C ++ * probe so that hot-insertion and removal are detected. A single ACK asserts ++ * presence; R_PROBE_ABSENT consecutive failures clear it, to ride out a ++ * transient I2C error on a live module. ++ */ ++static unsigned int sfp_i2c_get_state(struct sfp *sfp) ++{ ++ unsigned int state = sfp_gpio_get_state(sfp); ++ ++ if (time_after_eq(jiffies, sfp->i2c_present_next)) { ++ if (sfp_module_present_i2c(sfp)) { ++ sfp->i2c_present = true; ++ sfp->i2c_present_nak = 0; ++ } else if (sfp->i2c_present && ++ ++sfp->i2c_present_nak >= R_PROBE_ABSENT) { ++ sfp->i2c_present = false; ++ sfp->i2c_present_nak = 0; ++ } ++ sfp->i2c_present_next = jiffies + T_PROBE_PRESENT; ++ } ++ ++ if (sfp->i2c_present) ++ state |= SFP_F_PRESENT; ++ ++ return state; ++} ++ + static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len) + { + return sfp->write(sfp, a2, addr, buf, len); +@@ -3158,9 +3214,30 @@ static int sfp_probe(struct platform_dev + sfp->get_state = sfp_gpio_get_state; + sfp->set_state = sfp_gpio_set_state; + +- /* Modules that have no detect signal are always present */ +- if (!(sfp->gpio[GPIO_MODDEF0])) +- sfp->get_state = sff_gpio_get_state; ++ /* An SFP cage with no MOD_DEF0 GPIO has no hardware presence signal. ++ * Assuming the module is always present traps an empty cage in ++ * MOD_ERROR and never detects hot-insertion, so derive presence from a ++ * throttled I2C probe and poll for changes instead. sfp_i2c_configure() ++ * has already set i2c_max_block_size; seed i2c_block_size so the ++ * presence read does not issue a zero-length transfer before the first ++ * EEPROM read. Seed i2c_present_next to jiffies so the first probe ++ * happens immediately (a zero value would be in the past relative to ++ * the negative INITIAL_JIFFIES at boot and delay detection). ++ * ++ * A soldered-down module (sff,sff) has no presence signal and is ++ * genuinely always present, so it keeps the always-present behaviour; ++ * the I2C probe is gated on the cage type advertising SFP_F_PRESENT. ++ */ ++ if (!sfp->gpio[GPIO_MODDEF0]) { ++ if (sff->gpios & SFP_F_PRESENT) { ++ sfp->get_state = sfp_i2c_get_state; ++ sfp->i2c_block_size = sfp->i2c_max_block_size; ++ sfp->i2c_present_next = jiffies; ++ sfp->need_poll = true; ++ } else { ++ sfp->get_state = sff_gpio_get_state; ++ } ++ } + + device_property_read_u32(&pdev->dev, "maximum-power-milliwatt", + &sfp->max_power_mW); diff --git a/target/linux/generic/pending-6.18/750-net-sfp-add-quirk-for-QINIYEK-BJ-SFP-10G-T-copper-SF.patch b/target/linux/generic/pending-6.18/750-net-sfp-add-quirk-for-QINIYEK-BJ-SFP-10G-T-copper-SF.patch index 21ad584fdb..b09463fcdd 100644 --- a/target/linux/generic/pending-6.18/750-net-sfp-add-quirk-for-QINIYEK-BJ-SFP-10G-T-copper-SF.patch +++ b/target/linux/generic/pending-6.18/750-net-sfp-add-quirk-for-QINIYEK-BJ-SFP-10G-T-copper-SF.patch @@ -16,7 +16,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -585,6 +585,7 @@ static const struct sfp_quirk sfp_quirks +@@ -602,6 +602,7 @@ static const struct sfp_quirk sfp_quirks SFP_QUIRK_S("OEM", "SFP-2.5G-BX10-U", sfp_quirk_2500basex), SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc), SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc), diff --git a/target/linux/generic/pending-6.18/751-net-sfp-add-quirk-for-TP-LINK-SM410U.patch b/target/linux/generic/pending-6.18/751-net-sfp-add-quirk-for-TP-LINK-SM410U.patch index b0b71cb917..c1f17ae69b 100644 --- a/target/linux/generic/pending-6.18/751-net-sfp-add-quirk-for-TP-LINK-SM410U.patch +++ b/target/linux/generic/pending-6.18/751-net-sfp-add-quirk-for-TP-LINK-SM410U.patch @@ -14,7 +14,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -591,6 +591,7 @@ static const struct sfp_quirk sfp_quirks +@@ -608,6 +608,7 @@ static const struct sfp_quirk sfp_quirks SFP_QUIRK_F("Turris", "RTSFP-10G", sfp_fixup_rollball), SFP_QUIRK_S("ZOERAX", "SFP-2.5G-T", sfp_quirk_oem_2_5g), diff --git a/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch b/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch index c252aa95a0..b1cac719cb 100644 --- a/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch +++ b/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch @@ -31,7 +31,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -824,6 +824,7 @@ static int sfp_i2c_configure(struct sfp +@@ -841,6 +841,7 @@ static int sfp_i2c_configure(struct sfp return -EINVAL; } diff --git a/target/linux/realtek/patches-6.18/706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch b/target/linux/realtek/patches-6.18/706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch index 7516450646..d2ce503e81 100644 --- a/target/linux/realtek/patches-6.18/706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch +++ b/target/linux/realtek/patches-6.18/706-01-v7.2-net-sfp-apply-I2C-adapter-quirks-to-limit-block-size.patch @@ -24,7 +24,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -809,21 +809,29 @@ static int sfp_smbus_byte_write(struct s +@@ -826,21 +826,29 @@ static int sfp_smbus_byte_write(struct s static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c) { diff --git a/target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch b/target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch index e092443707..c00c0d8580 100644 --- a/target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch +++ b/target/linux/realtek/patches-6.18/706-02-v7.2-net-sfp-extend-SMBus-support.patch @@ -75,7 +75,7 @@ Signed-off-by: Jakub Kicinski #include #include "sfp.h" -@@ -758,50 +759,113 @@ static int sfp_i2c_write(struct sfp *sfp +@@ -775,50 +776,113 @@ static int sfp_i2c_write(struct sfp *sfp return ret == ARRAY_SIZE(msgs) ? len : 0; } @@ -213,7 +213,7 @@ Signed-off-by: Jakub Kicinski } return data - (u8 *)buf; -@@ -817,10 +881,29 @@ static int sfp_i2c_configure(struct sfp +@@ -834,10 +898,29 @@ static int sfp_i2c_configure(struct sfp sfp->read = sfp_i2c_read; sfp->write = sfp_i2c_write; max_block_size = SFP_EEPROM_BLOCK_SIZE; diff --git a/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch b/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch index cc6283f0a7..ceeaae4c75 100644 --- a/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch +++ b/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch @@ -10,7 +10,7 @@ Signed-off-by: Antoine Tenart --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -942,6 +942,29 @@ static int sfp_i2c_mdiobus_create(struct +@@ -959,6 +959,29 @@ static int sfp_i2c_mdiobus_create(struct return 0; } @@ -40,7 +40,7 @@ Signed-off-by: Antoine Tenart static void sfp_i2c_mdiobus_destroy(struct sfp *sfp) { mdiobus_unregister(sfp->i2c_mii); -@@ -2116,9 +2139,15 @@ static void sfp_sm_fault(struct sfp *sfp +@@ -2172,9 +2195,15 @@ static void sfp_sm_fault(struct sfp *sfp static int sfp_sm_add_mdio_bus(struct sfp *sfp) { From 80eefabec3399ce2094da595a256358cea75e264 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 16 Feb 2026 20:47:33 -0800 Subject: [PATCH 055/228] bcm53xx: ac87u: set WAN MAC in dts Userspace handling is deprecated. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22059 Signed-off-by: Jonas Jelonek --- target/linux/bcm53xx/base-files/etc/board.d/02_network | 4 ---- ...RM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch | 5 ++++- ...RM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch | 5 ++++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/target/linux/bcm53xx/base-files/etc/board.d/02_network b/target/linux/bcm53xx/base-files/etc/board.d/02_network index f255edf8b5..7e9caf6522 100644 --- a/target/linux/bcm53xx/base-files/etc/board.d/02_network +++ b/target/linux/bcm53xx/base-files/etc/board.d/02_network @@ -53,10 +53,6 @@ bcm53xx_setup_macs() wan_macaddr="$(nvram get wan_hwaddr)" case "$board" in - asus,rt-ac87u) - etXmacaddr=$(nvram get et1macaddr) - offset=1 - ;; dlink,dir-885l | \ linksys,ea9200 | \ linksys,panamera | \ diff --git a/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch b/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch index 9cfc3aac15..db49e5b164 100644 --- a/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch +++ b/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch @@ -318,7 +318,7 @@ Signed-off-by: Rafał Miłecki +}; --- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts +++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts -@@ -77,6 +77,40 @@ +@@ -77,6 +77,43 @@ status = "okay"; }; @@ -328,6 +328,9 @@ Signed-off-by: Rafał Miłecki + ports { + port@0 { + label = "wan"; ++ ++ nvmem-cells = <&et1macaddr 1>; ++ nvmem-cell-names = "mac-address"; + }; + + port@1 { diff --git a/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch b/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch index 9cfc3aac15..db49e5b164 100644 --- a/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch +++ b/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch @@ -318,7 +318,7 @@ Signed-off-by: Rafał Miłecki +}; --- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts +++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts -@@ -77,6 +77,40 @@ +@@ -77,6 +77,43 @@ status = "okay"; }; @@ -328,6 +328,9 @@ Signed-off-by: Rafał Miłecki + ports { + port@0 { + label = "wan"; ++ ++ nvmem-cells = <&et1macaddr 1>; ++ nvmem-cell-names = "mac-address"; + }; + + port@1 { From 38aa2fa410d9e3f9dc6cb48bd6b94bece4b79742 Mon Sep 17 00:00:00 2001 From: Andrii Kuiukoff Date: Sat, 30 May 2026 01:55:11 +0300 Subject: [PATCH 056/228] mediatek: creatlentem clt-r30b1: correct alternate model to EP-RT2980 Update DEVICE_ALT0_MODEL for the EDUP entry from "RT2980" to "EP-RT2980" to correct the alternate device model string. Signed-off-by: Andrii Kuiukoff Link: https://github.com/openwrt/openwrt/pull/20666 Signed-off-by: Jonas Jelonek --- target/linux/mediatek/image/filogic.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index 1169b2f1cb..bda388ee3b 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -1068,7 +1068,7 @@ define Device/creatlentem_clt-r30b1-common DEVICE_VENDOR := CreatLentem DEVICE_MODEL := CLT-R30B1 DEVICE_ALT0_VENDOR := EDUP - DEVICE_ALT0_MODEL := RT2980 + DEVICE_ALT0_MODEL := EP-RT2980 DEVICE_ALT1_VENDOR := Dragonglass DEVICE_ALT1_MODEL := DGX21 DEVICE_ALT2_VENDOR := Livinet From e414ca4fa6cbc8d1e95d59966b614a4129b5371f Mon Sep 17 00:00:00 2001 From: Andrii Kuiukoff Date: Wed, 29 Oct 2025 22:05:19 +0200 Subject: [PATCH 057/228] mediatek: creatlentem clt-r30b1: add all-in-UBI layout This commit introduces OpenWrt U-Boot all-in-ubi layout support for the CreatLentem CLT-R30B1, enabling: - Fully-featured U-Boot - Effective recovery mechanisms - Prolonged device lifetime by allocating most of the flash to UBI (which takes care of wear-leveling) - Maximum available storage space for OpenWrt - Unified firmware across different device variants OpenWrt U-Boot UBI flash instructions ------------------------------------- Using the installer image ------------------------- To simplify the installation process, this method uses a fork of Daniel Golle's (@dangowrt) UBI Installer https://github.com/dangowrt/owrt-ubi-installer 1. Ensure your router is running the latest generic OpenWrt firmware. Upgrade it if necessary. 2. Obtain the installer image: Build the installer from source https://github.com/andros-ua/owrt-ubi-installer/tree/clt-r30b1 or download a prebuilt image from the https://github.com/andros-ua/owrt-ubi-installer/releases 3. Flash the openwrt*creatlentem_clt-r30b1-ubi-initramfs-recovery-installer.itb image using sysupgrade. 4. Wait for installation: the green status LED will blink rapidly, indicating that the all-in-UBI installer is running. 5. Once the installation finishes, the status LED will turn solid white (lime) for 5 seconds. 6. After the device reboots, perform a final sysupgrade using the openwrt*creatlentem_clt-r30b1-ubi-squashfs-sysupgrade.itb image. Return to stock layout ---------------------- 1. Flash openwrt*creatlentem_clt-r30b1(-112m)-initramfs-kernel.bin via sysupgrade 2. Copy files to /tmp on the device via SCP: BL2.bin u-boot-env.bin Factory.bin FIP.bin openwrt*creatlentem_clt-r30b1(-112m)-squashfs-sysupgrade.bin 3. Restore stock MTD partitions: apk add kmod-mtd-rw insmod mtd-rw i_want_a_brick=1 mtd write /tmp/BL2.bin BL2 mtd write /tmp/u-boot-env.bin u-boot-env mtd write /tmp/Factory.bin Factory mtd write /tmp/FIP.bin FIP 4. Install the system: sysupgrade /tmp/*sysupgrade.bin Recovery -------- Use mtk_uartboot to recover corrupted BL2 or FIP via UART: https://github.com/981213/mtk_uartboot Stock layout ---------------------------------------- | dev: size erasesize name | | mtd0: 00100000 00020000 "BL2" | | mtd1: 00080000 00020000 "u-boot-env" | | mtd2: 00200000 00020000 "Factory" | | mtd3: 00200000 00020000 "FIP" | | mtd4: 07000000 00020000 "ubi" | ---------------------------------------- OpenWrt U-Boot UBI layout ---------------------------------- | dev: size erasesize name | | mtd0: 00100000 00020000 "BL2" | | mtd1: 07f00000 00020000 "ubi" | ---------------------------------- Signed-off-by: Andrii Kuiukoff Link: https://github.com/openwrt/openwrt/pull/20666 Signed-off-by: Jonas Jelonek --- package/boot/uboot-mediatek/Makefile | 13 + .../473-add-creatlentem_clt-r30b1-ubi.patch | 315 ++++++++++++++++++ .../uboot-envtools/files/mediatek_filogic | 1 + .../mt7981b-creatlentem-clt-r30b1-112m.dts | 13 +- .../mt7981b-creatlentem-clt-r30b1-common.dtsi | 12 +- .../dts/mt7981b-creatlentem-clt-r30b1-ubi.dts | 89 +++++ .../dts/mt7981b-creatlentem-clt-r30b1.dts | 13 +- .../filogic/base-files/etc/board.d/02_network | 1 + .../base-files/lib/upgrade/platform.sh | 2 + target/linux/mediatek/image/filogic.mk | 24 +- 10 files changed, 467 insertions(+), 16 deletions(-) create mode 100644 package/boot/uboot-mediatek/patches/473-add-creatlentem_clt-r30b1-ubi.patch create mode 100644 target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-ubi.dts diff --git a/package/boot/uboot-mediatek/Makefile b/package/boot/uboot-mediatek/Makefile index f9a37bc775..eb0a29ecc9 100644 --- a/package/boot/uboot-mediatek/Makefile +++ b/package/boot/uboot-mediatek/Makefile @@ -317,6 +317,18 @@ define U-Boot/mt7981_comfast_cf-wr632ax DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ddr3-1866 endef +define U-Boot/mt7981_creatlentem_clt-r30b1-ubi + NAME:=CreatLentem CLT-R30B1 (UBI) + BUILD_SUBTARGET:=filogic + BUILD_DEVICES:=creatlentem_clt-r30b1-ubi + UBOOT_CONFIG:=mt7981_creatlentem_clt-r30b1-ubi + UBOOT_IMAGE:=u-boot.fip + BL2_BOOTDEV:=spim-nand-ubi + BL2_SOC:=mt7981 + BL2_DDRTYPE:=ddr3-1866 + DEPENDS:=+trusted-firmware-a-mt7981-spim-nand-ubi-ddr3-1866 +endef + define U-Boot/mt7981_cudy_tr3000-v1 NAME:=Cudy TR3000 v1 BUILD_SUBTARGET:=filogic @@ -1247,6 +1259,7 @@ UBOOT_TARGETS := \ mt7981_cmcc_rax3000m-nand-ddr3 \ mt7981_cmcc_rax3000m-nand-ddr4 \ mt7981_comfast_cf-wr632ax \ + mt7981_creatlentem_clt-r30b1-ubi \ mt7981_cudy_tr3000-v1 \ mt7981_cudy_wbr3000uax-v1 \ mt7981_cudy_wr3000e-v1 \ diff --git a/package/boot/uboot-mediatek/patches/473-add-creatlentem_clt-r30b1-ubi.patch b/package/boot/uboot-mediatek/patches/473-add-creatlentem_clt-r30b1-ubi.patch new file mode 100644 index 0000000000..ba5a203a1b --- /dev/null +++ b/package/boot/uboot-mediatek/patches/473-add-creatlentem_clt-r30b1-ubi.patch @@ -0,0 +1,315 @@ +--- /dev/null ++++ b/configs/mt7981_creatlentem_clt-r30b1-ubi_defconfig +@@ -0,0 +1,112 @@ ++CONFIG_ARM=y ++CONFIG_ARM_SMCCC=y ++CONFIG_SYS_HAS_NONCACHED_MEMORY=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_TEXT_BASE=0x41e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DEFAULT_DEVICE_TREE="mt7981-creatlentem-clt-r30b1-ubi" ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_TARGET_MT7981=y ++CONFIG_SYS_LOAD_ADDR=0x46000000 ++CONFIG_PRE_CON_BUF_ADDR=0x4007EF00 ++CONFIG_DEBUG_UART_BASE=0x11002000 ++CONFIG_DEBUG_UART_CLOCK=40000000 ++CONFIG_DEBUG_UART=y ++CONFIG_FIT=y ++CONFIG_BOOTDELAY=30 ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_USE_PREBOOT=y ++CONFIG_DEFAULT_FDT_FILE="mt7981-creatlentem-clt-r30b1-ubi" ++CONFIG_LOGLEVEL=7 ++CONFIG_PRE_CONSOLE_BUFFER=y ++CONFIG_LOG=y ++# CONFIG_BOARD_INIT is not set ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_PROMPT="MT7981> " ++CONFIG_CMD_CPU=y ++CONFIG_CMD_LICENSE=y ++CONFIG_CMD_BOOTMENU=y ++CONFIG_CMD_ASKENV=y ++CONFIG_CMD_ERASEENV=y ++CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y ++CONFIG_CMD_STRINGS=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_LINK_LOCAL=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_PXE=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_PSTORE=y ++CONFIG_CMD_PSTORE_MEM_ADDR=0x42ff0000 ++CONFIG_CMD_UUID=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_UBI=y ++CONFIG_ENV_REDUNDANT=y ++CONFIG_ENV_UBI_PART="ubi" ++CONFIG_ENV_UBI_VOLUME="ubootenv" ++CONFIG_ENV_UBI_VOLUME_REDUND="ubootenv2" ++CONFIG_ENV_RELOC_GD_ENV_ADDR=y ++CONFIG_ENV_USE_DEFAULT_ENV_TEXT_FILE=y ++CONFIG_ENV_DEFAULT_ENV_TEXT_FILE="defenvs/creatlentem_clt-r30b1-ubi_env" ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++CONFIG_VERSION_VARIABLE=y ++CONFIG_NETCONSOLE=y ++CONFIG_USE_IPADDR=y ++CONFIG_IPADDR="192.168.1.1" ++CONFIG_USE_SERVERIP=y ++CONFIG_SERVERIP="192.168.1.254" ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_CLK=y ++CONFIG_GPIO_HOG=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++# CONFIG_MMC is not set ++CONFIG_MTD=y ++CONFIG_DM_MTD=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTD_UBI_FASTMAP=y ++CONFIG_PHY_FIXED=y ++CONFIG_MEDIATEK_ETH=y ++CONFIG_PHY=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_MT7981=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MTK_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_RAM=y ++CONFIG_DM_RNG=y ++CONFIG_RNG_MTK_V2=y ++CONFIG_DM_SERIAL=y ++CONFIG_MTK_SERIAL=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MTK_SPIM=y ++CONFIG_ZSTD=y ++CONFIG_HEXDUMP=y +--- /dev/null ++++ b/defenvs/creatlentem_clt-r30b1-ubi_env +@@ -0,0 +1,54 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x46000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootcmd=if pstore check ; then run boot_recovery ; else run boot_ubi ; fi ++bootconf=config-1 ++bootdelay=0 ++bootfile=openwrt-mediatek-filogic-creatlentem_clt-r30b1-ubi-initramfs-recovery.itb ++bootfile_bl2=openwrt-mediatek-filogic-creatlentem_clt-r30b1-ubi-preloader.bin ++bootfile_fip=openwrt-mediatek-filogic-creatlentem_clt-r30b1-ubi-bl31-uboot.fip ++bootfile_upg=openwrt-mediatek-filogic-creatlentem_clt-r30b1-ubi-squashfs-sysupgrade.itb ++bootled_pwr=red:status ++bootled_rec=green:status ++bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 ++bootmenu_default=0 ++bootmenu_delay=0 ++bootmenu_title= ( ( ( OpenWrt ) ) ) ++bootmenu_0=Initialize environment.=run _firstboot ++bootmenu_0d=Run default boot command.=run boot_default ++bootmenu_1=Boot system via TFTP.=run boot_tftp ; run bootmenu_confirm_return ++bootmenu_2=Boot production system from NAND.=run boot_production ; run bootmenu_confirm_return ++bootmenu_3=Boot recovery system from NAND.=run boot_recovery ; run bootmenu_confirm_return ++bootmenu_4=Load production system via TFTP then write to NAND.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_5=Load recovery system via TFTP then write to NAND.=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_recovery ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_6=Load BL31+U-Boot FIP via TFTP then write to NAND.=run boot_tftp_write_fip ; run bootmenu_confirm_return ++bootmenu_7=Load BL2 preloader via TFTP then write to NAND.=run boot_tftp_write_bl2 ; run bootmenu_confirm_return ++bootmenu_8=Reboot.=reset ++bootmenu_9=Reset all settings to factory defaults.=run reset_factory ; reset ++boot_first=if button reset ; then led $bootled_pwr off ; run boot_tftp_recovery ; setenv flag_recover 1 ; run boot_default ; fi ; bootmenu ++boot_default=if env exists flag_recover ; then else run bootcmd ; fi ; run boot_recovery ; setenv replacevol 1 ; run boot_tftp_forever ++boot_production=led $bootled_rec off ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_pwr off ++boot_recovery=led $bootled_pwr off ; run ubi_read_recovery && bootm $loadaddr#$bootconf ; led $bootled_rec off ++boot_ubi=run boot_production ; run boot_recovery ; run boot_tftp_forever ++boot_tftp_forever=led $bootled_pwr off ; while true ; do run boot_tftp_recovery ; sleep 1 ; done ++boot_tftp_production=tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run ubi_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_recovery=tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run ubi_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp=tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run ubi_write_fip && run reset_factory ++boot_tftp_write_bl2=tftpboot $loadaddr $bootfile_bl2 && run mtd_write_bl2 ++preboot=led $bootled_pwr on ; led $bootled_rec on ++reset_factory=mw $loadaddr 0xff 0x1f000 ; ubi write $loadaddr ubootenv 0x1f000 ; ubi write $loadaddr ubootenv2 0x1f000 ; ubi remove rootfs_data ++mtd_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr ++ubi_create_env=ubi check ubootenv || ubi create ubootenv 0x1f000 dynamic ; ubi check ubootenv2 || ubi create ubootenv2 0x1f000 dynamic ++ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi ++ubi_read_production=ubi read $loadaddr fit && iminfo $loadaddr && run ubi_prepare_rootfs ++ubi_read_recovery=ubi check recovery && ubi read $loadaddr recovery ++ubi_remove_rootfs=ubi check rootfs_data && ubi remove rootfs_data ++ubi_write_fip=run ubi_remove_rootfs ; ubi check fip && ubi remove fip ; ubi create fip 0x200000 static ; ubi write $loadaddr fip 0x200000 ++ubi_write_production=ubi check fit && ubi remove fit ; run ubi_remove_rootfs ; ubi create fit $filesize dynamic && ubi write $loadaddr fit $filesize ++ubi_write_recovery=ubi check recovery && ubi remove recovery ; run ubi_remove_rootfs ; ubi create recovery $filesize dynamic && ubi write $loadaddr recovery $filesize ++_init_env=setenv _init_env ; run ubi_create_env ; saveenv ; saveenv ++_firstboot=setenv _firstboot ; run _switch_to_menu ; run _init_env ; run boot_first ++_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title ++_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title $ver" +--- /dev/null ++++ b/arch/arm/dts/mt7981-creatlentem-clt-r30b1-ubi.dts +@@ -0,0 +1,140 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++/dts-v1/; ++#include "mt7981.dtsi" ++#include ++#include ++ ++/ { ++ model = "CreatLentem CLT-R30B1 (UBI)"; ++ compatible = "creatlentem,clt-r30b1-ubi", "mediatek,mt7981"; ++ ++ chosen { ++ stdout-path = &uart0; ++ tick-timer = &timer0; ++ }; ++ ++ memory@40000000 { ++ device_type = "memory"; ++ reg = <0x40000000 0x10000000>; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ button-reset { ++ label = "reset"; ++ linux,code = ; ++ gpios = <&pio 1 GPIO_ACTIVE_LOW>; ++ }; ++ ++ button-wps { ++ label = "wps"; ++ linux,code = ; ++ gpios = <&pio 0 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ led_status_green: led-0 { ++ label = "green:status"; ++ gpios = <&pio 11 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led_status_red: led-1 { ++ label = "red:status"; ++ gpios = <&pio 12 GPIO_ACTIVE_LOW>; ++ default-state = "on"; ++ }; ++ }; ++}; ++ ++ð { ++ status = "okay"; ++ mediatek,gmac-id = <0>; ++ phy-mode = "2500base-x"; ++ mediatek,switch = "mt7531"; ++ reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; ++ ++ fixed-link { ++ speed = <2500>; ++ full-duplex; ++ }; ++}; ++ ++&pio { ++ spi_flash_pins: spi0-pins-func-1 { ++ mux { ++ function = "flash"; ++ groups = "spi0", "spi0_wp_hold"; ++ }; ++ ++ conf-pu { ++ pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; ++ drive-strength = ; ++ bias-pull-up = ; ++ }; ++ ++ conf-pd { ++ pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; ++ drive-strength = ; ++ bias-pull-down = ; ++ }; ++ }; ++ ++ line_8-hog { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "LEDs power"; ++ }; ++}; ++ ++&spi0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi_flash_pins>; ++ status = "okay"; ++ must_tx; ++ enhance_timing; ++ dma_ext; ++ ipm_design; ++ support_quad; ++ tick_dly = <2>; ++ sample_sel = <0>; ++ ++ spi_nand@0 { ++ compatible = "spi-nand"; ++ reg = <0>; ++ spi-max-frequency = <52000000>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x0 0x100000>; ++ }; ++ ++ partition@100000 { ++ label = "ubi"; ++ reg = <0x100000 0x7f00000>; ++ compatible = "linux,ubi"; ++ }; ++ }; ++ }; ++}; ++ ++&uart0 { ++ mediatek,force-highspeed; ++ status = "okay"; ++}; ++ ++&watchdog { ++ status = "disabled"; ++}; diff --git a/package/boot/uboot-tools/uboot-envtools/files/mediatek_filogic b/package/boot/uboot-tools/uboot-envtools/files/mediatek_filogic index 6caeca6dd9..21646b100a 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/mediatek_filogic +++ b/package/boot/uboot-tools/uboot-envtools/files/mediatek_filogic @@ -27,6 +27,7 @@ acer,predator-w6x-ubootmod|\ asus,zenwifi-bt8-ubootmod|\ cmcc,a10-ubootmod|\ comfast,cf-wr632ax-ubootmod|\ +creatlentem,clt-r30b1-ubi|\ cudy,tr3000-v1-ubootmod|\ cudy,wbr3000uax-v1-ubootmod|\ cudy,wr3000e-v1-ubootmod|\ diff --git a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-112m.dts b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-112m.dts index 36351565eb..c987c76fad 100644 --- a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-112m.dts +++ b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-112m.dts @@ -7,9 +7,12 @@ compatible = "creatlentem,clt-r30b1-112m", "mediatek,mt7981"; }; -&partitions { - partition@580000 { - label = "ubi"; - reg = <0x0580000 0x7000000>; - }; +&spi_nand { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; +}; + +&ubi { + reg = <0x0580000 0x7000000>; }; diff --git a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-common.dtsi b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-common.dtsi index 6958c174a0..ff55eb3f9f 100644 --- a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-common.dtsi +++ b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-common.dtsi @@ -17,7 +17,7 @@ serial0 = &uart0; }; - chosen { + chosen: chosen { stdout-path = "serial0:115200n8"; }; @@ -109,7 +109,7 @@ pinctrl-0 = <&spi0_flash_pins>; status = "okay"; - spi_nand@0 { + spi_nand: spi-nand@0 { compatible = "spi-nand"; reg = <0>; @@ -124,10 +124,6 @@ spi-cal-addrlen = <5>; spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>; - mediatek,nmbm; - mediatek,bmt-max-ratio = <1>; - mediatek,bmt-max-reserved-blocks = <64>; - partitions: partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -183,6 +179,10 @@ reg = <0x380000 0x200000>; read-only; }; + + ubi: partition@580000 { + label = "ubi"; + }; }; }; }; diff --git a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-ubi.dts b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-ubi.dts new file mode 100644 index 0000000000..b4cd51e101 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1-ubi.dts @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7981b-creatlentem-clt-r30b1-common.dtsi" + +/ { + model = "CreatLentem CLT-R30B1 (UBI)"; + compatible = "creatlentem,clt-r30b1-ubi", "mediatek,mt7981"; +}; + +&chosen { + bootargs = "root=/dev/fit0 rootwait"; + rootdisk = <&ubi_rootdisk>; +}; + +/delete-node/ &partitions; + +&spi_nand { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x0 0x100000>; + read-only; + }; + + partition@100000 { + label = "ubi"; + reg = <0x100000 0x7f00000>; + compatible = "linux,ubi"; + + volumes { + ubi_factory: ubi-volume-factory { + volname = "factory"; + }; + + ubi_rootdisk: ubi-volume-fit { + volname = "fit"; + }; + + ubi-volume-ubootenv { + volname = "ubootenv"; + nvmem-layout { + compatible = "u-boot,env-redundant-bool"; + }; + }; + + ubi-volume-ubootenv2 { + volname = "ubootenv2"; + nvmem-layout { + compatible = "u-boot,env-redundant-bool"; + }; + }; + }; + }; + }; +}; + +&ubi_factory { + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + reg = <0x4 0x6>; + compatible = "mac-base"; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_24: macaddr@24 { + compatible = "mac-base"; + reg = <0x24 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_2a: macaddr@2a { + compatible = "mac-base"; + reg = <0x2a 0x6>; + #nvmem-cell-cells = <1>; + }; + }; +}; diff --git a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1.dts b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1.dts index 941d0c3435..9b38fd8cc2 100644 --- a/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1.dts +++ b/target/linux/mediatek/dts/mt7981b-creatlentem-clt-r30b1.dts @@ -8,13 +8,18 @@ }; &partitions { - partition@580000 { - label = "ubi"; - reg = <0x0580000 0x4000000>; - }; partition@4580000 { label = "data"; reg = <0x4580000 0x2000000>; }; +}; +&spi_nand { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; +}; + +&ubi { + reg = <0x0580000 0x4000000>; }; diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network index 8fcbcce3d3..36d79b80d7 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -56,6 +56,7 @@ mediatek_setup_interfaces() confiabits,mt7981|\ creatlentem,clt-r30b1|\ creatlentem,clt-r30b1-112m|\ + creatlentem,clt-r30b1-ubi|\ cudy,wr3000-v1|\ globitel,bt-r320|\ huasifei,wh3000r-nand|\ diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index 80fbfb24c8..bc6d827174 100644 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -147,6 +147,7 @@ platform_do_upgrade() { cmcc,a10-ubootmod|\ cmcc,rax3000m|\ comfast,cf-wr632ax-ubootmod|\ + creatlentem,clt-r30b1-ubi|\ cudy,tr3000-v1-ubootmod|\ cudy,wbr3000uax-v1-ubootmod|\ cudy,wr3000e-v1-ubootmod|\ @@ -360,6 +361,7 @@ platform_check_image() { cmcc,a10-ubootmod|\ cmcc,rax3000m|\ comfast,cf-wr632ax-ubootmod|\ + creatlentem,clt-r30b1-ubi|\ cudy,tr3000-v1-ubootmod|\ cudy,wbr3000uax-v1-ubootmod|\ cudy,wr3000e-v1-ubootmod|\ diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index bda388ee3b..eb660ddc14 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -1079,7 +1079,6 @@ define Device/creatlentem_clt-r30b1-common BLOCKSIZE := 128k PAGESIZE := 2048 KERNEL_IN_UBI := 1 - IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata endef define Device/creatlentem_clt-r30b1-112m @@ -1090,6 +1089,7 @@ define Device/creatlentem_clt-r30b1-112m DEVICE_DTS := mt7981b-creatlentem-clt-r30b1-112m SUPPORTED_DEVICES += clt,r30b1 clt,r30b1-112m IMAGE_SIZE := 114688k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata $(call Device/creatlentem_clt-r30b1-common) endef TARGET_DEVICES += creatlentem_clt-r30b1-112m @@ -1098,10 +1098,32 @@ define Device/creatlentem_clt-r30b1 DEVICE_DTS := mt7981b-creatlentem-clt-r30b1 SUPPORTED_DEVICES += mediatek,mt7981-spim-snand-rfb IMAGE_SIZE := 65536k + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata $(call Device/creatlentem_clt-r30b1-common) endef TARGET_DEVICES += creatlentem_clt-r30b1 +define Device/creatlentem_clt-r30b1-ubi + DEVICE_VARIANT := (UBI) + DEVICE_ALT0_VARIANT := (UBI) + DEVICE_ALT1_VARIANT := (UBI) + DEVICE_ALT2_VARIANT := (UBI) + DEVICE_DTS := mt7981b-creatlentem-clt-r30b1-ubi + UBOOTENV_IN_UBI := 1 + IMAGES := sysupgrade.itb + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 64k + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | append-metadata + ARTIFACTS := preloader.bin bl31-uboot.fip + ARTIFACT/preloader.bin := mt7981-bl2 spim-nand-ubi-ddr3-1866 + ARTIFACT/bl31-uboot.fip := mt7981-bl31-uboot creatlentem_clt-r30b1-ubi + $(call Device/creatlentem_clt-r30b1-common) +endef +TARGET_DEVICES += creatlentem_clt-r30b1-ubi + define Device/cudy_ap3000outdoor-v1 DEVICE_VENDOR := Cudy DEVICE_MODEL := AP3000 Outdoor From 317317d960e3edb5891ee4d25c3d654074cb568d Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Sat, 2 May 2026 21:51:12 -0700 Subject: [PATCH 058/228] kernel/mediatek: fix null dereference in dynamic calibration patch KASAN reported a null dereference in this patch. Fix it. Signed-off-by: Peter Collingbourne Link: https://github.com/openwrt/openwrt/pull/23237 Signed-off-by: Jonas Jelonek --- ...pi-Add-support-for-dynamic-calibration.patch | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/target/linux/mediatek/patches-6.18/432-drivers-spi-Add-support-for-dynamic-calibration.patch b/target/linux/mediatek/patches-6.18/432-drivers-spi-Add-support-for-dynamic-calibration.patch index 1b93477ed7..c39bb8f4c5 100644 --- a/target/linux/mediatek/patches-6.18/432-drivers-spi-Add-support-for-dynamic-calibration.patch +++ b/target/linux/mediatek/patches-6.18/432-drivers-spi-Add-support-for-dynamic-calibration.patch @@ -5,21 +5,21 @@ Subject: [PATCH 2/6] drivers: spi: Add support for dynamic calibration Signed-off-by: SkyLake.Huang --- - drivers/spi/spi.c | 137 ++++++++++++++++++++++++++++++++++++++++ + drivers/spi/spi.c | 140 ++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 42 ++++++++++++ - 2 files changed, 179 insertions(+) + 2 files changed, 182 insertions(+) --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c -@@ -1478,6 +1478,70 @@ static int spi_transfer_wait(struct spi_ +@@ -1478,6 +1478,73 @@ static int spi_transfer_wait(struct spi_ return 0; } +int spi_do_calibration(struct spi_controller *ctlr, struct spi_device *spi, + int (*cal_read)(void *priv, u32 *addr, int addrlen, u8 *buf, int readlen), void *drv_priv) +{ -+ int datalen = ctlr->cal_rule->datalen; -+ int addrlen = ctlr->cal_rule->addrlen; ++ int datalen; ++ int addrlen; + u8 *buf; + int ret; + int i; @@ -34,6 +34,9 @@ Signed-off-by: SkyLake.Huang + if(!ctlr->cal_target || !ctlr->cal_rule || !ctlr->append_caldata) + return 0; + ++ datalen = ctlr->cal_rule->datalen; ++ addrlen = ctlr->cal_rule->addrlen; ++ + buf = kzalloc(datalen * sizeof(u8), GFP_KERNEL); + if(!buf) + return -ENOMEM; @@ -82,7 +85,7 @@ Signed-off-by: SkyLake.Huang static void _spi_transfer_delay_ns(u32 ns) { if (!ns) -@@ -2332,6 +2396,75 @@ void spi_flush_queue(struct spi_controll +@@ -2332,6 +2399,75 @@ void spi_flush_queue(struct spi_controll /*-------------------------------------------------------------------------*/ #if defined(CONFIG_OF) @@ -158,7 +161,7 @@ Signed-off-by: SkyLake.Huang static void of_spi_parse_dt_cs_delay(struct device_node *nc, struct spi_delay *delay, const char *prop) { -@@ -2487,6 +2620,10 @@ of_register_spi_device(struct spi_contro +@@ -2487,6 +2623,10 @@ of_register_spi_device(struct spi_contro if (rc) goto err_out; From fbbc36c13672db97c7ade371c16c1c8ba2b42bd5 Mon Sep 17 00:00:00 2001 From: Greg Patrick Date: Tue, 2 Jun 2026 12:32:39 +0000 Subject: [PATCH 059/228] realtek: add support for NicGiga S100-0800S-M The NicGiga S100-0800S-M is an 8-port 10G SFP+ managed switch built on the Realtek RTL9303 reference design (vendor U-Boot reports board model "RTL9303_8XGE", board id 1). It is closely related to the TP-Link TL-ST1008F v2 and shares its general layout, but differs in how the SFP cages and port LEDs are wired (see below). This DTS is derived from the TP-Link TL-ST1008F v2 support added by Jonas Jelonek and Balazs Triszka in commit 39b9b491bb ("realtek: add support for TP-Link TL-ST1008F v2.0"). Specifications: - SoC: Realtek RTL9303 - RAM: 512 MiB DDR3 - Flash: 32 MiB SPI-NOR - Ethernet: 8x 10G SFP+ (RTL9303 SerDes 2-9) - UART: 115200 8N1 on the front-panel RJ45 console port (Cisco-style pinout) MAC address: The MAC addresses are read from the ethaddr variable in the vendor U-Boot environment via the u-boot-env nvmem layout: the base address is assigned to the SoC ethernet controller and an incrementing per-port offset to each SFP port. SFP presence and port LEDs: Unlike the TP-Link TL-ST1008F v2, this board does not route the cage MOD_ABS lines to the SoC GPIO controller (gpio0 pins 0-7 read stuck-low, so an empty cage reads "present"), and the single PCA9534 I2C expander is fully used for TX_DISABLE. No mod-def0-gpio is therefore provided; module presence, including runtime hot-insertion and removal, is detected by polling the SFP EEPROM over I2C. Each cage has a single green LED, driven active-low. Installation: Interrupt the vendor U-Boot and TFTP-boot an OpenWrt initramfs image: setenv ipaddr 192.168.1.1 setenv serverip tftpboot 0x82000000 <...-initramfs-kernel.bin> bootm 0x82000000 From the running initramfs, flash with: sysupgrade -n <...-squashfs-sysupgrade.bin> Signed-off-by: Greg Patrick Link: https://github.com/openwrt/openwrt/pull/23579 Signed-off-by: Jonas Jelonek --- .../dts/rtl9303_nicgiga_s100-0800s-m.dts | 287 ++++++++++++++++++ target/linux/realtek/image/rtl930x.mk | 11 + 2 files changed, 298 insertions(+) create mode 100644 target/linux/realtek/dts/rtl9303_nicgiga_s100-0800s-m.dts diff --git a/target/linux/realtek/dts/rtl9303_nicgiga_s100-0800s-m.dts b/target/linux/realtek/dts/rtl9303_nicgiga_s100-0800s-m.dts new file mode 100644 index 0000000000..924802baa6 --- /dev/null +++ b/target/linux/realtek/dts/rtl9303_nicgiga_s100-0800s-m.dts @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rtl930x.dtsi" + +#include +#include + +/ { + compatible = "nicgiga,s100-0800s-m", "realtek,rtl930x-soc"; + model = "NicGiga S100-0800S-M"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>, /* first 256 MiB */ + <0x20000000 0x10000000>; /* remaining 256 MiB */ + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + led_set { + compatible = "realtek,rtl9300-leds"; + active-low; + + /* One green LED per SFP cage, lit on link + activity at any speed. */ + led_set0 = <(RTL93XX_LED_SET_10G | RTL93XX_LED_SET_5G | RTL93XX_LED_SET_2P5G | + RTL93XX_LED_SET_1G | RTL93XX_LED_SET_100M | RTL93XX_LED_SET_10M | + RTL93XX_LED_SET_LINK | RTL93XX_LED_SET_ACT)>; + }; + + i2c_gpio { + compatible = "i2c-gpio"; + #address-cells = <1>; + #size-cells = <0>; + i2c-gpio,delay-us = <2>; + scl-gpios = <&gpio0 22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio0 23 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + + gpioexp0: i2c@38 { + reg = <0x38>; + compatible = "nxp,pca9534"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + /* + * The related TP-Link TL-ST1008F v2 (same RTL9303 reference design) + * routes the SFP cage MOD_ABS lines to gpio0 pins 0-7, but on this + * board those pins read stuck-low under OpenWrt (an empty cage still + * reads "present"), and the PCA9534 expander is fully consumed by + * TX_DISABLE. No mod-def0-gpio is therefore wired up; module presence + * is instead detected by polling the SFP EEPROM over I2C, which also + * handles runtime hot-insertion and removal. + */ + sfp0: sfp-p1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c0>; + tx-disable-gpio = <&gpioexp0 0 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <2900>; + #thermal-sensor-cells = <0>; + }; + + sfp1: sfp-p2 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + tx-disable-gpio = <&gpioexp0 1 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <1500>; + #thermal-sensor-cells = <0>; + }; + + sfp2: sfp-p3 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2>; + tx-disable-gpio = <&gpioexp0 2 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <1500>; + #thermal-sensor-cells = <0>; + }; + + sfp3: sfp-p4 { + compatible = "sff,sfp"; + i2c-bus = <&i2c3>; + tx-disable-gpio = <&gpioexp0 3 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <2000>; + #thermal-sensor-cells = <0>; + }; + + sfp4: sfp-p5 { + compatible = "sff,sfp"; + i2c-bus = <&i2c4>; + tx-disable-gpio = <&gpioexp0 4 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <2000>; + #thermal-sensor-cells = <0>; + }; + + sfp5: sfp-p6 { + compatible = "sff,sfp"; + i2c-bus = <&i2c5>; + tx-disable-gpio = <&gpioexp0 5 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <1500>; + #thermal-sensor-cells = <0>; + }; + + sfp6: sfp-p7 { + compatible = "sff,sfp"; + i2c-bus = <&i2c6>; + tx-disable-gpio = <&gpioexp0 6 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <1500>; + #thermal-sensor-cells = <0>; + }; + + sfp7: sfp-p8 { + compatible = "sff,sfp"; + i2c-bus = <&i2c7>; + tx-disable-gpio = <&gpioexp0 7 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <2900>; + #thermal-sensor-cells = <0>; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>; + hw_algo = "toggle"; + hw_margin_ms = <1200>; + always-running; + }; +}; + +&i2c_mst1 { + status = "okay"; + + /* SDA0-7 correspond to GPIO9-16 */ + i2c0: i2c@0 { reg = <0>; }; + i2c1: i2c@1 { reg = <1>; }; + i2c2: i2c@2 { reg = <2>; }; + i2c3: i2c@3 { reg = <3>; }; + i2c4: i2c@4 { reg = <4>; }; + i2c5: i2c@5 { reg = <5>; }; + i2c6: i2c@6 { reg = <6>; }; + i2c7: i2c@7 { reg = <7>; }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <100000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0xe0000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0xe0000 0x10000>; + + nvmem-layout { + compatible = "u-boot,env"; + + macaddr_ubootenv_ethaddr: ethaddr { + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@f0000 { + label = "u-boot-env2"; + reg = <0xf0000 0x10000>; + read-only; + }; + + partition@100000 { + label = "jffs2-cfg"; + reg = <0x100000 0x100000>; + }; + + partition@200000 { + label = "jffs2-log"; + reg = <0x200000 0x100000>; + }; + + partition@300000 { + compatible = "openwrt,uimage", "denx,uimage"; + reg = <0x300000 0x1d00000>; + label = "firmware"; + openwrt,ih-magic = <0x93030000>; + }; + }; + }; +}; + +&switch0 { + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT_SFP(0, 1, 2, 0, 0) + SWITCH_PORT_SFP(8, 2, 3, 0, 1) + SWITCH_PORT_SFP(16, 3, 4, 0, 2) + SWITCH_PORT_SFP(20, 4, 5, 0, 3) + SWITCH_PORT_SFP(24, 5, 6, 0, 4) + SWITCH_PORT_SFP(25, 6, 7, 0, 5) + SWITCH_PORT_SFP(26, 7, 8, 0, 6) + SWITCH_PORT_SFP(27, 8, 9, 0, 7) + + port@1c { + ethernet = <ðernet0>; + reg = <28>; + phy-mode = "internal"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; + +ðernet0 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 0>; + nvmem-cell-names = "mac-address"; +}; + +&port0 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 1>; + nvmem-cell-names = "mac-address"; +}; + +&port8 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 2>; + nvmem-cell-names = "mac-address"; +}; + +&port16 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 3>; + nvmem-cell-names = "mac-address"; +}; + +&port20 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 4>; + nvmem-cell-names = "mac-address"; +}; + +&port24 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 5>; + nvmem-cell-names = "mac-address"; +}; + +&port25 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 6>; + nvmem-cell-names = "mac-address"; +}; + +&port26 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 7>; + nvmem-cell-names = "mac-address"; +}; + +&port27 { + nvmem-cells = <&macaddr_ubootenv_ethaddr 8>; + nvmem-cell-names = "mac-address"; +}; + +&thermal_zones { + sfp-thermal { + polling-delay-passive = <10000>; + polling-delay = <10000>; + thermal-sensors = <&sfp0>, <&sfp1>, <&sfp2>, <&sfp3>, <&sfp4>, <&sfp5>, <&sfp6>, <&sfp7>; + trips { + sfp-crit { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + }; +}; diff --git a/target/linux/realtek/image/rtl930x.mk b/target/linux/realtek/image/rtl930x.mk index 9b01f629ac..f4b7a67eff 100644 --- a/target/linux/realtek/image/rtl930x.mk +++ b/target/linux/realtek/image/rtl930x.mk @@ -97,6 +97,17 @@ define Device/horaco_zx-swtgw2c8f endef TARGET_DEVICES += horaco_zx-swtgw2c8f +define Device/nicgiga_s100-0800s-m + SOC := rtl9303 + UIMAGE_MAGIC := 0x93030000 + DEVICE_VENDOR := NicGiga + DEVICE_MODEL := S100-0800S-M + DEVICE_PACKAGES := kmod-gpio-pca953x + IMAGE_SIZE := 29696k + $(Device/kernel-lzma) +endef +TARGET_DEVICES += nicgiga_s100-0800s-m + define Device/plasmacloud-common SOC := rtl9302 UIMAGE_MAGIC := 0x93000000 From 2c122bdd74d4b8f0f1ea8f3dc8f95cf7d17af947 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 16 Jun 2026 11:47:18 +0200 Subject: [PATCH 060/228] airoha: introduce HW-GRO support - Introduce HW-GRO support in order to allow bridging HW-GRO interfaces - Enable LRO for queues (7-0) - Rework LAN/WAN dynamic switching according to upstream requests: now in order to set GDM3/GDM4 as WAN it is necessary to enable Qdisc offloading without any dedicated ethool command. Signed-off-by: Lorenzo Bianconi Link: https://github.com/openwrt/openwrt/pull/23828 Signed-off-by: Christian Marangi --- ...nt-instead-of-atomic_t-for-qdma-user.patch | 49 ++ ...-airoha-Implement-HW-GRO-TCP-support.patch | 622 ++++++++++++++++ ...net-airoha-Implement-LRO-TCP-support.patch | 392 ---------- ...roha-Introduce-airoha_gdm_dev-struct.patch | 280 +++++--- ...airoha_qdma-pointer-in-airoha_gdm_de.patch | 126 ++-- ...on-airoha_gdm_dev-pointer-in-airoha_.patch | 8 +- ...qos_sq_bmap-in-airoha_gdm_dev-struct.patch | 31 +- ...cpu-fwd-_tx_packets-in-airoha_gdm_de.patch | 6 +- ...rt-multiple-net_devices-for-a-single.patch | 253 +++---- ...Do-not-stop-GDM-port-if-it-is-shared.patch | 37 +- ...net-airoha-Introduce-WAN-device-flag.patch | 17 +- ...rt-multiple-LAN-WAN-interfaces-for-h.patch | 18 +- ...e-airoha_set_gdm2_loopback-in-airoha.patch | 4 +- ...oha-Add-ethtool-priv_flags-callbacks.patch | 246 ------- ...-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch | 668 ++++++++++++++++++ ...-net-airoha-Rework-MTU-configuration.patch | 84 ++- ...r-handle-MIB-for-GDM-with-multiple-p.patch | 24 +- ...-airoha-fix-wrong-airoha_get_fe_port.patch | 4 +- ...get_sport-callback-at-the-beginning-.patch | 36 + ...ify-WAN-device-check-in-airoha_dev_i.patch | 42 ++ 20 files changed, 1901 insertions(+), 1046 deletions(-) create mode 100644 target/linux/airoha/patches-6.18/916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch create mode 100644 target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch delete mode 100644 target/linux/airoha/patches-6.18/916-net-airoha-Implement-LRO-TCP-support.patch delete mode 100644 target/linux/airoha/patches-6.18/920-12-net-airoha-Add-ethtool-priv_flags-callbacks.patch create mode 100644 target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch create mode 100644 target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch create mode 100644 target/linux/airoha/patches-6.18/922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch diff --git a/target/linux/airoha/patches-6.18/916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch b/target/linux/airoha/patches-6.18/916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch new file mode 100644 index 0000000000..5d4ecf6606 --- /dev/null +++ b/target/linux/airoha/patches-6.18/916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch @@ -0,0 +1,49 @@ +From a459b560e58be327689e9bd8c0a6be9a4f163366 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Lorenzo Bianconi +Date: Thu, 11 Jun 2026 23:55:51 +0200 +Subject: [PATCH] net: airoha: use int instead of atomic_t for qdma users + counter + +QDMA users counter is always accessed holding RTNL lock so we do not +require atomic_t for it. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 4 ++-- + drivers/net/ethernet/airoha/airoha_eth.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1761,7 +1761,7 @@ static int airoha_dev_open(struct net_de + airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, + GLOBAL_CFG_TX_DMA_EN_MASK | + GLOBAL_CFG_RX_DMA_EN_MASK); +- atomic_inc(&qdma->users); ++ qdma->users++; + + if (port->id == AIROHA_GDM2_IDX && + airoha_ppe_is_enabled(qdma->eth, 1)) { +@@ -1788,7 +1788,7 @@ static int airoha_dev_stop(struct net_de + airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); + +- if (atomic_dec_and_test(&qdma->users)) { ++ if (!--qdma->users) { + airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, + GLOBAL_CFG_TX_DMA_EN_MASK | + GLOBAL_CFG_RX_DMA_EN_MASK); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -525,7 +525,7 @@ struct airoha_qdma { + struct airoha_eth *eth; + void __iomem *regs; + +- atomic_t users; ++ int users; + + struct airoha_irq_bank irq_banks[AIROHA_MAX_NUM_IRQ_BANKS]; + diff --git a/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch b/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch new file mode 100644 index 0000000000..7598a22199 --- /dev/null +++ b/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch @@ -0,0 +1,622 @@ +From 598e1ddfe85ad0f4778eeadd5d878209dd931280 Mon Sep 17 00:00:00 2001 +Message-ID: <598e1ddfe85ad0f4778eeadd5d878209dd931280.1779112628.git.lorenzo@kernel.org> +From: Lorenzo Bianconi +Date: Thu, 14 May 2026 20:25:19 +0200 +Subject: [PATCH] net: airoha: Implement LRO TCP support + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 178 ++++++++++++++++++++-- + drivers/net/ethernet/airoha/airoha_eth.h | 23 +++ + drivers/net/ethernet/airoha/airoha_regs.h | 22 ++- + 3 files changed, 208 insertions(+), 15 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -11,8 +11,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + #include + + #include "airoha_regs.h" +@@ -439,6 +441,73 @@ static void airoha_fe_crsn_qsel_init(str + CDM_CRSN_QSEL_Q1)); + } + ++static void airoha_fe_lro_rxq_enable(struct airoha_eth *eth, int qdma_id, ++ int lro_queue_index, int qid, ++ int buf_size) ++{ ++ int id = qdma_id + 1; ++ ++ airoha_fe_rmw(eth, REG_CDM_LRO_LIMIT(id), ++ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK, ++ FIELD_PREP(CDM_LRO_AGG_SIZE_MASK, buf_size) | ++ FIELD_PREP(CDM_LRO_AGG_NUM_MASK, ++ AIROHA_RXQ_LRO_MAX_AGG_COUNT)); ++ airoha_fe_rmw(eth, REG_CDM_LRO_AGE_TIME(id), ++ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK, ++ FIELD_PREP(CDM_LRO_AGE_TIME_MASK, ++ AIROHA_RXQ_LRO_MAX_AGE_TIME) | ++ FIELD_PREP(CDM_LRO_AGG_TIME_MASK, ++ AIROHA_RXQ_LRO_MAX_AGG_TIME)); ++ airoha_fe_rmw(eth, REG_CDM_LRO_RXQ(id, lro_queue_index), ++ LRO_RXQ_MASK(lro_queue_index), ++ __field_prep(LRO_RXQ_MASK(lro_queue_index), qid)); ++ airoha_fe_set(eth, REG_CDM_LRO_EN(id), BIT(lro_queue_index)); ++} ++ ++static void airoha_fe_lro_disable(struct airoha_eth *eth, int qdma_id) ++{ ++ int i, id = qdma_id + 1; ++ ++ airoha_fe_clear(eth, REG_CDM_LRO_EN(id), LRO_RXQ_EN_MASK); ++ airoha_fe_clear(eth, REG_CDM_LRO_LIMIT(id), ++ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK); ++ airoha_fe_clear(eth, REG_CDM_LRO_AGE_TIME(id), ++ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK); ++ for (i = 0; i < AIROHA_MAX_NUM_LRO_QUEUES; i++) ++ airoha_fe_clear(eth, REG_CDM_LRO_RXQ(id, i), LRO_RXQ_MASK(i)); ++} ++ ++static bool airoha_fe_lro_is_enabled(struct airoha_eth *eth, int qdma_id) ++{ ++ return airoha_fe_get(eth, REG_CDM_LRO_EN(qdma_id + 1), ++ LRO_RXQ_EN_MASK); ++} ++ ++static void airoha_dev_lro_enable(struct airoha_gdm_port *port) ++{ ++ struct airoha_qdma *qdma = port->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int qdma_id = qdma - ð->qdma[0]; ++ int i, lro_queue_index = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { ++ struct airoha_queue *q = &qdma->q_rx[i]; ++ u32 size; ++ ++ if (!q->ndesc) ++ continue; ++ ++ if (!airoha_qdma_is_lro_queue(q)) ++ continue; ++ ++ size = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size)); ++ size = min_t(u32, size, CDM_LRO_AGG_SIZE_MASK); ++ airoha_fe_lro_rxq_enable(eth, qdma_id, lro_queue_index, i, ++ size); ++ lro_queue_index++; ++ } ++} ++ + static int airoha_fe_init(struct airoha_eth *eth) + { + airoha_fe_maccr_init(eth); +@@ -558,6 +627,7 @@ static int airoha_qdma_fill_rx_queue(str + e->dma_addr = page_pool_get_dma_addr(page) + offset; + e->dma_len = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size)); + ++ WRITE_ONCE(desc->tcp_ts_reply, 0); + val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len); + WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); + WRITE_ONCE(desc->addr, cpu_to_le32(e->dma_addr)); +@@ -603,12 +673,169 @@ static int airoha_qdma_get_gdm_port(stru + return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; + } + ++static struct sk_buff *airoha_qdma_lro_rx_skb(struct airoha_queue *q, ++ struct airoha_qdma_desc *desc, ++ struct airoha_queue_entry *e) ++{ ++ u32 len, th_off, tcp_ack_seq, agg_count, data_off, data_len; ++ u32 desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); ++ u32 msg1 = le32_to_cpu(READ_ONCE(desc->msg1)); ++ u32 msg2 = le32_to_cpu(READ_ONCE(desc->msg2)); ++ u32 msg3 = le32_to_cpu(READ_ONCE(desc->msg3)); ++ struct skb_shared_info *shinfo; ++ u16 tcp_win, l2_len; ++ struct sk_buff *skb; ++ struct tcphdr *th; ++ struct page *page; ++ bool ipv4, ipv6; ++ ++ ipv4 = FIELD_GET(QDMA_ETH_RXMSG_IP4_MASK, msg1); ++ ipv6 = FIELD_GET(QDMA_ETH_RXMSG_IP6_MASK, msg1); ++ if (!ipv4 && !ipv6) ++ return NULL; ++ ++ l2_len = FIELD_GET(QDMA_ETH_RXMSG_L2_LEN_MASK, msg2); ++ len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl); ++ ++ if (ipv4) { ++ struct iphdr *iph; ++ ++ if (len < l2_len + sizeof(*iph)) ++ return NULL; ++ ++ iph = (struct iphdr *)(e->buf + l2_len); ++ if (iph->protocol != IPPROTO_TCP) ++ return NULL; ++ ++ if (iph->ihl < 5) ++ return NULL; ++ ++ th_off = l2_len + (iph->ihl << 2); ++ if (len < th_off) ++ return NULL; ++ ++ iph->tot_len = cpu_to_be16(len - l2_len); ++ iph->check = 0; ++ iph->check = ip_fast_csum((void *)iph, iph->ihl); ++ } else { ++ struct ipv6hdr *ip6h; ++ ++ th_off = l2_len + sizeof(*ip6h); ++ if (len < th_off) ++ return NULL; ++ ++ ip6h = (struct ipv6hdr *)(e->buf + l2_len); ++ if (ip6h->nexthdr != NEXTHDR_TCP) ++ return NULL; ++ ++ ip6h->payload_len = cpu_to_be16(len - th_off); ++ } ++ ++ if (len < th_off + sizeof(*th)) ++ return NULL; ++ ++ th = (struct tcphdr *)(e->buf + th_off); ++ if (th->doff < 5) ++ return NULL; ++ ++ data_off = th_off + (th->doff << 2); ++ if (len < data_off) ++ return NULL; ++ ++ tcp_win = FIELD_GET(QDMA_ETH_RXMSG_TCP_WIN_MASK, msg3); ++ tcp_ack_seq = le32_to_cpu(READ_ONCE(desc->data)); ++ th->ack_seq = cpu_to_be32(tcp_ack_seq); ++ th->window = cpu_to_be16(tcp_win); ++ ++ /* Check tcp timestamp option */ ++ if (th->doff == (sizeof(*th) + TCPOLEN_TSTAMP_ALIGNED) / 4) { ++ u32 topt = get_unaligned_be32(th + 1); ++ ++ if (topt == ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | ++ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { ++ u8 *ptr = (u8 *)th + sizeof(*th) + 2 * sizeof(__be32); ++ __le32 tcp_ts_reply = READ_ONCE(desc->tcp_ts_reply); ++ ++ put_unaligned_be32(le32_to_cpu(tcp_ts_reply), ptr); ++ } ++ } ++ ++ if (ipv4) { ++ struct iphdr *iph = (struct iphdr *)(e->buf + l2_len); ++ ++ th->check = ~tcp_v4_check(len - th_off, iph->saddr, ++ iph->daddr, 0); ++ } else { ++ struct ipv6hdr *ip6h = (struct ipv6hdr *)(e->buf + l2_len); ++ ++ th->check = ~tcp_v6_check(len - th_off, &ip6h->saddr, ++ &ip6h->daddr, 0); ++ } ++ ++ skb = napi_alloc_skb(&q->napi, data_off); ++ if (!skb) ++ return NULL; ++ ++ __skb_put(skb, data_off); ++ memcpy(skb->data, e->buf, data_off); ++ ++ page = virt_to_head_page(e->buf); ++ data_len = len - data_off; ++ shinfo = skb_shinfo(skb); ++ skb_add_rx_frag(skb, shinfo->nr_frags, page, ++ e->buf + data_off - page_address(page), data_len, ++ q->buf_size); ++ ++ shinfo->gso_type = ipv4 ? SKB_GSO_TCPV4 : SKB_GSO_TCPV6; ++ agg_count = FIELD_GET(QDMA_ETH_RXMSG_AGG_COUNT_MASK, msg2); ++ shinfo->gso_size = DIV_ROUND_UP(data_len, agg_count); ++ shinfo->gso_segs = agg_count; ++ ++ skb->csum_start = skb_headroom(skb) + th_off; ++ skb->csum_offset = offsetof(struct tcphdr, check); ++ skb->ip_summed = CHECKSUM_PARTIAL; ++ ++ return skb; ++} ++ ++static struct sk_buff *airoha_qdma_build_rx_skb(struct airoha_queue *q, ++ struct airoha_qdma_desc *desc, ++ struct airoha_queue_entry *e, ++ struct net_device *netdev) ++{ ++ u32 msg2 = le32_to_cpu(READ_ONCE(desc->msg2)); ++ int qid = q - &q->qdma->q_rx[0]; ++ struct sk_buff *skb; ++ ++ if (FIELD_GET(QDMA_ETH_RXMSG_AGG_COUNT_MASK, msg2) > 1) { /* LRO */ ++ skb = airoha_qdma_lro_rx_skb(q, desc, e); ++ if (!skb) ++ return NULL; ++ } else { ++ u32 desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); ++ u32 len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl); ++ ++ skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, q->buf_size); ++ if (!skb) ++ return NULL; ++ ++ skb_reserve(skb, AIROHA_RX_HEADROOM); ++ __skb_put(skb, len); ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ } ++ ++ skb_mark_for_recycle(skb); ++ skb->dev = netdev; ++ skb_record_rx_queue(skb, qid); ++ skb->protocol = eth_type_trans(skb, netdev); ++ ++ return skb; ++} ++ + static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) + { + enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); +- struct airoha_qdma *qdma = q->qdma; +- struct airoha_eth *eth = qdma->eth; +- int qid = q - &qdma->q_rx[0]; ++ struct airoha_eth *eth = q->qdma->eth; + int done = 0; + + while (done < budget) { +@@ -643,18 +870,9 @@ static int airoha_qdma_rx_process(struct + + port = eth->ports[p]; + if (!q->skb) { /* first buffer */ +- q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, +- q->buf_size); ++ q->skb = airoha_qdma_build_rx_skb(q, desc, e, port->dev); + if (!q->skb) + goto free_frag; +- +- skb_reserve(q->skb, AIROHA_RX_HEADROOM); +- __skb_put(q->skb, len); +- skb_mark_for_recycle(q->skb); +- q->skb->dev = port->dev; +- q->skb->protocol = eth_type_trans(q->skb, port->dev); +- q->skb->ip_summed = CHECKSUM_UNNECESSARY; +- skb_record_rx_queue(q->skb, qid); + } else { /* scattered frame */ + struct skb_shared_info *shinfo = skb_shinfo(q->skb); + int nr_frags = shinfo->nr_frags; +@@ -743,12 +961,10 @@ static int airoha_qdma_rx_napi_poll(stru + static int airoha_qdma_init_rx_queue(struct airoha_queue *q, + struct airoha_qdma *qdma, int ndesc) + { +- const struct page_pool_params pp_params = { +- .order = 0, ++ struct page_pool_params pp_params = { + .pool_size = 256, + .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, + .dma_dir = DMA_FROM_DEVICE, +- .max_len = PAGE_SIZE, + .nid = NUMA_NO_NODE, + .dev = qdma->eth->dev, + .napi = &q->napi, +@@ -756,9 +972,10 @@ static int airoha_qdma_init_rx_queue(str + struct airoha_eth *eth = qdma->eth; + int qid = q - &qdma->q_rx[0], thr; + dma_addr_t dma_addr; ++ bool lro_q; + +- q->buf_size = PAGE_SIZE / 2; + q->qdma = qdma; ++ lro_q = airoha_qdma_is_lro_queue(q); + + q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry), + GFP_KERNEL); +@@ -770,6 +987,9 @@ static int airoha_qdma_init_rx_queue(str + if (!q->desc) + return -ENOMEM; + ++ pp_params.order = lro_q ? AIROHA_LRO_PAGE_ORDER : 0; ++ pp_params.max_len = PAGE_SIZE << pp_params.order; ++ + q->page_pool = page_pool_create(&pp_params); + if (IS_ERR(q->page_pool)) { + int err = PTR_ERR(q->page_pool); +@@ -778,6 +998,7 @@ static int airoha_qdma_init_rx_queue(str + return err; + } + ++ q->buf_size = lro_q ? pp_params.max_len : pp_params.max_len / 2; + q->ndesc = ndesc; + netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); + +@@ -791,7 +1012,12 @@ static int airoha_qdma_init_rx_queue(str + FIELD_PREP(RX_RING_THR_MASK, thr)); + airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK, + FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head)); +- airoha_qdma_set(qdma, REG_RX_SCATTER_CFG(qid), RX_RING_SG_EN_MASK); ++ if (lro_q) ++ airoha_qdma_clear(qdma, REG_RX_SCATTER_CFG(qid), ++ RX_RING_SG_EN_MASK); ++ else ++ airoha_qdma_set(qdma, REG_RX_SCATTER_CFG(qid), ++ RX_RING_SG_EN_MASK); + + airoha_qdma_fill_rx_queue(q); + +@@ -813,6 +1039,7 @@ static void airoha_qdma_cleanup_rx_queue + page_pool_get_dma_dir(q->page_pool)); + page_pool_put_full_page(q->page_pool, page, false); + /* Reset DMA descriptor */ ++ WRITE_ONCE(desc->tcp_ts_reply, 0); + WRITE_ONCE(desc->ctrl, 0); + WRITE_ONCE(desc->addr, 0); + WRITE_ONCE(desc->data, 0); +@@ -1720,13 +1947,45 @@ static void airoha_update_hw_stats(struc + spin_unlock(&port->stats.lock); + } + ++static void airoha_update_netdev_features(struct airoha_gdm_port *port) ++{ ++ struct airoha_eth *eth = port->eth; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { ++ struct airoha_gdm_port *p = eth->ports[i]; ++ struct net_device *netdev; ++ ++ if (!p) ++ continue; ++ ++ netdev = p->dev; ++ if (netdev->reg_state != NETREG_REGISTERED) ++ continue; ++ ++ netdev_update_features(netdev); ++ } ++} ++ + static int airoha_dev_open(struct net_device *dev) + { + int err, len = ETH_HLEN + dev->mtu + ETH_FCS_LEN; + struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_qdma *qdma = port->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int qdma_id = qdma - ð->qdma[0]; + u32 pse_port = FE_PSE_PORT_PPE1; + ++ /* HW LRO is configured on the QDMA and it is shared between ++ * all the devices using it. Refuse to open a second device on ++ * the same QDMA if LRO is enabled on any device sharing it. ++ */ ++ if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { ++ netdev_warn(dev, "required to disable HW GRO on QDMA%d\n", ++ qdma_id); ++ return -EBUSY; ++ } ++ + #if defined(CONFIG_PCS_AIROHA) + if (airhoa_is_phy_external(port)) { + err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); +@@ -1747,13 +2006,13 @@ static int airoha_dev_open(struct net_de + + /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ + if (netdev_uses_dsa(dev) || port->id > 2) +- airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), ++ airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id), + GDM_STAG_EN_MASK); + else +- airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), ++ airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), + GDM_STAG_EN_MASK); + +- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), ++ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), + GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, + FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | + FIELD_PREP(GDM_LONG_LEN_MASK, len)); +@@ -1763,14 +2022,18 @@ static int airoha_dev_open(struct net_de + GLOBAL_CFG_RX_DMA_EN_MASK); + qdma->users++; + +- if (port->id == AIROHA_GDM2_IDX && +- airoha_ppe_is_enabled(qdma->eth, 1)) { ++ if (port->id == AIROHA_GDM2_IDX && airoha_ppe_is_enabled(eth, 1)) { + /* For PPE2 always use secondary cpu port. */ + pse_port = FE_PSE_PORT_PPE2; + } +- airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), + pse_port); + ++ if (dev->features & NETIF_F_GRO_HW) ++ airoha_dev_lro_enable(port); ++ ++ airoha_update_netdev_features(port); ++ + return 0; + } + +@@ -1778,6 +2041,7 @@ static int airoha_dev_stop(struct net_de + { + struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_qdma *qdma = port->qdma; ++ struct airoha_eth *eth = qdma->eth; + int i; + + netif_tx_disable(dev); +@@ -1785,7 +2049,7 @@ static int airoha_dev_stop(struct net_de + for (i = 0; i < dev->num_tx_queues; i++) + netdev_tx_reset_subqueue(dev, i); + +- airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); + + if (!--qdma->users) { +@@ -1801,6 +2065,8 @@ static int airoha_dev_stop(struct net_de + } + } + ++ airoha_update_netdev_features(port); ++ + #if defined(CONFIG_PCS_AIROHA) + if (airhoa_is_phy_external(port)) { + phylink_stop(port->phylink); +@@ -2034,6 +2300,38 @@ int airoha_get_fe_port(struct airoha_gdm + } + } + ++static netdev_features_t airoha_dev_fix_features(struct net_device *dev, ++ netdev_features_t features) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_qdma *qdma = port->qdma; ++ ++ if (qdma->users > 1) ++ features &= ~NETIF_F_GRO_HW; ++ ++ return features; ++} ++ ++static int airoha_dev_set_features(struct net_device *dev, ++ netdev_features_t features) ++{ ++ netdev_features_t diff = dev->features ^ features; ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_qdma *qdma = port->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int qdma_id = qdma - ð->qdma[0]; ++ ++ if (!(diff & NETIF_F_GRO_HW)) ++ return 0; ++ ++ if (features & NETIF_F_GRO_HW) ++ airoha_dev_lro_enable(port); ++ else ++ airoha_fe_lro_disable(eth, qdma_id); ++ ++ return 0; ++} ++ + static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, + struct net_device *dev) + { +@@ -2933,6 +3231,8 @@ static const struct net_device_ops airoh + .ndo_stop = airoha_dev_stop, + .ndo_change_mtu = airoha_dev_change_mtu, + .ndo_select_queue = airoha_dev_select_queue, ++ .ndo_fix_features = airoha_dev_fix_features, ++ .ndo_set_features = airoha_dev_set_features, + .ndo_start_xmit = airoha_dev_xmit, + .ndo_get_stats64 = airoha_dev_get_stats64, + .ndo_set_mac_address = airoha_dev_set_macaddr, +@@ -3150,12 +3450,9 @@ static int airoha_alloc_gdm_port(struct + dev->ethtool_ops = &airoha_ethtool_ops; + dev->max_mtu = AIROHA_MAX_MTU; + dev->watchdog_timeo = 5 * HZ; +- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | +- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | +- NETIF_F_SG | NETIF_F_TSO | +- NETIF_F_HW_TC; +- dev->features |= dev->hw_features; +- dev->vlan_features = dev->hw_features; ++ dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; ++ dev->features |= AIROHA_HW_FEATURES; ++ dev->vlan_features = AIROHA_HW_FEATURES; + dev->dev.of_node = np; + SET_NETDEV_DEV(dev, eth->dev); + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -43,6 +43,18 @@ + (_n) == 15 ? 128 : \ + (_n) == 0 ? 1024 : 16) + ++#define AIROHA_LRO_PAGE_ORDER order_base_2(SZ_16K / PAGE_SIZE) ++#define AIROHA_MAX_NUM_LRO_QUEUES 8 ++#define AIROHA_RXQ_LRO_EN_MASK GENMASK(7, 0) ++#define AIROHA_RXQ_LRO_MAX_AGG_COUNT 64 ++#define AIROHA_RXQ_LRO_MAX_AGG_TIME 100 ++#define AIROHA_RXQ_LRO_MAX_AGE_TIME 2000 ++ ++#define AIROHA_HW_FEATURES \ ++ (NETIF_F_IP_CSUM | NETIF_F_RXCSUM | \ ++ NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | \ ++ NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_TC) ++ + #define PSE_RSV_PAGES 128 + #define PSE_QUEUE_RSV_PAGES 64 + +@@ -666,6 +678,18 @@ static inline bool airoha_is_7583(struct + return eth->soc->version == 0x7583; + } + ++static inline bool airoha_qdma_is_lro_queue(struct airoha_queue *q) ++{ ++ struct airoha_qdma *qdma = q->qdma; ++ int qid = q - &qdma->q_rx[0]; ++ ++ /* EN7581 SoC supports at most 8 LRO rx queues */ ++ BUILD_BUG_ON(hweight32(AIROHA_RXQ_LRO_EN_MASK) > ++ AIROHA_MAX_NUM_LRO_QUEUES); ++ ++ return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid)); ++} ++ + int airoha_get_fe_port(struct airoha_gdm_port *port); + bool airoha_is_valid_gdm_port(struct airoha_eth *eth, + struct airoha_gdm_port *port); +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -122,6 +122,20 @@ + #define CDM_CRSN_QSEL_REASON_MASK(_n) \ + GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) + ++#define REG_CDM_LRO_RXQ(_n, _m) (CDM_BASE(_n) + 0x78 + ((_m) & 0x4)) ++#define LRO_RXQ_MASK(_n) GENMASK(4 + (((_n) & 0x3) << 3), ((_n) & 0x3) << 3) ++ ++#define REG_CDM_LRO_EN(_n) (CDM_BASE(_n) + 0x80) ++#define LRO_RXQ_EN_MASK GENMASK(7, 0) ++ ++#define REG_CDM_LRO_LIMIT(_n) (CDM_BASE(_n) + 0x84) ++#define CDM_LRO_AGG_NUM_MASK GENMASK(23, 16) ++#define CDM_LRO_AGG_SIZE_MASK GENMASK(15, 0) ++ ++#define REG_CDM_LRO_AGE_TIME(_n) (CDM_BASE(_n) + 0x88) ++#define CDM_LRO_AGE_TIME_MASK GENMASK(31, 16) ++#define CDM_LRO_AGG_TIME_MASK GENMASK(15, 0) ++ + #define REG_GDM_FWD_CFG(_n) GDM_BASE(_n) + #define GDM_PAD_EN_MASK BIT(28) + #define GDM_DROP_CRC_ERR_MASK BIT(23) +@@ -895,9 +909,15 @@ + #define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21) + #define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16) + #define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0) ++/* RX MSG2 */ ++#define QDMA_ETH_RXMSG_AGG_COUNT_MASK GENMASK(31, 24) ++#define QDMA_ETH_RXMSG_L2_LEN_MASK GENMASK(6, 0) ++/* RX MSG3 */ ++#define QDMA_ETH_RXMSG_AGG_LEN_MASK GENMASK(31, 16) ++#define QDMA_ETH_RXMSG_TCP_WIN_MASK GENMASK(15, 0) + + struct airoha_qdma_desc { +- __le32 rsv; ++ __le32 tcp_ts_reply; + __le32 ctrl; + __le32 addr; + __le32 data; diff --git a/target/linux/airoha/patches-6.18/916-net-airoha-Implement-LRO-TCP-support.patch b/target/linux/airoha/patches-6.18/916-net-airoha-Implement-LRO-TCP-support.patch deleted file mode 100644 index 7636ecbbc8..0000000000 --- a/target/linux/airoha/patches-6.18/916-net-airoha-Implement-LRO-TCP-support.patch +++ /dev/null @@ -1,392 +0,0 @@ -From 598e1ddfe85ad0f4778eeadd5d878209dd931280 Mon Sep 17 00:00:00 2001 -Message-ID: <598e1ddfe85ad0f4778eeadd5d878209dd931280.1779112628.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Thu, 14 May 2026 20:25:19 +0200 -Subject: [PATCH] net: airoha: Implement LRO TCP support - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 178 ++++++++++++++++++++-- - drivers/net/ethernet/airoha/airoha_eth.h | 23 +++ - drivers/net/ethernet/airoha/airoha_regs.h | 22 ++- - 3 files changed, 208 insertions(+), 15 deletions(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - - #include "airoha_regs.h" -@@ -439,6 +440,48 @@ static void airoha_fe_crsn_qsel_init(str - CDM_CRSN_QSEL_Q1)); - } - -+static void airoha_fe_lro_init_rx_queue(struct airoha_eth *eth, int qdma_id, -+ int lro_queue_index, int qid, -+ int buf_size) -+{ -+ int id = qdma_id + 1; -+ -+ airoha_fe_rmw(eth, REG_CDM_LRO_LIMIT(id), -+ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK, -+ FIELD_PREP(CDM_LRO_AGG_SIZE_MASK, buf_size) | -+ FIELD_PREP(CDM_LRO_AGG_NUM_MASK, -+ AIROHA_RXQ_LRO_MAX_AGG_COUNT)); -+ airoha_fe_rmw(eth, REG_CDM_LRO_AGE_TIME(id), -+ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK, -+ FIELD_PREP(CDM_LRO_AGE_TIME_MASK, -+ AIROHA_RXQ_LRO_MAX_AGE_TIME) | -+ FIELD_PREP(CDM_LRO_AGG_TIME_MASK, -+ AIROHA_RXQ_LRO_MAX_AGG_TIME)); -+ airoha_fe_rmw(eth, REG_CDM_LRO_RXQ(id, lro_queue_index), -+ LRO_RXQ_MASK(lro_queue_index), -+ __field_prep(LRO_RXQ_MASK(lro_queue_index), qid)); -+ airoha_fe_set(eth, REG_CDM_LRO_EN(id), BIT(lro_queue_index)); -+} -+ -+static void airoha_fe_lro_disable(struct airoha_eth *eth, int qdma_id) -+{ -+ int i, id = qdma_id + 1; -+ -+ airoha_fe_clear(eth, REG_CDM_LRO_EN(id), LRO_RXQ_EN_MASK); -+ airoha_fe_clear(eth, REG_CDM_LRO_LIMIT(id), -+ CDM_LRO_AGG_NUM_MASK | CDM_LRO_AGG_SIZE_MASK); -+ airoha_fe_clear(eth, REG_CDM_LRO_AGE_TIME(id), -+ CDM_LRO_AGE_TIME_MASK | CDM_LRO_AGG_TIME_MASK); -+ for (i = 0; i < AIROHA_MAX_NUM_LRO_QUEUES; i++) -+ airoha_fe_clear(eth, REG_CDM_LRO_RXQ(id, i), LRO_RXQ_MASK(i)); -+} -+ -+static bool airoha_fe_lro_is_enabled(struct airoha_eth *eth, int qdma_id) -+{ -+ return airoha_fe_get(eth, REG_CDM_LRO_EN(qdma_id + 1), -+ LRO_RXQ_EN_MASK); -+} -+ - static int airoha_fe_init(struct airoha_eth *eth) - { - airoha_fe_maccr_init(eth); -@@ -603,6 +646,85 @@ static int airoha_qdma_get_gdm_port(stru - return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; - } - -+static int airoha_qdma_lro_rx_process(struct airoha_queue *q, -+ struct airoha_qdma_desc *desc) -+{ -+ u32 desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); -+ u32 msg1 = le32_to_cpu(READ_ONCE(desc->msg1)); -+ u32 msg2 = le32_to_cpu(READ_ONCE(desc->msg2)); -+ u32 msg3 = le32_to_cpu(READ_ONCE(desc->msg3)); -+ struct sk_buff *skb = q->skb; -+ u32 len, th_off, tcp_ack_seq; -+ u16 tcp_win, l2_len; -+ struct tcphdr *th; -+ bool ipv4, ipv6; -+ -+ if (FIELD_GET(QDMA_ETH_RXMSG_AGG_COUNT_MASK, msg2) <= 1) -+ return 0; -+ -+ ipv4 = FIELD_GET(QDMA_ETH_RXMSG_IP4_MASK, msg1); -+ ipv6 = FIELD_GET(QDMA_ETH_RXMSG_IP6_MASK, msg1); -+ if (!ipv4 && !ipv6) -+ return -EOPNOTSUPP; -+ -+ l2_len = FIELD_GET(QDMA_ETH_RXMSG_L2_LEN_MASK, msg2); -+ len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl); -+ if (ipv4) { -+ struct iphdr *iph; -+ -+ if (!pskb_may_pull(skb, l2_len + sizeof(*iph))) -+ return -EINVAL; -+ -+ iph = (struct iphdr *)(skb->data + l2_len); -+ if (iph->protocol != IPPROTO_TCP) -+ return -EOPNOTSUPP; -+ -+ iph->tot_len = cpu_to_be16(len - l2_len); -+ iph->check = 0; -+ iph->check = ip_fast_csum((void *)iph, iph->ihl); -+ th_off = l2_len + (iph->ihl << 2); -+ } else { -+ struct ipv6hdr *ip6h; -+ -+ if (!pskb_may_pull(skb, l2_len + sizeof(*ip6h))) -+ return -EINVAL; -+ -+ ip6h = (struct ipv6hdr *)(skb->data + l2_len); -+ if (ip6h->nexthdr != NEXTHDR_TCP) -+ return -EOPNOTSUPP; -+ -+ ip6h->payload_len = cpu_to_be16(len - l2_len - sizeof(*ip6h)); -+ th_off = l2_len + sizeof(*ip6h); -+ } -+ -+ tcp_win = FIELD_GET(QDMA_ETH_RXMSG_TCP_WIN_MASK, msg3); -+ tcp_ack_seq = le32_to_cpu(READ_ONCE(desc->data)); -+ -+ if (!pskb_may_pull(skb, th_off + sizeof(*th))) -+ return -EINVAL; -+ -+ th = (struct tcphdr *)(skb->data + th_off); -+ th->ack_seq = cpu_to_be32(tcp_ack_seq); -+ th->window = cpu_to_be16(tcp_win); -+ -+ /* Check tcp timestamp option */ -+ if (th->doff == (sizeof(*th) + TCPOLEN_TSTAMP_ALIGNED) / 4) { -+ __be32 *topt = (__be32 *)(th + 1); -+ -+ if (*topt == cpu_to_be32((TCPOPT_NOP << 24) | -+ (TCPOPT_NOP << 16) | -+ (TCPOPT_TIMESTAMP << 8) | -+ TCPOLEN_TIMESTAMP)) { -+ __le32 tcp_ts_reply = READ_ONCE(desc->tcp_ts_reply); -+ -+ put_unaligned_be32(le32_to_cpu(tcp_ts_reply), -+ topt + 2); -+ } -+ } -+ -+ return 0; -+} -+ - static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) - { - enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); -@@ -650,11 +772,15 @@ static int airoha_qdma_rx_process(struct - - skb_reserve(q->skb, AIROHA_RX_HEADROOM); - __skb_put(q->skb, len); -- skb_mark_for_recycle(q->skb); - q->skb->dev = port->dev; -- q->skb->protocol = eth_type_trans(q->skb, port->dev); - q->skb->ip_summed = CHECKSUM_UNNECESSARY; - skb_record_rx_queue(q->skb, qid); -+ -+ if (airoha_qdma_lro_rx_process(q, desc) < 0) -+ goto free_frag; -+ -+ q->skb->protocol = eth_type_trans(q->skb, port->dev); -+ skb_mark_for_recycle(q->skb); - } else { /* scattered frame */ - struct skb_shared_info *shinfo = skb_shinfo(q->skb); - int nr_frags = shinfo->nr_frags; -@@ -743,12 +869,10 @@ static int airoha_qdma_rx_napi_poll(stru - static int airoha_qdma_init_rx_queue(struct airoha_queue *q, - struct airoha_qdma *qdma, int ndesc) - { -- const struct page_pool_params pp_params = { -- .order = 0, -+ struct page_pool_params pp_params = { - .pool_size = 256, - .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, - .dma_dir = DMA_FROM_DEVICE, -- .max_len = PAGE_SIZE, - .nid = NUMA_NO_NODE, - .dev = qdma->eth->dev, - .napi = &q->napi, -@@ -756,9 +880,10 @@ static int airoha_qdma_init_rx_queue(str - struct airoha_eth *eth = qdma->eth; - int qid = q - &qdma->q_rx[0], thr; - dma_addr_t dma_addr; -+ bool lro_q; - -- q->buf_size = PAGE_SIZE / 2; - q->qdma = qdma; -+ lro_q = airoha_qdma_is_lro_queue(q); - - q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry), - GFP_KERNEL); -@@ -770,6 +895,9 @@ static int airoha_qdma_init_rx_queue(str - if (!q->desc) - return -ENOMEM; - -+ pp_params.order = lro_q ? AIROHA_LRO_PAGE_ORDER : 0; -+ pp_params.max_len = PAGE_SIZE << pp_params.order; -+ - q->page_pool = page_pool_create(&pp_params); - if (IS_ERR(q->page_pool)) { - int err = PTR_ERR(q->page_pool); -@@ -778,6 +906,7 @@ static int airoha_qdma_init_rx_queue(str - return err; - } - -+ q->buf_size = lro_q ? pp_params.max_len : pp_params.max_len / 2; - q->ndesc = ndesc; - netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); - -@@ -2034,6 +2163,67 @@ int airoha_get_fe_port(struct airoha_gdm - } - } - -+static int airoha_dev_set_features(struct net_device *dev, -+ netdev_features_t features) -+{ -+ netdev_features_t diff = dev->features ^ features; -+ struct airoha_gdm_port *port = netdev_priv(dev); -+ struct airoha_qdma *qdma = port->qdma; -+ struct airoha_eth *eth = qdma->eth; -+ int qdma_id = qdma - ð->qdma[0]; -+ int i; -+ -+ if (!(diff & NETIF_F_LRO)) -+ return 0; -+ -+ if (netif_running(dev)) -+ return -EBUSY; -+ -+ /* reset LRO configuration */ -+ if (features & NETIF_F_LRO) { -+ int lro_queue_index = 0; -+ -+ if (airoha_fe_lro_is_enabled(eth, qdma_id)) -+ return 0; -+ -+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { -+ struct airoha_queue *q = &qdma->q_rx[i]; -+ u32 size; -+ -+ if (!q->ndesc) -+ continue; -+ -+ if (!airoha_qdma_is_lro_queue(q)) -+ continue; -+ -+ size = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size)); -+ size = min_t(u32, size, CDM_LRO_AGG_SIZE_MASK); -+ airoha_fe_lro_init_rx_queue(eth, qdma_id, -+ lro_queue_index, i, size); -+ lro_queue_index++; -+ } -+ } else { -+ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { -+ struct airoha_gdm_port *p = eth->ports[i]; -+ -+ if (!p) -+ continue; -+ -+ if (p->qdma != qdma) -+ continue; -+ -+ if (p->dev == dev) -+ continue; -+ -+ if (p->dev->features & NETIF_F_LRO) -+ return 0; -+ } -+ airoha_fe_lro_disable(eth, qdma_id); -+ } -+ -+ return 0; -+} -+ - static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, - struct net_device *dev) - { -@@ -2933,6 +3123,7 @@ static const struct net_device_ops airoh - .ndo_stop = airoha_dev_stop, - .ndo_change_mtu = airoha_dev_change_mtu, - .ndo_select_queue = airoha_dev_select_queue, -+ .ndo_set_features = airoha_dev_set_features, - .ndo_start_xmit = airoha_dev_xmit, - .ndo_get_stats64 = airoha_dev_get_stats64, - .ndo_set_mac_address = airoha_dev_set_macaddr, -@@ -3150,12 +3341,9 @@ static int airoha_alloc_gdm_port(struct - dev->ethtool_ops = &airoha_ethtool_ops; - dev->max_mtu = AIROHA_MAX_MTU; - dev->watchdog_timeo = 5 * HZ; -- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | -- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | -- NETIF_F_SG | NETIF_F_TSO | -- NETIF_F_HW_TC; -- dev->features |= dev->hw_features; -- dev->vlan_features = dev->hw_features; -+ dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; -+ dev->features |= AIROHA_HW_FEATURES; -+ dev->vlan_features = AIROHA_HW_FEATURES; - dev->dev.of_node = np; - SET_NETDEV_DEV(dev, eth->dev); - ---- a/drivers/net/ethernet/airoha/airoha_eth.h -+++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -43,6 +43,18 @@ - (_n) == 15 ? 128 : \ - (_n) == 0 ? 1024 : 16) - -+#define AIROHA_LRO_PAGE_ORDER 2 -+#define AIROHA_MAX_NUM_LRO_QUEUES 8 -+#define AIROHA_RXQ_LRO_EN_MASK 0xff000000 -+#define AIROHA_RXQ_LRO_MAX_AGG_COUNT 64 -+#define AIROHA_RXQ_LRO_MAX_AGG_TIME 100 -+#define AIROHA_RXQ_LRO_MAX_AGE_TIME 2000 /* 1ms */ -+ -+#define AIROHA_HW_FEATURES \ -+ (NETIF_F_IP_CSUM | NETIF_F_RXCSUM | \ -+ NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | \ -+ NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_TC) -+ - #define PSE_RSV_PAGES 128 - #define PSE_QUEUE_RSV_PAGES 64 - -@@ -666,6 +678,18 @@ static inline bool airoha_is_7583(struct - return eth->soc->version == 0x7583; - } - -+static inline bool airoha_qdma_is_lro_queue(struct airoha_queue *q) -+{ -+ struct airoha_qdma *qdma = q->qdma; -+ int qid = q - &qdma->q_rx[0]; -+ -+ /* EN7581 SoC supports at most 8 LRO rx queues */ -+ BUILD_BUG_ON(hweight32(AIROHA_RXQ_LRO_EN_MASK) > -+ AIROHA_MAX_NUM_LRO_QUEUES); -+ -+ return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid)); -+} -+ - int airoha_get_fe_port(struct airoha_gdm_port *port); - bool airoha_is_valid_gdm_port(struct airoha_eth *eth, - struct airoha_gdm_port *port); ---- a/drivers/net/ethernet/airoha/airoha_regs.h -+++ b/drivers/net/ethernet/airoha/airoha_regs.h -@@ -122,6 +122,20 @@ - #define CDM_CRSN_QSEL_REASON_MASK(_n) \ - GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) - -+#define REG_CDM_LRO_RXQ(_n, _m) (CDM_BASE(_n) + 0x78 + ((_m) & 0x4)) -+#define LRO_RXQ_MASK(_n) GENMASK(4 + (((_n) & 0x3) << 3), ((_n) & 0x3) << 3) -+ -+#define REG_CDM_LRO_EN(_n) (CDM_BASE(_n) + 0x80) -+#define LRO_RXQ_EN_MASK GENMASK(7, 0) -+ -+#define REG_CDM_LRO_LIMIT(_n) (CDM_BASE(_n) + 0x84) -+#define CDM_LRO_AGG_NUM_MASK GENMASK(23, 16) -+#define CDM_LRO_AGG_SIZE_MASK GENMASK(15, 0) -+ -+#define REG_CDM_LRO_AGE_TIME(_n) (CDM_BASE(_n) + 0x88) -+#define CDM_LRO_AGE_TIME_MASK GENMASK(31, 16) -+#define CDM_LRO_AGG_TIME_MASK GENMASK(15, 0) -+ - #define REG_GDM_FWD_CFG(_n) GDM_BASE(_n) - #define GDM_PAD_EN_MASK BIT(28) - #define GDM_DROP_CRC_ERR_MASK BIT(23) -@@ -895,9 +909,15 @@ - #define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21) - #define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16) - #define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0) -+/* RX MSG2 */ -+#define QDMA_ETH_RXMSG_AGG_COUNT_MASK GENMASK(31, 24) -+#define QDMA_ETH_RXMSG_L2_LEN_MASK GENMASK(6, 0) -+/* RX MSG3 */ -+#define QDMA_ETH_RXMSG_AGG_LEN_MASK GENMASK(31, 16) -+#define QDMA_ETH_RXMSG_TCP_WIN_MASK GENMASK(15, 0) - - struct airoha_qdma_desc { -- __le32 rsv; -+ __le32 tcp_ts_reply; - __le32 ctrl; - __le32 addr; - __le32 data; diff --git a/target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch b/target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch index 6d2eee0446..f92593c504 100644 --- a/target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch +++ b/target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch @@ -25,7 +25,18 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -738,6 +738,7 @@ static int airoha_qdma_rx_process(struct +@@ -483,8 +483,9 @@ static bool airoha_fe_lro_is_enabled(str + LRO_RXQ_EN_MASK); + } + +-static void airoha_dev_lro_enable(struct airoha_gdm_port *port) ++static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) + { ++ struct airoha_gdm_port *port = dev->port; + struct airoha_qdma *qdma = port->qdma; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; +@@ -843,6 +844,7 @@ static int airoha_qdma_rx_process(struct struct airoha_qdma_desc *desc = &q->desc[q->tail]; u32 hash, reason, msg1, desc_ctrl; struct airoha_gdm_port *port; @@ -33,35 +44,21 @@ Signed-off-by: Lorenzo Bianconi int data_len, len, p; struct page *page; -@@ -764,6 +765,10 @@ static int airoha_qdma_rx_process(struct +@@ -869,8 +871,12 @@ static int airoha_qdma_rx_process(struct goto free_frag; port = eth->ports[p]; + if (!port->dev) + goto free_frag; + -+ netdev = port->dev->dev; ++ netdev = netdev_from_priv(port->dev); if (!q->skb) { /* first buffer */ - q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, - q->buf_size); -@@ -772,14 +777,14 @@ static int airoha_qdma_rx_process(struct - - skb_reserve(q->skb, AIROHA_RX_HEADROOM); - __skb_put(q->skb, len); -- q->skb->dev = port->dev; -+ q->skb->dev = netdev; - q->skb->ip_summed = CHECKSUM_UNNECESSARY; - skb_record_rx_queue(q->skb, qid); - - if (airoha_qdma_lro_rx_process(q, desc) < 0) +- q->skb = airoha_qdma_build_rx_skb(q, desc, e, port->dev); ++ q->skb = airoha_qdma_build_rx_skb(q, desc, e, netdev); + if (!q->skb) goto free_frag; - -- q->skb->protocol = eth_type_trans(q->skb, port->dev); -+ q->skb->protocol = eth_type_trans(q->skb, netdev); - skb_mark_for_recycle(q->skb); } else { /* scattered frame */ - struct skb_shared_info *shinfo = skb_shinfo(q->skb); -@@ -796,7 +801,7 @@ static int airoha_qdma_rx_process(struct +@@ -888,7 +894,7 @@ static int airoha_qdma_rx_process(struct if (FIELD_GET(QDMA_DESC_MORE_MASK, desc_ctrl)) continue; @@ -70,33 +67,55 @@ Signed-off-by: Lorenzo Bianconi /* PPE module requires untagged packets to work * properly and it provides DSA port index via the * DMA descriptor. Report DSA tag to the DSA stack -@@ -993,6 +998,7 @@ static void airoha_qdma_wake_netdev_txqs +@@ -1091,6 +1097,7 @@ static void airoha_qdma_wake_netdev_txqs for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; -+ struct airoha_gdm_dev *dev; ++ struct net_device *netdev; int j; if (!port) -@@ -1001,11 +1007,12 @@ static void airoha_qdma_wake_netdev_txqs +@@ -1099,11 +1106,12 @@ static void airoha_qdma_wake_netdev_txqs if (port->qdma != qdma) continue; - for (j = 0; j < port->dev->num_tx_queues; j++) { -+ dev = port->dev; -+ for (j = 0; j < dev->dev->num_tx_queues; j++) { ++ netdev = netdev_from_priv(port->dev); ++ for (j = 0; j < netdev->num_tx_queues; j++) { if (airoha_qdma_get_txq(qdma, j) != qid) continue; - netif_wake_subqueue(port->dev, j); -+ netif_wake_subqueue(dev->dev, j); ++ netif_wake_subqueue(netdev, j); } } q->txq_stopped = false; -@@ -1849,33 +1856,34 @@ static void airoha_update_hw_stats(struc +@@ -1947,9 +1955,10 @@ static void airoha_update_hw_stats(struc spin_unlock(&port->stats.lock); } +-static void airoha_update_netdev_features(struct airoha_gdm_port *port) ++static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) + { +- struct airoha_eth *eth = port->eth; ++ struct airoha_gdm_port *port = dev->port; ++ struct airoha_eth *eth = dev->eth; + int i; + + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { +@@ -1959,7 +1968,7 @@ static void airoha_update_netdev_feature + if (!p) + continue; + +- netdev = p->dev; ++ netdev = netdev_from_priv(p->dev); + if (netdev->reg_state != NETREG_REGISTERED) + continue; + +@@ -1967,10 +1976,11 @@ static void airoha_update_netdev_feature + } + } + -static int airoha_dev_open(struct net_device *dev) +static int airoha_dev_open(struct net_device *netdev) { @@ -106,16 +125,28 @@ Signed-off-by: Lorenzo Bianconi + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; struct airoha_qdma *qdma = port->qdma; - u32 pse_port = FE_PSE_PORT_PPE1; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; +@@ -1981,31 +1991,32 @@ static int airoha_dev_open(struct net_de + * the same QDMA if LRO is enabled on any device sharing it. + */ + if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { +- netdev_warn(dev, "required to disable HW GRO on QDMA%d\n", ++ netdev_warn(netdev, "required to disable HW GRO on QDMA%d\n", + qdma_id); + return -EBUSY; + } #if defined(CONFIG_PCS_AIROHA) if (airhoa_is_phy_external(port)) { - err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); -+ err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0); ++ err = phylink_of_phy_connect(dev->phylink, ++ netdev->dev.of_node, 0); if (err) { - netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -+ netdev_err(netdev, "%s: could not attach PHY: %d\n", __func__, - err); +- err); ++ netdev_err(netdev, "%s: could not attach PHY: %d\n", ++ __func__, err); return err; } @@ -133,10 +164,21 @@ Signed-off-by: Lorenzo Bianconi /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ - if (netdev_uses_dsa(dev) || port->id > 2) + if (netdev_uses_dsa(netdev) || port->id > 2) - airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), + airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); else -@@ -1903,16 +1911,17 @@ static int airoha_dev_open(struct net_de +@@ -2029,25 +2040,26 @@ static int airoha_dev_open(struct net_de + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), + pse_port); + +- if (dev->features & NETIF_F_GRO_HW) +- airoha_dev_lro_enable(port); ++ if (netdev->features & NETIF_F_GRO_HW) ++ airoha_dev_lro_enable(dev); + +- airoha_update_netdev_features(port); ++ airoha_update_netdev_features(dev); + return 0; } @@ -147,6 +189,7 @@ Signed-off-by: Lorenzo Bianconi + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; struct airoha_qdma *qdma = port->qdma; + struct airoha_eth *eth = qdma->eth; int i; - netif_tx_disable(dev); @@ -157,9 +200,14 @@ Signed-off-by: Lorenzo Bianconi + for (i = 0; i < netdev->num_tx_queues; i++) + netdev_tx_reset_subqueue(netdev, i); - airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), FE_PSE_PORT_DROP); -@@ -1932,24 +1941,25 @@ static int airoha_dev_stop(struct net_de +@@ -2065,28 +2077,29 @@ static int airoha_dev_stop(struct net_de + } + } + +- airoha_update_netdev_features(port); ++ airoha_update_netdev_features(dev); #if defined(CONFIG_PCS_AIROHA) if (airhoa_is_phy_external(port)) { @@ -191,7 +239,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2015,16 +2025,17 @@ static int airoha_set_gdm2_loopback(stru +@@ -2152,16 +2165,17 @@ static int airoha_set_gdm2_loopback(stru return 0; } @@ -209,12 +257,12 @@ Signed-off-by: Lorenzo Bianconi port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; - port->dev->irq = port->qdma->irq_banks[0].irq; - airoha_set_macaddr(port, dev->dev_addr); -+ dev->dev->irq = port->qdma->irq_banks[0].irq; ++ netdev->irq = port->qdma->irq_banks[0].irq; + airoha_set_macaddr(port, netdev->dev_addr); switch (port->id) { case AIROHA_GDM3_IDX: -@@ -2049,10 +2060,11 @@ static int airoha_dev_init(struct net_de +@@ -2186,10 +2200,11 @@ static int airoha_dev_init(struct net_de return 0; } @@ -228,7 +276,7 @@ Signed-off-by: Lorenzo Bianconi unsigned int start; airoha_update_hw_stats(port); -@@ -2071,36 +2083,39 @@ static void airoha_dev_get_stats64(struc +@@ -2208,36 +2223,39 @@ static void airoha_dev_get_stats64(struc } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -275,10 +323,24 @@ Signed-off-by: Lorenzo Bianconi } static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev) -@@ -2163,11 +2178,12 @@ int airoha_get_fe_port(struct airoha_gdm +@@ -2300,10 +2318,11 @@ int airoha_get_fe_port(struct airoha_gdm } } +-static netdev_features_t airoha_dev_fix_features(struct net_device *dev, ++static netdev_features_t airoha_dev_fix_features(struct net_device *netdev, + netdev_features_t features) + { +- struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_gdm_port *port = dev->port; + struct airoha_qdma *qdma = port->qdma; + + if (qdma->users > 1) +@@ -2312,11 +2331,12 @@ static netdev_features_t airoha_dev_fix_ + return features; + } + -static int airoha_dev_set_features(struct net_device *dev, +static int airoha_dev_set_features(struct net_device *netdev, netdev_features_t features) @@ -291,38 +353,16 @@ Signed-off-by: Lorenzo Bianconi struct airoha_qdma *qdma = port->qdma; struct airoha_eth *eth = qdma->eth; int qdma_id = qdma - ð->qdma[0]; -@@ -2176,7 +2192,7 @@ static int airoha_dev_set_features(struc - if (!(diff & NETIF_F_LRO)) +@@ -2325,7 +2345,7 @@ static int airoha_dev_set_features(struc return 0; -- if (netif_running(dev)) -+ if (netif_running(netdev)) - return -EBUSY; - - /* reset LRO configuration */ -@@ -2205,6 +2221,7 @@ static int airoha_dev_set_features(struc - } else { - for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { - struct airoha_gdm_port *p = eth->ports[i]; -+ struct airoha_gdm_dev *d; - - if (!p) - continue; -@@ -2212,10 +2229,11 @@ static int airoha_dev_set_features(struc - if (p->qdma != qdma) - continue; - -- if (p->dev == dev) -+ d = p->dev; -+ if (d->dev == netdev) - continue; - -- if (p->dev->features & NETIF_F_LRO) -+ if (d->dev->features & NETIF_F_LRO) - return 0; - } + if (features & NETIF_F_GRO_HW) +- airoha_dev_lro_enable(port); ++ airoha_dev_lro_enable(dev); + else airoha_fe_lro_disable(eth, qdma_id); -@@ -2225,9 +2243,10 @@ static int airoha_dev_set_features(struc + +@@ -2333,9 +2353,10 @@ static int airoha_dev_set_features(struc } static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, @@ -335,7 +375,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_qdma *qdma = port->qdma; u32 nr_frags, tag, msg0, msg1, len; struct airoha_queue_entry *e; -@@ -2240,7 +2259,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2348,7 +2369,7 @@ static netdev_tx_t airoha_dev_xmit(struc u8 fport; qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb)); @@ -344,7 +384,7 @@ Signed-off-by: Lorenzo Bianconi msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK, qid / AIROHA_NUM_QOS_QUEUES) | -@@ -2276,7 +2295,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2384,7 +2405,7 @@ static netdev_tx_t airoha_dev_xmit(struc spin_lock_bh(&q->lock); @@ -353,7 +393,7 @@ Signed-off-by: Lorenzo Bianconi nr_frags = 1 + skb_shinfo(skb)->nr_frags; if (q->queued + nr_frags >= q->ndesc) { -@@ -2300,9 +2319,9 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2408,9 +2429,9 @@ static netdev_tx_t airoha_dev_xmit(struc dma_addr_t addr; u32 val; @@ -365,7 +405,7 @@ Signed-off-by: Lorenzo Bianconi goto error_unmap; list_move_tail(&e->list, &tx_list); -@@ -2351,7 +2370,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2459,7 +2480,7 @@ static netdev_tx_t airoha_dev_xmit(struc error_unmap: list_for_each_entry(e, &tx_list, list) { @@ -374,7 +414,7 @@ Signed-off-by: Lorenzo Bianconi DMA_TO_DEVICE); e->dma_addr = 0; } -@@ -2360,25 +2379,27 @@ error_unmap: +@@ -2468,25 +2489,27 @@ error_unmap: spin_unlock_bh(&q->lock); error: dev_kfree_skb_any(skb); @@ -407,7 +447,7 @@ Signed-off-by: Lorenzo Bianconi unsigned int start; airoha_update_hw_stats(port); -@@ -2406,11 +2427,12 @@ static const struct ethtool_rmon_hist_ra +@@ -2514,11 +2537,12 @@ static const struct ethtool_rmon_hist_ra }; static void @@ -422,7 +462,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_hw_stats *hw_stats = &port->stats; unsigned int start; -@@ -2435,11 +2457,12 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2543,11 +2567,12 @@ airoha_ethtool_get_rmon_stats(struct net } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -437,7 +477,7 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < AIROHA_NUM_TX_RING; i++) -@@ -2524,10 +2547,12 @@ static int airoha_qdma_set_tx_ets_sched( +@@ -2632,10 +2657,12 @@ static int airoha_qdma_set_tx_ets_sched( ARRAY_SIZE(w)); } @@ -452,7 +492,7 @@ Signed-off-by: Lorenzo Bianconi u64 cpu_tx_packets = airoha_qdma_rr(port->qdma, REG_CNTR_VAL(channel << 1)); u64 fwd_tx_packets = airoha_qdma_rr(port->qdma, -@@ -2789,11 +2814,12 @@ static int airoha_qdma_set_trtcm_token_b +@@ -2897,11 +2924,12 @@ static int airoha_qdma_set_trtcm_token_b mode, val); } @@ -467,7 +507,7 @@ Signed-off-by: Lorenzo Bianconi int i, err; for (i = 0; i <= TRTCM_PEAK_MODE; i++) { -@@ -2813,20 +2839,22 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2921,20 +2949,22 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -494,7 +534,7 @@ Signed-off-by: Lorenzo Bianconi if (err) { NL_SET_ERR_MSG_MOD(opt->extack, "failed configuring htb offload"); -@@ -2836,9 +2864,10 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2944,9 +2974,10 @@ static int airoha_tc_htb_alloc_leaf_queu if (opt->command == TC_HTB_NODE_MODIFY) return 0; @@ -507,7 +547,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); return err; -@@ -2928,11 +2957,12 @@ static int airoha_tc_matchall_act_valida +@@ -3036,11 +3067,12 @@ static int airoha_tc_matchall_act_valida return 0; } @@ -522,7 +562,7 @@ Signed-off-by: Lorenzo Bianconi u32 rate = 0, bucket_size = 0; switch (f->command) { -@@ -2967,18 +2997,19 @@ static int airoha_dev_tc_matchall(struct +@@ -3075,18 +3107,19 @@ static int airoha_dev_tc_matchall(struct static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { @@ -546,7 +586,7 @@ Signed-off-by: Lorenzo Bianconi default: return -EOPNOTSUPP; } -@@ -3025,47 +3056,51 @@ static int airoha_dev_setup_tc_block(str +@@ -3133,47 +3166,51 @@ static int airoha_dev_setup_tc_block(str } } @@ -610,7 +650,7 @@ Signed-off-by: Lorenzo Bianconi if (!test_bit(channel, port->qos_sq_bmap)) { NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); -@@ -3101,8 +3136,8 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -3209,8 +3246,8 @@ static int airoha_tc_setup_qdisc_htb(str return 0; } @@ -621,7 +661,7 @@ Signed-off-by: Lorenzo Bianconi { switch (type) { case TC_SETUP_QDISC_ETS: -@@ -3174,13 +3209,18 @@ static void airoha_metadata_dst_free(str +@@ -3283,13 +3320,18 @@ static void airoha_metadata_dst_free(str } } @@ -643,7 +683,7 @@ Signed-off-by: Lorenzo Bianconi return true; } -@@ -3192,8 +3232,9 @@ static void airoha_mac_link_up(struct ph +@@ -3301,8 +3343,9 @@ static void airoha_mac_link_up(struct ph unsigned int mode, phy_interface_t interface, int speed, int duplex, bool tx_pause, bool rx_pause) { @@ -655,7 +695,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_qdma *qdma = port->qdma; struct airoha_eth *eth = qdma->eth; u32 frag_size_tx, frag_size_rx; -@@ -3249,65 +3290,122 @@ static int airoha_fill_available_pcs(str +@@ -3358,65 +3401,121 @@ static int airoha_fill_available_pcs(str &num_available_pcs); } @@ -753,7 +793,7 @@ Signed-off-by: Lorenzo Bianconi + netdev->ethtool_ops = &airoha_ethtool_ops; + netdev->max_mtu = AIROHA_MAX_MTU; + netdev->watchdog_timeo = 5 * HZ; -+ netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; ++ netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; + netdev->features |= AIROHA_HW_FEATURES; + netdev->vlan_features = AIROHA_HW_FEATURES; + netdev->dev.of_node = np; @@ -775,7 +815,6 @@ Signed-off-by: Lorenzo Bianconi + } + + dev = netdev_priv(netdev); -+ dev->dev = netdev; + dev->port = port; + port->dev = dev; + dev->eth = eth; @@ -800,7 +839,7 @@ Signed-off-by: Lorenzo Bianconi int err, p; u32 id; -@@ -3329,58 +3427,22 @@ static int airoha_alloc_gdm_port(struct +@@ -3438,58 +3537,22 @@ static int airoha_alloc_gdm_port(struct return -EINVAL; } @@ -818,7 +857,7 @@ Signed-off-by: Lorenzo Bianconi - dev->ethtool_ops = &airoha_ethtool_ops; - dev->max_mtu = AIROHA_MAX_MTU; - dev->watchdog_timeo = 5 * HZ; -- dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; +- dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; - dev->features |= AIROHA_HW_FEATURES; - dev->vlan_features = AIROHA_HW_FEATURES; - dev->dev.of_node = np; @@ -865,16 +904,16 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_register_gdm_devices(struct airoha_eth *eth) -@@ -3394,7 +3456,7 @@ static int airoha_register_gdm_devices(s +@@ -3503,7 +3566,7 @@ static int airoha_register_gdm_devices(s if (!port) continue; - err = register_netdev(port->dev); -+ err = register_netdev(port->dev->dev); ++ err = register_netdev(netdev_from_priv(port->dev)); if (err) return err; } -@@ -3503,16 +3565,18 @@ error_napi_stop: +@@ -3612,16 +3675,22 @@ error_napi_stop: for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -885,18 +924,23 @@ Signed-off-by: Lorenzo Bianconi - if (port->dev->reg_state == NETREG_REGISTERED) { + dev = port->dev; -+ if (dev && dev->dev->reg_state == NETREG_REGISTERED) { ++ if (dev) { ++ struct net_device *netdev = netdev_from_priv(dev); ++ ++ if (netdev->reg_state == NETREG_REGISTERED) { #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) +- if (airhoa_is_phy_external(port)) - phylink_destroy(port->phylink); -+ phylink_destroy(dev->phylink); ++ if (airhoa_is_phy_external(port)) ++ phylink_destroy(dev->phylink); #endif - unregister_netdev(port->dev); -+ unregister_netdev(dev->dev); ++ unregister_netdev(netdev); ++ } } airoha_metadata_dst_free(port); } -@@ -3534,15 +3598,19 @@ static void airoha_remove(struct platfor +@@ -3643,15 +3712,19 @@ static void airoha_remove(struct platfor for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -914,25 +958,24 @@ Signed-off-by: Lorenzo Bianconi + + dev = port->dev; + if (dev) -+ unregister_netdev(dev->dev); ++ unregister_netdev(netdev_from_priv(dev)); airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -547,17 +547,22 @@ struct airoha_qdma { +@@ -547,17 +547,21 @@ struct airoha_qdma { struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; }; -struct airoha_gdm_port { - struct airoha_qdma *qdma; -- struct airoha_eth *eth; +struct airoha_gdm_dev { + struct airoha_gdm_port *port; - struct net_device *dev; + struct airoha_eth *eth; +- struct net_device *dev; - int id; - int nbq; -+ struct airoha_eth *eth; #if defined(CONFIG_PCS_AIROHA) struct phylink *phylink; @@ -948,7 +991,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_hw_stats stats; -@@ -691,8 +696,8 @@ static inline bool airoha_qdma_is_lro_qu +@@ -691,8 +695,8 @@ static inline bool airoha_qdma_is_lro_qu } int airoha_get_fe_port(struct airoha_gdm_port *port); @@ -1007,12 +1050,33 @@ Signed-off-by: Lorenzo Bianconi if (dsa_port >= 0 || eth->ports[1]) pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; -@@ -1485,7 +1488,7 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -1484,8 +1487,8 @@ void airoha_ppe_check_skb(struct airoha_ + void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) { ++ struct net_device *dev = netdev_from_priv(port->dev); struct airoha_eth *eth = port->qdma->eth; - struct net_device *dev = port->dev; -+ struct net_device *dev = port->dev->dev; const u8 *addr = dev->dev_addr; u32 val; +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2760,6 +2760,17 @@ static inline void *netdev_priv(const st + return (void *)dev->priv; + } + ++/** ++ * netdev_from_priv() - get network device from priv ++ * @priv: network device private data ++ * ++ * Returns: net_device to which @priv belongs ++ */ ++static inline struct net_device *netdev_from_priv(const void *priv) ++{ ++ return container_of(priv, struct net_device, priv); ++} ++ + /* Set the sysfs physical device reference for the network logical device + * if set prior to registration will cause a symlink during initialization. + */ diff --git a/target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch b/target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch index 8f3dd2d1d1..b95371056f 100644 --- a/target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch +++ b/target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch @@ -24,7 +24,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -80,9 +80,10 @@ static bool airhoa_is_phy_external(struc +@@ -81,9 +81,10 @@ static bool airhoa_is_phy_external(struc } #endif @@ -37,7 +37,7 @@ Signed-off-by: Lorenzo Bianconi u32 val, reg; reg = airoha_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H -@@ -94,7 +95,7 @@ static void airoha_set_macaddr(struct ai +@@ -95,7 +96,7 @@ static void airoha_set_macaddr(struct ai airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val); airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); @@ -46,7 +46,7 @@ Signed-off-by: Lorenzo Bianconi } static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, -@@ -110,10 +111,10 @@ static void airoha_set_gdm_port_fwd_cfg( +@@ -111,10 +112,10 @@ static void airoha_set_gdm_port_fwd_cfg( FIELD_PREP(GDM_UCFQ_MASK, val)); } @@ -60,7 +60,24 @@ Signed-off-by: Lorenzo Bianconi u32 vip_port; vip_port = eth->soc->ops.get_vip_port(port, port->nbq); -@@ -1004,10 +1005,13 @@ static void airoha_qdma_wake_netdev_txqs +@@ -485,8 +486,7 @@ static bool airoha_fe_lro_is_enabled(str + + static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) + { +- struct airoha_gdm_port *port = dev->port; +- struct airoha_qdma *qdma = port->qdma; ++ struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; + int i, lro_queue_index = 0; +@@ -1097,13 +1097,18 @@ static void airoha_qdma_wake_netdev_txqs + + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { + struct airoha_gdm_port *port = eth->ports[i]; ++ struct airoha_gdm_dev *dev; + struct net_device *netdev; + int j; + if (!port) continue; @@ -72,11 +89,8 @@ Signed-off-by: Lorenzo Bianconi + if (dev->qdma != qdma) continue; -- dev = port->dev; - for (j = 0; j < dev->dev->num_tx_queues; j++) { - if (airoha_qdma_get_txq(qdma, j) != qid) - continue; -@@ -1712,9 +1716,10 @@ static void airoha_qdma_stop_napi(struct + netdev = netdev_from_priv(port->dev); +@@ -1811,9 +1816,10 @@ static void airoha_qdma_stop_napi(struct } } @@ -89,16 +103,16 @@ Signed-off-by: Lorenzo Bianconi u32 val, i = 0; spin_lock(&port->stats.lock); -@@ -1861,7 +1866,7 @@ static int airoha_dev_open(struct net_de +@@ -1981,7 +1987,7 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; + struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; u32 pse_port = FE_PSE_PORT_PPE1; - - #if defined(CONFIG_PCS_AIROHA) -@@ -1878,7 +1883,7 @@ static int airoha_dev_open(struct net_de +@@ -2011,7 +2017,7 @@ static int airoha_dev_open(struct net_de #endif netif_tx_start_all_queues(netdev); @@ -107,12 +121,13 @@ Signed-off-by: Lorenzo Bianconi if (err) return err; -@@ -1915,11 +1920,11 @@ static int airoha_dev_stop(struct net_de +@@ -2052,12 +2058,12 @@ static int airoha_dev_stop(struct net_de { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; + struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; int i; netif_tx_disable(netdev); @@ -121,7 +136,7 @@ Signed-off-by: Lorenzo Bianconi for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); -@@ -1952,21 +1957,21 @@ static int airoha_dev_stop(struct net_de +@@ -2092,21 +2098,21 @@ static int airoha_dev_stop(struct net_de static int airoha_dev_set_macaddr(struct net_device *netdev, void *p) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -147,7 +162,7 @@ Signed-off-by: Lorenzo Bianconi u32 val, pse_port, chan; int i, src_port; -@@ -2013,7 +2018,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -2153,7 +2159,7 @@ static int airoha_set_gdm2_loopback(stru __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2)); for (i = 0; i < eth->soc->num_ppe; i++) @@ -156,20 +171,20 @@ Signed-off-by: Lorenzo Bianconi if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); -@@ -2033,9 +2038,9 @@ static int airoha_dev_init(struct net_de +@@ -2173,9 +2179,9 @@ static int airoha_dev_init(struct net_de int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ - port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; -- dev->dev->irq = port->qdma->irq_banks[0].irq; +- netdev->irq = port->qdma->irq_banks[0].irq; - airoha_set_macaddr(port, netdev->dev_addr); + dev->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; -+ dev->dev->irq = dev->qdma->irq_banks[0].irq; ++ netdev->irq = dev->qdma->irq_banks[0].irq; + airoha_set_macaddr(dev, netdev->dev_addr); switch (port->id) { case AIROHA_GDM3_IDX: -@@ -2044,7 +2049,7 @@ static int airoha_dev_init(struct net_de +@@ -2184,7 +2190,7 @@ static int airoha_dev_init(struct net_de if (!eth->ports[1]) { int err; @@ -178,7 +193,7 @@ Signed-off-by: Lorenzo Bianconi if (err) return err; } -@@ -2054,8 +2059,7 @@ static int airoha_dev_init(struct net_de +@@ -2194,8 +2200,7 @@ static int airoha_dev_init(struct net_de } for (i = 0; i < eth->soc->num_ppe; i++) @@ -188,7 +203,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2067,7 +2071,7 @@ static void airoha_dev_get_stats64(struc +@@ -2207,7 +2212,7 @@ static void airoha_dev_get_stats64(struc struct airoha_gdm_port *port = dev->port; unsigned int start; @@ -197,7 +212,7 @@ Signed-off-by: Lorenzo Bianconi do { start = u64_stats_fetch_begin(&port->stats.syncp); storage->rx_packets = port->stats.rx_ok_pkts; -@@ -2087,8 +2091,8 @@ static int airoha_dev_change_mtu(struct +@@ -2227,8 +2232,8 @@ static int airoha_dev_change_mtu(struct { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -207,7 +222,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), GDM_LONG_LEN_MASK, -@@ -2162,10 +2166,10 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -2302,10 +2307,10 @@ static u32 airoha_get_dsa_tag(struct sk_ #endif } @@ -221,7 +236,17 @@ Signed-off-by: Lorenzo Bianconi switch (eth->soc->version) { case 0x7583: -@@ -2183,8 +2187,7 @@ static int airoha_dev_set_features(struc +@@ -2322,8 +2327,7 @@ static netdev_features_t airoha_dev_fix_ + netdev_features_t features) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_gdm_port *port = dev->port; +- struct airoha_qdma *qdma = port->qdma; ++ struct airoha_qdma *qdma = dev->qdma; + + if (qdma->users > 1) + features &= ~NETIF_F_GRO_HW; +@@ -2336,8 +2340,7 @@ static int airoha_dev_set_features(struc { netdev_features_t diff = netdev->features ^ features; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -230,21 +255,8 @@ Signed-off-by: Lorenzo Bianconi + struct airoha_qdma *qdma = dev->qdma; struct airoha_eth *eth = qdma->eth; int qdma_id = qdma - ð->qdma[0]; - int i; -@@ -2226,10 +2229,10 @@ static int airoha_dev_set_features(struc - if (!p) - continue; -- if (p->qdma != qdma) -+ d = p->dev; -+ if (d->qdma != qdma) - continue; - -- d = p->dev; - if (d->dev == netdev) - continue; - -@@ -2246,8 +2249,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2356,8 +2359,7 @@ static netdev_tx_t airoha_dev_xmit(struc struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -254,7 +266,7 @@ Signed-off-by: Lorenzo Bianconi u32 nr_frags, tag, msg0, msg1, len; struct airoha_queue_entry *e; struct netdev_queue *txq; -@@ -2285,7 +2287,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2395,7 +2397,7 @@ static netdev_tx_t airoha_dev_xmit(struc } } @@ -263,7 +275,7 @@ Signed-off-by: Lorenzo Bianconi msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) | FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); -@@ -2388,8 +2390,7 @@ static void airoha_ethtool_get_drvinfo(s +@@ -2498,8 +2500,7 @@ static void airoha_ethtool_get_drvinfo(s struct ethtool_drvinfo *info) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -273,7 +285,7 @@ Signed-off-by: Lorenzo Bianconi strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver)); strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info)); -@@ -2402,7 +2403,7 @@ static void airoha_ethtool_get_mac_stats +@@ -2512,7 +2513,7 @@ static void airoha_ethtool_get_mac_stats struct airoha_gdm_port *port = dev->port; unsigned int start; @@ -282,7 +294,7 @@ Signed-off-by: Lorenzo Bianconi do { start = u64_stats_fetch_begin(&port->stats.syncp); stats->FramesTransmittedOK = port->stats.tx_ok_pkts; -@@ -2442,7 +2443,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2552,7 +2553,7 @@ airoha_ethtool_get_rmon_stats(struct net ARRAY_SIZE(hw_stats->rx_len) + 1); *ranges = airoha_ethtool_rmon_ranges; @@ -291,7 +303,7 @@ Signed-off-by: Lorenzo Bianconi do { int i; -@@ -2462,18 +2463,17 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2572,18 +2573,17 @@ static int airoha_qdma_set_chan_tx_sched const u16 *weights, u8 n_weights) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -312,7 +324,7 @@ Signed-off-by: Lorenzo Bianconi TWRR_RW_CMD_MASK | FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | -@@ -2481,13 +2481,12 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2591,13 +2591,12 @@ static int airoha_qdma_set_chan_tx_sched err = read_poll_timeout(airoha_qdma_rr, status, status & TWRR_RW_CMD_DONE, USEC_PER_MSEC, 10 * USEC_PER_MSEC, @@ -328,7 +340,7 @@ Signed-off-by: Lorenzo Bianconi CHAN_QOS_MODE_MASK(channel), __field_prep(CHAN_QOS_MODE_MASK(channel), mode)); -@@ -2553,9 +2552,9 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2663,9 +2662,9 @@ static int airoha_qdma_get_tx_ets_stats( struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -340,7 +352,7 @@ Signed-off-by: Lorenzo Bianconi REG_CNTR_VAL((channel << 1) + 1)); u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) + (fwd_tx_packets - port->fwd_tx_packets); -@@ -2819,17 +2818,16 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2929,17 +2928,16 @@ static int airoha_qdma_set_tx_rate_limit u32 bucket_size) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -360,7 +372,7 @@ Signed-off-by: Lorenzo Bianconi REG_EGRESS_TRTCM_CFG, i, rate, bucket_size); if (err) -@@ -2879,11 +2877,11 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2989,11 +2987,11 @@ static int airoha_tc_htb_alloc_leaf_queu return 0; } @@ -374,7 +386,7 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { -@@ -2962,7 +2960,6 @@ static int airoha_dev_tc_matchall(struct +@@ -3072,7 +3070,6 @@ static int airoha_dev_tc_matchall(struct { enum trtcm_unit_type unit_type = TRTCM_BYTE_UNIT; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -382,7 +394,7 @@ Signed-off-by: Lorenzo Bianconi u32 rate = 0, bucket_size = 0; switch (f->command) { -@@ -2987,7 +2984,7 @@ static int airoha_dev_tc_matchall(struct +@@ -3097,7 +3094,7 @@ static int airoha_dev_tc_matchall(struct fallthrough; } case TC_CLSMATCHALL_DESTROY: @@ -391,7 +403,7 @@ Signed-off-by: Lorenzo Bianconi unit_type); default: return -EOPNOTSUPP; -@@ -2999,8 +2996,7 @@ static int airoha_dev_setup_tc_block_cb( +@@ -3109,8 +3106,7 @@ static int airoha_dev_setup_tc_block_cb( { struct net_device *netdev = cb_priv; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -401,7 +413,7 @@ Signed-off-by: Lorenzo Bianconi if (!tc_can_offload(netdev)) return -EOPNOTSUPP; -@@ -3235,7 +3231,7 @@ static void airoha_mac_link_up(struct ph +@@ -3346,7 +3342,7 @@ static void airoha_mac_link_up(struct ph struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, phylink_config); struct airoha_gdm_port *port = dev->port; @@ -417,10 +429,10 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev { struct airoha_gdm_port *port; + struct airoha_qdma *qdma; - struct net_device *dev; struct airoha_eth *eth; -@@ -559,7 +560,6 @@ struct airoha_gdm_dev { + #if defined(CONFIG_PCS_AIROHA) +@@ -558,7 +559,6 @@ struct airoha_gdm_dev { }; struct airoha_gdm_port { @@ -428,7 +440,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev *dev; int id; int nbq; -@@ -695,19 +695,18 @@ static inline bool airoha_qdma_is_lro_qu +@@ -694,19 +694,18 @@ static inline bool airoha_qdma_is_lro_qu return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid)); } @@ -483,11 +495,11 @@ Signed-off-by: Lorenzo Bianconi -void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev) { +- struct net_device *dev = netdev_from_priv(port->dev); - struct airoha_eth *eth = port->qdma->eth; -- struct net_device *dev = port->dev->dev; - const u8 *addr = dev->dev_addr; ++ struct net_device *netdev = netdev_from_priv(dev); + struct airoha_gdm_port *port = dev->port; -+ struct net_device *netdev = dev->dev; + struct airoha_eth *eth = dev->eth; + const u8 *addr = netdev->dev_addr; u32 val; diff --git a/target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch b/target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch index 3ae068204b..64ed102d3a 100644 --- a/target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch +++ b/target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch @@ -23,7 +23,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -82,12 +82,10 @@ static bool airhoa_is_phy_external(struc +@@ -83,12 +83,10 @@ static bool airhoa_is_phy_external(struc static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) { @@ -37,18 +37,18 @@ Signed-off-by: Lorenzo Bianconi val = (addr[0] << 16) | (addr[1] << 8) | addr[2]; airoha_fe_wr(eth, reg, val); -@@ -2038,7 +2036,7 @@ static int airoha_dev_init(struct net_de +@@ -2179,7 +2177,7 @@ static int airoha_dev_init(struct net_de int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ - dev->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; + dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; - dev->dev->irq = dev->qdma->irq_banks[0].irq; + netdev->irq = dev->qdma->irq_banks[0].irq; airoha_set_macaddr(dev, netdev->dev_addr); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -664,8 +664,10 @@ static inline u16 airoha_qdma_get_txq(st +@@ -663,8 +663,10 @@ static inline u16 airoha_qdma_get_txq(st return qid % ARRAY_SIZE(qdma->q_tx); } diff --git a/target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch b/target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch index 7e0077124a..3bbcaab936 100644 --- a/target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch +++ b/target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch @@ -22,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2835,30 +2835,40 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2945,30 +2945,46 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -36,6 +36,7 @@ Signed-off-by: Lorenzo Bianconi - int err, num_tx_queues = netdev->real_num_tx_queues; - struct airoha_gdm_dev *dev = netdev_priv(netdev); - struct airoha_gdm_port *port = dev->port; ++ int err; if (opt->parent_classid != TC_HTB_CLASSID_ROOT) { NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid"); @@ -45,7 +46,13 @@ Signed-off-by: Lorenzo Bianconi - err = airoha_qdma_set_tx_rate_limit(netdev, channel, rate, - opt->quantum); - if (err) { -+ return airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); ++ err = airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); ++ if (err) + NL_SET_ERR_MSG_MOD(opt->extack, + "failed configuring htb offload"); +- return err; ++ ++ return err; +} + +static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev, @@ -60,9 +67,7 @@ Signed-off-by: Lorenzo Bianconi + * in use by another net_device running on the same QDMA block. + */ + if (test_and_set_bit(channel, qdma->qos_channel_map)) { - NL_SET_ERR_MSG_MOD(opt->extack, -- "failed configuring htb offload"); -- return err; ++ NL_SET_ERR_MSG_MOD(opt->extack, + "qdma qos channel already in use"); + return -EBUSY; } @@ -75,7 +80,7 @@ Signed-off-by: Lorenzo Bianconi err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1); if (err) { -@@ -2866,13 +2876,17 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2976,13 +2992,17 @@ static int airoha_tc_htb_alloc_leaf_queu opt->quantum); NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); @@ -95,7 +100,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev, -@@ -3053,11 +3067,13 @@ static int airoha_dev_setup_tc_block(str +@@ -3163,11 +3183,13 @@ static int airoha_dev_setup_tc_block(str static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -111,7 +116,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev, -@@ -3065,9 +3081,8 @@ static int airoha_tc_htb_delete_leaf_que +@@ -3175,9 +3197,8 @@ static int airoha_tc_htb_delete_leaf_que { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -122,7 +127,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); return -EINVAL; } -@@ -3080,10 +3095,9 @@ static int airoha_tc_htb_delete_leaf_que +@@ -3190,10 +3211,9 @@ static int airoha_tc_htb_delete_leaf_que static int airoha_tc_htb_destroy(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -134,7 +139,7 @@ Signed-off-by: Lorenzo Bianconi airoha_tc_remove_htb_queue(netdev, q); return 0; -@@ -3094,9 +3108,8 @@ static int airoha_tc_get_htb_get_leaf_qu +@@ -3204,9 +3224,8 @@ static int airoha_tc_get_htb_get_leaf_qu { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -145,7 +150,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); return -EINVAL; } -@@ -3115,6 +3128,7 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -3225,6 +3244,7 @@ static int airoha_tc_setup_qdisc_htb(str case TC_HTB_DESTROY: return airoha_tc_htb_destroy(dev); case TC_HTB_NODE_MODIFY: @@ -164,7 +169,7 @@ Signed-off-by: Lorenzo Bianconi }; struct airoha_gdm_dev { -@@ -557,6 +559,8 @@ struct airoha_gdm_dev { +@@ -556,6 +558,8 @@ struct airoha_gdm_dev { struct phylink *phylink; struct phylink_config phylink_config; #endif @@ -173,7 +178,7 @@ Signed-off-by: Lorenzo Bianconi }; struct airoha_gdm_port { -@@ -566,8 +570,6 @@ struct airoha_gdm_port { +@@ -565,8 +569,6 @@ struct airoha_gdm_port { struct airoha_hw_stats stats; diff --git a/target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch b/target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch index 9522e36b71..dfe8662b56 100644 --- a/target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch +++ b/target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch @@ -21,7 +21,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2548,19 +2548,17 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2658,19 +2658,17 @@ static int airoha_qdma_get_tx_ets_stats( struct tc_ets_qopt_offload *opt) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -50,7 +50,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -561,6 +561,9 @@ struct airoha_gdm_dev { +@@ -560,6 +560,9 @@ struct airoha_gdm_dev { #endif DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); @@ -60,7 +60,7 @@ Signed-off-by: Lorenzo Bianconi }; struct airoha_gdm_port { -@@ -570,10 +573,6 @@ struct airoha_gdm_port { +@@ -569,10 +572,6 @@ struct airoha_gdm_port { struct airoha_hw_stats stats; diff --git a/target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch b/target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch index ad848a432a..870b24371b 100644 --- a/target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch +++ b/target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch @@ -56,7 +56,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -115,7 +115,7 @@ static int airoha_set_vip_for_gdm_port(s +@@ -116,7 +116,7 @@ static int airoha_set_vip_for_gdm_port(s struct airoha_eth *eth = dev->eth; u32 vip_port; @@ -65,7 +65,7 @@ Signed-off-by: Lorenzo Bianconi if (enable) { airoha_fe_set(eth, REG_FE_VIP_PORT_EN, vip_port); airoha_fe_set(eth, REG_FE_IFC_PORT_EN, vip_port); -@@ -619,30 +619,26 @@ static int airoha_qdma_fill_rx_queue(str +@@ -646,30 +646,26 @@ static int airoha_qdma_fill_rx_queue(str return nframes; } @@ -100,82 +100,65 @@ Signed-off-by: Lorenzo Bianconi + + if (p >= ARRAY_SIZE(eth->ports)) + return ERR_PTR(-ENODEV); -+ + +- return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; + port = eth->ports[p]; + if (!port) + return ERR_PTR(-ENODEV); + + if (d >= ARRAY_SIZE(port->devs)) + return ERR_PTR(-ENODEV); - -- return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; ++ + return port->devs[d] ? port->devs[d] : ERR_PTR(-ENODEV); } - static int airoha_qdma_lro_rx_process(struct airoha_queue *q, -@@ -736,9 +732,8 @@ static int airoha_qdma_rx_process(struct + static struct sk_buff *airoha_qdma_lro_rx_skb(struct airoha_queue *q, +@@ -841,9 +837,9 @@ static int airoha_qdma_rx_process(struct struct airoha_queue_entry *e = &q->entry[q->tail]; struct airoha_qdma_desc *desc = &q->desc[q->tail]; u32 hash, reason, msg1, desc_ctrl; - struct airoha_gdm_port *port; -- struct net_device *netdev; -- int data_len, len, p; + struct airoha_gdm_dev *dev; + struct net_device *netdev; +- int data_len, len, p; + int data_len, len; struct page *page; desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); -@@ -759,15 +754,10 @@ static int airoha_qdma_rx_process(struct +@@ -864,15 +860,11 @@ static int airoha_qdma_rx_process(struct if (!len || data_len < len) goto free_frag; - p = airoha_qdma_get_gdm_port(eth, desc); - if (p < 0 || !eth->ports[p]) -- goto free_frag; -- -- port = eth->ports[p]; -- if (!port->dev) + dev = airoha_qdma_get_gdm_dev(eth, desc); + if (IS_ERR(dev)) goto free_frag; -- netdev = port->dev->dev; +- port = eth->ports[p]; +- if (!port->dev) +- goto free_frag; +- +- netdev = netdev_from_priv(port->dev); ++ netdev = netdev_from_priv(dev); if (!q->skb) { /* first buffer */ - q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, - q->buf_size); -@@ -776,14 +766,14 @@ static int airoha_qdma_rx_process(struct - - skb_reserve(q->skb, AIROHA_RX_HEADROOM); - __skb_put(q->skb, len); -- q->skb->dev = netdev; -+ q->skb->dev = dev->dev; - q->skb->ip_summed = CHECKSUM_UNNECESSARY; - skb_record_rx_queue(q->skb, qid); - - if (airoha_qdma_lro_rx_process(q, desc) < 0) - goto free_frag; - -- q->skb->protocol = eth_type_trans(q->skb, netdev); -+ q->skb->protocol = eth_type_trans(q->skb, dev->dev); - skb_mark_for_recycle(q->skb); - } else { /* scattered frame */ - struct skb_shared_info *shinfo = skb_shinfo(q->skb); -@@ -800,7 +790,9 @@ static int airoha_qdma_rx_process(struct - if (FIELD_GET(QDMA_DESC_MORE_MASK, desc_ctrl)) + q->skb = airoha_qdma_build_rx_skb(q, desc, e, netdev); + if (!q->skb) +@@ -893,6 +885,8 @@ static int airoha_qdma_rx_process(struct continue; -- if (netdev_uses_dsa(netdev)) { -+ if (netdev_uses_dsa(dev->dev)) { + if (netdev_uses_dsa(netdev)) { + struct airoha_gdm_port *port = dev->port; + /* PPE module requires untagged packets to work * properly and it provides DSA port index via the * DMA descriptor. Report DSA tag to the DSA stack -@@ -997,24 +989,27 @@ static void airoha_qdma_wake_netdev_txqs +@@ -1095,26 +1089,29 @@ static void airoha_qdma_wake_netdev_txqs for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; - struct airoha_gdm_dev *dev; +- struct net_device *netdev; - int j; + int d; @@ -187,6 +170,7 @@ Signed-off-by: Lorenzo Bianconi - continue; + for (d = 0; d < ARRAY_SIZE(port->devs); d++) { + struct airoha_gdm_dev *dev = port->devs[d]; ++ struct net_device *netdev; + int j; - if (dev->qdma != qdma) @@ -194,36 +178,75 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; -- for (j = 0; j < dev->dev->num_tx_queues; j++) { +- netdev = netdev_from_priv(port->dev); +- for (j = 0; j < netdev->num_tx_queues; j++) { - if (airoha_qdma_get_txq(qdma, j) != qid) + if (dev->qdma != qdma) continue; -- netif_wake_subqueue(dev->dev, j); -+ for (j = 0; j < dev->dev->num_tx_queues; j++) { +- netif_wake_subqueue(netdev, j); ++ netdev = netdev_from_priv(dev); ++ for (j = 0; j < netdev->num_tx_queues; j++) { + if (airoha_qdma_get_txq(qdma, j) != qid) + continue; + -+ netif_wake_subqueue(dev->dev, j); ++ netif_wake_subqueue(netdev, j); + } } } q->txq_stopped = false; -@@ -1903,11 +1898,9 @@ static int airoha_dev_open(struct net_de +@@ -1961,22 +1958,32 @@ static void airoha_update_hw_stats(struc + + static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) + { +- struct airoha_gdm_port *port = dev->port; + struct airoha_eth *eth = dev->eth; + int i; + + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { +- struct airoha_gdm_port *p = eth->ports[i]; +- struct net_device *netdev; ++ struct airoha_gdm_port *port = eth->ports[i]; ++ int j; + +- if (!p) ++ if (!port) + continue; + +- netdev = netdev_from_priv(p->dev); +- if (netdev->reg_state != NETREG_REGISTERED) +- continue; ++ for (j = 0; j < ARRAY_SIZE(port->devs); j++) { ++ struct airoha_gdm_dev *iter_dev = port->devs[j]; ++ struct net_device *netdev; ++ ++ if (!iter_dev || iter_dev == dev) ++ continue; ++ ++ if (iter_dev->qdma != dev->qdma) ++ continue; ++ ++ netdev = netdev_from_priv(iter_dev); ++ if (netdev->reg_state != NETREG_REGISTERED) ++ continue; + +- netdev_update_features(netdev); ++ netdev_update_features(netdev); ++ } + } + } + +@@ -2037,7 +2044,8 @@ static int airoha_dev_open(struct net_de GLOBAL_CFG_RX_DMA_EN_MASK); - atomic_inc(&qdma->users); + qdma->users++; -- if (port->id == AIROHA_GDM2_IDX && -- airoha_ppe_is_enabled(qdma->eth, 1)) { -- /* For PPE2 always use secondary cpu port. */ +- if (port->id == AIROHA_GDM2_IDX && airoha_ppe_is_enabled(eth, 1)) { + if (!airoha_is_lan_gdm_dev(dev) && -+ airoha_ppe_is_enabled(qdma->eth, 1)) ++ airoha_ppe_is_enabled(eth, 1)) { + /* For PPE2 always use secondary cpu port. */ pse_port = FE_PSE_PORT_PPE2; -- } - airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), - pse_port); - -@@ -2002,7 +1995,7 @@ static int airoha_set_gdm2_loopback(stru + } +@@ -2143,7 +2151,7 @@ static int airoha_set_gdm2_loopback(stru airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); @@ -232,7 +255,7 @@ Signed-off-by: Lorenzo Bianconi if (src_port < 0) return src_port; -@@ -2019,7 +2012,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -2160,7 +2168,7 @@ static int airoha_set_gdm2_loopback(stru airoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX); if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { @@ -241,7 +264,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask, __field_prep(mask, AIROHA_GDM2_IDX)); -@@ -2033,7 +2026,7 @@ static int airoha_dev_init(struct net_de +@@ -2174,7 +2182,7 @@ static int airoha_dev_init(struct net_de struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; struct airoha_eth *eth = dev->eth; @@ -250,7 +273,7 @@ Signed-off-by: Lorenzo Bianconi /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; -@@ -2056,8 +2049,8 @@ static int airoha_dev_init(struct net_de +@@ -2197,8 +2205,8 @@ static int airoha_dev_init(struct net_de break; } @@ -261,42 +284,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2222,20 +2215,26 @@ static int airoha_dev_set_features(struc - } else { - for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { - struct airoha_gdm_port *p = eth->ports[i]; -- struct airoha_gdm_dev *d; -+ int j; - - if (!p) - continue; - -- d = p->dev; -- if (d->qdma != qdma) -- continue; -+ for (j = 0; j < ARRAY_SIZE(p->devs); j++) { -+ struct airoha_gdm_dev *d = p->devs[j]; - -- if (d->dev == netdev) -- continue; -+ if (!d) -+ continue; - -- if (d->dev->features & NETIF_F_LRO) -- return 0; -+ if (d->qdma != qdma) -+ continue; -+ -+ if (d->dev == netdev) -+ continue; -+ -+ if (d->dev->features & NETIF_F_LRO) -+ return 0; -+ } - } - airoha_fe_lro_disable(eth, qdma_id); - } -@@ -2286,7 +2285,8 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2396,7 +2404,8 @@ static netdev_tx_t airoha_dev_xmit(struc } fport = airoha_get_fe_port(dev); @@ -306,7 +294,7 @@ Signed-off-by: Lorenzo Bianconi FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); q = &qdma->q_tx[qid]; -@@ -3222,12 +3222,15 @@ bool airoha_is_valid_gdm_dev(struct airo +@@ -3339,12 +3348,15 @@ bool airoha_is_valid_gdm_dev(struct airo for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -324,7 +312,7 @@ Signed-off-by: Lorenzo Bianconi } return false; -@@ -3351,10 +3354,11 @@ static int airoha_setup_phylink(struct n +@@ -3468,10 +3480,11 @@ static int airoha_setup_phylink(struct n static int airoha_alloc_gdm_device(struct airoha_eth *eth, struct airoha_gdm_port *port, @@ -338,15 +326,15 @@ Signed-off-by: Lorenzo Bianconi int err; netdev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*dev), -@@ -3372,7 +3376,6 @@ static int airoha_alloc_gdm_device(struc - netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; +@@ -3489,7 +3502,6 @@ static int airoha_alloc_gdm_device(struc + netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; netdev->features |= AIROHA_HW_FEATURES; netdev->vlan_features = AIROHA_HW_FEATURES; - netdev->dev.of_node = np; SET_NETDEV_DEV(netdev, eth->dev); /* reserve hw queues for HTB offloading */ -@@ -3390,11 +3393,25 @@ static int airoha_alloc_gdm_device(struc +@@ -3507,10 +3519,24 @@ static int airoha_alloc_gdm_device(struc netdev->dev_addr); } @@ -364,7 +352,6 @@ Signed-off-by: Lorenzo Bianconi + + netdev->dev.of_node = of_node_get(np); dev = netdev_priv(netdev); - dev->dev = netdev; dev->port = port; - port->dev = dev; dev->eth = eth; @@ -373,7 +360,7 @@ Signed-off-by: Lorenzo Bianconi #if defined(CONFIG_PCS_AIROHA) if (airhoa_is_phy_external(port)) { -@@ -3412,7 +3429,8 @@ static int airoha_alloc_gdm_port(struct +@@ -3528,7 +3554,8 @@ static int airoha_alloc_gdm_port(struct { const __be32 *id_ptr = of_get_property(np, "reg", NULL); struct airoha_gdm_port *port; @@ -383,7 +370,7 @@ Signed-off-by: Lorenzo Bianconi u32 id; if (!id_ptr) { -@@ -3440,15 +3458,51 @@ static int airoha_alloc_gdm_port(struct +@@ -3556,15 +3583,51 @@ static int airoha_alloc_gdm_port(struct u64_stats_init(&port->stats.syncp); spin_lock_init(&port->stats.lock); port->id = id; @@ -438,7 +425,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_register_gdm_devices(struct airoha_eth *eth) -@@ -3457,14 +3511,22 @@ static int airoha_register_gdm_devices(s +@@ -3573,14 +3636,22 @@ static int airoha_register_gdm_devices(s for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -448,7 +435,7 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; -- err = register_netdev(port->dev->dev); +- err = register_netdev(netdev_from_priv(port->dev)); - if (err) - return err; + for (j = 0; j < ARRAY_SIZE(port->devs); j++) { @@ -458,14 +445,14 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; + -+ err = register_netdev(dev->dev); ++ err = register_netdev(netdev_from_priv(dev)); + if (err) + return err; + } } set_bit(DEV_STATE_REGISTERED, ð->state); -@@ -3571,18 +3633,27 @@ error_napi_stop: +@@ -3687,15 +3758,19 @@ error_napi_stop: for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -476,30 +463,28 @@ Signed-off-by: Lorenzo Bianconi continue; - dev = port->dev; -- if (dev && dev->dev->reg_state == NETREG_REGISTERED) { +- if (dev) { +- struct net_device *netdev = netdev_from_priv(dev); + for (j = 0; j < ARRAY_SIZE(port->devs); j++) { + struct airoha_gdm_dev *dev = port->devs[j]; + struct net_device *netdev; + + if (!dev) + continue; -+ -+ netdev = dev->dev; -+ if (netdev->reg_state == NETREG_REGISTERED) { + ++ netdev = netdev_from_priv(dev); + if (netdev->reg_state == NETREG_REGISTERED) { #if defined(CONFIG_PCS_AIROHA) -- if (airhoa_is_phy_external(port)) -- phylink_destroy(dev->phylink); -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(dev->phylink); + if (airhoa_is_phy_external(port)) +@@ -3703,6 +3778,7 @@ error_napi_stop: #endif -- unregister_netdev(dev->dev); -+ unregister_netdev(netdev); -+ } + unregister_netdev(netdev); + } + of_node_put(netdev->dev.of_node); } airoha_metadata_dst_free(port); } -@@ -3604,19 +3675,26 @@ static void airoha_remove(struct platfor +@@ -3724,19 +3800,27 @@ static void airoha_remove(struct platfor for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -517,21 +502,23 @@ Signed-off-by: Lorenzo Bianconi + continue; + #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) - phylink_destroy(dev->phylink); +- if (airhoa_is_phy_external(port)) +- phylink_destroy(dev->phylink); ++ if (airhoa_is_phy_external(port)) ++ phylink_destroy(dev->phylink); #endif -- + - dev = port->dev; - if (dev) -- unregister_netdev(dev->dev); -+ netdev = dev->dev; +- unregister_netdev(netdev_from_priv(dev)); ++ netdev = netdev_from_priv(dev); + unregister_netdev(netdev); + of_node_put(netdev->dev.of_node); + } airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); -@@ -3678,6 +3756,39 @@ static u32 airoha_en7581_get_vip_port(st +@@ -3798,6 +3882,39 @@ static u32 airoha_en7581_get_vip_port(st return 0; } @@ -571,7 +558,7 @@ Signed-off-by: Lorenzo Bianconi static const char * const an7583_xsi_rsts_names[] = { "hsi0-mac", "hsi1-mac", -@@ -3726,6 +3837,36 @@ static u32 airoha_an7583_get_vip_port(st +@@ -3846,6 +3963,36 @@ static u32 airoha_an7583_get_vip_port(st return 0; } @@ -608,7 +595,7 @@ Signed-off-by: Lorenzo Bianconi static const struct airoha_eth_soc_data en7581_soc_data = { .version = 0x7581, .xsi_rsts_names = en7581_xsi_rsts_names, -@@ -3734,6 +3875,7 @@ static const struct airoha_eth_soc_data +@@ -3854,6 +4001,7 @@ static const struct airoha_eth_soc_data .ops = { .get_sport = airoha_en7581_get_sport, .get_vip_port = airoha_en7581_get_vip_port, @@ -616,7 +603,7 @@ Signed-off-by: Lorenzo Bianconi }, }; -@@ -3745,6 +3887,7 @@ static const struct airoha_eth_soc_data +@@ -3865,6 +4013,7 @@ static const struct airoha_eth_soc_data .ops = { .get_sport = airoha_an7583_get_sport, .get_vip_port = airoha_an7583_get_vip_port, @@ -634,17 +621,7 @@ Signed-off-by: Lorenzo Bianconi #define AIROHA_MAX_NUM_QDMA 2 #define AIROHA_MAX_NUM_IRQ_BANKS 4 #define AIROHA_MAX_DSA_PORTS 7 -@@ -552,8 +553,8 @@ struct airoha_qdma { - struct airoha_gdm_dev { - struct airoha_gdm_port *port; - struct airoha_qdma *qdma; -- struct net_device *dev; - struct airoha_eth *eth; -+ struct net_device *dev; - - #if defined(CONFIG_PCS_AIROHA) - struct phylink *phylink; -@@ -564,12 +565,13 @@ struct airoha_gdm_dev { +@@ -563,12 +564,13 @@ struct airoha_gdm_dev { /* qos stats counters */ u64 cpu_tx_packets; u64 fwd_tx_packets; @@ -660,7 +637,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_hw_stats stats; -@@ -605,6 +607,8 @@ struct airoha_eth_soc_data { +@@ -604,6 +606,8 @@ struct airoha_eth_soc_data { struct { int (*get_sport)(struct airoha_gdm_port *port, int nbq); u32 (*get_vip_port)(struct airoha_gdm_port *port, int nbq); diff --git a/target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch b/target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch index eafefba314..7dc33792bd 100644 --- a/target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch +++ b/target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch @@ -23,25 +23,27 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1859,8 +1859,8 @@ static int airoha_dev_open(struct net_de +@@ -1992,10 +1992,10 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; - u32 pse_port = FE_PSE_PORT_PPE1; - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -@@ -1888,10 +1888,20 @@ static int airoha_dev_open(struct net_de - airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), + /* HW LRO is configured on the QDMA and it is shared between + * all the devices using it. Refuse to open a second device on +@@ -2034,10 +2034,20 @@ static int airoha_dev_open(struct net_de + airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); -- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), +- airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), - GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, - FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | - FIELD_PREP(GDM_LONG_LEN_MASK, len)); -+ cur_len = airoha_fe_get(qdma->eth, REG_GDM_LEN_CFG(port->id), ++ cur_len = airoha_fe_get(eth, REG_GDM_LEN_CFG(port->id), + GDM_LONG_LEN_MASK); + if (!port->users || len > cur_len) { + /* Opening a sibling net_device with a larger MTU updates the @@ -49,7 +51,7 @@ Signed-off-by: Lorenzo Bianconi + * multiple net_devices with different MTUs to share the same + * GDM port. + */ -+ airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), ++ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), + GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, + FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | + FIELD_PREP(GDM_LONG_LEN_MASK, len)); @@ -58,7 +60,7 @@ Signed-off-by: Lorenzo Bianconi airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK | -@@ -1907,6 +1917,30 @@ static int airoha_dev_open(struct net_de +@@ -2060,6 +2070,30 @@ static int airoha_dev_open(struct net_de return 0; } @@ -75,7 +77,7 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; + -+ netdev = dev->dev; ++ netdev = netdev_from_priv(dev); + if (netif_running(netdev)) + len = max_t(u32, len, netdev->mtu); + } @@ -89,22 +91,21 @@ Signed-off-by: Lorenzo Bianconi static int airoha_dev_stop(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -1919,8 +1953,12 @@ static int airoha_dev_stop(struct net_de +@@ -2073,8 +2107,11 @@ static int airoha_dev_stop(struct net_de for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); -- airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), +- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), - FE_PSE_PORT_DROP); + if (--port->users) -+ airoha_set_port_mtu(dev->eth, port); ++ airoha_set_port_mtu(eth, port); + else -+ airoha_set_gdm_port_fwd_cfg(qdma->eth, -+ REG_GDM_FWD_CFG(port->id), ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); - if (atomic_dec_and_test(&qdma->users)) { + if (!--qdma->users) { airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, -@@ -2082,13 +2120,10 @@ static int airoha_dev_change_mtu(struct +@@ -2238,13 +2275,10 @@ static int airoha_dev_change_mtu(struct { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -122,7 +123,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -572,6 +572,7 @@ struct airoha_gdm_dev { +@@ -571,6 +571,7 @@ struct airoha_gdm_dev { struct airoha_gdm_port { struct airoha_gdm_dev *devs[AIROHA_MAX_NUM_GDM_DEVS]; int id; diff --git a/target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch b/target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch index 9451c6fcee..a21fa3f05b 100644 --- a/target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch +++ b/target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch @@ -29,14 +29,16 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2059,36 +2059,80 @@ static int airoha_set_gdm2_loopback(stru +@@ -2214,36 +2214,81 @@ static int airoha_set_gdm2_loopback(stru return 0; } -static int airoha_dev_init(struct net_device *netdev) +static struct airoha_gdm_dev * +airoha_get_wan_gdm_dev(struct airoha_eth *eth) -+{ + { +- struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_gdm_port *port = dev->port; + int i; + + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { @@ -58,15 +60,14 @@ Signed-off-by: Lorenzo Bianconi +} + +static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev) - { -- struct airoha_gdm_dev *dev = netdev_priv(netdev); -- struct airoha_gdm_port *port = dev->port; ++{ ++ struct net_device *netdev = netdev_from_priv(dev); struct airoha_eth *eth = dev->eth; int ppe_id; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; - dev->dev->irq = dev->qdma->irq_banks[0].irq; + netdev->irq = dev->qdma->irq_banks[0].irq; - airoha_set_macaddr(dev, netdev->dev_addr); + + ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1); @@ -138,7 +139,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev { struct airoha_gdm_port *port; struct airoha_qdma *qdma; -@@ -566,6 +570,7 @@ struct airoha_gdm_dev { +@@ -565,6 +569,7 @@ struct airoha_gdm_dev { u64 cpu_tx_packets; u64 fwd_tx_packets; @@ -146,7 +147,7 @@ Signed-off-by: Lorenzo Bianconi int nbq; }; -@@ -672,13 +677,7 @@ static inline u16 airoha_qdma_get_txq(st +@@ -671,13 +676,7 @@ static inline u16 airoha_qdma_get_txq(st static inline bool airoha_is_lan_gdm_dev(struct airoha_gdm_dev *dev) { diff --git a/target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch b/target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch index be9382c9eb..553bd3cbf5 100644 --- a/target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch +++ b/target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch @@ -30,7 +30,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -80,20 +80,74 @@ static bool airhoa_is_phy_external(struc +@@ -81,20 +81,76 @@ static bool airhoa_is_phy_external(struc } #endif @@ -66,7 +66,7 @@ Signed-off-by: Lorenzo Bianconi + airoha_is_lan_gdm_dev(dev)) + continue; + -+ netdev = iter_dev->dev; ++ netdev = netdev_from_priv(iter_dev); + if (netdev->reg_state != NETREG_REGISTERED) + continue; + @@ -85,9 +85,11 @@ Signed-off-by: Lorenzo Bianconi + * the same for each net_device with the same LAN/WAN + * configuration. + */ ++ struct net_device *netdev = netdev_from_priv(dev); ++ + dev_warn(eth->dev, + "%s: wrong mac addr, MSBs must be %02x:%02x:%02x\n", -+ dev->dev->name, ref_addr[0], ref_addr[1], ++ netdev->name, ref_addr[0], ref_addr[1], + ref_addr[2]); + dev_warn(eth->dev, "FE hw forwarding won't work properly\n"); + @@ -103,15 +105,15 @@ Signed-off-by: Lorenzo Bianconi - airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); + airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), lmin); + airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), lmax); ++ ++ airoha_ppe_init_upd_mem(dev, addr); - airoha_ppe_init_upd_mem(dev); -+ airoha_ppe_init_upd_mem(dev, addr); -+ + return 0; } static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, -@@ -1986,13 +2040,18 @@ static int airoha_dev_stop(struct net_de +@@ -2141,13 +2197,18 @@ static int airoha_dev_stop(struct net_de static int airoha_dev_set_macaddr(struct net_device *netdev, void *p) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -134,7 +136,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -713,7 +713,7 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -712,7 +712,7 @@ void airoha_ppe_check_skb(struct airoha_ int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data); int airoha_ppe_init(struct airoha_eth *eth); void airoha_ppe_deinit(struct airoha_eth *eth); @@ -152,8 +154,8 @@ Signed-off-by: Lorenzo Bianconi -void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev) +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev, const u8 *addr) { +- struct net_device *netdev = netdev_from_priv(dev); struct airoha_gdm_port *port = dev->port; -- struct net_device *netdev = dev->dev; struct airoha_eth *eth = dev->eth; - const u8 *addr = netdev->dev_addr; u32 val; diff --git a/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch b/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch index aca2ae2576..92ce90e7ca 100644 --- a/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch +++ b/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch @@ -17,7 +17,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2056,7 +2056,7 @@ static int airoha_dev_set_macaddr(struct +@@ -2213,7 +2213,7 @@ static int airoha_dev_set_macaddr(struct return 0; } @@ -26,7 +26,7 @@ Signed-off-by: Lorenzo Bianconi { struct airoha_gdm_port *port = dev->port; struct airoha_eth *eth = dev->eth; -@@ -2188,7 +2188,7 @@ static int airoha_dev_init(struct net_de +@@ -2346,7 +2346,7 @@ static int airoha_dev_init(struct net_de (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)) { int err; diff --git a/target/linux/airoha/patches-6.18/920-12-net-airoha-Add-ethtool-priv_flags-callbacks.patch b/target/linux/airoha/patches-6.18/920-12-net-airoha-Add-ethtool-priv_flags-callbacks.patch deleted file mode 100644 index f55b97253f..0000000000 --- a/target/linux/airoha/patches-6.18/920-12-net-airoha-Add-ethtool-priv_flags-callbacks.patch +++ /dev/null @@ -1,246 +0,0 @@ -From e928621a0bbd010b75624c77105ce31f2b8d2faf Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: -From: Lorenzo Bianconi -Date: Sat, 13 Dec 2025 09:45:09 +0100 -Subject: [PATCH 12/13] net: airoha: Add ethtool priv_flags callbacks - -Introduce ethtool priv_flags callbacks in order to allow the user to -select if the configured device will be used as hw lan or wan and enable -or disable gdm2 loopback (used for hw QoS). - -Tested-by: Madhur Agrawal -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 173 ++++++++++++++++++++++ - drivers/net/ethernet/airoha/airoha_regs.h | 1 + - 2 files changed, 174 insertions(+) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1916,6 +1916,11 @@ static int airoha_dev_open(struct net_de - u32 cur_len, pse_port = FE_PSE_PORT_PPE1; - struct airoha_qdma *qdma = dev->qdma; - -+ if (port->id == AIROHA_GDM2_IDX && airoha_is_lan_gdm_dev(dev)) { -+ /* GDM2 can be used just as wan */ -+ return -EBUSY; -+ } -+ - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0); -@@ -2118,6 +2123,45 @@ static int airoha_enable_gdm2_loopback(s - return 0; - } - -+static int airoha_disable_gdm2_loopback(struct airoha_gdm_dev *dev) -+{ -+ struct airoha_eth *eth = dev->eth; -+ int i, src_port; -+ u32 pse_port; -+ -+ src_port = eth->soc->ops.get_sport(dev->port, dev->nbq); -+ if (src_port < 0) -+ return src_port; -+ -+ airoha_fe_clear(eth, -+ REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)), -+ SP_CPORT_MASK(src_port & SP_CPORT_DFT_MASK)); -+ -+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), -+ FE_PSE_PORT_DROP); -+ airoha_fe_clear(eth, REG_GDM_LPBK_CFG(AIROHA_GDM2_IDX), -+ LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK); -+ pse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2 -+ : FE_PSE_PORT_PPE1; -+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), -+ pse_port); -+ -+ airoha_fe_rmw(eth, REG_FE_WAN_PORT, WAN0_MASK, -+ FIELD_PREP(WAN0_MASK, AIROHA_GDM2_IDX)); -+ -+ for (i = 0; i < eth->soc->num_ppe; i++) -+ airoha_fe_clear(eth, REG_PPE_DFT_CPORT(i, AIROHA_GDM2_IDX), -+ DFT_CPORT_MASK(AIROHA_GDM2_IDX)); -+ -+ /* Enable VIP and IFC for GDM2 */ -+ airoha_fe_set(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); -+ airoha_fe_set(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); -+ -+ airoha_fe_wr(eth, REG_SRC_PORT_FC_MAP6, FC_MAP6_DEF_VALUE); -+ -+ return 0; -+} -+ - static struct airoha_gdm_dev * - airoha_get_wan_gdm_dev(struct airoha_eth *eth) - { -@@ -2522,6 +2566,80 @@ error: - return NETDEV_TX_OK; - } - -+struct airoha_ethool_priv_flags { -+ char name[ETH_GSTRING_LEN]; -+ int (*handler)(struct net_device *netdev, u32 flags); -+}; -+ -+static int airoha_dev_set_wan_flag(struct net_device *netdev, u32 flags) -+{ -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ struct airoha_gdm_port *port = dev->port; -+ struct airoha_eth *eth = dev->eth; -+ -+ if (!((dev->flags ^ flags) & AIROHA_PRIV_F_WAN)) -+ return 0; -+ -+ if (netif_running(netdev)) -+ return -EBUSY; -+ -+ if (flags & AIROHA_PRIV_F_WAN) { -+ struct airoha_gdm_dev *wan_dev; -+ -+ /* Verify the wan device is not already configured */ -+ wan_dev = airoha_get_wan_gdm_dev(eth); -+ if (wan_dev && wan_dev != dev) -+ return -EBUSY; -+ -+ switch (port->id) { -+ case AIROHA_GDM2_IDX: -+ dev->flags |= AIROHA_PRIV_F_WAN; -+ airoha_dev_set_qdma(dev); -+ break; -+ case AIROHA_GDM3_IDX: -+ case AIROHA_GDM4_IDX: { -+ int err; -+ -+ dev->flags |= AIROHA_PRIV_F_WAN; -+ airoha_dev_set_qdma(dev); -+ -+ err = airoha_enable_gdm2_loopback(dev); -+ if (err) { -+ dev->flags &= ~AIROHA_PRIV_F_WAN; -+ return err; -+ } -+ break; -+ } -+ default: -+ return -EOPNOTSUPP; -+ } -+ } else { -+ switch (port->id) { -+ case AIROHA_GDM3_IDX: -+ case AIROHA_GDM4_IDX: { -+ int err; -+ -+ err = airoha_disable_gdm2_loopback(dev); -+ if (err) -+ return err; -+ break; -+ } -+ default: -+ break; -+ } -+ -+ dev->flags &= ~AIROHA_PRIV_F_WAN; -+ airoha_dev_set_qdma(dev); -+ } -+ -+ return airoha_set_macaddr(dev, netdev->dev_addr); -+} -+ -+static const struct airoha_ethool_priv_flags airoha_eth_priv_flags[] = { -+ { "wan", airoha_dev_set_wan_flag }, -+}; -+#define AIROHA_PRIV_FLAGS_STR_LEN ARRAY_SIZE(airoha_eth_priv_flags) -+ - static void airoha_ethtool_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) - { -@@ -2530,6 +2648,7 @@ static void airoha_ethtool_get_drvinfo(s - - strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver)); - strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info)); -+ info->n_priv_flags = AIROHA_PRIV_FLAGS_STR_LEN; - } - - static void airoha_ethtool_get_mac_stats(struct net_device *netdev, -@@ -2594,6 +2713,56 @@ airoha_ethtool_get_rmon_stats(struct net - } while (u64_stats_fetch_retry(&port->stats.syncp, start)); - } - -+static int airoha_ethtool_set_priv_flags(struct net_device *netdev, u32 flags) -+{ -+ int i; -+ -+ for (i = 0; i < AIROHA_PRIV_FLAGS_STR_LEN; i++) { -+ int err; -+ -+ if (!airoha_eth_priv_flags[i].handler) -+ continue; -+ -+ err = airoha_eth_priv_flags[i].handler(netdev, flags); -+ if (err) -+ return err; -+ } -+ -+ return 0; -+} -+ -+static u32 airoha_ethtool_get_priv_flags(struct net_device *netdev) -+{ -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ -+ return dev->flags; -+} -+ -+static int airoha_ethtool_get_sset_count(struct net_device *netdev, int sset) -+{ -+ switch (sset) { -+ case ETH_SS_PRIV_FLAGS: -+ return AIROHA_PRIV_FLAGS_STR_LEN; -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+ -+static void airoha_ethtool_get_strings(struct net_device *netdev, -+ u32 stringset, u8 *data) -+{ -+ int i; -+ -+ switch (stringset) { -+ case ETH_SS_PRIV_FLAGS: -+ for (i = 0; i < AIROHA_PRIV_FLAGS_STR_LEN; i++) -+ ethtool_puts(&data, airoha_eth_priv_flags[i].name); -+ break; -+ default: -+ break; -+ } -+} -+ - static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, - int channel, enum tx_sched_mode mode, - const u16 *weights, u8 n_weights) -@@ -3315,6 +3484,10 @@ static const struct ethtool_ops airoha_e - .get_rmon_stats = airoha_ethtool_get_rmon_stats, - .get_link_ksettings = phy_ethtool_get_link_ksettings, - .get_link = ethtool_op_get_link, -+ .set_priv_flags = airoha_ethtool_set_priv_flags, -+ .get_priv_flags = airoha_ethtool_get_priv_flags, -+ .get_sset_count = airoha_ethtool_get_sset_count, -+ .get_strings = airoha_ethtool_get_strings, - }; - - static void airoha_mac_config(struct phylink_config *config, unsigned int mode, ---- a/drivers/net/ethernet/airoha/airoha_regs.h -+++ b/drivers/net/ethernet/airoha/airoha_regs.h -@@ -402,6 +402,7 @@ - - #define REG_SRC_PORT_FC_MAP6 0x2298 - #define FC_ID_OF_SRC_PORT_MASK(_n) GENMASK(4 + ((_n) << 3), ((_n) << 3)) -+#define FC_MAP6_DEF_VALUE 0x1b1a1918 - - #define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4 - diff --git a/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch b/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch new file mode 100644 index 0000000000..2c16f2ac02 --- /dev/null +++ b/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch @@ -0,0 +1,668 @@ +From e928621a0bbd010b75624c77105ce31f2b8d2faf Mon Sep 17 00:00:00 2001 +Message-ID: +In-Reply-To: +References: +From: Lorenzo Bianconi +Date: Sat, 13 Dec 2025 09:45:09 +0100 +Subject: [PATCH 12/13] net: airoha: Add ethtool priv_flags callbacks + +Introduce ethtool priv_flags callbacks in order to allow the user to +select if the configured device will be used as hw lan or wan and enable +or disable gdm2 loopback (used for hw QoS). + +Tested-by: Madhur Agrawal +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 173 ++++++++++++++++++++++ + drivers/net/ethernet/airoha/airoha_regs.h | 1 + + 2 files changed, 174 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -540,7 +540,7 @@ static bool airoha_fe_lro_is_enabled(str + + static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) + { +- struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_qdma *qdma = airoha_qdma_deref(dev); + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; + int i, lro_queue_index = 0; +@@ -1158,7 +1158,7 @@ static void airoha_qdma_wake_netdev_txqs + if (!dev) + continue; + +- if (dev->qdma != qdma) ++ if (rcu_access_pointer(dev->qdma) != qdma) + continue; + + netdev = netdev_from_priv(dev); +@@ -2031,7 +2031,8 @@ static void airoha_update_netdev_feature + if (!iter_dev || iter_dev == dev) + continue; + +- if (iter_dev->qdma != dev->qdma) ++ if (rcu_access_pointer(iter_dev->qdma) != ++ rcu_access_pointer(dev->qdma)) + continue; + + netdev = netdev_from_priv(iter_dev); +@@ -2043,20 +2044,57 @@ static void airoha_update_netdev_feature + } + } + ++static void airoha_qdma_start(struct airoha_qdma *qdma) ++{ ++ airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, ++ GLOBAL_CFG_TX_DMA_EN_MASK | ++ GLOBAL_CFG_RX_DMA_EN_MASK); ++ qdma->users++; ++} ++ ++static void airoha_qdma_stop(struct airoha_qdma *qdma) ++{ ++ u32 status; ++ ++ if (--qdma->users) ++ return; ++ ++ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, ++ GLOBAL_CFG_TX_DMA_EN_MASK | ++ GLOBAL_CFG_RX_DMA_EN_MASK); ++ ++ if (read_poll_timeout(airoha_qdma_rr, status, ++ !(status & (GLOBAL_CFG_TX_DMA_BUSY_MASK | ++ GLOBAL_CFG_RX_DMA_BUSY_MASK)), ++ USEC_PER_MSEC, 50 * USEC_PER_MSEC, true, ++ qdma, REG_QDMA_GLOBAL_CFG)) ++ dev_warn(qdma->eth->dev, "QDMA DMA engine busy timeout\n"); ++ ++ for (int i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { ++ if (!qdma->q_tx[i].ndesc) ++ continue; ++ ++ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); ++ } ++} ++ + static int airoha_dev_open(struct net_device *netdev) + { + int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; +- struct airoha_qdma *qdma = dev->qdma; +- struct airoha_eth *eth = qdma->eth; +- int qdma_id = qdma - ð->qdma[0]; ++ struct airoha_eth *eth = dev->eth; ++ struct airoha_qdma *qdma; ++ int qdma_id; + + /* HW LRO is configured on the QDMA and it is shared between + * all the devices using it. Refuse to open a second device on + * the same QDMA if LRO is enabled on any device sharing it. + */ ++ qdma = airoha_qdma_deref(dev); ++ qdma_id = qdma - ð->qdma[0]; ++ + if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { + netdev_warn(netdev, "required to disable HW GRO on QDMA%d\n", + qdma_id); +@@ -2105,10 +2143,7 @@ static int airoha_dev_open(struct net_de + } + port->users++; + +- airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, +- GLOBAL_CFG_TX_DMA_EN_MASK | +- GLOBAL_CFG_RX_DMA_EN_MASK); +- qdma->users++; ++ airoha_qdma_start(qdma); + + if (!airoha_is_lan_gdm_dev(dev) && + airoha_ppe_is_enabled(eth, 1)) { +@@ -2154,8 +2189,7 @@ static int airoha_dev_stop(struct net_de + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; +- struct airoha_qdma *qdma = dev->qdma; +- struct airoha_eth *eth = qdma->eth; ++ struct airoha_qdma *qdma; + int i; + + netif_tx_disable(netdev); +@@ -2163,25 +2197,14 @@ static int airoha_dev_stop(struct net_de + for (i = 0; i < netdev->num_tx_queues; i++) + netdev_tx_reset_subqueue(netdev, i); + ++ qdma = airoha_qdma_deref(dev); + if (--port->users) +- airoha_set_port_mtu(eth, port); ++ airoha_set_port_mtu(dev->eth, port); + else +- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), ++ airoha_set_gdm_port_fwd_cfg(qdma->eth, ++ REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); +- +- if (!--qdma->users) { +- airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, +- GLOBAL_CFG_TX_DMA_EN_MASK | +- GLOBAL_CFG_RX_DMA_EN_MASK); +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { +- if (!qdma->q_tx[i].ndesc) +- continue; +- +- airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); +- } +- } +- ++ airoha_qdma_stop(qdma); + airoha_update_netdev_features(dev); + + #if defined(CONFIG_PCS_AIROHA) +@@ -2275,6 +2298,53 @@ static int airoha_enable_gdm2_loopback(s + return 0; + } + ++static int airoha_disable_gdm2_loopback(struct airoha_gdm_dev *dev) ++{ ++ struct airoha_gdm_port *port = dev->port; ++ struct airoha_eth *eth = dev->eth; ++ int i, src_port; ++ u32 pse_port; ++ ++ src_port = eth->soc->ops.get_sport(dev->port, dev->nbq); ++ if (src_port < 0) ++ return src_port; ++ ++ airoha_fe_clear(eth, ++ REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)), ++ SP_CPORT_MASK(src_port & SP_CPORT_DFT_MASK)); ++ ++ airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), ++ GDM_STRIP_CRC_MASK); ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), ++ FE_PSE_PORT_DROP); ++ airoha_fe_clear(eth, REG_GDM_LPBK_CFG(AIROHA_GDM2_IDX), ++ LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK); ++ pse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2 ++ : FE_PSE_PORT_PPE1; ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), ++ pse_port); ++ ++ airoha_fe_rmw(eth, REG_FE_WAN_PORT, WAN0_MASK, ++ FIELD_PREP(WAN0_MASK, AIROHA_GDM2_IDX)); ++ ++ for (i = 0; i < eth->soc->num_ppe; i++) ++ airoha_fe_clear(eth, REG_PPE_DFT_CPORT(i, AIROHA_GDM2_IDX), ++ DFT_CPORT_MASK(AIROHA_GDM2_IDX)); ++ ++ /* Enable VIP and IFC for GDM2 */ ++ airoha_fe_set(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); ++ airoha_fe_set(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); ++ ++ if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { ++ u32 mask = FC_ID_OF_SRC_PORT_MASK(dev->nbq); ++ ++ airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask, ++ FC_MAP6_DEF_VALUE & mask); ++ } ++ ++ return 0; ++} ++ + static struct airoha_gdm_dev * + airoha_get_wan_gdm_dev(struct airoha_eth *eth) + { +@@ -2301,15 +2371,30 @@ airoha_get_wan_gdm_dev(struct airoha_eth + static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev) + { + struct net_device *netdev = netdev_from_priv(dev); ++ struct airoha_qdma *cur_qdma, *qdma; + struct airoha_eth *eth = dev->eth; + int ppe_id; + + /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ +- dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; +- netdev->irq = dev->qdma->irq_banks[0].irq; ++ qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; ++ cur_qdma = airoha_qdma_deref(dev); ++ if (netif_running(netdev)) ++ airoha_qdma_start(qdma); ++ ++ rcu_assign_pointer(dev->qdma, qdma); ++ netdev->irq = qdma->irq_banks[0].irq; + + ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1); + airoha_ppe_set_cpu_port(dev, ppe_id, airoha_get_fe_port(dev)); ++ ++ if (!cur_qdma) ++ return; ++ ++ synchronize_rcu(); ++ netif_tx_wake_all_queues(netdev); ++ ++ if (netif_running(netdev)) ++ airoha_qdma_stop(cur_qdma); + } + + static int airoha_dev_init(struct net_device *netdev) +@@ -2473,8 +2558,9 @@ static netdev_features_t airoha_dev_fix_ + netdev_features_t features) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_qdma *qdma; + ++ qdma = airoha_qdma_deref(dev); + if (qdma->users > 1) + features &= ~NETIF_F_GRO_HW; + +@@ -2486,9 +2572,8 @@ static int airoha_dev_set_features(struc + { + netdev_features_t diff = netdev->features ^ features; + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; +- struct airoha_eth *eth = qdma->eth; +- int qdma_id = qdma - ð->qdma[0]; ++ struct airoha_qdma *qdma = airoha_qdma_deref(dev); ++ int qdma_id = qdma - &dev->eth->qdma[0]; + + if (!(diff & NETIF_F_GRO_HW)) + return 0; +@@ -2496,7 +2581,7 @@ static int airoha_dev_set_features(struc + if (features & NETIF_F_GRO_HW) + airoha_dev_lro_enable(dev); + else +- airoha_fe_lro_disable(eth, qdma_id); ++ airoha_fe_lro_disable(dev->eth, qdma_id); + + return 0; + } +@@ -2505,9 +2590,9 @@ static netdev_tx_t airoha_dev_xmit(struc + struct net_device *netdev) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; + u32 nr_frags, tag, msg0, msg1, len; + struct airoha_queue_entry *e; ++ struct airoha_qdma *qdma; + struct netdev_queue *txq; + struct airoha_queue *q; + LIST_HEAD(tx_list); +@@ -2516,6 +2601,8 @@ static netdev_tx_t airoha_dev_xmit(struc + u16 index; + u8 fport; + ++ rcu_read_lock(); ++ qdma = rcu_dereference(dev->qdma); + qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb)); + tag = airoha_get_dsa_tag(skb, netdev); + +@@ -2562,6 +2649,8 @@ static netdev_tx_t airoha_dev_xmit(struc + netif_tx_stop_queue(txq); + q->txq_stopped = true; + spin_unlock_bh(&q->lock); ++ rcu_read_unlock(); ++ + return NETDEV_TX_BUSY; + } + +@@ -2624,6 +2713,7 @@ static netdev_tx_t airoha_dev_xmit(struc + FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); + + spin_unlock_bh(&q->lock); ++ rcu_read_unlock(); + + return NETDEV_TX_OK; + +@@ -2639,6 +2729,7 @@ error_unmap: + error: + dev_kfree_skb_any(skb); + netdev->stats.tx_dropped++; ++ rcu_read_unlock(); + + return NETDEV_TX_OK; + } +@@ -2720,17 +2811,19 @@ static int airoha_qdma_set_chan_tx_sched + const u16 *weights, u8 n_weights) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_qdma *qdma; + int i; + ++ qdma = airoha_qdma_deref(dev); + for (i = 0; i < AIROHA_NUM_TX_RING; i++) +- airoha_qdma_clear(dev->qdma, REG_QUEUE_CLOSE_CFG(channel), ++ airoha_qdma_clear(qdma, REG_QUEUE_CLOSE_CFG(channel), + TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i)); + + for (i = 0; i < n_weights; i++) { + u32 status; + int err; + +- airoha_qdma_wr(dev->qdma, REG_TXWRR_WEIGHT_CFG, ++ airoha_qdma_wr(qdma, REG_TXWRR_WEIGHT_CFG, + TWRR_RW_CMD_MASK | + FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | + FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | +@@ -2738,12 +2831,12 @@ static int airoha_qdma_set_chan_tx_sched + err = read_poll_timeout(airoha_qdma_rr, status, + status & TWRR_RW_CMD_DONE, + USEC_PER_MSEC, 10 * USEC_PER_MSEC, +- true, dev->qdma, REG_TXWRR_WEIGHT_CFG); ++ true, qdma, REG_TXWRR_WEIGHT_CFG); + if (err) + return err; + } + +- airoha_qdma_rmw(dev->qdma, REG_CHAN_QOS_MODE(channel >> 3), ++ airoha_qdma_rmw(qdma, REG_CHAN_QOS_MODE(channel >> 3), + CHAN_QOS_MODE_MASK(channel), + __field_prep(CHAN_QOS_MODE_MASK(channel), mode)); + +@@ -2807,13 +2900,15 @@ static int airoha_qdma_get_tx_ets_stats( + struct tc_ets_qopt_offload *opt) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; ++ u64 cpu_tx_packets, fwd_tx_packets, tx_packets; ++ struct airoha_qdma *qdma; + +- u64 cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel << 1)); +- u64 fwd_tx_packets = airoha_qdma_rr(qdma, +- REG_CNTR_VAL((channel << 1) + 1)); +- u64 tx_packets = (cpu_tx_packets - dev->cpu_tx_packets) + +- (fwd_tx_packets - dev->fwd_tx_packets); ++ qdma = airoha_qdma_deref(dev); ++ cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel << 1)); ++ fwd_tx_packets = airoha_qdma_rr(qdma, ++ REG_CNTR_VAL((channel << 1) + 1)); ++ tx_packets = (cpu_tx_packets - dev->cpu_tx_packets) + ++ (fwd_tx_packets - dev->fwd_tx_packets); + + _bstats_update(opt->stats.bstats, 0, tx_packets); + dev->cpu_tx_packets = cpu_tx_packets; +@@ -3073,16 +3168,18 @@ static int airoha_qdma_set_tx_rate_limit + u32 bucket_size) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_qdma *qdma; + int i, err; + ++ qdma = airoha_qdma_deref(dev); + for (i = 0; i <= TRTCM_PEAK_MODE; i++) { +- err = airoha_qdma_set_trtcm_config(dev->qdma, channel, ++ err = airoha_qdma_set_trtcm_config(qdma, channel, + REG_EGRESS_TRTCM_CFG, i, + !!rate, TRTCM_METER_MODE); + if (err) + return err; + +- err = airoha_qdma_set_trtcm_token_bucket(dev->qdma, channel, ++ err = airoha_qdma_set_trtcm_token_bucket(qdma, channel, + REG_EGRESS_TRTCM_CFG, + i, rate, bucket_size); + if (err) +@@ -3118,11 +3215,12 @@ static int airoha_tc_htb_alloc_leaf_queu + u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; + int err, num_tx_queues = netdev->real_num_tx_queues; + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_qdma *qdma; + + /* Here we need to check the requested QDMA channel is not already + * in use by another net_device running on the same QDMA block. + */ ++ qdma = airoha_qdma_deref(dev); + if (test_and_set_bit(channel, qdma->qos_channel_map)) { + NL_SET_ERR_MSG_MOD(opt->extack, + "qdma qos channel already in use"); +@@ -3156,7 +3254,7 @@ static int airoha_qdma_set_rx_meter(stru + u32 rate, u32 bucket_size, + enum trtcm_unit_type unit_type) + { +- struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_qdma *qdma = airoha_qdma_deref(dev); + int i; + + for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { +@@ -3330,11 +3428,12 @@ static int airoha_dev_setup_tc_block(str + static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); +- struct airoha_qdma *qdma = dev->qdma; ++ struct airoha_qdma *qdma; + + netif_set_real_num_tx_queues(netdev, netdev->real_num_tx_queues - 1); + airoha_qdma_set_tx_rate_limit(netdev, queue + 1, 0, 0); + ++ qdma = airoha_qdma_deref(dev); + clear_bit(queue, qdma->qos_channel_map); + clear_bit(queue, dev->qos_sq_bmap); + } +@@ -3355,6 +3454,95 @@ static int airoha_tc_htb_delete_leaf_que + return 0; + } + ++static void airoha_disable_qos_for_gdm34(struct net_device *netdev) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_gdm_port *port = dev->port; ++ int err; ++ ++ if (port->id != AIROHA_GDM3_IDX && ++ port->id != AIROHA_GDM4_IDX) ++ return; ++ ++ err = airoha_disable_gdm2_loopback(dev); ++ if (err) ++ netdev_warn(netdev, ++ "failed disabling GDM2 loopback: %d\n", err); ++ ++ dev->flags &= ~AIROHA_PRIV_F_WAN; ++ airoha_dev_set_qdma(dev); ++ ++ airoha_set_macaddr(dev, netdev->dev_addr); ++ if (netif_running(netdev)) ++ airoha_set_gdm_port_fwd_cfg(dev->eth, ++ REG_GDM_FWD_CFG(port->id), ++ FE_PSE_PORT_PPE1); ++} ++ ++static int airoha_enable_qos_for_gdm34(struct net_device *netdev, ++ struct netlink_ext_ack *extack) ++{ ++ struct airoha_gdm_dev *wan_dev, *dev = netdev_priv(netdev); ++ struct airoha_gdm_port *port = dev->port; ++ struct airoha_eth *eth = dev->eth; ++ int err = -EBUSY; ++ ++ if (port->id != AIROHA_GDM3_IDX && ++ port->id != AIROHA_GDM4_IDX) { ++ /* HW QoS is always supported by GDM1 and GDM2 */ ++ return 0; ++ } ++ ++ if (!airoha_is_lan_gdm_dev(dev)) /* Already enabled */ ++ return 0; ++ ++ mutex_lock(&flow_offload_mutex); ++ ++ wan_dev = airoha_get_wan_gdm_dev(eth); ++ if (wan_dev) { ++ if ((wan_dev->flags & AIROHA_PRIV_F_QOS) || ++ wan_dev->port->id == AIROHA_GDM2_IDX) { ++ NL_SET_ERR_MSG_MOD(extack, ++ "QoS configured for WAN device"); ++ goto error_unlock; ++ } ++ airoha_disable_qos_for_gdm34(netdev_from_priv(wan_dev)); ++ } ++ ++ dev->flags |= AIROHA_PRIV_F_WAN; ++ airoha_dev_set_qdma(dev); ++ err = airoha_enable_gdm2_loopback(dev); ++ if (err) ++ goto error_disable_wan; ++ ++ err = airoha_set_macaddr(dev, netdev->dev_addr); ++ if (err) ++ goto error_disable_loopback; ++ ++ if (netif_running(netdev)) { ++ u32 pse_port; ++ ++ pse_port = airoha_ppe_is_enabled(eth, 1) ? FE_PSE_PORT_PPE2 ++ : FE_PSE_PORT_PPE1; ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), ++ pse_port); ++ } ++ ++ mutex_unlock(&flow_offload_mutex); ++ ++ return 0; ++ ++error_disable_loopback: ++ airoha_disable_gdm2_loopback(dev); ++error_disable_wan: ++ dev->flags &= ~AIROHA_PRIV_F_WAN; ++ airoha_dev_set_qdma(dev); ++error_unlock: ++ mutex_unlock(&flow_offload_mutex); ++ ++ return err; ++} ++ + static int airoha_tc_htb_destroy(struct net_device *netdev) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); +@@ -3363,6 +3551,8 @@ static int airoha_tc_htb_destroy(struct + for_each_set_bit(q, dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS) + airoha_tc_remove_htb_queue(netdev, q); + ++ dev->flags &= ~AIROHA_PRIV_F_QOS; ++ + return 0; + } + +@@ -3382,24 +3572,33 @@ static int airoha_tc_get_htb_get_leaf_qu + return 0; + } + +-static int airoha_tc_setup_qdisc_htb(struct net_device *dev, ++static int airoha_tc_setup_qdisc_htb(struct net_device *netdev, + struct tc_htb_qopt_offload *opt) + { + switch (opt->command) { +- case TC_HTB_CREATE: ++ case TC_HTB_CREATE: { ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ int err; ++ ++ err = airoha_enable_qos_for_gdm34(netdev, opt->extack); ++ if (err) ++ return err; ++ ++ dev->flags |= AIROHA_PRIV_F_QOS; + break; ++ } + case TC_HTB_DESTROY: +- return airoha_tc_htb_destroy(dev); ++ return airoha_tc_htb_destroy(netdev); + case TC_HTB_NODE_MODIFY: +- return airoha_tc_htb_modify_queue(dev, opt); ++ return airoha_tc_htb_modify_queue(netdev, opt); + case TC_HTB_LEAF_ALLOC_QUEUE: +- return airoha_tc_htb_alloc_leaf_queue(dev, opt); ++ return airoha_tc_htb_alloc_leaf_queue(netdev, opt); + case TC_HTB_LEAF_DEL: + case TC_HTB_LEAF_DEL_LAST: + case TC_HTB_LEAF_DEL_LAST_FORCE: +- return airoha_tc_htb_delete_leaf_queue(dev, opt); ++ return airoha_tc_htb_delete_leaf_queue(netdev, opt); + case TC_HTB_LEAF_QUERY_QUEUE: +- return airoha_tc_get_htb_get_leaf_queue(dev, opt); ++ return airoha_tc_get_htb_get_leaf_queue(netdev, opt); + default: + return -EOPNOTSUPP; + } +@@ -3509,8 +3708,8 @@ static void airoha_mac_link_up(struct ph + { + struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, + phylink_config); ++ struct airoha_qdma *qdma = airoha_qdma_deref(dev); + struct airoha_gdm_port *port = dev->port; +- struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; + u32 frag_size_tx, frag_size_rx; + +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -402,6 +402,7 @@ + + #define REG_SRC_PORT_FC_MAP6 0x2298 + #define FC_ID_OF_SRC_PORT_MASK(_n) GENMASK(4 + ((_n) << 3), ((_n) << 3)) ++#define FC_MAP6_DEF_VALUE 0x1b1a1918 + + #define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4 + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -552,11 +552,12 @@ struct airoha_qdma { + + enum airoha_priv_flags { + AIROHA_PRIV_F_WAN = BIT(0), ++ AIROHA_PRIV_F_QOS = BIT(1), + }; + + struct airoha_gdm_dev { ++ struct airoha_qdma __rcu *qdma; + struct airoha_gdm_port *port; +- struct airoha_qdma *qdma; + struct airoha_eth *eth; + + #if defined(CONFIG_PCS_AIROHA) +@@ -705,6 +706,16 @@ int airoha_get_fe_port(struct airoha_gdm + bool airoha_is_valid_gdm_dev(struct airoha_eth *eth, + struct airoha_gdm_dev *dev); + ++extern struct mutex flow_offload_mutex; ++ ++static inline struct airoha_qdma * ++airoha_qdma_deref(struct airoha_gdm_dev *dev) ++{ ++ return rcu_dereference_protected(dev->qdma, ++ lockdep_rtnl_is_held() || ++ lockdep_is_held(&flow_offload_mutex)); ++} ++ + void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport); + bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index); + void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -16,7 +16,10 @@ + #include "airoha_regs.h" + #include "airoha_eth.h" + +-static DEFINE_MUTEX(flow_offload_mutex); ++/* Serialize airoha_gdm_dev flags, QDMA pointer and PPE CPU port ++ * configuration. ++ */ ++DEFINE_MUTEX(flow_offload_mutex); + static DEFINE_SPINLOCK(ppe_lock); + + static const struct rhashtable_params airoha_flow_table_params = { +@@ -87,8 +90,8 @@ static u32 airoha_ppe_get_timestamp(stru + + void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport) + { +- struct airoha_qdma *qdma = dev->qdma; +- struct airoha_eth *eth = qdma->eth; ++ struct airoha_qdma *qdma = airoha_qdma_deref(dev); ++ struct airoha_eth *eth = dev->eth; + u8 qdma_id = qdma - ð->qdma[0]; + u32 fe_cpu_port; + diff --git a/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch b/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch index 072b50fe35..d17c537daa 100644 --- a/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch +++ b/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch @@ -16,7 +16,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -185,10 +185,15 @@ static void airoha_fe_maccr_init(struct +@@ -188,10 +188,15 @@ static void airoha_fe_maccr_init(struct { int p; @@ -33,8 +33,8 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_CDM_VLAN_CTRL(1), CDM_VLAN_MASK, FIELD_PREP(CDM_VLAN_MASK, 0x8100)); -@@ -1908,13 +1913,24 @@ static void airoha_update_hw_stats(struc - spin_unlock(&port->stats.lock); +@@ -2078,15 +2083,25 @@ static void airoha_qdma_stop(struct airo + } } +static void airoha_dev_set_mtu(struct net_device *netdev) @@ -54,17 +54,19 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; - u32 cur_len, pse_port = FE_PSE_PORT_PPE1; - struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = dev->eth; + struct airoha_qdma *qdma; +- int qdma_id; + u32 pse_port = FE_PSE_PORT_PPE1; -+ int err; ++ int err, qdma_id; - if (port->id == AIROHA_GDM2_IDX && airoha_is_lan_gdm_dev(dev)) { - /* GDM2 can be used just as wan */ -@@ -1947,19 +1963,7 @@ static int airoha_dev_open(struct net_de - airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), + /* HW LRO is configured on the QDMA and it is shared between + * all the devices using it. Refuse to open a second device on +@@ -2128,19 +2143,7 @@ static int airoha_dev_open(struct net_de + airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); -- cur_len = airoha_fe_get(qdma->eth, REG_GDM_LEN_CFG(port->id), +- cur_len = airoha_fe_get(eth, REG_GDM_LEN_CFG(port->id), - GDM_LONG_LEN_MASK); - if (!port->users || len > cur_len) { - /* Opening a sibling net_device with a larger MTU updates the @@ -72,7 +74,7 @@ Signed-off-by: Lorenzo Bianconi - * multiple net_devices with different MTUs to share the same - * GDM port. - */ -- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), +- airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), - GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, - FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | - FIELD_PREP(GDM_LONG_LEN_MASK, len)); @@ -80,8 +82,8 @@ Signed-off-by: Lorenzo Bianconi + airoha_dev_set_mtu(netdev); port->users++; - airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, -@@ -1976,30 +1980,6 @@ static int airoha_dev_open(struct net_de + airoha_qdma_start(qdma); +@@ -2161,30 +2164,6 @@ static int airoha_dev_open(struct net_de return 0; } @@ -98,7 +100,7 @@ Signed-off-by: Lorenzo Bianconi - if (!dev) - continue; - -- netdev = dev->dev; +- netdev = netdev_from_priv(dev); - if (netif_running(netdev)) - len = max_t(u32, len, netdev->mtu); - } @@ -112,16 +114,16 @@ Signed-off-by: Lorenzo Bianconi static int airoha_dev_stop(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -2013,7 +1993,7 @@ static int airoha_dev_stop(struct net_de - netdev_tx_reset_subqueue(netdev, i); +@@ -2199,7 +2178,7 @@ static int airoha_dev_stop(struct net_de + qdma = airoha_qdma_deref(dev); if (--port->users) - airoha_set_port_mtu(dev->eth, port); + airoha_ppe_set_mtu(dev); else airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), -@@ -2083,10 +2063,6 @@ static int airoha_enable_gdm2_loopback(s +@@ -2258,10 +2237,6 @@ static int airoha_enable_gdm2_loopback(s FIELD_PREP(LPBK_CHAN_MASK, chan) | LBK_GAP_MODE_MASK | LBK_LEN_MODE_MASK | LBK_CHAN_MODE_MASK | LPBK_EN_MASK); @@ -132,7 +134,7 @@ Signed-off-by: Lorenzo Bianconi /* Forward the traffic to the proper GDM port */ pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3 : FE_PSE_PORT_GDM4; -@@ -2270,7 +2246,7 @@ static int airoha_dev_change_mtu(struct +@@ -2469,7 +2444,7 @@ static int airoha_dev_change_mtu(struct WRITE_ONCE(netdev->mtu, mtu); if (port->users) @@ -141,14 +143,22 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2613,6 +2589,7 @@ static int airoha_dev_set_wan_flag(struc - default: - return -EOPNOTSUPP; - } -+ airoha_dev_set_mtu(netdev); - } else { - switch (port->id) { - case AIROHA_GDM3_IDX: +@@ -3471,6 +3446,7 @@ static void airoha_disable_qos_for_gdm34 + + dev->flags &= ~AIROHA_PRIV_F_WAN; + airoha_dev_set_qdma(dev); ++ airoha_dev_set_mtu(netdev); + + airoha_set_macaddr(dev, netdev->dev_addr); + if (netif_running(netdev)) +@@ -3519,6 +3495,7 @@ static int airoha_enable_qos_for_gdm34(s + if (err) + goto error_disable_loopback; + ++ airoha_dev_set_mtu(netdev); + if (netif_running(netdev)) { + u32 pse_port; + --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h @@ -23,6 +23,7 @@ @@ -159,9 +169,9 @@ Signed-off-by: Lorenzo Bianconi #define AIROHA_MAX_PACKET_SIZE 2048 #define AIROHA_NUM_QOS_CHANNELS 4 #define AIROHA_NUM_QOS_QUEUES 8 -@@ -706,6 +707,7 @@ int airoha_get_fe_port(struct airoha_gdm - bool airoha_is_valid_gdm_dev(struct airoha_eth *eth, - struct airoha_gdm_dev *dev); +@@ -716,6 +717,7 @@ airoha_qdma_deref(struct airoha_gdm_dev + lockdep_is_held(&flow_offload_mutex)); + } +void airoha_ppe_set_mtu(struct airoha_gdm_dev *dev); void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport); @@ -169,7 +179,7 @@ Signed-off-by: Lorenzo Bianconi void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -98,6 +98,35 @@ void airoha_ppe_set_cpu_port(struct airo +@@ -101,6 +101,39 @@ void airoha_ppe_set_cpu_port(struct airo __field_prep(DFT_CPORT_MASK(fport), fe_cpu_port)); } @@ -177,20 +187,24 @@ Signed-off-by: Lorenzo Bianconi +{ + struct airoha_gdm_port *port = dev->port; + struct airoha_eth *eth = dev->eth; ++ struct airoha_qdma *qdma; + int i, ppe_id, index; + u32 mtu = 0; + ++ qdma = airoha_qdma_deref(dev); + for (i = 0; i < ARRAY_SIZE(port->devs); i++) { + struct airoha_gdm_dev *d = port->devs[i]; + struct net_device *netdev; ++ struct airoha_qdma *q; + + if (!d) + continue; + -+ if (d->qdma != dev->qdma) ++ q = airoha_qdma_deref(d); ++ if (q != qdma) + continue; + -+ netdev = d->dev; ++ netdev = netdev_from_priv(d); + if (netif_running(netdev)) + mtu = max_t(u32, mtu, netdev->mtu); + } @@ -205,7 +219,7 @@ Signed-off-by: Lorenzo Bianconi static void airoha_ppe_hw_init(struct airoha_ppe *ppe) { u32 sram_ppe_num_data_entries = PPE_SRAM_NUM_ENTRIES, sram_num_entries; -@@ -116,8 +145,6 @@ static void airoha_ppe_hw_init(struct ai +@@ -119,8 +152,6 @@ static void airoha_ppe_hw_init(struct ai PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries); for (i = 0; i < eth->soc->num_ppe; i++) { @@ -214,7 +228,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_wr(eth, REG_PPE_TB_BASE(i), ppe->foe_dma + sram_tb_size); -@@ -167,15 +194,6 @@ static void airoha_ppe_hw_init(struct ai +@@ -170,15 +201,6 @@ static void airoha_ppe_hw_init(struct ai airoha_fe_wr(eth, REG_PPE_HASH_SEED(i), PPE_HASH_SEED); airoha_fe_clear(eth, REG_PPE_PPE_FLOW_CFG(i), PPE_FLOW_CFG_IP6_6RD_MASK); @@ -230,7 +244,7 @@ Signed-off-by: Lorenzo Bianconi } for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { -@@ -197,6 +215,7 @@ static void airoha_ppe_hw_init(struct ai +@@ -200,6 +222,7 @@ static void airoha_ppe_hw_init(struct ai airoha_ppe_is_enabled(eth, 1); fport = airoha_get_fe_port(dev); airoha_ppe_set_cpu_port(dev, ppe_id, fport); diff --git a/target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch b/target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch index 25db5b6661..1aec4e91fc 100644 --- a/target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch +++ b/target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch @@ -31,7 +31,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -612,6 +612,14 @@ static int airoha_fe_init(struct airoha_ +@@ -640,6 +640,14 @@ static int airoha_fe_init(struct airoha_ airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX), GDM_PAD_EN_MASK | GDM_STRIP_CRC_MASK); @@ -46,7 +46,7 @@ Signed-off-by: Christian Marangi airoha_fe_crsn_qsel_init(eth); airoha_fe_clear(eth, REG_FE_CPORT_CFG, FE_CPORT_QUEUE_XFC_MASK); -@@ -1768,149 +1776,169 @@ static void airoha_qdma_stop_napi(struct +@@ -1872,149 +1880,169 @@ static void airoha_qdma_stop_napi(struct } } @@ -269,8 +269,8 @@ Signed-off-by: Christian Marangi + spin_unlock(&port->stats_lock); } - static void airoha_dev_set_mtu(struct net_device *netdev) -@@ -2220,23 +2248,22 @@ static void airoha_dev_get_stats64(struc + static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) +@@ -2418,23 +2446,22 @@ static void airoha_dev_get_stats64(struc struct rtnl_link_stats64 *storage) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -306,7 +306,7 @@ Signed-off-by: Christian Marangi } static int airoha_dev_change_mtu(struct net_device *netdev, int mtu) -@@ -2632,20 +2659,19 @@ static void airoha_ethtool_get_mac_stats +@@ -2723,20 +2750,19 @@ static void airoha_ethtool_get_mac_stats struct ethtool_eth_mac_stats *stats) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -336,7 +336,7 @@ Signed-off-by: Christian Marangi } static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = { -@@ -2665,8 +2691,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2756,8 +2782,7 @@ airoha_ethtool_get_rmon_stats(struct net const struct ethtool_rmon_hist_range **ranges) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -346,7 +346,7 @@ Signed-off-by: Christian Marangi unsigned int start; BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) != -@@ -2679,7 +2704,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2770,7 +2795,7 @@ airoha_ethtool_get_rmon_stats(struct net do { int i; @@ -355,7 +355,7 @@ Signed-off-by: Christian Marangi stats->fragments = hw_stats->rx_fragment; stats->jabbers = hw_stats->rx_jabber; for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1; -@@ -2687,7 +2712,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2778,7 +2803,7 @@ airoha_ethtool_get_rmon_stats(struct net stats->hist[i] = hw_stats->rx_len[i]; stats->hist_tx[i] = hw_stats->tx_len[i]; } @@ -363,16 +363,16 @@ Signed-off-by: Christian Marangi + } while (u64_stats_fetch_retry(&dev->stats.syncp, start)); } - static int airoha_ethtool_set_priv_flags(struct net_device *netdev, u32 flags) -@@ -3695,6 +3720,7 @@ static int airoha_alloc_gdm_device(struc + static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, +@@ -3849,6 +3874,7 @@ static int airoha_alloc_gdm_device(struc netdev->dev.of_node = of_node_get(np); dev = netdev_priv(netdev); + u64_stats_init(&dev->stats.syncp); - dev->dev = netdev; dev->port = port; dev->eth = eth; -@@ -3743,9 +3769,8 @@ static int airoha_alloc_gdm_port(struct + dev->nbq = nbq; +@@ -3896,9 +3922,8 @@ static int airoha_alloc_gdm_port(struct if (!port) return -ENOMEM; diff --git a/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch b/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch index 75a49306c2..2df1996d19 100644 --- a/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch +++ b/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch @@ -18,7 +18,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2345,17 +2345,9 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -2543,17 +2543,9 @@ static u32 airoha_get_dsa_tag(struct sk_ int airoha_get_fe_port(struct airoha_gdm_dev *dev) { struct airoha_gdm_port *port = dev->port; @@ -37,4 +37,4 @@ Signed-off-by: Christian Marangi + : port->id; } - static int airoha_dev_set_features(struct net_device *netdev, + static netdev_features_t airoha_dev_fix_features(struct net_device *netdev, diff --git a/target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch b/target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch new file mode 100644 index 0000000000..9cd99c759d --- /dev/null +++ b/target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch @@ -0,0 +1,36 @@ +From 18aa76cd820c412358dc36d115b8e02d24a78f39 Mon Sep 17 00:00:00 2001 +Message-ID: <18aa76cd820c412358dc36d115b8e02d24a78f39.1780942778.git.lorenzo@kernel.org> +From: Lorenzo Bianconi +Date: Mon, 8 Jun 2026 20:10:35 +0200 +Subject: [PATCH] net: airoha: move get_sport() callback at the beginning of + airoha_enable_gdm2_loopback() + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2250,6 +2250,10 @@ static int airoha_enable_gdm2_loopback(s + u32 val, pse_port, chan; + int i, src_port; + ++ src_port = eth->soc->ops.get_sport(port, dev->nbq); ++ if (src_port < 0) ++ return src_port; ++ + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), + FE_PSE_PORT_DROP); + airoha_fe_clear(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), +@@ -2275,10 +2279,6 @@ static int airoha_enable_gdm2_loopback(s + airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); + airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); + +- src_port = eth->soc->ops.get_sport(port, dev->nbq); +- if (src_port < 0) +- return src_port; +- + airoha_fe_rmw(eth, REG_FE_WAN_PORT, + WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, + FIELD_PREP(WAN0_MASK, src_port)); diff --git a/target/linux/airoha/patches-6.18/922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch b/target/linux/airoha/patches-6.18/922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch new file mode 100644 index 0000000000..c9e788e3e1 --- /dev/null +++ b/target/linux/airoha/patches-6.18/922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch @@ -0,0 +1,42 @@ +From 3d67e4ba79bd4b40f520d26af098f133b5f551d4 Mon Sep 17 00:00:00 2001 +Message-ID: <3d67e4ba79bd4b40f520d26af098f133b5f551d4.1781097105.git.lorenzo@kernel.org> +From: Lorenzo Bianconi +Date: Sat, 6 Jun 2026 08:53:03 +0200 +Subject: [PATCH] net: airoha: simplify WAN device check in airoha_dev_init() + +airoha_register_gdm_devices() iterates eth->ports[] in order, so GDM2's +netdev is always registered before GDM3/GDM4. This means the explicit +check for eth->ports[1] && eth->ports[1]->devs[0] is a redundant +special-case of what airoha_get_wan_gdm_dev() already covers, since +GDM2 is always marked as WAN during its own ndo_init. +Remove the redundant check and rely solely on airoha_get_wan_gdm_dev() +which handles both the GDM2-present and GDM2-absent cases. + +Signed-off-by: Lorenzo Bianconi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2407,18 +2407,10 @@ static int airoha_dev_init(struct net_de + + switch (port->id) { + case AIROHA_GDM3_IDX: +- case AIROHA_GDM4_IDX: { +- struct airoha_eth *eth = dev->eth; +- +- /* GDM2 supports a single net_device */ +- if (eth->ports[1] && eth->ports[1]->devs[0]) +- break; +- +- if (airoha_get_wan_gdm_dev(eth)) ++ case AIROHA_GDM4_IDX: ++ if (airoha_get_wan_gdm_dev(dev->eth)) + break; +- + fallthrough; +- } + case AIROHA_GDM2_IDX: + /* GDM2 is always used as wan */ + dev->flags |= AIROHA_PRIV_F_WAN; From bd13b32899f0684f283dc14f9d552bba903f6ea7 Mon Sep 17 00:00:00 2001 From: Qingfang Deng Date: Fri, 12 Jun 2026 16:30:02 +0800 Subject: [PATCH 061/228] kernel: remove legacy iptables patches These patches were introduced 15 years ago by commit 19eaf1c5f78a to speed up iptables match. We have been using fw4 and nftables for a long time, so they are obsolete. Signed-off-by: Qingfang Deng Link: https://github.com/openwrt/openwrt/pull/23749 Signed-off-by: Markus Stockhausen --- ...etfilter_match_bypass_default_checks.patch | 110 ------------------ ...netfilter_match_bypass_default_table.patch | 106 ----------------- ...netfilter_match_reduce_memory_access.patch | 22 ---- ...etfilter_match_bypass_default_checks.patch | 110 ------------------ ...netfilter_match_bypass_default_table.patch | 106 ----------------- ...netfilter_match_reduce_memory_access.patch | 22 ---- 6 files changed, 476 deletions(-) delete mode 100644 target/linux/generic/pending-6.12/610-netfilter_match_bypass_default_checks.patch delete mode 100644 target/linux/generic/pending-6.12/611-netfilter_match_bypass_default_table.patch delete mode 100644 target/linux/generic/pending-6.12/612-netfilter_match_reduce_memory_access.patch delete mode 100644 target/linux/generic/pending-6.18/610-netfilter_match_bypass_default_checks.patch delete mode 100644 target/linux/generic/pending-6.18/611-netfilter_match_bypass_default_table.patch delete mode 100644 target/linux/generic/pending-6.18/612-netfilter_match_reduce_memory_access.patch diff --git a/target/linux/generic/pending-6.12/610-netfilter_match_bypass_default_checks.patch b/target/linux/generic/pending-6.12/610-netfilter_match_bypass_default_checks.patch deleted file mode 100644 index fd22200a84..0000000000 --- a/target/linux/generic/pending-6.12/610-netfilter_match_bypass_default_checks.patch +++ /dev/null @@ -1,110 +0,0 @@ -From: Felix Fietkau -Subject: kernel: add a new version of my netfilter speedup patches for linux 2.6.39 and 3.0 - -Signed-off-by: Felix Fietkau ---- - include/uapi/linux/netfilter_ipv4/ip_tables.h | 1 + - net/ipv4/netfilter/ip_tables.c | 37 +++++++++++++++++++++++++++ - 2 files changed, 38 insertions(+) - ---- a/include/uapi/linux/netfilter_ipv4/ip_tables.h -+++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h -@@ -89,6 +89,7 @@ struct ipt_ip { - #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ - #define IPT_F_GOTO 0x02 /* Set if jump is a goto */ - #define IPT_F_MASK 0x03 /* All possible flag bits mask. */ -+#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */ - - /* Values for "inv" field in struct ipt_ip. */ - #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -48,6 +48,9 @@ ip_packet_match(const struct iphdr *ip, - { - unsigned long ret; - -+ if (ipinfo->flags & IPT_F_NO_DEF_MATCH) -+ return true; -+ - if (NF_INVF(ipinfo, IPT_INV_SRCIP, - (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || - NF_INVF(ipinfo, IPT_INV_DSTIP, -@@ -78,6 +81,29 @@ ip_packet_match(const struct iphdr *ip, - return true; - } - -+static void -+ip_checkdefault(struct ipt_ip *ip) -+{ -+ static const char iface_mask[IFNAMSIZ] = {}; -+ -+ if (ip->invflags || ip->flags & IPT_F_FRAG) -+ return; -+ -+ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0) -+ return; -+ -+ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) -+ return; -+ -+ if (ip->smsk.s_addr || ip->dmsk.s_addr) -+ return; -+ -+ if (ip->proto) -+ return; -+ -+ ip->flags |= IPT_F_NO_DEF_MATCH; -+} -+ - static bool - ip_checkentry(const struct ipt_ip *ip) - { -@@ -523,6 +549,8 @@ find_check_entry(struct ipt_entry *e, st - struct xt_mtchk_param mtpar; - struct xt_entry_match *ematch; - -+ ip_checkdefault(&e->ip); -+ - if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) - return -ENOMEM; - -@@ -817,6 +845,7 @@ copy_entries_to_user(unsigned int total_ - const struct xt_table_info *private = table->private; - int ret = 0; - const void *loc_cpu_entry; -+ u8 flags; - - counters = alloc_counters(table); - if (IS_ERR(counters)) -@@ -844,6 +873,14 @@ copy_entries_to_user(unsigned int total_ - goto free_counters; - } - -+ flags = e->ip.flags & IPT_F_MASK; -+ if (copy_to_user(userptr + off -+ + offsetof(struct ipt_entry, ip.flags), -+ &flags, sizeof(flags)) != 0) { -+ ret = -EFAULT; -+ goto free_counters; -+ } -+ - for (i = sizeof(struct ipt_entry); - i < e->target_offset; - i += m->u.match_size) { -@@ -1225,12 +1262,15 @@ compat_copy_entry_to_user(struct ipt_ent - compat_uint_t origsize; - const struct xt_entry_match *ematch; - int ret = 0; -+ u8 flags = e->ip.flags & IPT_F_MASK; - - origsize = *size; - ce = *dstptr; - if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 || - copy_to_user(&ce->counters, &counters[i], -- sizeof(counters[i])) != 0) -+ sizeof(counters[i])) != 0 || -+ copy_to_user(&ce->ip.flags, &flags, -+ sizeof(flags)) != 0) - return -EFAULT; - - *dstptr += sizeof(struct compat_ipt_entry); diff --git a/target/linux/generic/pending-6.12/611-netfilter_match_bypass_default_table.patch b/target/linux/generic/pending-6.12/611-netfilter_match_bypass_default_table.patch deleted file mode 100644 index 9f0efe4ec4..0000000000 --- a/target/linux/generic/pending-6.12/611-netfilter_match_bypass_default_table.patch +++ /dev/null @@ -1,106 +0,0 @@ -From: Felix Fietkau -Subject: netfilter: match bypass default table - -Signed-off-by: Felix Fietkau ---- - net/ipv4/netfilter/ip_tables.c | 79 +++++++++++++++++++++++++++++++----------- - 1 file changed, 58 insertions(+), 21 deletions(-) - ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -244,6 +244,33 @@ struct ipt_entry *ipt_next_entry(const s - return (void *)entry + entry->next_offset; - } - -+static bool -+ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict) -+{ -+ struct xt_entry_target *t; -+ struct xt_standard_target *st; -+ -+ if (e->target_offset != sizeof(struct ipt_entry)) -+ return false; -+ -+ if (!(e->ip.flags & IPT_F_NO_DEF_MATCH)) -+ return false; -+ -+ t = ipt_get_target(e); -+ if (t->u.kernel.target->target) -+ return false; -+ -+ st = (struct xt_standard_target *) t; -+ if (st->verdict == XT_RETURN) -+ return false; -+ -+ if (st->verdict >= 0) -+ return false; -+ -+ *verdict = (unsigned)(-st->verdict) - 1; -+ return true; -+} -+ - /* Returns one of the generic firewall policies, like NF_ACCEPT. */ - unsigned int - ipt_do_table(void *priv, -@@ -265,27 +292,28 @@ ipt_do_table(void *priv, - unsigned int addend; - - /* Initialization */ -+ WARN_ON(!(table->valid_hooks & (1 << hook))); -+ local_bh_disable(); -+ private = READ_ONCE(table->private); /* Address dependency. */ -+ cpu = smp_processor_id(); -+ table_base = private->entries; -+ -+ e = get_entry(table_base, private->hook_entry[hook]); -+ if (ipt_handle_default_rule(e, &verdict)) { -+ struct xt_counters *counter; -+ -+ counter = xt_get_this_cpu_counter(&e->counters); -+ ADD_COUNTER(*counter, skb->len, 1); -+ local_bh_enable(); -+ return verdict; -+ } -+ - stackidx = 0; - ip = ip_hdr(skb); - indev = state->in ? state->in->name : nulldevname; - outdev = state->out ? state->out->name : nulldevname; -- /* We handle fragments by dealing with the first fragment as -- * if it was a normal packet. All other fragments are treated -- * normally, except that they will NEVER match rules that ask -- * things we don't know, ie. tcp syn flag or ports). If the -- * rule is also a fragment-specific rule, non-fragments won't -- * match it. */ -- acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; -- acpar.thoff = ip_hdrlen(skb); -- acpar.hotdrop = false; -- acpar.state = state; - -- WARN_ON(!(table->valid_hooks & (1 << hook))); -- local_bh_disable(); - addend = xt_write_recseq_begin(); -- private = READ_ONCE(table->private); /* Address dependency. */ -- cpu = smp_processor_id(); -- table_base = private->entries; - jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; - - /* Switch to alternate jumpstack if we're being invoked via TEE. -@@ -298,7 +326,16 @@ ipt_do_table(void *priv, - if (static_key_false(&xt_tee_enabled)) - jumpstack += private->stacksize * __this_cpu_read(nf_skb_duplicated); - -- e = get_entry(table_base, private->hook_entry[hook]); -+ /* We handle fragments by dealing with the first fragment as -+ * if it was a normal packet. All other fragments are treated -+ * normally, except that they will NEVER match rules that ask -+ * things we don't know, ie. tcp syn flag or ports). If the -+ * rule is also a fragment-specific rule, non-fragments won't -+ * match it. */ -+ acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; -+ acpar.thoff = ip_hdrlen(skb); -+ acpar.hotdrop = false; -+ acpar.state = state; - - do { - const struct xt_entry_target *t; diff --git a/target/linux/generic/pending-6.12/612-netfilter_match_reduce_memory_access.patch b/target/linux/generic/pending-6.12/612-netfilter_match_reduce_memory_access.patch deleted file mode 100644 index 7f291fc008..0000000000 --- a/target/linux/generic/pending-6.12/612-netfilter_match_reduce_memory_access.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Felix Fietkau -Subject: netfilter: reduce match memory access - -Signed-off-by: Felix Fietkau ---- - net/ipv4/netfilter/ip_tables.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -51,9 +51,9 @@ ip_packet_match(const struct iphdr *ip, - if (ipinfo->flags & IPT_F_NO_DEF_MATCH) - return true; - -- if (NF_INVF(ipinfo, IPT_INV_SRCIP, -+ if (NF_INVF(ipinfo, IPT_INV_SRCIP, ipinfo->smsk.s_addr && - (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || -- NF_INVF(ipinfo, IPT_INV_DSTIP, -+ NF_INVF(ipinfo, IPT_INV_DSTIP, ipinfo->dmsk.s_addr && - (ip->daddr & ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr)) - return false; - diff --git a/target/linux/generic/pending-6.18/610-netfilter_match_bypass_default_checks.patch b/target/linux/generic/pending-6.18/610-netfilter_match_bypass_default_checks.patch deleted file mode 100644 index fd22200a84..0000000000 --- a/target/linux/generic/pending-6.18/610-netfilter_match_bypass_default_checks.patch +++ /dev/null @@ -1,110 +0,0 @@ -From: Felix Fietkau -Subject: kernel: add a new version of my netfilter speedup patches for linux 2.6.39 and 3.0 - -Signed-off-by: Felix Fietkau ---- - include/uapi/linux/netfilter_ipv4/ip_tables.h | 1 + - net/ipv4/netfilter/ip_tables.c | 37 +++++++++++++++++++++++++++ - 2 files changed, 38 insertions(+) - ---- a/include/uapi/linux/netfilter_ipv4/ip_tables.h -+++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h -@@ -89,6 +89,7 @@ struct ipt_ip { - #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ - #define IPT_F_GOTO 0x02 /* Set if jump is a goto */ - #define IPT_F_MASK 0x03 /* All possible flag bits mask. */ -+#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */ - - /* Values for "inv" field in struct ipt_ip. */ - #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -48,6 +48,9 @@ ip_packet_match(const struct iphdr *ip, - { - unsigned long ret; - -+ if (ipinfo->flags & IPT_F_NO_DEF_MATCH) -+ return true; -+ - if (NF_INVF(ipinfo, IPT_INV_SRCIP, - (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || - NF_INVF(ipinfo, IPT_INV_DSTIP, -@@ -78,6 +81,29 @@ ip_packet_match(const struct iphdr *ip, - return true; - } - -+static void -+ip_checkdefault(struct ipt_ip *ip) -+{ -+ static const char iface_mask[IFNAMSIZ] = {}; -+ -+ if (ip->invflags || ip->flags & IPT_F_FRAG) -+ return; -+ -+ if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0) -+ return; -+ -+ if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0) -+ return; -+ -+ if (ip->smsk.s_addr || ip->dmsk.s_addr) -+ return; -+ -+ if (ip->proto) -+ return; -+ -+ ip->flags |= IPT_F_NO_DEF_MATCH; -+} -+ - static bool - ip_checkentry(const struct ipt_ip *ip) - { -@@ -523,6 +549,8 @@ find_check_entry(struct ipt_entry *e, st - struct xt_mtchk_param mtpar; - struct xt_entry_match *ematch; - -+ ip_checkdefault(&e->ip); -+ - if (!xt_percpu_counter_alloc(alloc_state, &e->counters)) - return -ENOMEM; - -@@ -817,6 +845,7 @@ copy_entries_to_user(unsigned int total_ - const struct xt_table_info *private = table->private; - int ret = 0; - const void *loc_cpu_entry; -+ u8 flags; - - counters = alloc_counters(table); - if (IS_ERR(counters)) -@@ -844,6 +873,14 @@ copy_entries_to_user(unsigned int total_ - goto free_counters; - } - -+ flags = e->ip.flags & IPT_F_MASK; -+ if (copy_to_user(userptr + off -+ + offsetof(struct ipt_entry, ip.flags), -+ &flags, sizeof(flags)) != 0) { -+ ret = -EFAULT; -+ goto free_counters; -+ } -+ - for (i = sizeof(struct ipt_entry); - i < e->target_offset; - i += m->u.match_size) { -@@ -1225,12 +1262,15 @@ compat_copy_entry_to_user(struct ipt_ent - compat_uint_t origsize; - const struct xt_entry_match *ematch; - int ret = 0; -+ u8 flags = e->ip.flags & IPT_F_MASK; - - origsize = *size; - ce = *dstptr; - if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 || - copy_to_user(&ce->counters, &counters[i], -- sizeof(counters[i])) != 0) -+ sizeof(counters[i])) != 0 || -+ copy_to_user(&ce->ip.flags, &flags, -+ sizeof(flags)) != 0) - return -EFAULT; - - *dstptr += sizeof(struct compat_ipt_entry); diff --git a/target/linux/generic/pending-6.18/611-netfilter_match_bypass_default_table.patch b/target/linux/generic/pending-6.18/611-netfilter_match_bypass_default_table.patch deleted file mode 100644 index 8185a8b0df..0000000000 --- a/target/linux/generic/pending-6.18/611-netfilter_match_bypass_default_table.patch +++ /dev/null @@ -1,106 +0,0 @@ -From: Felix Fietkau -Subject: netfilter: match bypass default table - -Signed-off-by: Felix Fietkau ---- - net/ipv4/netfilter/ip_tables.c | 79 +++++++++++++++++++++++++++++++----------- - 1 file changed, 58 insertions(+), 21 deletions(-) - ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -244,6 +244,33 @@ struct ipt_entry *ipt_next_entry(const s - return (void *)entry + entry->next_offset; - } - -+static bool -+ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict) -+{ -+ struct xt_entry_target *t; -+ struct xt_standard_target *st; -+ -+ if (e->target_offset != sizeof(struct ipt_entry)) -+ return false; -+ -+ if (!(e->ip.flags & IPT_F_NO_DEF_MATCH)) -+ return false; -+ -+ t = ipt_get_target(e); -+ if (t->u.kernel.target->target) -+ return false; -+ -+ st = (struct xt_standard_target *) t; -+ if (st->verdict == XT_RETURN) -+ return false; -+ -+ if (st->verdict >= 0) -+ return false; -+ -+ *verdict = (unsigned)(-st->verdict) - 1; -+ return true; -+} -+ - /* Returns one of the generic firewall policies, like NF_ACCEPT. */ - unsigned int - ipt_do_table(void *priv, -@@ -265,27 +292,28 @@ ipt_do_table(void *priv, - unsigned int addend; - - /* Initialization */ -+ WARN_ON(!(table->valid_hooks & (1 << hook))); -+ local_bh_disable(); -+ private = READ_ONCE(table->private); /* Address dependency. */ -+ cpu = smp_processor_id(); -+ table_base = private->entries; -+ -+ e = get_entry(table_base, private->hook_entry[hook]); -+ if (ipt_handle_default_rule(e, &verdict)) { -+ struct xt_counters *counter; -+ -+ counter = xt_get_this_cpu_counter(&e->counters); -+ ADD_COUNTER(*counter, skb->len, 1); -+ local_bh_enable(); -+ return verdict; -+ } -+ - stackidx = 0; - ip = ip_hdr(skb); - indev = state->in ? state->in->name : nulldevname; - outdev = state->out ? state->out->name : nulldevname; -- /* We handle fragments by dealing with the first fragment as -- * if it was a normal packet. All other fragments are treated -- * normally, except that they will NEVER match rules that ask -- * things we don't know, ie. tcp syn flag or ports). If the -- * rule is also a fragment-specific rule, non-fragments won't -- * match it. */ -- acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; -- acpar.thoff = ip_hdrlen(skb); -- acpar.hotdrop = false; -- acpar.state = state; - -- WARN_ON(!(table->valid_hooks & (1 << hook))); -- local_bh_disable(); - addend = xt_write_recseq_begin(); -- private = READ_ONCE(table->private); /* Address dependency. */ -- cpu = smp_processor_id(); -- table_base = private->entries; - jumpstack = (struct ipt_entry **)private->jumpstack[cpu]; - - /* Switch to alternate jumpstack if we're being invoked via TEE. -@@ -298,7 +326,16 @@ ipt_do_table(void *priv, - if (static_key_false(&xt_tee_enabled)) - jumpstack += private->stacksize * current->in_nf_duplicate; - -- e = get_entry(table_base, private->hook_entry[hook]); -+ /* We handle fragments by dealing with the first fragment as -+ * if it was a normal packet. All other fragments are treated -+ * normally, except that they will NEVER match rules that ask -+ * things we don't know, ie. tcp syn flag or ports). If the -+ * rule is also a fragment-specific rule, non-fragments won't -+ * match it. */ -+ acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET; -+ acpar.thoff = ip_hdrlen(skb); -+ acpar.hotdrop = false; -+ acpar.state = state; - - do { - const struct xt_entry_target *t; diff --git a/target/linux/generic/pending-6.18/612-netfilter_match_reduce_memory_access.patch b/target/linux/generic/pending-6.18/612-netfilter_match_reduce_memory_access.patch deleted file mode 100644 index 7f291fc008..0000000000 --- a/target/linux/generic/pending-6.18/612-netfilter_match_reduce_memory_access.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Felix Fietkau -Subject: netfilter: reduce match memory access - -Signed-off-by: Felix Fietkau ---- - net/ipv4/netfilter/ip_tables.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/net/ipv4/netfilter/ip_tables.c -+++ b/net/ipv4/netfilter/ip_tables.c -@@ -51,9 +51,9 @@ ip_packet_match(const struct iphdr *ip, - if (ipinfo->flags & IPT_F_NO_DEF_MATCH) - return true; - -- if (NF_INVF(ipinfo, IPT_INV_SRCIP, -+ if (NF_INVF(ipinfo, IPT_INV_SRCIP, ipinfo->smsk.s_addr && - (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) || -- NF_INVF(ipinfo, IPT_INV_DSTIP, -+ NF_INVF(ipinfo, IPT_INV_DSTIP, ipinfo->dmsk.s_addr && - (ip->daddr & ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr)) - return false; - From f7c1d91f1fc85e5aa2ded8c6452823b94a05bb13 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Thu, 18 Jun 2026 01:30:57 +0200 Subject: [PATCH 062/228] odhcpd: update to Git HEAD (2026-06-18) 0320032ae313 odhcpd: fix out of bounds write in dhcpv6_ia_handle_IAs 26b122007030 dhcpv6-ia: avoid dangling first lease pointer 03dacc23356b dhcpv6-ia: fix Reconfigure Accept Auth option write offset Signed-off-by: Hauke Mehrtens --- package/network/services/odhcpd/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/services/odhcpd/Makefile b/package/network/services/odhcpd/Makefile index a6340f0966..cd8b8cea7a 100644 --- a/package/network/services/odhcpd/Makefile +++ b/package/network/services/odhcpd/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/odhcpd.git -PKG_MIRROR_HASH:=f982e7fc12f928359835ccb4b8e650ce935aa67e099bcacded6987d18452ae8d -PKG_SOURCE_DATE:=2026-06-14 -PKG_SOURCE_VERSION:=c6792bac3905d4bf726d914e9994f6d4b98c5b57 +PKG_MIRROR_HASH:=2d6504c0ee35cecc6b91d1603152bbe37b41a5a09217a90bd539e7c6371e011a +PKG_SOURCE_DATE:=2026-06-18 +PKG_SOURCE_VERSION:=03dacc23356b5789842b9d1bba0200fd005e35f3 PKG_MAINTAINER:=Álvaro Fernández Rojas PKG_LICENSE:=GPL-2.0 From 0d5fa224879029fde0637e2aa3707059c1264394 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Thu, 18 Jun 2026 01:44:32 +0200 Subject: [PATCH 063/228] openssl: update to 3.5.7 This release incorporates the following bug fixes and mitigations: * Fixed heap use-after-free in PKCS7_verify(). (CVE-2026-45447) * Fixed CMS AuthEnvelopedData processing may accept forged messages. (CVE-2026-34182) * Fixed unbounded memory growth in the QUIC PATH_CHALLENGE handler. (CVE-2026-34183) * Fixed NULL pointer dereference in QUIC server initial packet handling. (CVE-2026-42764) * Fixed AES-OCB IV ignored on EVP_Cipher() path. (CVE-2026-45445) * Fixed possible heap buffer overflow in ASN.1 multibyte string conversion. (CVE-2026-7383) * Fixed out-of-bounds read in CMS password-based decryption. (CVE-2026-9076) * Fixed heap buffer over-read in ASN.1 content parsing. (CVE-2026-34180) * Fixed PKCS#12 files with PBMAC1 are accepted with short HMAC keys. (CVE-2026-34181) * Fixed possible NULL dereference in password-dased CMS decryption. (CVE-2026-42766) * Fixed NULL pointer dereference in CRMF EncryptedValue decryption. (CVE-2026-42767) * Fixed multi-RecipientInfo Bleichenbacher Oracle in CMS_decrypt() and PKCS7_decrypt(). (CVE-2026-42768) * Fixed trust anchor substitution via cert/issuer typo in CMP rootCaKeyUpdate. (CVE-2026-42769) * Fixed FFC-DH peer validation uses attacker-supplied q. (CVE-2026-42770) * Fixed incorrect tag processing for empty messages in AES-GCM-SIV and AES-SIV modes. (CVE-2026-45446) Link: https://github.com/openwrt/openwrt/pull/23852 Signed-off-by: Hauke Mehrtens --- package/libs/openssl/Makefile | 4 ++-- .../libs/openssl/patches/100-Configure-afalg-support.patch | 2 +- .../libs/openssl/patches/140-allow-prefer-chacha20.patch | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package/libs/openssl/Makefile b/package/libs/openssl/Makefile index b7eb5e6c21..daf470bf66 100644 --- a/package/libs/openssl/Makefile +++ b/package/libs/openssl/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openssl -PKG_VERSION:=3.5.6 +PKG_VERSION:=3.5.7 PKG_RELEASE:=1 PKG_BUILD_FLAGS:=no-mips16 gc-sections no-lto @@ -21,7 +21,7 @@ PKG_SOURCE_URL:= \ https://www.openssl.org/source/old/$(PKG_BASE)/ \ https://github.com/openssl/openssl/releases/download/$(PKG_NAME)-$(PKG_VERSION)/ -PKG_HASH:=deae7c80cba99c4b4f940ecadb3c3338b13cb77418409238e57d7f31f2a3b736 +PKG_HASH:=a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8 PKG_LICENSE:=Apache-2.0 PKG_LICENSE_FILES:=LICENSE.txt diff --git a/package/libs/openssl/patches/100-Configure-afalg-support.patch b/package/libs/openssl/patches/100-Configure-afalg-support.patch index 0596e36202..3ff962d7a8 100644 --- a/package/libs/openssl/patches/100-Configure-afalg-support.patch +++ b/package/libs/openssl/patches/100-Configure-afalg-support.patch @@ -10,7 +10,7 @@ Signed-off-by: Eneas U de Queiroz --- a/Configure +++ b/Configure -@@ -1811,7 +1811,9 @@ $config{CFLAGS} = [ map { $_ eq '--ossl- +@@ -1816,7 +1816,9 @@ $config{CFLAGS} = [ map { $_ eq '--ossl- unless ($disabled{afalgeng}) { $config{afalgeng}=""; diff --git a/package/libs/openssl/patches/140-allow-prefer-chacha20.patch b/package/libs/openssl/patches/140-allow-prefer-chacha20.patch index beeceef7c5..2a3f476cab 100644 --- a/package/libs/openssl/patches/140-allow-prefer-chacha20.patch +++ b/package/libs/openssl/patches/140-allow-prefer-chacha20.patch @@ -16,7 +16,7 @@ Signed-off-by: Eneas U de Queiroz --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c -@@ -1471,11 +1471,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ +@@ -1475,11 +1475,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail); @@ -46,7 +46,7 @@ Signed-off-by: Eneas U de Queiroz /* * ...and generally, our preferred cipher is AES. -@@ -1530,7 +1548,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ +@@ -1534,7 +1552,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_ * Within each group, ciphers remain sorted by strength and previous * preference, i.e., * 1) ECDHE > DHE @@ -55,7 +55,7 @@ Signed-off-by: Eneas U de Queiroz * 3) AES > rest * 4) TLS 1.2 > legacy * -@@ -2232,7 +2250,13 @@ const char *OSSL_default_cipher_list(voi +@@ -2236,7 +2254,13 @@ const char *OSSL_default_cipher_list(voi */ const char *OSSL_default_ciphersuites(void) { From 581134305ee0322705b0bd85e93384a7b893f5ec Mon Sep 17 00:00:00 2001 From: Stan Grishin Date: Mon, 15 Jun 2026 20:47:54 +0000 Subject: [PATCH 064/228] an7581/base-files: use IPKG_INSTROOT when sourcing functions.sh * fixes the following error message when using image builder to create an image for an7581 devices: build_dir/target-aarch64_cortex-a53_musl/root-airoha/etc/init.d/airoha_fan: line 8: /lib/functions.sh: No such file or directory Signed-off-by: Stan Grishin Link: https://github.com/openwrt/openwrt/pull/23814 Signed-off-by: Jonas Jelonek --- target/linux/airoha/an7581/base-files/etc/init.d/airoha_fan | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/airoha/an7581/base-files/etc/init.d/airoha_fan b/target/linux/airoha/an7581/base-files/etc/init.d/airoha_fan index d30205f546..b9d5633bd1 100755 --- a/target/linux/airoha/an7581/base-files/etc/init.d/airoha_fan +++ b/target/linux/airoha/an7581/base-files/etc/init.d/airoha_fan @@ -5,7 +5,7 @@ START=99 -. /lib/functions.sh +. "$IPKG_INSTROOT/lib/functions.sh" find_nct7802() { From 6fde98771191f3cf7dc12b150354e64d7c477eff Mon Sep 17 00:00:00 2001 From: "Sven Eckelmann (Plasma Cloud)" Date: Thu, 18 Jun 2026 11:49:54 +0200 Subject: [PATCH 065/228] ramips: pax1800-lite: do not attach both ubi partitions on boot The dual-boot mechanism depends on the fact that the bootloader specifies the ubi.mtd= of the currently active slot. And the Linux is expected to only attach the specified ubi-partition. Otherwise the kernel will use the "rootfs" partition of the initially attached ubi partition as its root partition. Which is of course wrong when the kernel parameter specified ubi.mtd=firmware2. Fixes: c7c54f313425 ("ramips: add support for Plasma Cloud PAX1800-Lite") Signed-off-by: Sven Eckelmann (Plasma Cloud) Link: https://github.com/openwrt/openwrt/pull/23857 Signed-off-by: Jonas Jelonek --- target/linux/ramips/dts/mt7621_plasmacloud_pax1800-lite.dts | 2 -- 1 file changed, 2 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_plasmacloud_pax1800-lite.dts b/target/linux/ramips/dts/mt7621_plasmacloud_pax1800-lite.dts index b1e29e276a..c0395a2c1d 100644 --- a/target/linux/ramips/dts/mt7621_plasmacloud_pax1800-lite.dts +++ b/target/linux/ramips/dts/mt7621_plasmacloud_pax1800-lite.dts @@ -154,13 +154,11 @@ partition@0 { label = "firmware1"; reg = <0x0 0x4000000>; - compatible = "linux,ubi"; }; partition@4000000 { label = "firmware2"; reg = <0x4000000 0x4000000>; - compatible = "linux,ubi"; }; }; }; From 78f8876830a22b667585f093adf3b9c6089e9f0d Mon Sep 17 00:00:00 2001 From: Wayen Yan Date: Sun, 14 Jun 2026 22:25:37 +0800 Subject: [PATCH 066/228] thermal: airoha: fix wrong variable in AN7583 error check In an7583_thermal_probe(), the code assigns priv->chip_scu from device_node_to_regmap() but then checks IS_ERR(priv->map) and returns PTR_ERR(priv->map). The variable priv->map is not assigned in this function, so the error check uses a different variable than what was actually assigned. This should check chip_scu instead of map. Fixes: 5891a9e5fbdf ("thermal/drivers: airoha: Add support for AN7583") Signed-off-by: Wayen Yan Link: https://github.com/openwrt/openwrt/pull/23781 Signed-off-by: Jonas Jelonek --- ...402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/airoha/patches-6.18/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch b/target/linux/airoha/patches-6.18/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch index 51332350ef..dd7912259c 100644 --- a/target/linux/airoha/patches-6.18/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch +++ b/target/linux/airoha/patches-6.18/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch @@ -231,8 +231,8 @@ Signed-off-by: Christian Marangi + int i; + + priv->chip_scu = device_node_to_regmap(dev->parent->of_node); -+ if (IS_ERR(priv->map)) -+ return PTR_ERR(priv->map); ++ if (IS_ERR(priv->chip_scu)) ++ return PTR_ERR(priv->chip_scu); + + for (i = 0; i < AIROHA_THERMAL_FIELD_MAX; i++) { + struct regmap_field *field; From a3646ae7ac36d7ebd20605886771460c429e8ad6 Mon Sep 17 00:00:00 2001 From: Lars Gierth Date: Thu, 18 Jun 2026 16:51:55 +0200 Subject: [PATCH 067/228] realtek: rtl930x: remove SFP power settings for Hasivo F1100W I think these were copied from a different device's DTS at the very beginning of the porting work. We don't know the actual maximums of these SFP ports, so let's stick with the 1W default, unless someone researches what the Hasivo vendor firmware does for this setting. Signed-off-by: Lars Gierth Link: https://github.com/openwrt/openwrt/pull/23865 Signed-off-by: Jonas Jelonek --- .../realtek/dts/rtl9303_hasivo_f1100w-4sx-4xgt-common.dtsi | 4 ---- 1 file changed, 4 deletions(-) diff --git a/target/linux/realtek/dts/rtl9303_hasivo_f1100w-4sx-4xgt-common.dtsi b/target/linux/realtek/dts/rtl9303_hasivo_f1100w-4sx-4xgt-common.dtsi index 38be37061d..99f5b24d09 100644 --- a/target/linux/realtek/dts/rtl9303_hasivo_f1100w-4sx-4xgt-common.dtsi +++ b/target/linux/realtek/dts/rtl9303_hasivo_f1100w-4sx-4xgt-common.dtsi @@ -55,7 +55,6 @@ compatible = "sff,sfp"; i2c-bus = <&i2c0>; mod-def0-gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; - maximum-power-milliwatt = <2000>; #thermal-sensor-cells = <0>; }; @@ -63,7 +62,6 @@ compatible = "sff,sfp"; i2c-bus = <&i2c1>; mod-def0-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; - maximum-power-milliwatt = <2000>; #thermal-sensor-cells = <0>; }; @@ -71,7 +69,6 @@ compatible = "sff,sfp"; i2c-bus = <&i2c2>; mod-def0-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; - maximum-power-milliwatt = <2000>; #thermal-sensor-cells = <0>; }; @@ -79,7 +76,6 @@ compatible = "sff,sfp"; i2c-bus = <&i2c3>; mod-def0-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; - maximum-power-milliwatt = <2000>; #thermal-sensor-cells = <0>; }; }; From 71767c37a7f9c37137ccfa3aca1600c4ffa504f0 Mon Sep 17 00:00:00 2001 From: Lars Gierth Date: Thu, 18 Jun 2026 18:34:14 +0200 Subject: [PATCH 068/228] realtek: rtl931x: remove unused thermal-sensor-cells from DTS Quote @jonasjelonek: It's all not really wired up correctly, the thermal driver has no support for RTL931x and nothing else really links e.g. SFP slots with a fan or whatever. Signed-off-by: Lars Gierth Link: https://github.com/openwrt/openwrt/pull/23865 Signed-off-by: Jonas Jelonek --- .../realtek/dts/rtl9313_xikestor_sks8300-12x-v1.dts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/target/linux/realtek/dts/rtl9313_xikestor_sks8300-12x-v1.dts b/target/linux/realtek/dts/rtl9313_xikestor_sks8300-12x-v1.dts index d18883b3cf..65e883c4e3 100644 --- a/target/linux/realtek/dts/rtl9313_xikestor_sks8300-12x-v1.dts +++ b/target/linux/realtek/dts/rtl9313_xikestor_sks8300-12x-v1.dts @@ -90,7 +90,6 @@ los-gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 1 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp2: sfp-p2 { @@ -99,7 +98,6 @@ los-gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 4 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp3: sfp-p3 { @@ -108,7 +106,6 @@ los-gpio = <&gpio1 6 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 7 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 8 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp4: sfp-p4 { @@ -117,7 +114,6 @@ los-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 10 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp5: sfp-p5 { @@ -126,7 +122,6 @@ los-gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 13 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp6: sfp-p6 { @@ -135,7 +130,6 @@ los-gpio = <&gpio1 21 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 22 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp7: sfp-p7 { @@ -144,7 +138,6 @@ los-gpio = <&gpio1 24 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 25 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp8: sfp-p8 { @@ -153,7 +146,6 @@ los-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio1 28 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp9: sfp-p9 { @@ -162,7 +154,6 @@ los-gpio = <&gpio2 3 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio2 4 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio2 5 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp10: sfp-p10 { @@ -171,7 +162,6 @@ los-gpio = <&gpio2 0 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio2 1 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio2 2 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp11: sfp-p11 { @@ -180,7 +170,6 @@ los-gpio = <&gpio2 9 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio2 10 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; sfp12: sfp-p12 { @@ -189,7 +178,6 @@ los-gpio = <&gpio2 6 GPIO_ACTIVE_HIGH>; mod-def0-gpio = <&gpio2 7 GPIO_ACTIVE_LOW>; tx-disable-gpio = <&gpio2 8 GPIO_ACTIVE_HIGH>; - #thermal-sensor-cells = <0>; }; }; From 71d0568aa3cbe42dd5969440b5fa987d270936c6 Mon Sep 17 00:00:00 2001 From: Wayen Yan Date: Sun, 14 Jun 2026 11:14:11 +0800 Subject: [PATCH 069/228] thermal: airoha: fix wrong variable in TEMPOFFSETL regmap_write The regmap_write for TEMPOFFSETL should use low_temp but incorrectly uses high_temp, causing the low temperature threshold to be misconfigured. This prevents the low temperature trip point from working properly. Fixes: 7d55e75edc87 ("thermal: airoha: convert to regmap API") Signed-off-by: Wayen Yan Link: https://github.com/openwrt/openwrt/pull/23780 Signed-off-by: Jonas Jelonek --- .../402-01-thermal-airoha-convert-to-regmap-API.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/airoha/patches-6.18/402-01-thermal-airoha-convert-to-regmap-API.patch b/target/linux/airoha/patches-6.18/402-01-thermal-airoha-convert-to-regmap-API.patch index 9414bef9cb..6b6cbc3dd0 100644 --- a/target/linux/airoha/patches-6.18/402-01-thermal-airoha-convert-to-regmap-API.patch +++ b/target/linux/airoha/patches-6.18/402-01-thermal-airoha-convert-to-regmap-API.patch @@ -41,7 +41,7 @@ Signed-off-by: Christian Marangi - writel(TEMP_TO_RAW(priv, low) >> 4, - priv->base + EN7581_TEMPOFFSETL); + regmap_write(priv->map, EN7581_TEMPOFFSETL, -+ TEMP_TO_RAW(priv, high) >> 4); ++ TEMP_TO_RAW(priv, low) >> 4); enable_monitor = true; } From 3aeb95bf226133d745a1c58702ad0ecab3d63de3 Mon Sep 17 00:00:00 2001 From: Wayen Yan Date: Sun, 14 Jun 2026 11:19:21 +0800 Subject: [PATCH 070/228] uart: airoha: fix out-of-bounds access in baud rate calculation The baud rate table lookup does not check if the requested index is within bounds before accessing the array. This can cause out-of-bounds read when an unsupported baud rate is requested. Signed-off-by: Wayen Yan Link: https://github.com/openwrt/openwrt/pull/23783 Signed-off-by: Jonas Jelonek --- .../airoha/patches-6.18/886-uart-add-en7523-support.patch | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/linux/airoha/patches-6.18/886-uart-add-en7523-support.patch b/target/linux/airoha/patches-6.18/886-uart-add-en7523-support.patch index 4a94fb4945..1118066013 100644 --- a/target/linux/airoha/patches-6.18/886-uart-add-en7523-support.patch +++ b/target/linux/airoha/patches-6.18/886-uart-add-en7523-support.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/drivers/tty/serial/8250/8250_en7523.c -@@ -0,0 +1,94 @@ +@@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Airoha EN7523 driver. @@ -84,6 +84,8 @@ + xyd_x = ((nom/denom) << 4); + if (xyd_x < XYD_Y) break; + } ++ if (i >= CLOCK_DIV_TAB_ELEMS) ++ i = CLOCK_DIV_TAB_ELEMS - 1; + + serial_port_out(port, UART_XINCLKDR, clock_div_reg[i]); + serial_port_out(port, UART_XYD, (xyd_x<<16) | XYD_Y); From 6590a3d656449e08664ceb97192f6d7f73ea6a63 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Wed, 17 Jun 2026 09:20:02 +0000 Subject: [PATCH 071/228] realtek: pcs: rtl83xx: move reset into activation RTL838x and RTL839x call a reset at the end of their setup procedure while RTL93xx do not do that. Since this is another hurdle for unifying the setup procedure, move them to the activation hooks for now. This retains behavior for both variants. Though something is called now for RTL839x, the reset still skips 5G SerDes. Link: https://github.com/openwrt/openwrt/pull/23861 Signed-off-by: Jonas Jelonek --- .../realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index e236b94df2..51eafa3784 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -768,6 +768,8 @@ static int rtpcs_838x_sds_activate(struct rtpcs_serdes *sds) { int ret; + rtpcs_838x_sds_reset(sds); + /* CFG_FIB_PDOWN / BMCR_PDOWN */ ret = rtpcs_sds_write_bits(sds, 2, MII_BMCR, 11, 11, 0x0); if (ret) @@ -902,8 +904,6 @@ static int rtpcs_838x_setup_serdes(struct rtpcs_serdes *sds, return ret; sds->hw_mode = hw_mode; - - rtpcs_838x_sds_reset(sds); return 0; } @@ -1152,6 +1152,7 @@ static int rtpcs_839x_sds_deactivate(struct rtpcs_serdes *sds) static int rtpcs_839x_sds_activate(struct rtpcs_serdes *sds) { + rtpcs_839x_sds_reset(sds); return 0; } @@ -1172,8 +1173,6 @@ static int rtpcs_839x_setup_serdes(struct rtpcs_serdes *sds, return ret; sds->hw_mode = hw_mode; - - rtpcs_839x_sds_reset(sds); return 0; } From 3aca9acdb3ea0c022e853603860a911f0fd25b33 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Wed, 17 Jun 2026 14:21:45 +0000 Subject: [PATCH 072/228] realtek: pcs: move mode setting to pcs_config Right now, setting the hardware mode of a SerDes is always the last step in setup_serdes for each variant and more or less does exactly the same. Drop that redundancy, replacing it with a ops hook and unified call from pcs_config. This changes behavior for RTL839x. Before, setup for 5G SerDes was skipped entirely. Now, the mode is set properly. Tested on a device, this has no negative effect. Link: https://github.com/openwrt/openwrt/pull/23861 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 50 +++++-------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 51eafa3784..dd8d22ddc3 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -199,6 +199,8 @@ struct rtpcs_sds_ops { int (*deactivate)(struct rtpcs_serdes *sds); /* required: power back up */ int (*activate)(struct rtpcs_serdes *sds); + /* required: set hardware mode */ + int (*set_hw_mode)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); /* optional: finalization that must follow power-up, e.g. RX calibration */ int (*post_config)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); }; @@ -895,16 +897,7 @@ static int rtpcs_838x_init(struct rtpcs_ctrl *ctrl) static int rtpcs_838x_setup_serdes(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { - int ret; - - rtpcs_838x_sds_patch(sds, hw_mode); - - ret = rtpcs_838x_sds_set_mode(sds, hw_mode); - if (ret) - return ret; - - sds->hw_mode = hw_mode; - return 0; + return rtpcs_838x_sds_patch(sds, hw_mode); } static int rtpcs_838x_sds_post_config(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) @@ -1159,20 +1152,6 @@ static int rtpcs_839x_sds_activate(struct rtpcs_serdes *sds) static int rtpcs_839x_setup_serdes(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { - int ret; - - /* Don't touch 5G SerDes, they are already properly configured - * at startup for QSGMII. Thus, connected PHYs should work out - * of the box. - */ - if (sds->type == RTPCS_SDS_TYPE_5G) - return 0; - - ret = rtpcs_sds_set_mac_mode(sds, hw_mode); - if (ret < 0) - return ret; - - sds->hw_mode = hw_mode; return 0; } @@ -3088,13 +3067,6 @@ static int rtpcs_930x_setup_serdes(struct rtpcs_serdes *sds, rtpcs_930x_sds_tx_config(sds, hw_mode); - /* Enable SDS in desired mode */ - ret = rtpcs_930x_sds_set_mode(sds, hw_mode); - if (ret < 0) - return ret; - - sds->hw_mode = hw_mode; - return 0; } @@ -3890,12 +3862,6 @@ static int rtpcs_931x_setup_serdes(struct rtpcs_serdes *sds, return ret; } - ret = rtpcs_931x_sds_set_mode(sds, hw_mode); - if (ret < 0) - return ret; - - sds->hw_mode = hw_mode; - return 0; } @@ -4128,6 +4094,12 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, if (ret < 0) return ret; + ret = sds->ops->set_hw_mode(sds, hw_mode); + if (ret < 0) + return ret; + + sds->hw_mode = hw_mode; + ret = sds->ops->activate(sds); if (ret < 0) return ret; @@ -4417,6 +4389,7 @@ static const struct rtpcs_sds_ops rtpcs_838x_sds_ops = { .restart_autoneg = rtpcs_generic_sds_restart_autoneg, .deactivate = rtpcs_838x_sds_deactivate, .activate = rtpcs_838x_sds_activate, + .set_hw_mode = rtpcs_838x_sds_set_mode, .post_config = rtpcs_838x_sds_post_config, }; @@ -4457,6 +4430,7 @@ static const struct rtpcs_sds_ops rtpcs_839x_sds_ops = { .restart_autoneg = rtpcs_generic_sds_restart_autoneg, .deactivate = rtpcs_839x_sds_deactivate, .activate = rtpcs_839x_sds_activate, + .set_hw_mode = rtpcs_sds_set_mac_mode, }; static const struct rtpcs_sds_regs rtpcs_839x_sds_regs = { @@ -4502,6 +4476,7 @@ static const struct rtpcs_sds_ops rtpcs_930x_sds_ops = { .config_polarity = rtpcs_930x_sds_config_polarity, .deactivate = rtpcs_930x_sds_deactivate, .activate = rtpcs_930x_sds_activate, + .set_hw_mode = rtpcs_930x_sds_set_mode, .post_config = rtpcs_930x_sds_post_config, }; @@ -4547,6 +4522,7 @@ static const struct rtpcs_sds_ops rtpcs_931x_sds_ops = { .config_polarity = rtpcs_931x_sds_config_polarity, .deactivate = rtpcs_931x_sds_deactivate, .activate = rtpcs_931x_sds_activate, + .set_hw_mode = rtpcs_931x_sds_set_mode, }; static const struct rtpcs_sds_regs rtpcs_931x_sds_regs = { From 458e498c1fa4313802952f624e34767574b2e807 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Wed, 17 Jun 2026 08:35:52 +0000 Subject: [PATCH 073/228] realtek: pcs: carve out media selection as generic So far, RTL931x implemented its media selection logic within setup_serdes, unavailable to potential other users. One of those is RTL930x which needs this too. To easy further refactoring, carve out the logic to a generic helper providing the equal selection for all variants anyway. Link: https://github.com/openwrt/openwrt/pull/23861 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index dd8d22ddc3..a18bed919e 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -512,6 +512,26 @@ static int rtpcs_sds_determine_hw_mode(struct rtpcs_serdes *sds, return 0; } +static int rtpcs_sds_select_media(enum rtpcs_sds_mode hw_mode, enum rtpcs_sds_media *media) +{ + switch (hw_mode) { + case RTPCS_SDS_MODE_OFF: + *media = RTPCS_SDS_MEDIA_NONE; + break; + case RTPCS_SDS_MODE_SGMII: + case RTPCS_SDS_MODE_1000BASEX: + case RTPCS_SDS_MODE_2500BASEX: + case RTPCS_SDS_MODE_10GBASER: + *media = RTPCS_SDS_MEDIA_FIBER; + break; + default: + *media = RTPCS_SDS_MEDIA_PCB; + break; + } + + return 0; +} + static bool rtpcs_sds_mode_is_usxgmii(enum rtpcs_sds_mode hw_mode) { return (hw_mode == RTPCS_SDS_MODE_USXGMII_10GSXGMII || @@ -3842,20 +3862,10 @@ static int rtpcs_931x_setup_serdes(struct rtpcs_serdes *sds, if (ret < 0) return ret; - switch (hw_mode) { - case RTPCS_SDS_MODE_OFF: - sds_media = RTPCS_SDS_MEDIA_NONE; - break; - case RTPCS_SDS_MODE_SGMII: - case RTPCS_SDS_MODE_1000BASEX: - case RTPCS_SDS_MODE_2500BASEX: - case RTPCS_SDS_MODE_10GBASER: - sds_media = RTPCS_SDS_MEDIA_FIBER; - break; - default: - sds_media = RTPCS_SDS_MEDIA_PCB; - break; - } + ret = rtpcs_sds_select_media(hw_mode, &sds_media); + if (ret < 0) + return ret; + ret = rtpcs_931x_sds_set_media(sds, sds_media, hw_mode); if (ret < 0) { dev_err(ctrl->dev, "failed to config SerDes for media: %d\n", ret); From 97b48adb0f318273de63130db8f15d3a58e1bc3d Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Wed, 17 Jun 2026 09:06:00 +0000 Subject: [PATCH 074/228] realtek: pcs: encapsule rtl930x media config in function Move the two pieces for media configuration from RTL930x's setup_serdes into a separate function, having the same encapsulation as RTL931x. This will further allow to unify the setup sequence, and play a central role in refactoring of the whole calibration code later. Link: https://github.com/openwrt/openwrt/pull/23861 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index a18bed919e..cde06a2a65 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -3066,9 +3066,24 @@ static int rtpcs_930x_sds_cmu_band_get(struct rtpcs_serdes *sds) return cmu_band; } +static int rtpcs_930x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_media media, + enum rtpcs_sds_mode hw_mode) +{ + /* + * dal_longan_construct_mac_default_10gmedia_fiber: set medium to fiber. + * TODO: this is unconditional regardless of hw_mode; needs mode-aware + * handling. + */ + rtpcs_sds_write_bits(sds, 0x1f, 11, 1, 1, 1); + + rtpcs_930x_sds_tx_config(sds, hw_mode); + return 0; +} + static int rtpcs_930x_setup_serdes(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { + enum rtpcs_sds_media sds_media; int ret; /* Apply configuration for a hardware mode to SerDes */ @@ -3078,14 +3093,13 @@ static int rtpcs_930x_setup_serdes(struct rtpcs_serdes *sds, /* Maybe use dal_longan_sds_init */ - /* - * dal_longan_construct_mac_default_10gmedia_fiber: set medium to fiber. - * TODO: this is unconditional regardless of hw_mode; needs mode-aware - * handling. - */ - rtpcs_sds_write_bits(sds, 0x1f, 11, 1, 1, 1); + ret = rtpcs_sds_select_media(hw_mode, &sds_media); + if (ret < 0) + return ret; - rtpcs_930x_sds_tx_config(sds, hw_mode); + ret = rtpcs_930x_sds_config_media(sds, sds_media, hw_mode); + if (ret < 0) + return ret; return 0; } From 9156053a1a44cfee44e7894f086bc398b0fa3588 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Wed, 17 Jun 2026 09:09:17 +0000 Subject: [PATCH 075/228] realtek: pcs: rtl931x: adjust function naming Rename the RTL931x function _sds_set_media to _sds_config_media to (1) match the RTL930x name and (2) better express what it's doing. It's not just setting the media type, it's configuring media-specific parameters. Link: https://github.com/openwrt/openwrt/pull/23861 Signed-off-by: Jonas Jelonek --- .../linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index cde06a2a65..fc1fa296e3 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -3689,8 +3689,8 @@ static int rtpcs_931x_sds_config_rx(struct rtpcs_serdes *sds, return 0; } -static int rtpcs_931x_sds_set_media(struct rtpcs_serdes *sds, enum rtpcs_sds_media sds_media, - enum rtpcs_sds_mode hw_mode) +static int rtpcs_931x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_media sds_media, + enum rtpcs_sds_mode hw_mode) { struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); bool is_dac, is_10g; @@ -3880,7 +3880,7 @@ static int rtpcs_931x_setup_serdes(struct rtpcs_serdes *sds, if (ret < 0) return ret; - ret = rtpcs_931x_sds_set_media(sds, sds_media, hw_mode); + ret = rtpcs_931x_sds_config_media(sds, sds_media, hw_mode); if (ret < 0) { dev_err(ctrl->dev, "failed to config SerDes for media: %d\n", ret); return ret; From 84b63cfa755b45d7c7188104ddaf6fa1f36992af Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Thu, 18 Jun 2026 07:20:21 +0000 Subject: [PATCH 076/228] realtek: pcs: move media configuration to pcs_config As next step, move the media configuration to pcs_config by adding another optional SerDes ops hook which is called from pcs_config. Drop the redundant call sites in setup_serdes then. Link: https://github.com/openwrt/openwrt/pull/23861 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index fc1fa296e3..87fe421400 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -201,6 +201,9 @@ struct rtpcs_sds_ops { int (*activate)(struct rtpcs_serdes *sds); /* required: set hardware mode */ int (*set_hw_mode)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); + /* optional: configure media-specific parameters */ + int (*config_media)(struct rtpcs_serdes *sds, enum rtpcs_sds_media media, + enum rtpcs_sds_mode hw_mode); /* optional: finalization that must follow power-up, e.g. RX calibration */ int (*post_config)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); }; @@ -3083,7 +3086,6 @@ static int rtpcs_930x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_ static int rtpcs_930x_setup_serdes(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { - enum rtpcs_sds_media sds_media; int ret; /* Apply configuration for a hardware mode to SerDes */ @@ -3093,14 +3095,6 @@ static int rtpcs_930x_setup_serdes(struct rtpcs_serdes *sds, /* Maybe use dal_longan_sds_init */ - ret = rtpcs_sds_select_media(hw_mode, &sds_media); - if (ret < 0) - return ret; - - ret = rtpcs_930x_sds_config_media(sds, sds_media, hw_mode); - if (ret < 0) - return ret; - return 0; } @@ -3864,8 +3858,6 @@ static int rtpcs_931x_sds_config_hw_mode(struct rtpcs_serdes *sds, static int rtpcs_931x_setup_serdes(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { - struct rtpcs_ctrl *ctrl = sds->ctrl; - enum rtpcs_sds_media sds_media; int ret; ret = rtpcs_931x_sds_config_hw_mode(sds, hw_mode); @@ -3876,16 +3868,6 @@ static int rtpcs_931x_setup_serdes(struct rtpcs_serdes *sds, if (ret < 0) return ret; - ret = rtpcs_sds_select_media(hw_mode, &sds_media); - if (ret < 0) - return ret; - - ret = rtpcs_931x_sds_config_media(sds, sds_media, hw_mode); - if (ret < 0) { - dev_err(ctrl->dev, "failed to config SerDes for media: %d\n", ret); - return ret; - } - return 0; } @@ -4088,6 +4070,7 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, struct rtpcs_link *link = rtpcs_phylink_pcs_to_link(pcs); struct rtpcs_ctrl *ctrl = link->ctrl; struct rtpcs_serdes *sds = link->sds; + enum rtpcs_sds_media sds_media; enum rtpcs_sds_mode hw_mode; int ret; @@ -4118,6 +4101,16 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, if (ret < 0) return ret; + if (sds->ops->config_media) { + ret = rtpcs_sds_select_media(hw_mode, &sds_media); + if (ret < 0) + return ret; + + ret = sds->ops->config_media(sds, sds_media, hw_mode); + if (ret < 0) + return ret; + } + ret = sds->ops->set_hw_mode(sds, hw_mode); if (ret < 0) return ret; @@ -4501,6 +4494,7 @@ static const struct rtpcs_sds_ops rtpcs_930x_sds_ops = { .deactivate = rtpcs_930x_sds_deactivate, .activate = rtpcs_930x_sds_activate, .set_hw_mode = rtpcs_930x_sds_set_mode, + .config_media = rtpcs_930x_sds_config_media, .post_config = rtpcs_930x_sds_post_config, }; @@ -4547,6 +4541,7 @@ static const struct rtpcs_sds_ops rtpcs_931x_sds_ops = { .deactivate = rtpcs_931x_sds_deactivate, .activate = rtpcs_931x_sds_activate, .set_hw_mode = rtpcs_931x_sds_set_mode, + .config_media = rtpcs_931x_sds_config_media, }; static const struct rtpcs_sds_regs rtpcs_931x_sds_regs = { From f6d95ca8c2f743378a3e974818b7f221839c1642 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Thu, 18 Jun 2026 07:24:46 +0000 Subject: [PATCH 077/228] realtek: pcs: rtl931x: call CMU config from hw mode config One deviating piece left is the extra call in 931x's setup_serdes to config_cmu. It is called right after the hw mode configuration, in contrast to 930x. Until we find a better home, move it to the end of config_hw_mode to retain behavior but to pave the way for the final unification steps. Link: https://github.com/openwrt/openwrt/pull/23861 Signed-off-by: Jonas Jelonek --- .../linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 87fe421400..4a24fe39ce 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -3852,7 +3852,7 @@ static int rtpcs_931x_sds_config_hw_mode(struct rtpcs_serdes *sds, return -ENOTSUPP; } - return 0; + return rtpcs_93xx_sds_config_cmu(sds, hw_mode); } static int rtpcs_931x_setup_serdes(struct rtpcs_serdes *sds, @@ -3864,10 +3864,6 @@ static int rtpcs_931x_setup_serdes(struct rtpcs_serdes *sds, if (ret < 0) return ret; - ret = rtpcs_93xx_sds_config_cmu(sds, hw_mode); - if (ret < 0) - return ret; - return 0; } From 4ec2d6dd974751fede83ad69c6b4a4a29d973c77 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Thu, 18 Jun 2026 07:46:12 +0000 Subject: [PATCH 078/228] realtek: pcs: drop setup_serdes Introducing the setup_serdes hook in the PCS driver was always intended to be only a temporary solution. It was needed to be able to collect all scattered code in the PCS driver first. Later, refactoring can be done to bring everything into a proper shape. Now we've reached the point where the setup of all variants has been refactored in such a way that all share the same high-level sequence. This is fully orchestrated in pcs_config now. Thus, the setup_serdes hook is no longer needed. Move the last piece out of it into another SerDes op hook, then drop setup_serdes. Link: https://github.com/openwrt/openwrt/pull/23861 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 56 +++++-------------- 1 file changed, 13 insertions(+), 43 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 4a24fe39ce..d03bc77707 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -199,6 +199,8 @@ struct rtpcs_sds_ops { int (*deactivate)(struct rtpcs_serdes *sds); /* required: power back up */ int (*activate)(struct rtpcs_serdes *sds); + /* required: configure SerDes for hardware mode */ + int (*config_hw_mode)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); /* required: set hardware mode */ int (*set_hw_mode)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); /* optional: configure media-specific parameters */ @@ -278,7 +280,6 @@ struct rtpcs_config { int (*init)(struct rtpcs_ctrl *ctrl); int (*sds_probe)(struct rtpcs_serdes *sds); - int (*setup_serdes)(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode); }; struct rtpcs_sds_config { @@ -843,8 +844,7 @@ static int rtpcs_838x_sds_set_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode 0x7 << int_mode_shift, int_mode_val << int_mode_shift); } -static int rtpcs_838x_sds_patch(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) +static int rtpcs_838x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { struct rtpcs_ctrl *ctrl = sds->ctrl; u8 sds_id = sds->id; @@ -917,12 +917,6 @@ static int rtpcs_838x_init(struct rtpcs_ctrl *ctrl) return 0; } -static int rtpcs_838x_setup_serdes(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - return rtpcs_838x_sds_patch(sds, hw_mode); -} - static int rtpcs_838x_sds_post_config(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { /* @@ -1172,8 +1166,11 @@ static int rtpcs_839x_sds_activate(struct rtpcs_serdes *sds) return 0; } -static int rtpcs_839x_setup_serdes(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) +/* + * Keep this as a no-op stub until RTL839x is extended to do proper configuration + * here. E.g., the still missing SGMII, 100BASEX and 1000BASEX setup should go here. + */ +static int rtpcs_839x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { return 0; } @@ -3083,21 +3080,6 @@ static int rtpcs_930x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_ return 0; } -static int rtpcs_930x_setup_serdes(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - int ret; - - /* Apply configuration for a hardware mode to SerDes */ - ret = rtpcs_930x_sds_config_hw_mode(sds, hw_mode); - if (ret < 0) - return ret; - - /* Maybe use dal_longan_sds_init */ - - return 0; -} - static int rtpcs_930x_sds_post_config(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { int calib_tries = 0; @@ -3855,18 +3837,6 @@ static int rtpcs_931x_sds_config_hw_mode(struct rtpcs_serdes *sds, return rtpcs_93xx_sds_config_cmu(sds, hw_mode); } -static int rtpcs_931x_setup_serdes(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - int ret; - - ret = rtpcs_931x_sds_config_hw_mode(sds, hw_mode); - if (ret < 0) - return ret; - - return 0; -} - /** * rtpcs_931x_init_mac_groups - Initialize MAC groups * @@ -4093,7 +4063,7 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, if (ret < 0) return ret; - ret = ctrl->cfg->setup_serdes(sds, hw_mode); + ret = sds->ops->config_hw_mode(sds, hw_mode); if (ret < 0) return ret; @@ -4402,6 +4372,7 @@ static const struct rtpcs_sds_ops rtpcs_838x_sds_ops = { .restart_autoneg = rtpcs_generic_sds_restart_autoneg, .deactivate = rtpcs_838x_sds_deactivate, .activate = rtpcs_838x_sds_activate, + .config_hw_mode = rtpcs_838x_sds_config_hw_mode, .set_hw_mode = rtpcs_838x_sds_set_mode, .post_config = rtpcs_838x_sds_post_config, }; @@ -4427,7 +4398,6 @@ static const struct rtpcs_config rtpcs_838x_cfg = { .sds_hw_mode_vals = rtpcs_838x_sds_hw_mode_vals, .init = rtpcs_838x_init, .sds_probe = rtpcs_838x_sds_probe, - .setup_serdes = rtpcs_838x_setup_serdes, }; static const struct phylink_pcs_ops rtpcs_839x_pcs_ops = { @@ -4443,6 +4413,7 @@ static const struct rtpcs_sds_ops rtpcs_839x_sds_ops = { .restart_autoneg = rtpcs_generic_sds_restart_autoneg, .deactivate = rtpcs_839x_sds_deactivate, .activate = rtpcs_839x_sds_activate, + .config_hw_mode = rtpcs_839x_sds_config_hw_mode, .set_hw_mode = rtpcs_sds_set_mac_mode, }; @@ -4467,7 +4438,6 @@ static const struct rtpcs_config rtpcs_839x_cfg = { .sds_hw_mode_vals = rtpcs_839x_sds_hw_mode_vals, .init = rtpcs_839x_init, .sds_probe = rtpcs_839x_sds_probe, - .setup_serdes = rtpcs_839x_setup_serdes, }; static const struct phylink_pcs_ops rtpcs_930x_pcs_ops = { @@ -4489,6 +4459,7 @@ static const struct rtpcs_sds_ops rtpcs_930x_sds_ops = { .config_polarity = rtpcs_930x_sds_config_polarity, .deactivate = rtpcs_930x_sds_deactivate, .activate = rtpcs_930x_sds_activate, + .config_hw_mode = rtpcs_930x_sds_config_hw_mode, .set_hw_mode = rtpcs_930x_sds_set_mode, .config_media = rtpcs_930x_sds_config_media, .post_config = rtpcs_930x_sds_post_config, @@ -4515,7 +4486,6 @@ static const struct rtpcs_config rtpcs_930x_cfg = { .sds_hw_mode_vals = rtpcs_93xx_sds_hw_mode_vals, .init = rtpcs_93xx_init, .sds_probe = rtpcs_930x_sds_probe, - .setup_serdes = rtpcs_930x_setup_serdes, }; static const struct phylink_pcs_ops rtpcs_931x_pcs_ops = { @@ -4536,6 +4506,7 @@ static const struct rtpcs_sds_ops rtpcs_931x_sds_ops = { .config_polarity = rtpcs_931x_sds_config_polarity, .deactivate = rtpcs_931x_sds_deactivate, .activate = rtpcs_931x_sds_activate, + .config_hw_mode = rtpcs_931x_sds_config_hw_mode, .set_hw_mode = rtpcs_931x_sds_set_mode, .config_media = rtpcs_931x_sds_config_media, }; @@ -4561,7 +4532,6 @@ static const struct rtpcs_config rtpcs_931x_cfg = { .sds_hw_mode_vals = rtpcs_93xx_sds_hw_mode_vals, .init = rtpcs_931x_init, .sds_probe = rtpcs_931x_sds_probe, - .setup_serdes = rtpcs_931x_setup_serdes, }; static const struct of_device_id rtpcs_of_match[] = { From cdb3dee613d1c0aea5236e8b7cbcdfa984c80ba9 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Wed, 17 Jun 2026 19:44:29 +0200 Subject: [PATCH 079/228] generic: 6.18: backport netdev_from_priv() helper Backport netdev_from_priv() helper from upstream kernel to reduce patch delta on backporting new driver and fixes from upstream kernel. Link: https://github.com/openwrt/openwrt/pull/23849 Signed-off-by: Christian Marangi --- ...v7.1-net-add-netdev_from_priv-helper.patch | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 target/linux/generic/backport-6.18/601-v7.1-net-add-netdev_from_priv-helper.patch diff --git a/target/linux/generic/backport-6.18/601-v7.1-net-add-netdev_from_priv-helper.patch b/target/linux/generic/backport-6.18/601-v7.1-net-add-netdev_from_priv-helper.patch new file mode 100644 index 0000000000..3586c3f36f --- /dev/null +++ b/target/linux/generic/backport-6.18/601-v7.1-net-add-netdev_from_priv-helper.patch @@ -0,0 +1,35 @@ +From eb37011395f12138056a4d124159f1a8436662d3 Mon Sep 17 00:00:00 2001 +From: Qingfang Deng +Date: Fri, 20 Mar 2026 15:56:03 +0800 +Subject: [PATCH] net: add netdev_from_priv() helper + +Add a helper to get netdev from private data pointer, so drivers won't +have to store redundant netdev in priv. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20260320075605.490832-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +--- + include/linux/netdevice.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2750,6 +2750,17 @@ static inline void *netdev_priv(const st + return (void *)dev->priv; + } + ++/** ++ * netdev_from_priv() - get network device from priv ++ * @priv: network device private data ++ * ++ * Returns: net_device to which @priv belongs ++ */ ++static inline struct net_device *netdev_from_priv(const void *priv) ++{ ++ return container_of(priv, struct net_device, priv); ++} ++ + /* Set the sysfs physical device reference for the network logical device + * if set prior to registration will cause a symlink during initialization. + */ From 3ed5f087337c6e3d23da446647193c07277a39b4 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Wed, 17 Jun 2026 19:47:16 +0200 Subject: [PATCH 080/228] airoha: replace multi serdes patch with upstream kernel version Now that multi serdes patch are accepted upstream, reorder the current patch in the 1xx numbering and add the kernel version tag. Also replace the downstream patch with the exact version merged upstream. Downstream PCS implementation is updated with a new revision for the ethernet code. Update any patch affected by these changes. Link: https://github.com/openwrt/openwrt/pull/23849 Signed-off-by: Christian Marangi --- ...flow-control-source-port-mapping-dep.patch | 2 +- ...PE-cpu-port-configuration-for-GDM2-l.patch | 2 +- ...oha-Introduce-airoha_gdm_dev-struct.patch} | 463 ++++-------------- ...iroha_qdma-pointer-in-airoha_gdm_de.patch} | 151 ++---- ...n-airoha_gdm_dev-pointer-in-airoha_.patch} | 21 +- ...os_sq_bmap-in-airoha_gdm_dev-struct.patch} | 51 +- ...pu-fwd-_tx_packets-in-airoha_gdm_de.patch} | 22 +- ...e-airoha_set_gdm2_loopback-in-airoha.patch | 38 ++ ...se-after-free-in-metadata-dst-teardo.patch | 37 ++ ...t-extack-error-to-the-user-if-airoha.patch | 40 ++ ...ULL-check-for-of_reserved_mem_lookup.patch | 41 ++ ...e-private-net_device-pointer-in-airo.patch | 125 +++++ ...t-multiple-net_devices-for-a-single.patch} | 190 +++---- ...o-not-stop-GDM-port-if-it-is-shared.patch} | 46 +- ...et-airoha-Introduce-WAN-device-flag.patch} | 29 +- ...t-multiple-LAN-WAN-interfaces-for-h.patch} | 48 +- ...-handle-MIBs-for-GDM-ports-with-mul.patch} | 76 +-- ...t-instead-of-atomic_t-for-qdma-user.patch} | 15 +- ...get_sport-callback-at-the-beginning-.patch | 50 ++ ...fy-WAN-device-check-in-airoha_dev_i.patch} | 10 +- ...-airoha-deassert-XSI-line-on-hw-init.patch | 2 +- ...eference-for-SPORT-GDM4-in-qdma_get_.patch | 31 -- ...nitial-fixup-for-GDM3-4-port-support.patch | 12 +- ...7-airoha-ethernet-drop-xsi-mac-reset.patch | 4 +- ...oha-add-phylink-support-for-GDM2-3-4.patch | 281 ----------- ...10-10-net-airoha-add-phylink-support.patch | 361 ++++++++++++++ ...t-airoha-define-sport-value-for-GDM3.patch | 26 - ...le-external-phy-code-if-PCS_AIROHA-i.patch | 124 ----- ...w-QoS-parameter-according-to-the-pac.patch | 22 +- ...-airoha-Implement-HW-GRO-TCP-support.patch | 227 +++++---- ...e-airoha_set_gdm2_loopback-in-airoha.patch | 37 -- ...-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch | 78 ++- ...-net-airoha-Rework-MTU-configuration.patch | 20 +- ...-airoha-fix-wrong-airoha_get_fe_port.patch | 2 +- ...get_sport-callback-at-the-beginning-.patch | 36 -- 35 files changed, 1258 insertions(+), 1462 deletions(-) rename target/linux/airoha/patches-6.18/{920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch => 161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch} (63%) rename target/linux/airoha/patches-6.18/{920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch => 161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch} (72%) rename target/linux/airoha/patches-6.18/{920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch => 161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch} (75%) rename target/linux/airoha/patches-6.18/{920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch => 161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch} (80%) rename target/linux/airoha/patches-6.18/{920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch => 161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch} (76%) create mode 100644 target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch create mode 100644 target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch create mode 100644 target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch create mode 100644 target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch create mode 100644 target/linux/airoha/patches-6.18/165-01-v7.2-net-airoha-Remove-private-net_device-pointer-in-airo.patch rename target/linux/airoha/patches-6.18/{920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch => 165-02-v7.2-net-airoha-Support-multiple-net_devices-for-a-single.patch} (77%) rename target/linux/airoha/patches-6.18/{920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch => 165-03-v7.2-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch} (70%) rename target/linux/airoha/patches-6.18/{920-08-net-airoha-Introduce-WAN-device-flag.patch => 165-04-v7.2-net-airoha-Introduce-WAN-device-flag.patch} (83%) rename target/linux/airoha/patches-6.18/{920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch => 165-05-v7.2-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch} (75%) rename target/linux/airoha/patches-6.18/{920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch => 166-v7.2-net-airoha-better-handle-MIBs-for-GDM-ports-with-mul.patch} (87%) rename target/linux/airoha/patches-6.18/{916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch => 167-v7.2-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch} (75%) create mode 100644 target/linux/airoha/patches-6.18/168-v7.2-net-airoha-move-get_sport-callback-at-the-beginning-.patch rename target/linux/airoha/patches-6.18/{922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch => 169-v7.2-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch} (77%) delete mode 100644 target/linux/airoha/patches-6.18/310-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch delete mode 100644 target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support-for-GDM2-3-4.patch create mode 100644 target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch delete mode 100644 target/linux/airoha/patches-6.18/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch delete mode 100644 target/linux/airoha/patches-6.18/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch delete mode 100644 target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch delete mode 100644 target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch diff --git a/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch b/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch index 7e078d0865..6be83a301b 100644 --- a/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch +++ b/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch @@ -28,7 +28,7 @@ Signed-off-by: Jakub Kicinski - FC_ID_OF_SRC_PORT24_MASK, - FIELD_PREP(FC_ID_OF_SRC_PORT24_MASK, 2)); + if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { -+ u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); ++ u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); + + airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask, + __field_prep(mask, AIROHA_GDM2_IDX)); diff --git a/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch b/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch index 417adfd7db..56ac972956 100644 --- a/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch +++ b/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch @@ -41,7 +41,7 @@ Signed-off-by: Paolo Abeni + airoha_ppe_set_cpu_port(port, i, AIROHA_GDM2_IDX); + if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { - u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); + u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); @@ -1873,7 +1876,8 @@ static int airoha_dev_init(struct net_de } diff --git a/target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch b/target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch similarity index 63% rename from target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch rename to target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch index f92593c504..f6c5f766f2 100644 --- a/target/linux/airoha/patches-6.18/920-01-net-airoha-Introduce-airoha_gdm_dev-struct.patch +++ b/target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch @@ -1,8 +1,7 @@ -From e15783f7c987e199ecf80b3d858ed5a86d33c508 Mon Sep 17 00:00:00 2001 -Message-ID: +From ec6c391bcca748bca041d5db92ff3bc4c99b3572 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 1 Nov 2025 11:25:52 +0100 -Subject: [PATCH 01/13] net: airoha: Introduce airoha_gdm_dev struct +Date: Wed, 27 May 2026 12:21:15 +0200 +Subject: [PATCH 1/6] net: airoha: Introduce airoha_gdm_dev struct EN7581 and AN7583 SoCs support connecting multiple external SerDes to GDM3 or GDM4 ports via a hw arbiter that manages the traffic in a TDM manner. @@ -17,6 +16,8 @@ connected to the same GDM port. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-1-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 312 ++++++++++++++--------- drivers/net/ethernet/airoha/airoha_eth.h | 13 +- @@ -25,18 +26,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -483,8 +483,9 @@ static bool airoha_fe_lro_is_enabled(str - LRO_RXQ_EN_MASK); - } - --static void airoha_dev_lro_enable(struct airoha_gdm_port *port) -+static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) - { -+ struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; -@@ -843,6 +844,7 @@ static int airoha_qdma_rx_process(struct +@@ -600,6 +600,7 @@ static int airoha_qdma_rx_process(struct struct airoha_qdma_desc *desc = &q->desc[q->tail]; u32 hash, reason, msg1, desc_ctrl; struct airoha_gdm_port *port; @@ -44,21 +34,29 @@ Signed-off-by: Lorenzo Bianconi int data_len, len, p; struct page *page; -@@ -869,8 +871,12 @@ static int airoha_qdma_rx_process(struct +@@ -626,6 +627,10 @@ static int airoha_qdma_rx_process(struct goto free_frag; port = eth->ports[p]; + if (!port->dev) + goto free_frag; + -+ netdev = netdev_from_priv(port->dev); ++ netdev = port->dev->dev; if (!q->skb) { /* first buffer */ -- q->skb = airoha_qdma_build_rx_skb(q, desc, e, port->dev); -+ q->skb = airoha_qdma_build_rx_skb(q, desc, e, netdev); - if (!q->skb) - goto free_frag; + q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, + q->buf_size); +@@ -635,8 +640,8 @@ static int airoha_qdma_rx_process(struct + skb_reserve(q->skb, AIROHA_RX_HEADROOM); + __skb_put(q->skb, len); + skb_mark_for_recycle(q->skb); +- q->skb->dev = port->dev; +- q->skb->protocol = eth_type_trans(q->skb, port->dev); ++ q->skb->dev = netdev; ++ q->skb->protocol = eth_type_trans(q->skb, netdev); + q->skb->ip_summed = CHECKSUM_UNNECESSARY; + skb_record_rx_queue(q->skb, qid); } else { /* scattered frame */ -@@ -888,7 +894,7 @@ static int airoha_qdma_rx_process(struct +@@ -654,7 +659,7 @@ static int airoha_qdma_rx_process(struct if (FIELD_GET(QDMA_DESC_MORE_MASK, desc_ctrl)) continue; @@ -67,55 +65,33 @@ Signed-off-by: Lorenzo Bianconi /* PPE module requires untagged packets to work * properly and it provides DSA port index via the * DMA descriptor. Report DSA tag to the DSA stack -@@ -1091,6 +1097,7 @@ static void airoha_qdma_wake_netdev_txqs +@@ -848,6 +853,7 @@ static void airoha_qdma_wake_netdev_txqs for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; -+ struct net_device *netdev; ++ struct airoha_gdm_dev *dev; int j; if (!port) -@@ -1099,11 +1106,12 @@ static void airoha_qdma_wake_netdev_txqs +@@ -856,11 +862,12 @@ static void airoha_qdma_wake_netdev_txqs if (port->qdma != qdma) continue; - for (j = 0; j < port->dev->num_tx_queues; j++) { -+ netdev = netdev_from_priv(port->dev); -+ for (j = 0; j < netdev->num_tx_queues; j++) { ++ dev = port->dev; ++ for (j = 0; j < dev->dev->num_tx_queues; j++) { if (airoha_qdma_get_txq(qdma, j) != qid) continue; - netif_wake_subqueue(port->dev, j); -+ netif_wake_subqueue(netdev, j); ++ netif_wake_subqueue(dev->dev, j); } } q->txq_stopped = false; -@@ -1947,9 +1955,10 @@ static void airoha_update_hw_stats(struc +@@ -1700,19 +1707,20 @@ static void airoha_update_hw_stats(struc spin_unlock(&port->stats.lock); } --static void airoha_update_netdev_features(struct airoha_gdm_port *port) -+static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) - { -- struct airoha_eth *eth = port->eth; -+ struct airoha_gdm_port *port = dev->port; -+ struct airoha_eth *eth = dev->eth; - int i; - - for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { -@@ -1959,7 +1968,7 @@ static void airoha_update_netdev_feature - if (!p) - continue; - -- netdev = p->dev; -+ netdev = netdev_from_priv(p->dev); - if (netdev->reg_state != NETREG_REGISTERED) - continue; - -@@ -1967,10 +1976,11 @@ static void airoha_update_netdev_feature - } - } - -static int airoha_dev_open(struct net_device *dev) +static int airoha_dev_open(struct net_device *netdev) { @@ -125,35 +101,7 @@ Signed-off-by: Lorenzo Bianconi + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; -@@ -1981,31 +1991,32 @@ static int airoha_dev_open(struct net_de - * the same QDMA if LRO is enabled on any device sharing it. - */ - if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { -- netdev_warn(dev, "required to disable HW GRO on QDMA%d\n", -+ netdev_warn(netdev, "required to disable HW GRO on QDMA%d\n", - qdma_id); - return -EBUSY; - } - - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -- err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); -+ err = phylink_of_phy_connect(dev->phylink, -+ netdev->dev.of_node, 0); - if (err) { -- netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -- err); -+ netdev_err(netdev, "%s: could not attach PHY: %d\n", -+ __func__, err); - return err; - } - -- phylink_start(port->phylink); -+ phylink_start(dev->phylink); - } - #endif + u32 pse_port = FE_PSE_PORT_PPE1; - netif_tx_start_all_queues(dev); + netif_tx_start_all_queues(netdev); @@ -161,24 +109,12 @@ Signed-off-by: Lorenzo Bianconi if (err) return err; - /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ -- if (netdev_uses_dsa(dev) || port->id > 2) -+ if (netdev_uses_dsa(netdev) || port->id > 2) - airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id), +- if (netdev_uses_dsa(dev)) ++ if (netdev_uses_dsa(netdev)) + airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); else -@@ -2029,25 +2040,26 @@ static int airoha_dev_open(struct net_de - airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), - pse_port); - -- if (dev->features & NETIF_F_GRO_HW) -- airoha_dev_lro_enable(port); -+ if (netdev->features & NETIF_F_GRO_HW) -+ airoha_dev_lro_enable(dev); - -- airoha_update_netdev_features(port); -+ airoha_update_netdev_features(dev); - +@@ -1740,16 +1748,17 @@ static int airoha_dev_open(struct net_de return 0; } @@ -189,7 +125,6 @@ Signed-off-by: Lorenzo Bianconi + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; int i; - netif_tx_disable(dev); @@ -200,24 +135,9 @@ Signed-off-by: Lorenzo Bianconi + for (i = 0; i < netdev->num_tx_queues; i++) + netdev_tx_reset_subqueue(netdev, i); - airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), + airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), FE_PSE_PORT_DROP); -@@ -2065,28 +2077,29 @@ static int airoha_dev_stop(struct net_de - } - } - -- airoha_update_netdev_features(port); -+ airoha_update_netdev_features(dev); - - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -- phylink_stop(port->phylink); -- phylink_disconnect_phy(port->phylink); -+ phylink_stop(dev->phylink); -+ phylink_disconnect_phy(dev->phylink); - } - #endif - +@@ -1770,16 +1779,17 @@ static int airoha_dev_stop(struct net_de return 0; } @@ -239,7 +159,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2152,16 +2165,17 @@ static int airoha_set_gdm2_loopback(stru +@@ -1845,16 +1855,17 @@ static int airoha_set_gdm2_loopback(stru return 0; } @@ -257,12 +177,12 @@ Signed-off-by: Lorenzo Bianconi port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; - port->dev->irq = port->qdma->irq_banks[0].irq; - airoha_set_macaddr(port, dev->dev_addr); -+ netdev->irq = port->qdma->irq_banks[0].irq; ++ dev->dev->irq = port->qdma->irq_banks[0].irq; + airoha_set_macaddr(port, netdev->dev_addr); switch (port->id) { case AIROHA_GDM3_IDX: -@@ -2186,10 +2200,11 @@ static int airoha_dev_init(struct net_de +@@ -1879,10 +1890,11 @@ static int airoha_dev_init(struct net_de return 0; } @@ -276,7 +196,7 @@ Signed-off-by: Lorenzo Bianconi unsigned int start; airoha_update_hw_stats(port); -@@ -2208,36 +2223,39 @@ static void airoha_dev_get_stats64(struc +@@ -1901,36 +1913,39 @@ static void airoha_dev_get_stats64(struc } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -323,46 +243,7 @@ Signed-off-by: Lorenzo Bianconi } static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev) -@@ -2300,10 +2318,11 @@ int airoha_get_fe_port(struct airoha_gdm - } - } - --static netdev_features_t airoha_dev_fix_features(struct net_device *dev, -+static netdev_features_t airoha_dev_fix_features(struct net_device *netdev, - netdev_features_t features) - { -- struct airoha_gdm_port *port = netdev_priv(dev); -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; - - if (qdma->users > 1) -@@ -2312,11 +2331,12 @@ static netdev_features_t airoha_dev_fix_ - return features; - } - --static int airoha_dev_set_features(struct net_device *dev, -+static int airoha_dev_set_features(struct net_device *netdev, - netdev_features_t features) - { -- netdev_features_t diff = dev->features ^ features; -- struct airoha_gdm_port *port = netdev_priv(dev); -+ netdev_features_t diff = netdev->features ^ features; -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; -@@ -2325,7 +2345,7 @@ static int airoha_dev_set_features(struc - return 0; - - if (features & NETIF_F_GRO_HW) -- airoha_dev_lro_enable(port); -+ airoha_dev_lro_enable(dev); - else - airoha_fe_lro_disable(eth, qdma_id); - -@@ -2333,9 +2353,10 @@ static int airoha_dev_set_features(struc +@@ -1994,9 +2009,10 @@ int airoha_get_fe_port(struct airoha_gdm } static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, @@ -375,7 +256,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_qdma *qdma = port->qdma; u32 nr_frags, tag, msg0, msg1, len; struct airoha_queue_entry *e; -@@ -2348,7 +2369,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2009,7 +2025,7 @@ static netdev_tx_t airoha_dev_xmit(struc u8 fport; qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb)); @@ -384,7 +265,7 @@ Signed-off-by: Lorenzo Bianconi msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK, qid / AIROHA_NUM_QOS_QUEUES) | -@@ -2384,7 +2405,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2045,7 +2061,7 @@ static netdev_tx_t airoha_dev_xmit(struc spin_lock_bh(&q->lock); @@ -393,7 +274,7 @@ Signed-off-by: Lorenzo Bianconi nr_frags = 1 + skb_shinfo(skb)->nr_frags; if (q->queued + nr_frags >= q->ndesc) { -@@ -2408,9 +2429,9 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2069,9 +2085,9 @@ static netdev_tx_t airoha_dev_xmit(struc dma_addr_t addr; u32 val; @@ -405,7 +286,7 @@ Signed-off-by: Lorenzo Bianconi goto error_unmap; list_move_tail(&e->list, &tx_list); -@@ -2459,7 +2480,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2120,7 +2136,7 @@ static netdev_tx_t airoha_dev_xmit(struc error_unmap: list_for_each_entry(e, &tx_list, list) { @@ -414,7 +295,7 @@ Signed-off-by: Lorenzo Bianconi DMA_TO_DEVICE); e->dma_addr = 0; } -@@ -2468,25 +2489,27 @@ error_unmap: +@@ -2129,25 +2145,27 @@ error_unmap: spin_unlock_bh(&q->lock); error: dev_kfree_skb_any(skb); @@ -447,7 +328,7 @@ Signed-off-by: Lorenzo Bianconi unsigned int start; airoha_update_hw_stats(port); -@@ -2514,11 +2537,12 @@ static const struct ethtool_rmon_hist_ra +@@ -2175,11 +2193,12 @@ static const struct ethtool_rmon_hist_ra }; static void @@ -462,7 +343,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_hw_stats *hw_stats = &port->stats; unsigned int start; -@@ -2543,11 +2567,12 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2204,11 +2223,12 @@ airoha_ethtool_get_rmon_stats(struct net } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -477,7 +358,7 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < AIROHA_NUM_TX_RING; i++) -@@ -2632,10 +2657,12 @@ static int airoha_qdma_set_tx_ets_sched( +@@ -2293,10 +2313,12 @@ static int airoha_qdma_set_tx_ets_sched( ARRAY_SIZE(w)); } @@ -492,7 +373,7 @@ Signed-off-by: Lorenzo Bianconi u64 cpu_tx_packets = airoha_qdma_rr(port->qdma, REG_CNTR_VAL(channel << 1)); u64 fwd_tx_packets = airoha_qdma_rr(port->qdma, -@@ -2897,11 +2924,12 @@ static int airoha_qdma_set_trtcm_token_b +@@ -2558,11 +2580,12 @@ static int airoha_qdma_set_trtcm_token_b mode, val); } @@ -507,7 +388,7 @@ Signed-off-by: Lorenzo Bianconi int i, err; for (i = 0; i <= TRTCM_PEAK_MODE; i++) { -@@ -2921,20 +2949,22 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2582,20 +2605,22 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -534,7 +415,7 @@ Signed-off-by: Lorenzo Bianconi if (err) { NL_SET_ERR_MSG_MOD(opt->extack, "failed configuring htb offload"); -@@ -2944,9 +2974,10 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2605,9 +2630,10 @@ static int airoha_tc_htb_alloc_leaf_queu if (opt->command == TC_HTB_NODE_MODIFY) return 0; @@ -547,7 +428,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); return err; -@@ -3036,11 +3067,12 @@ static int airoha_tc_matchall_act_valida +@@ -2697,11 +2723,12 @@ static int airoha_tc_matchall_act_valida return 0; } @@ -562,7 +443,7 @@ Signed-off-by: Lorenzo Bianconi u32 rate = 0, bucket_size = 0; switch (f->command) { -@@ -3075,18 +3107,19 @@ static int airoha_dev_tc_matchall(struct +@@ -2736,18 +2763,19 @@ static int airoha_dev_tc_matchall(struct static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { @@ -586,7 +467,7 @@ Signed-off-by: Lorenzo Bianconi default: return -EOPNOTSUPP; } -@@ -3133,47 +3166,51 @@ static int airoha_dev_setup_tc_block(str +@@ -2794,47 +2822,51 @@ static int airoha_dev_setup_tc_block(str } } @@ -650,7 +531,7 @@ Signed-off-by: Lorenzo Bianconi if (!test_bit(channel, port->qos_sq_bmap)) { NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); -@@ -3209,8 +3246,8 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -2870,8 +2902,8 @@ static int airoha_tc_setup_qdisc_htb(str return 0; } @@ -661,7 +542,7 @@ Signed-off-by: Lorenzo Bianconi { switch (type) { case TC_SETUP_QDISC_ETS: -@@ -3283,13 +3320,18 @@ static void airoha_metadata_dst_free(str +@@ -2937,25 +2969,81 @@ static void airoha_metadata_dst_free(str } } @@ -683,96 +564,9 @@ Signed-off-by: Lorenzo Bianconi return true; } -@@ -3301,8 +3343,9 @@ static void airoha_mac_link_up(struct ph - unsigned int mode, phy_interface_t interface, - int speed, int duplex, bool tx_pause, bool rx_pause) - { -- struct airoha_gdm_port *port = container_of(config, struct airoha_gdm_port, -- phylink_config); -+ struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, -+ phylink_config); -+ struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; - struct airoha_eth *eth = qdma->eth; - u32 frag_size_tx, frag_size_rx; -@@ -3358,65 +3401,121 @@ static int airoha_fill_available_pcs(str - &num_available_pcs); + return false; } --static int airoha_setup_phylink(struct net_device *dev) -+static int airoha_setup_phylink(struct net_device *netdev) - { -- struct airoha_gdm_port *port = netdev_priv(dev); -- struct device_node *np = dev->dev.of_node; -+ struct airoha_gdm_dev *dev = netdev_priv(netdev); -+ struct device_node *np = netdev->dev.of_node; - phy_interface_t phy_mode; - struct phylink *phylink; - int err; - - err = of_get_phy_mode(np, &phy_mode); - if (err) { -- dev_err(&dev->dev, "incorrect phy-mode\n"); -+ dev_err(&netdev->dev, "incorrect phy-mode\n"); - return err; - } - -- port->phylink_config.dev = &dev->dev; -- port->phylink_config.type = PHYLINK_NETDEV; -- port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -- MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | -- MAC_5000FD | MAC_10000FD; -+ dev->phylink_config.dev = &netdev->dev; -+ dev->phylink_config.type = PHYLINK_NETDEV; -+ dev->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -+ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | -+ MAC_5000FD | MAC_10000FD; - -- err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), NULL, -- &port->phylink_config.num_available_pcs); -+ err = fwnode_phylink_pcs_parse(dev_fwnode(&netdev->dev), NULL, -+ &dev->phylink_config.num_available_pcs); - if (err) - return err; - -- port->phylink_config.fill_available_pcs = airoha_fill_available_pcs; -+ dev->phylink_config.fill_available_pcs = airoha_fill_available_pcs; - - __set_bit(PHY_INTERFACE_MODE_SGMII, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_1000BASEX, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_2500BASEX, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_10GBASER, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - __set_bit(PHY_INTERFACE_MODE_USXGMII, -- port->phylink_config.supported_interfaces); -+ dev->phylink_config.supported_interfaces); - -- phy_interface_copy(port->phylink_config.pcs_interfaces, -- port->phylink_config.supported_interfaces); -+ phy_interface_copy(dev->phylink_config.pcs_interfaces, -+ dev->phylink_config.supported_interfaces); - -- phylink = phylink_create(&port->phylink_config, -+ phylink = phylink_create(&dev->phylink_config, - of_fwnode_handle(np), - phy_mode, &airoha_phylink_ops); - if (IS_ERR(phylink)) - return PTR_ERR(phylink); - -- port->phylink = phylink; -+ dev->phylink = phylink; - - return err; - } - #endif - +static int airoha_alloc_gdm_device(struct airoha_eth *eth, + struct airoha_gdm_port *port, + struct device_node *np) @@ -793,9 +587,11 @@ Signed-off-by: Lorenzo Bianconi + netdev->ethtool_ops = &airoha_ethtool_ops; + netdev->max_mtu = AIROHA_MAX_MTU; + netdev->watchdog_timeo = 5 * HZ; -+ netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; -+ netdev->features |= AIROHA_HW_FEATURES; -+ netdev->vlan_features = AIROHA_HW_FEATURES; ++ netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO6 | ++ NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO | ++ NETIF_F_HW_TC; ++ netdev->features |= netdev->hw_features; ++ netdev->vlan_features = netdev->hw_features; + netdev->dev.of_node = np; + SET_NETDEV_DEV(netdev, eth->dev); + @@ -815,18 +611,11 @@ Signed-off-by: Lorenzo Bianconi + } + + dev = netdev_priv(netdev); ++ dev->dev = netdev; + dev->port = port; + port->dev = dev; + dev->eth = eth; + -+#if defined(CONFIG_PCS_AIROHA) -+ if (airhoa_is_phy_external(port)) { -+ err = airoha_setup_phylink(netdev); -+ if (err) -+ return err; -+ } -+#endif -+ + return 0; +} + @@ -839,7 +628,7 @@ Signed-off-by: Lorenzo Bianconi int err, p; u32 id; -@@ -3438,58 +3537,22 @@ static int airoha_alloc_gdm_port(struct +@@ -2977,53 +3065,22 @@ static int airoha_alloc_gdm_port(struct return -EINVAL; } @@ -857,17 +646,20 @@ Signed-off-by: Lorenzo Bianconi - dev->ethtool_ops = &airoha_ethtool_ops; - dev->max_mtu = AIROHA_MAX_MTU; - dev->watchdog_timeo = 5 * HZ; -- dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; -- dev->features |= AIROHA_HW_FEATURES; -- dev->vlan_features = AIROHA_HW_FEATURES; +- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | +- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | +- NETIF_F_SG | NETIF_F_TSO | +- NETIF_F_HW_TC; +- dev->features |= dev->hw_features; +- dev->vlan_features = dev->hw_features; - dev->dev.of_node = np; - SET_NETDEV_DEV(dev, eth->dev); -- + - /* reserve hw queues for HTB offloading */ - err = netif_set_real_num_tx_queues(dev, AIROHA_NUM_TX_RING); - if (err) - return err; - +- - err = of_get_ethdev_address(np, dev); - if (err) { - if (err == -EPROBE_DEFER) @@ -888,32 +680,25 @@ Signed-off-by: Lorenzo Bianconi port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; eth->ports[p] = port; --#if defined(CONFIG_PCS_AIROHA) -- if (airhoa_is_phy_external(port)) { -- err = airoha_setup_phylink(dev); -- if (err) -- return err; -- } --#endif +- return airoha_metadata_dst_alloc(port); + err = airoha_metadata_dst_alloc(port); + if (err) + return err; - -- return airoha_metadata_dst_alloc(port); ++ + return airoha_alloc_gdm_device(eth, port, np); } static int airoha_register_gdm_devices(struct airoha_eth *eth) -@@ -3503,7 +3566,7 @@ static int airoha_register_gdm_devices(s +@@ -3037,7 +3094,7 @@ static int airoha_register_gdm_devices(s if (!port) continue; - err = register_netdev(port->dev); -+ err = register_netdev(netdev_from_priv(port->dev)); ++ err = register_netdev(port->dev->dev); if (err) return err; } -@@ -3612,16 +3675,22 @@ error_napi_stop: +@@ -3146,12 +3203,14 @@ error_napi_stop: for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -922,25 +707,15 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; -- if (port->dev->reg_state == NETREG_REGISTERED) { -+ dev = port->dev; -+ if (dev) { -+ struct net_device *netdev = netdev_from_priv(dev); -+ -+ if (netdev->reg_state == NETREG_REGISTERED) { - #if defined(CONFIG_PCS_AIROHA) -- if (airhoa_is_phy_external(port)) -- phylink_destroy(port->phylink); -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(dev->phylink); - #endif +- if (port->dev->reg_state == NETREG_REGISTERED) - unregister_netdev(port->dev); -+ unregister_netdev(netdev); -+ } - } ++ dev = port->dev; ++ if (dev && dev->dev->reg_state == NETREG_REGISTERED) ++ unregister_netdev(dev->dev); airoha_metadata_dst_free(port); } -@@ -3643,15 +3712,19 @@ static void airoha_remove(struct platfor + airoha_hw_cleanup(eth); +@@ -3172,11 +3231,14 @@ static void airoha_remove(struct platfor for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -949,49 +724,34 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) -- phylink_destroy(port->phylink); -+ phylink_destroy(dev->phylink); - #endif - unregister_netdev(port->dev); -+ + dev = port->dev; + if (dev) -+ unregister_netdev(netdev_from_priv(dev)); ++ unregister_netdev(dev->dev); airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -547,17 +547,21 @@ struct airoha_qdma { +@@ -535,10 +535,15 @@ struct airoha_qdma { struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; }; --struct airoha_gdm_port { -- struct airoha_qdma *qdma; +struct airoha_gdm_dev { + struct airoha_gdm_port *port; - struct airoha_eth *eth; -- struct net_device *dev; -- int id; -- int nbq; - - #if defined(CONFIG_PCS_AIROHA) - struct phylink *phylink; - struct phylink_config phylink_config; - #endif ++ struct net_device *dev; ++ struct airoha_eth *eth; +}; + -+struct airoha_gdm_port { -+ struct airoha_qdma *qdma; + struct airoha_gdm_port { + struct airoha_qdma *qdma; +- struct airoha_eth *eth; +- struct net_device *dev; + struct airoha_gdm_dev *dev; -+ int id; -+ int nbq; + int id; + int nbq; - struct airoha_hw_stats stats; - -@@ -691,8 +695,8 @@ static inline bool airoha_qdma_is_lro_qu +@@ -662,8 +667,8 @@ static inline bool airoha_is_7583(struct } int airoha_get_fe_port(struct airoha_gdm_port *port); @@ -1004,14 +764,14 @@ Signed-off-by: Lorenzo Bianconi u8 fport); --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -299,12 +299,12 @@ static void airoha_ppe_foe_set_bridge_ad +@@ -298,12 +298,12 @@ static void airoha_ppe_foe_set_bridge_ad static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth, struct airoha_foe_entry *hwe, - struct net_device *dev, int type, + struct net_device *netdev, int type, struct airoha_flow_data *data, - int l4proto, u8 dsfield) + int l4proto) { u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val; - int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev); @@ -1019,7 +779,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_foe_mac_info_common *l2; u8 smac_id = 0xf; -@@ -320,10 +320,11 @@ static int airoha_ppe_foe_entry_prepare( +@@ -319,10 +319,11 @@ static int airoha_ppe_foe_entry_prepare( hwe->ib1 = val; val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f); @@ -1033,14 +793,14 @@ Signed-off-by: Lorenzo Bianconi val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, info.idx) | FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, FE_PSE_PORT_CDM4); -@@ -333,12 +334,14 @@ static int airoha_ppe_foe_entry_prepare( +@@ -332,12 +333,14 @@ static int airoha_ppe_foe_entry_prepare( FIELD_PREP(AIROHA_FOE_MAC_WDMA_WCID, info.wcid); } else { - struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_gdm_dev *dev = netdev_priv(netdev); - u8 pse_port, channel, priority; + struct airoha_gdm_port *port; + u8 pse_port, channel; - if (!airoha_is_valid_gdm_port(eth, port)) + if (!airoha_is_valid_gdm_dev(eth, dev)) @@ -1050,33 +810,12 @@ Signed-off-by: Lorenzo Bianconi if (dsa_port >= 0 || eth->ports[1]) pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; -@@ -1484,8 +1487,8 @@ void airoha_ppe_check_skb(struct airoha_ - +@@ -1473,7 +1476,7 @@ void airoha_ppe_check_skb(struct airoha_ void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) { -+ struct net_device *dev = netdev_from_priv(port->dev); struct airoha_eth *eth = port->qdma->eth; - struct net_device *dev = port->dev; ++ struct net_device *dev = port->dev->dev; const u8 *addr = dev->dev_addr; u32 val; ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -2760,6 +2760,17 @@ static inline void *netdev_priv(const st - return (void *)dev->priv; - } - -+/** -+ * netdev_from_priv() - get network device from priv -+ * @priv: network device private data -+ * -+ * Returns: net_device to which @priv belongs -+ */ -+static inline struct net_device *netdev_from_priv(const void *priv) -+{ -+ return container_of(priv, struct net_device, priv); -+} -+ - /* Set the sysfs physical device reference for the network logical device - * if set prior to registration will cause a symlink during initialization. - */ diff --git a/target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch b/target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch similarity index 72% rename from target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch rename to target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch index b95371056f..78388f5c63 100644 --- a/target/linux/airoha/patches-6.18/920-02-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch +++ b/target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch @@ -1,10 +1,7 @@ -From f62cea6483cc55360863d66300790a5fb9de5f7c Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: +From 528c5153a557f69482d91609a2a002ded22a3441 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Tue, 24 Feb 2026 18:43:05 +0100 -Subject: [PATCH 02/13] net: airoha: Move airoha_qdma pointer in airoha_gdm_dev +Date: Wed, 27 May 2026 12:21:16 +0200 +Subject: [PATCH 2/6] net: airoha: Move airoha_qdma pointer in airoha_gdm_dev struct Move airoha_qdma pointer from airoha_gdm_port struct to airoha_gdm_dev @@ -16,6 +13,8 @@ to the same GDM{3,4} port via an external hw arbiter. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-2-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 105 +++++++++++------------ drivers/net/ethernet/airoha/airoha_eth.h | 9 +- @@ -24,9 +23,9 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -81,9 +81,10 @@ static bool airhoa_is_phy_external(struc +@@ -71,9 +71,10 @@ static void airoha_qdma_irq_disable(stru + airoha_qdma_set_irqmask(irq_bank, index, mask, 0); } - #endif -static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) +static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) @@ -37,7 +36,7 @@ Signed-off-by: Lorenzo Bianconi u32 val, reg; reg = airoha_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H -@@ -95,7 +96,7 @@ static void airoha_set_macaddr(struct ai +@@ -85,7 +86,7 @@ static void airoha_set_macaddr(struct ai airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val); airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); @@ -46,7 +45,7 @@ Signed-off-by: Lorenzo Bianconi } static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, -@@ -111,10 +112,10 @@ static void airoha_set_gdm_port_fwd_cfg( +@@ -101,10 +102,10 @@ static void airoha_set_gdm_port_fwd_cfg( FIELD_PREP(GDM_UCFQ_MASK, val)); } @@ -60,24 +59,7 @@ Signed-off-by: Lorenzo Bianconi u32 vip_port; vip_port = eth->soc->ops.get_vip_port(port, port->nbq); -@@ -485,8 +486,7 @@ static bool airoha_fe_lro_is_enabled(str - - static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) - { -- struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = port->qdma; -+ struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; - int i, lro_queue_index = 0; -@@ -1097,13 +1097,18 @@ static void airoha_qdma_wake_netdev_txqs - - for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { - struct airoha_gdm_port *port = eth->ports[i]; -+ struct airoha_gdm_dev *dev; - struct net_device *netdev; - int j; - +@@ -859,10 +860,13 @@ static void airoha_qdma_wake_netdev_txqs if (!port) continue; @@ -89,8 +71,11 @@ Signed-off-by: Lorenzo Bianconi + if (dev->qdma != qdma) continue; - netdev = netdev_from_priv(port->dev); -@@ -1811,9 +1816,10 @@ static void airoha_qdma_stop_napi(struct +- dev = port->dev; + for (j = 0; j < dev->dev->num_tx_queues; j++) { + if (airoha_qdma_get_txq(qdma, j) != qid) + continue; +@@ -1563,9 +1567,10 @@ static void airoha_qdma_stop_napi(struct } } @@ -103,17 +88,13 @@ Signed-off-by: Lorenzo Bianconi u32 val, i = 0; spin_lock(&port->stats.lock); -@@ -1981,7 +1987,7 @@ static int airoha_dev_open(struct net_de +@@ -1712,11 +1717,11 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; + struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; u32 pse_port = FE_PSE_PORT_PPE1; -@@ -2011,7 +2017,7 @@ static int airoha_dev_open(struct net_de - #endif netif_tx_start_all_queues(netdev); - err = airoha_set_vip_for_gdm_port(port, true); @@ -121,13 +102,12 @@ Signed-off-by: Lorenzo Bianconi if (err) return err; -@@ -2052,12 +2058,12 @@ static int airoha_dev_stop(struct net_de +@@ -1752,11 +1757,11 @@ static int airoha_dev_stop(struct net_de { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; - struct airoha_qdma *qdma = port->qdma; + struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; int i; netif_tx_disable(netdev); @@ -136,7 +116,7 @@ Signed-off-by: Lorenzo Bianconi for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); -@@ -2092,21 +2098,21 @@ static int airoha_dev_stop(struct net_de +@@ -1782,21 +1787,21 @@ static int airoha_dev_stop(struct net_de static int airoha_dev_set_macaddr(struct net_device *netdev, void *p) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -162,7 +142,7 @@ Signed-off-by: Lorenzo Bianconi u32 val, pse_port, chan; int i, src_port; -@@ -2153,7 +2159,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1843,7 +1848,7 @@ static int airoha_set_gdm2_loopback(stru __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2)); for (i = 0; i < eth->soc->num_ppe; i++) @@ -170,21 +150,21 @@ Signed-off-by: Lorenzo Bianconi + airoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX); if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { - u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); -@@ -2173,9 +2179,9 @@ static int airoha_dev_init(struct net_de + u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); +@@ -1863,9 +1868,9 @@ static int airoha_dev_init(struct net_de int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ - port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; -- netdev->irq = port->qdma->irq_banks[0].irq; +- dev->dev->irq = port->qdma->irq_banks[0].irq; - airoha_set_macaddr(port, netdev->dev_addr); + dev->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; -+ netdev->irq = dev->qdma->irq_banks[0].irq; ++ dev->dev->irq = dev->qdma->irq_banks[0].irq; + airoha_set_macaddr(dev, netdev->dev_addr); switch (port->id) { case AIROHA_GDM3_IDX: -@@ -2184,7 +2190,7 @@ static int airoha_dev_init(struct net_de +@@ -1874,7 +1879,7 @@ static int airoha_dev_init(struct net_de if (!eth->ports[1]) { int err; @@ -193,7 +173,7 @@ Signed-off-by: Lorenzo Bianconi if (err) return err; } -@@ -2194,8 +2200,7 @@ static int airoha_dev_init(struct net_de +@@ -1884,8 +1889,7 @@ static int airoha_dev_init(struct net_de } for (i = 0; i < eth->soc->num_ppe; i++) @@ -203,7 +183,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2207,7 +2212,7 @@ static void airoha_dev_get_stats64(struc +@@ -1897,7 +1901,7 @@ static void airoha_dev_get_stats64(struc struct airoha_gdm_port *port = dev->port; unsigned int start; @@ -212,7 +192,7 @@ Signed-off-by: Lorenzo Bianconi do { start = u64_stats_fetch_begin(&port->stats.syncp); storage->rx_packets = port->stats.rx_ok_pkts; -@@ -2227,8 +2232,8 @@ static int airoha_dev_change_mtu(struct +@@ -1917,8 +1921,8 @@ static int airoha_dev_change_mtu(struct { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -222,7 +202,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), GDM_LONG_LEN_MASK, -@@ -2302,10 +2307,10 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -1992,10 +1996,10 @@ static u32 airoha_get_dsa_tag(struct sk_ #endif } @@ -236,27 +216,7 @@ Signed-off-by: Lorenzo Bianconi switch (eth->soc->version) { case 0x7583: -@@ -2322,8 +2327,7 @@ static netdev_features_t airoha_dev_fix_ - netdev_features_t features) - { - struct airoha_gdm_dev *dev = netdev_priv(netdev); -- struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = port->qdma; -+ struct airoha_qdma *qdma = dev->qdma; - - if (qdma->users > 1) - features &= ~NETIF_F_GRO_HW; -@@ -2336,8 +2340,7 @@ static int airoha_dev_set_features(struc - { - netdev_features_t diff = netdev->features ^ features; - struct airoha_gdm_dev *dev = netdev_priv(netdev); -- struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = port->qdma; -+ struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; - -@@ -2356,8 +2359,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2012,8 +2016,7 @@ static netdev_tx_t airoha_dev_xmit(struc struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -266,7 +226,7 @@ Signed-off-by: Lorenzo Bianconi u32 nr_frags, tag, msg0, msg1, len; struct airoha_queue_entry *e; struct netdev_queue *txq; -@@ -2395,7 +2397,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2051,7 +2054,7 @@ static netdev_tx_t airoha_dev_xmit(struc } } @@ -275,7 +235,7 @@ Signed-off-by: Lorenzo Bianconi msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) | FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); -@@ -2498,8 +2500,7 @@ static void airoha_ethtool_get_drvinfo(s +@@ -2154,8 +2157,7 @@ static void airoha_ethtool_get_drvinfo(s struct ethtool_drvinfo *info) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -285,7 +245,7 @@ Signed-off-by: Lorenzo Bianconi strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver)); strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info)); -@@ -2512,7 +2513,7 @@ static void airoha_ethtool_get_mac_stats +@@ -2168,7 +2170,7 @@ static void airoha_ethtool_get_mac_stats struct airoha_gdm_port *port = dev->port; unsigned int start; @@ -294,7 +254,7 @@ Signed-off-by: Lorenzo Bianconi do { start = u64_stats_fetch_begin(&port->stats.syncp); stats->FramesTransmittedOK = port->stats.tx_ok_pkts; -@@ -2552,7 +2553,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2208,7 +2210,7 @@ airoha_ethtool_get_rmon_stats(struct net ARRAY_SIZE(hw_stats->rx_len) + 1); *ranges = airoha_ethtool_rmon_ranges; @@ -303,7 +263,7 @@ Signed-off-by: Lorenzo Bianconi do { int i; -@@ -2572,18 +2573,17 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2228,18 +2230,17 @@ static int airoha_qdma_set_chan_tx_sched const u16 *weights, u8 n_weights) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -324,7 +284,7 @@ Signed-off-by: Lorenzo Bianconi TWRR_RW_CMD_MASK | FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | -@@ -2591,13 +2591,12 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2247,13 +2248,12 @@ static int airoha_qdma_set_chan_tx_sched err = read_poll_timeout(airoha_qdma_rr, status, status & TWRR_RW_CMD_DONE, USEC_PER_MSEC, 10 * USEC_PER_MSEC, @@ -340,7 +300,7 @@ Signed-off-by: Lorenzo Bianconi CHAN_QOS_MODE_MASK(channel), __field_prep(CHAN_QOS_MODE_MASK(channel), mode)); -@@ -2663,9 +2662,9 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2319,9 +2319,9 @@ static int airoha_qdma_get_tx_ets_stats( struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -352,7 +312,7 @@ Signed-off-by: Lorenzo Bianconi REG_CNTR_VAL((channel << 1) + 1)); u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) + (fwd_tx_packets - port->fwd_tx_packets); -@@ -2929,17 +2928,16 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2585,17 +2585,16 @@ static int airoha_qdma_set_tx_rate_limit u32 bucket_size) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -372,7 +332,7 @@ Signed-off-by: Lorenzo Bianconi REG_EGRESS_TRTCM_CFG, i, rate, bucket_size); if (err) -@@ -2989,11 +2987,11 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2645,11 +2644,11 @@ static int airoha_tc_htb_alloc_leaf_queu return 0; } @@ -386,7 +346,7 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { -@@ -3072,7 +3070,6 @@ static int airoha_dev_tc_matchall(struct +@@ -2728,7 +2727,6 @@ static int airoha_dev_tc_matchall(struct { enum trtcm_unit_type unit_type = TRTCM_BYTE_UNIT; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -394,7 +354,7 @@ Signed-off-by: Lorenzo Bianconi u32 rate = 0, bucket_size = 0; switch (f->command) { -@@ -3097,7 +3094,7 @@ static int airoha_dev_tc_matchall(struct +@@ -2753,7 +2751,7 @@ static int airoha_dev_tc_matchall(struct fallthrough; } case TC_CLSMATCHALL_DESTROY: @@ -403,7 +363,7 @@ Signed-off-by: Lorenzo Bianconi unit_type); default: return -EOPNOTSUPP; -@@ -3109,8 +3106,7 @@ static int airoha_dev_setup_tc_block_cb( +@@ -2765,8 +2763,7 @@ static int airoha_dev_setup_tc_block_cb( { struct net_device *netdev = cb_priv; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -413,26 +373,15 @@ Signed-off-by: Lorenzo Bianconi if (!tc_can_offload(netdev)) return -EOPNOTSUPP; -@@ -3346,7 +3342,7 @@ static void airoha_mac_link_up(struct ph - struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, - phylink_config); - struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = port->qdma; -+ struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - u32 frag_size_tx, frag_size_rx; - --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -549,6 +549,7 @@ struct airoha_qdma { +@@ -537,12 +537,12 @@ struct airoha_qdma { struct airoha_gdm_dev { struct airoha_gdm_port *port; + struct airoha_qdma *qdma; + struct net_device *dev; struct airoha_eth *eth; - - #if defined(CONFIG_PCS_AIROHA) -@@ -558,7 +559,6 @@ struct airoha_gdm_dev { }; struct airoha_gdm_port { @@ -440,8 +389,8 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev *dev; int id; int nbq; -@@ -694,19 +694,18 @@ static inline bool airoha_qdma_is_lro_qu - return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid)); +@@ -666,19 +666,18 @@ static inline bool airoha_is_7583(struct + return eth->soc->version == 0x7583; } -int airoha_get_fe_port(struct airoha_gdm_port *port); @@ -465,7 +414,7 @@ Signed-off-by: Lorenzo Bianconi u32 hash); --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -85,9 +85,9 @@ static u32 airoha_ppe_get_timestamp(stru +@@ -84,9 +84,9 @@ static u32 airoha_ppe_get_timestamp(stru AIROHA_FOE_IB1_BIND_TIMESTAMP); } @@ -477,7 +426,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_eth *eth = qdma->eth; u8 qdma_id = qdma - ð->qdma[0]; u32 fe_cpu_port; -@@ -181,8 +181,8 @@ static void airoha_ppe_hw_init(struct ai +@@ -180,8 +180,8 @@ static void airoha_ppe_hw_init(struct ai if (!port) continue; @@ -488,18 +437,18 @@ Signed-off-by: Lorenzo Bianconi } } } -@@ -1485,11 +1485,12 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -1473,11 +1473,12 @@ void airoha_ppe_check_skb(struct airoha_ airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan); } -void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev) { -- struct net_device *dev = netdev_from_priv(port->dev); - struct airoha_eth *eth = port->qdma->eth; +- struct net_device *dev = port->dev->dev; - const u8 *addr = dev->dev_addr; -+ struct net_device *netdev = netdev_from_priv(dev); + struct airoha_gdm_port *port = dev->port; ++ struct net_device *netdev = dev->dev; + struct airoha_eth *eth = dev->eth; + const u8 *addr = netdev->dev_addr; u32 val; diff --git a/target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch b/target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch similarity index 75% rename from target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch rename to target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch index 64ed102d3a..072089fe8b 100644 --- a/target/linux/airoha/patches-6.18/920-03-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch +++ b/target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch @@ -1,10 +1,7 @@ -From 32bfd008c19f9ad55514181d8cd02e14bf384475 Mon Sep 17 00:00:00 2001 -Message-ID: <32bfd008c19f9ad55514181d8cd02e14bf384475.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From eca4f59b536780a56bd22db03fe5465e8e978f36 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 13 Dec 2025 10:06:45 +0100 -Subject: [PATCH 03/13] net: airoha: Rely on airoha_gdm_dev pointer in +Date: Wed, 27 May 2026 12:21:17 +0200 +Subject: [PATCH 3/6] net: airoha: Rely on airoha_gdm_dev pointer in airoha_is_lan_gdm_port() Rename airoha_is_lan_gdm_port in airoha_is_lan_gdm_dev. Moreover, rely @@ -15,6 +12,8 @@ the same GDM{3,4} port via an external hw arbiter. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-3-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 6 ++---- drivers/net/ethernet/airoha/airoha_eth.h | 4 +++- @@ -23,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -83,12 +83,10 @@ static bool airhoa_is_phy_external(struc +@@ -73,12 +73,10 @@ static void airoha_qdma_irq_disable(stru static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) { @@ -37,18 +36,18 @@ Signed-off-by: Lorenzo Bianconi val = (addr[0] << 16) | (addr[1] << 8) | addr[2]; airoha_fe_wr(eth, reg, val); -@@ -2179,7 +2177,7 @@ static int airoha_dev_init(struct net_de +@@ -1868,7 +1866,7 @@ static int airoha_dev_init(struct net_de int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ - dev->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; + dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; - netdev->irq = dev->qdma->irq_banks[0].irq; + dev->dev->irq = dev->qdma->irq_banks[0].irq; airoha_set_macaddr(dev, netdev->dev_addr); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -663,8 +663,10 @@ static inline u16 airoha_qdma_get_txq(st +@@ -647,8 +647,10 @@ static inline u16 airoha_qdma_get_txq(st return qid % ARRAY_SIZE(qdma->q_tx); } @@ -62,7 +61,7 @@ Signed-off-by: Lorenzo Bianconi * phy module. --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -367,7 +367,7 @@ static int airoha_ppe_foe_entry_prepare( +@@ -362,7 +362,7 @@ static int airoha_ppe_foe_entry_prepare( /* For downlink traffic consume SRAM memory for hw * forwarding descriptors queue. */ diff --git a/target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch b/target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch similarity index 80% rename from target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch rename to target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch index 3bbcaab936..b35b1b0a69 100644 --- a/target/linux/airoha/patches-6.18/920-04-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch +++ b/target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch @@ -1,10 +1,7 @@ -From 634d75285db77f3385aa85a1bf2b185396225100 Mon Sep 17 00:00:00 2001 -Message-ID: <634d75285db77f3385aa85a1bf2b185396225100.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From 069626af6dfaa26b82119900f4aff1fec38d5983 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 10 Apr 2026 14:35:32 +0200 -Subject: [PATCH 04/13] net: airoha: Move qos_sq_bmap in airoha_gdm_dev struct +Date: Wed, 27 May 2026 12:21:18 +0200 +Subject: [PATCH 4/6] net: airoha: Move qos_sq_bmap in airoha_gdm_dev struct Since now multiple net_devices connected to different QDMA blocks can share the same GDM port, qos_sq_bmap field can be overwritten with the @@ -14,7 +11,10 @@ airoha_gdm_port struct to airoha_gdm_dev one. Add qos_channel_map bitmap in airoha_qdma struct to track if a shared QDMA channel is already in use by another net_device. +Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-4-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 58 +++++++++++++++--------- drivers/net/ethernet/airoha/airoha_eth.h | 6 ++- @@ -22,7 +22,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2945,30 +2945,46 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2602,30 +2602,40 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -36,7 +36,6 @@ Signed-off-by: Lorenzo Bianconi - int err, num_tx_queues = netdev->real_num_tx_queues; - struct airoha_gdm_dev *dev = netdev_priv(netdev); - struct airoha_gdm_port *port = dev->port; -+ int err; if (opt->parent_classid != TC_HTB_CLASSID_ROOT) { NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid"); @@ -46,13 +45,7 @@ Signed-off-by: Lorenzo Bianconi - err = airoha_qdma_set_tx_rate_limit(netdev, channel, rate, - opt->quantum); - if (err) { -+ err = airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); -+ if (err) - NL_SET_ERR_MSG_MOD(opt->extack, - "failed configuring htb offload"); -- return err; -+ -+ return err; ++ return airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); +} + +static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev, @@ -67,7 +60,9 @@ Signed-off-by: Lorenzo Bianconi + * in use by another net_device running on the same QDMA block. + */ + if (test_and_set_bit(channel, qdma->qos_channel_map)) { -+ NL_SET_ERR_MSG_MOD(opt->extack, + NL_SET_ERR_MSG_MOD(opt->extack, +- "failed configuring htb offload"); +- return err; + "qdma qos channel already in use"); + return -EBUSY; } @@ -80,7 +75,7 @@ Signed-off-by: Lorenzo Bianconi err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1); if (err) { -@@ -2976,13 +2992,17 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2633,13 +2643,17 @@ static int airoha_tc_htb_alloc_leaf_queu opt->quantum); NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); @@ -100,7 +95,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev, -@@ -3163,11 +3183,13 @@ static int airoha_dev_setup_tc_block(str +@@ -2820,11 +2834,13 @@ static int airoha_dev_setup_tc_block(str static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -116,7 +111,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev, -@@ -3175,9 +3197,8 @@ static int airoha_tc_htb_delete_leaf_que +@@ -2832,9 +2848,8 @@ static int airoha_tc_htb_delete_leaf_que { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -127,7 +122,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); return -EINVAL; } -@@ -3190,10 +3211,9 @@ static int airoha_tc_htb_delete_leaf_que +@@ -2847,10 +2862,9 @@ static int airoha_tc_htb_delete_leaf_que static int airoha_tc_htb_destroy(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -139,7 +134,7 @@ Signed-off-by: Lorenzo Bianconi airoha_tc_remove_htb_queue(netdev, q); return 0; -@@ -3204,9 +3224,8 @@ static int airoha_tc_get_htb_get_leaf_qu +@@ -2861,9 +2875,8 @@ static int airoha_tc_get_htb_get_leaf_qu { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -150,7 +145,7 @@ Signed-off-by: Lorenzo Bianconi NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); return -EINVAL; } -@@ -3225,6 +3244,7 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -2882,6 +2895,7 @@ static int airoha_tc_setup_qdisc_htb(str case TC_HTB_DESTROY: return airoha_tc_htb_destroy(dev); case TC_HTB_NODE_MODIFY: @@ -160,7 +155,7 @@ Signed-off-by: Lorenzo Bianconi case TC_HTB_LEAF_DEL: --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -545,6 +545,8 @@ struct airoha_qdma { +@@ -533,6 +533,8 @@ struct airoha_qdma { struct airoha_queue q_tx[AIROHA_NUM_TX_RING]; struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; @@ -169,16 +164,16 @@ Signed-off-by: Lorenzo Bianconi }; struct airoha_gdm_dev { -@@ -556,6 +558,8 @@ struct airoha_gdm_dev { - struct phylink *phylink; - struct phylink_config phylink_config; - #endif +@@ -540,6 +542,8 @@ struct airoha_gdm_dev { + struct airoha_qdma *qdma; + struct net_device *dev; + struct airoha_eth *eth; + + DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); }; struct airoha_gdm_port { -@@ -565,8 +569,6 @@ struct airoha_gdm_port { +@@ -549,8 +553,6 @@ struct airoha_gdm_port { struct airoha_hw_stats stats; diff --git a/target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch b/target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch similarity index 76% rename from target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch rename to target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch index dfe8662b56..cb62a387b6 100644 --- a/target/linux/airoha/patches-6.18/920-05-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch +++ b/target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch @@ -1,11 +1,8 @@ -From 00272dbf6a52241a21145631f22dc5f03891078b Mon Sep 17 00:00:00 2001 -Message-ID: <00272dbf6a52241a21145631f22dc5f03891078b.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From 962c17dd287887aa87a6f30d64239d7e1e4e05fa Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 10 Apr 2026 14:47:08 +0200 -Subject: [PATCH 05/13] net: airoha: Move {cpu,fwd}_tx_packets in - airoha_gdm_dev struct +Date: Wed, 27 May 2026 12:21:19 +0200 +Subject: [PATCH 5/6] net: airoha: Move {cpu,fwd}_tx_packets in airoha_gdm_dev + struct Since now multiple net_devices connected to different QDMA blocks can share the same GDM port, cpu_tx_packets and fwd_tx_packets fields can @@ -13,7 +10,10 @@ be overwritten with the value from a different QDMA block. In order to fix the issue move cpu_tx_packets and fwd_tx_packets fields from airoha_gdm_port struct to airoha_gdm_dev one. +Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-5-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 16 +++++++--------- drivers/net/ethernet/airoha/airoha_eth.h | 7 +++---- @@ -21,7 +21,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2658,19 +2658,17 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2315,19 +2315,17 @@ static int airoha_qdma_get_tx_ets_stats( struct tc_ets_qopt_offload *opt) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -50,8 +50,8 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -560,6 +560,9 @@ struct airoha_gdm_dev { - #endif +@@ -544,6 +544,9 @@ struct airoha_gdm_dev { + struct airoha_eth *eth; DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); + /* qos stats counters */ @@ -60,7 +60,7 @@ Signed-off-by: Lorenzo Bianconi }; struct airoha_gdm_port { -@@ -569,10 +572,6 @@ struct airoha_gdm_port { +@@ -553,10 +556,6 @@ struct airoha_gdm_port { struct airoha_hw_stats stats; diff --git a/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch b/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch new file mode 100644 index 0000000000..eaf4d8e426 --- /dev/null +++ b/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch @@ -0,0 +1,38 @@ +From 842a7ee50d68d66afef4536bf3abdaaed2e0e5f5 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 27 May 2026 12:21:20 +0200 +Subject: [PATCH 6/6] net: airoha: Rename airoha_set_gdm2_loopback in + airoha_enable_gdm2_loopback + +This is a preliminary patch in order to allow the user to select if the +configured device will be used as hw lan or wan. +Please not this patch does not introduce any logical changes, just +cosmetic ones. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260527-airoha-eth-multi-serdes-preliminary-v1-6-ec6ed73ef7fc@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1796,7 +1796,7 @@ static int airoha_dev_set_macaddr(struct + return 0; + } + +-static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev) ++static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev) + { + struct airoha_gdm_port *port = dev->port; + struct airoha_eth *eth = dev->eth; +@@ -1877,7 +1877,7 @@ static int airoha_dev_init(struct net_de + if (!eth->ports[1]) { + int err; + +- err = airoha_set_gdm2_loopback(dev); ++ err = airoha_enable_gdm2_loopback(dev); + if (err) + return err; + } diff --git a/target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch b/target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch new file mode 100644 index 0000000000..7ea6058ac4 --- /dev/null +++ b/target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch @@ -0,0 +1,37 @@ +From b38cae85d1c45ff189d7ecb6ac36f41cdc3d84d0 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 2 Jun 2026 11:21:04 +0200 +Subject: [PATCH] net: airoha: Fix use-after-free in metadata dst teardown + +airoha_metadata_dst_free() runs metadata_dst_free() which frees the +metadata_dst with kfree() immediately, bypassing the RCU grace period. +In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from +the skb to the metadata_dst. This function requires RCU read-side +protection and the dst must remain valid until all RCU readers complete. +Since metadata_dst_free() calls kfree() directly, an use-after-free can +occur if any skb still holds a noref pointer to the dst when the driver +tears it down. +Replace metadata_dst_free() with dst_release() which properly goes +through the refcount path: when the refcount drops to zero, it schedules +the actual free via call_rcu_hurry(), ensuring all RCU readers have +completed before the memory is freed. + +Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260602-airoha-mtk-metadata-uaf-fix-v1-1-3aaa99d83351@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2972,7 +2972,7 @@ static void airoha_metadata_dst_free(str + if (!port->dsa_meta[i]) + continue; + +- metadata_dst_free(port->dsa_meta[i]); ++ dst_release(&port->dsa_meta[i]->dst); + } + } + diff --git a/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch b/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch new file mode 100644 index 0000000000..6e4807b0e3 --- /dev/null +++ b/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch @@ -0,0 +1,40 @@ +From 144969cd80c5227c2b19fe5f644d6eebd61be586 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 3 Jun 2026 12:30:01 +0200 +Subject: [PATCH] net: airoha: Report extack error to the user if + airoha_tc_htb_modify_queue() fails + +Report an extack error message in airoha_tc_htb_modify_queue routine if +airoha_qdma_set_tx_rate_limit() fails. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Alexander Lobakin +Link: https://patch.msgid.link/20260603-airoha_tc_htb_modify_queue-err-message-v1-1-33ec3ab997d9@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2605,13 +2605,19 @@ static int airoha_tc_htb_modify_queue(st + { + u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; + u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */ ++ int err; + + if (opt->parent_classid != TC_HTB_CLASSID_ROOT) { + NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid"); + return -EINVAL; + } + +- return airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); ++ err = airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum); ++ if (err) ++ NL_SET_ERR_MSG_MOD(opt->extack, ++ "failed configuring htb offload"); ++ ++ return err; + } + + static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev, diff --git a/target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch b/target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch new file mode 100644 index 0000000000..830198151c --- /dev/null +++ b/target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch @@ -0,0 +1,41 @@ +From f9f25118faa4dd2b6e3d14a03d123bbdbd59925d Mon Sep 17 00:00:00 2001 +From: ZhaoJinming +Date: Thu, 4 Jun 2026 15:03:52 +0800 +Subject: [PATCH] net: airoha: Add NULL check for of_reserved_mem_lookup() in + airoha_qdma_init_hfwd_queues() + +of_reserved_mem_lookup() may return NULL if the reserved memory region +referenced by the "memory-region" phandle is not found in the reserved +memory table (e.g. due to a misconfigured DTS or a removed +memory-region node). The current code dereferences the returned +pointer without checking for NULL, leading to a kernel NULL pointer +dereference at the following lines: + + dma_addr = rmem->base; // line 1156 + num_desc = div_u64(rmem->size, buf_size); // line 1160 + +Add a NULL check after of_reserved_mem_lookup() and return -ENODEV if +the lookup fails, which is consistent with the existing error handling +for of_parse_phandle() failure in the same code block. + +Fixes: 3a1ce9e3d01b ("net: airoha: Add the capability to allocate hwfd buffers via reserved-memory") +Cc: stable@vger.kernel.org +Signed-off-by: ZhaoJinming +Acked-by: Lorenzo Bianconi +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1159,6 +1159,9 @@ static int airoha_qdma_init_hfwd_queues( + + rmem = of_reserved_mem_lookup(np); + of_node_put(np); ++ if (!rmem) ++ return -ENODEV; ++ + dma_addr = rmem->base; + /* Compute the number of hw descriptors according to the + * reserved memory size and the payload buffer size diff --git a/target/linux/airoha/patches-6.18/165-01-v7.2-net-airoha-Remove-private-net_device-pointer-in-airo.patch b/target/linux/airoha/patches-6.18/165-01-v7.2-net-airoha-Remove-private-net_device-pointer-in-airo.patch new file mode 100644 index 0000000000..f4da9bf742 --- /dev/null +++ b/target/linux/airoha/patches-6.18/165-01-v7.2-net-airoha-Remove-private-net_device-pointer-in-airo.patch @@ -0,0 +1,125 @@ +From 4408f520680990042a1e6bfdf3cef217a1abf152 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 3 Jun 2026 08:00:16 +0200 +Subject: [PATCH 1/5] net: airoha: Remove private net_device pointer in + airoha_gdm_dev struct + +Remove redundant net_device pointer inside airoha_gdm_dev struct and +rely on netdev_from_priv routine instead. Please note this patch does +not introduce any logical change, just code refactoring. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-2-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 23 ++++++++++++++--------- + drivers/net/ethernet/airoha/airoha_eth.h | 1 - + drivers/net/ethernet/airoha/airoha_ppe.c | 2 +- + 3 files changed, 15 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -629,7 +629,7 @@ static int airoha_qdma_rx_process(struct + if (!port->dev) + goto free_frag; + +- netdev = port->dev->dev; ++ netdev = netdev_from_priv(port->dev); + if (!q->skb) { /* first buffer */ + q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, + q->buf_size); +@@ -853,6 +853,7 @@ static void airoha_qdma_wake_netdev_txqs + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { + struct airoha_gdm_port *port = eth->ports[i]; + struct airoha_gdm_dev *dev; ++ struct net_device *netdev; + int j; + + if (!port) +@@ -865,11 +866,12 @@ static void airoha_qdma_wake_netdev_txqs + if (dev->qdma != qdma) + continue; + +- for (j = 0; j < dev->dev->num_tx_queues; j++) { ++ netdev = netdev_from_priv(dev); ++ for (j = 0; j < netdev->num_tx_queues; j++) { + if (airoha_qdma_get_txq(qdma, j) != qid) + continue; + +- netif_wake_subqueue(dev->dev, j); ++ netif_wake_subqueue(netdev, j); + } + } + q->txq_stopped = false; +@@ -1870,7 +1872,7 @@ static int airoha_dev_init(struct net_de + + /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ + dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; +- dev->dev->irq = dev->qdma->irq_banks[0].irq; ++ netdev->irq = dev->qdma->irq_banks[0].irq; + airoha_set_macaddr(dev, netdev->dev_addr); + + switch (port->id) { +@@ -3047,7 +3049,6 @@ static int airoha_alloc_gdm_device(struc + } + + dev = netdev_priv(netdev); +- dev->dev = netdev; + dev->port = port; + port->dev = dev; + dev->eth = eth; +@@ -3110,7 +3111,7 @@ static int airoha_register_gdm_devices(s + if (!port) + continue; + +- err = register_netdev(port->dev->dev); ++ err = register_netdev(netdev_from_priv(port->dev)); + if (err) + return err; + } +@@ -3225,8 +3226,12 @@ error_napi_stop: + continue; + + dev = port->dev; +- if (dev && dev->dev->reg_state == NETREG_REGISTERED) +- unregister_netdev(dev->dev); ++ if (dev) { ++ struct net_device *netdev = netdev_from_priv(dev); ++ ++ if (netdev->reg_state == NETREG_REGISTERED) ++ unregister_netdev(netdev); ++ } + airoha_metadata_dst_free(port); + } + airoha_hw_cleanup(eth); +@@ -3254,7 +3259,7 @@ static void airoha_remove(struct platfor + + dev = port->dev; + if (dev) +- unregister_netdev(dev->dev); ++ unregister_netdev(netdev_from_priv(dev)); + airoha_metadata_dst_free(port); + } + airoha_hw_cleanup(eth); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -540,7 +540,6 @@ struct airoha_qdma { + struct airoha_gdm_dev { + struct airoha_gdm_port *port; + struct airoha_qdma *qdma; +- struct net_device *dev; + struct airoha_eth *eth; + + DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1475,8 +1475,8 @@ void airoha_ppe_check_skb(struct airoha_ + + void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev) + { ++ struct net_device *netdev = netdev_from_priv(dev); + struct airoha_gdm_port *port = dev->port; +- struct net_device *netdev = dev->dev; + struct airoha_eth *eth = dev->eth; + const u8 *addr = netdev->dev_addr; + u32 val; diff --git a/target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch b/target/linux/airoha/patches-6.18/165-02-v7.2-net-airoha-Support-multiple-net_devices-for-a-single.patch similarity index 77% rename from target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch rename to target/linux/airoha/patches-6.18/165-02-v7.2-net-airoha-Support-multiple-net_devices-for-a-single.patch index 870b24371b..922d1057f5 100644 --- a/target/linux/airoha/patches-6.18/920-06-net-airoha-Support-multiple-net_devices-for-a-single.patch +++ b/target/linux/airoha/patches-6.18/165-02-v7.2-net-airoha-Support-multiple-net_devices-for-a-single.patch @@ -1,11 +1,8 @@ -From 8eb0a71bfbe92b6fbc668c5d9ebdcbf6523a89ad Mon Sep 17 00:00:00 2001 -Message-ID: <8eb0a71bfbe92b6fbc668c5d9ebdcbf6523a89ad.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From a9c2ca61fec7706574c009d8f1898ca392368f89 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 1 Nov 2025 11:27:48 +0100 -Subject: [PATCH 06/13] net: airoha: Support multiple net_devices for a single - FE GDM port +Date: Wed, 3 Jun 2026 08:00:17 +0200 +Subject: [PATCH 2/5] net: airoha: Support multiple net_devices for a single FE + GDM port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -48,15 +45,17 @@ logics for the net_device type connected to GDM3 or GDM4. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-3-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- - drivers/net/ethernet/airoha/airoha_eth.c | 274 +++++++++++++++++------ - drivers/net/ethernet/airoha/airoha_eth.h | 10 +- - drivers/net/ethernet/airoha/airoha_ppe.c | 13 +- - 3 files changed, 228 insertions(+), 69 deletions(-) + drivers/net/ethernet/airoha/airoha_eth.c | 280 +++++++++++++++++------ + drivers/net/ethernet/airoha/airoha_eth.h | 8 +- + drivers/net/ethernet/airoha/airoha_ppe.c | 26 ++- + 3 files changed, 237 insertions(+), 77 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -116,7 +116,7 @@ static int airoha_set_vip_for_gdm_port(s +@@ -106,7 +106,7 @@ static int airoha_set_vip_for_gdm_port(s struct airoha_eth *eth = dev->eth; u32 vip_port; @@ -65,7 +64,7 @@ Signed-off-by: Lorenzo Bianconi if (enable) { airoha_fe_set(eth, REG_FE_VIP_PORT_EN, vip_port); airoha_fe_set(eth, REG_FE_IFC_PORT_EN, vip_port); -@@ -646,30 +646,26 @@ static int airoha_qdma_fill_rx_queue(str +@@ -566,24 +566,26 @@ static int airoha_qdma_fill_rx_queue(str return nframes; } @@ -80,14 +79,8 @@ Signed-off-by: Lorenzo Bianconi - sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); - switch (sport) { -- case 0x18: -- port = 3; /* GDM4 */ -- break; -- case 0x16: -- port = 2; /* GDM3 */ -- break; - case 0x10 ... 0x14: -- port = 0; /* GDM1 */ +- port = 0; - break; - case 0x2 ... 0x4: - port = sport - 1; @@ -97,11 +90,11 @@ Signed-off-by: Lorenzo Bianconi - } + if (eth->soc->ops.get_dev_from_sport(desc, &p, &d)) + return ERR_PTR(-ENODEV); -+ -+ if (p >= ARRAY_SIZE(eth->ports)) -+ return ERR_PTR(-ENODEV); - return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; ++ if (p >= ARRAY_SIZE(eth->ports)) ++ return ERR_PTR(-ENODEV); ++ + port = eth->ports[p]; + if (!port) + return ERR_PTR(-ENODEV); @@ -112,8 +105,8 @@ Signed-off-by: Lorenzo Bianconi + return port->devs[d] ? port->devs[d] : ERR_PTR(-ENODEV); } - static struct sk_buff *airoha_qdma_lro_rx_skb(struct airoha_queue *q, -@@ -841,9 +837,9 @@ static int airoha_qdma_rx_process(struct + static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) +@@ -598,9 +600,9 @@ static int airoha_qdma_rx_process(struct struct airoha_queue_entry *e = &q->entry[q->tail]; struct airoha_qdma_desc *desc = &q->desc[q->tail]; u32 hash, reason, msg1, desc_ctrl; @@ -125,7 +118,7 @@ Signed-off-by: Lorenzo Bianconi struct page *page; desc_ctrl = le32_to_cpu(READ_ONCE(desc->ctrl)); -@@ -864,15 +860,11 @@ static int airoha_qdma_rx_process(struct +@@ -621,15 +623,11 @@ static int airoha_qdma_rx_process(struct if (!len || data_len < len) goto free_frag; @@ -142,9 +135,9 @@ Signed-off-by: Lorenzo Bianconi - netdev = netdev_from_priv(port->dev); + netdev = netdev_from_priv(dev); if (!q->skb) { /* first buffer */ - q->skb = airoha_qdma_build_rx_skb(q, desc, e, netdev); - if (!q->skb) -@@ -893,6 +885,8 @@ static int airoha_qdma_rx_process(struct + q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, + q->buf_size); +@@ -659,6 +657,8 @@ static int airoha_qdma_rx_process(struct continue; if (netdev_uses_dsa(netdev)) { @@ -153,7 +146,7 @@ Signed-off-by: Lorenzo Bianconi /* PPE module requires untagged packets to work * properly and it provides DSA port index via the * DMA descriptor. Report DSA tag to the DSA stack -@@ -1095,26 +1089,29 @@ static void airoha_qdma_wake_netdev_txqs +@@ -852,26 +852,29 @@ static void airoha_qdma_wake_netdev_txqs for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -178,7 +171,7 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; -- netdev = netdev_from_priv(port->dev); +- netdev = netdev_from_priv(dev); - for (j = 0; j < netdev->num_tx_queues; j++) { - if (airoha_qdma_get_txq(qdma, j) != qid) + if (dev->qdma != qdma) @@ -195,58 +188,21 @@ Signed-off-by: Lorenzo Bianconi } } q->txq_stopped = false; -@@ -1961,22 +1958,32 @@ static void airoha_update_hw_stats(struc - - static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) - { -- struct airoha_gdm_port *port = dev->port; - struct airoha_eth *eth = dev->eth; - int i; - - for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { -- struct airoha_gdm_port *p = eth->ports[i]; -- struct net_device *netdev; -+ struct airoha_gdm_port *port = eth->ports[i]; -+ int j; - -- if (!p) -+ if (!port) - continue; - -- netdev = netdev_from_priv(p->dev); -- if (netdev->reg_state != NETREG_REGISTERED) -- continue; -+ for (j = 0; j < ARRAY_SIZE(port->devs); j++) { -+ struct airoha_gdm_dev *iter_dev = port->devs[j]; -+ struct net_device *netdev; -+ -+ if (!iter_dev || iter_dev == dev) -+ continue; -+ -+ if (iter_dev->qdma != dev->qdma) -+ continue; -+ -+ netdev = netdev_from_priv(iter_dev); -+ if (netdev->reg_state != NETREG_REGISTERED) -+ continue; - -- netdev_update_features(netdev); -+ netdev_update_features(netdev); -+ } - } - } - -@@ -2037,7 +2044,8 @@ static int airoha_dev_open(struct net_de +@@ -1745,11 +1748,9 @@ static int airoha_dev_open(struct net_de GLOBAL_CFG_RX_DMA_EN_MASK); - qdma->users++; + atomic_inc(&qdma->users); -- if (port->id == AIROHA_GDM2_IDX && airoha_ppe_is_enabled(eth, 1)) { +- if (port->id == AIROHA_GDM2_IDX && +- airoha_ppe_is_enabled(qdma->eth, 1)) { +- /* For PPE2 always use secondary cpu port. */ + if (!airoha_is_lan_gdm_dev(dev) && -+ airoha_ppe_is_enabled(eth, 1)) { - /* For PPE2 always use secondary cpu port. */ ++ airoha_ppe_is_enabled(qdma->eth, 1)) pse_port = FE_PSE_PORT_PPE2; - } -@@ -2143,7 +2151,7 @@ static int airoha_set_gdm2_loopback(stru +- } + airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), + pse_port); + +@@ -1837,7 +1838,7 @@ static int airoha_enable_gdm2_loopback(s airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); @@ -255,16 +211,16 @@ Signed-off-by: Lorenzo Bianconi if (src_port < 0) return src_port; -@@ -2160,7 +2168,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1854,7 +1855,7 @@ static int airoha_enable_gdm2_loopback(s airoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX); if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { -- u32 mask = FC_ID_OF_SRC_PORT_MASK(nbq); +- u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); + u32 mask = FC_ID_OF_SRC_PORT_MASK(dev->nbq); airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, mask, __field_prep(mask, AIROHA_GDM2_IDX)); -@@ -2174,7 +2182,7 @@ static int airoha_dev_init(struct net_de +@@ -1868,7 +1869,7 @@ static int airoha_dev_init(struct net_de struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; struct airoha_eth *eth = dev->eth; @@ -273,7 +229,7 @@ Signed-off-by: Lorenzo Bianconi /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ dev->qdma = ð->qdma[!airoha_is_lan_gdm_dev(dev)]; -@@ -2197,8 +2205,8 @@ static int airoha_dev_init(struct net_de +@@ -1891,8 +1892,8 @@ static int airoha_dev_init(struct net_de break; } @@ -284,7 +240,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2396,7 +2404,8 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2058,7 +2059,8 @@ static netdev_tx_t airoha_dev_xmit(struc } fport = airoha_get_fe_port(dev); @@ -294,7 +250,7 @@ Signed-off-by: Lorenzo Bianconi FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); q = &qdma->q_tx[qid]; -@@ -3339,12 +3348,15 @@ bool airoha_is_valid_gdm_dev(struct airo +@@ -2994,12 +2996,15 @@ bool airoha_is_valid_gdm_dev(struct airo for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -312,7 +268,7 @@ Signed-off-by: Lorenzo Bianconi } return false; -@@ -3468,10 +3480,11 @@ static int airoha_setup_phylink(struct n +@@ -3007,10 +3012,11 @@ bool airoha_is_valid_gdm_dev(struct airo static int airoha_alloc_gdm_device(struct airoha_eth *eth, struct airoha_gdm_port *port, @@ -326,15 +282,15 @@ Signed-off-by: Lorenzo Bianconi int err; netdev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*dev), -@@ -3489,7 +3502,6 @@ static int airoha_alloc_gdm_device(struc - netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; - netdev->features |= AIROHA_HW_FEATURES; - netdev->vlan_features = AIROHA_HW_FEATURES; +@@ -3030,7 +3036,6 @@ static int airoha_alloc_gdm_device(struc + NETIF_F_HW_TC; + netdev->features |= netdev->hw_features; + netdev->vlan_features = netdev->hw_features; - netdev->dev.of_node = np; SET_NETDEV_DEV(netdev, eth->dev); /* reserve hw queues for HTB offloading */ -@@ -3507,10 +3519,24 @@ static int airoha_alloc_gdm_device(struc +@@ -3048,10 +3053,24 @@ static int airoha_alloc_gdm_device(struc netdev->dev_addr); } @@ -358,9 +314,9 @@ Signed-off-by: Lorenzo Bianconi + dev->nbq = nbq; + port->devs[index] = dev; - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { -@@ -3528,7 +3554,8 @@ static int airoha_alloc_gdm_port(struct + return 0; + } +@@ -3061,7 +3080,8 @@ static int airoha_alloc_gdm_port(struct { const __be32 *id_ptr = of_get_property(np, "reg", NULL); struct airoha_gdm_port *port; @@ -370,7 +326,7 @@ Signed-off-by: Lorenzo Bianconi u32 id; if (!id_ptr) { -@@ -3556,15 +3583,51 @@ static int airoha_alloc_gdm_port(struct +@@ -3089,15 +3109,51 @@ static int airoha_alloc_gdm_port(struct u64_stats_init(&port->stats.syncp); spin_lock_init(&port->stats.lock); port->id = id; @@ -425,7 +381,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_register_gdm_devices(struct airoha_eth *eth) -@@ -3573,14 +3636,22 @@ static int airoha_register_gdm_devices(s +@@ -3106,14 +3162,22 @@ static int airoha_register_gdm_devices(s for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -452,7 +408,7 @@ Signed-off-by: Lorenzo Bianconi } set_bit(DEV_STATE_REGISTERED, ð->state); -@@ -3687,15 +3758,19 @@ error_napi_stop: +@@ -3220,17 +3284,22 @@ error_napi_stop: for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -473,18 +429,13 @@ Signed-off-by: Lorenzo Bianconi + continue; + netdev = netdev_from_priv(dev); - if (netdev->reg_state == NETREG_REGISTERED) { - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) -@@ -3703,6 +3778,7 @@ error_napi_stop: - #endif + if (netdev->reg_state == NETREG_REGISTERED) unregister_netdev(netdev); - } + of_node_put(netdev->dev.of_node); } airoha_metadata_dst_free(port); } -@@ -3724,19 +3800,27 @@ static void airoha_remove(struct platfor +@@ -3252,14 +3321,22 @@ static void airoha_remove(struct platfor for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -494,6 +445,9 @@ Signed-off-by: Lorenzo Bianconi if (!port) continue; +- dev = port->dev; +- if (dev) +- unregister_netdev(netdev_from_priv(dev)); + for (j = 0; j < ARRAY_SIZE(port->devs); j++) { + struct airoha_gdm_dev *dev = port->devs[j]; + struct net_device *netdev; @@ -501,16 +455,6 @@ Signed-off-by: Lorenzo Bianconi + if (!dev) + continue; + - #if defined(CONFIG_PCS_AIROHA) -- if (airhoa_is_phy_external(port)) -- phylink_destroy(dev->phylink); -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(dev->phylink); - #endif - -- dev = port->dev; -- if (dev) -- unregister_netdev(netdev_from_priv(dev)); + netdev = netdev_from_priv(dev); + unregister_netdev(netdev); + of_node_put(netdev->dev.of_node); @@ -518,7 +462,7 @@ Signed-off-by: Lorenzo Bianconi airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); -@@ -3798,6 +3882,39 @@ static u32 airoha_en7581_get_vip_port(st +@@ -3322,6 +3399,39 @@ static u32 airoha_en7581_get_vip_port(st return 0; } @@ -556,9 +500,9 @@ Signed-off-by: Lorenzo Bianconi +} + static const char * const an7583_xsi_rsts_names[] = { + "xsi-mac", "hsi0-mac", - "hsi1-mac", -@@ -3846,6 +3963,36 @@ static u32 airoha_an7583_get_vip_port(st +@@ -3371,6 +3481,36 @@ static u32 airoha_an7583_get_vip_port(st return 0; } @@ -595,7 +539,7 @@ Signed-off-by: Lorenzo Bianconi static const struct airoha_eth_soc_data en7581_soc_data = { .version = 0x7581, .xsi_rsts_names = en7581_xsi_rsts_names, -@@ -3854,6 +4001,7 @@ static const struct airoha_eth_soc_data +@@ -3379,6 +3519,7 @@ static const struct airoha_eth_soc_data .ops = { .get_sport = airoha_en7581_get_sport, .get_vip_port = airoha_en7581_get_vip_port, @@ -603,7 +547,7 @@ Signed-off-by: Lorenzo Bianconi }, }; -@@ -3865,6 +4013,7 @@ static const struct airoha_eth_soc_data +@@ -3390,6 +3531,7 @@ static const struct airoha_eth_soc_data .ops = { .get_sport = airoha_an7583_get_sport, .get_vip_port = airoha_an7583_get_vip_port, @@ -621,7 +565,7 @@ Signed-off-by: Lorenzo Bianconi #define AIROHA_MAX_NUM_QDMA 2 #define AIROHA_MAX_NUM_IRQ_BANKS 4 #define AIROHA_MAX_DSA_PORTS 7 -@@ -563,12 +564,13 @@ struct airoha_gdm_dev { +@@ -546,12 +547,13 @@ struct airoha_gdm_dev { /* qos stats counters */ u64 cpu_tx_packets; u64 fwd_tx_packets; @@ -637,7 +581,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_hw_stats stats; -@@ -604,6 +606,8 @@ struct airoha_eth_soc_data { +@@ -587,6 +589,8 @@ struct airoha_eth_soc_data { struct { int (*get_sport)(struct airoha_gdm_port *port, int nbq); u32 (*get_vip_port)(struct airoha_gdm_port *port, int nbq); @@ -648,7 +592,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -168,9 +168,7 @@ static void airoha_ppe_hw_init(struct ai +@@ -167,9 +167,7 @@ static void airoha_ppe_hw_init(struct ai airoha_fe_clear(eth, REG_PPE_PPE_FLOW_CFG(i), PPE_FLOW_CFG_IP6_6RD_MASK); @@ -659,7 +603,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_PPE_MTU(i, p), FP0_EGRESS_MTU_MASK | FP1_EGRESS_MTU_MASK, -@@ -178,11 +176,27 @@ static void airoha_ppe_hw_init(struct ai +@@ -177,11 +175,27 @@ static void airoha_ppe_hw_init(struct ai AIROHA_MAX_MTU) | FIELD_PREP(FP1_EGRESS_MTU_MASK, AIROHA_MAX_MTU)); diff --git a/target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch b/target/linux/airoha/patches-6.18/165-03-v7.2-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch similarity index 70% rename from target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch rename to target/linux/airoha/patches-6.18/165-03-v7.2-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch index 7dc33792bd..cc8627fe54 100644 --- a/target/linux/airoha/patches-6.18/920-07-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch +++ b/target/linux/airoha/patches-6.18/165-03-v7.2-net-airoha-Do-not-stop-GDM-port-if-it-is-shared.patch @@ -1,10 +1,7 @@ -From de856a5b802cf030c8e242e98df3bc88446a4ea1 Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: +From 99b9d095d71e5cb84121dacce2ac217aad9b174f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 20 Mar 2026 11:09:40 +0100 -Subject: [PATCH 07/13] net: airoha: Do not stop GDM port if it is shared +Date: Wed, 3 Jun 2026 08:00:18 +0200 +Subject: [PATCH 3/5] net: airoha: Do not stop GDM port if it is shared Theoretically, in the current codebase, two independent net_devices can be connected to the same GDM port so we need to check the GDM port is not @@ -16,6 +13,8 @@ GDM port. Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-4-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 59 +++++++++++++++++++----- drivers/net/ethernet/airoha/airoha_eth.h | 1 + @@ -23,27 +22,25 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1992,10 +1992,10 @@ static int airoha_dev_open(struct net_de +@@ -1723,8 +1723,8 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - int qdma_id = qdma - ð->qdma[0]; - u32 pse_port = FE_PSE_PORT_PPE1; - /* HW LRO is configured on the QDMA and it is shared between - * all the devices using it. Refuse to open a second device on -@@ -2034,10 +2034,20 @@ static int airoha_dev_open(struct net_de - airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), + netif_tx_start_all_queues(netdev); + err = airoha_set_vip_for_gdm_port(dev, true); +@@ -1738,10 +1738,20 @@ static int airoha_dev_open(struct net_de + airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); -- airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), +- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), - GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, - FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | - FIELD_PREP(GDM_LONG_LEN_MASK, len)); -+ cur_len = airoha_fe_get(eth, REG_GDM_LEN_CFG(port->id), ++ cur_len = airoha_fe_get(qdma->eth, REG_GDM_LEN_CFG(port->id), + GDM_LONG_LEN_MASK); + if (!port->users || len > cur_len) { + /* Opening a sibling net_device with a larger MTU updates the @@ -51,7 +48,7 @@ Signed-off-by: Lorenzo Bianconi + * multiple net_devices with different MTUs to share the same + * GDM port. + */ -+ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), ++ airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), + GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, + FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | + FIELD_PREP(GDM_LONG_LEN_MASK, len)); @@ -60,7 +57,7 @@ Signed-off-by: Lorenzo Bianconi airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK | -@@ -2060,6 +2070,30 @@ static int airoha_dev_open(struct net_de +@@ -1757,6 +1767,30 @@ static int airoha_dev_open(struct net_de return 0; } @@ -91,21 +88,22 @@ Signed-off-by: Lorenzo Bianconi static int airoha_dev_stop(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -2073,8 +2107,11 @@ static int airoha_dev_stop(struct net_de +@@ -1769,8 +1803,12 @@ static int airoha_dev_stop(struct net_de for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); -- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), +- airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), - FE_PSE_PORT_DROP); + if (--port->users) -+ airoha_set_port_mtu(eth, port); ++ airoha_set_port_mtu(dev->eth, port); + else -+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), ++ airoha_set_gdm_port_fwd_cfg(qdma->eth, ++ REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); - if (!--qdma->users) { + if (atomic_dec_and_test(&qdma->users)) { airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, -@@ -2238,13 +2275,10 @@ static int airoha_dev_change_mtu(struct +@@ -1925,13 +1963,10 @@ static int airoha_dev_change_mtu(struct { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -123,7 +121,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -571,6 +571,7 @@ struct airoha_gdm_dev { +@@ -554,6 +554,7 @@ struct airoha_gdm_dev { struct airoha_gdm_port { struct airoha_gdm_dev *devs[AIROHA_MAX_NUM_GDM_DEVS]; int id; diff --git a/target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch b/target/linux/airoha/patches-6.18/165-04-v7.2-net-airoha-Introduce-WAN-device-flag.patch similarity index 83% rename from target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch rename to target/linux/airoha/patches-6.18/165-04-v7.2-net-airoha-Introduce-WAN-device-flag.patch index a21fa3f05b..35e864e30d 100644 --- a/target/linux/airoha/patches-6.18/920-08-net-airoha-Introduce-WAN-device-flag.patch +++ b/target/linux/airoha/patches-6.18/165-04-v7.2-net-airoha-Introduce-WAN-device-flag.patch @@ -1,10 +1,7 @@ -From c4f3077948eda05a6b9d1a11304d82c3e0300151 Mon Sep 17 00:00:00 2001 -Message-ID: -In-Reply-To: -References: +From 7758cb462ff72b10d71e72bca8cf65179a1264e8 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Fri, 3 Apr 2026 12:07:27 +0200 -Subject: [PATCH 08/13] net: airoha: Introduce WAN device flag +Date: Wed, 3 Jun 2026 08:00:19 +0200 +Subject: [PATCH 4/5] net: airoha: Introduce WAN device flag Introduce WAN flag to specify if a given device is used to transmit/receive WAN or LAN traffic. Current codebase supports specifying LAN/WAN device @@ -21,15 +18,17 @@ officially supported since PCS/external phy is not merged mainline yet Tested-by: Xuegang Lu Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-5-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- - drivers/net/ethernet/airoha/airoha_eth.c | 72 +++++++++++++++++++----- + drivers/net/ethernet/airoha/airoha_eth.c | 73 +++++++++++++++++++----- drivers/net/ethernet/airoha/airoha_eth.h | 13 ++--- drivers/net/ethernet/airoha/airoha_ppe.c | 2 +- - 3 files changed, 65 insertions(+), 22 deletions(-) + 3 files changed, 66 insertions(+), 22 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2214,36 +2214,81 @@ static int airoha_set_gdm2_loopback(stru +@@ -1902,36 +1902,81 @@ static int airoha_enable_gdm2_loopback(s return 0; } @@ -86,7 +85,7 @@ Signed-off-by: Lorenzo Bianconi - if (!eth->ports[1]) { - int err; - -- err = airoha_set_gdm2_loopback(dev); +- err = airoha_enable_gdm2_loopback(dev); - if (err) - return err; - } @@ -119,7 +118,7 @@ Signed-off-by: Lorenzo Bianconi + (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)) { + int err; + -+ err = airoha_set_gdm2_loopback(dev); ++ err = airoha_enable_gdm2_loopback(dev); + if (err) + return err; + } @@ -128,7 +127,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -550,6 +550,10 @@ struct airoha_qdma { +@@ -538,6 +538,10 @@ struct airoha_qdma { DECLARE_BITMAP(qos_channel_map, AIROHA_NUM_QOS_CHANNELS); }; @@ -139,7 +138,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_gdm_dev { struct airoha_gdm_port *port; struct airoha_qdma *qdma; -@@ -565,6 +569,7 @@ struct airoha_gdm_dev { +@@ -548,6 +552,7 @@ struct airoha_gdm_dev { u64 cpu_tx_packets; u64 fwd_tx_packets; @@ -147,7 +146,7 @@ Signed-off-by: Lorenzo Bianconi int nbq; }; -@@ -671,13 +676,7 @@ static inline u16 airoha_qdma_get_txq(st +@@ -654,13 +659,7 @@ static inline u16 airoha_qdma_get_txq(st static inline bool airoha_is_lan_gdm_dev(struct airoha_gdm_dev *dev) { @@ -164,7 +163,7 @@ Signed-off-by: Lorenzo Bianconi static inline bool airoha_is_7581(struct airoha_eth *eth) --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -356,7 +356,7 @@ static int airoha_ppe_foe_entry_prepare( +@@ -355,7 +355,7 @@ static int airoha_ppe_foe_entry_prepare( return -EINVAL; port = dev->port; diff --git a/target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch b/target/linux/airoha/patches-6.18/165-05-v7.2-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch similarity index 75% rename from target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch rename to target/linux/airoha/patches-6.18/165-05-v7.2-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch index 553bd3cbf5..a4041bb3db 100644 --- a/target/linux/airoha/patches-6.18/920-09-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch +++ b/target/linux/airoha/patches-6.18/165-05-v7.2-net-airoha-Support-multiple-LAN-WAN-interfaces-for-h.patch @@ -1,38 +1,42 @@ -From 144f0e6e55896625e3411aad02399a5ebb48d8f9 Mon Sep 17 00:00:00 2001 -Message-ID: <144f0e6e55896625e3411aad02399a5ebb48d8f9.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: +From ef2aee987174b51573645b4bdacedf610e89ce1a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Mon, 13 Apr 2026 17:38:51 +0200 -Subject: [PATCH 09/13] net: airoha: Support multiple LAN/WAN interfaces for hw +Date: Wed, 3 Jun 2026 08:00:20 +0200 +Subject: [PATCH 5/5] net: airoha: Support multiple LAN/WAN interfaces for hw MAC address configuration The EN7581 and AN7583 SoCs provide registers to configure hardware LAN/WAN -MAC addresses, used to determine whether received traffic is destined for -this host or should be forwarded to another device. +MAC addresses. These registers are used during FE hw acceleration to +determine whether received traffic is destined to this host (L3 traffic) +or should be switched to another device (L2 traffic). The SoC hardware design assumes all interfaces configured as LAN (or WAN) -share a common upper MAC address, which is programmed into the -REG_FE_{LAN,WAN}_MAC_H register. The lower bytes of 'local' addresses can -be expressed as a range via the REG_FE_MAC_LMIN and REG_FE_MAC_LMAX -registers. +share the MAC address MSBs, which are programmed into the +REG_FE_{LAN,WAN}_MAC_H register. The LSBs of 'local' mac addresses can be +expressed as a range via the REG_FE_MAC_LMIN and REG_FE_MAC_LMAX +registers. In order to properly accelerate the traffic, FE module requires +the user to configure the REG_FE_{LAN,WAN}_MAC_H register respecting this +limitation. Please note a misconfiguration in REG_FE_{LAN,WAN}_MAC_H +will still allow the user to log into the device for debugging. Previously, only a single interface was considered when programming these registers. Extend the logic to derive the correct minimum and maximum values for REG_FE_MAC_LMIN/REG_FE_MAC_LMAX when two or more interfaces are -configured as LAN or WAN. +configured as LAN or WAN. Since this functionality was not available +before this series, no regression is introduced. Tested-by: Madhur Agrawal Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260603-airoha-eth-multi-serdes-v9-6-5d476bc2f426@kernel.org +Signed-off-by: Jakub Kicinski --- - drivers/net/ethernet/airoha/airoha_eth.c | 77 ++++++++++++++++++++---- + drivers/net/ethernet/airoha/airoha_eth.c | 77 +++++++++++++++++++++--- drivers/net/ethernet/airoha/airoha_eth.h | 2 +- drivers/net/ethernet/airoha/airoha_ppe.c | 4 +- - 3 files changed, 68 insertions(+), 15 deletions(-) + 3 files changed, 71 insertions(+), 12 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -81,20 +81,76 @@ static bool airhoa_is_phy_external(struc +@@ -71,20 +71,76 @@ static void airoha_qdma_irq_disable(stru + airoha_qdma_set_irqmask(irq_bank, index, mask, 0); } - #endif -static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) +static int airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr) @@ -105,15 +109,15 @@ Signed-off-by: Lorenzo Bianconi - airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); + airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), lmin); + airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), lmax); -+ -+ airoha_ppe_init_upd_mem(dev, addr); - airoha_ppe_init_upd_mem(dev); ++ airoha_ppe_init_upd_mem(dev, addr); ++ + return 0; } static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, -@@ -2141,13 +2197,18 @@ static int airoha_dev_stop(struct net_de +@@ -1829,13 +1885,18 @@ static int airoha_dev_stop(struct net_de static int airoha_dev_set_macaddr(struct net_device *netdev, void *p) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -136,7 +140,7 @@ Signed-off-by: Lorenzo Bianconi } --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -712,7 +712,7 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -683,7 +683,7 @@ void airoha_ppe_check_skb(struct airoha_ int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data); int airoha_ppe_init(struct airoha_eth *eth); void airoha_ppe_deinit(struct airoha_eth *eth); @@ -147,7 +151,7 @@ Signed-off-by: Lorenzo Bianconi u32 hash); --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c -@@ -1499,12 +1499,10 @@ void airoha_ppe_check_skb(struct airoha_ +@@ -1487,12 +1487,10 @@ void airoha_ppe_check_skb(struct airoha_ airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan); } diff --git a/target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch b/target/linux/airoha/patches-6.18/166-v7.2-net-airoha-better-handle-MIBs-for-GDM-ports-with-mul.patch similarity index 87% rename from target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch rename to target/linux/airoha/patches-6.18/166-v7.2-net-airoha-better-handle-MIBs-for-GDM-ports-with-mul.patch index 1aec4e91fc..474cbe9a1b 100644 --- a/target/linux/airoha/patches-6.18/920-14-net-airoha-Better-handle-MIB-for-GDM-with-multiple-p.patch +++ b/target/linux/airoha/patches-6.18/166-v7.2-net-airoha-better-handle-MIBs-for-GDM-ports-with-mul.patch @@ -1,29 +1,31 @@ -From 9652322e0b47eacfef497828f6476a2a3169fd13 Mon Sep 17 00:00:00 2001 -Message-ID: <9652322e0b47eacfef497828f6476a2a3169fd13.1779351672.git.lorenzo@kernel.org> -From: Christian Marangi -Date: Sat, 17 Jan 2026 14:46:12 +0100 -Subject: [PATCH] net: airoha: Better handle MIB for GDM with multiple port - attached - -In the context of a GDM that can have multiple port attached (GDM3/4) -the HW counter (MIB) are global for the GDM port. This cause duplicated -stats reported to the kernel for the related interface. +From 8f4695fb67b259b2cae0be1eef55859bfc559058 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 11 Jun 2026 12:43:00 +0200 +Subject: [PATCH] net: airoha: better handle MIBs for GDM ports with multiple + devs attached +In the context of a GDM port that can have multiple net_devices attached +(GDM3 and GDM4), the HW counters (MIBs) are global for the GDM port. +This cause duplicated stats reported to the kernel for the related +net_device. The SoC supports a split MIB feature where each counter is tracked based on the relevant HW channel (NBQ) to account for this scenario and provide a way to select the related counter on accessing the MIB registers. - Enable this feature for GDM3 and GDM4 and configure the relevant HW channel before updating the HW stats to report correct HW counter to the kernel for the related interface. +Move the stats struct from port to dev since HW counter are now specific +to the network device instead of the GDM port. Refactor +airoha_update_hw_stats() to take airoha_eth and airoha_gdm_port +parameters since the function operates on the entire port. -Also move the stats struct from port to dev since HW counter are -now specific to the network interface instead of the GDM port. - -Co-developed-by: Brown Huang -Signed-off-by: Brown Huang +Co-developed-by: Christian Marangi Signed-off-by: Christian Marangi +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260611-airoha-eth-multi-serdes-stats-v1-1-42442ae42064@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 191 +++++++++++++---------- drivers/net/ethernet/airoha/airoha_eth.h | 7 +- @@ -31,9 +33,9 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -640,6 +640,14 @@ static int airoha_fe_init(struct airoha_ - airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX), - GDM_PAD_EN_MASK | GDM_STRIP_CRC_MASK); +@@ -556,6 +556,14 @@ static int airoha_fe_init(struct airoha_ + airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM3_IDX), GDM_PAD_EN_MASK); + airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX), GDM_PAD_EN_MASK); + /* Enable split for MIB counters for GDM3 and GDM4 */ + airoha_fe_set(eth, REG_FE_GDM_MIB_CFG(AIROHA_GDM3_IDX), @@ -46,7 +48,7 @@ Signed-off-by: Christian Marangi airoha_fe_crsn_qsel_init(eth); airoha_fe_clear(eth, REG_FE_CPORT_CFG, FE_CPORT_QUEUE_XFC_MASK); -@@ -1872,149 +1880,169 @@ static void airoha_qdma_stop_napi(struct +@@ -1629,149 +1637,169 @@ static void airoha_qdma_stop_napi(struct } } @@ -59,14 +61,14 @@ Signed-off-by: Christian Marangi - spin_lock(&port->stats.lock); - u64_stats_update_begin(&port->stats.syncp); -+ u64_stats_update_begin(&dev->stats.syncp); -+ + /* Read relevant MIB for GDM with multiple port attached */ + if (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX) + airoha_fe_rmw(eth, REG_FE_GDM_MIB_CFG(port->id), + FE_TX_MIB_ID_MASK | FE_RX_MIB_ID_MASK, + FIELD_PREP(FE_TX_MIB_ID_MASK, dev->nbq) | + FIELD_PREP(FE_RX_MIB_ID_MASK, dev->nbq)); ++ ++ u64_stats_update_begin(&dev->stats.syncp); /* TX */ val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_H(port->id)); @@ -245,7 +247,9 @@ Signed-off-by: Christian Marangi + + u64_stats_update_end(&dev->stats.syncp); +} -+ + +- /* reset mib counters */ +- airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id), +static void airoha_update_hw_stats(struct airoha_gdm_dev *dev) +{ + struct airoha_gdm_port *port = dev->port; @@ -257,9 +261,7 @@ Signed-off-by: Christian Marangi + if (port->devs[i]) + airoha_dev_get_hw_stats(port->devs[i]); + } - -- /* reset mib counters */ -- airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id), ++ + /* Reset MIB counters */ + airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id), FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK); @@ -269,8 +271,8 @@ Signed-off-by: Christian Marangi + spin_unlock(&port->stats_lock); } - static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) -@@ -2418,23 +2446,22 @@ static void airoha_dev_get_stats64(struc + static int airoha_dev_open(struct net_device *netdev) +@@ -2046,23 +2074,22 @@ static void airoha_dev_get_stats64(struc struct rtnl_link_stats64 *storage) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -306,7 +308,7 @@ Signed-off-by: Christian Marangi } static int airoha_dev_change_mtu(struct net_device *netdev, int mtu) -@@ -2723,20 +2750,19 @@ static void airoha_ethtool_get_mac_stats +@@ -2313,20 +2340,19 @@ static void airoha_ethtool_get_mac_stats struct ethtool_eth_mac_stats *stats) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -336,7 +338,7 @@ Signed-off-by: Christian Marangi } static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = { -@@ -2756,8 +2782,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2346,8 +2372,7 @@ airoha_ethtool_get_rmon_stats(struct net const struct ethtool_rmon_hist_range **ranges) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -346,7 +348,7 @@ Signed-off-by: Christian Marangi unsigned int start; BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) != -@@ -2770,7 +2795,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2360,7 +2385,7 @@ airoha_ethtool_get_rmon_stats(struct net do { int i; @@ -355,7 +357,7 @@ Signed-off-by: Christian Marangi stats->fragments = hw_stats->rx_fragment; stats->jabbers = hw_stats->rx_jabber; for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1; -@@ -2778,7 +2803,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2368,7 +2393,7 @@ airoha_ethtool_get_rmon_stats(struct net stats->hist[i] = hw_stats->rx_len[i]; stats->hist_tx[i] = hw_stats->tx_len[i]; } @@ -364,7 +366,7 @@ Signed-off-by: Christian Marangi } static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, -@@ -3849,6 +3874,7 @@ static int airoha_alloc_gdm_device(struc +@@ -3208,6 +3233,7 @@ static int airoha_alloc_gdm_device(struc netdev->dev.of_node = of_node_get(np); dev = netdev_priv(netdev); @@ -372,7 +374,7 @@ Signed-off-by: Christian Marangi dev->port = port; dev->eth = eth; dev->nbq = nbq; -@@ -3896,9 +3922,8 @@ static int airoha_alloc_gdm_port(struct +@@ -3247,9 +3273,8 @@ static int airoha_alloc_gdm_port(struct if (!port) return -ENOMEM; @@ -385,7 +387,7 @@ Signed-off-by: Christian Marangi err = airoha_metadata_dst_alloc(port); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -228,8 +228,6 @@ struct airoha_tx_irq_queue { +@@ -215,8 +215,6 @@ struct airoha_tx_irq_queue { }; struct airoha_hw_stats { @@ -394,7 +396,7 @@ Signed-off-by: Christian Marangi struct u64_stats_sync syncp; /* get_stats64 */ -@@ -573,6 +571,8 @@ struct airoha_gdm_dev { +@@ -554,6 +552,8 @@ struct airoha_gdm_dev { u32 flags; int nbq; @@ -403,7 +405,7 @@ Signed-off-by: Christian Marangi }; struct airoha_gdm_port { -@@ -580,7 +580,8 @@ struct airoha_gdm_port { +@@ -561,7 +561,8 @@ struct airoha_gdm_port { int id; int users; diff --git a/target/linux/airoha/patches-6.18/916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch b/target/linux/airoha/patches-6.18/167-v7.2-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch similarity index 75% rename from target/linux/airoha/patches-6.18/916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch rename to target/linux/airoha/patches-6.18/167-v7.2-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch index 5d4ecf6606..46c18073e5 100644 --- a/target/linux/airoha/patches-6.18/916-01-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch +++ b/target/linux/airoha/patches-6.18/167-v7.2-net-airoha-use-int-instead-of-atomic_t-for-qdma-user.patch @@ -1,5 +1,4 @@ From a459b560e58be327689e9bd8c0a6be9a4f163366 Mon Sep 17 00:00:00 2001 -Message-ID: From: Lorenzo Bianconi Date: Thu, 11 Jun 2026 23:55:51 +0200 Subject: [PATCH] net: airoha: use int instead of atomic_t for qdma users @@ -18,18 +17,18 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1761,7 +1761,7 @@ static int airoha_dev_open(struct net_de +@@ -1840,7 +1840,7 @@ static int airoha_dev_open(struct net_de airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK | GLOBAL_CFG_RX_DMA_EN_MASK); - atomic_inc(&qdma->users); + qdma->users++; - if (port->id == AIROHA_GDM2_IDX && - airoha_ppe_is_enabled(qdma->eth, 1)) { -@@ -1788,7 +1788,7 @@ static int airoha_dev_stop(struct net_de - airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), - FE_PSE_PORT_DROP); + if (!airoha_is_lan_gdm_dev(dev) && + airoha_ppe_is_enabled(qdma->eth, 1)) +@@ -1894,7 +1894,7 @@ static int airoha_dev_stop(struct net_de + REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); - if (atomic_dec_and_test(&qdma->users)) { + if (!--qdma->users) { @@ -38,7 +37,7 @@ Signed-off-by: Jakub Kicinski GLOBAL_CFG_RX_DMA_EN_MASK); --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -525,7 +525,7 @@ struct airoha_qdma { +@@ -524,7 +524,7 @@ struct airoha_qdma { struct airoha_eth *eth; void __iomem *regs; diff --git a/target/linux/airoha/patches-6.18/168-v7.2-net-airoha-move-get_sport-callback-at-the-beginning-.patch b/target/linux/airoha/patches-6.18/168-v7.2-net-airoha-move-get_sport-callback-at-the-beginning-.patch new file mode 100644 index 0000000000..da75698155 --- /dev/null +++ b/target/linux/airoha/patches-6.18/168-v7.2-net-airoha-move-get_sport-callback-at-the-beginning-.patch @@ -0,0 +1,50 @@ +From aeb62be4d3b18b76551bf7806e30d72e5c3bbade Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 8 Jun 2026 23:24:15 +0200 +Subject: [PATCH] net: airoha: move get_sport() callback at the beginning of + airoha_enable_gdm2_loopback() + +Move the get_sport() callback invocation at the beginning of +airoha_enable_gdm2_loopback() routine in order to avoid leaving the +hardware in a partially configured state if get_sport() fails. +Previously, get_sport() was called after GDM2 forwarding, loopback, +channel, length, VIP and IFC registers had already been programmed. +A failure at that point would return an error leaving GDM2 with +loopback enabled but WAN port, PPE CPU port and flow control mappings +not configured. +Performing the get_sport() lookup before any register write guarantees +the routine either completes the full configuration sequence or exits +with no side effects on the hardware. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260608-airoha_enable_gdm2_loopback-minor-change-v1-1-1787a0f42b31@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1936,6 +1936,10 @@ static int airoha_enable_gdm2_loopback(s + u32 val, pse_port, chan; + int i, src_port; + ++ src_port = eth->soc->ops.get_sport(port, dev->nbq); ++ if (src_port < 0) ++ return src_port; ++ + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), + FE_PSE_PORT_DROP); + airoha_fe_clear(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), +@@ -1965,10 +1969,6 @@ static int airoha_enable_gdm2_loopback(s + airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); + airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); + +- src_port = eth->soc->ops.get_sport(port, dev->nbq); +- if (src_port < 0) +- return src_port; +- + airoha_fe_rmw(eth, REG_FE_WAN_PORT, + WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, + FIELD_PREP(WAN0_MASK, src_port)); diff --git a/target/linux/airoha/patches-6.18/922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch b/target/linux/airoha/patches-6.18/169-v7.2-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch similarity index 77% rename from target/linux/airoha/patches-6.18/922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch rename to target/linux/airoha/patches-6.18/169-v7.2-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch index c9e788e3e1..e2ce9978b8 100644 --- a/target/linux/airoha/patches-6.18/922-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch +++ b/target/linux/airoha/patches-6.18/169-v7.2-net-airoha-simplify-WAN-device-check-in-airoha_dev_i.patch @@ -1,7 +1,6 @@ -From 3d67e4ba79bd4b40f520d26af098f133b5f551d4 Mon Sep 17 00:00:00 2001 -Message-ID: <3d67e4ba79bd4b40f520d26af098f133b5f551d4.1781097105.git.lorenzo@kernel.org> +From 9912dfa2d46aef4cd708246aa6b39b49213f5e62 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi -Date: Sat, 6 Jun 2026 08:53:03 +0200 +Date: Wed, 10 Jun 2026 15:25:13 +0200 Subject: [PATCH] net: airoha: simplify WAN device check in airoha_dev_init() airoha_register_gdm_devices() iterates eth->ports[] in order, so GDM2's @@ -13,13 +12,16 @@ Remove the redundant check and rely solely on airoha_get_wan_gdm_dev() which handles both the GDM2-present and GDM2-absent cases. Signed-off-by: Lorenzo Bianconi +Reviewed-by: Alexander Lobakin +Link: https://patch.msgid.link/20260610-airoha-eth-simplify-dev-init-v2-1-8f244e69b0d4@kernel.org +Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2407,18 +2407,10 @@ static int airoha_dev_init(struct net_de +@@ -2035,18 +2035,10 @@ static int airoha_dev_init(struct net_de switch (port->id) { case AIROHA_GDM3_IDX: diff --git a/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch b/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch index a75e06f944..61cd51ca60 100644 --- a/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch +++ b/target/linux/airoha/patches-6.18/310-02-net-airoha-deassert-XSI-line-on-hw-init.patch @@ -13,7 +13,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1487,6 +1487,10 @@ static int airoha_hw_init(struct platfor +@@ -1568,6 +1568,10 @@ static int airoha_hw_init(struct platfor if (err) return err; diff --git a/target/linux/airoha/patches-6.18/310-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch b/target/linux/airoha/patches-6.18/310-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch deleted file mode 100644 index d5a2ba9d1a..0000000000 --- a/target/linux/airoha/patches-6.18/310-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ad29054f9b0e96e30a5d0bb6967d1204b8ea8bd1 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Fri, 17 Jan 2025 10:12:02 +0100 -Subject: [PATCH 3/9] net: airoha: add reference for SPORT GDM4 in - qdma_get_gdm_port - -Add SPORT reference in get gdm port as the on receive the SPORT 0x18 is -assigned for the GDM4 port. - -While at it also add comments to better identify GDM1 ports. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -574,8 +574,11 @@ static int airoha_qdma_get_gdm_port(stru - - sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); - switch (sport) { -+ case 0x18: -+ port = 3; /* GDM4 */ -+ break; - case 0x10 ... 0x14: -- port = 0; -+ port = 0; /* GDM1 */ - break; - case 0x2 ... 0x4: - port = sport - 1; diff --git a/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch b/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch index cd774e11ea..2de3c8d1a8 100644 --- a/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch +++ b/target/linux/airoha/patches-6.18/310-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch @@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -498,8 +498,10 @@ static int airoha_fe_init(struct airoha_ +@@ -553,8 +553,10 @@ static int airoha_fe_init(struct airoha_ FIELD_PREP(IP_ASSEMBLE_PORT_MASK, 0) | FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22)); @@ -26,15 +26,15 @@ Signed-off-by: Christian Marangi + airoha_fe_set(eth, REG_GDM_FWD_CFG(AIROHA_GDM4_IDX), + GDM_PAD_EN_MASK | GDM_STRIP_CRC_MASK); - airoha_fe_crsn_qsel_init(eth); - -@@ -1719,7 +1721,8 @@ static int airoha_dev_open(struct net_de + /* Enable split for MIB counters for GDM3 and GDM4 */ + airoha_fe_set(eth, REG_FE_GDM_MIB_CFG(AIROHA_GDM3_IDX), +@@ -1819,7 +1821,8 @@ static int airoha_dev_open(struct net_de if (err) return err; -- if (netdev_uses_dsa(dev)) +- if (netdev_uses_dsa(netdev)) + /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ -+ if (netdev_uses_dsa(dev) || port->id > 2) ++ if (netdev_uses_dsa(netdev) || port->id > 2) airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); else diff --git a/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch b/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch index 0ecba241d8..d6560370d2 100644 --- a/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch +++ b/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch @@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -3196,7 +3196,6 @@ static void airoha_remove(struct platfor +@@ -3511,7 +3511,6 @@ static void airoha_remove(struct platfor } static const char * const en7581_xsi_rsts_names[] = { @@ -23,7 +23,7 @@ Signed-off-by: Christian Marangi "hsi0-mac", "hsi1-mac", "hsi-mac", -@@ -3250,7 +3249,6 @@ static u32 airoha_en7581_get_vip_port(st +@@ -3598,7 +3597,6 @@ static int airoha_en7581_get_dev_from_sp } static const char * const an7583_xsi_rsts_names[] = { diff --git a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support-for-GDM2-3-4.patch b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support-for-GDM2-3-4.patch deleted file mode 100644 index 7421c01c06..0000000000 --- a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support-for-GDM2-3-4.patch +++ /dev/null @@ -1,281 +0,0 @@ -From ee93671d30d7741a39026c2aaaa6a7729929c347 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Fri, 17 Jan 2025 13:23:13 +0100 -Subject: [PATCH 2/2] net: airoha: add phylink support for GDM2/3/4 - -Add phylink support for GDM2/3/4 port that require configuration of the -PCS to make the external PHY or attached SFP cage work. - -These needs to be defined in the GDM port node using the pcs-handle -property. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/airoha/Kconfig | 1 + - drivers/net/ethernet/airoha/airoha_eth.c | 146 +++++++++++++++++++++- - drivers/net/ethernet/airoha/airoha_eth.h | 3 + - drivers/net/ethernet/airoha/airoha_regs.h | 12 ++ - 4 files changed, 161 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/airoha/Kconfig -+++ b/drivers/net/ethernet/airoha/Kconfig -@@ -20,6 +20,7 @@ config NET_AIROHA - depends on NET_DSA || !NET_DSA - select NET_AIROHA_NPU - select PAGE_POOL -+ select PHYLINK - help - This driver supports the gigabit ethernet MACs in the - Airoha SoC family. ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -71,6 +72,11 @@ static void airoha_qdma_irq_disable(stru - airoha_qdma_set_irqmask(irq_bank, index, mask, 0); - } - -+static bool airhoa_is_phy_external(struct airoha_gdm_port *port) -+{ -+ return port->id != 1; -+} -+ - static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) - { - struct airoha_eth *eth = port->qdma->eth; -@@ -1716,6 +1722,17 @@ static int airoha_dev_open(struct net_de - struct airoha_qdma *qdma = port->qdma; - u32 pse_port = FE_PSE_PORT_PPE1; - -+ if (airhoa_is_phy_external(port)) { -+ err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); -+ if (err) { -+ netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, -+ err); -+ return err; -+ } -+ -+ phylink_start(port->phylink); -+ } -+ - netif_tx_start_all_queues(dev); - err = airoha_set_vip_for_gdm_port(port, true); - if (err) -@@ -1777,6 +1794,11 @@ static int airoha_dev_stop(struct net_de - } - } - -+ if (airhoa_is_phy_external(port)) { -+ phylink_stop(port->phylink); -+ phylink_disconnect_phy(port->phylink); -+ } -+ - return 0; - } - -@@ -2916,6 +2938,11 @@ static const struct ethtool_ops airoha_e - .get_link = ethtool_op_get_link, - }; - -+static void airoha_mac_config(struct phylink_config *config, unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+} -+ - static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port) - { - int i; -@@ -2960,6 +2987,119 @@ bool airoha_is_valid_gdm_port(struct air - return false; - } - -+static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, -+ unsigned int mode, phy_interface_t interface, -+ int speed, int duplex, bool tx_pause, bool rx_pause) -+{ -+ struct airoha_gdm_port *port = container_of(config, struct airoha_gdm_port, -+ phylink_config); -+ struct airoha_qdma *qdma = port->qdma; -+ struct airoha_eth *eth = qdma->eth; -+ u32 frag_size_tx, frag_size_rx; -+ -+ if (port->id != 4) -+ return; -+ -+ switch (speed) { -+ case SPEED_10000: -+ case SPEED_5000: -+ frag_size_tx = 8; -+ frag_size_rx = 8; -+ break; -+ case SPEED_2500: -+ frag_size_tx = 2; -+ frag_size_rx = 1; -+ break; -+ default: -+ frag_size_tx = 1; -+ frag_size_rx = 0; -+ } -+ -+ /* Configure TX/RX frag based on speed */ -+ airoha_fe_rmw(eth, REG_GDMA4_TMBI_FRAG, -+ GDMA4_SGMII0_TX_FRAG_SIZE_MASK, -+ FIELD_PREP(GDMA4_SGMII0_TX_FRAG_SIZE_MASK, -+ frag_size_tx)); -+ -+ airoha_fe_rmw(eth, REG_GDMA4_RMBI_FRAG, -+ GDMA4_SGMII0_RX_FRAG_SIZE_MASK, -+ FIELD_PREP(GDMA4_SGMII0_RX_FRAG_SIZE_MASK, -+ frag_size_rx)); -+} -+ -+static void airoha_mac_link_down(struct phylink_config *config, unsigned int mode, -+ phy_interface_t interface) -+{ -+} -+ -+static const struct phylink_mac_ops airoha_phylink_ops = { -+ .mac_config = airoha_mac_config, -+ .mac_link_up = airoha_mac_link_up, -+ .mac_link_down = airoha_mac_link_down, -+}; -+ -+static int airoha_fill_available_pcs(struct phylink_config *config, -+ struct phylink_pcs **available_pcs, -+ unsigned int num_available_pcs) -+{ -+ struct device *dev = config->dev; -+ -+ return fwnode_phylink_pcs_parse(dev_fwnode(dev), available_pcs, -+ &num_available_pcs); -+} -+ -+static int airoha_setup_phylink(struct net_device *dev) -+{ -+ struct airoha_gdm_port *port = netdev_priv(dev); -+ struct device_node *np = dev->dev.of_node; -+ phy_interface_t phy_mode; -+ struct phylink *phylink; -+ int err; -+ -+ err = of_get_phy_mode(np, &phy_mode); -+ if (err) { -+ dev_err(&dev->dev, "incorrect phy-mode\n"); -+ return err; -+ } -+ -+ port->phylink_config.dev = &dev->dev; -+ port->phylink_config.type = PHYLINK_NETDEV; -+ port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -+ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | -+ MAC_5000FD | MAC_10000FD; -+ -+ err = fwnode_phylink_pcs_parse(dev_fwnode(&dev->dev), NULL, -+ &port->phylink_config.num_available_pcs); -+ if (err) -+ return err; -+ -+ port->phylink_config.fill_available_pcs = airoha_fill_available_pcs; -+ -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, -+ port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_USXGMII, -+ port->phylink_config.supported_interfaces); -+ -+ phy_interface_copy(port->phylink_config.pcs_interfaces, -+ port->phylink_config.supported_interfaces); -+ -+ phylink = phylink_create(&port->phylink_config, -+ of_fwnode_handle(np), -+ phy_mode, &airoha_phylink_ops); -+ if (IS_ERR(phylink)) -+ return PTR_ERR(phylink); -+ -+ port->phylink = phylink; -+ -+ return err; -+} -+ - static int airoha_alloc_gdm_port(struct airoha_eth *eth, - struct device_node *np) - { -@@ -3033,6 +3173,12 @@ static int airoha_alloc_gdm_port(struct - port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; - eth->ports[p] = port; - -+ if (airhoa_is_phy_external(port)) { -+ err = airoha_setup_phylink(dev); -+ if (err) -+ return err; -+ } -+ - return airoha_metadata_dst_alloc(port); - } - -@@ -3160,8 +3306,11 @@ error_napi_stop: - if (!port) - continue; - -- if (port->dev->reg_state == NETREG_REGISTERED) -+ if (port->dev->reg_state == NETREG_REGISTERED) { -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(port->phylink); - unregister_netdev(port->dev); -+ } - airoha_metadata_dst_free(port); - } - airoha_hw_cleanup(eth); -@@ -3186,6 +3335,8 @@ static void airoha_remove(struct platfor - if (!port) - continue; - -+ if (airhoa_is_phy_external(port)) -+ phylink_destroy(port->phylink); - unregister_netdev(port->dev); - airoha_metadata_dst_free(port); - } ---- a/drivers/net/ethernet/airoha/airoha_eth.h -+++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -542,6 +542,9 @@ struct airoha_gdm_port { - int id; - int nbq; - -+ struct phylink *phylink; -+ struct phylink_config phylink_config; -+ - struct airoha_hw_stats stats; - - DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); ---- a/drivers/net/ethernet/airoha/airoha_regs.h -+++ b/drivers/net/ethernet/airoha/airoha_regs.h -@@ -358,6 +358,18 @@ - #define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) - #define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) - -+#define REG_GDMA4_TMBI_FRAG 0x2028 -+#define GDMA4_SGMII1_TX_WEIGHT_MASK GENMASK(31, 26) -+#define GDMA4_SGMII1_TX_FRAG_SIZE_MASK GENMASK(25, 16) -+#define GDMA4_SGMII0_TX_WEIGHT_MASK GENMASK(15, 10) -+#define GDMA4_SGMII0_TX_FRAG_SIZE_MASK GENMASK(9, 0) -+ -+#define REG_GDMA4_RMBI_FRAG 0x202c -+#define GDMA4_SGMII1_RX_WEIGHT_MASK GENMASK(31, 26) -+#define GDMA4_SGMII1_RX_FRAG_SIZE_MASK GENMASK(25, 16) -+#define GDMA4_SGMII0_RX_WEIGHT_MASK GENMASK(15, 10) -+#define GDMA4_SGMII0_RX_FRAG_SIZE_MASK GENMASK(9, 0) -+ - #define REG_MC_VLAN_EN 0x2100 - #define MC_VLAN_EN_MASK BIT(0) - diff --git a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch new file mode 100644 index 0000000000..de636badfb --- /dev/null +++ b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch @@ -0,0 +1,361 @@ +From beb56181a370b003b12f657239b510435cae2c9d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 17 Jan 2025 13:23:13 +0100 +Subject: [PATCH] net: airoha: add phylink support + +Add phylink support for each GDM port. For GDM1 add the internal interface +mode as the only supported mode. For GDM2/3/4 add the required +configuration of the PCS to make the external PHY or attached SFP cage +work. + +These needs to be defined in the GDM port node using the pcs-handle +property. + +Update and provide a .get/set_link_ksettings function that use phylink +for ethtool OPs now that we fully support phylink. + +Signed-off-by: Christian Marangi +--- + drivers/net/ethernet/airoha/Kconfig | 1 + + drivers/net/ethernet/airoha/airoha_eth.c | 193 +++++++++++++++++++++- + drivers/net/ethernet/airoha/airoha_eth.h | 7 +- + drivers/net/ethernet/airoha/airoha_regs.h | 12 ++ + 4 files changed, 206 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/airoha/Kconfig ++++ b/drivers/net/ethernet/airoha/Kconfig +@@ -20,6 +20,7 @@ config NET_AIROHA + depends on NET_DSA || !NET_DSA + select NET_AIROHA_NPU + select PAGE_POOL ++ select PHYLINK + help + This driver supports the gigabit ethernet MACs in the + Airoha SoC family. +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1794,7 +1795,7 @@ static void airoha_update_hw_stats(struc + struct airoha_gdm_port *port = dev->port; + int i; + +- spin_lock(&port->stats_lock); ++ spin_lock(&port->lock); + + for (i = 0; i < ARRAY_SIZE(port->devs); i++) { + if (port->devs[i]) +@@ -1805,7 +1806,7 @@ static void airoha_update_hw_stats(struc + airoha_fe_set(dev->eth, REG_FE_GDM_MIB_CLEAR(port->id), + FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK); + +- spin_unlock(&port->stats_lock); ++ spin_unlock(&port->lock); + } + + static int airoha_dev_open(struct net_device *netdev) +@@ -1816,6 +1817,14 @@ static int airoha_dev_open(struct net_de + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; + struct airoha_qdma *qdma = dev->qdma; + ++ err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0); ++ if (err) { ++ netdev_err(netdev, "could not attach PHY: %d\n", err); ++ return err; ++ } ++ ++ phylink_start(dev->phylink); ++ + netif_tx_start_all_queues(netdev); + err = airoha_set_vip_for_gdm_port(dev, true); + if (err) +@@ -1914,6 +1923,9 @@ static int airoha_dev_stop(struct net_de + } + } + ++ phylink_stop(dev->phylink); ++ phylink_disconnect_phy(dev->phylink); ++ + return 0; + } + +@@ -2395,6 +2407,24 @@ airoha_ethtool_get_rmon_stats(struct net + } while (u64_stats_fetch_retry(&dev->stats.syncp, start)); + } + ++static int ++airoha_ethtool_get_link_ksettings(struct net_device *netdev, ++ struct ethtool_link_ksettings *cmd) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ ++ return phylink_ethtool_ksettings_get(dev->phylink, cmd); ++} ++ ++static int ++airoha_ethtool_set_link_ksettings(struct net_device *netdev, ++ const struct ethtool_link_ksettings *cmd) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ ++ return phylink_ethtool_ksettings_set(dev->phylink, cmd); ++} ++ + static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, + int channel, enum tx_sched_mode mode, + const u16 *weights, u8 n_weights) +@@ -3119,7 +3149,8 @@ static const struct ethtool_ops airoha_e + .get_drvinfo = airoha_ethtool_get_drvinfo, + .get_eth_mac_stats = airoha_ethtool_get_mac_stats, + .get_rmon_stats = airoha_ethtool_get_rmon_stats, +- .get_link_ksettings = phy_ethtool_get_link_ksettings, ++ .get_link_ksettings = airoha_ethtool_get_link_ksettings, ++ .set_link_ksettings = airoha_ethtool_set_link_ksettings, + .get_link = ethtool_op_get_link, + }; + +@@ -3175,6 +3206,159 @@ bool airoha_is_valid_gdm_dev(struct airo + return false; + } + ++/* Nothing to do in MAC, everything is handled in PCS */ ++static void airoha_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++} ++ ++static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, ++ phylink_config); ++ struct airoha_gdm_port *port = dev->port; ++ struct airoha_eth *eth = dev->eth; ++ u32 frag_size_tx, frag_size_rx; ++ u32 mask, val; ++ ++ /* TX/RX frag is configured only for GDM4 */ ++ if (port->id != AIROHA_GDM4_IDX) ++ return; ++ ++ switch (speed) { ++ case SPEED_10000: ++ case SPEED_5000: ++ frag_size_tx = 8; ++ frag_size_rx = 8; ++ break; ++ case SPEED_2500: ++ frag_size_tx = 2; ++ frag_size_rx = 1; ++ break; ++ default: ++ frag_size_tx = 1; ++ frag_size_rx = 0; ++ } ++ ++ spin_lock(&port->lock); ++ ++ /* Configure TX/RX frag based on speed */ ++ if (dev->nbq == 1) { ++ mask = GDM4_SGMII1_TX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII1_TX_FRAG_SIZE_MASK, ++ frag_size_tx); ++ } else { ++ mask = GDM4_SGMII0_TX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII0_TX_FRAG_SIZE_MASK, ++ frag_size_tx); ++ } ++ airoha_fe_rmw(eth, REG_FE_GDM4_TMBI_FRAG, mask, val); ++ ++ if (dev->nbq == 1) { ++ mask = GDM4_SGMII1_RX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII1_RX_FRAG_SIZE_MASK, ++ frag_size_rx); ++ } else { ++ mask = GDM4_SGMII0_RX_FRAG_SIZE_MASK; ++ val = FIELD_PREP(GDM4_SGMII0_RX_FRAG_SIZE_MASK, ++ frag_size_rx); ++ } ++ airoha_fe_rmw(eth, REG_FE_GDM4_RMBI_FRAG, mask, val); ++ ++ spin_unlock(&port->lock); ++} ++ ++/* Nothing to do in MAC, everything is handled in PCS */ ++static void airoha_mac_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++} ++ ++static const struct phylink_mac_ops airoha_phylink_ops = { ++ .mac_config = airoha_mac_config, ++ .mac_link_up = airoha_mac_link_up, ++ .mac_link_down = airoha_mac_link_down, ++}; ++ ++static int airoha_fill_available_pcs(struct phylink_config *config, ++ struct phylink_pcs **available_pcs, ++ unsigned int num_possible_pcs) ++{ ++ struct device *dev = config->dev; ++ ++ return fwnode_phylink_pcs_parse(dev_fwnode(dev), available_pcs, ++ &num_possible_pcs); ++} ++ ++static int airoha_setup_phylink(struct net_device *netdev) ++{ ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct device_node *np = netdev->dev.of_node; ++ struct airoha_gdm_port *port = dev->port; ++ struct phylink_config *config; ++ phy_interface_t phy_mode; ++ struct phylink *phylink; ++ int err; ++ ++ err = of_get_phy_mode(np, &phy_mode); ++ if (err) { ++ dev_err(&netdev->dev, "incorrect phy-mode\n"); ++ return err; ++ } ++ ++ config = &dev->phylink_config; ++ config->dev = &netdev->dev; ++ config->type = PHYLINK_NETDEV; ++ ++ /* ++ * GDM1 only supports internal for Embedded Switch ++ * and doesn't require a PCS. ++ */ ++ if (port->id == AIROHA_GDM1_IDX) { ++ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10000FD; ++ ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ config->supported_interfaces); ++ } else { ++ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10 | MAC_100 | MAC_1000 | ++ MAC_2500FD | MAC_5000FD | MAC_10000FD; ++ ++ err = fwnode_phylink_pcs_parse(dev_fwnode(config->dev), NULL, ++ &dev->phylink_config.num_available_pcs); ++ if (err) ++ return err; ++ ++ config->fill_available_pcs = airoha_fill_available_pcs; ++ ++ __set_bit(PHY_INTERFACE_MODE_SGMII, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, ++ config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_USXGMII, ++ config->supported_interfaces); ++ ++ phy_interface_copy(config->pcs_interfaces, ++ config->supported_interfaces); ++ } ++ ++ phylink = phylink_create(config, of_fwnode_handle(np), ++ phy_mode, &airoha_phylink_ops); ++ if (IS_ERR(phylink)) ++ return PTR_ERR(phylink); ++ ++ dev->phylink = phylink; ++ ++ return 0; ++} ++ + static int airoha_alloc_gdm_device(struct airoha_eth *eth, + struct airoha_gdm_port *port, + int nbq, struct device_node *np) +@@ -3238,7 +3422,7 @@ static int airoha_alloc_gdm_device(struc + dev->nbq = nbq; + port->devs[index] = dev; + +- return 0; ++ return airoha_setup_phylink(netdev); + } + + static int airoha_alloc_gdm_port(struct airoha_eth *eth, +@@ -3273,7 +3457,7 @@ static int airoha_alloc_gdm_port(struct + return -ENOMEM; + + port->id = id; +- spin_lock_init(&port->stats_lock); ++ spin_lock_init(&port->lock); + eth->ports[p] = port; + + err = airoha_metadata_dst_alloc(port); +@@ -3464,6 +3648,8 @@ error_napi_stop: + netdev = netdev_from_priv(dev); + if (netdev->reg_state == NETREG_REGISTERED) + unregister_netdev(netdev); ++ if (dev->phylink) ++ phylink_destroy(dev->phylink); + of_node_put(netdev->dev.of_node); + } + airoha_metadata_dst_free(port); +@@ -3500,6 +3686,7 @@ static void airoha_remove(struct platfor + + netdev = netdev_from_priv(dev); + unregister_netdev(netdev); ++ phylink_destroy(dev->phylink); + of_node_put(netdev->dev.of_node); + } + airoha_metadata_dst_free(port); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -554,6 +554,9 @@ struct airoha_gdm_dev { + int nbq; + + struct airoha_hw_stats stats; ++ ++ struct phylink *phylink; ++ struct phylink_config phylink_config; + }; + + struct airoha_gdm_port { +@@ -561,8 +564,8 @@ struct airoha_gdm_port { + int id; + int users; + +- /* protect concurrent hw_stats accesses */ +- spinlock_t stats_lock; ++ /* protect concurrent hw_stats and frag register accesses */ ++ spinlock_t lock; + + struct metadata_dst *dsa_meta[AIROHA_MAX_DSA_PORTS]; + }; +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -358,6 +358,18 @@ + #define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) + #define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) + ++#define REG_FE_GDM4_TMBI_FRAG 0x2028 ++#define GDM4_SGMII1_TX_WEIGHT_MASK GENMASK(31, 26) ++#define GDM4_SGMII1_TX_FRAG_SIZE_MASK GENMASK(25, 16) ++#define GDM4_SGMII0_TX_WEIGHT_MASK GENMASK(15, 10) ++#define GDM4_SGMII0_TX_FRAG_SIZE_MASK GENMASK(9, 0) ++ ++#define REG_FE_GDM4_RMBI_FRAG 0x202c ++#define GDM4_SGMII1_RX_WEIGHT_MASK GENMASK(31, 26) ++#define GDM4_SGMII1_RX_FRAG_SIZE_MASK GENMASK(25, 16) ++#define GDM4_SGMII0_RX_WEIGHT_MASK GENMASK(15, 10) ++#define GDM4_SGMII0_RX_FRAG_SIZE_MASK GENMASK(9, 0) ++ + #define REG_MC_VLAN_EN 0x2100 + #define MC_VLAN_EN_MASK BIT(0) + diff --git a/target/linux/airoha/patches-6.18/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch b/target/linux/airoha/patches-6.18/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch deleted file mode 100644 index b78cc3455f..0000000000 --- a/target/linux/airoha/patches-6.18/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 6548e580509397a622b7c504a79de93414771459 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 25 Jun 2025 00:04:36 +0200 -Subject: [PATCH 6/6] net: ethernet: airoha: define sport value for GDM3 - -On Airoha AN7583, the Serdes Ethernet goes through the GDM3 port. -To correctly receive packet for QDMA, add the sport value to identify -packet from GDM3 port. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -585,6 +585,9 @@ static int airoha_qdma_get_gdm_port(stru - case 0x18: - port = 3; /* GDM4 */ - break; -+ case 0x16: -+ port = 2; /* GDM3 */ -+ break; - case 0x10 ... 0x14: - port = 0; /* GDM1 */ - break; diff --git a/target/linux/airoha/patches-6.18/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch b/target/linux/airoha/patches-6.18/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch deleted file mode 100644 index d43d3303a0..0000000000 --- a/target/linux/airoha/patches-6.18/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 843e2892f2d9353bf039e0dfb5442a600e75009e Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Thu, 9 Oct 2025 23:46:08 +0300 -Subject: [PATCH] net: airoha: disable external phy code if PCS_AIROHA is not - enabled - -External phy code breaks building for EN7523, so disable it if -PCS_AIROHA is not selected. - -Signed-off-by: Mikhail Kshevetskiy ---- - drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++++++++ - drivers/net/ethernet/airoha/airoha_eth.h | 2 ++ - 2 files changed, 18 insertions(+) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -72,10 +72,12 @@ static void airoha_qdma_irq_disable(stru - airoha_qdma_set_irqmask(irq_bank, index, mask, 0); - } - -+#if defined(CONFIG_PCS_AIROHA) - static bool airhoa_is_phy_external(struct airoha_gdm_port *port) - { - return port->id != 1; - } -+#endif - - static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) - { -@@ -1725,6 +1727,7 @@ static int airoha_dev_open(struct net_de - struct airoha_qdma *qdma = port->qdma; - u32 pse_port = FE_PSE_PORT_PPE1; - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); - if (err) { -@@ -1735,6 +1738,7 @@ static int airoha_dev_open(struct net_de - - phylink_start(port->phylink); - } -+#endif - - netif_tx_start_all_queues(dev); - err = airoha_set_vip_for_gdm_port(port, true); -@@ -1797,10 +1801,12 @@ static int airoha_dev_stop(struct net_de - } - } - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - phylink_stop(port->phylink); - phylink_disconnect_phy(port->phylink); - } -+#endif - - return 0; - } -@@ -2990,6 +2996,7 @@ bool airoha_is_valid_gdm_port(struct air - return false; - } - -+#if defined(CONFIG_PCS_AIROHA) - static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, - unsigned int mode, phy_interface_t interface, - int speed, int duplex, bool tx_pause, bool rx_pause) -@@ -3102,6 +3109,7 @@ static int airoha_setup_phylink(struct n - - return err; - } -+#endif - - static int airoha_alloc_gdm_port(struct airoha_eth *eth, - struct device_node *np) -@@ -3176,11 +3184,13 @@ static int airoha_alloc_gdm_port(struct - port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; - eth->ports[p] = port; - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - err = airoha_setup_phylink(dev); - if (err) - return err; - } -+#endif - - return airoha_metadata_dst_alloc(port); - } -@@ -3310,8 +3320,10 @@ error_napi_stop: - continue; - - if (port->dev->reg_state == NETREG_REGISTERED) { -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) - phylink_destroy(port->phylink); -+#endif - unregister_netdev(port->dev); - } - airoha_metadata_dst_free(port); -@@ -3338,8 +3350,10 @@ static void airoha_remove(struct platfor - if (!port) - continue; - -+#if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) - phylink_destroy(port->phylink); -+#endif - unregister_netdev(port->dev); - airoha_metadata_dst_free(port); - } ---- a/drivers/net/ethernet/airoha/airoha_eth.h -+++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -542,8 +542,10 @@ struct airoha_gdm_port { - int id; - int nbq; - -+#if defined(CONFIG_PCS_AIROHA) - struct phylink *phylink; - struct phylink_config phylink_config; -+#endif - - struct airoha_hw_stats stats; - diff --git a/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch b/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch index 6acc99da3e..7670611c01 100644 --- a/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch +++ b/target/linux/airoha/patches-6.18/915-02-net-airoha-Set-hw-QoS-parameter-according-to-the-pac.patch @@ -25,25 +25,25 @@ Signed-off-by: Lorenzo Bianconi #include "airoha_regs.h" #include "airoha_eth.h" -@@ -300,7 +301,7 @@ static int airoha_ppe_foe_entry_prepare( +@@ -314,7 +315,7 @@ static int airoha_ppe_foe_entry_prepare( struct airoha_foe_entry *hwe, - struct net_device *dev, int type, + struct net_device *netdev, int type, struct airoha_flow_data *data, - int l4proto) + int l4proto, u8 dsfield) { u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val; - int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev); -@@ -333,7 +334,7 @@ static int airoha_ppe_foe_entry_prepare( - info.wcid); + int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&netdev); +@@ -349,7 +350,7 @@ static int airoha_ppe_foe_entry_prepare( } else { - struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port; - u8 pse_port, channel; + u8 pse_port, channel, priority; - if (!airoha_is_valid_gdm_port(eth, port)) + if (!airoha_is_valid_gdm_dev(eth, dev)) return -EINVAL; -@@ -352,9 +353,13 @@ static int airoha_ppe_foe_entry_prepare( +@@ -369,9 +370,13 @@ static int airoha_ppe_foe_entry_prepare( */ channel = dsa_port >= 0 ? dsa_port : port->id; channel = channel % AIROHA_NUM_QOS_CHANNELS; @@ -58,7 +58,7 @@ Signed-off-by: Lorenzo Bianconi AIROHA_FOE_IB2_PSE_QOS; /* For downlink traffic consume SRAM memory for hw * forwarding descriptors queue. -@@ -1046,9 +1051,9 @@ static int airoha_ppe_flow_offload_repla +@@ -1063,9 +1068,9 @@ static int airoha_ppe_flow_offload_repla struct net_device *odev = NULL; struct flow_action_entry *act; struct airoha_foe_entry hwe; @@ -69,7 +69,7 @@ Signed-off-by: Lorenzo Bianconi if (rhashtable_lookup(ð->flow_table, &f->cookie, airoha_flow_table_params)) -@@ -1078,6 +1083,13 @@ static int airoha_ppe_flow_offload_repla +@@ -1095,6 +1100,13 @@ static int airoha_ppe_flow_offload_repla return -EOPNOTSUPP; } @@ -83,7 +83,7 @@ Signed-off-by: Lorenzo Bianconi switch (addr_type) { case 0: offload_type = PPE_PKT_TYPE_BRIDGE; -@@ -1143,7 +1155,7 @@ static int airoha_ppe_flow_offload_repla +@@ -1160,7 +1172,7 @@ static int airoha_ppe_flow_offload_repla return -EINVAL; err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type, diff --git a/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch b/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch index 7598a22199..16513e3c25 100644 --- a/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch +++ b/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch @@ -24,7 +24,7 @@ Signed-off-by: Lorenzo Bianconi #include #include "airoha_regs.h" -@@ -439,6 +441,73 @@ static void airoha_fe_crsn_qsel_init(str +@@ -487,6 +489,73 @@ static void airoha_fe_crsn_qsel_init(str CDM_CRSN_QSEL_Q1)); } @@ -70,9 +70,9 @@ Signed-off-by: Lorenzo Bianconi + LRO_RXQ_EN_MASK); +} + -+static void airoha_dev_lro_enable(struct airoha_gdm_port *port) ++static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) +{ -+ struct airoha_qdma *qdma = port->qdma; ++ struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; + int i, lro_queue_index = 0; @@ -98,7 +98,7 @@ Signed-off-by: Lorenzo Bianconi static int airoha_fe_init(struct airoha_eth *eth) { airoha_fe_maccr_init(eth); -@@ -558,6 +627,7 @@ static int airoha_qdma_fill_rx_queue(str +@@ -614,6 +683,7 @@ static int airoha_qdma_fill_rx_queue(str e->dma_addr = page_pool_get_dma_addr(page) + offset; e->dma_len = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size)); @@ -106,8 +106,8 @@ Signed-off-by: Lorenzo Bianconi val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len); WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); WRITE_ONCE(desc->addr, cpu_to_le32(e->dma_addr)); -@@ -603,12 +673,169 @@ static int airoha_qdma_get_gdm_port(stru - return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; +@@ -655,12 +725,169 @@ airoha_qdma_get_gdm_dev(struct airoha_et + return port->devs[d] ? port->devs[d] : ERR_PTR(-ENODEV); } +static struct sk_buff *airoha_qdma_lro_rx_skb(struct airoha_queue *q, @@ -279,27 +279,27 @@ Signed-off-by: Lorenzo Bianconi int done = 0; while (done < budget) { -@@ -643,18 +870,9 @@ static int airoha_qdma_rx_process(struct +@@ -696,18 +923,9 @@ static int airoha_qdma_rx_process(struct - port = eth->ports[p]; + netdev = netdev_from_priv(dev); if (!q->skb) { /* first buffer */ - q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM, - q->buf_size); -+ q->skb = airoha_qdma_build_rx_skb(q, desc, e, port->dev); ++ q->skb = airoha_qdma_build_rx_skb(q, desc, e, netdev); if (!q->skb) goto free_frag; - - skb_reserve(q->skb, AIROHA_RX_HEADROOM); - __skb_put(q->skb, len); - skb_mark_for_recycle(q->skb); -- q->skb->dev = port->dev; -- q->skb->protocol = eth_type_trans(q->skb, port->dev); +- q->skb->dev = netdev; +- q->skb->protocol = eth_type_trans(q->skb, netdev); - q->skb->ip_summed = CHECKSUM_UNNECESSARY; - skb_record_rx_queue(q->skb, qid); } else { /* scattered frame */ struct skb_shared_info *shinfo = skb_shinfo(q->skb); int nr_frags = shinfo->nr_frags; -@@ -743,12 +961,10 @@ static int airoha_qdma_rx_napi_poll(stru +@@ -798,12 +1016,10 @@ static int airoha_qdma_rx_napi_poll(stru static int airoha_qdma_init_rx_queue(struct airoha_queue *q, struct airoha_qdma *qdma, int ndesc) { @@ -313,7 +313,7 @@ Signed-off-by: Lorenzo Bianconi .nid = NUMA_NO_NODE, .dev = qdma->eth->dev, .napi = &q->napi, -@@ -756,9 +972,10 @@ static int airoha_qdma_init_rx_queue(str +@@ -811,9 +1027,10 @@ static int airoha_qdma_init_rx_queue(str struct airoha_eth *eth = qdma->eth; int qid = q - &qdma->q_rx[0], thr; dma_addr_t dma_addr; @@ -325,7 +325,7 @@ Signed-off-by: Lorenzo Bianconi q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry), GFP_KERNEL); -@@ -770,6 +987,9 @@ static int airoha_qdma_init_rx_queue(str +@@ -825,6 +1042,9 @@ static int airoha_qdma_init_rx_queue(str if (!q->desc) return -ENOMEM; @@ -335,7 +335,7 @@ Signed-off-by: Lorenzo Bianconi q->page_pool = page_pool_create(&pp_params); if (IS_ERR(q->page_pool)) { int err = PTR_ERR(q->page_pool); -@@ -778,6 +998,7 @@ static int airoha_qdma_init_rx_queue(str +@@ -833,6 +1053,7 @@ static int airoha_qdma_init_rx_queue(str return err; } @@ -343,7 +343,7 @@ Signed-off-by: Lorenzo Bianconi q->ndesc = ndesc; netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); -@@ -791,7 +1012,12 @@ static int airoha_qdma_init_rx_queue(str +@@ -846,7 +1067,12 @@ static int airoha_qdma_init_rx_queue(str FIELD_PREP(RX_RING_THR_MASK, thr)); airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK, FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head)); @@ -357,7 +357,7 @@ Signed-off-by: Lorenzo Bianconi airoha_qdma_fill_rx_queue(q); -@@ -813,6 +1039,7 @@ static void airoha_qdma_cleanup_rx_queue +@@ -868,6 +1094,7 @@ static void airoha_qdma_cleanup_rx_queue page_pool_get_dma_dir(q->page_pool)); page_pool_put_full_page(q->page_pool, page, false); /* Reset DMA descriptor */ @@ -365,56 +365,67 @@ Signed-off-by: Lorenzo Bianconi WRITE_ONCE(desc->ctrl, 0); WRITE_ONCE(desc->addr, 0); WRITE_ONCE(desc->data, 0); -@@ -1720,13 +1947,45 @@ static void airoha_update_hw_stats(struc - spin_unlock(&port->stats.lock); +@@ -1809,6 +2036,37 @@ static void airoha_update_hw_stats(struc + spin_unlock(&port->lock); } -+static void airoha_update_netdev_features(struct airoha_gdm_port *port) ++static void airoha_update_netdev_features(struct airoha_gdm_dev *dev) +{ -+ struct airoha_eth *eth = port->eth; ++ struct airoha_eth *eth = dev->eth; + int i; + + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { -+ struct airoha_gdm_port *p = eth->ports[i]; -+ struct net_device *netdev; ++ struct airoha_gdm_port *port = dev->port; ++ int j; + -+ if (!p) ++ if (!port) + continue; + -+ netdev = p->dev; -+ if (netdev->reg_state != NETREG_REGISTERED) -+ continue; ++ for (j = 0; j < ARRAY_SIZE(port->devs); j++) { ++ struct airoha_gdm_dev *iter_dev = port->devs[j]; ++ struct net_device *netdev; + -+ netdev_update_features(netdev); ++ if (!iter_dev || iter_dev == dev) ++ continue; ++ ++ if (iter_dev->qdma != dev->qdma) ++ continue; ++ ++ netdev = netdev_from_priv(iter_dev); ++ if (netdev->reg_state != NETREG_REGISTERED) ++ continue; ++ ++ netdev_update_features(netdev); ++ } + } +} + - static int airoha_dev_open(struct net_device *dev) + static int airoha_dev_open(struct net_device *netdev) { - int err, len = ETH_HLEN + dev->mtu + ETH_FCS_LEN; - struct airoha_gdm_port *port = netdev_priv(dev); - struct airoha_qdma *qdma = port->qdma; + int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; +@@ -1816,6 +2074,18 @@ static int airoha_dev_open(struct net_de + struct airoha_gdm_port *port = dev->port; + u32 cur_len, pse_port = FE_PSE_PORT_PPE1; + struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; - u32 pse_port = FE_PSE_PORT_PPE1; - ++ + /* HW LRO is configured on the QDMA and it is shared between + * all the devices using it. Refuse to open a second device on + * the same QDMA if LRO is enabled on any device sharing it. + */ + if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { -+ netdev_warn(dev, "required to disable HW GRO on QDMA%d\n", ++ netdev_warn(netdev, "required to disable HW GRO on QDMA%d\n", + qdma_id); + return -EBUSY; + } -+ - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); -@@ -1747,13 +2006,13 @@ static int airoha_dev_open(struct net_de + + err = phylink_of_phy_connect(dev->phylink, netdev->dev.of_node, 0); + if (err) { +@@ -1832,13 +2102,13 @@ static int airoha_dev_open(struct net_de /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ - if (netdev_uses_dsa(dev) || port->id > 2) + if (netdev_uses_dsa(netdev) || port->id > 2) - airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), + airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); @@ -423,68 +434,77 @@ Signed-off-by: Lorenzo Bianconi + airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); -- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), -+ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), - GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, - FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | - FIELD_PREP(GDM_LONG_LEN_MASK, len)); -@@ -1763,14 +2022,18 @@ static int airoha_dev_open(struct net_de - GLOBAL_CFG_RX_DMA_EN_MASK); +- cur_len = airoha_fe_get(qdma->eth, REG_GDM_LEN_CFG(port->id), ++ cur_len = airoha_fe_get(eth, REG_GDM_LEN_CFG(port->id), + GDM_LONG_LEN_MASK); + if (!port->users || len > cur_len) { + /* Opening a sibling net_device with a larger MTU updates the +@@ -1846,7 +2116,7 @@ static int airoha_dev_open(struct net_de + * multiple net_devices with different MTUs to share the same + * GDM port. + */ +- airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), ++ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), + GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, + FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | + FIELD_PREP(GDM_LONG_LEN_MASK, len)); +@@ -1859,11 +2129,16 @@ static int airoha_dev_open(struct net_de qdma->users++; -- if (port->id == AIROHA_GDM2_IDX && -- airoha_ppe_is_enabled(qdma->eth, 1)) { -+ if (port->id == AIROHA_GDM2_IDX && airoha_ppe_is_enabled(eth, 1)) { - /* For PPE2 always use secondary cpu port. */ + if (!airoha_is_lan_gdm_dev(dev) && +- airoha_ppe_is_enabled(qdma->eth, 1)) ++ airoha_ppe_is_enabled(eth, 1)) pse_port = FE_PSE_PORT_PPE2; - } - airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), pse_port); -+ if (dev->features & NETIF_F_GRO_HW) -+ airoha_dev_lro_enable(port); ++ if (netdev->features & NETIF_F_GRO_HW) ++ airoha_dev_lro_enable(dev); + -+ airoha_update_netdev_features(port); ++ airoha_update_netdev_features(dev); + return 0; } -@@ -1778,6 +2041,7 @@ static int airoha_dev_stop(struct net_de - { - struct airoha_gdm_port *port = netdev_priv(dev); - struct airoha_qdma *qdma = port->qdma; +@@ -1896,6 +2171,7 @@ static int airoha_dev_stop(struct net_de + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_gdm_port *port = dev->port; + struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; int i; - netif_tx_disable(dev); -@@ -1785,7 +2049,7 @@ static int airoha_dev_stop(struct net_de - for (i = 0; i < dev->num_tx_queues; i++) - netdev_tx_reset_subqueue(dev, i); + netif_tx_disable(netdev); +@@ -1904,9 +2180,9 @@ static int airoha_dev_stop(struct net_de + netdev_tx_reset_subqueue(netdev, i); -- airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), -+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), - FE_PSE_PORT_DROP); + if (--port->users) +- airoha_set_port_mtu(dev->eth, port); ++ airoha_set_port_mtu(eth, port); + else +- airoha_set_gdm_port_fwd_cfg(qdma->eth, ++ airoha_set_gdm_port_fwd_cfg(eth, + REG_GDM_FWD_CFG(port->id), + FE_PSE_PORT_DROP); - if (!--qdma->users) { -@@ -1801,6 +2065,8 @@ static int airoha_dev_stop(struct net_de +@@ -1923,6 +2199,8 @@ static int airoha_dev_stop(struct net_de } } -+ airoha_update_netdev_features(port); ++ airoha_update_netdev_features(dev); + - #if defined(CONFIG_PCS_AIROHA) - if (airhoa_is_phy_external(port)) { - phylink_stop(port->phylink); -@@ -2034,6 +2300,38 @@ int airoha_get_fe_port(struct airoha_gdm + phylink_stop(dev->phylink); + phylink_disconnect_phy(dev->phylink); + +@@ -2195,6 +2473,38 @@ int airoha_get_fe_port(struct airoha_gdm } } -+static netdev_features_t airoha_dev_fix_features(struct net_device *dev, ++static netdev_features_t airoha_dev_fix_features(struct net_device *netdev, + netdev_features_t features) +{ -+ struct airoha_gdm_port *port = netdev_priv(dev); -+ struct airoha_qdma *qdma = port->qdma; ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_qdma *qdma = dev->qdma; + + if (qdma->users > 1) + features &= ~NETIF_F_GRO_HW; @@ -492,12 +512,12 @@ Signed-off-by: Lorenzo Bianconi + return features; +} + -+static int airoha_dev_set_features(struct net_device *dev, ++static int airoha_dev_set_features(struct net_device *netdev, + netdev_features_t features) +{ -+ netdev_features_t diff = dev->features ^ features; -+ struct airoha_gdm_port *port = netdev_priv(dev); -+ struct airoha_qdma *qdma = port->qdma; ++ netdev_features_t diff = netdev->features ^ features; ++ struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ struct airoha_qdma *qdma = dev->qdma; + struct airoha_eth *eth = qdma->eth; + int qdma_id = qdma - ð->qdma[0]; + @@ -505,7 +525,7 @@ Signed-off-by: Lorenzo Bianconi + return 0; + + if (features & NETIF_F_GRO_HW) -+ airoha_dev_lro_enable(port); ++ airoha_dev_lro_enable(dev); + else + airoha_fe_lro_disable(eth, qdma_id); + @@ -513,9 +533,9 @@ Signed-off-by: Lorenzo Bianconi +} + static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, - struct net_device *dev) + struct net_device *netdev) { -@@ -2933,6 +3231,8 @@ static const struct net_device_ops airoh +@@ -3139,6 +3449,8 @@ static const struct net_device_ops airoh .ndo_stop = airoha_dev_stop, .ndo_change_mtu = airoha_dev_change_mtu, .ndo_select_queue = airoha_dev_select_queue, @@ -524,25 +544,24 @@ Signed-off-by: Lorenzo Bianconi .ndo_start_xmit = airoha_dev_xmit, .ndo_get_stats64 = airoha_dev_get_stats64, .ndo_set_mac_address = airoha_dev_set_macaddr, -@@ -3150,12 +3450,9 @@ static int airoha_alloc_gdm_port(struct - dev->ethtool_ops = &airoha_ethtool_ops; - dev->max_mtu = AIROHA_MAX_MTU; - dev->watchdog_timeo = 5 * HZ; -- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | -- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | -- NETIF_F_SG | NETIF_F_TSO | -- NETIF_F_HW_TC; -- dev->features |= dev->hw_features; -- dev->vlan_features = dev->hw_features; -+ dev->hw_features = AIROHA_HW_FEATURES | NETIF_F_GRO_HW; -+ dev->features |= AIROHA_HW_FEATURES; -+ dev->vlan_features = AIROHA_HW_FEATURES; - dev->dev.of_node = np; - SET_NETDEV_DEV(dev, eth->dev); +@@ -3380,11 +3692,9 @@ static int airoha_alloc_gdm_device(struc + netdev->ethtool_ops = &airoha_ethtool_ops; + netdev->max_mtu = AIROHA_MAX_MTU; + netdev->watchdog_timeo = 5 * HZ; +- netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO6 | +- NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO | +- NETIF_F_HW_TC; +- netdev->features |= netdev->hw_features; +- netdev->vlan_features = netdev->hw_features; ++ netdev->hw_features = AIROHA_HW_FEATURES | NETIF_F_LRO; ++ netdev->features |= AIROHA_HW_FEATURES; ++ netdev->vlan_features = AIROHA_HW_FEATURES; + SET_NETDEV_DEV(netdev, eth->dev); + /* reserve hw queues for HTB offloading */ --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -43,6 +43,18 @@ +@@ -44,6 +44,18 @@ (_n) == 15 ? 128 : \ (_n) == 0 ? 1024 : 16) @@ -561,7 +580,7 @@ Signed-off-by: Lorenzo Bianconi #define PSE_RSV_PAGES 128 #define PSE_QUEUE_RSV_PAGES 64 -@@ -666,6 +678,18 @@ static inline bool airoha_is_7583(struct +@@ -676,6 +688,18 @@ static inline bool airoha_is_7583(struct return eth->soc->version == 0x7583; } @@ -577,9 +596,9 @@ Signed-off-by: Lorenzo Bianconi + return !!(AIROHA_RXQ_LRO_EN_MASK & BIT(qid)); +} + - int airoha_get_fe_port(struct airoha_gdm_port *port); - bool airoha_is_valid_gdm_port(struct airoha_eth *eth, - struct airoha_gdm_port *port); + int airoha_get_fe_port(struct airoha_gdm_dev *dev); + bool airoha_is_valid_gdm_dev(struct airoha_eth *eth, + struct airoha_gdm_dev *dev); --- a/drivers/net/ethernet/airoha/airoha_regs.h +++ b/drivers/net/ethernet/airoha/airoha_regs.h @@ -122,6 +122,20 @@ diff --git a/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch b/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch deleted file mode 100644 index 92ce90e7ca..0000000000 --- a/target/linux/airoha/patches-6.18/920-10-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 917f959d54efd09719bd5047aa4b9543615e131e Mon Sep 17 00:00:00 2001 -Message-ID: <917f959d54efd09719bd5047aa4b9543615e131e.1779348625.git.lorenzo@kernel.org> -In-Reply-To: -References: -From: Lorenzo Bianconi -Date: Fri, 19 Dec 2025 23:12:32 +0100 -Subject: [PATCH 10/13] net: airoha: Rename airoha_set_gdm2_loopback in - airoha_enable_gdm2_loopback - -This is a preliminary patch in order to allow the user to select if the -configured device will be used as hw lan or wan. - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2213,7 +2213,7 @@ static int airoha_dev_set_macaddr(struct - return 0; - } - --static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev) -+static int airoha_enable_gdm2_loopback(struct airoha_gdm_dev *dev) - { - struct airoha_gdm_port *port = dev->port; - struct airoha_eth *eth = dev->eth; -@@ -2346,7 +2346,7 @@ static int airoha_dev_init(struct net_de - (port->id == AIROHA_GDM3_IDX || port->id == AIROHA_GDM4_IDX)) { - int err; - -- err = airoha_set_gdm2_loopback(dev); -+ err = airoha_enable_gdm2_loopback(dev); - if (err) - return err; - } diff --git a/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch b/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch index 2c16f2ac02..77b37d5483 100644 --- a/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch +++ b/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch @@ -19,7 +19,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -540,7 +540,7 @@ static bool airoha_fe_lro_is_enabled(str +@@ -533,7 +533,7 @@ static bool airoha_fe_lro_is_enabled(str static void airoha_dev_lro_enable(struct airoha_gdm_dev *dev) { @@ -28,7 +28,7 @@ Signed-off-by: Lorenzo Bianconi struct airoha_eth *eth = qdma->eth; int qdma_id = qdma - ð->qdma[0]; int i, lro_queue_index = 0; -@@ -1158,7 +1158,7 @@ static void airoha_qdma_wake_netdev_txqs +@@ -1159,7 +1159,7 @@ static void airoha_qdma_wake_netdev_txqs if (!dev) continue; @@ -37,7 +37,7 @@ Signed-off-by: Lorenzo Bianconi continue; netdev = netdev_from_priv(dev); -@@ -2031,7 +2031,8 @@ static void airoha_update_netdev_feature +@@ -2055,7 +2055,8 @@ static void airoha_update_netdev_feature if (!iter_dev || iter_dev == dev) continue; @@ -47,7 +47,7 @@ Signed-off-by: Lorenzo Bianconi continue; netdev = netdev_from_priv(iter_dev); -@@ -2043,20 +2044,57 @@ static void airoha_update_netdev_feature +@@ -2067,20 +2068,57 @@ static void airoha_update_netdev_feature } } @@ -108,7 +108,7 @@ Signed-off-by: Lorenzo Bianconi if (qdma->users && airoha_fe_lro_is_enabled(eth, qdma_id)) { netdev_warn(netdev, "required to disable HW GRO on QDMA%d\n", qdma_id); -@@ -2105,10 +2143,7 @@ static int airoha_dev_open(struct net_de +@@ -2123,10 +2161,7 @@ static int airoha_dev_open(struct net_de } port->users++; @@ -119,8 +119,8 @@ Signed-off-by: Lorenzo Bianconi + airoha_qdma_start(qdma); if (!airoha_is_lan_gdm_dev(dev) && - airoha_ppe_is_enabled(eth, 1)) { -@@ -2154,8 +2189,7 @@ static int airoha_dev_stop(struct net_de + airoha_ppe_is_enabled(eth, 1)) +@@ -2170,8 +2205,7 @@ static int airoha_dev_stop(struct net_de { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -130,7 +130,7 @@ Signed-off-by: Lorenzo Bianconi int i; netif_tx_disable(netdev); -@@ -2163,25 +2197,14 @@ static int airoha_dev_stop(struct net_de +@@ -2179,26 +2213,14 @@ static int airoha_dev_stop(struct net_de for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); @@ -139,9 +139,9 @@ Signed-off-by: Lorenzo Bianconi - airoha_set_port_mtu(eth, port); + airoha_set_port_mtu(dev->eth, port); else -- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), +- airoha_set_gdm_port_fwd_cfg(eth, + airoha_set_gdm_port_fwd_cfg(qdma->eth, -+ REG_GDM_FWD_CFG(port->id), + REG_GDM_FWD_CFG(port->id), FE_PSE_PORT_DROP); - - if (!--qdma->users) { @@ -160,8 +160,8 @@ Signed-off-by: Lorenzo Bianconi + airoha_qdma_stop(qdma); airoha_update_netdev_features(dev); - #if defined(CONFIG_PCS_AIROHA) -@@ -2275,6 +2298,53 @@ static int airoha_enable_gdm2_loopback(s + phylink_stop(dev->phylink); +@@ -2288,6 +2310,53 @@ static int airoha_enable_gdm2_loopback(s return 0; } @@ -215,7 +215,7 @@ Signed-off-by: Lorenzo Bianconi static struct airoha_gdm_dev * airoha_get_wan_gdm_dev(struct airoha_eth *eth) { -@@ -2301,15 +2371,30 @@ airoha_get_wan_gdm_dev(struct airoha_eth +@@ -2314,15 +2383,30 @@ airoha_get_wan_gdm_dev(struct airoha_eth static void airoha_dev_set_qdma(struct airoha_gdm_dev *dev) { struct net_device *netdev = netdev_from_priv(dev); @@ -248,7 +248,7 @@ Signed-off-by: Lorenzo Bianconi } static int airoha_dev_init(struct net_device *netdev) -@@ -2473,8 +2558,9 @@ static netdev_features_t airoha_dev_fix_ +@@ -2477,8 +2561,9 @@ static netdev_features_t airoha_dev_fix_ netdev_features_t features) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -259,7 +259,7 @@ Signed-off-by: Lorenzo Bianconi if (qdma->users > 1) features &= ~NETIF_F_GRO_HW; -@@ -2486,9 +2572,8 @@ static int airoha_dev_set_features(struc +@@ -2490,9 +2575,8 @@ static int airoha_dev_set_features(struc { netdev_features_t diff = netdev->features ^ features; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -271,7 +271,7 @@ Signed-off-by: Lorenzo Bianconi if (!(diff & NETIF_F_GRO_HW)) return 0; -@@ -2496,7 +2581,7 @@ static int airoha_dev_set_features(struc +@@ -2500,7 +2584,7 @@ static int airoha_dev_set_features(struc if (features & NETIF_F_GRO_HW) airoha_dev_lro_enable(dev); else @@ -280,7 +280,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -2505,9 +2590,9 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2509,9 +2593,9 @@ static netdev_tx_t airoha_dev_xmit(struc struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -291,7 +291,7 @@ Signed-off-by: Lorenzo Bianconi struct netdev_queue *txq; struct airoha_queue *q; LIST_HEAD(tx_list); -@@ -2516,6 +2601,8 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2520,6 +2604,8 @@ static netdev_tx_t airoha_dev_xmit(struc u16 index; u8 fport; @@ -300,7 +300,7 @@ Signed-off-by: Lorenzo Bianconi qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb)); tag = airoha_get_dsa_tag(skb, netdev); -@@ -2562,6 +2649,8 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2566,6 +2652,8 @@ static netdev_tx_t airoha_dev_xmit(struc netif_tx_stop_queue(txq); q->txq_stopped = true; spin_unlock_bh(&q->lock); @@ -309,7 +309,7 @@ Signed-off-by: Lorenzo Bianconi return NETDEV_TX_BUSY; } -@@ -2624,6 +2713,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2628,6 +2716,7 @@ static netdev_tx_t airoha_dev_xmit(struc FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); spin_unlock_bh(&q->lock); @@ -317,7 +317,7 @@ Signed-off-by: Lorenzo Bianconi return NETDEV_TX_OK; -@@ -2639,6 +2729,7 @@ error_unmap: +@@ -2643,6 +2732,7 @@ error_unmap: error: dev_kfree_skb_any(skb); netdev->stats.tx_dropped++; @@ -325,7 +325,7 @@ Signed-off-by: Lorenzo Bianconi return NETDEV_TX_OK; } -@@ -2720,17 +2811,19 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2740,17 +2830,19 @@ static int airoha_qdma_set_chan_tx_sched const u16 *weights, u8 n_weights) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -347,7 +347,7 @@ Signed-off-by: Lorenzo Bianconi TWRR_RW_CMD_MASK | FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | -@@ -2738,12 +2831,12 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2758,12 +2850,12 @@ static int airoha_qdma_set_chan_tx_sched err = read_poll_timeout(airoha_qdma_rr, status, status & TWRR_RW_CMD_DONE, USEC_PER_MSEC, 10 * USEC_PER_MSEC, @@ -362,7 +362,7 @@ Signed-off-by: Lorenzo Bianconi CHAN_QOS_MODE_MASK(channel), __field_prep(CHAN_QOS_MODE_MASK(channel), mode)); -@@ -2807,13 +2900,15 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2827,13 +2919,15 @@ static int airoha_qdma_get_tx_ets_stats( struct tc_ets_qopt_offload *opt) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -384,7 +384,7 @@ Signed-off-by: Lorenzo Bianconi _bstats_update(opt->stats.bstats, 0, tx_packets); dev->cpu_tx_packets = cpu_tx_packets; -@@ -3073,16 +3168,18 @@ static int airoha_qdma_set_tx_rate_limit +@@ -3093,16 +3187,18 @@ static int airoha_qdma_set_tx_rate_limit u32 bucket_size) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -405,7 +405,7 @@ Signed-off-by: Lorenzo Bianconi REG_EGRESS_TRTCM_CFG, i, rate, bucket_size); if (err) -@@ -3118,11 +3215,12 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -3138,11 +3234,12 @@ static int airoha_tc_htb_alloc_leaf_queu u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; int err, num_tx_queues = netdev->real_num_tx_queues; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -419,7 +419,7 @@ Signed-off-by: Lorenzo Bianconi if (test_and_set_bit(channel, qdma->qos_channel_map)) { NL_SET_ERR_MSG_MOD(opt->extack, "qdma qos channel already in use"); -@@ -3156,7 +3254,7 @@ static int airoha_qdma_set_rx_meter(stru +@@ -3176,7 +3273,7 @@ static int airoha_qdma_set_rx_meter(stru u32 rate, u32 bucket_size, enum trtcm_unit_type unit_type) { @@ -428,7 +428,7 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { -@@ -3330,11 +3428,12 @@ static int airoha_dev_setup_tc_block(str +@@ -3350,11 +3447,12 @@ static int airoha_dev_setup_tc_block(str static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -442,7 +442,7 @@ Signed-off-by: Lorenzo Bianconi clear_bit(queue, qdma->qos_channel_map); clear_bit(queue, dev->qos_sq_bmap); } -@@ -3355,6 +3454,95 @@ static int airoha_tc_htb_delete_leaf_que +@@ -3375,6 +3473,95 @@ static int airoha_tc_htb_delete_leaf_que return 0; } @@ -538,7 +538,7 @@ Signed-off-by: Lorenzo Bianconi static int airoha_tc_htb_destroy(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -3363,6 +3551,8 @@ static int airoha_tc_htb_destroy(struct +@@ -3383,6 +3570,8 @@ static int airoha_tc_htb_destroy(struct for_each_set_bit(q, dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS) airoha_tc_remove_htb_queue(netdev, q); @@ -547,7 +547,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -3382,24 +3572,33 @@ static int airoha_tc_get_htb_get_leaf_qu +@@ -3402,24 +3591,33 @@ static int airoha_tc_get_htb_get_leaf_qu return 0; } @@ -588,16 +588,6 @@ Signed-off-by: Lorenzo Bianconi default: return -EOPNOTSUPP; } -@@ -3509,8 +3708,8 @@ static void airoha_mac_link_up(struct ph - { - struct airoha_gdm_dev *dev = container_of(config, struct airoha_gdm_dev, - phylink_config); -+ struct airoha_qdma *qdma = airoha_qdma_deref(dev); - struct airoha_gdm_port *port = dev->port; -- struct airoha_qdma *qdma = dev->qdma; - struct airoha_eth *eth = qdma->eth; - u32 frag_size_tx, frag_size_rx; - --- a/drivers/net/ethernet/airoha/airoha_regs.h +++ b/drivers/net/ethernet/airoha/airoha_regs.h @@ -402,6 +402,7 @@ @@ -610,7 +600,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h -@@ -552,11 +552,12 @@ struct airoha_qdma { +@@ -550,11 +550,12 @@ struct airoha_qdma { enum airoha_priv_flags { AIROHA_PRIV_F_WAN = BIT(0), @@ -623,8 +613,8 @@ Signed-off-by: Lorenzo Bianconi - struct airoha_qdma *qdma; struct airoha_eth *eth; - #if defined(CONFIG_PCS_AIROHA) -@@ -705,6 +706,16 @@ int airoha_get_fe_port(struct airoha_gdm + DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); +@@ -704,6 +705,16 @@ int airoha_get_fe_port(struct airoha_gdm bool airoha_is_valid_gdm_dev(struct airoha_eth *eth, struct airoha_gdm_dev *dev); diff --git a/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch b/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch index d17c537daa..2e854b6f49 100644 --- a/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch +++ b/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch @@ -16,7 +16,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -188,10 +188,15 @@ static void airoha_fe_maccr_init(struct +@@ -181,10 +181,15 @@ static void airoha_fe_maccr_init(struct { int p; @@ -33,7 +33,7 @@ Signed-off-by: Lorenzo Bianconi airoha_fe_rmw(eth, REG_CDM_VLAN_CTRL(1), CDM_VLAN_MASK, FIELD_PREP(CDM_VLAN_MASK, 0x8100)); -@@ -2078,15 +2083,25 @@ static void airoha_qdma_stop(struct airo +@@ -2102,15 +2107,25 @@ static void airoha_qdma_stop(struct airo } } @@ -62,7 +62,7 @@ Signed-off-by: Lorenzo Bianconi /* HW LRO is configured on the QDMA and it is shared between * all the devices using it. Refuse to open a second device on -@@ -2128,19 +2143,7 @@ static int airoha_dev_open(struct net_de +@@ -2146,19 +2161,7 @@ static int airoha_dev_open(struct net_de airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); @@ -83,7 +83,7 @@ Signed-off-by: Lorenzo Bianconi port->users++; airoha_qdma_start(qdma); -@@ -2161,30 +2164,6 @@ static int airoha_dev_open(struct net_de +@@ -2177,30 +2180,6 @@ static int airoha_dev_open(struct net_de return 0; } @@ -114,7 +114,7 @@ Signed-off-by: Lorenzo Bianconi static int airoha_dev_stop(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -2199,7 +2178,7 @@ static int airoha_dev_stop(struct net_de +@@ -2215,7 +2194,7 @@ static int airoha_dev_stop(struct net_de qdma = airoha_qdma_deref(dev); if (--port->users) @@ -123,7 +123,7 @@ Signed-off-by: Lorenzo Bianconi else airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), -@@ -2258,10 +2237,6 @@ static int airoha_enable_gdm2_loopback(s +@@ -2274,10 +2253,6 @@ static int airoha_enable_gdm2_loopback(s FIELD_PREP(LPBK_CHAN_MASK, chan) | LBK_GAP_MODE_MASK | LBK_LEN_MODE_MASK | LBK_CHAN_MODE_MASK | LPBK_EN_MASK); @@ -134,7 +134,7 @@ Signed-off-by: Lorenzo Bianconi /* Forward the traffic to the proper GDM port */ pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3 : FE_PSE_PORT_GDM4; -@@ -2469,7 +2444,7 @@ static int airoha_dev_change_mtu(struct +@@ -2472,7 +2447,7 @@ static int airoha_dev_change_mtu(struct WRITE_ONCE(netdev->mtu, mtu); if (port->users) @@ -143,7 +143,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -3471,6 +3446,7 @@ static void airoha_disable_qos_for_gdm34 +@@ -3490,6 +3465,7 @@ static void airoha_disable_qos_for_gdm34 dev->flags &= ~AIROHA_PRIV_F_WAN; airoha_dev_set_qdma(dev); @@ -151,7 +151,7 @@ Signed-off-by: Lorenzo Bianconi airoha_set_macaddr(dev, netdev->dev_addr); if (netif_running(netdev)) -@@ -3519,6 +3495,7 @@ static int airoha_enable_qos_for_gdm34(s +@@ -3538,6 +3514,7 @@ static int airoha_enable_qos_for_gdm34(s if (err) goto error_disable_loopback; @@ -169,7 +169,7 @@ Signed-off-by: Lorenzo Bianconi #define AIROHA_MAX_PACKET_SIZE 2048 #define AIROHA_NUM_QOS_CHANNELS 4 #define AIROHA_NUM_QOS_QUEUES 8 -@@ -716,6 +717,7 @@ airoha_qdma_deref(struct airoha_gdm_dev +@@ -715,6 +716,7 @@ airoha_qdma_deref(struct airoha_gdm_dev lockdep_is_held(&flow_offload_mutex)); } diff --git a/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch b/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch index 2df1996d19..a0a1ed0135 100644 --- a/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch +++ b/target/linux/airoha/patches-6.18/920-15-net-airoha-fix-wrong-airoha_get_fe_port.patch @@ -18,7 +18,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2543,17 +2543,9 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -2519,17 +2519,9 @@ static u32 airoha_get_dsa_tag(struct sk_ int airoha_get_fe_port(struct airoha_gdm_dev *dev) { struct airoha_gdm_port *port = dev->port; diff --git a/target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch b/target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch deleted file mode 100644 index 9cd99c759d..0000000000 --- a/target/linux/airoha/patches-6.18/921-net-airoha-move-get_sport-callback-at-the-beginning-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 18aa76cd820c412358dc36d115b8e02d24a78f39 Mon Sep 17 00:00:00 2001 -Message-ID: <18aa76cd820c412358dc36d115b8e02d24a78f39.1780942778.git.lorenzo@kernel.org> -From: Lorenzo Bianconi -Date: Mon, 8 Jun 2026 20:10:35 +0200 -Subject: [PATCH] net: airoha: move get_sport() callback at the beginning of - airoha_enable_gdm2_loopback() - -Signed-off-by: Lorenzo Bianconi ---- - drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2250,6 +2250,10 @@ static int airoha_enable_gdm2_loopback(s - u32 val, pse_port, chan; - int i, src_port; - -+ src_port = eth->soc->ops.get_sport(port, dev->nbq); -+ if (src_port < 0) -+ return src_port; -+ - airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), - FE_PSE_PORT_DROP); - airoha_fe_clear(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), -@@ -2275,10 +2279,6 @@ static int airoha_enable_gdm2_loopback(s - airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); - airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); - -- src_port = eth->soc->ops.get_sport(port, dev->nbq); -- if (src_port < 0) -- return src_port; -- - airoha_fe_rmw(eth, REG_FE_WAN_PORT, - WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, - FIELD_PREP(WAN0_MASK, src_port)); From 0d7add7433c5327cc4fe9d04d46189e8d2b55e7e Mon Sep 17 00:00:00 2001 From: Wayen Yan Date: Fri, 19 Jun 2026 16:03:52 +0800 Subject: [PATCH 081/228] net: pcs: airoha: fix swapped JCPLL SDM DI_LS/DI_EN REG_FIELD entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The JCPLL SDM DI_LS and DI_EN REG_FIELD entries have their bit positions swapped compared to the #define macros: #define JCPLL_SDM_DI_LS GENMASK(25,24) → bits 24-25 #define JCPLL_SDM_DI_EN BIT(16) → bit 16 But the REG_FIELD mapping is: DI_LS → REG_FIELD(..., 16, 16) ← wrong, should be (24, 25) DI_EN → REG_FIELD(..., 24, 25) ← wrong, should be (16, 16) Fix by swapping the enum and REG_FIELD order so DI_EN comes before DI_LS, keeping the bit values in ascending order and matching the register layout. This way: [DI_EN] = REG_FIELD(..., 16, 16) ← BIT(16) ✓ [DI_LS] = REG_FIELD(..., 24, 25) ← GENMASK(25,24) ✓ The TXPLL section in the same file already follows this bit-order convention (DI_EN at bit 0, DI_LS at bits 8-9). Signed-off-by: Wayen Yan Link: https://github.com/openwrt/openwrt/pull/23876 Signed-off-by: Christian Marangi --- ...roha-add-PCS-driver-for-Airoha-AN7581-SoC.patch | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/target/linux/airoha/patches-6.18/310-09-net-pcs-airoha-add-PCS-driver-for-Airoha-AN7581-SoC.patch b/target/linux/airoha/patches-6.18/310-09-net-pcs-airoha-add-PCS-driver-for-Airoha-AN7581-SoC.patch index 7c6c687b30..3bd81271c0 100644 --- a/target/linux/airoha/patches-6.18/310-09-net-pcs-airoha-add-PCS-driver-for-Airoha-AN7581-SoC.patch +++ b/target/linux/airoha/patches-6.18/310-09-net-pcs-airoha-add-PCS-driver-for-Airoha-AN7581-SoC.patch @@ -2717,8 +2717,8 @@ Signed-off-by: Christian Marangi + AN7581_PCS_JCPLL_SPARE_L, + AN7581_PCS_JCPLL_RST_DLY, + AN7581_PCS_JCPLL_PLL_RSTB, -+ AN7581_PCS_JCPLL_SDM_DI_LS, + AN7581_PCS_JCPLL_SDM_DI_EN, ++ AN7581_PCS_JCPLL_SDM_DI_LS, + + AN7581_PCS_JCPLL_SDM_OUT, + AN7581_PCS_JCPLL_SDM_ORD, @@ -2879,8 +2879,8 @@ Signed-off-by: Christian Marangi + + [AN7581_PCS_JCPLL_RST_DLY] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 0, 2), + [AN7581_PCS_JCPLL_PLL_RSTB] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 8, 8), -+ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 16, 16), -+ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 24, 25), ++ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 16, 16), ++ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, 24, 25), + + [AN7581_PCS_JCPLL_SDM_OUT] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_SDM_IFM, 24, 24), + [AN7581_PCS_JCPLL_SDM_ORD] = REG_FIELD(AIROHA_PCS_ANA_PXP_JCPLL_SDM_IFM, 16, 17), @@ -3045,8 +3045,8 @@ Signed-off-by: Christian Marangi + + [AN7581_PCS_JCPLL_RST_DLY] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 0, 2), + [AN7581_PCS_JCPLL_PLL_RSTB] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 8, 8), -+ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 16, 16), -+ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 24, 25), ++ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 16, 16), ++ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 24, 25), + + [AN7581_PCS_JCPLL_SDM_OUT] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_SDM_IFM, 24, 24), + [AN7581_PCS_JCPLL_SDM_ORD] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_SDM_IFM, 16, 17), @@ -3211,8 +3211,8 @@ Signed-off-by: Christian Marangi + + [AN7581_PCS_JCPLL_RST_DLY] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 0, 2), + [AN7581_PCS_JCPLL_PLL_RSTB] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 8, 8), -+ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 16, 16), -+ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 24, 25), ++ [AN7581_PCS_JCPLL_SDM_DI_EN] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 16, 16), ++ [AN7581_PCS_JCPLL_SDM_DI_LS] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_RST_DLY, 24, 25), + + [AN7581_PCS_JCPLL_SDM_OUT] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_SDM_IFM, 24, 24), + [AN7581_PCS_JCPLL_SDM_ORD] = REG_FIELD(AIROHA_PCS_ANA_PXP_2L_JCPLL_SDM_IFM, 16, 17), From bef32df164b78d55b7c93ea1c3801212f53b38c4 Mon Sep 17 00:00:00 2001 From: Lars Gierth Date: Fri, 29 May 2026 01:33:24 +0200 Subject: [PATCH 082/228] realtek: uci-defaults: refactor and expand fwenv ethaddr hack With the upcoming addition of the Hasivo F5800W-12S+ switch model, another invariant of the u-boot env ethaddr fixup will be neccessary. While previously all devices used the exact "zero" dummy ethaddr, this new Hasivo ends in :10 instead of :00. Make the hack work based on the 5-byte prefix of the ethaddr. The currently known possible values for the 6th byte are 0x00 and 0x10. This can be further expanded in the future if neccessary. The separate XGS1010-12-A1 case doesn't need to deal with ethaddr prefixes as it only covers one single device with one single dummy ethaddr. Also use this opportunity to add more documentation, and extract the common json and fw_setenv logic to a separate function. Signed-off-by: Lars Gierth Link: https://github.com/openwrt/openwrt/pull/23443 Signed-off-by: Markus Stockhausen --- .../realtek/base-files/etc/board.d/02_network | 3 +- .../etc/uci-defaults/99_fwenv-store-ethaddr | 59 ++++++++++--------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/target/linux/realtek/base-files/etc/board.d/02_network b/target/linux/realtek/base-files/etc/board.d/02_network index cdd5ded1da..eed572aaf3 100644 --- a/target/linux/realtek/base-files/etc/board.d/02_network +++ b/target/linux/realtek/base-files/etc/board.d/02_network @@ -103,7 +103,8 @@ realtek_setup_macs() tplink,tl-st1008f-v2|\ zyxel,xgs1010-12-a1) lan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) - [ -z "$lan_mac" ] || [ "$lan_mac" = "00:e0:4c:00:00:00" ] && lan_mac=$(macaddr_random) + mac_prefix=$(echo "$lan_mac" | cut -d: -f1-5) + [ -z "$lan_mac" ] || [ "$mac_prefix" = "00:e0:4c:00:00" ] && lan_mac=$(macaddr_random) lan_mac_start=$lan_mac eth0_mac=$lan_mac ;; diff --git a/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr b/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr index 3d9e795311..f6974f96f9 100644 --- a/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr +++ b/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr @@ -11,48 +11,53 @@ BOARD_CFG=/etc/board.json # Some devices make it hard or impossible to acquire a usable ethaddr / MAC address # of the device. Some store it in weird places, some ship with only the common -# Realtek dummy ethaddr, and some are outright broken. +# Realtek dummy ethaddr, and some are outright broken. Often the MAC address +# isn't printed on the case label either. # # For these devices, we generate a random ethaddr in /etc/board.d/02_network, -# which is stored in /etc/board.json. Here we take this random ethaddr and -# persist it in the U-Boot environment, so that it survives sysupgrades. +# which is saved in /etc/board.json. +# +# Here we take this random ethaddr and store it in the U-Boot environment, +# so that it survives sysupgrades and factory resets. + +store_board_ethaddr() { + local board_ethaddr + json_init + json_load_file "$BOARD_CFG" + json_select network_device + json_select eth0 + json_get_var board_ethaddr macaddr + json_cleanup + [ -n "$board_ethaddr" ] && fw_setenv ethaddr "$board_ethaddr" +} case "$(board_name)" in +# F1100W-4SX-4XGT and its variants ship with the dummy ethaddr in the u-boot +# environment, and the real ethaddr stored in RUNTIME/RUNTIME2 JFFS2 partitions, +# which would be annoying to deal with. Also ethaddr isn't printed on the case. +# +# TL-ST1008F v2 ships with a dummy ethaddr because it's an unmanaged switch. +# +# We store the random ethaddr if the currently stored ethaddr is empty or dummy. hasivo,f1100w-4sx-4xgt|\ hasivo,f1100w-4sx-4xgt-512mb|\ tplink,tl-st1008f-v2) env_ethaddr=$(macaddr_canonicalize "$(fw_printenv -n ethaddr 2>/dev/null)") + ethaddr_prefix=$(echo "$env_ethaddr" | cut -d: -f1-5) - # F1100W-4SX-4XGT and its variants ship with the dummy ethaddr in the u-boot - # environment, and the real ethaddr stored in RUNTIME/RUNTIME2 JFFS2 partitions, - # which would be annoying to deal with. Also ethaddr isn't printed on the case. - # - # TL-ST1008F v2 ships with a dummy ethaddr because it's an unmanaged switch. - # - # We persist the random ethaddr if the currently stored ethaddr is empty or dummy. - if [ -z "$env_ethaddr" ] || [ "$env_ethaddr" = "00:e0:4c:00:00:00" ]; then - json_init - json_load_file "$BOARD_CFG" - json_select network_device - json_select eth0 - json_get_var board_ethaddr macaddr - [ -n "$board_ethaddr" ] && fw_setenv ethaddr "$board_ethaddr" + if [ -z "$env_ethaddr" ] || [ "$ethaddr_prefix" = "00:e0:4c:00:00" ]; then + store_board_ethaddr fi ;; +# This device ships with an empty environment (invalid CRC). If it is still in +# that state, we don't want to modify it, because that would write the defaults +# of the userspace U-Boot tools (which differ from the ones in the bootloader). +# Thus, we don't do anything here if the ethaddr variable is empty. zyxel,xgs1010-12-a1) env_ethaddr=$(macaddr_canonicalize "$(fw_printenv -n ethaddr 2>/dev/null)") - # This device ships with an empty environment (invalid CRC). If it is still in - # that state, we don't want to modify it, because that would write the defaults - # of the userspace U-Boot tools (which differ from the ones in the bootloader). - # Thus, we don't do anything here if the ethaddr variable is empty. if [ "$env_ethaddr" = "00:e0:4c:00:00:00" ]; then - json_init - json_load_file "$BOARD_CFG" - json_select network_device - json_select eth0 - json_get_var board_ethaddr macaddr - [ -n "$board_ethaddr" ] && fw_setenv ethaddr "$board_ethaddr" + store_board_ethaddr fi ;; esac From 4694bb11a40629441312722f5a9763d8f21daac7 Mon Sep 17 00:00:00 2001 From: Lars Gierth Date: Tue, 19 May 2026 03:52:03 +0200 Subject: [PATCH 083/228] realtek: rtl931x: add support for Hasivo F5800W-12S+ This commit adds support for the Hasivo F5800W-12S+ 12-port SFP+ switch. Based on board revision `RTL_12S+ v1.01`. Hardware -------- | | | |----------|----------------------------------------------------------------| | SoC | RTL9313 rev B | | RAM | 512 MB Samsung K4B4G1646E | | Flash | 32 MB Macronix MX25L25645G SPI NOR, 29 MB usable by OpenWrt | | Ethernet | 12x SFP+ via SoC (10G/2.5G/1G) | | LEDs | 12x green 10G link, 12x green 1G link, | | | 3x green power and PSUs -- no system status LED | | Button | Reset | | Console | RJ45 38400 bps 8n1 | | Watchdog | via Hasivo MCU | | Power | 2x internal 100-240V AC PSUs with 2x C14 inputs | | Clock | NXP PCF8563 with coin cell battery | | Fans | 2x 40mm case fan via Hasivo MCU | Installing OpenWrt ------------------ 1. Attach to RJ45 serial console port using a cisco cable. 2. Attach SFP to port 12. 3. Serve initramfs-kernel.bin on TFTP 192.168.1.111. 4. Power on the device. 5. Interrupt U-Boot by pressing `Ctrl+c`, then `z`, then `h`, during 3 second countdown. 6. Bring up networking: `rtk network on ; rtk 10g 55 fiber10g`. 7. Boot from TFTP: `tftpboot 0x84f00000 initramfs-kernel.bin ; bootm 0x84f00000`. 8. Use `mtd dump` to make backups of all flash partitions. 9. Use SCP to copy `squashfs-sysupgrade.bin` to the device, then run `sysupgrade`. Restoring factory firmware -------------------------- OpenWrt uses the `RUNTIME` and `RUNTIME2` partitions as one combined partition. To restore them from backups, boot from `initramfs-kernel.bin` just like during the installation, then use `mtd write` to write your backups of the factory `mtd5` and `mtd6` partitions to the live `mtd5` partition. Notes/Quirks ------------ - U-Boot interruption is obfuscated. Press `Ctrl+c`, then `z`, then `h`, during the 3 second countdown. - MAC address is stored on the `RUNTIME` or `RUNTIME2` partitions, which are used by OpenWrt. Instead, we generate one random MAC address and store it in the U-Boot environment. - There is no system status LED. The three non-network LEDs are for primary PSU (MS label), secondary PSU (SL), and powered on/off (PW). Signed-off-by: Lars Gierth Link: https://github.com/openwrt/openwrt/pull/23443 Signed-off-by: Markus Stockhausen --- .../realtek/base-files/etc/board.d/02_network | 1 + .../etc/uci-defaults/99_fwenv-store-ethaddr | 5 +- .../dts/rtl9313_hasivo_f5800w-12s-plus.dts | 334 ++++++++++++++++++ target/linux/realtek/image/rtl931x.mk | 10 + 4 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 target/linux/realtek/dts/rtl9313_hasivo_f5800w-12s-plus.dts diff --git a/target/linux/realtek/base-files/etc/board.d/02_network b/target/linux/realtek/base-files/etc/board.d/02_network index eed572aaf3..d5bd3bf3db 100644 --- a/target/linux/realtek/base-files/etc/board.d/02_network +++ b/target/linux/realtek/base-files/etc/board.d/02_network @@ -100,6 +100,7 @@ realtek_setup_macs() ;; hasivo,f1100w-4sx-4xgt|\ hasivo,f1100w-4sx-4xgt-512mb|\ + hasivo,f5800w-12s-plus|\ tplink,tl-st1008f-v2|\ zyxel,xgs1010-12-a1) lan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) diff --git a/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr b/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr index f6974f96f9..285aca82db 100644 --- a/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr +++ b/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr @@ -36,11 +36,14 @@ case "$(board_name)" in # environment, and the real ethaddr stored in RUNTIME/RUNTIME2 JFFS2 partitions, # which would be annoying to deal with. Also ethaddr isn't printed on the case. # -# TL-ST1008F v2 ships with a dummy ethaddr because it's an unmanaged switch. +# F5800W-12S+ same as F1100W, except the MAC address ends with :10, not :00. +# +# TL-ST1008F v2 ships with the dummy ethaddr because it's sold as unmanaged. # # We store the random ethaddr if the currently stored ethaddr is empty or dummy. hasivo,f1100w-4sx-4xgt|\ hasivo,f1100w-4sx-4xgt-512mb|\ +hasivo,f5800w-12s-plus|\ tplink,tl-st1008f-v2) env_ethaddr=$(macaddr_canonicalize "$(fw_printenv -n ethaddr 2>/dev/null)") ethaddr_prefix=$(echo "$env_ethaddr" | cut -d: -f1-5) diff --git a/target/linux/realtek/dts/rtl9313_hasivo_f5800w-12s-plus.dts b/target/linux/realtek/dts/rtl9313_hasivo_f5800w-12s-plus.dts new file mode 100644 index 0000000000..0619fa78f9 --- /dev/null +++ b/target/linux/realtek/dts/rtl9313_hasivo_f5800w-12s-plus.dts @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/dts-v1/; + +#include "rtl931x.dtsi" + +#include +#include +#include +#include + +/ { + compatible = "hasivo,f5800w-12s-plus", "realtek,rtl9313-soc"; + model = "Hasivo F5800W-12S+"; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>, /* 256 MiB lowmem */ + <0x90000000 0x10000000>; /* 256 MiB highmem */ + }; + + chosen { + stdout-path = "serial0:38400n8"; + }; + + keys { + compatible = "gpio-keys"; + + button-reset { + label = "reset"; + gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + led_set { + compatible = "realtek,rtl9300-leds"; + active-low; + + led_set1 = < + ( // Green lower row - 2.5G/1G link + RTL93XX_LED_SET_2P5G | + RTL93XX_LED_SET_1G | + RTL93XX_LED_SET_LINK | + RTL93XX_LED_SET_ACT + ) + ( // Green upper row - 10G link + RTL93XX_LED_SET_10G | + RTL93XX_LED_SET_LINK | + RTL93XX_LED_SET_ACT + )>; + }; + + i2c_sys: i2c-system { + compatible = "i2c-gpio"; + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_disable_jtag>; + + scl-gpios = <&gpio0 4 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio0 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-gpio,delay-us = <28>; + + rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; + + mcu_mgmt: mcu@6f { + compatible = "hasivo,stc8-mfd", "syscon"; + reg = <0x6f>; + + mcu_wdt: watchdog { + compatible = "hasivo,mcu-wdt"; + }; + + sensor { + compatible = "hasivo,mcu-sensor"; + }; + }; + }; + + sfp1: sfp-p1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda0>; + los-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>; + }; + + sfp2: sfp-p2 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda1>; + los-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>; + }; + + sfp3: sfp-p3 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda2>; + los-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>; + }; + + sfp4: sfp-p4 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda3>; + los-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + }; + + sfp5: sfp-p5 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda4>; + los-gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; + }; + + sfp6: sfp-p6 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1_sda5>; + los-gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + }; + + sfp7: sfp-p7 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda6>; + los-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>; + }; + + sfp8: sfp-p8 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda7>; + los-gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 32 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio1 33 GPIO_ACTIVE_HIGH>; + }; + + sfp9: sfp-p9 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda8>; + los-gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio1 36 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>; + }; + + sfp10: sfp-p10 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda9>; + los-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; + }; + + sfp11: sfp-p11 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda10>; + los-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; + }; + + sfp12: sfp-p12 { + compatible = "sff,sfp"; + i2c-bus = <&i2c2_sda11>; + los-gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>; + mod-def0-gpios = <&gpio2 8 GPIO_ACTIVE_LOW>; + tx-disable-gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; + }; +}; + +&i2c_mst1 { + status = "okay"; + + i2c1_sda0: i2c@0 { reg = <0>; }; + i2c1_sda1: i2c@1 { reg = <1>; }; + i2c1_sda2: i2c@2 { reg = <2>; }; + i2c1_sda3: i2c@3 { reg = <3>; }; + i2c1_sda4: i2c@4 { reg = <4>; }; + i2c1_sda5: i2c@5 { reg = <5>; }; +}; + +&i2c_mst2 { + status = "okay"; + + i2c2_sda6: i2c@6 { reg = <6>; }; + i2c2_sda7: i2c@7 { reg = <7>; }; + i2c2_sda8: i2c@8 { reg = <8>; }; + i2c2_sda9: i2c@9 { reg = <9>; }; + i2c2_sda10: i2c@a { reg = <10>; }; + i2c2_sda11: i2c@b { reg = <11>; }; +}; + +&mdio_aux { + status = "okay"; + + gpio1: gpio@0 { + compatible = "realtek,rtl8231"; + reg = <0>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&gpio1 0 0 37>; + + led-controller { + compatible = "realtek,rtl8231-leds"; + status = "disabled"; + }; + }; + + gpio2: gpio@1 { + compatible = "realtek,rtl8231"; + reg = <1>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&gpio2 0 0 37>; + + led-controller { + compatible = "realtek,rtl8231-leds"; + status = "disabled"; + }; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* stock is LOADER */ + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x00e0000>; + read-only; + }; + + /* stock is BDINFO */ + partition@e0000 { + label = "u-boot-env"; + reg = <0x00e0000 0x0010000>; + }; + + /* stock is SYSINFO */ + partition@f0000 { + label = "u-boot-env2"; + reg = <0x00f0000 0x0010000>; + }; + + /* stock is CFG JFFS2 */ + partition@100000 { + label = "jffs"; + reg = <0x0100000 0x0100000>; + }; + + /* stock is LOG JFFS2 */ + partition@200000 { + label = "jffs2"; + reg = <0x0200000 0x0100000>; + }; + + /* stock is RUNTIME and RUNTIME2 + * RUNTIME is <0x0300000 0x0700000> + * RUNTIME2 is <0x0a00000 0x1600000> + */ + partition@300000 { + compatible = "openwrt,uimage", "denx,uimage"; + label = "firmware"; + reg = <0x0300000 0x1d00000>; + }; + }; + }; +}; + +&switch0 { + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + SWITCH_PORT_SFP(0, 1, 2, 1, 1) + SWITCH_PORT_SFP(8, 2, 3, 1, 2) + SWITCH_PORT_SFP(16, 3, 4, 1, 3) + SWITCH_PORT_SFP(24, 4, 5, 1, 4) + SWITCH_PORT_SFP(32, 5, 6, 1, 5) + SWITCH_PORT_SFP(40, 6, 7, 1, 6) + SWITCH_PORT_SFP(48, 7, 8, 1, 7) + SWITCH_PORT_SFP(50, 8, 9, 1, 8) + SWITCH_PORT_SFP(52, 9, 10, 1, 9) + SWITCH_PORT_SFP(53, 10, 11, 1, 10) + SWITCH_PORT_SFP(54, 11, 12, 1, 11) + SWITCH_PORT_SFP(55, 12, 13, 1, 12) + + /* CPU port */ + port@56 { + ethernet = <ðernet0>; + reg = <56>; + phy-mode = "internal"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; + +&serdes2 { tx-polarity = ; }; +&serdes3 { tx-polarity = ; }; +&serdes4 { tx-polarity = ; }; +&serdes5 { tx-polarity = ; }; +&serdes6 { tx-polarity = ; }; +&serdes7 { tx-polarity = ; }; +&serdes8 { tx-polarity = ; }; +&serdes9 { tx-polarity = ; }; +&serdes10 { tx-polarity = ; }; +&serdes11 { tx-polarity = ; }; +&serdes12 { tx-polarity = ; }; +&serdes13 { tx-polarity = ; }; diff --git a/target/linux/realtek/image/rtl931x.mk b/target/linux/realtek/image/rtl931x.mk index 865ef551a9..3d6607a1f0 100644 --- a/target/linux/realtek/image/rtl931x.mk +++ b/target/linux/realtek/image/rtl931x.mk @@ -2,6 +2,16 @@ include ./common.mk +define Device/hasivo_f5800w-12s-plus + SOC := rtl9313 + DEVICE_VENDOR := Hasivo + DEVICE_MODEL := F5800W-12S+ + IMAGE_SIZE := 29696k + DEVICE_PACKAGES := kmod-hasivo-mcu-wdt kmod-hasivo-mcu-sensor kmod-rtc-pcf8563 + $(Device/kernel-lzma) +endef +TARGET_DEVICES += hasivo_f5800w-12s-plus + define Device/plasmacloud-common SOC := rtl9312 UIMAGE_MAGIC := 0x93100000 From 30214f3b03edc61ac1f4c9af6b61fe5c22c8afa9 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 16 Jun 2026 13:19:45 -0700 Subject: [PATCH 084/228] ath79: move leds-reset driver to files This driver looks like it will never be upstreamed. Keep it local for easier modification. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/21027 Signed-off-by: Jonas Jelonek --- .../ath79/files/drivers/leds/leds-reset.c | 140 +++++++++++++++++ ...ds-add-reset-controller-based-driver.patch | 143 ------------------ ...ds-add-reset-controller-based-driver.patch | 143 ------------------ 3 files changed, 140 insertions(+), 286 deletions(-) create mode 100644 target/linux/ath79/files/drivers/leds/leds-reset.c diff --git a/target/linux/ath79/files/drivers/leds/leds-reset.c b/target/linux/ath79/files/drivers/leds/leds-reset.c new file mode 100644 index 0000000000..b7fb953a08 --- /dev/null +++ b/target/linux/ath79/files/drivers/leds/leds-reset.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2018 John Crispin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +struct reset_led_data { + struct led_classdev cdev; + struct reset_control *rst; +}; + +static inline struct reset_led_data * + cdev_to_reset_led_data(struct led_classdev *led_cdev) +{ + return container_of(led_cdev, struct reset_led_data, cdev); +} + +static void reset_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev); + + if (value == LED_OFF) + reset_control_assert(led_dat->rst); + else + reset_control_deassert(led_dat->rst); +} + +struct reset_leds_priv { + int num_leds; + struct reset_led_data leds[]; +}; + +static inline int sizeof_reset_leds_priv(int num_leds) +{ + return sizeof(struct reset_leds_priv) + + (sizeof(struct reset_led_data) * num_leds); +} + +static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct fwnode_handle *child; + struct reset_leds_priv *priv; + int count, ret; + + count = device_get_child_node_count(dev); + if (!count) + return ERR_PTR(-ENODEV); + + priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL); + if (!priv) + return ERR_PTR(-ENOMEM); + + device_for_each_child_node(dev, child) { + struct reset_led_data *led = &priv->leds[priv->num_leds]; + struct device_node *np = to_of_node(child); + + ret = fwnode_property_read_string(child, "label", &led->cdev.name); + if (!led->cdev.name) { + fwnode_handle_put(child); + return ERR_PTR(-EINVAL); + } + led->rst = __of_reset_control_get(np, NULL, 0, RESET_CONTROL_EXCLUSIVE); + if (IS_ERR(led->rst)) + return ERR_PTR(-EINVAL); + + fwnode_property_read_string(child, "linux,default-trigger", + &led->cdev.default_trigger); + + led->cdev.brightness_set = reset_led_set; + ret = devm_led_classdev_register(&pdev->dev, &led->cdev); + if (ret < 0) + return ERR_PTR(ret); + led->cdev.dev->of_node = np; + priv->num_leds++; + } + + return priv; +} + +static const struct of_device_id of_reset_leds_match[] = { + { .compatible = "reset-leds", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_reset_leds_match); + +static int reset_led_probe(struct platform_device *pdev) +{ + struct reset_leds_priv *priv; + + priv = reset_leds_create(pdev); + if (IS_ERR(priv)) + return PTR_ERR(priv); + + platform_set_drvdata(pdev, priv); + + return 0; +} + +static void reset_led_shutdown(struct platform_device *pdev) +{ + struct reset_leds_priv *priv = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < priv->num_leds; i++) { + struct reset_led_data *led = &priv->leds[i]; + + if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN)) + reset_led_set(&led->cdev, LED_OFF); + } +} + +static struct platform_driver reset_led_driver = { + .probe = reset_led_probe, + .shutdown = reset_led_shutdown, + .driver = { + .name = "leds-reset", + .of_match_table = of_reset_leds_match, + }, +}; + +module_platform_driver(reset_led_driver); + +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("reset controller LED driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-reset"); diff --git a/target/linux/ath79/patches-6.12/800-leds-add-reset-controller-based-driver.patch b/target/linux/ath79/patches-6.12/800-leds-add-reset-controller-based-driver.patch index 883d4910fc..d68566f03a 100644 --- a/target/linux/ath79/patches-6.12/800-leds-add-reset-controller-based-driver.patch +++ b/target/linux/ath79/patches-6.12/800-leds-add-reset-controller-based-driver.patch @@ -31,149 +31,6 @@ Signed-off-by: John Crispin comment "LED Triggers" source "drivers/leds/trigger/Kconfig" ---- /dev/null -+++ b/drivers/leds/leds-reset.c -@@ -0,0 +1,140 @@ -+/* -+ * Copyright (C) 2018 John Crispin -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct reset_led_data { -+ struct led_classdev cdev; -+ struct reset_control *rst; -+}; -+ -+static inline struct reset_led_data * -+ cdev_to_reset_led_data(struct led_classdev *led_cdev) -+{ -+ return container_of(led_cdev, struct reset_led_data, cdev); -+} -+ -+static void reset_led_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev); -+ -+ if (value == LED_OFF) -+ reset_control_assert(led_dat->rst); -+ else -+ reset_control_deassert(led_dat->rst); -+} -+ -+struct reset_leds_priv { -+ int num_leds; -+ struct reset_led_data leds[]; -+}; -+ -+static inline int sizeof_reset_leds_priv(int num_leds) -+{ -+ return sizeof(struct reset_leds_priv) + -+ (sizeof(struct reset_led_data) * num_leds); -+} -+ -+static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct fwnode_handle *child; -+ struct reset_leds_priv *priv; -+ int count, ret; -+ -+ count = device_get_child_node_count(dev); -+ if (!count) -+ return ERR_PTR(-ENODEV); -+ -+ priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL); -+ if (!priv) -+ return ERR_PTR(-ENOMEM); -+ -+ device_for_each_child_node(dev, child) { -+ struct reset_led_data *led = &priv->leds[priv->num_leds]; -+ struct device_node *np = to_of_node(child); -+ -+ ret = fwnode_property_read_string(child, "label", &led->cdev.name); -+ if (!led->cdev.name) { -+ fwnode_handle_put(child); -+ return ERR_PTR(-EINVAL); -+ } -+ led->rst = __of_reset_control_get(np, NULL, 0, RESET_CONTROL_EXCLUSIVE); -+ if (IS_ERR(led->rst)) -+ return ERR_PTR(-EINVAL); -+ -+ fwnode_property_read_string(child, "linux,default-trigger", -+ &led->cdev.default_trigger); -+ -+ led->cdev.brightness_set = reset_led_set; -+ ret = devm_led_classdev_register(&pdev->dev, &led->cdev); -+ if (ret < 0) -+ return ERR_PTR(ret); -+ led->cdev.dev->of_node = np; -+ priv->num_leds++; -+ } -+ -+ return priv; -+} -+ -+static const struct of_device_id of_reset_leds_match[] = { -+ { .compatible = "reset-leds", }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, of_reset_leds_match); -+ -+static int reset_led_probe(struct platform_device *pdev) -+{ -+ struct reset_leds_priv *priv; -+ -+ priv = reset_leds_create(pdev); -+ if (IS_ERR(priv)) -+ return PTR_ERR(priv); -+ -+ platform_set_drvdata(pdev, priv); -+ -+ return 0; -+} -+ -+static void reset_led_shutdown(struct platform_device *pdev) -+{ -+ struct reset_leds_priv *priv = platform_get_drvdata(pdev); -+ int i; -+ -+ for (i = 0; i < priv->num_leds; i++) { -+ struct reset_led_data *led = &priv->leds[i]; -+ -+ if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN)) -+ reset_led_set(&led->cdev, LED_OFF); -+ } -+} -+ -+static struct platform_driver reset_led_driver = { -+ .probe = reset_led_probe, -+ .shutdown = reset_led_shutdown, -+ .driver = { -+ .name = "leds-reset", -+ .of_match_table = of_reset_leds_match, -+ }, -+}; -+ -+module_platform_driver(reset_led_driver); -+ -+MODULE_AUTHOR("John Crispin "); -+MODULE_DESCRIPTION("reset controller LED driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:leds-reset"); --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_LEDS_TURRIS_OMNIA) += leds diff --git a/target/linux/ath79/patches-6.18/800-leds-add-reset-controller-based-driver.patch b/target/linux/ath79/patches-6.18/800-leds-add-reset-controller-based-driver.patch index febdadd666..f3a0f8ebea 100644 --- a/target/linux/ath79/patches-6.18/800-leds-add-reset-controller-based-driver.patch +++ b/target/linux/ath79/patches-6.18/800-leds-add-reset-controller-based-driver.patch @@ -31,149 +31,6 @@ Signed-off-by: John Crispin comment "LED Triggers" source "drivers/leds/trigger/Kconfig" ---- /dev/null -+++ b/drivers/leds/leds-reset.c -@@ -0,0 +1,140 @@ -+/* -+ * Copyright (C) 2018 John Crispin -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct reset_led_data { -+ struct led_classdev cdev; -+ struct reset_control *rst; -+}; -+ -+static inline struct reset_led_data * -+ cdev_to_reset_led_data(struct led_classdev *led_cdev) -+{ -+ return container_of(led_cdev, struct reset_led_data, cdev); -+} -+ -+static void reset_led_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev); -+ -+ if (value == LED_OFF) -+ reset_control_assert(led_dat->rst); -+ else -+ reset_control_deassert(led_dat->rst); -+} -+ -+struct reset_leds_priv { -+ int num_leds; -+ struct reset_led_data leds[]; -+}; -+ -+static inline int sizeof_reset_leds_priv(int num_leds) -+{ -+ return sizeof(struct reset_leds_priv) + -+ (sizeof(struct reset_led_data) * num_leds); -+} -+ -+static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct fwnode_handle *child; -+ struct reset_leds_priv *priv; -+ int count, ret; -+ -+ count = device_get_child_node_count(dev); -+ if (!count) -+ return ERR_PTR(-ENODEV); -+ -+ priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL); -+ if (!priv) -+ return ERR_PTR(-ENOMEM); -+ -+ device_for_each_child_node(dev, child) { -+ struct reset_led_data *led = &priv->leds[priv->num_leds]; -+ struct device_node *np = to_of_node(child); -+ -+ ret = fwnode_property_read_string(child, "label", &led->cdev.name); -+ if (!led->cdev.name) { -+ fwnode_handle_put(child); -+ return ERR_PTR(-EINVAL); -+ } -+ led->rst = __of_reset_control_get(np, NULL, 0, RESET_CONTROL_EXCLUSIVE); -+ if (IS_ERR(led->rst)) -+ return ERR_PTR(-EINVAL); -+ -+ fwnode_property_read_string(child, "linux,default-trigger", -+ &led->cdev.default_trigger); -+ -+ led->cdev.brightness_set = reset_led_set; -+ ret = devm_led_classdev_register(&pdev->dev, &led->cdev); -+ if (ret < 0) -+ return ERR_PTR(ret); -+ led->cdev.dev->of_node = np; -+ priv->num_leds++; -+ } -+ -+ return priv; -+} -+ -+static const struct of_device_id of_reset_leds_match[] = { -+ { .compatible = "reset-leds", }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, of_reset_leds_match); -+ -+static int reset_led_probe(struct platform_device *pdev) -+{ -+ struct reset_leds_priv *priv; -+ -+ priv = reset_leds_create(pdev); -+ if (IS_ERR(priv)) -+ return PTR_ERR(priv); -+ -+ platform_set_drvdata(pdev, priv); -+ -+ return 0; -+} -+ -+static void reset_led_shutdown(struct platform_device *pdev) -+{ -+ struct reset_leds_priv *priv = platform_get_drvdata(pdev); -+ int i; -+ -+ for (i = 0; i < priv->num_leds; i++) { -+ struct reset_led_data *led = &priv->leds[i]; -+ -+ if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN)) -+ reset_led_set(&led->cdev, LED_OFF); -+ } -+} -+ -+static struct platform_driver reset_led_driver = { -+ .probe = reset_led_probe, -+ .shutdown = reset_led_shutdown, -+ .driver = { -+ .name = "leds-reset", -+ .of_match_table = of_reset_leds_match, -+ }, -+}; -+ -+module_platform_driver(reset_led_driver); -+ -+MODULE_AUTHOR("John Crispin "); -+MODULE_DESCRIPTION("reset controller LED driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:leds-reset"); --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_LEDS_UPBOARD) += leds-upbo From bf8ca30dbea99a084d16ddabd59d5d18c1ad14b3 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 16 Jun 2026 13:39:11 -0700 Subject: [PATCH 085/228] ath79: improve reset-controller driver Use _scoped loop to about fwnode_handle_put everywhere. Remove usage of of_node. Use devm_led_classdev_register_ext to avoid fwnode handle leaks. Remove custom struct_size function. Fix other various issues found with AI. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/21027 Signed-off-by: Jonas Jelonek --- .../ath79/files/drivers/leds/leds-reset.c | 71 +++++++------------ 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/target/linux/ath79/files/drivers/leds/leds-reset.c b/target/linux/ath79/files/drivers/leds/leds-reset.c index b7fb953a08..ead9d18a82 100644 --- a/target/linux/ath79/files/drivers/leds/leds-reset.c +++ b/target/linux/ath79/files/drivers/leds/leds-reset.c @@ -11,13 +11,13 @@ #include #include #include +#include #include #include -#include struct reset_led_data { - struct led_classdev cdev; struct reset_control *rst; + struct led_classdev cdev; }; static inline struct reset_led_data * @@ -42,69 +42,46 @@ struct reset_leds_priv { struct reset_led_data leds[]; }; -static inline int sizeof_reset_leds_priv(int num_leds) -{ - return sizeof(struct reset_leds_priv) + - (sizeof(struct reset_led_data) * num_leds); -} - -static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev) +static int reset_led_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct fwnode_handle *child; struct reset_leds_priv *priv; - int count, ret; + int count; count = device_get_child_node_count(dev); if (!count) - return ERR_PTR(-ENODEV); + return -ENODEV; - priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL); + priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL); if (!priv) - return ERR_PTR(-ENOMEM); + return -ENOMEM; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct reset_led_data *led = &priv->leds[priv->num_leds]; - struct device_node *np = to_of_node(child); + struct led_init_data init_data = { + .fwnode = child, + }; + int ret; ret = fwnode_property_read_string(child, "label", &led->cdev.name); - if (!led->cdev.name) { - fwnode_handle_put(child); - return ERR_PTR(-EINVAL); - } - led->rst = __of_reset_control_get(np, NULL, 0, RESET_CONTROL_EXCLUSIVE); + if (ret) + return ret; + + led->rst = of_reset_control_get_exclusive(to_of_node(child), NULL); if (IS_ERR(led->rst)) - return ERR_PTR(-EINVAL); + return PTR_ERR(led->rst); fwnode_property_read_string(child, "linux,default-trigger", &led->cdev.default_trigger); led->cdev.brightness_set = reset_led_set; - ret = devm_led_classdev_register(&pdev->dev, &led->cdev); + ret = devm_led_classdev_register_ext(dev, &led->cdev, &init_data); if (ret < 0) - return ERR_PTR(ret); - led->cdev.dev->of_node = np; + return ret; + priv->num_leds++; } - return priv; -} - -static const struct of_device_id of_reset_leds_match[] = { - { .compatible = "reset-leds", }, - {}, -}; - -MODULE_DEVICE_TABLE(of, of_reset_leds_match); - -static int reset_led_probe(struct platform_device *pdev) -{ - struct reset_leds_priv *priv; - - priv = reset_leds_create(pdev); - if (IS_ERR(priv)) - return PTR_ERR(priv); - platform_set_drvdata(pdev, priv); return 0; @@ -123,6 +100,13 @@ static void reset_led_shutdown(struct platform_device *pdev) } } +static const struct of_device_id of_reset_leds_match[] = { + { .compatible = "reset-leds", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_reset_leds_match); + static struct platform_driver reset_led_driver = { .probe = reset_led_probe, .shutdown = reset_led_shutdown, @@ -137,4 +121,3 @@ module_platform_driver(reset_led_driver); MODULE_AUTHOR("John Crispin "); MODULE_DESCRIPTION("reset controller LED driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:leds-reset"); From e2d12cfae6bec4f65f2b5bec6eecb7ca1c6455da Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 18 Jun 2026 12:54:37 -0700 Subject: [PATCH 086/228] bcm53xx: backport meraki mx6x warning fix The kernel ended up fixing this dts problem at runtime, but fix it directly instead. Upstream backport. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23870 Signed-off-by: Jonas Jelonek --- ...Move-MX6X-pinctrl-config-to-PWM-node.patch | 41 +++++++++++++++++++ ...Move-MX6X-pinctrl-config-to-PWM-node.patch | 41 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 target/linux/bcm53xx/patches-6.12/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch create mode 100644 target/linux/bcm53xx/patches-6.18/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch diff --git a/target/linux/bcm53xx/patches-6.12/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch b/target/linux/bcm53xx/patches-6.12/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch new file mode 100644 index 0000000000..515d2b7df9 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch @@ -0,0 +1,41 @@ +From d7b3f4a4eb23d82ef923cf17509292b719340378 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Wed, 29 Apr 2026 22:16:12 -0700 +Subject: [PATCH] ARM: dts: NSP: Move MX6X pinctrl config to PWM node + +On boot there is this warning: + +/axi@18000000/pinctrl@3f1c0: Fixed dependency cycle(s) with /axi@18000000/pinctrl@3f1c0/pwm_leds + +Fix by moving the pinctrl configuration to pwm, which is the actual +consumer. + +Signed-off-by: Rosen Penev +Link: https://lore.kernel.org/r/20260430051612.700050-1-rosenp@gmail.com +Signed-off-by: Florian Fainelli +--- + .../arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi +@@ -121,9 +121,6 @@ + }; + + &pinctrl { +- pinctrl-names = "default"; +- pinctrl-0 = <&pwm_leds>; +- + pwm_leds: pwm_leds { + function = "pwm"; + groups = "pwm1_grp", "pwm2_grp", "pwm3_grp"; +@@ -131,6 +128,9 @@ + }; + + &pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_leds>; ++ + status = "okay"; + #pwm-cells = <2>; + }; diff --git a/target/linux/bcm53xx/patches-6.18/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch b/target/linux/bcm53xx/patches-6.18/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch new file mode 100644 index 0000000000..49da9fa9dd --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/331-v7.2-ARM-dts-NSP-Move-MX6X-pinctrl-config-to-PWM-node.patch @@ -0,0 +1,41 @@ +From d7b3f4a4eb23d82ef923cf17509292b719340378 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Wed, 29 Apr 2026 22:16:12 -0700 +Subject: [PATCH] ARM: dts: NSP: Move MX6X pinctrl config to PWM node + +On boot there is this warning: + +/axi@18000000/pinctrl@3f1c0: Fixed dependency cycle(s) with /axi@18000000/pinctrl@3f1c0/pwm_leds + +Fix by moving the pinctrl configuration to pwm, which is the actual +consumer. + +Signed-off-by: Rosen Penev +Link: https://lore.kernel.org/r/20260430051612.700050-1-rosenp@gmail.com +Signed-off-by: Florian Fainelli +--- + .../arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi +@@ -121,9 +121,6 @@ + }; + + &pinctrl { +- pinctrl-names = "default"; +- pinctrl-0 = <&pwm_leds>; +- + pwm_leds: pwm_leds { + function = "pwm"; + groups = "pwm1_grp", "pwm2_grp", "pwm3_grp"; +@@ -131,6 +128,9 @@ + }; + + &pwm { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm_leds>; ++ + status = "okay"; + }; + From f83bddb9c083b49e191c2d9822f60aa8b55de476 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 3 Dec 2025 20:48:57 -0800 Subject: [PATCH 087/228] treewide: use _scoped for loops Done for local patches. Potential upstreaming will be using these anyway. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23872 Signed-off-by: Jonas Jelonek --- .../generic/files/drivers/net/phy/b53/b53_common.c | 1 + ...mtd-parsers-add-nvmem-support-to-cmdlinepart.patch | 11 +++++------ .../hack-6.12/800-GPIO-add-named-gpio-exports.patch | 5 ++--- ...mtd-parsers-add-nvmem-support-to-cmdlinepart.patch | 11 +++++------ .../hack-6.18/800-GPIO-add-named-gpio-exports.patch | 5 ++--- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c index 1130afdd9c..0a698cca78 100644 --- a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c +++ b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c @@ -566,6 +566,7 @@ static int b53_configure_ports_of(struct b53_device *dev) } } + of_node_put(dn); return 0; } diff --git a/target/linux/generic/hack-6.12/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch b/target/linux/generic/hack-6.12/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch index 190fecc1a0..9f8f8c112c 100644 --- a/target/linux/generic/hack-6.12/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch +++ b/target/linux/generic/hack-6.12/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch @@ -27,7 +27,7 @@ Signed-off-by: Ansuel Smith /* special size referring to all the remaining space in a partition */ #define SIZE_REMAINING ULLONG_MAX -@@ -315,6 +316,68 @@ static int mtdpart_setup_real(char *s) +@@ -315,6 +316,67 @@ static int mtdpart_setup_real(char *s) return 0; } @@ -37,7 +37,6 @@ Signed-off-by: Ansuel Smith +{ + struct device_node *mtd_node; + struct device_node *ofpart_node; -+ struct device_node *pp; + struct mtd_partition part; + const char *partname; + @@ -47,7 +46,7 @@ Signed-off-by: Ansuel Smith + + ofpart_node = of_get_child_by_name(mtd_node, "partitions"); + -+ for_each_child_of_node(ofpart_node, pp) { ++ for_each_child_of_node_scoped(ofpart_node, pp) { + const __be32 *reg; + int len; + int a_cells, s_cells; @@ -71,7 +70,7 @@ Signed-off-by: Ansuel Smith + + part.offset = of_read_number(reg, a_cells); + part.size = of_read_number(reg + a_cells, s_cells); -+ part.of_node = pp; ++ part.of_node = of_node_get(pp); + + partname = of_get_property(pp, "label", &len); + if (!partname) @@ -96,7 +95,7 @@ Signed-off-by: Ansuel Smith /* * Main function to be called from the MTD mapping driver/device to * obtain the partitioning information. At this point the command line -@@ -330,6 +393,7 @@ static int parse_cmdline_partitions(stru +@@ -330,6 +392,7 @@ static int parse_cmdline_partitions(stru int i, err; struct cmdline_mtd_partition *part; const char *mtd_id = master->name; @@ -104,7 +103,7 @@ Signed-off-by: Ansuel Smith /* parse command line */ if (!cmdline_parsed) { -@@ -374,6 +438,13 @@ static int parse_cmdline_partitions(stru +@@ -374,6 +437,13 @@ static int parse_cmdline_partitions(stru sizeof(*part->parts) * (part->num_parts - i)); i--; } diff --git a/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch index fe2b19c563..367ad69664 100644 --- a/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch +++ b/target/linux/generic/hack-6.12/800-GPIO-add-named-gpio-exports.patch @@ -15,7 +15,7 @@ Signed-off-by: John Crispin #include "gpiolib.h" #include "gpiolib-of.h" -@@ -1205,3 +1207,73 @@ void of_gpiochip_remove(struct gpio_chip +@@ -1205,3 +1207,72 @@ void of_gpiochip_remove(struct gpio_chip of_node_put(np); } @@ -30,11 +30,10 @@ Signed-off-by: John Crispin +static int of_gpio_export_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; -+ struct device_node *cnp; + u32 val; + int nb = 0; + -+ for_each_child_of_node(np, cnp) { ++ for_each_child_of_node_scoped(np, cnp) { + const char *name = NULL; + int gpio; + bool dmc; diff --git a/target/linux/generic/hack-6.18/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch b/target/linux/generic/hack-6.18/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch index 190fecc1a0..9f8f8c112c 100644 --- a/target/linux/generic/hack-6.18/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch +++ b/target/linux/generic/hack-6.18/421-drivers-mtd-parsers-add-nvmem-support-to-cmdlinepart.patch @@ -27,7 +27,7 @@ Signed-off-by: Ansuel Smith /* special size referring to all the remaining space in a partition */ #define SIZE_REMAINING ULLONG_MAX -@@ -315,6 +316,68 @@ static int mtdpart_setup_real(char *s) +@@ -315,6 +316,67 @@ static int mtdpart_setup_real(char *s) return 0; } @@ -37,7 +37,6 @@ Signed-off-by: Ansuel Smith +{ + struct device_node *mtd_node; + struct device_node *ofpart_node; -+ struct device_node *pp; + struct mtd_partition part; + const char *partname; + @@ -47,7 +46,7 @@ Signed-off-by: Ansuel Smith + + ofpart_node = of_get_child_by_name(mtd_node, "partitions"); + -+ for_each_child_of_node(ofpart_node, pp) { ++ for_each_child_of_node_scoped(ofpart_node, pp) { + const __be32 *reg; + int len; + int a_cells, s_cells; @@ -71,7 +70,7 @@ Signed-off-by: Ansuel Smith + + part.offset = of_read_number(reg, a_cells); + part.size = of_read_number(reg + a_cells, s_cells); -+ part.of_node = pp; ++ part.of_node = of_node_get(pp); + + partname = of_get_property(pp, "label", &len); + if (!partname) @@ -96,7 +95,7 @@ Signed-off-by: Ansuel Smith /* * Main function to be called from the MTD mapping driver/device to * obtain the partitioning information. At this point the command line -@@ -330,6 +393,7 @@ static int parse_cmdline_partitions(stru +@@ -330,6 +392,7 @@ static int parse_cmdline_partitions(stru int i, err; struct cmdline_mtd_partition *part; const char *mtd_id = master->name; @@ -104,7 +103,7 @@ Signed-off-by: Ansuel Smith /* parse command line */ if (!cmdline_parsed) { -@@ -374,6 +438,13 @@ static int parse_cmdline_partitions(stru +@@ -374,6 +437,13 @@ static int parse_cmdline_partitions(stru sizeof(*part->parts) * (part->num_parts - i)); i--; } diff --git a/target/linux/generic/hack-6.18/800-GPIO-add-named-gpio-exports.patch b/target/linux/generic/hack-6.18/800-GPIO-add-named-gpio-exports.patch index 63a49702f7..a18015d0b9 100644 --- a/target/linux/generic/hack-6.18/800-GPIO-add-named-gpio-exports.patch +++ b/target/linux/generic/hack-6.18/800-GPIO-add-named-gpio-exports.patch @@ -15,7 +15,7 @@ Signed-off-by: John Crispin #include "gpiolib.h" #include "gpiolib-of.h" -@@ -1302,3 +1304,73 @@ bool of_gpiochip_instance_match(struct g +@@ -1302,3 +1304,72 @@ bool of_gpiochip_instance_match(struct g return false; } @@ -30,11 +30,10 @@ Signed-off-by: John Crispin +static int of_gpio_export_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; -+ struct device_node *cnp; + u32 val; + int nb = 0; + -+ for_each_child_of_node(np, cnp) { ++ for_each_child_of_node_scoped(np, cnp) { + const char *name = NULL; + int gpio; + bool dmc; From d32dd03f3dc62f7d0b4e96a9e2a7ef3ed5081c8f Mon Sep 17 00:00:00 2001 From: Shine <4c.fce2@proton.me> Date: Fri, 19 Jun 2026 16:09:27 +0200 Subject: [PATCH 088/228] realtek: rtl930x: use common DTSI for Zyxel XGS1010-12 In preparation for adding support for the B1 revision of this model, introduce a common DTSI and image recipe. Signed-off-by: Shine <4c.fce2@proton.me> Link: https://github.com/openwrt/openwrt/pull/23882 Signed-off-by: Markus Stockhausen --- .../dts/rtl9302_zyxel_xgs1010-12-a1.dts | 97 +---------------- .../dts/rtl9302_zyxel_xgs1010-12-common.dtsi | 101 ++++++++++++++++++ target/linux/realtek/image/common.mk | 10 ++ target/linux/realtek/image/rtl930x.mk | 8 +- 4 files changed, 113 insertions(+), 103 deletions(-) create mode 100644 target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-common.dtsi diff --git a/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-a1.dts b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-a1.dts index 7a5d2f4b3d..a1f19a9aa6 100644 --- a/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-a1.dts +++ b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-a1.dts @@ -1,106 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later /dts-v1/; -#include "rtl9302_zyxel_xgs1x10-12-common.dtsi" +#include "rtl9302_zyxel_xgs1010-12-common.dtsi" / { compatible = "zyxel,xgs1010-12-a1", "realtek,rtl930x-soc"; model = "Zyxel XGS1010-12 A1"; - - virtual_flash { - compatible = "mtd-concat"; - - devices = <&fwconcat0 &fwconcat1 &fwconcat2>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "firmware"; - reg = <0x0 0x0>; - compatible = "openwrt,uimage", "denx,uimage"; - openwrt,ih-magic = <0x93001010>; - }; - }; - }; -}; - -&spi0 { - status = "okay"; - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <10000000>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "u-boot"; - reg = <0x0 0xe0000>; - read-only; - }; - - partition@e0000 { - label = "u-boot-env"; - reg = <0xe0000 0x10000>; - }; - - partition@f0000 { - label = "u-boot-env2"; - reg = <0xf0000 0x10000>; - read-only; - }; - - /* - * If additional space is needed in the future, the JFFS2 partitions could - * be added to the concatenated firmware partition. They are only reserved - * for now to allow running the XGS1210-12 firmware, which can be useful - * as a reference during development. - */ - - partition@100000 { - label = "jffs2-cfg"; - reg = <0x100000 0x100000>; - }; - - partition@200000 { - label = "jffs2-log"; - reg = <0x200000 0x100000>; - }; - - fwconcat1: partition@300000 { - label = "fwconcat1"; - reg = <0x300000 0x510000>; - }; - - partition@810000 { - reg = <0x810000 0x10000>; - label = "htp-log"; - read-only; - }; - - fwconcat2: partition@820000 { - label = "fwconcat2"; - reg = <0x820000 0xd0000>; - }; - - partition@8f0000 { - reg = <0x8f0000 0x10000>; - label = "htp-flash-test"; - read-only; - }; - - fwconcat0: partition@900000 { - label = "fwconcat0"; - reg = <0x900000 0x700000>; - }; - }; - }; }; &mdio_bus1 { diff --git a/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-common.dtsi b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-common.dtsi new file mode 100644 index 0000000000..bb510c3849 --- /dev/null +++ b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-common.dtsi @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/dts-v1/; + +#include "rtl9302_zyxel_xgs1x10-12-common.dtsi" + +/ { + virtual_flash { + compatible = "mtd-concat"; + + devices = <&fwconcat0 &fwconcat1 &fwconcat2>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "firmware"; + reg = <0x0 0x0>; + compatible = "openwrt,uimage", "denx,uimage"; + openwrt,ih-magic = <0x93001010>; + }; + }; + }; +}; + +&spi0 { + status = "okay"; + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0xe0000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0xe0000 0x10000>; + }; + + partition@f0000 { + label = "u-boot-env2"; + reg = <0xf0000 0x10000>; + read-only; + }; + + /* + * If additional space is needed in the future, the JFFS2 partitions could + * be added to the concatenated firmware partition. They are only reserved + * for now to allow running the XGS1210-12 firmware, which can be useful + * as a reference during development. + */ + + partition@100000 { + label = "jffs2-cfg"; + reg = <0x100000 0x100000>; + }; + + partition@200000 { + label = "jffs2-log"; + reg = <0x200000 0x100000>; + }; + + fwconcat1: partition@300000 { + label = "fwconcat1"; + reg = <0x300000 0x510000>; + }; + + partition@810000 { + reg = <0x810000 0x10000>; + label = "htp-log"; + read-only; + }; + + fwconcat2: partition@820000 { + label = "fwconcat2"; + reg = <0x820000 0xd0000>; + }; + + partition@8f0000 { + reg = <0x8f0000 0x10000>; + label = "htp-flash-test"; + read-only; + }; + + fwconcat0: partition@900000 { + label = "fwconcat0"; + reg = <0x900000 0x700000>; + }; + }; + }; +}; diff --git a/target/linux/realtek/image/common.mk b/target/linux/realtek/image/common.mk index 3a820fec43..6975654395 100644 --- a/target/linux/realtek/image/common.mk +++ b/target/linux/realtek/image/common.mk @@ -101,6 +101,16 @@ define Device/zyxel_gs1900 check-size 6976k endef +define Device/zyxel_xgs1010-12 + SOC := rtl9302 + UIMAGE_MAGIC := 0x93001010 + DEVICE_VENDOR := Zyxel + DEVICE_MODEL := XGS1010-12 + KERNEL_SIZE := 7168k + IMAGE_SIZE := 13184k + $(Device/kernel-lzma) +endef + define Device/zyxel_xgs1210-12 SOC := rtl9302 UIMAGE_MAGIC := 0x93001210 diff --git a/target/linux/realtek/image/rtl930x.mk b/target/linux/realtek/image/rtl930x.mk index f4b7a67eff..b1a2602fa1 100644 --- a/target/linux/realtek/image/rtl930x.mk +++ b/target/linux/realtek/image/rtl930x.mk @@ -272,14 +272,8 @@ endef TARGET_DEVICES += xikestor_sks8310-8x define Device/zyxel_xgs1010-12-a1 - SOC := rtl9302 - UIMAGE_MAGIC := 0x93001010 - DEVICE_VENDOR := Zyxel - DEVICE_MODEL := XGS1010-12 + $(Device/zyxel_xgs1010-12) DEVICE_VARIANT := A1 - KERNEL_SIZE := 7168k - IMAGE_SIZE := 13184k - $(Device/kernel-lzma) endef TARGET_DEVICES += zyxel_xgs1010-12-a1 From 304525e7545110d1d46117a1759a22280c608f46 Mon Sep 17 00:00:00 2001 From: Shine <4c.fce2@proton.me> Date: Fri, 19 Jun 2026 16:09:27 +0200 Subject: [PATCH 089/228] realtek: rtl930x: add support for Zyxel XGS1010-12 B1 This commit adds support for the Zyxel XGS1010-12 B1 revision, which is basically the unmanaged version of the XGS1210-12 B1. It features a newer uBoot build and slightly different 2.5G PHYs than the A1 revision of this model. SoC: RTL9302B RAM: 128MB DDR3 Flash: 16MB SPI-NOR Ethernet: 8x 1GBE RJ45 (RTL8218D) 2x 2.5GBE (2x RTL8226B) 2x SFP+ cage (10G/2.5G/1G) UART: 3.3V 115200 8N1, accessible from the right side of the case Pinout (top to bottom): Vcc - Tx - Rx - Gnd MAC address: The base MAC is stored in uBoot env variable 'ethaddr', which contains only a placeholder ('00:E0:4C:00:00:00') in the factory default configuration. Will be generated randomly at boot unless manually preset (see installation instructions). Additional port MACs are assigned incrementally per port. This contribution is based on the already existing support for the Zyxel XGS1010-12-A1 and XGS1210-12-B1. Installation instructions: 1. Set your PC's IP address to 192.168.1.111 and serve the OpenWrt Initramfs image via TFTP (e.g. as "initramfs.bin") 2. Connect to the device via UART, power on and press Esc within 1 second after prompted. 3. (Optional) Set a unique MAC address: setenv ethaddr AA:BB:CC:DD:EE:FF 4. Populate the uBoot env partition with the command: saveenv 5. Enter the following command line to boot the Initramfs OpenWrt image: rtk network on; tftpboot 0x84f00000 initramfs.bin; bootm 6. Wait until OpenWrt has booted and connect via SSH. 7. (Optional) Back up the original partitions (at least mtd5-mtd9) in order to be able to revert to stock later. 8. Update the boot command needed to boot OpenWrt: fw_setenv bootcmd "rtk network on; bootm 0xb4900000" 9. Install the OpenWrt sysupgrade image and wait for the device to boot OpenWrt from flash. Enjoy. Back to stock: 1. Boot the Initramfs image as described above. 2. Write the previously backed up mtd5-mtd9 partitions to flash. 3. Restore the boot command to stock: fw_setenv bootcmd boota 4. Reboot into stock firmware. Signed-off-by: Shine <4c.fce2@proton.me> Link: https://github.com/openwrt/openwrt/pull/23882 Signed-off-by: Markus Stockhausen --- .../realtek/base-files/etc/board.d/02_network | 3 ++- .../etc/uci-defaults/99_fwenv-store-ethaddr | 3 ++- .../realtek/dts/rtl9302_zyxel_xgs1010-12-b1.dts | 17 +++++++++++++++++ target/linux/realtek/image/rtl930x.mk | 6 ++++++ 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-b1.dts diff --git a/target/linux/realtek/base-files/etc/board.d/02_network b/target/linux/realtek/base-files/etc/board.d/02_network index d5bd3bf3db..95ea56a268 100644 --- a/target/linux/realtek/base-files/etc/board.d/02_network +++ b/target/linux/realtek/base-files/etc/board.d/02_network @@ -102,7 +102,8 @@ realtek_setup_macs() hasivo,f1100w-4sx-4xgt-512mb|\ hasivo,f5800w-12s-plus|\ tplink,tl-st1008f-v2|\ - zyxel,xgs1010-12-a1) + zyxel,xgs1010-12-a1|\ + zyxel,xgs1010-12-b1) lan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) mac_prefix=$(echo "$lan_mac" | cut -d: -f1-5) [ -z "$lan_mac" ] || [ "$mac_prefix" = "00:e0:4c:00:00" ] && lan_mac=$(macaddr_random) diff --git a/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr b/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr index 285aca82db..5a8e3a8ae1 100644 --- a/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr +++ b/target/linux/realtek/base-files/etc/uci-defaults/99_fwenv-store-ethaddr @@ -56,7 +56,8 @@ tplink,tl-st1008f-v2) # that state, we don't want to modify it, because that would write the defaults # of the userspace U-Boot tools (which differ from the ones in the bootloader). # Thus, we don't do anything here if the ethaddr variable is empty. -zyxel,xgs1010-12-a1) +zyxel,xgs1010-12-a1|\ +zyxel,xgs1010-12-b1) env_ethaddr=$(macaddr_canonicalize "$(fw_printenv -n ethaddr 2>/dev/null)") if [ "$env_ethaddr" = "00:e0:4c:00:00:00" ]; then diff --git a/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-b1.dts b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-b1.dts new file mode 100644 index 0000000000..7437890749 --- /dev/null +++ b/target/linux/realtek/dts/rtl9302_zyxel_xgs1010-12-b1.dts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/dts-v1/; + +#include "rtl9302_zyxel_xgs1010-12-common.dtsi" + +/ { + compatible = "zyxel,xgs1010-12-b1", "realtek,rtl930x-soc"; + model = "Zyxel XGS1010-12 B1"; +}; + +&mdio_bus1 { + PHY_C45(24, 1) +}; + +&mdio_bus2 { + PHY_C45(25, 2) +}; diff --git a/target/linux/realtek/image/rtl930x.mk b/target/linux/realtek/image/rtl930x.mk index b1a2602fa1..e58020551b 100644 --- a/target/linux/realtek/image/rtl930x.mk +++ b/target/linux/realtek/image/rtl930x.mk @@ -277,6 +277,12 @@ define Device/zyxel_xgs1010-12-a1 endef TARGET_DEVICES += zyxel_xgs1010-12-a1 +define Device/zyxel_xgs1010-12-b1 + $(Device/zyxel_xgs1010-12) + DEVICE_VARIANT := B1 +endef +TARGET_DEVICES += zyxel_xgs1010-12-b1 + define Device/zyxel_xgs1210-12-a1 $(Device/zyxel_xgs1210-12) SUPPORTED_DEVICES += zyxel,xgs1210-12 From 560fb07c03b8a6490d625fd05eeaf8180aa36b6a Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 20 Jun 2026 16:22:14 -0700 Subject: [PATCH 090/228] ipq40xx: add beginning space to bootargs-append Technically not needed but more consistent with other users. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23899 Signed-off-by: Jonas Jelonek --- target/linux/ipq40xx/dts/qcom-ipq4019-lbr20.dts | 2 +- target/linux/ipq40xx/dts/qcom-ipq4019-rbx20.dtsi | 2 +- target/linux/ipq40xx/dts/qcom-ipq4019-rtl30vw.dts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/ipq40xx/dts/qcom-ipq4019-lbr20.dts b/target/linux/ipq40xx/dts/qcom-ipq4019-lbr20.dts index f4c71fb8dc..eeb7e5421f 100644 --- a/target/linux/ipq40xx/dts/qcom-ipq4019-lbr20.dts +++ b/target/linux/ipq40xx/dts/qcom-ipq4019-lbr20.dts @@ -11,7 +11,7 @@ compatible = "netgear,lbr20"; chosen { - bootargs-append = "ubi.mtd=ubi root=/dev/ubiblock0_0"; + bootargs-append = " ubi.mtd=ubi root=/dev/ubiblock0_0"; }; aliases { diff --git a/target/linux/ipq40xx/dts/qcom-ipq4019-rbx20.dtsi b/target/linux/ipq40xx/dts/qcom-ipq4019-rbx20.dtsi index 08d2c0e4a0..b0aa6df86a 100644 --- a/target/linux/ipq40xx/dts/qcom-ipq4019-rbx20.dtsi +++ b/target/linux/ipq40xx/dts/qcom-ipq4019-rbx20.dtsi @@ -8,7 +8,7 @@ / { chosen { - bootargs-append = "ubi.mtd=ubi root=/dev/ubiblock0_0"; + bootargs-append = " ubi.mtd=ubi root=/dev/ubiblock0_0"; }; aliases { diff --git a/target/linux/ipq40xx/dts/qcom-ipq4019-rtl30vw.dts b/target/linux/ipq40xx/dts/qcom-ipq4019-rtl30vw.dts index 0a8b366be6..47e8a81abf 100644 --- a/target/linux/ipq40xx/dts/qcom-ipq4019-rtl30vw.dts +++ b/target/linux/ipq40xx/dts/qcom-ipq4019-rtl30vw.dts @@ -23,7 +23,7 @@ }; chosen { - bootargs-append = "ubi.mtd=ubifs root=/dev/ubiblock0_0 rootfstype=squashfs ro"; + bootargs-append = " ubi.mtd=ubifs root=/dev/ubiblock0_0 rootfstype=squashfs ro"; }; led_spi { From 30db95936f693eb4d468422c199c4ccad415e1b9 Mon Sep 17 00:00:00 2001 From: Ahmed Naseef Date: Fri, 19 Jun 2026 14:26:37 +0400 Subject: [PATCH 091/228] econet: use kernel 6.18 by default and drop 6.12 Switch the econet target to use kernel 6.18 and drop 6.12. Signed-off-by: Ahmed Naseef Link: https://github.com/openwrt/openwrt/pull/23879 Signed-off-by: Jonas Jelonek --- target/linux/econet/Makefile | 3 +- target/linux/econet/en751221/config-6.12 | 209 ---------- target/linux/econet/en751627/config-6.12 | 239 ----------- target/linux/econet/en7528/config-6.12 | 241 ----------- ...rrupt-controller-Add-EcoNet-EN751221.patch | 98 ----- ....16-irqchip-Add-EcoNet-EN751221-INTC.patch | 353 ----------------- ...-bindings-vendor-prefixes-Add-EcoNet.patch | 26 -- ...er-Add-EcoNet-EN751221-HPT-CPU-Timer.patch | 100 ----- ...-drivers-Add-EcoNet-Timer-HPT-driver.patch | 276 ------------- ...ngs-mips-Add-EcoNet-platform-binding.patch | 44 --- ...ips-Add-EcoNet-MIPS-platform-support.patch | 222 ----------- ...dings-vendor-prefixes-Add-SmartFiber.patch | 29 -- ...Net-DTS-with-EN751221-and-SmartFiber.patch | 149 ------- ...entry-for-newly-added-EcoNet-platfor.patch | 38 -- ...t-Fix-incorrect-Kconfig-dependencies.patch | 32 -- ...en7581_reset_register-in-en7581_clk_.patch | 174 -------- ...7523-map-io-region-in-a-single-block.patch | 84 ---- ...3-Move-reset-delay-in-mtk_pcie_en758.patch | 42 -- ...k-clock-handling-for-different-clock.patch | 83 ---- ...en7523-Add-clock-for-eMMC-for-EN7581.patch | 41 -- ...eset-controller-support-for-EN7523-S.patch | 133 ------- ...k-airoha-Add-reset-support-to-EN7523.patch | 35 -- ...k-airoha-Update-reg-mapping-for-EN75.patch | 74 ---- ...k-airoha-Add-reset-support-to-EN7523.patch | 81 ---- ...ck-drop-NUM_CLOCKS-define-for-EN7581.patch | 26 -- ...ngs-clock-add-ID-for-eMMC-for-EN7581.patch | 25 -- ...emove-unnecessary-restriction-length.patch | 33 -- ...e-unnecessary-switch-to-non-dma-mode.patch | 30 -- ...-airoha-unify-dirmap-read-write-code.patch | 137 ------- ...rt-of-dualio-quadio-flash-reading-co.patch | 94 ----- ...-setting-of-page-oob-sizes-in-REG_SP.patch | 64 --- ...e-the-number-of-modification-of-REG_.patch | 199 ---------- ...ustom-sector-size-equal-to-flash-pag.patch | 142 ------- ...-reading-flash-page-settings-from-SN.patch | 206 ---------- ...uffer-must-be-0xff-ed-before-writing.patch | 32 -- .../100-econet-add-en7528-soc.patch | 119 ------ .../101-econet-timer-add-en7528-support.patch | 264 ------------- ...for-the-Airoha-EN7523-SoC-SPI-contro.patch | 341 ---------------- ...pi-Airoha-adapt-to-support-en75-mips.patch | 56 --- ...03-spi-airoha-snfi-enable-for-econet.patch | 21 - .../310-usb-enable-econet-usb.patch | 21 - ...0-gpio-en7523-enable-for-econet-mips.patch | 17 - .../886-uart-add-en7523-support.patch | 206 ---------- .../887-uart-airoha-add-econet-support.patch | 18 - .../901-nand-enable-en75-bbt.patch | 40 -- .../902-snand-mtk-bmt-support.patch | 34 -- ...k-reset-add-econet-en751221-bindings.patch | 176 --------- ...conet-en751221-clock-reset-support-t.patch | 364 ----------------- ...pcie-add-en7528-pcie-and-phy-support.patch | 373 ------------------ .../913-pcie-fix-bogus-prefetch-window.patch | 38 -- .../914-phy-add-en7528-usb-phy-driver.patch | 358 ----------------- ...-usb-xhci-mtk-add-en7528-ltssm-quirk.patch | 58 --- 52 files changed, 1 insertion(+), 6297 deletions(-) delete mode 100644 target/linux/econet/en751221/config-6.12 delete mode 100644 target/linux/econet/en751627/config-6.12 delete mode 100644 target/linux/econet/en7528/config-6.12 delete mode 100644 target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch delete mode 100644 target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch delete mode 100644 target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch delete mode 100644 target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch delete mode 100644 target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch delete mode 100644 target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch delete mode 100644 target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch delete mode 100644 target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch delete mode 100644 target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch delete mode 100644 target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch delete mode 100644 target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch delete mode 100644 target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch delete mode 100644 target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch delete mode 100644 target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch delete mode 100644 target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch delete mode 100644 target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch delete mode 100644 target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch delete mode 100644 target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch delete mode 100644 target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch delete mode 100644 target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch delete mode 100644 target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch delete mode 100644 target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch delete mode 100644 target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch delete mode 100644 target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch delete mode 100644 target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch delete mode 100644 target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch delete mode 100644 target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch delete mode 100644 target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch delete mode 100644 target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch delete mode 100644 target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch delete mode 100644 target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch delete mode 100644 target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch delete mode 100644 target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch delete mode 100644 target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch delete mode 100644 target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch delete mode 100644 target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch delete mode 100644 target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch delete mode 100644 target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch delete mode 100644 target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch delete mode 100644 target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch delete mode 100644 target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch delete mode 100644 target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch delete mode 100644 target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch delete mode 100644 target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch delete mode 100644 target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch delete mode 100644 target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch delete mode 100644 target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch delete mode 100644 target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch diff --git a/target/linux/econet/Makefile b/target/linux/econet/Makefile index 2341f6b70d..a895827ef9 100644 --- a/target/linux/econet/Makefile +++ b/target/linux/econet/Makefile @@ -9,8 +9,7 @@ BOARDNAME:=EcoNet EN75xx MIPS FEATURES:=dt source-only squashfs nand usb SUBTARGETS:=en751221 en751627 en7528 -KERNEL_PATCHVER:=6.12 -KERNEL_TESTING_PATCHVER:=6.18 +KERNEL_PATCHVER:=6.18 define Target/Description Build firmware image for EcoNet EN75xx MIPS based boards. diff --git a/target/linux/econet/en751221/config-6.12 b/target/linux/econet/en751221/config-6.12 deleted file mode 100644 index fe69f10c74..0000000000 --- a/target/linux/econet/en751221/config-6.12 +++ /dev/null @@ -1,209 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_BLK_MQ_PCI=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_EN7523=y -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_DIEI=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS32_R1 is not set -CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPSR2=y -CONFIG_CPU_MITIGATIONS=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_GF128MUL=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_ZBOOT=y -CONFIG_DMA_NEED_SYNC=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTB_ECONET_NONE=y -# CONFIG_DTB_ECONET_SMARTFIBER_XP8421_B is not set -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_EARLY_PRINTK_8250=y -CONFIG_ECONET=y -CONFIG_ECONET_EN751221_INTC=y -CONFIG_ECONET_EN751221_TIMER=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_FS_IOMAP=y -CONFIG_FUNCTION_ALIGNMENT=0 -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GPIO_CDEV=y -# CONFIG_GPIO_EN7523 is not set -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_ZLIB=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=2 -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MIPS_SPRAM=y -CONFIG_MMU_LAZY_TLB_REFCOUNT=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_MTK_BMT=y -CONFIG_MTD_SPI_NAND=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=13 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SRCU_NMI_SAFE=y -CONFIG_NET_EGRESS=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_INGRESS=y -CONFIG_NET_XGRESS=y -CONFIG_NR_CPUS=2 -CONFIG_NVMEM=y -CONFIG_NVMEM_LAYOUTS=y -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_PADATA=y -CONFIG_PAGE_POOL=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_MEDIATEK=y -CONFIG_PCI_DISABLE_COMMON_QUIRKS=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_DRIVERS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_ARCH_FALLBACKS=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHY_EN7528_PCIE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SERIAL_8250_AIROHA is not set -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_ECONET_EN751221=y -# CONFIG_SOC_ECONET_EN7528 is not set -CONFIG_SPI=y -CONFIG_SPI_AIROHA_EN7523=y -# CONFIG_SPI_AIROHA_SNFI is not set -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_MIPS16=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_SYS_SUPPORTS_ZBOOT=y -CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y -CONFIG_TARGET_ISA_REV=2 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB_SUPPORT=y -CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y -CONFIG_USE_OF=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZBOOT_LOAD_ADDRESS=0x80020000 -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/econet/en751627/config-6.12 b/target/linux/econet/en751627/config-6.12 deleted file mode 100644 index 5e7b280d72..0000000000 --- a/target/linux/econet/en751627/config-6.12 +++ /dev/null @@ -1,239 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BOARD_SCACHE=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_EN7523=y -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_DIEI=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS32_R1 is not set -CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPSR2=y -CONFIG_CPU_MIPSR2_IRQ_EI=y -CONFIG_CPU_MIPSR2_IRQ_VI=y -CONFIG_CPU_MITIGATIONS=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_GF128MUL=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LIB_SHA1=y -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_ZBOOT=y -CONFIG_DMA_NEED_SYNC=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTB_ECONET_NONE=y -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_EARLY_PRINTK_8250=y -CONFIG_ECONET=y -CONFIG_ECONET_EN751221_TIMER=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_FS_IOMAP=y -CONFIG_FUNCTION_ALIGNMENT=0 -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_EN7523=y -CONFIG_GPIO_GENERIC=y -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_JFFS2_FS is not set -CONFIG_LEDS_GPIO=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CM=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_CPC=y -CONFIG_MIPS_CPS=y -# CONFIG_MIPS_CPS_NS16550_BOOL is not set -CONFIG_MIPS_CPU_SCACHE=y -CONFIG_MIPS_GIC=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_MIPS_MT=y -CONFIG_MIPS_MT_FPAFF=y -CONFIG_MIPS_MT_SMP=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=4 -CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MIPS_SPRAM=y -CONFIG_MMU_LAZY_TLB_REFCOUNT=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_MTK_BMT=y -CONFIG_MTD_SPI_NAND=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=13 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SRCU_NMI_SAFE=y -CONFIG_NET_EGRESS=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_INGRESS=y -CONFIG_NET_XGRESS=y -CONFIG_NLS=y -CONFIG_NR_CPUS=4 -CONFIG_NVMEM=y -CONFIG_NVMEM_LAYOUTS=y -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_PADATA=y -CONFIG_PAGE_POOL=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -CONFIG_PCI=y -CONFIG_PCIE_MEDIATEK=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_DRIVERS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_ARCH_FALLBACKS=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHY_EN7528_PCIE=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SCHED_CORE is not set -CONFIG_SCHED_SMT=y -CONFIG_SERIAL_8250_AIROHA=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -# CONFIG_SOC_ECONET_EN751221 is not set -CONFIG_SOC_ECONET_EN7528=y -CONFIG_SPI=y -# CONFIG_SPI_AIROHA_EN7523 is not set -CONFIG_SPI_AIROHA_SNFI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPLIT_PTE_PTLOCKS=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HIGHMEM=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_MIPS16=y -CONFIG_SYS_SUPPORTS_MIPS_CPS=y -CONFIG_SYS_SUPPORTS_MULTITHREADING=y -CONFIG_SYS_SUPPORTS_SCHED_SMT=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_SYS_SUPPORTS_ZBOOT=y -CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y -CONFIG_TARGET_ISA_REV=2 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB=y -CONFIG_USB_COMMON=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_MTK=y -# CONFIG_USB_XHCI_PLATFORM is not set -CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y -CONFIG_USE_OF=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZBOOT_LOAD_ADDRESS=0x80020000 -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/econet/en7528/config-6.12 b/target/linux/econet/en7528/config-6.12 deleted file mode 100644 index f577834028..0000000000 --- a/target/linux/econet/en7528/config-6.12 +++ /dev/null @@ -1,241 +0,0 @@ -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MMAP_RND_BITS_MAX=15 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BOARD_SCACHE=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_EN7523=y -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -CONFIG_CPU_GENERIC_DUMP_TLB=y -CONFIG_CPU_HAS_DIEI=y -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_CPU_HAS_RIXI=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS32_R1 is not set -CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPSR2=y -CONFIG_CPU_MIPSR2_IRQ_EI=y -CONFIG_CPU_MIPSR2_IRQ_VI=y -CONFIG_CPU_MITIGATIONS=y -CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y -CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_CPU_SUPPORTS_MSA=y -CONFIG_CRC16=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_GF128MUL=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_ZBOOT=y -CONFIG_DMA_NEED_SYNC=y -CONFIG_DMA_NONCOHERENT=y -CONFIG_DTB_ECONET_NONE=y -CONFIG_DTC=y -CONFIG_EARLY_PRINTK=y -CONFIG_EARLY_PRINTK_8250=y -CONFIG_ECONET=y -CONFIG_ECONET_EN751221_TIMER=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_FS_IOMAP=y -CONFIG_FUNCTION_ALIGNMENT=0 -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_LIB_ASHLDI3=y -CONFIG_GENERIC_LIB_ASHRDI3=y -CONFIG_GENERIC_LIB_CMPDI2=y -CONFIG_GENERIC_LIB_LSHRDI3=y -CONFIG_GENERIC_LIB_UCMPDI2=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_EN7523=y -CONFIG_GPIO_GENERIC=y -CONFIG_HARDWARE_WATCHPOINTS=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HZ_PERIODIC=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MIPS_CPU=y -CONFIG_IRQ_WORK=y -# CONFIG_JFFS2_FS is not set -CONFIG_LEDS_GPIO=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -CONFIG_MIPS=y -CONFIG_MIPS_ASID_BITS=8 -CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CM=y -# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set -CONFIG_MIPS_CMDLINE_FROM_DTB=y -CONFIG_MIPS_CPC=y -CONFIG_MIPS_CPS=y -# CONFIG_MIPS_CPS_NS16550_BOOL is not set -CONFIG_MIPS_CPU_SCACHE=y -CONFIG_MIPS_GIC=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_MIPS_MT=y -CONFIG_MIPS_MT_FPAFF=y -CONFIG_MIPS_MT_SMP=y -# CONFIG_MIPS_NO_APPENDED_DTB is not set -CONFIG_MIPS_NR_CPU_NR_MAP=4 -CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y -CONFIG_MIPS_RAW_APPENDED_DTB=y -CONFIG_MIPS_SPRAM=y -CONFIG_MMU_LAZY_TLB_REFCOUNT=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_MTK_BMT=y -CONFIG_MTD_SPI_NAND=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=13 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SRCU_NMI_SAFE=y -CONFIG_NET_EGRESS=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_INGRESS=y -CONFIG_NET_XGRESS=y -CONFIG_NLS=y -CONFIG_NR_CPUS=4 -CONFIG_NVMEM=y -CONFIG_NVMEM_LAYOUTS=y -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_PADATA=y -CONFIG_PAGE_POOL=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -CONFIG_PCI=y -CONFIG_PCIE_MEDIATEK=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_DRIVERS_GENERIC=y -CONFIG_PCI_MSI=y -CONFIG_PCI_MSI_ARCH_FALLBACKS=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHY_EN7528_PCIE=y -CONFIG_PHY_EN7528_USB=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -# CONFIG_SCHED_CORE is not set -CONFIG_SCHED_SMT=y -CONFIG_SERIAL_8250_AIROHA=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SGL_ALLOC=y -CONFIG_SMP=y -CONFIG_SMP_UP=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -# CONFIG_SOC_ECONET_EN751221 is not set -CONFIG_SOC_ECONET_EN7528=y -CONFIG_SPI=y -# CONFIG_SPI_AIROHA_EN7523 is not set -CONFIG_SPI_AIROHA_SNFI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPLIT_PTE_PTLOCKS=y -CONFIG_SYNC_R4K=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_SYS_HAS_EARLY_PRINTK=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_HIGHMEM=y -CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_SYS_SUPPORTS_MIPS16=y -CONFIG_SYS_SUPPORTS_MIPS_CPS=y -CONFIG_SYS_SUPPORTS_MULTITHREADING=y -CONFIG_SYS_SUPPORTS_SCHED_SMT=y -CONFIG_SYS_SUPPORTS_SMP=y -CONFIG_SYS_SUPPORTS_ZBOOT=y -CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y -CONFIG_TARGET_ISA_REV=2 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_USB=y -CONFIG_USB_COMMON=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_MTK=y -# CONFIG_USB_XHCI_PLATFORM is not set -CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y -CONFIG_USE_OF=y -CONFIG_WEAK_ORDERING=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZBOOT_LOAD_ADDRESS=0x80020000 -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch b/target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch deleted file mode 100644 index c146af679a..0000000000 --- a/target/linux/econet/patches-6.12/001-v6.16-dt-bindings-interrupt-controller-Add-EcoNet-EN751221.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 9773c540441c6ae15aefb49e67142e94369dbbc0 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Sun, 30 Mar 2025 17:02:58 +0000 -Subject: [PATCH] dt-bindings: interrupt-controller: Add EcoNet EN751221 INTC - -Document the device tree binding for the interrupt controller in the -EcoNet EN751221 MIPS SoC. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Gleixner -Reviewed-by: Rob Herring (Arm) -Link: https://lore.kernel.org/all/20250330170306.2584136-3-cjd@cjdns.fr ---- - .../econet,en751221-intc.yaml | 78 +++++++++++++++++++ - 1 file changed, 78 insertions(+) - create mode 100644 Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml -@@ -0,0 +1,78 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/interrupt-controller/econet,en751221-intc.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet EN751221 Interrupt Controller -+ -+maintainers: -+ - Caleb James DeLisle -+ -+description: -+ The EcoNet EN751221 Interrupt Controller is a simple interrupt controller -+ designed for the MIPS 34Kc MT SMP processor with 2 VPEs. Each interrupt can -+ be routed to either VPE but not both, so to support per-CPU interrupts, a -+ secondary IRQ number is allocated to control masking/unmasking on VPE#1. For -+ lack of a better term we call these "shadow interrupts". The assignment of -+ shadow interrupts is defined by the SoC integrator when wiring the interrupt -+ lines, so they are configurable in the device tree. -+ -+allOf: -+ - $ref: /schemas/interrupt-controller.yaml# -+ -+properties: -+ compatible: -+ const: econet,en751221-intc -+ -+ reg: -+ maxItems: 1 -+ -+ "#interrupt-cells": -+ const: 1 -+ -+ interrupt-controller: true -+ -+ interrupts: -+ maxItems: 1 -+ description: Interrupt line connecting this controller to its parent. -+ -+ econet,shadow-interrupts: -+ $ref: /schemas/types.yaml#/definitions/uint32-matrix -+ description: -+ An array of interrupt number pairs where each pair represents a shadow -+ interrupt relationship. The first number in each pair is the primary IRQ, -+ and the second is its shadow IRQ used for VPE#1 control. For example, -+ <8 3> means IRQ 8 is shadowed by IRQ 3, so IRQ 3 cannot be mapped, but -+ when VPE#1 requests IRQ 8, it will manipulate the IRQ 3 mask bit. -+ minItems: 1 -+ maxItems: 20 -+ items: -+ items: -+ - description: primary per-CPU IRQ -+ - description: shadow IRQ number -+ -+required: -+ - compatible -+ - reg -+ - interrupt-controller -+ - "#interrupt-cells" -+ - interrupts -+ -+additionalProperties: false -+ -+examples: -+ - | -+ interrupt-controller@1fb40000 { -+ compatible = "econet,en751221-intc"; -+ reg = <0x1fb40000 0x100>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ -+ interrupt-parent = <&cpuintc>; -+ interrupts = <2>; -+ -+ econet,shadow-interrupts = <7 2>, <8 3>, <13 12>, <30 29>; -+ }; -+... diff --git a/target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch b/target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch deleted file mode 100644 index d3f57f4e7f..0000000000 --- a/target/linux/econet/patches-6.12/002-v6.16-irqchip-Add-EcoNet-EN751221-INTC.patch +++ /dev/null @@ -1,353 +0,0 @@ -From 1902a59cf5f9d8b99ecf0cb8f122cb00ef7a3f13 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Sun, 30 Mar 2025 17:02:59 +0000 -Subject: [PATCH] irqchip: Add EcoNet EN751221 INTC - -Add a driver for the interrupt controller in the EcoNet EN751221 MIPS SoC. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Gleixner -Link: https://lore.kernel.org/all/20250330170306.2584136-4-cjd@cjdns.fr ---- - drivers/irqchip/Kconfig | 5 + - drivers/irqchip/Makefile | 1 + - drivers/irqchip/irq-econet-en751221.c | 309 ++++++++++++++++++++++++++ - 3 files changed, 315 insertions(+) - create mode 100644 drivers/irqchip/irq-econet-en751221.c - ---- a/drivers/irqchip/Kconfig -+++ b/drivers/irqchip/Kconfig -@@ -148,6 +148,11 @@ config DW_APB_ICTL - select GENERIC_IRQ_CHIP - select IRQ_DOMAIN_HIERARCHY - -+config ECONET_EN751221_INTC -+ bool -+ select GENERIC_IRQ_CHIP -+ select IRQ_DOMAIN -+ - config FARADAY_FTINTC010 - bool - select IRQ_DOMAIN ---- a/drivers/irqchip/Makefile -+++ b/drivers/irqchip/Makefile -@@ -10,6 +10,7 @@ obj-$(CONFIG_ARCH_BCM2835) += irq-bcm28 - obj-$(CONFIG_ARCH_ACTIONS) += irq-owl-sirq.o - obj-$(CONFIG_DAVINCI_CP_INTC) += irq-davinci-cp-intc.o - obj-$(CONFIG_EXYNOS_IRQ_COMBINER) += exynos-combiner.o -+obj-$(CONFIG_ECONET_EN751221_INTC) += irq-econet-en751221.o - obj-$(CONFIG_FARADAY_FTINTC010) += irq-ftintc010.o - obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o - obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o ---- /dev/null -+++ b/drivers/irqchip/irq-econet-en751221.c -@@ -0,0 +1,309 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * EN751221 Interrupt Controller Driver. -+ * -+ * The EcoNet EN751221 Interrupt Controller is a simple interrupt controller -+ * designed for the MIPS 34Kc MT SMP processor with 2 VPEs. Each interrupt can -+ * be routed to either VPE but not both, so to support per-CPU interrupts, a -+ * secondary IRQ number is allocated to control masking/unmasking on VPE#1. In -+ * this driver, these are called "shadow interrupts". The assignment of shadow -+ * interrupts is defined by the SoC integrator when wiring the interrupt lines, -+ * so they are configurable in the device tree. -+ * -+ * If an interrupt (say 30) needs per-CPU capability, the SoC integrator -+ * allocates another IRQ number (say 29) to be its shadow. The device tree -+ * reflects this by adding the pair <30 29> to the "econet,shadow-interrupts" -+ * property. -+ * -+ * When VPE#1 requests IRQ 30, the driver manipulates the mask bit for IRQ 29, -+ * telling the hardware to mask VPE#1's view of IRQ 30. -+ * -+ * Copyright (C) 2025 Caleb James DeLisle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define IRQ_COUNT 40 -+ -+#define NOT_PERCPU 0xff -+#define IS_SHADOW 0xfe -+ -+#define REG_MASK0 0x04 -+#define REG_MASK1 0x50 -+#define REG_PENDING0 0x08 -+#define REG_PENDING1 0x54 -+ -+/** -+ * @membase: Base address of the interrupt controller registers -+ * @interrupt_shadows: Array of all interrupts, for each value, -+ * - NOT_PERCPU: This interrupt is not per-cpu, so it has no shadow -+ * - IS_SHADOW: This interrupt is a shadow of another per-cpu interrupt -+ * - else: This is a per-cpu interrupt whose shadow is the value -+ */ -+static struct { -+ void __iomem *membase; -+ u8 interrupt_shadows[IRQ_COUNT]; -+} econet_intc __ro_after_init; -+ -+static DEFINE_RAW_SPINLOCK(irq_lock); -+ -+/* IRQs must be disabled */ -+static void econet_wreg(u32 reg, u32 val, u32 mask) -+{ -+ u32 v; -+ -+ guard(raw_spinlock)(&irq_lock); -+ -+ v = ioread32(econet_intc.membase + reg); -+ v &= ~mask; -+ v |= val & mask; -+ iowrite32(v, econet_intc.membase + reg); -+} -+ -+/* IRQs must be disabled */ -+static void econet_chmask(u32 hwirq, bool unmask) -+{ -+ u32 reg, mask; -+ u8 shadow; -+ -+ /* -+ * If the IRQ is a shadow, it should never be manipulated directly. -+ * It should only be masked/unmasked as a result of the "real" per-cpu -+ * irq being manipulated by a thread running on VPE#1. -+ * If it is per-cpu (has a shadow), and we're on VPE#1, the shadow is what we mask. -+ * This is single processor only, so smp_processor_id() never exceeds 1. -+ */ -+ shadow = econet_intc.interrupt_shadows[hwirq]; -+ if (WARN_ON_ONCE(shadow == IS_SHADOW)) -+ return; -+ else if (shadow != NOT_PERCPU && smp_processor_id() == 1) -+ hwirq = shadow; -+ -+ if (hwirq >= 32) { -+ reg = REG_MASK1; -+ mask = BIT(hwirq - 32); -+ } else { -+ reg = REG_MASK0; -+ mask = BIT(hwirq); -+ } -+ -+ econet_wreg(reg, unmask ? mask : 0, mask); -+} -+ -+/* IRQs must be disabled */ -+static void econet_intc_mask(struct irq_data *d) -+{ -+ econet_chmask(d->hwirq, false); -+} -+ -+/* IRQs must be disabled */ -+static void econet_intc_unmask(struct irq_data *d) -+{ -+ econet_chmask(d->hwirq, true); -+} -+ -+static void econet_mask_all(void) -+{ -+ /* IRQs are generally disabled during init, but guarding here makes it non-obligatory. */ -+ guard(irqsave)(); -+ econet_wreg(REG_MASK0, 0, ~0); -+ econet_wreg(REG_MASK1, 0, ~0); -+} -+ -+static void econet_intc_handle_pending(struct irq_domain *d, u32 pending, u32 offset) -+{ -+ int hwirq; -+ -+ while (pending) { -+ hwirq = fls(pending) - 1; -+ generic_handle_domain_irq(d, hwirq + offset); -+ pending &= ~BIT(hwirq); -+ } -+} -+ -+static void econet_intc_from_parent(struct irq_desc *desc) -+{ -+ struct irq_chip *chip = irq_desc_get_chip(desc); -+ struct irq_domain *domain; -+ u32 pending0, pending1; -+ -+ chained_irq_enter(chip, desc); -+ -+ pending0 = ioread32(econet_intc.membase + REG_PENDING0); -+ pending1 = ioread32(econet_intc.membase + REG_PENDING1); -+ -+ if (unlikely(!(pending0 | pending1))) { -+ spurious_interrupt(); -+ } else { -+ domain = irq_desc_get_handler_data(desc); -+ econet_intc_handle_pending(domain, pending0, 0); -+ econet_intc_handle_pending(domain, pending1, 32); -+ } -+ -+ chained_irq_exit(chip, desc); -+} -+ -+static const struct irq_chip econet_irq_chip; -+ -+static int econet_intc_map(struct irq_domain *d, u32 irq, irq_hw_number_t hwirq) -+{ -+ int ret; -+ -+ if (hwirq >= IRQ_COUNT) { -+ pr_err("%s: hwirq %lu out of range\n", __func__, hwirq); -+ return -EINVAL; -+ } else if (econet_intc.interrupt_shadows[hwirq] == IS_SHADOW) { -+ pr_err("%s: can't map hwirq %lu, it is a shadow interrupt\n", __func__, hwirq); -+ return -EINVAL; -+ } -+ -+ if (econet_intc.interrupt_shadows[hwirq] == NOT_PERCPU) { -+ irq_set_chip_and_handler(irq, &econet_irq_chip, handle_level_irq); -+ } else { -+ irq_set_chip_and_handler(irq, &econet_irq_chip, handle_percpu_devid_irq); -+ ret = irq_set_percpu_devid(irq); -+ if (ret) -+ pr_warn("%s: Failed irq_set_percpu_devid for %u: %d\n", d->name, irq, ret); -+ } -+ -+ irq_set_chip_data(irq, NULL); -+ return 0; -+} -+ -+static const struct irq_chip econet_irq_chip = { -+ .name = "en751221-intc", -+ .irq_unmask = econet_intc_unmask, -+ .irq_mask = econet_intc_mask, -+ .irq_mask_ack = econet_intc_mask, -+}; -+ -+static const struct irq_domain_ops econet_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = econet_intc_map -+}; -+ -+static int __init get_shadow_interrupts(struct device_node *node) -+{ -+ const char *field = "econet,shadow-interrupts"; -+ int num_shadows; -+ -+ num_shadows = of_property_count_u32_elems(node, field); -+ -+ memset(econet_intc.interrupt_shadows, NOT_PERCPU, -+ sizeof(econet_intc.interrupt_shadows)); -+ -+ if (num_shadows <= 0) { -+ return 0; -+ } else if (num_shadows % 2) { -+ pr_err("%pOF: %s count is odd, ignoring\n", node, field); -+ return 0; -+ } -+ -+ u32 *shadows __free(kfree) = kmalloc_array(num_shadows, sizeof(u32), GFP_KERNEL); -+ if (!shadows) -+ return -ENOMEM; -+ -+ if (of_property_read_u32_array(node, field, shadows, num_shadows)) { -+ pr_err("%pOF: Failed to read %s\n", node, field); -+ return -EINVAL; -+ } -+ -+ for (int i = 0; i < num_shadows; i += 2) { -+ u32 shadow = shadows[i + 1]; -+ u32 target = shadows[i]; -+ -+ if (shadow > IRQ_COUNT) { -+ pr_err("%pOF: %s[%d] shadow(%d) out of range\n", -+ node, field, i + 1, shadow); -+ continue; -+ } -+ -+ if (target >= IRQ_COUNT) { -+ pr_err("%pOF: %s[%d] target(%d) out of range\n", node, field, i, target); -+ continue; -+ } -+ -+ if (econet_intc.interrupt_shadows[target] != NOT_PERCPU) { -+ pr_err("%pOF: %s[%d] target(%d) already has a shadow\n", -+ node, field, i, target); -+ continue; -+ } -+ -+ if (econet_intc.interrupt_shadows[shadow] != NOT_PERCPU) { -+ pr_err("%pOF: %s[%d] shadow(%d) already has a target\n", -+ node, field, i + 1, shadow); -+ continue; -+ } -+ -+ econet_intc.interrupt_shadows[target] = shadow; -+ econet_intc.interrupt_shadows[shadow] = IS_SHADOW; -+ } -+ -+ return 0; -+} -+ -+static int __init econet_intc_of_init(struct device_node *node, struct device_node *parent) -+{ -+ struct irq_domain *domain; -+ struct resource res; -+ int ret, irq; -+ -+ ret = get_shadow_interrupts(node); -+ if (ret) -+ return ret; -+ -+ irq = irq_of_parse_and_map(node, 0); -+ if (!irq) { -+ pr_err("%pOF: DT: Failed to get IRQ from 'interrupts'\n", node); -+ return -EINVAL; -+ } -+ -+ if (of_address_to_resource(node, 0, &res)) { -+ pr_err("%pOF: DT: Failed to get 'reg'\n", node); -+ ret = -EINVAL; -+ goto err_dispose_mapping; -+ } -+ -+ if (!request_mem_region(res.start, resource_size(&res), res.name)) { -+ pr_err("%pOF: Failed to request memory\n", node); -+ ret = -EBUSY; -+ goto err_dispose_mapping; -+ } -+ -+ econet_intc.membase = ioremap(res.start, resource_size(&res)); -+ if (!econet_intc.membase) { -+ pr_err("%pOF: Failed to remap membase\n", node); -+ ret = -ENOMEM; -+ goto err_release; -+ } -+ -+ econet_mask_all(); -+ -+ domain = irq_domain_add_linear(node, IRQ_COUNT, &econet_domain_ops, NULL); -+ if (!domain) { -+ pr_err("%pOF: Failed to add irqdomain\n", node); -+ ret = -ENOMEM; -+ goto err_unmap; -+ } -+ -+ irq_set_chained_handler_and_data(irq, econet_intc_from_parent, domain); -+ -+ return 0; -+ -+err_unmap: -+ iounmap(econet_intc.membase); -+err_release: -+ release_mem_region(res.start, resource_size(&res)); -+err_dispose_mapping: -+ irq_dispose_mapping(irq); -+ return ret; -+} -+ -+IRQCHIP_DECLARE(econet_en751221_intc, "econet,en751221-intc", econet_intc_of_init); diff --git a/target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch b/target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch deleted file mode 100644 index e2466782d1..0000000000 --- a/target/linux/econet/patches-6.12/003-v6.16-dt-bindings-vendor-prefixes-Add-EcoNet.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 9e0dd98654a528735d2b363d0dc73f7904108652 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Sun, 30 Mar 2025 17:02:57 +0000 -Subject: [PATCH] dt-bindings: vendor-prefixes: Add EcoNet - -Add the "econet" vendor prefix for SoC maker - -Signed-off-by: Caleb James DeLisle -Acked-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250330170306.2584136-2-cjd@cjdns.fr -Signed-off-by: Rob Herring (Arm) ---- - Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/Documentation/devicetree/bindings/vendor-prefixes.yaml -+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml -@@ -420,6 +420,8 @@ patternProperties: - description: EBV Elektronik - "^eckelmann,.*": - description: Eckelmann AG -+ "^econet,.*": -+ description: EcoNet (HK) Limited - "^edgeble,.*": - description: Edgeble AI Technologies Pvt. Ltd. - "^edimax,.*": diff --git a/target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch b/target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch deleted file mode 100644 index 92f8604ea2..0000000000 --- a/target/linux/econet/patches-6.12/004-v6.16-dt-bindings-timer-Add-EcoNet-EN751221-HPT-CPU-Timer.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 30fddbd5325459102e448c9a26a1bc15ef563381 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:54 +0000 -Subject: [PATCH] dt-bindings: timer: Add EcoNet EN751221 "HPT" CPU Timer - -Add device tree bindings for the so-called high-precision timer (HPT) -in the EcoNet EN751221 SoC. - -Signed-off-by: Caleb James DeLisle -Reviewed-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250507134500.390547-2-cjd@cjdns.fr -Signed-off-by: Daniel Lezcano ---- - .../bindings/timer/econet,en751221-timer.yaml | 80 +++++++++++++++++++ - 1 file changed, 80 insertions(+) - create mode 100644 Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml -@@ -0,0 +1,80 @@ -+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/timer/econet,en751221-timer.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet EN751221 High Precision Timer (HPT) -+ -+maintainers: -+ - Caleb James DeLisle -+ -+description: -+ The EcoNet High Precision Timer (HPT) is a timer peripheral found in various -+ EcoNet SoCs, including the EN751221 and EN751627 families. It provides per-VPE -+ count/compare registers and a per-CPU control register, with a single interrupt -+ line using a percpu-devid interrupt mechanism. -+ -+properties: -+ compatible: -+ oneOf: -+ - const: econet,en751221-timer -+ - items: -+ - const: econet,en751627-timer -+ - const: econet,en751221-timer -+ -+ reg: -+ minItems: 1 -+ maxItems: 2 -+ -+ interrupts: -+ maxItems: 1 -+ description: A percpu-devid timer interrupt shared across CPUs. -+ -+ clocks: -+ maxItems: 1 -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ - clocks -+ -+allOf: -+ - if: -+ properties: -+ compatible: -+ contains: -+ const: econet,en751627-timer -+ then: -+ properties: -+ reg: -+ items: -+ - description: VPE timers 0 and 1 -+ - description: VPE timers 2 and 3 -+ else: -+ properties: -+ reg: -+ items: -+ - description: VPE timers 0 and 1 -+ -+additionalProperties: false -+ -+examples: -+ - | -+ timer@1fbf0400 { -+ compatible = "econet,en751627-timer", "econet,en751221-timer"; -+ reg = <0x1fbf0400 0x100>, <0x1fbe0000 0x100>; -+ interrupt-parent = <&intc>; -+ interrupts = <30>; -+ clocks = <&hpt_clock>; -+ }; -+ - | -+ timer@1fbf0400 { -+ compatible = "econet,en751221-timer"; -+ reg = <0x1fbe0400 0x100>; -+ interrupt-parent = <&intc>; -+ interrupts = <30>; -+ clocks = <&hpt_clock>; -+ }; -+... diff --git a/target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch b/target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch deleted file mode 100644 index dcd4bb15e3..0000000000 --- a/target/linux/econet/patches-6.12/005-v6.16-clocksource-drivers-Add-EcoNet-Timer-HPT-driver.patch +++ /dev/null @@ -1,276 +0,0 @@ -From 3b4c33ac87d0d11308f4445ecec2a124e2e77724 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:55 +0000 -Subject: [PATCH] clocksource/drivers: Add EcoNet Timer HPT driver - -Introduce a clocksource driver for the so-called high-precision timer (HPT) -in the EcoNet EN751221 and EN751627 MIPS SoCs. - -It's a 32 bit upward-counting one-shot timer which relies on the crystal so it -is unaffected by CPU power mode. On MIPS 34K devices (single core) there is -one timer, and on 1004K devices (dual core) there are two. - -Each timer has two sets of count/compare registers so that there is one for -each of the VPEs on the core. Because each core has 2 VPEs, register selection -takes the CPU number / 2 for the timer corrisponding to the core, then CPU -number % 2 for the register corrisponding to the VPE. - -These timers use a percpu-devid IRQ to route interrupts to the VPE which set -the event. - -Signed-off-by: Caleb James DeLisle -Link: https://lore.kernel.org/r/20250507134500.390547-3-cjd@cjdns.fr -Signed-off-by: Daniel Lezcano ---- - drivers/clocksource/Kconfig | 8 + - drivers/clocksource/Makefile | 1 + - drivers/clocksource/timer-econet-en751221.c | 216 ++++++++++++++++++++ - 3 files changed, 225 insertions(+) - create mode 100644 drivers/clocksource/timer-econet-en751221.c - ---- a/drivers/clocksource/Kconfig -+++ b/drivers/clocksource/Kconfig -@@ -73,6 +73,14 @@ config DW_APB_TIMER_OF - select DW_APB_TIMER - select TIMER_OF - -+config ECONET_EN751221_TIMER -+ bool "EcoNet EN751221 High Precision Timer" if COMPILE_TEST -+ depends on HAS_IOMEM -+ select CLKSRC_MMIO -+ select TIMER_OF -+ help -+ Support for CPU timer found on EcoNet MIPS based SoCs. -+ - config FTTMR010_TIMER - bool "Faraday Technology timer driver" if COMPILE_TEST - depends on HAS_IOMEM ---- a/drivers/clocksource/Makefile -+++ b/drivers/clocksource/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_CLKBLD_I8253) += i8253.o - obj-$(CONFIG_CLKSRC_MMIO) += mmio.o - obj-$(CONFIG_DAVINCI_TIMER) += timer-davinci.o - obj-$(CONFIG_DIGICOLOR_TIMER) += timer-digicolor.o -+obj-$(CONFIG_ECONET_EN751221_TIMER) += timer-econet-en751221.o - obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o - obj-$(CONFIG_OMAP_DM_SYSTIMER) += timer-ti-dm-systimer.o - obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o ---- /dev/null -+++ b/drivers/clocksource/timer-econet-en751221.c -@@ -0,0 +1,216 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Timer present on EcoNet EN75xx MIPS based SoCs. -+ * -+ * Copyright (C) 2025 by Caleb James DeLisle -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define ECONET_BITS 32 -+#define ECONET_MIN_DELTA 0x00001000 -+#define ECONET_MAX_DELTA GENMASK(ECONET_BITS - 2, 0) -+/* 34Kc hardware has 1 block and 1004Kc has 2. */ -+#define ECONET_NUM_BLOCKS DIV_ROUND_UP(NR_CPUS, 2) -+ -+static struct { -+ void __iomem *membase[ECONET_NUM_BLOCKS]; -+ u32 freq_hz; -+} econet_timer __ro_after_init; -+ -+static DEFINE_PER_CPU(struct clock_event_device, econet_timer_pcpu); -+ -+/* Each memory block has 2 timers, the order of registers is: -+ * CTL, CMR0, CNT0, CMR1, CNT1 -+ */ -+static inline void __iomem *reg_ctl(u32 timer_n) -+{ -+ return econet_timer.membase[timer_n >> 1]; -+} -+ -+static inline void __iomem *reg_compare(u32 timer_n) -+{ -+ return econet_timer.membase[timer_n >> 1] + (timer_n & 1) * 0x08 + 0x04; -+} -+ -+static inline void __iomem *reg_count(u32 timer_n) -+{ -+ return econet_timer.membase[timer_n >> 1] + (timer_n & 1) * 0x08 + 0x08; -+} -+ -+static inline u32 ctl_bit_enabled(u32 timer_n) -+{ -+ return 1U << (timer_n & 1); -+} -+ -+static inline u32 ctl_bit_pending(u32 timer_n) -+{ -+ return 1U << ((timer_n & 1) + 16); -+} -+ -+static bool cevt_is_pending(int cpu_id) -+{ -+ return ioread32(reg_ctl(cpu_id)) & ctl_bit_pending(cpu_id); -+} -+ -+static irqreturn_t cevt_interrupt(int irq, void *dev_id) -+{ -+ struct clock_event_device *dev = this_cpu_ptr(&econet_timer_pcpu); -+ int cpu = cpumask_first(dev->cpumask); -+ -+ /* Each VPE has its own events, -+ * so this will only happen on spurious interrupt. -+ */ -+ if (!cevt_is_pending(cpu)) -+ return IRQ_NONE; -+ -+ iowrite32(ioread32(reg_count(cpu)), reg_compare(cpu)); -+ dev->event_handler(dev); -+ return IRQ_HANDLED; -+} -+ -+static int cevt_set_next_event(ulong delta, struct clock_event_device *dev) -+{ -+ u32 next; -+ int cpu; -+ -+ cpu = cpumask_first(dev->cpumask); -+ next = ioread32(reg_count(cpu)) + delta; -+ iowrite32(next, reg_compare(cpu)); -+ -+ if ((s32)(next - ioread32(reg_count(cpu))) < ECONET_MIN_DELTA / 2) -+ return -ETIME; -+ -+ return 0; -+} -+ -+static int cevt_init_cpu(uint cpu) -+{ -+ struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, cpu); -+ u32 reg; -+ -+ pr_debug("%s: Setting up clockevent for CPU %d\n", cd->name, cpu); -+ -+ reg = ioread32(reg_ctl(cpu)) | ctl_bit_enabled(cpu); -+ iowrite32(reg, reg_ctl(cpu)); -+ -+ enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); -+ -+ /* Do this last because it synchronously configures the timer */ -+ clockevents_config_and_register(cd, econet_timer.freq_hz, -+ ECONET_MIN_DELTA, ECONET_MAX_DELTA); -+ -+ return 0; -+} -+ -+static u64 notrace sched_clock_read(void) -+{ -+ /* Always read from clock zero no matter the CPU */ -+ return (u64)ioread32(reg_count(0)); -+} -+ -+/* Init */ -+ -+static void __init cevt_dev_init(uint cpu) -+{ -+ iowrite32(0, reg_count(cpu)); -+ iowrite32(U32_MAX, reg_compare(cpu)); -+} -+ -+static int __init cevt_init(struct device_node *np) -+{ -+ int i, irq, ret; -+ -+ irq = irq_of_parse_and_map(np, 0); -+ if (irq <= 0) { -+ pr_err("%pOFn: irq_of_parse_and_map failed", np); -+ return -EINVAL; -+ } -+ -+ ret = request_percpu_irq(irq, cevt_interrupt, np->name, &econet_timer_pcpu); -+ -+ if (ret < 0) { -+ pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, irq, ret); -+ goto err_unmap_irq; -+ } -+ -+ for_each_possible_cpu(i) { -+ struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i); -+ -+ cd->rating = 310, -+ cd->features = CLOCK_EVT_FEAT_ONESHOT | -+ CLOCK_EVT_FEAT_C3STOP | -+ CLOCK_EVT_FEAT_PERCPU; -+ cd->set_next_event = cevt_set_next_event; -+ cd->irq = irq; -+ cd->cpumask = cpumask_of(i); -+ cd->name = np->name; -+ -+ cevt_dev_init(i); -+ } -+ -+ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, -+ "clockevents/econet/timer:starting", -+ cevt_init_cpu, NULL); -+ return 0; -+ -+err_unmap_irq: -+ irq_dispose_mapping(irq); -+ return ret; -+} -+ -+static int __init timer_init(struct device_node *np) -+{ -+ int num_blocks = DIV_ROUND_UP(num_possible_cpus(), 2); -+ struct clk *clk; -+ int ret; -+ -+ clk = of_clk_get(np, 0); -+ if (IS_ERR(clk)) { -+ pr_err("%pOFn: Failed to get CPU clock from DT %ld\n", np, PTR_ERR(clk)); -+ return PTR_ERR(clk); -+ } -+ -+ econet_timer.freq_hz = clk_get_rate(clk); -+ -+ for (int i = 0; i < num_blocks; i++) { -+ econet_timer.membase[i] = of_iomap(np, i); -+ if (!econet_timer.membase[i]) { -+ pr_err("%pOFn: failed to map register [%d]\n", np, i); -+ return -ENXIO; -+ } -+ } -+ -+ /* For clocksource purposes always read clock zero, whatever the CPU */ -+ ret = clocksource_mmio_init(reg_count(0), np->name, -+ econet_timer.freq_hz, 301, ECONET_BITS, -+ clocksource_mmio_readl_up); -+ if (ret) { -+ pr_err("%pOFn: clocksource_mmio_init failed: %d", np, ret); -+ return ret; -+ } -+ -+ ret = cevt_init(np); -+ if (ret < 0) -+ return ret; -+ -+ sched_clock_register(sched_clock_read, ECONET_BITS, -+ econet_timer.freq_hz); -+ -+ pr_info("%pOFn: using %u.%03u MHz high precision timer\n", np, -+ econet_timer.freq_hz / 1000000, -+ (econet_timer.freq_hz / 1000) % 1000); -+ -+ return 0; -+} -+ -+TIMER_OF_DECLARE(econet_timer_hpt, "econet,en751221-timer", timer_init); diff --git a/target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch b/target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch deleted file mode 100644 index 64714dc8a2..0000000000 --- a/target/linux/econet/patches-6.12/006-v6.16-dt-bindings-mips-Add-EcoNet-platform-binding.patch +++ /dev/null @@ -1,44 +0,0 @@ -From be8b4173719a61fdd8379e86895d855775cf5f91 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:56 +0000 -Subject: [PATCH] dt-bindings: mips: Add EcoNet platform binding - -Document the top-level device tree binding for EcoNet MIPS-based SoCs. - -Signed-off-by: Caleb James DeLisle -Reviewed-by: Krzysztof Kozlowski -Signed-off-by: Thomas Bogendoerfer ---- - .../devicetree/bindings/mips/econet.yaml | 26 +++++++++++++++++++ - 1 file changed, 26 insertions(+) - create mode 100644 Documentation/devicetree/bindings/mips/econet.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/mips/econet.yaml -@@ -0,0 +1,26 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/mips/econet.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet MIPS SoCs -+ -+maintainers: -+ - Caleb James DeLisle -+ -+properties: -+ $nodename: -+ const: '/' -+ -+ compatible: -+ oneOf: -+ - description: Boards with EcoNet EN751221 family SoC -+ items: -+ - enum: -+ - smartfiber,xp8421-b -+ - const: econet,en751221 -+ -+additionalProperties: true -+ -+... diff --git a/target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch b/target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch deleted file mode 100644 index 86b05b07a1..0000000000 --- a/target/linux/econet/patches-6.12/007-v6.16-mips-Add-EcoNet-MIPS-platform-support.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 35fb26f94dfa1b291086b84b2421f957214824d1 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:57 +0000 -Subject: [PATCH] mips: Add EcoNet MIPS platform support - -Add platform support for EcoNet MIPS SoCs. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/Kbuild.platforms | 1 + - arch/mips/Kconfig | 25 +++++++++ - arch/mips/boot/compressed/uart-16550.c | 5 ++ - arch/mips/econet/Kconfig | 37 ++++++++++++ - arch/mips/econet/Makefile | 2 + - arch/mips/econet/Platform | 5 ++ - arch/mips/econet/init.c | 78 ++++++++++++++++++++++++++ - 7 files changed, 153 insertions(+) - create mode 100644 arch/mips/econet/Kconfig - create mode 100644 arch/mips/econet/Makefile - create mode 100644 arch/mips/econet/Platform - create mode 100644 arch/mips/econet/init.c - ---- a/arch/mips/Kbuild.platforms -+++ b/arch/mips/Kbuild.platforms -@@ -11,6 +11,7 @@ platform-$(CONFIG_CAVIUM_OCTEON_SOC) += - platform-$(CONFIG_EYEQ) += mobileye/ - platform-$(CONFIG_MIPS_COBALT) += cobalt/ - platform-$(CONFIG_MACH_DECSTATION) += dec/ -+platform-$(CONFIG_ECONET) += econet/ - platform-$(CONFIG_MIPS_GENERIC) += generic/ - platform-$(CONFIG_MACH_JAZZ) += jazz/ - platform-$(CONFIG_LANTIQ) += lantiq/ ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -388,6 +388,30 @@ config MACH_DECSTATION - - otherwise choose R3000. - -+config ECONET -+ bool "EcoNet MIPS family" -+ select BOOT_RAW -+ select CPU_BIG_ENDIAN -+ select DEBUG_ZBOOT -+ select EARLY_PRINTK_8250 -+ select ECONET_EN751221_TIMER -+ select SERIAL_OF_PLATFORM -+ select SYS_SUPPORTS_BIG_ENDIAN -+ select SYS_HAS_CPU_MIPS32_R1 -+ select SYS_HAS_CPU_MIPS32_R2 -+ select SYS_HAS_EARLY_PRINTK -+ select SYS_SUPPORTS_32BIT_KERNEL -+ select SYS_SUPPORTS_MIPS16 -+ select SYS_SUPPORTS_ZBOOT_UART16550 -+ select USE_GENERIC_EARLY_PRINTK_8250 -+ select USE_OF -+ help -+ EcoNet EN75xx MIPS devices are big endian MIPS machines used -+ in XPON (fiber) and DSL applications. They have SPI, PCI, USB, -+ GPIO, and Ethernet, with optional XPON, DSL, and VoIP DSP cores. -+ Don't confuse these with the Airoha ARM devices sometimes referred -+ to as "EcoNet", this family is for MIPS based devices only. -+ - config MACH_JAZZ - bool "Jazz family of machines" - select ARC_MEMORY -@@ -1017,6 +1041,7 @@ source "arch/mips/ath79/Kconfig" - source "arch/mips/bcm47xx/Kconfig" - source "arch/mips/bcm63xx/Kconfig" - source "arch/mips/bmips/Kconfig" -+source "arch/mips/econet/Kconfig" - source "arch/mips/generic/Kconfig" - source "arch/mips/ingenic/Kconfig" - source "arch/mips/jazz/Kconfig" ---- a/arch/mips/boot/compressed/uart-16550.c -+++ b/arch/mips/boot/compressed/uart-16550.c -@@ -20,6 +20,11 @@ - #define PORT(offset) (CKSEG1ADDR(INGENIC_UART_BASE_ADDR) + (4 * offset)) - #endif - -+#ifdef CONFIG_ECONET -+#define EN75_UART_BASE 0x1fbf0003 -+#define PORT(offset) (CKSEG1ADDR(EN75_UART_BASE) + (4 * (offset))) -+#endif -+ - #ifndef IOTYPE - #define IOTYPE char - #endif ---- /dev/null -+++ b/arch/mips/econet/Kconfig -@@ -0,0 +1,37 @@ -+# SPDX-License-Identifier: GPL-2.0 -+if ECONET -+ -+choice -+ prompt "EcoNet SoC selection" -+ default SOC_ECONET_EN751221 -+ help -+ Select EcoNet MIPS SoC type. Individual SoCs within a family are -+ very similar, so is it enough to select the right family, and -+ then customize to the specific SoC using the device tree only. -+ -+ config SOC_ECONET_EN751221 -+ bool "EN751221 family" -+ select COMMON_CLK -+ select ECONET_EN751221_INTC -+ select IRQ_MIPS_CPU -+ select SMP -+ select SMP_UP -+ select SYS_SUPPORTS_SMP -+ help -+ The EN751221 family includes EN7512, RN7513, EN7521, EN7526. -+ They are based on single core MIPS 34Kc processors. To boot -+ this kernel, you will need a device tree such as -+ MIPS_RAW_APPENDED_DTB=y, and a root filesystem. -+endchoice -+ -+choice -+ prompt "Devicetree selection" -+ default DTB_ECONET_NONE -+ help -+ Select the devicetree. -+ -+ config DTB_ECONET_NONE -+ bool "None" -+endchoice -+ -+endif ---- /dev/null -+++ b/arch/mips/econet/Makefile -@@ -0,0 +1,2 @@ -+ -+obj-y := init.o ---- /dev/null -+++ b/arch/mips/econet/Platform -@@ -0,0 +1,5 @@ -+# To address a 7.2MB kernel size limit in the EcoNet SDK bootloader, -+# we put the load address well above where the bootloader loads and then use -+# zboot. So please set CONFIG_ZBOOT_LOAD_ADDRESS to the address where your -+# bootloader actually places the kernel. -+load-$(CONFIG_ECONET) += 0xffffffff81000000 ---- /dev/null -+++ b/arch/mips/econet/init.c -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * EcoNet setup code -+ * -+ * Copyright (C) 2025 Caleb James DeLisle -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CR_AHB_RSTCR ((void __iomem *)CKSEG1ADDR(0x1fb00040)) -+#define RESET BIT(31) -+ -+#define UART_BASE CKSEG1ADDR(0x1fbf0003) -+#define UART_REG_SHIFT 2 -+ -+static void hw_reset(char *command) -+{ -+ iowrite32(RESET, CR_AHB_RSTCR); -+} -+ -+/* 1. Bring up early printk. */ -+void __init prom_init(void) -+{ -+ setup_8250_early_printk_port(UART_BASE, UART_REG_SHIFT, 0); -+ _machine_restart = hw_reset; -+} -+ -+/* 2. Parse the DT and find memory */ -+void __init plat_mem_setup(void) -+{ -+ void *dtb; -+ -+ set_io_port_base(KSEG1); -+ -+ dtb = get_fdt(); -+ if (!dtb) -+ panic("no dtb found"); -+ -+ __dt_setup_arch(dtb); -+ -+ early_init_dt_scan_memory(); -+} -+ -+/* 3. Overload __weak device_tree_init(), add SMP_UP ops */ -+void __init device_tree_init(void) -+{ -+ unflatten_and_copy_device_tree(); -+ -+ register_up_smp_ops(); -+} -+ -+const char *get_system_type(void) -+{ -+ return "EcoNet-EN75xx"; -+} -+ -+/* 4. Initialize the IRQ subsystem */ -+void __init arch_init_irq(void) -+{ -+ irqchip_init(); -+} -+ -+/* 5. Timers */ -+void __init plat_time_init(void) -+{ -+ of_clk_init(NULL); -+ timer_probe(); -+} diff --git a/target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch b/target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch deleted file mode 100644 index 6d51af0231..0000000000 --- a/target/linux/econet/patches-6.12/008-v6.16-dt-bindings-vendor-prefixes-Add-SmartFiber.patch +++ /dev/null @@ -1,29 +0,0 @@ -From abc2d0bc2cb7c1412b8b254c0446f94b3e203c7c Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:58 +0000 -Subject: [PATCH] dt-bindings: vendor-prefixes: Add SmartFiber -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add "smartfiber" vendor prefix for manufactorer of EcoNet based boards. - -Signed-off-by: Caleb James DeLisle -Acked-by: Krzysztof Kozlowski -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Thomas Bogendoerfer ---- - Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/Documentation/devicetree/bindings/vendor-prefixes.yaml -+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml -@@ -1370,6 +1370,8 @@ patternProperties: - description: SKOV A/S - "^skyworks,.*": - description: Skyworks Solutions, Inc. -+ "^smartfiber,.*": -+ description: ShenZhen Smartfiber Technology Co, Ltd. - "^smartlabs,.*": - description: SmartLabs LLC - "^smartrg,.*": diff --git a/target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch b/target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch deleted file mode 100644 index cb5b457137..0000000000 --- a/target/linux/econet/patches-6.12/009-v6.16-mips-dts-Add-EcoNet-DTS-with-EN751221-and-SmartFiber.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0ec4887009729297f7c10368084e41a8a9fbbd0e Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:44:59 +0000 -Subject: [PATCH] mips: dts: Add EcoNet DTS with EN751221 and SmartFiber - XP8421-B board - -Add DTS files in support of EcoNet platform, including SmartFiber XP8421-B, -a low cost commercially available board based on EN751221. - -Signed-off-by: Caleb James DeLisle -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/boot/dts/Makefile | 1 + - arch/mips/boot/dts/econet/Makefile | 2 + - arch/mips/boot/dts/econet/en751221.dtsi | 67 +++++++++++++++++++ - .../econet/en751221_smartfiber_xp8421-b.dts | 19 ++++++ - arch/mips/econet/Kconfig | 11 +++ - 5 files changed, 100 insertions(+) - create mode 100644 arch/mips/boot/dts/econet/Makefile - create mode 100644 arch/mips/boot/dts/econet/en751221.dtsi - create mode 100644 arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts - ---- a/arch/mips/boot/dts/Makefile -+++ b/arch/mips/boot/dts/Makefile -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - subdir-$(CONFIG_BMIPS_GENERIC) += brcm - subdir-$(CONFIG_CAVIUM_OCTEON_SOC) += cavium-octeon -+subdir-$(CONFIG_ECONET) += econet - subdir-$(CONFIG_EYEQ) += mobileye - subdir-$(CONFIG_FIT_IMAGE_FDT_MARDUK) += img - subdir-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += img ---- /dev/null -+++ b/arch/mips/boot/dts/econet/Makefile -@@ -0,0 +1,2 @@ -+# SPDX-License-Identifier: GPL-2.0 -+dtb-$(CONFIG_DTB_ECONET_SMARTFIBER_XP8421_B) += en751221_smartfiber_xp8421-b.dtb ---- /dev/null -+++ b/arch/mips/boot/dts/econet/en751221.dtsi -@@ -0,0 +1,67 @@ -+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+/dts-v1/; -+ -+/ { -+ compatible = "econet,en751221"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ hpt_clock: clock { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <200000000>; /* 200 MHz */ -+ }; -+ -+ cpus: cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "mips,mips24KEc"; -+ reg = <0>; -+ }; -+ }; -+ -+ cpuintc: interrupt-controller { -+ compatible = "mti,cpu-interrupt-controller"; -+ interrupt-controller; -+ #address-cells = <0>; -+ #interrupt-cells = <1>; -+ }; -+ -+ intc: interrupt-controller@1fb40000 { -+ compatible = "econet,en751221-intc"; -+ reg = <0x1fb40000 0x100>; -+ interrupt-parent = <&cpuintc>; -+ interrupts = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <1>; -+ econet,shadow-interrupts = <7 2>, <8 3>, <13 12>, <30 29>; -+ }; -+ -+ uart: serial@1fbf0000 { -+ compatible = "ns16550"; -+ reg = <0x1fbf0000 0x30>; -+ reg-io-width = <4>; -+ reg-shift = <2>; -+ interrupt-parent = <&intc>; -+ interrupts = <0>; -+ /* -+ * Conversion of baud rate to clock frequency requires a -+ * computation that is not in the ns16550 driver, so this -+ * uart is fixed at 115200 baud. -+ */ -+ clock-frequency = <1843200>; -+ }; -+ -+ timer_hpt: timer@1fbf0400 { -+ compatible = "econet,en751221-timer"; -+ reg = <0x1fbf0400 0x100>; -+ -+ interrupt-parent = <&intc>; -+ interrupts = <30>; -+ clocks = <&hpt_clock>; -+ }; -+}; ---- /dev/null -+++ b/arch/mips/boot/dts/econet/en751221_smartfiber_xp8421-b.dts -@@ -0,0 +1,19 @@ -+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+/dts-v1/; -+ -+#include "en751221.dtsi" -+ -+/ { -+ model = "SmartFiber XP8421-B"; -+ compatible = "smartfiber,xp8421-b", "econet,en751221"; -+ -+ memory@0 { -+ device_type = "memory"; -+ reg = <0x00000000 0x1c000000>; -+ }; -+ -+ chosen { -+ stdout-path = "/serial@1fbf0000:115200"; -+ linux,usable-memory-range = <0x00020000 0x1bfe0000>; -+ }; -+}; ---- a/arch/mips/econet/Kconfig -+++ b/arch/mips/econet/Kconfig -@@ -32,6 +32,17 @@ choice - - config DTB_ECONET_NONE - bool "None" -+ -+ config DTB_ECONET_SMARTFIBER_XP8421_B -+ bool "EN751221 SmartFiber XP8421-B" -+ depends on SOC_ECONET_EN751221 -+ select BUILTIN_DTB -+ help -+ The SmartFiber XP8421-B is a device based on the EN751221 SoC. -+ It has 512MB of memory and 256MB of NAND flash. This kernel -+ needs only an appended initramfs to boot. It can be loaded -+ through XMODEM and booted from memory in the bootloader, or -+ it can be packed in tclinux.trx format and written to flash. - endchoice - - endif diff --git a/target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch b/target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch deleted file mode 100644 index e4230573c2..0000000000 --- a/target/linux/econet/patches-6.12/010-v6.16-MAINTAINERS-Add-entry-for-newly-added-EcoNet-platfor.patch +++ /dev/null @@ -1,38 +0,0 @@ -From faefb0a59c5914b7b8f737e2ec5c82822e5bc4c7 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 7 May 2025 13:45:00 +0000 -Subject: [PATCH] MAINTAINERS: Add entry for newly added EcoNet platform. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add a MAINTAINERS entry as part of integration of the EcoNet MIPS platform. - -Signed-off-by: Caleb James DeLisle -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Thomas Bogendoerfer ---- - MAINTAINERS | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -8025,6 +8025,18 @@ W: https://linuxtv.org - Q: http://patchwork.linuxtv.org/project/linux-media/list/ - F: drivers/media/dvb-frontends/ec100* - -+ECONET MIPS PLATFORM -+M: Caleb James DeLisle -+L: linux-mips@vger.kernel.org -+S: Maintained -+F: Documentation/devicetree/bindings/interrupt-controller/econet,en751221-intc.yaml -+F: Documentation/devicetree/bindings/mips/econet.yaml -+F: Documentation/devicetree/bindings/timer/econet,en751221-timer.yaml -+F: arch/mips/boot/dts/econet/ -+F: arch/mips/econet/ -+F: drivers/clocksource/timer-econet-en751221.c -+F: drivers/irqchip/irq-econet-en751221.c -+ - ECRYPT FILE SYSTEM - M: Tyler Hicks - L: ecryptfs@vger.kernel.org diff --git a/target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch b/target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch deleted file mode 100644 index fe9e6792eb..0000000000 --- a/target/linux/econet/patches-6.12/011-v6.16-mips-econet-Fix-incorrect-Kconfig-dependencies.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 79ee1d20e37cd553cc961962fca8107e69a0c293 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 21 May 2025 21:33:33 +0000 -Subject: [PATCH] mips: econet: Fix incorrect Kconfig dependencies - -config ECONET selects SERIAL_OF_PLATFORM and that depends on SERIAL_8250 -so we need to select SERIAL_8250 directly. -Also do not enable DEBUG_ZBOOT unless DEBUG_KERNEL is set. - -Signed-off-by: Caleb James DeLisle -Reported-by: kernel test robot -Closes: https://lore.kernel.org/oe-kbuild-all/202505211654.CBdIsoTq-lkp@intel.com/ -Closes: https://lore.kernel.org/oe-kbuild-all/202505211451.WRjyf3a9-lkp@intel.com/ -Signed-off-by: Thomas Bogendoerfer ---- - arch/mips/Kconfig | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -392,9 +392,10 @@ config ECONET - bool "EcoNet MIPS family" - select BOOT_RAW - select CPU_BIG_ENDIAN -- select DEBUG_ZBOOT -+ select DEBUG_ZBOOT if DEBUG_KERNEL - select EARLY_PRINTK_8250 - select ECONET_EN751221_TIMER -+ select SERIAL_8250 - select SERIAL_OF_PLATFORM - select SYS_SUPPORTS_BIG_ENDIAN - select SYS_HAS_CPU_MIPS32_R1 diff --git a/target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch b/target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch deleted file mode 100644 index 26b3da9c4d..0000000000 --- a/target/linux/econet/patches-6.12/012-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 82e6bf912d5846646892becea659b39d178d79e3 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 12 Nov 2024 01:08:53 +0100 -Subject: [PATCH 5/8] clk: en7523: move en7581_reset_register() in - en7581_clk_hw_init() - -Move en7581_reset_register routine in en7581_clk_hw_init() since reset -feature is supported just by EN7581 SoC. -Get rid of reset struct in en_clk_soc_data data struct. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-6-8ada5e394ae4@kernel.org -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 93 ++++++++++++++-------------------------- - 1 file changed, 33 insertions(+), 60 deletions(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -76,11 +76,6 @@ struct en_rst_data { - - struct en_clk_soc_data { - const struct clk_ops pcie_ops; -- struct { -- const u16 *bank_ofs; -- const u16 *idx_map; -- u16 idx_map_nr; -- } reset; - int (*hw_init)(struct platform_device *pdev, - struct clk_hw_onecell_data *clk_data); - }; -@@ -596,32 +591,6 @@ static void en7581_register_clocks(struc - clk_data->num = EN7523_NUM_CLOCKS; - } - --static int en7581_clk_hw_init(struct platform_device *pdev, -- struct clk_hw_onecell_data *clk_data) --{ -- void __iomem *np_base; -- struct regmap *map; -- u32 val; -- -- map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); -- if (IS_ERR(map)) -- return PTR_ERR(map); -- -- np_base = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(np_base)) -- return PTR_ERR(np_base); -- -- en7581_register_clocks(&pdev->dev, clk_data, map, np_base); -- -- val = readl(np_base + REG_NP_SCU_SSTR); -- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); -- writel(val, np_base + REG_NP_SCU_SSTR); -- val = readl(np_base + REG_NP_SCU_PCIC); -- writel(val | 3, np_base + REG_NP_SCU_PCIC); -- -- return 0; --} -- - static int en7523_reset_update(struct reset_controller_dev *rcdev, - unsigned long id, bool assert) - { -@@ -671,23 +640,18 @@ static int en7523_reset_xlate(struct res - return rst_data->idx_map[reset_spec->args[0]]; - } - --static const struct reset_control_ops en7523_reset_ops = { -+static const struct reset_control_ops en7581_reset_ops = { - .assert = en7523_reset_assert, - .deassert = en7523_reset_deassert, - .status = en7523_reset_status, - }; - --static int en7523_reset_register(struct platform_device *pdev, -- const struct en_clk_soc_data *soc_data) -+static int en7581_reset_register(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; - struct en_rst_data *rst_data; - void __iomem *base; - -- /* no reset lines available */ -- if (!soc_data->reset.idx_map_nr) -- return 0; -- - base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(base)) - return PTR_ERR(base); -@@ -696,13 +660,13 @@ static int en7523_reset_register(struct - if (!rst_data) - return -ENOMEM; - -- rst_data->bank_ofs = soc_data->reset.bank_ofs; -- rst_data->idx_map = soc_data->reset.idx_map; -+ rst_data->bank_ofs = en7581_rst_ofs; -+ rst_data->idx_map = en7581_rst_map; - rst_data->base = base; - -- rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr; -+ rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); - rst_data->rcdev.of_xlate = en7523_reset_xlate; -- rst_data->rcdev.ops = &en7523_reset_ops; -+ rst_data->rcdev.ops = &en7581_reset_ops; - rst_data->rcdev.of_node = dev->of_node; - rst_data->rcdev.of_reset_n_cells = 1; - rst_data->rcdev.owner = THIS_MODULE; -@@ -711,6 +675,32 @@ static int en7523_reset_register(struct - return devm_reset_controller_register(dev, &rst_data->rcdev); - } - -+static int en7581_clk_hw_init(struct platform_device *pdev, -+ struct clk_hw_onecell_data *clk_data) -+{ -+ void __iomem *np_base; -+ struct regmap *map; -+ u32 val; -+ -+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); -+ if (IS_ERR(map)) -+ return PTR_ERR(map); -+ -+ np_base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(np_base)) -+ return PTR_ERR(np_base); -+ -+ en7581_register_clocks(&pdev->dev, clk_data, map, np_base); -+ -+ val = readl(np_base + REG_NP_SCU_SSTR); -+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); -+ writel(val, np_base + REG_NP_SCU_SSTR); -+ val = readl(np_base + REG_NP_SCU_PCIC); -+ writel(val | 3, np_base + REG_NP_SCU_PCIC); -+ -+ return en7581_reset_register(pdev); -+} -+ - static int en7523_clk_probe(struct platform_device *pdev) - { - struct device_node *node = pdev->dev.of_node; -@@ -729,19 +719,7 @@ static int en7523_clk_probe(struct platf - if (r) - return r; - -- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); -- if (r) -- return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n", -- pdev->name); -- -- r = en7523_reset_register(pdev, soc_data); -- if (r) { -- of_clk_del_provider(node); -- return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n", -- pdev->name); -- } -- -- return 0; -+ return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); - } - - static const struct en_clk_soc_data en7523_data = { -@@ -759,11 +737,6 @@ static const struct en_clk_soc_data en75 - .enable = en7581_pci_enable, - .disable = en7581_pci_disable, - }, -- .reset = { -- .bank_ofs = en7581_rst_ofs, -- .idx_map = en7581_rst_map, -- .idx_map_nr = ARRAY_SIZE(en7581_rst_map), -- }, - .hw_init = en7581_clk_hw_init, - }; - diff --git a/target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch b/target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch deleted file mode 100644 index 4e4952d8a6..0000000000 --- a/target/linux/econet/patches-6.12/013-v6.13-clk-en7523-map-io-region-in-a-single-block.patch +++ /dev/null @@ -1,84 +0,0 @@ -From a9eaf305017a5ebe73ab34e85bd5414055a88f29 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 12 Nov 2024 01:08:54 +0100 -Subject: [PATCH 6/8] clk: en7523: map io region in a single block - -Map all clock-controller memory region in a single block. -This patch does not introduce any backward incompatibility since the dts -for EN7581 SoC is not upstream yet. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-7-8ada5e394ae4@kernel.org -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 32 +++++++++++++------------------- - 1 file changed, 13 insertions(+), 19 deletions(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -39,8 +39,8 @@ - #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) - #define REG_CRYPTO_CLKSRC2 0x20c - --#define REG_RST_CTRL2 0x00 --#define REG_RST_CTRL1 0x04 -+#define REG_RST_CTRL2 0x830 -+#define REG_RST_CTRL1 0x834 - - struct en_clk_desc { - int id; -@@ -646,15 +646,9 @@ static const struct reset_control_ops en - .status = en7523_reset_status, - }; - --static int en7581_reset_register(struct platform_device *pdev) -+static int en7581_reset_register(struct device *dev, void __iomem *base) - { -- struct device *dev = &pdev->dev; - struct en_rst_data *rst_data; -- void __iomem *base; -- -- base = devm_platform_ioremap_resource(pdev, 1); -- if (IS_ERR(base)) -- return PTR_ERR(base); - - rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); - if (!rst_data) -@@ -678,27 +672,27 @@ static int en7581_reset_register(struct - static int en7581_clk_hw_init(struct platform_device *pdev, - struct clk_hw_onecell_data *clk_data) - { -- void __iomem *np_base; - struct regmap *map; -+ void __iomem *base; - u32 val; - - map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); - if (IS_ERR(map)) - return PTR_ERR(map); - -- np_base = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(np_base)) -- return PTR_ERR(np_base); -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); - -- en7581_register_clocks(&pdev->dev, clk_data, map, np_base); -+ en7581_register_clocks(&pdev->dev, clk_data, map, base); - -- val = readl(np_base + REG_NP_SCU_SSTR); -+ val = readl(base + REG_NP_SCU_SSTR); - val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); -- writel(val, np_base + REG_NP_SCU_SSTR); -- val = readl(np_base + REG_NP_SCU_PCIC); -- writel(val | 3, np_base + REG_NP_SCU_PCIC); -+ writel(val, base + REG_NP_SCU_SSTR); -+ val = readl(base + REG_NP_SCU_PCIC); -+ writel(val | 3, base + REG_NP_SCU_PCIC); - -- return en7581_reset_register(pdev); -+ return en7581_reset_register(&pdev->dev, base); - } - - static int en7523_clk_probe(struct platform_device *pdev) diff --git a/target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch b/target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch deleted file mode 100644 index 44664202a8..0000000000 --- a/target/linux/econet/patches-6.12/014-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 90d4e466c9ea2010f33880a36317a8486ccbe082 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Wed, 8 Jan 2025 10:50:43 +0100 -Subject: [PATCH 1/3] PCI: mediatek-gen3: Move reset delay in - mtk_pcie_en7581_power_up() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal -causing occasional PCIe link down issues. In order to overcome the -problem, PCIe block is reset using REG_PCI_CONTROL (0x88) and -REG_RESET_CONTROL (0x834) registers available in the clock module -running clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up(). - -In order to make the code more readable, move the wait for the time -needed to complete the PCIe reset from en7581_pci_enable() to -mtk_pcie_en7581_power_up(). - -Reduce reset timeout from 250ms to the standard PCIE_T_PVPERL_MS value -(100ms) since it has no impact on the driver behavior. - -Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-4-21ac939a3b9b@kernel.org -Signed-off-by: Lorenzo Bianconi -Signed-off-by: Krzysztof Wilczyński -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Manivannan Sadhasivam -Acked-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -478,7 +478,6 @@ static int en7581_pci_enable(struct clk_ - REG_PCI_CONTROL_PERSTOUT; - val = readl(np_base + REG_PCI_CONTROL); - writel(val | mask, np_base + REG_PCI_CONTROL); -- msleep(250); - - return 0; - } diff --git a/target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch b/target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch deleted file mode 100644 index a33e842b9e..0000000000 --- a/target/linux/econet/patches-6.12/015-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch +++ /dev/null @@ -1,83 +0,0 @@ -From e4a9748e7103c47e575459db2b6a77d14f34da2b Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:02 +0100 -Subject: [PATCH 2/3] clk: en7523: Rework clock handling for different clock - numbers - -Airoha EN7581 SoC have additional clock compared to EN7523 but current -driver permits to only support up to EN7523 clock numbers. - -To handle this, rework the clock handling and permit to declare the -clocks number in match_data and alloca clk_data based on the compatible -match_data. - -Signed-off-by: Christian Marangi -Link: https://lore.kernel.org/r/20250113231030.6735-2-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 14 ++++++++------ - 1 file changed, 8 insertions(+), 6 deletions(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -75,6 +75,7 @@ struct en_rst_data { - }; - - struct en_clk_soc_data { -+ u32 num_clocks; - const struct clk_ops pcie_ops; - int (*hw_init)(struct platform_device *pdev, - struct clk_hw_onecell_data *clk_data); -@@ -503,8 +504,6 @@ static void en7523_register_clocks(struc - u32 rate; - int i; - -- clk_data->num = EN7523_NUM_CLOCKS; -- - for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { - const struct en_clk_desc *desc = &en7523_base_clks[i]; - u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg; -@@ -586,8 +585,6 @@ static void en7581_register_clocks(struc - - hw = en7523_register_pcie_clk(dev, base); - clk_data->hws[EN7523_CLK_PCIE] = hw; -- -- clk_data->num = EN7523_NUM_CLOCKS; - } - - static int en7523_reset_update(struct reset_controller_dev *rcdev, -@@ -701,13 +698,15 @@ static int en7523_clk_probe(struct platf - struct clk_hw_onecell_data *clk_data; - int r; - -+ soc_data = device_get_match_data(&pdev->dev); -+ - clk_data = devm_kzalloc(&pdev->dev, -- struct_size(clk_data, hws, EN7523_NUM_CLOCKS), -+ struct_size(clk_data, hws, soc_data->num_clocks), - GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - -- soc_data = device_get_match_data(&pdev->dev); -+ clk_data->num = soc_data->num_clocks; - r = soc_data->hw_init(pdev, clk_data); - if (r) - return r; -@@ -716,6 +715,7 @@ static int en7523_clk_probe(struct platf - } - - static const struct en_clk_soc_data en7523_data = { -+ .num_clocks = ARRAY_SIZE(en7523_base_clks) + 1, - .pcie_ops = { - .is_enabled = en7523_pci_is_enabled, - .prepare = en7523_pci_prepare, -@@ -725,6 +725,8 @@ static const struct en_clk_soc_data en75 - }; - - static const struct en_clk_soc_data en7581_data = { -+ /* We increment num_clocks by 1 to account for additional PCIe clock */ -+ .num_clocks = ARRAY_SIZE(en7581_base_clks) + 1, - .pcie_ops = { - .is_enabled = en7581_pci_is_enabled, - .enable = en7581_pci_enable, diff --git a/target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch b/target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch deleted file mode 100644 index 35d34a5ccf..0000000000 --- a/target/linux/econet/patches-6.12/016-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch +++ /dev/null @@ -1,41 +0,0 @@ -From bfe257f9780d8f77045a7da6ec959ee0659d2f98 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:05 +0100 -Subject: [PATCH 3/3] clk: en7523: Add clock for eMMC for EN7581 - -Add clock for eMMC for EN7581. This is used to give info of the current -eMMC source clock and to switch it from 200MHz or 150MHz. - -Signed-off-by: Christian Marangi -Link: https://lore.kernel.org/r/20250113231030.6735-5-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -91,6 +91,7 @@ static const u32 emi7581_base[] = { 5400 - static const u32 bus7581_base[] = { 600000000, 540000000 }; - static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; - static const u32 crypto_base[] = { 540000000, 480000000 }; -+static const u32 emmc7581_base[] = { 200000000, 150000000 }; - - static const struct en_clk_desc en7523_base_clks[] = { - { -@@ -281,6 +282,15 @@ static const struct en_clk_desc en7581_b - .base_shift = 0, - .base_values = crypto_base, - .n_base_values = ARRAY_SIZE(crypto_base), -+ }, { -+ .id = EN7581_CLK_EMMC, -+ .name = "emmc", -+ -+ .base_reg = REG_CRYPTO_CLKSRC2, -+ .base_bits = 1, -+ .base_shift = 12, -+ .base_values = emmc7581_base, -+ .n_base_values = ARRAY_SIZE(emmc7581_base), - } - }; - diff --git a/target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch b/target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch deleted file mode 100644 index c332cef387..0000000000 --- a/target/linux/econet/patches-6.12/017-v6.19rc1-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 1c0608d860db973ad09b5a9ccb19b76ae07622a3 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Mon, 10 Nov 2025 06:56:44 +0300 -Subject: [PATCH] clk: en7523: Add reset-controller support for EN7523 SoC - -Introduce reset API support to EN7523 clock driver. EN7523 uses the -same reset logic as EN7581, so just reuse existing code. - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: AngeloGioacchino Del Regno -Reviewed-by: Philipp Zabel -Signed-off-by: Stephen Boyd ---- - drivers/clk/clk-en7523.c | 64 ++++++++++++++++++++++++++++++++++++---- - 1 file changed, 59 insertions(+), 5 deletions(-) - ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - - #define RST_NR_PER_BANK 32 -@@ -299,6 +300,53 @@ static const u16 en7581_rst_ofs[] = { - REG_RST_CTRL1, - }; - -+static const u16 en7523_rst_map[] = { -+ /* RST_CTRL2 */ -+ [EN7523_XPON_PHY_RST] = 0, -+ [EN7523_XSI_MAC_RST] = 7, -+ [EN7523_XSI_PHY_RST] = 8, -+ [EN7523_NPU_RST] = 9, -+ [EN7523_I2S_RST] = 10, -+ [EN7523_TRNG_RST] = 11, -+ [EN7523_TRNG_MSTART_RST] = 12, -+ [EN7523_DUAL_HSI0_RST] = 13, -+ [EN7523_DUAL_HSI1_RST] = 14, -+ [EN7523_HSI_RST] = 15, -+ [EN7523_DUAL_HSI0_MAC_RST] = 16, -+ [EN7523_DUAL_HSI1_MAC_RST] = 17, -+ [EN7523_HSI_MAC_RST] = 18, -+ [EN7523_WDMA_RST] = 19, -+ [EN7523_WOE0_RST] = 20, -+ [EN7523_WOE1_RST] = 21, -+ [EN7523_HSDMA_RST] = 22, -+ [EN7523_I2C2RBUS_RST] = 23, -+ [EN7523_TDMA_RST] = 24, -+ /* RST_CTRL1 */ -+ [EN7523_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0, -+ [EN7523_FE_PDMA_RST] = RST_NR_PER_BANK + 1, -+ [EN7523_FE_QDMA_RST] = RST_NR_PER_BANK + 2, -+ [EN7523_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4, -+ [EN7523_CRYPTO_RST] = RST_NR_PER_BANK + 6, -+ [EN7523_TIMER_RST] = RST_NR_PER_BANK + 8, -+ [EN7523_PCM1_RST] = RST_NR_PER_BANK + 11, -+ [EN7523_UART_RST] = RST_NR_PER_BANK + 12, -+ [EN7523_GPIO_RST] = RST_NR_PER_BANK + 13, -+ [EN7523_GDMA_RST] = RST_NR_PER_BANK + 14, -+ [EN7523_I2C_MASTER_RST] = RST_NR_PER_BANK + 16, -+ [EN7523_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17, -+ [EN7523_SFC_RST] = RST_NR_PER_BANK + 18, -+ [EN7523_UART2_RST] = RST_NR_PER_BANK + 19, -+ [EN7523_GDMP_RST] = RST_NR_PER_BANK + 20, -+ [EN7523_FE_RST] = RST_NR_PER_BANK + 21, -+ [EN7523_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22, -+ [EN7523_GSW_RST] = RST_NR_PER_BANK + 23, -+ [EN7523_SFC2_PCM_RST] = RST_NR_PER_BANK + 25, -+ [EN7523_PCIE0_RST] = RST_NR_PER_BANK + 26, -+ [EN7523_PCIE1_RST] = RST_NR_PER_BANK + 27, -+ [EN7523_PCIE_HB_RST] = RST_NR_PER_BANK + 29, -+ [EN7523_XPON_MAC_RST] = RST_NR_PER_BANK + 31, -+}; -+ - static const u16 en7581_rst_map[] = { - /* RST_CTRL2 */ - [EN7581_XPON_PHY_RST] = 0, -@@ -357,6 +405,9 @@ static const u16 en7581_rst_map[] = { - [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31, - }; - -+static int en7581_reset_register(struct device *dev, void __iomem *base, -+ const u16 *rst_map, int nr_resets); -+ - static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) - { - if (!desc->base_bits) -@@ -552,7 +603,8 @@ static int en7523_clk_hw_init(struct pla - - en7523_register_clocks(&pdev->dev, clk_data, base, np_base); - -- return 0; -+ return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map, -+ ARRAY_SIZE(en7523_rst_map)); - } - - static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, -@@ -652,7 +704,8 @@ static const struct reset_control_ops en - .status = en7523_reset_status, - }; - --static int en7581_reset_register(struct device *dev, void __iomem *base) -+static int en7581_reset_register(struct device *dev, void __iomem *base, -+ const u16 *rst_map, int nr_resets) - { - struct en_rst_data *rst_data; - -@@ -661,10 +714,10 @@ static int en7581_reset_register(struct - return -ENOMEM; - - rst_data->bank_ofs = en7581_rst_ofs; -- rst_data->idx_map = en7581_rst_map; -+ rst_data->idx_map = rst_map; - rst_data->base = base; - -- rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); -+ rst_data->rcdev.nr_resets = nr_resets; - rst_data->rcdev.of_xlate = en7523_reset_xlate; - rst_data->rcdev.ops = &en7581_reset_ops; - rst_data->rcdev.of_node = dev->of_node; -@@ -698,7 +751,8 @@ static int en7581_clk_hw_init(struct pla - val = readl(base + REG_NP_SCU_PCIC); - writel(val | 3, base + REG_NP_SCU_PCIC); - -- return en7581_reset_register(&pdev->dev, base); -+ return en7581_reset_register(&pdev->dev, base, en7581_rst_map, -+ ARRAY_SIZE(en7581_rst_map)); - } - - static int en7523_clk_probe(struct platform_device *pdev) diff --git a/target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch b/target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch deleted file mode 100644 index ef56753c9b..0000000000 --- a/target/linux/econet/patches-6.12/018-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 947643509279a605a09959a06d332bf027e8be57 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Mon, 10 Nov 2025 06:56:43 +0300 -Subject: [PATCH] dt-bindings: clock: airoha: Add reset support to EN7523 clock - binding - -Introduce reset capability to EN7523 device-tree clock binding -documentation. - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: Rob Herring (Arm) -Signed-off-by: Stephen Boyd ---- - Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml -+++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml -@@ -64,8 +64,6 @@ allOf: - - description: scu base address - - description: misc scu base address - -- '#reset-cells': false -- - - if: - properties: - compatible: -@@ -89,6 +87,7 @@ examples: - reg = <0x1fa20000 0x400>, - <0x1fb00000 0x1000>; - #clock-cells = <1>; -+ #reset-cells = <1>; - }; - - - | diff --git a/target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch b/target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch deleted file mode 100644 index a4af01dd20..0000000000 --- a/target/linux/econet/patches-6.12/019-v6.13-dt-bindings-clock-airoha-Update-reg-mapping-for-EN75.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0f7c637d1103d79829dec198e5f1b678c1feb5f2 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 12 Nov 2024 01:08:48 +0100 -Subject: [PATCH] dt-bindings: clock: airoha: Update reg mapping for EN7581 - SoC. - -clk-en7523 driver for EN7581 SoC is mapping all the scu memory region -while it is configuring the chip-scu one via a syscon. Update the reg -mapping definition for this device. This patch does not introduce any -backward incompatibility since the dts for EN7581 SoC is not upstream -yet. - -Signed-off-by: Lorenzo Bianconi -Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-1-8ada5e394ae4@kernel.org -Reviewed-by: Rob Herring (Arm) -Signed-off-by: Stephen Boyd ---- - .../bindings/clock/airoha,en7523-scu.yaml | 23 +++++++------------ - 1 file changed, 8 insertions(+), 15 deletions(-) - ---- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml -+++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml -@@ -34,8 +34,10 @@ properties: - - airoha,en7581-scu - - reg: -- minItems: 2 -- maxItems: 4 -+ items: -+ - description: scu base address -+ - description: misc scu base address -+ minItems: 1 - - "#clock-cells": - description: -@@ -60,9 +62,7 @@ allOf: - then: - properties: - reg: -- items: -- - description: scu base address -- - description: misc scu base address -+ minItems: 2 - - - if: - properties: -@@ -71,11 +71,7 @@ allOf: - then: - properties: - reg: -- items: -- - description: scu base address -- - description: misc scu base address -- - description: reset base address -- - description: pb scu base address -+ maxItems: 1 - - additionalProperties: false - -@@ -95,12 +91,9 @@ examples: - #address-cells = <2>; - #size-cells = <2>; - -- scuclk: clock-controller@1fa20000 { -+ scuclk: clock-controller@1fb00000 { - compatible = "airoha,en7581-scu"; -- reg = <0x0 0x1fa20000 0x0 0x400>, -- <0x0 0x1fb00000 0x0 0x90>, -- <0x0 0x1fb00830 0x0 0x8>, -- <0x0 0x1fbe3400 0x0 0xfc>; -+ reg = <0x0 0x1fb00000 0x0 0x970>; - #clock-cells = <1>; - #reset-cells = <1>; - }; diff --git a/target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch b/target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch deleted file mode 100644 index 135fcced63..0000000000 --- a/target/linux/econet/patches-6.12/020-v6.19rc1-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 947643509279a605a09959a06d332bf027e8be57 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Mon, 10 Nov 2025 06:56:43 +0300 -Subject: [PATCH] dt-bindings: clock: airoha: Add reset support to EN7523 clock - binding - -Introduce reset capability to EN7523 device-tree clock binding -documentation. - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: Rob Herring (Arm) -Signed-off-by: Stephen Boyd ---- - .../dt-bindings/reset/airoha,en7523-reset.h | 61 +++++++++++++++++++ - 1 file changed, 61 insertions(+) - create mode 100644 include/dt-bindings/reset/airoha,en7523-reset.h - ---- /dev/null -+++ b/include/dt-bindings/reset/airoha,en7523-reset.h -@@ -0,0 +1,61 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Copyright (C) 2024 iopsys Software Solutions AB. -+ * Copyright (C) 2025 Genexis AB. -+ * -+ * Author: Mikhail Kshevetskiy -+ * -+ * based on -+ * include/dt-bindings/reset/airoha,en7581-reset.h -+ * by Lorenzo Bianconi -+ */ -+ -+#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ -+#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ -+ -+/* RST_CTRL2 */ -+#define EN7523_XPON_PHY_RST 0 -+#define EN7523_XSI_MAC_RST 1 -+#define EN7523_XSI_PHY_RST 2 -+#define EN7523_NPU_RST 3 -+#define EN7523_I2S_RST 4 -+#define EN7523_TRNG_RST 5 -+#define EN7523_TRNG_MSTART_RST 6 -+#define EN7523_DUAL_HSI0_RST 7 -+#define EN7523_DUAL_HSI1_RST 8 -+#define EN7523_HSI_RST 9 -+#define EN7523_DUAL_HSI0_MAC_RST 10 -+#define EN7523_DUAL_HSI1_MAC_RST 11 -+#define EN7523_HSI_MAC_RST 12 -+#define EN7523_WDMA_RST 13 -+#define EN7523_WOE0_RST 14 -+#define EN7523_WOE1_RST 15 -+#define EN7523_HSDMA_RST 16 -+#define EN7523_I2C2RBUS_RST 17 -+#define EN7523_TDMA_RST 18 -+/* RST_CTRL1 */ -+#define EN7523_PCM1_ZSI_ISI_RST 19 -+#define EN7523_FE_PDMA_RST 20 -+#define EN7523_FE_QDMA_RST 21 -+#define EN7523_PCM_SPIWP_RST 22 -+#define EN7523_CRYPTO_RST 23 -+#define EN7523_TIMER_RST 24 -+#define EN7523_PCM1_RST 25 -+#define EN7523_UART_RST 26 -+#define EN7523_GPIO_RST 27 -+#define EN7523_GDMA_RST 28 -+#define EN7523_I2C_MASTER_RST 29 -+#define EN7523_PCM2_ZSI_ISI_RST 30 -+#define EN7523_SFC_RST 31 -+#define EN7523_UART2_RST 32 -+#define EN7523_GDMP_RST 33 -+#define EN7523_FE_RST 34 -+#define EN7523_USB_HOST_P0_RST 35 -+#define EN7523_GSW_RST 36 -+#define EN7523_SFC2_PCM_RST 37 -+#define EN7523_PCIE0_RST 38 -+#define EN7523_PCIE1_RST 39 -+#define EN7523_PCIE_HB_RST 40 -+#define EN7523_XPON_MAC_RST 41 -+ -+#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ */ diff --git a/target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch b/target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch deleted file mode 100644 index a6594ebac8..0000000000 --- a/target/linux/econet/patches-6.12/021-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 02d3b7557ce28c373ea1e925ae16ab5988284313 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:03 +0100 -Subject: [PATCH 1/2] dt-bindings: clock: drop NUM_CLOCKS define for EN7581 - -Drop NUM_CLOCKS define for EN7581 include. This is not a binding and -should not be placed here. Value is derived internally in the user -driver. - -Signed-off-by: Christian Marangi -Acked-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250113231030.6735-3-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - include/dt-bindings/clock/en7523-clk.h | 2 -- - 1 file changed, 2 deletions(-) - ---- a/include/dt-bindings/clock/en7523-clk.h -+++ b/include/dt-bindings/clock/en7523-clk.h -@@ -12,6 +12,4 @@ - #define EN7523_CLK_CRYPTO 6 - #define EN7523_CLK_PCIE 7 - --#define EN7523_NUM_CLOCKS 8 -- - #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ diff --git a/target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch b/target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch deleted file mode 100644 index f500a79808..0000000000 --- a/target/linux/econet/patches-6.12/022-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 82108ad3285f58f314ad41398f44017c7dbe44de Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Tue, 14 Jan 2025 00:10:04 +0100 -Subject: [PATCH 2/2] dt-bindings: clock: add ID for eMMC for EN7581 - -Add ID for eMMC for EN7581. This is to control clock selection of eMMC -between 200MHz and 150MHz. - -Signed-off-by: Christian Marangi -Acked-by: Conor Dooley -Link: https://lore.kernel.org/r/20250113231030.6735-4-ansuelsmth@gmail.com -Signed-off-by: Stephen Boyd ---- - include/dt-bindings/clock/en7523-clk.h | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/include/dt-bindings/clock/en7523-clk.h -+++ b/include/dt-bindings/clock/en7523-clk.h -@@ -12,4 +12,6 @@ - #define EN7523_CLK_CRYPTO 6 - #define EN7523_CLK_PCIE 7 - -+#define EN7581_CLK_EMMC 8 -+ - #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ diff --git a/target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch b/target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch deleted file mode 100644 index c99c25921c..0000000000 --- a/target/linux/econet/patches-6.12/029-05-v6.19-spi-airoha-remove-unnecessary-restriction-length.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 661856ca131c8bf6724905966e02149805660abe Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Sun, 12 Oct 2025 15:16:53 +0300 -Subject: [PATCH 05/14] spi: airoha: remove unnecessary restriction length - -The "length < 160" restriction is not needed because airoha_snand_write_data() -and airoha_snand_read_data() will properly handle data transfers above -SPI_MAX_TRANSFER_SIZE. - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: AngeloGioacchino Del Regno -Link: https://patch.msgid.link/20251012121707.2296160-3-mikhail.kshevetskiy@iopsys.eu -Signed-off-by: Mark Brown ---- - drivers/spi/spi-airoha-snfi.c | 7 ------- - 1 file changed, 7 deletions(-) - ---- a/drivers/spi/spi-airoha-snfi.c -+++ b/drivers/spi/spi-airoha-snfi.c -@@ -619,13 +619,6 @@ static int airoha_snand_adjust_op_size(s - - if (op->data.nbytes > max_len) - op->data.nbytes = max_len; -- } else { -- max_len = 1 + op->addr.nbytes + op->dummy.nbytes; -- if (max_len >= 160) -- return -EOPNOTSUPP; -- -- if (op->data.nbytes > 160 - max_len) -- op->data.nbytes = 160 - max_len; - } - - return 0; diff --git a/target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch b/target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch deleted file mode 100644 index afe496c968..0000000000 --- a/target/linux/econet/patches-6.12/029-06-v6.19-spi-airoha-remove-unnecessary-switch-to-non-dma-mode.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 7350f8dc15bfbb7abf1ce4babea6fcace1c574c5 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Sun, 12 Oct 2025 15:16:55 +0300 -Subject: [PATCH 06/14] spi: airoha: remove unnecessary switch to non-dma mode - -The code switches to dma at the start of dirmap operation and returns -to non-dma at the end of dirmap operation, so an additional switch to -non-dma at the start of dirmap write is not required. - -Signed-off-by: Mikhail Kshevetskiy -Acked-by: Lorenzo Bianconi -Reviewed-by: AngeloGioacchino Del Regno -Link: https://patch.msgid.link/20251012121707.2296160-5-mikhail.kshevetskiy@iopsys.eu -Signed-off-by: Mark Brown ---- - drivers/spi/spi-airoha-snfi.c | 3 --- - 1 file changed, 3 deletions(-) - ---- a/drivers/spi/spi-airoha-snfi.c -+++ b/drivers/spi/spi-airoha-snfi.c -@@ -815,9 +815,6 @@ static ssize_t airoha_snand_dirmap_write - int err; - - as_ctrl = spi_controller_get_devdata(spi->controller); -- err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); -- if (err < 0) -- return err; - - memcpy(txrx_buf + offs, buf, len); - dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE, diff --git a/target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch b/target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch deleted file mode 100644 index c85c6861fc..0000000000 --- a/target/linux/econet/patches-6.12/029-07-v6.19-spi-airoha-unify-dirmap-read-write-code.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 233a22687411ea053a4b169c07324ee6aa33bf38 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Sun, 12 Oct 2025 15:16:58 +0300 -Subject: [PATCH 07/14] spi: airoha: unify dirmap read/write code - -Makes dirmap writing looks similar to dirmap reading. Just a minor -refactoring, no behavior change is expected. - -Signed-off-by: Mikhail Kshevetskiy -Link: https://patch.msgid.link/20251012121707.2296160-8-mikhail.kshevetskiy@iopsys.eu -Signed-off-by: Mark Brown ---- - drivers/spi/spi-airoha-snfi.c | 50 ++++++++++++++++++++++------------- - 1 file changed, 32 insertions(+), 18 deletions(-) - ---- a/drivers/spi/spi-airoha-snfi.c -+++ b/drivers/spi/spi-airoha-snfi.c -@@ -672,6 +672,8 @@ static ssize_t airoha_snand_dirmap_read( - u32 val, rd_mode; - int err; - -+ as_ctrl = spi_controller_get_devdata(spi->controller); -+ - switch (op->cmd.opcode) { - case SPI_NAND_OP_READ_FROM_CACHE_DUAL: - rd_mode = 1; -@@ -684,7 +686,6 @@ static ssize_t airoha_snand_dirmap_read( - break; - } - -- as_ctrl = spi_controller_get_devdata(spi->controller); - err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); - if (err < 0) - return err; -@@ -748,7 +749,7 @@ static ssize_t airoha_snand_dirmap_read( - if (err) - goto error_dma_unmap; - -- /* trigger dma start read */ -+ /* trigger dma reading */ - err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, - SPI_NFI_RD_TRIG); - if (err) -@@ -806,37 +807,47 @@ error_dma_mode_off: - static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc, - u64 offs, size_t len, const void *buf) - { -- struct spi_mem_op *op = &desc->info.op_tmpl; - struct spi_device *spi = desc->mem->spi; - u8 *txrx_buf = spi_get_ctldata(spi); - struct airoha_snand_ctrl *as_ctrl; - dma_addr_t dma_addr; -- u32 wr_mode, val; -+ u32 wr_mode, val, opcode; - int err; - - as_ctrl = spi_controller_get_devdata(spi->controller); - -+ opcode = desc->info.op_tmpl.cmd.opcode; -+ switch (opcode) { -+ case SPI_NAND_OP_PROGRAM_LOAD_SINGLE: -+ case SPI_NAND_OP_PROGRAM_LOAD_RAMDOM_SINGLE: -+ wr_mode = 0; -+ break; -+ case SPI_NAND_OP_PROGRAM_LOAD_QUAD: -+ case SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD: -+ wr_mode = 2; -+ break; -+ default: -+ /* unknown opcode */ -+ return -EOPNOTSUPP; -+ } -+ - memcpy(txrx_buf + offs, buf, len); -- dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE, -- DMA_TO_DEVICE); -- err = dma_mapping_error(as_ctrl->dev, dma_addr); -- if (err) -- return err; - - err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); - if (err < 0) -- goto error_dma_unmap; -+ return err; - - err = airoha_snand_nfi_config(as_ctrl); - if (err) -- goto error_dma_unmap; -+ goto error_dma_mode_off; - -- if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD || -- op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD) -- wr_mode = BIT(1); -- else -- wr_mode = 0; -+ dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE, -+ DMA_TO_DEVICE); -+ err = dma_mapping_error(as_ctrl->dev, dma_addr); -+ if (err) -+ goto error_dma_mode_off; - -+ /* set dma addr */ - err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR, - dma_addr); - if (err) -@@ -850,12 +861,13 @@ static ssize_t airoha_snand_dirmap_write - if (err) - goto error_dma_unmap; - -+ /* set write command */ - err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1, -- FIELD_PREP(SPI_NFI_PG_LOAD_CMD, -- op->cmd.opcode)); -+ FIELD_PREP(SPI_NFI_PG_LOAD_CMD, opcode)); - if (err) - goto error_dma_unmap; - -+ /* set write mode */ - err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL, - FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode)); - if (err) -@@ -887,6 +899,7 @@ static ssize_t airoha_snand_dirmap_write - if (err) - goto error_dma_unmap; - -+ /* trigger dma writing */ - err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, - SPI_NFI_WR_TRIG); - if (err) -@@ -931,6 +944,7 @@ static ssize_t airoha_snand_dirmap_write - error_dma_unmap: - dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE, - DMA_TO_DEVICE); -+error_dma_mode_off: - airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); - return err; - } diff --git a/target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch b/target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch deleted file mode 100644 index 7e3fcb4764..0000000000 --- a/target/linux/econet/patches-6.12/029-08-v6.19-spi-airoha-support-of-dualio-quadio-flash-reading-co.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 80b09137aeab27e59004383058f8cc696a9ee048 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Sun, 12 Oct 2025 15:16:59 +0300 -Subject: [PATCH 08/14] spi: airoha: support of dualio/quadio flash reading - commands - -Airoha snfi spi controller supports acceleration of DUAL/QUAD -operations, but does not supports DUAL_IO/QUAD_IO operations. -Luckily DUAL/QUAD operations do the same as DUAL_IO/QUAD_IO ones, -so we can issue corresponding DUAL/QUAD operation instead of -DUAL_IO/QUAD_IO one. - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: AngeloGioacchino Del Regno -Link: https://patch.msgid.link/20251012121707.2296160-9-mikhail.kshevetskiy@iopsys.eu -Signed-off-by: Mark Brown ---- - drivers/spi/spi-airoha-snfi.c | 28 ++++++++++++++++++++++------ - 1 file changed, 22 insertions(+), 6 deletions(-) - ---- a/drivers/spi/spi-airoha-snfi.c -+++ b/drivers/spi/spi-airoha-snfi.c -@@ -147,6 +147,8 @@ - #define SPI_NFI_CUS_SEC_SIZE_EN BIT(16) - - #define REG_SPI_NFI_RD_CTL2 0x0510 -+#define SPI_NFI_DATA_READ_CMD GENMASK(7, 0) -+ - #define REG_SPI_NFI_RD_CTL3 0x0514 - - #define REG_SPI_NFI_PG_CTL1 0x0524 -@@ -179,7 +181,9 @@ - #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE 0x03 - #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST 0x0b - #define SPI_NAND_OP_READ_FROM_CACHE_DUAL 0x3b -+#define SPI_NAND_OP_READ_FROM_CACHE_DUALIO 0xbb - #define SPI_NAND_OP_READ_FROM_CACHE_QUAD 0x6b -+#define SPI_NAND_OP_READ_FROM_CACHE_QUADIO 0xeb - #define SPI_NAND_OP_WRITE_ENABLE 0x06 - #define SPI_NAND_OP_WRITE_DISABLE 0x04 - #define SPI_NAND_OP_PROGRAM_LOAD_SINGLE 0x02 -@@ -664,26 +668,38 @@ static int airoha_snand_dirmap_create(st - static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc, - u64 offs, size_t len, void *buf) - { -- struct spi_mem_op *op = &desc->info.op_tmpl; - struct spi_device *spi = desc->mem->spi; - struct airoha_snand_ctrl *as_ctrl; - u8 *txrx_buf = spi_get_ctldata(spi); - dma_addr_t dma_addr; -- u32 val, rd_mode; -+ u32 val, rd_mode, opcode; - int err; - - as_ctrl = spi_controller_get_devdata(spi->controller); - -- switch (op->cmd.opcode) { -+ /* -+ * DUALIO and QUADIO opcodes are not supported by the spi controller, -+ * replace them with supported opcodes. -+ */ -+ opcode = desc->info.op_tmpl.cmd.opcode; -+ switch (opcode) { -+ case SPI_NAND_OP_READ_FROM_CACHE_SINGLE: -+ case SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST: -+ rd_mode = 0; -+ break; - case SPI_NAND_OP_READ_FROM_CACHE_DUAL: -+ case SPI_NAND_OP_READ_FROM_CACHE_DUALIO: -+ opcode = SPI_NAND_OP_READ_FROM_CACHE_DUAL; - rd_mode = 1; - break; - case SPI_NAND_OP_READ_FROM_CACHE_QUAD: -+ case SPI_NAND_OP_READ_FROM_CACHE_QUADIO: -+ opcode = SPI_NAND_OP_READ_FROM_CACHE_QUAD; - rd_mode = 2; - break; - default: -- rd_mode = 0; -- break; -+ /* unknown opcode */ -+ return -EOPNOTSUPP; - } - - err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); -@@ -717,7 +733,7 @@ static ssize_t airoha_snand_dirmap_read( - - /* set read command */ - err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2, -- op->cmd.opcode); -+ FIELD_PREP(SPI_NFI_DATA_READ_CMD, opcode)); - if (err) - goto error_dma_unmap; - diff --git a/target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch b/target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch deleted file mode 100644 index f8902f7e57..0000000000 --- a/target/linux/econet/patches-6.12/029-09-v6.19-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG_SP.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 70eec454f2d6cdfab547c262781acd38328e11a1 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Sun, 12 Oct 2025 15:17:00 +0300 -Subject: [PATCH 09/14] spi: airoha: avoid setting of page/oob sizes in - REG_SPI_NFI_PAGEFMT - -spi-airoha-snfi uses custom sector size in REG_SPI_NFI_SECCUS_SIZE -register, so setting of page/oob sizes in REG_SPI_NFI_PAGEFMT is not -required. - -Signed-off-by: Mikhail Kshevetskiy -Link: https://patch.msgid.link/20251012121707.2296160-10-mikhail.kshevetskiy@iopsys.eu -Signed-off-by: Mark Brown ---- - drivers/spi/spi-airoha-snfi.c | 38 ----------------------------------- - 1 file changed, 38 deletions(-) - ---- a/drivers/spi/spi-airoha-snfi.c -+++ b/drivers/spi/spi-airoha-snfi.c -@@ -518,44 +518,6 @@ static int airoha_snand_nfi_config(struc - if (err) - return err; - -- /* page format */ -- switch (as_ctrl->nfi_cfg.spare_size) { -- case 26: -- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x1); -- break; -- case 27: -- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x2); -- break; -- case 28: -- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x3); -- break; -- default: -- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x0); -- break; -- } -- -- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT, -- SPI_NFI_SPARE_SIZE, val); -- if (err) -- return err; -- -- switch (as_ctrl->nfi_cfg.page_size) { -- case 2048: -- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x1); -- break; -- case 4096: -- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x2); -- break; -- default: -- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x0); -- break; -- } -- -- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT, -- SPI_NFI_PAGE_SIZE, val); -- if (err) -- return err; -- - /* sec num */ - val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); - err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, diff --git a/target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch b/target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch deleted file mode 100644 index 40e2f6ea21..0000000000 --- a/target/linux/econet/patches-6.12/029-10-v6.19-spi-airoha-reduce-the-number-of-modification-of-REG_.patch +++ /dev/null @@ -1,199 +0,0 @@ -From d1ff30df1d9a4eb4c067795abb5e2a66910fd108 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Sun, 12 Oct 2025 15:17:01 +0300 -Subject: [PATCH 10/14] spi: airoha: reduce the number of modification of - REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers - -This just reduce the number of modification of REG_SPI_NFI_CNFG and -REG_SPI_NFI_SECCUS_SIZE registers during dirmap operation. - -This patch is a necessary step to avoid reading flash page settings -from SNFI registers during driver startup. - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: AngeloGioacchino Del Regno -Link: https://patch.msgid.link/20251012121707.2296160-11-mikhail.kshevetskiy@iopsys.eu -Signed-off-by: Mark Brown ---- - drivers/spi/spi-airoha-snfi.c | 135 +++++++++++++++++++++++++--------- - 1 file changed, 102 insertions(+), 33 deletions(-) - ---- a/drivers/spi/spi-airoha-snfi.c -+++ b/drivers/spi/spi-airoha-snfi.c -@@ -668,7 +668,48 @@ static ssize_t airoha_snand_dirmap_read( - if (err < 0) - return err; - -- err = airoha_snand_nfi_config(as_ctrl); -+ /* NFI reset */ -+ err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, -+ SPI_NFI_FIFO_FLUSH | SPI_NFI_RST); -+ if (err) -+ goto error_dma_mode_off; -+ -+ /* NFI configure: -+ * - No AutoFDM (custom sector size (SECCUS) register will be used) -+ * - No SoC's hardware ECC (flash internal ECC will be used) -+ * - Use burst mode (faster, but requires 16 byte alignment for addresses) -+ * - Setup for reading (SPI_NFI_READ_MODE) -+ * - Setup reading command: FIELD_PREP(SPI_NFI_OPMODE, 6) -+ * - Use DMA instead of PIO for data reading -+ */ -+ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, -+ SPI_NFI_DMA_MODE | -+ SPI_NFI_READ_MODE | -+ SPI_NFI_DMA_BURST_EN | -+ SPI_NFI_HW_ECC_EN | -+ SPI_NFI_AUTO_FDM_EN | -+ SPI_NFI_OPMODE, -+ SPI_NFI_DMA_MODE | -+ SPI_NFI_READ_MODE | -+ SPI_NFI_DMA_BURST_EN | -+ FIELD_PREP(SPI_NFI_OPMODE, 6)); -+ if (err) -+ goto error_dma_mode_off; -+ -+ /* Set number of sector will be read */ -+ val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); -+ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, -+ SPI_NFI_SEC_NUM, val); -+ if (err) -+ goto error_dma_mode_off; -+ -+ /* Set custom sector size */ -+ val = as_ctrl->nfi_cfg.sec_size; -+ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, -+ SPI_NFI_CUS_SEC_SIZE | -+ SPI_NFI_CUS_SEC_SIZE_EN, -+ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | -+ SPI_NFI_CUS_SEC_SIZE_EN); - if (err) - goto error_dma_mode_off; - -@@ -684,7 +725,14 @@ static ssize_t airoha_snand_dirmap_read( - if (err) - goto error_dma_unmap; - -- /* set cust sec size */ -+ /* -+ * Setup transfer length -+ * --------------------- -+ * The following rule MUST be met: -+ * transfer_length = -+ * = NFI_SNF_MISC_CTL2.read_data_byte_number = -+ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size -+ */ - val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; - val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val); - err = regmap_update_bits(as_ctrl->regmap_nfi, -@@ -711,18 +759,6 @@ static ssize_t airoha_snand_dirmap_read( - if (err) - goto error_dma_unmap; - -- /* set nfi read */ -- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, -- SPI_NFI_OPMODE, -- FIELD_PREP(SPI_NFI_OPMODE, 6)); -- if (err) -- goto error_dma_unmap; -- -- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, -- SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE); -- if (err) -- goto error_dma_unmap; -- - err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0); - if (err) - goto error_dma_unmap; -@@ -815,7 +851,48 @@ static ssize_t airoha_snand_dirmap_write - if (err < 0) - return err; - -- err = airoha_snand_nfi_config(as_ctrl); -+ /* NFI reset */ -+ err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, -+ SPI_NFI_FIFO_FLUSH | SPI_NFI_RST); -+ if (err) -+ goto error_dma_mode_off; -+ -+ /* -+ * NFI configure: -+ * - No AutoFDM (custom sector size (SECCUS) register will be used) -+ * - No SoC's hardware ECC (flash internal ECC will be used) -+ * - Use burst mode (faster, but requires 16 byte alignment for addresses) -+ * - Setup for writing (SPI_NFI_READ_MODE bit is cleared) -+ * - Setup writing command: FIELD_PREP(SPI_NFI_OPMODE, 3) -+ * - Use DMA instead of PIO for data writing -+ */ -+ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, -+ SPI_NFI_DMA_MODE | -+ SPI_NFI_READ_MODE | -+ SPI_NFI_DMA_BURST_EN | -+ SPI_NFI_HW_ECC_EN | -+ SPI_NFI_AUTO_FDM_EN | -+ SPI_NFI_OPMODE, -+ SPI_NFI_DMA_MODE | -+ SPI_NFI_DMA_BURST_EN | -+ FIELD_PREP(SPI_NFI_OPMODE, 3)); -+ if (err) -+ goto error_dma_mode_off; -+ -+ /* Set number of sector will be written */ -+ val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); -+ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, -+ SPI_NFI_SEC_NUM, val); -+ if (err) -+ goto error_dma_mode_off; -+ -+ /* Set custom sector size */ -+ val = as_ctrl->nfi_cfg.sec_size; -+ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, -+ SPI_NFI_CUS_SEC_SIZE | -+ SPI_NFI_CUS_SEC_SIZE_EN, -+ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | -+ SPI_NFI_CUS_SEC_SIZE_EN); - if (err) - goto error_dma_mode_off; - -@@ -831,8 +908,16 @@ static ssize_t airoha_snand_dirmap_write - if (err) - goto error_dma_unmap; - -- val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, -- as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num); -+ /* -+ * Setup transfer length -+ * --------------------- -+ * The following rule MUST be met: -+ * transfer_length = -+ * = NFI_SNF_MISC_CTL2.write_data_byte_number = -+ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size -+ */ -+ val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; -+ val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val); - err = regmap_update_bits(as_ctrl->regmap_nfi, - REG_SPI_NFI_SNF_MISC_CTL2, - SPI_NFI_PROG_LOAD_BYTE_NUM, val); -@@ -857,22 +942,6 @@ static ssize_t airoha_snand_dirmap_write - if (err) - goto error_dma_unmap; - -- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, -- SPI_NFI_READ_MODE); -- if (err) -- goto error_dma_unmap; -- -- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, -- SPI_NFI_OPMODE, -- FIELD_PREP(SPI_NFI_OPMODE, 3)); -- if (err) -- goto error_dma_unmap; -- -- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, -- SPI_NFI_DMA_MODE); -- if (err) -- goto error_dma_unmap; -- - err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80); - if (err) - goto error_dma_unmap; diff --git a/target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch b/target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch deleted file mode 100644 index 514212835c..0000000000 --- a/target/linux/econet/patches-6.12/029-11-v6.19-spi-airoha-set-custom-sector-size-equal-to-flash-pag.patch +++ /dev/null @@ -1,142 +0,0 @@ -From fb81b5cecb8553e3ca2b45288cf340d43c9c2991 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Sun, 12 Oct 2025 15:17:02 +0300 -Subject: [PATCH 11/14] spi: airoha: set custom sector size equal to flash page - size - -Set custom sector size equal to flash page size including oob. Thus we -will always read a single sector. The maximum custom sector size is -8187, so all possible flash sector sizes are supported. - -This patch is a necessary step to avoid reading flash page settings -from SNFI registers during driver startup. - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: AngeloGioacchino Del Regno -Link: https://patch.msgid.link/20251012121707.2296160-12-mikhail.kshevetskiy@iopsys.eu -Signed-off-by: Mark Brown ---- - drivers/spi/spi-airoha-snfi.c | 35 +++++++++++++++++++---------------- - 1 file changed, 19 insertions(+), 16 deletions(-) - ---- a/drivers/spi/spi-airoha-snfi.c -+++ b/drivers/spi/spi-airoha-snfi.c -@@ -519,7 +519,7 @@ static int airoha_snand_nfi_config(struc - return err; - - /* sec num */ -- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); -+ val = FIELD_PREP(SPI_NFI_SEC_NUM, 1); - err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, - SPI_NFI_SEC_NUM, val); - if (err) -@@ -532,7 +532,8 @@ static int airoha_snand_nfi_config(struc - return err; - - /* set cust sec size */ -- val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, as_ctrl->nfi_cfg.sec_size); -+ val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, -+ as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num); - return regmap_update_bits(as_ctrl->regmap_nfi, - REG_SPI_NFI_SECCUS_SIZE, - SPI_NFI_CUS_SEC_SIZE, val); -@@ -635,10 +636,13 @@ static ssize_t airoha_snand_dirmap_read( - u8 *txrx_buf = spi_get_ctldata(spi); - dma_addr_t dma_addr; - u32 val, rd_mode, opcode; -+ size_t bytes; - int err; - - as_ctrl = spi_controller_get_devdata(spi->controller); - -+ bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; -+ - /* - * DUALIO and QUADIO opcodes are not supported by the spi controller, - * replace them with supported opcodes. -@@ -697,18 +701,17 @@ static ssize_t airoha_snand_dirmap_read( - goto error_dma_mode_off; - - /* Set number of sector will be read */ -- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); - err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, -- SPI_NFI_SEC_NUM, val); -+ SPI_NFI_SEC_NUM, -+ FIELD_PREP(SPI_NFI_SEC_NUM, 1)); - if (err) - goto error_dma_mode_off; - - /* Set custom sector size */ -- val = as_ctrl->nfi_cfg.sec_size; - err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, - SPI_NFI_CUS_SEC_SIZE | - SPI_NFI_CUS_SEC_SIZE_EN, -- FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | -+ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) | - SPI_NFI_CUS_SEC_SIZE_EN); - if (err) - goto error_dma_mode_off; -@@ -733,11 +736,10 @@ static ssize_t airoha_snand_dirmap_read( - * = NFI_SNF_MISC_CTL2.read_data_byte_number = - * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size - */ -- val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; -- val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val); - err = regmap_update_bits(as_ctrl->regmap_nfi, - REG_SPI_NFI_SNF_MISC_CTL2, -- SPI_NFI_READ_DATA_BYTE_NUM, val); -+ SPI_NFI_READ_DATA_BYTE_NUM, -+ FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, bytes)); - if (err) - goto error_dma_unmap; - -@@ -826,10 +828,13 @@ static ssize_t airoha_snand_dirmap_write - struct airoha_snand_ctrl *as_ctrl; - dma_addr_t dma_addr; - u32 wr_mode, val, opcode; -+ size_t bytes; - int err; - - as_ctrl = spi_controller_get_devdata(spi->controller); - -+ bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; -+ - opcode = desc->info.op_tmpl.cmd.opcode; - switch (opcode) { - case SPI_NAND_OP_PROGRAM_LOAD_SINGLE: -@@ -880,18 +885,17 @@ static ssize_t airoha_snand_dirmap_write - goto error_dma_mode_off; - - /* Set number of sector will be written */ -- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); - err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, -- SPI_NFI_SEC_NUM, val); -+ SPI_NFI_SEC_NUM, -+ FIELD_PREP(SPI_NFI_SEC_NUM, 1)); - if (err) - goto error_dma_mode_off; - - /* Set custom sector size */ -- val = as_ctrl->nfi_cfg.sec_size; - err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, - SPI_NFI_CUS_SEC_SIZE | - SPI_NFI_CUS_SEC_SIZE_EN, -- FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | -+ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) | - SPI_NFI_CUS_SEC_SIZE_EN); - if (err) - goto error_dma_mode_off; -@@ -916,11 +920,10 @@ static ssize_t airoha_snand_dirmap_write - * = NFI_SNF_MISC_CTL2.write_data_byte_number = - * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size - */ -- val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; -- val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val); - err = regmap_update_bits(as_ctrl->regmap_nfi, - REG_SPI_NFI_SNF_MISC_CTL2, -- SPI_NFI_PROG_LOAD_BYTE_NUM, val); -+ SPI_NFI_PROG_LOAD_BYTE_NUM, -+ FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, bytes)); - if (err) - goto error_dma_unmap; - diff --git a/target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch b/target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch deleted file mode 100644 index 00fd100bc3..0000000000 --- a/target/linux/econet/patches-6.12/029-12-v6.19-spi-airoha-avoid-reading-flash-page-settings-from-SN.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 902c0ea18a97b1a6eeee5799cb1fd9a79ef9208e Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Sun, 12 Oct 2025 15:17:03 +0300 -Subject: [PATCH 12/14] spi: airoha: avoid reading flash page settings from - SNFI registers during driver startup - -The spinand driver do 3 type of dirmap requests: - * read/write whole flash page without oob - (offs = 0, len = page_size) - * read/write whole flash page including oob - (offs = 0, len = page_size + oob_size) - * read/write oob area only - (offs = page_size, len = oob_size) - -The trick is: - * read/write a single "sector" - * set a custom sector size equal to offs + len. It's a bit safer to - rounded up "sector size" value 64. - * set the transfer length equal to custom sector size - -And it works! - -Thus we can remove a dirty hack that reads flash page settings from -SNFI registers during driver startup. Also airoha_snand_adjust_op_size() -function becomes unnecessary. - -Signed-off-by: Mikhail Kshevetskiy -Link: https://patch.msgid.link/20251012121707.2296160-13-mikhail.kshevetskiy@iopsys.eu -Signed-off-by: Mark Brown ---- - drivers/spi/spi-airoha-snfi.c | 115 ++-------------------------------- - 1 file changed, 5 insertions(+), 110 deletions(-) - ---- a/drivers/spi/spi-airoha-snfi.c -+++ b/drivers/spi/spi-airoha-snfi.c -@@ -223,13 +223,6 @@ struct airoha_snand_ctrl { - struct regmap *regmap_ctrl; - struct regmap *regmap_nfi; - struct clk *spi_clk; -- -- struct { -- size_t page_size; -- size_t sec_size; -- u8 sec_num; -- u8 spare_size; -- } nfi_cfg; - }; - - static int airoha_snand_set_fifo_op(struct airoha_snand_ctrl *as_ctrl, -@@ -490,55 +483,6 @@ static int airoha_snand_nfi_init(struct - SPI_NFI_ALL_IRQ_EN, SPI_NFI_AHB_DONE_EN); - } - --static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl) --{ -- int err; -- u32 val; -- -- err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, -- SPI_NFI_FIFO_FLUSH | SPI_NFI_RST); -- if (err) -- return err; -- -- /* auto FDM */ -- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, -- SPI_NFI_AUTO_FDM_EN); -- if (err) -- return err; -- -- /* HW ECC */ -- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, -- SPI_NFI_HW_ECC_EN); -- if (err) -- return err; -- -- /* DMA Burst */ -- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, -- SPI_NFI_DMA_BURST_EN); -- if (err) -- return err; -- -- /* sec num */ -- val = FIELD_PREP(SPI_NFI_SEC_NUM, 1); -- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, -- SPI_NFI_SEC_NUM, val); -- if (err) -- return err; -- -- /* enable cust sec size */ -- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, -- SPI_NFI_CUS_SEC_SIZE_EN); -- if (err) -- return err; -- -- /* set cust sec size */ -- val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, -- as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num); -- return regmap_update_bits(as_ctrl->regmap_nfi, -- REG_SPI_NFI_SECCUS_SIZE, -- SPI_NFI_CUS_SEC_SIZE, val); --} -- - static bool airoha_snand_is_page_ops(const struct spi_mem_op *op) - { - if (op->addr.nbytes != 2) -@@ -571,26 +515,6 @@ static bool airoha_snand_is_page_ops(con - } - } - --static int airoha_snand_adjust_op_size(struct spi_mem *mem, -- struct spi_mem_op *op) --{ -- size_t max_len; -- -- if (airoha_snand_is_page_ops(op)) { -- struct airoha_snand_ctrl *as_ctrl; -- -- as_ctrl = spi_controller_get_devdata(mem->spi->controller); -- max_len = as_ctrl->nfi_cfg.sec_size; -- max_len += as_ctrl->nfi_cfg.spare_size; -- max_len *= as_ctrl->nfi_cfg.sec_num; -- -- if (op->data.nbytes > max_len) -- op->data.nbytes = max_len; -- } -- -- return 0; --} -- - static bool airoha_snand_supports_op(struct spi_mem *mem, - const struct spi_mem_op *op) - { -@@ -641,7 +565,8 @@ static ssize_t airoha_snand_dirmap_read( - - as_ctrl = spi_controller_get_devdata(spi->controller); - -- bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; -+ /* minimum oob size is 64 */ -+ bytes = round_up(offs + len, 64); - - /* - * DUALIO and QUADIO opcodes are not supported by the spi controller, -@@ -833,7 +758,8 @@ static ssize_t airoha_snand_dirmap_write - - as_ctrl = spi_controller_get_devdata(spi->controller); - -- bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; -+ /* minimum oob size is 64 */ -+ bytes = round_up(offs + len, 64); - - opcode = desc->info.op_tmpl.cmd.opcode; - switch (opcode) { -@@ -1076,7 +1002,6 @@ static int airoha_snand_exec_op(struct s - } - - static const struct spi_controller_mem_ops airoha_snand_mem_ops = { -- .adjust_op_size = airoha_snand_adjust_op_size, - .supports_op = airoha_snand_supports_op, - .exec_op = airoha_snand_exec_op, - .dirmap_create = airoha_snand_dirmap_create, -@@ -1106,36 +1031,6 @@ static int airoha_snand_setup(struct spi - return 0; - } - --static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl) --{ -- u32 val, sec_size, sec_num; -- int err; -- -- err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, &val); -- if (err) -- return err; -- -- sec_num = FIELD_GET(SPI_NFI_SEC_NUM, val); -- -- err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, &val); -- if (err) -- return err; -- -- sec_size = FIELD_GET(SPI_NFI_CUS_SEC_SIZE, val); -- -- /* init default value */ -- as_ctrl->nfi_cfg.sec_size = sec_size; -- as_ctrl->nfi_cfg.sec_num = sec_num; -- as_ctrl->nfi_cfg.page_size = round_down(sec_size * sec_num, 1024); -- as_ctrl->nfi_cfg.spare_size = 16; -- -- err = airoha_snand_nfi_init(as_ctrl); -- if (err) -- return err; -- -- return airoha_snand_nfi_config(as_ctrl); --} -- - static const struct regmap_config spi_ctrl_regmap_config = { - .name = "ctrl", - .reg_bits = 32, -@@ -1227,7 +1122,7 @@ static int airoha_snand_probe(struct pla - ctrl->setup = airoha_snand_setup; - device_set_node(&ctrl->dev, dev_fwnode(dev)); - -- err = airoha_snand_nfi_setup(as_ctrl); -+ err = airoha_snand_nfi_init(as_ctrl); - if (err) - return err; - diff --git a/target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch b/target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch deleted file mode 100644 index 669f9b2dd4..0000000000 --- a/target/linux/econet/patches-6.12/029-13-v6.19-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0743acf746a81e0460a56fd5ff847d97fa7eb370 Mon Sep 17 00:00:00 2001 -From: Mikhail Kshevetskiy -Date: Sun, 12 Oct 2025 15:17:04 +0300 -Subject: [PATCH 13/14] spi: airoha: buffer must be 0xff-ed before writing - -During writing, the entire flash page (including OOB) will be updated -with the values from the temporary buffer, so we need to fill the -untouched areas of the buffer with 0xff value to prevent accidental -data overwriting. - -Signed-off-by: Mikhail Kshevetskiy -Reviewed-by: AngeloGioacchino Del Regno -Link: https://patch.msgid.link/20251012121707.2296160-14-mikhail.kshevetskiy@iopsys.eu -Signed-off-by: Mark Brown ---- - drivers/spi/spi-airoha-snfi.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/spi/spi-airoha-snfi.c -+++ b/drivers/spi/spi-airoha-snfi.c -@@ -776,7 +776,11 @@ static ssize_t airoha_snand_dirmap_write - return -EOPNOTSUPP; - } - -+ if (offs > 0) -+ memset(txrx_buf, 0xff, offs); - memcpy(txrx_buf + offs, buf, len); -+ if (bytes > offs + len) -+ memset(txrx_buf + offs + len, 0xff, bytes - offs - len); - - err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); - if (err < 0) diff --git a/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch b/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch deleted file mode 100644 index f11c6d329d..0000000000 --- a/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch +++ /dev/null @@ -1,119 +0,0 @@ -From: Ahmed Naseef -Subject: mips: econet: add EN7528 SoC support - -The EN7528 is a little endian dual-core MIPS 1004Kc SoC used in xPON -devices. Unlike the big endian EN751221, EN7528 uses the MIPS GIC -interrupt controller for SMP. - -This adds boot support for the EN7528 SoC family: -- New SOC_ECONET_EN7528 Kconfig option -- Little endian support for ECONET platform -- UART base address adjustment for endianness -- CPS SMP ops registration for multi-core support - -Signed-off-by: Ahmed Naseef ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -391,13 +391,13 @@ config MACH_DECSTATION - config ECONET - bool "EcoNet MIPS family" - select BOOT_RAW -- select CPU_BIG_ENDIAN - select DEBUG_ZBOOT if DEBUG_KERNEL - select EARLY_PRINTK_8250 - select ECONET_EN751221_TIMER - select SERIAL_8250 - select SERIAL_OF_PLATFORM - select SYS_SUPPORTS_BIG_ENDIAN -+ select SYS_SUPPORTS_LITTLE_ENDIAN - select SYS_HAS_CPU_MIPS32_R1 - select SYS_HAS_CPU_MIPS32_R2 - select SYS_HAS_EARLY_PRINTK ---- a/arch/mips/econet/Kconfig -+++ b/arch/mips/econet/Kconfig -@@ -12,6 +12,7 @@ choice - config SOC_ECONET_EN751221 - bool "EN751221 family" - select COMMON_CLK -+ select CPU_BIG_ENDIAN - select ECONET_EN751221_INTC - select IRQ_MIPS_CPU - select SMP -@@ -22,6 +23,23 @@ choice - They are based on single core MIPS 34Kc processors. To boot - this kernel, you will need a device tree such as - MIPS_RAW_APPENDED_DTB=y, and a root filesystem. -+ -+ config SOC_ECONET_EN7528 -+ bool "EN7528 family" -+ select COMMON_CLK -+ select CPU_LITTLE_ENDIAN -+ select IRQ_MIPS_CPU -+ select MIPS_CPU_SCACHE -+ select MIPS_GIC -+ select SMP -+ select SMP_UP -+ select SYS_SUPPORTS_HIGHMEM -+ select SYS_SUPPORTS_MIPS_CPS -+ select SYS_SUPPORTS_MULTITHREADING -+ select SYS_SUPPORTS_SMP -+ help -+ The EN7528 family with dual-core MIPS 1004Kc. -+ Requires MIPS_RAW_APPENDED_DTB=y for boot. - endchoice - - choice ---- a/arch/mips/econet/init.c -+++ b/arch/mips/econet/init.c -@@ -16,11 +16,16 @@ - #include - #include - #include -+#include - - #define CR_AHB_RSTCR ((void __iomem *)CKSEG1ADDR(0x1fb00040)) - #define RESET BIT(31) - --#define UART_BASE CKSEG1ADDR(0x1fbf0003) -+#ifdef CONFIG_CPU_LITTLE_ENDIAN -+#define UART_BASE CKSEG1ADDR(0x1fbf0000) /* LE: byte at offset 0 */ -+#else -+#define UART_BASE CKSEG1ADDR(0x1fbf0003) /* BE: byte at offset 3 */ -+#endif - #define UART_REG_SHIFT 2 - - static void hw_reset(char *command) -@@ -51,11 +56,18 @@ void __init plat_mem_setup(void) - early_init_dt_scan_memory(); - } - --/* 3. Overload __weak device_tree_init(), add SMP_UP ops */ -+/* 3. Overload __weak device_tree_init(), register SMP ops */ - void __init device_tree_init(void) - { - unflatten_and_copy_device_tree(); - -+ /* EN7528 dual-core: probe CM/CPC and register CPS SMP ops */ -+ mips_cm_probe(); -+ mips_cpc_probe(); -+ -+ if (!register_cps_smp_ops()) -+ return; -+ - register_up_smp_ops(); - } - ---- a/arch/mips/boot/compressed/uart-16550.c -+++ b/arch/mips/boot/compressed/uart-16550.c -@@ -21,7 +21,11 @@ - #endif - - #ifdef CONFIG_ECONET -+#ifdef CONFIG_CPU_LITTLE_ENDIAN -+#define EN75_UART_BASE 0x1fbf0000 -+#else - #define EN75_UART_BASE 0x1fbf0003 -+#endif - #define PORT(offset) (CKSEG1ADDR(EN75_UART_BASE) + (4 * (offset))) - #endif - diff --git a/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch b/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch deleted file mode 100644 index 3d86414591..0000000000 --- a/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch +++ /dev/null @@ -1,264 +0,0 @@ -From: Ahmed Naseef -Subject: mips: econet: timer: add EN7528 support to EN751221 timer driver - -Extend the existing EN751221 timer driver to support EN7528/EN751627 SoCs. -The driver now auto-detects the IRQ mode based on device tree: -- EN751221: Single percpu IRQ (legacy interrupt controller) -- EN7528/EN751627: Separate IRQ per CPU (GIC shared interrupts) - -Signed-off-by: Ahmed Naseef ---- a/drivers/clocksource/Kconfig -+++ b/drivers/clocksource/Kconfig -@@ -79,7 +79,10 @@ config ECONET_EN751221_TIMER - select CLKSRC_MMIO - select TIMER_OF - help -- Support for CPU timer found on EcoNet MIPS based SoCs. -+ Support for CPU timer found on EcoNet EN75xx MIPS based SoCs -+ (EN751221, EN751627, EN7528). The driver supports both GIC-based -+ (separate IRQ per CPU) and legacy interrupt controller (percpu IRQ) -+ modes. - - config FTTMR010_TIMER - bool "Faraday Technology timer driver" if COMPILE_TEST ---- a/drivers/clocksource/timer-econet-en751221.c -+++ b/drivers/clocksource/timer-econet-en751221.c -@@ -2,12 +2,20 @@ - /* - * Timer present on EcoNet EN75xx MIPS based SoCs. - * -+ * This driver supports both: -+ * - EN751221: Single percpu IRQ mode (legacy interrupt controller) -+ * - EN7528/EN751627: Separate IRQ per CPU mode (GIC shared interrupts) -+ * -+ * The mode is auto-detected based on IRQ count in device tree. -+ * - * Copyright (C) 2025 by Caleb James DeLisle -+ * Copyright (C) 2025 by Ahmed Naseef - */ - - #include - #include - #include -+#include - #include - #include - #include -@@ -21,10 +29,14 @@ - #define ECONET_MAX_DELTA GENMASK(ECONET_BITS - 2, 0) - /* 34Kc hardware has 1 block and 1004Kc has 2. */ - #define ECONET_NUM_BLOCKS DIV_ROUND_UP(NR_CPUS, 2) -+#define ECONET_MAX_IRQS 4 - - static struct { - void __iomem *membase[ECONET_NUM_BLOCKS]; - u32 freq_hz; -+ int irqs[ECONET_MAX_IRQS]; -+ int num_irqs; -+ bool use_percpu_irq; - } econet_timer __ro_after_init; - - static DEFINE_PER_CPU(struct clock_event_device, econet_timer_pcpu); -@@ -98,12 +110,21 @@ static int cevt_init_cpu(uint cpu) - struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, cpu); - u32 reg; - -+ if (!econet_timer.use_percpu_irq && cpu >= econet_timer.num_irqs) -+ return -EINVAL; -+ - pr_debug("%s: Setting up clockevent for CPU %d\n", cd->name, cpu); - - reg = ioread32(reg_ctl(cpu)) | ctl_bit_enabled(cpu); - iowrite32(reg, reg_ctl(cpu)); - -- enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); -+ if (econet_timer.use_percpu_irq) { -+ enable_percpu_irq(cd->irq, IRQ_TYPE_NONE); -+ } else { -+ if (irq_force_affinity(econet_timer.irqs[cpu], cpumask_of(cpu))) -+ pr_warn("%s: failed to set IRQ %d affinity to CPU %d\n", -+ cd->name, econet_timer.irqs[cpu], cpu); -+ } - - /* Do this last because it synchronously configures the timer */ - clockevents_config_and_register(cd, econet_timer.freq_hz, -@@ -126,7 +147,21 @@ static void __init cevt_dev_init(uint cp - iowrite32(U32_MAX, reg_compare(cpu)); - } - --static int __init cevt_init(struct device_node *np) -+static void __init cevt_setup_clockevent(struct clock_event_device *cd, -+ struct device_node *np, -+ int irq, int cpu) -+{ -+ cd->rating = 310; -+ cd->features = CLOCK_EVT_FEAT_ONESHOT | -+ CLOCK_EVT_FEAT_C3STOP | -+ CLOCK_EVT_FEAT_PERCPU; -+ cd->set_next_event = cevt_set_next_event; -+ cd->irq = irq; -+ cd->cpumask = cpumask_of(cpu); -+ cd->name = np->name; -+} -+ -+static int __init cevt_init_percpu(struct device_node *np) - { - int i, irq, ret; - -@@ -137,42 +172,85 @@ static int __init cevt_init(struct devic - } - - ret = request_percpu_irq(irq, cevt_interrupt, np->name, &econet_timer_pcpu); -- - if (ret < 0) { - pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, irq, ret); -- goto err_unmap_irq; -+ irq_dispose_mapping(irq); -+ return ret; - } - - for_each_possible_cpu(i) { - struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i); - -- cd->rating = 310, -- cd->features = CLOCK_EVT_FEAT_ONESHOT | -- CLOCK_EVT_FEAT_C3STOP | -- CLOCK_EVT_FEAT_PERCPU; -- cd->set_next_event = cevt_set_next_event; -- cd->irq = irq; -- cd->cpumask = cpumask_of(i); -- cd->name = np->name; -+ cevt_setup_clockevent(cd, np, irq, i); -+ cevt_dev_init(i); -+ } -+ -+ return 0; -+} -+ -+static int __init cevt_init_separate(struct device_node *np) -+{ -+ int i, ret; -+ -+ for (i = 0; i < econet_timer.num_irqs; i++) { -+ struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i); -+ -+ econet_timer.irqs[i] = irq_of_parse_and_map(np, i); -+ if (econet_timer.irqs[i] <= 0) { -+ pr_err("%pOFn: irq_of_parse_and_map failed", np); -+ ret = -EINVAL; -+ goto err_free_irqs; -+ } -+ -+ ret = request_irq(econet_timer.irqs[i], cevt_interrupt, -+ IRQF_TIMER | IRQF_NOBALANCING, -+ np->name, NULL); -+ if (ret < 0) { -+ pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, -+ econet_timer.irqs[i], ret); -+ irq_dispose_mapping(econet_timer.irqs[i]); -+ goto err_free_irqs; -+ } - -+ cevt_setup_clockevent(cd, np, econet_timer.irqs[i], i); - cevt_dev_init(i); - } - -- cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, -- "clockevents/econet/timer:starting", -- cevt_init_cpu, NULL); - return 0; - --err_unmap_irq: -- irq_dispose_mapping(irq); -+err_free_irqs: -+ while (--i >= 0) { -+ free_irq(econet_timer.irqs[i], NULL); -+ irq_dispose_mapping(econet_timer.irqs[i]); -+ } - return ret; - } - -+static int __init cevt_init(struct device_node *np) -+{ -+ econet_timer.num_irqs = of_irq_count(np); -+ if (econet_timer.num_irqs <= 0 || econet_timer.num_irqs > ECONET_MAX_IRQS) { -+ pr_err("%pOFn: invalid IRQ count %d\n", np, econet_timer.num_irqs); -+ return -EINVAL; -+ } -+ -+ /* Auto-detect mode based on IRQ count: -+ * 1 IRQ = percpu mode (EN751221) -+ * N IRQs = separate IRQ per CPU (EN7528/EN751627) -+ */ -+ econet_timer.use_percpu_irq = (econet_timer.num_irqs == 1); -+ -+ if (econet_timer.use_percpu_irq) -+ return cevt_init_percpu(np); -+ else -+ return cevt_init_separate(np); -+} -+ - static int __init timer_init(struct device_node *np) - { - int num_blocks = DIV_ROUND_UP(num_possible_cpus(), 2); - struct clk *clk; -- int ret; -+ int ret, i; - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { -@@ -182,11 +260,12 @@ static int __init timer_init(struct devi - - econet_timer.freq_hz = clk_get_rate(clk); - -- for (int i = 0; i < num_blocks; i++) { -+ for (i = 0; i < num_blocks; i++) { - econet_timer.membase[i] = of_iomap(np, i); - if (!econet_timer.membase[i]) { - pr_err("%pOFn: failed to map register [%d]\n", np, i); -- return -ENXIO; -+ ret = -ENXIO; -+ goto err_unmap; - } - } - -@@ -196,21 +275,34 @@ static int __init timer_init(struct devi - clocksource_mmio_readl_up); - if (ret) { - pr_err("%pOFn: clocksource_mmio_init failed: %d", np, ret); -- return ret; -+ goto err_unmap; - } - - ret = cevt_init(np); - if (ret < 0) -- return ret; -+ goto err_unmap; -+ -+ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, -+ "clockevents/econet/timer:starting", -+ cevt_init_cpu, NULL); - - sched_clock_register(sched_clock_read, ECONET_BITS, - econet_timer.freq_hz); - -- pr_info("%pOFn: using %u.%03u MHz high precision timer\n", np, -+ pr_info("%pOFn: using %u.%03u MHz high precision timer (%s mode)\n", np, - econet_timer.freq_hz / 1000000, -- (econet_timer.freq_hz / 1000) % 1000); -+ (econet_timer.freq_hz / 1000) % 1000, -+ econet_timer.use_percpu_irq ? "percpu" : "separate IRQ"); - - return 0; -+ -+err_unmap: -+ for (i = 0; i < num_blocks; i++) { -+ if (econet_timer.membase[i]) -+ iounmap(econet_timer.membase[i]); -+ } -+ return ret; - } - --TIMER_OF_DECLARE(econet_timer_hpt, "econet,en751221-timer", timer_init); -+TIMER_OF_DECLARE(econet_en751221_timer, "econet,en751221-timer", timer_init); -+TIMER_OF_DECLARE(econet_en7528_timer, "econet,en7528-timer", timer_init); diff --git a/target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch b/target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch deleted file mode 100644 index d3f3054fe7..0000000000 --- a/target/linux/econet/patches-6.12/300-spi-Add-support-for-the-Airoha-EN7523-SoC-SPI-contro.patch +++ /dev/null @@ -1,341 +0,0 @@ ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -370,6 +370,12 @@ config SPI_DLN2 - This driver can also be built as a module. If so, the module - will be called spi-dln2. - -+config SPI_AIROHA_EN7523 -+ bool "Airoha EN7523 SPI controller support" -+ depends on ARCH_AIROHA -+ help -+ This enables SPI controller support for the Airoha EN7523 SoC. -+ - config SPI_EP93XX - tristate "Cirrus Logic EP93xx SPI controller" - depends on ARCH_EP93XX || COMPILE_TEST ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -52,6 +52,7 @@ obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1. - obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o - obj-$(CONFIG_SPI_DW_PCI) += spi-dw-pci.o - obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o -+obj-$(CONFIG_SPI_AIROHA_EN7523) += spi-en7523.o - obj-$(CONFIG_SPI_FALCON) += spi-falcon.o - obj-$(CONFIG_SPI_FSI) += spi-fsi.o - obj-$(CONFIG_SPI_FSL_CPM) += spi-fsl-cpm.o ---- /dev/null -+++ b/drivers/spi/spi-en7523.c -@@ -0,0 +1,313 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+#include -+#include -+#include -+#include -+ -+ -+#define ENSPI_READ_IDLE_EN 0x0004 -+#define ENSPI_MTX_MODE_TOG 0x0014 -+#define ENSPI_RDCTL_FSM 0x0018 -+#define ENSPI_MANUAL_EN 0x0020 -+#define ENSPI_MANUAL_OPFIFO_EMPTY 0x0024 -+#define ENSPI_MANUAL_OPFIFO_WDATA 0x0028 -+#define ENSPI_MANUAL_OPFIFO_FULL 0x002C -+#define ENSPI_MANUAL_OPFIFO_WR 0x0030 -+#define ENSPI_MANUAL_DFIFO_FULL 0x0034 -+#define ENSPI_MANUAL_DFIFO_WDATA 0x0038 -+#define ENSPI_MANUAL_DFIFO_EMPTY 0x003C -+#define ENSPI_MANUAL_DFIFO_RD 0x0040 -+#define ENSPI_MANUAL_DFIFO_RDATA 0x0044 -+#define ENSPI_IER 0x0090 -+#define ENSPI_NFI2SPI_EN 0x0130 -+ -+// TODO not in spi block -+#define ENSPI_CLOCK_DIVIDER ((void __iomem *)0x1fa201c4) -+ -+#define OP_CSH 0x00 -+#define OP_CSL 0x01 -+#define OP_CK 0x02 -+#define OP_OUTS 0x08 -+#define OP_OUTD 0x09 -+#define OP_OUTQ 0x0A -+#define OP_INS 0x0C -+#define OP_INS0 0x0D -+#define OP_IND 0x0E -+#define OP_INQ 0x0F -+#define OP_OS2IS 0x10 -+#define OP_OS2ID 0x11 -+#define OP_OS2IQ 0x12 -+#define OP_OD2IS 0x13 -+#define OP_OD2ID 0x14 -+#define OP_OD2IQ 0x15 -+#define OP_OQ2IS 0x16 -+#define OP_OQ2ID 0x17 -+#define OP_OQ2IQ 0x18 -+#define OP_OSNIS 0x19 -+#define OP_ODNID 0x1A -+ -+#define MATRIX_MODE_AUTO 1 -+#define CONF_MTX_MODE_AUTO 0 -+#define MANUALEN_AUTO 0 -+#define MATRIX_MODE_MANUAL 0 -+#define CONF_MTX_MODE_MANUAL 9 -+#define MANUALEN_MANUAL 1 -+ -+#define _ENSPI_MAX_XFER 0x1ff -+ -+#define REG(x) (iobase + x) -+ -+ -+static void __iomem *iobase; -+ -+ -+static void opfifo_write(u32 cmd, u32 len) -+{ -+ u32 tmp = ((cmd & 0x1f) << 9) | (len & 0x1ff); -+ -+ writel(tmp, REG(ENSPI_MANUAL_OPFIFO_WDATA)); -+ -+ /* Wait for room in OPFIFO */ -+ while (readl(REG(ENSPI_MANUAL_OPFIFO_FULL))) -+ ; -+ -+ /* Shift command into OPFIFO */ -+ writel(1, REG(ENSPI_MANUAL_OPFIFO_WR)); -+ -+ /* Wait for command to finish */ -+ while (!readl(REG(ENSPI_MANUAL_OPFIFO_EMPTY))) -+ ; -+} -+ -+static void set_cs(int state) -+{ -+ if (state) -+ opfifo_write(OP_CSH, 1); -+ else -+ opfifo_write(OP_CSL, 1); -+} -+ -+static void manual_begin_cmd(void) -+{ -+ /* Disable read idle state */ -+ writel(0, REG(ENSPI_READ_IDLE_EN)); -+ -+ /* Wait for FSM to reach idle state */ -+ while (readl(REG(ENSPI_RDCTL_FSM))) -+ ; -+ -+ /* Set SPI core to manual mode */ -+ writel(CONF_MTX_MODE_MANUAL, REG(ENSPI_MTX_MODE_TOG)); -+ writel(MANUALEN_MANUAL, REG(ENSPI_MANUAL_EN)); -+} -+ -+static void manual_end_cmd(void) -+{ -+ /* Set SPI core to auto mode */ -+ writel(CONF_MTX_MODE_AUTO, REG(ENSPI_MTX_MODE_TOG)); -+ writel(MANUALEN_AUTO, REG(ENSPI_MANUAL_EN)); -+ -+ /* Enable read idle state */ -+ writel(1, REG(ENSPI_READ_IDLE_EN)); -+} -+ -+static void dfifo_read(u8 *buf, int len) -+{ -+ int i; -+ -+ for (i = 0; i < len; i++) { -+ /* Wait for requested data to show up in DFIFO */ -+ while (readl(REG(ENSPI_MANUAL_DFIFO_EMPTY))) -+ ; -+ buf[i] = readl(REG(ENSPI_MANUAL_DFIFO_RDATA)); -+ /* Queue up next byte */ -+ writel(1, REG(ENSPI_MANUAL_DFIFO_RD)); -+ } -+} -+ -+static void dfifo_write(const u8 *buf, int len) -+{ -+ int i; -+ -+ for (i = 0; i < len; i++) { -+ /* Wait for room in DFIFO */ -+ while (readl(REG(ENSPI_MANUAL_DFIFO_FULL))) -+ ; -+ writel(buf[i], REG(ENSPI_MANUAL_DFIFO_WDATA)); -+ } -+} -+ -+#if 0 -+static void set_spi_clock_speed(int freq_mhz) -+{ -+ u32 tmp, val; -+ -+ tmp = readl(ENSPI_CLOCK_DIVIDER); -+ tmp &= 0xffff0000; -+ writel(tmp, ENSPI_CLOCK_DIVIDER); -+ -+ val = (400 / (freq_mhz * 2)); -+ tmp |= (val << 8) | 1; -+ writel(tmp, ENSPI_CLOCK_DIVIDER); -+} -+#endif -+ -+static void init_hw(void) -+{ -+ /* Disable manual/auto mode clash interrupt */ -+ writel(0, REG(ENSPI_IER)); -+ -+ // TODO via clk framework -+ // set_spi_clock_speed(50); -+ -+ /* Disable DMA */ -+ writel(0, REG(ENSPI_NFI2SPI_EN)); -+} -+ -+static int xfer_read(struct spi_transfer *xfer) -+{ -+ int opcode; -+ uint8_t *buf = xfer->rx_buf; -+ -+ switch (xfer->rx_nbits) { -+ case SPI_NBITS_SINGLE: -+ opcode = OP_INS; -+ break; -+ case SPI_NBITS_DUAL: -+ opcode = OP_IND; -+ break; -+ case SPI_NBITS_QUAD: -+ opcode = OP_INQ; -+ break; -+ } -+ -+ opfifo_write(opcode, xfer->len); -+ dfifo_read(buf, xfer->len); -+ -+ return xfer->len; -+} -+ -+static int xfer_write(struct spi_transfer *xfer, int next_xfer_is_rx) -+{ -+ int opcode; -+ const uint8_t *buf = xfer->tx_buf; -+ -+ if (next_xfer_is_rx) { -+ /* need to use Ox2Ix opcode to set the core to input afterwards */ -+ switch (xfer->tx_nbits) { -+ case SPI_NBITS_SINGLE: -+ opcode = OP_OS2IS; -+ break; -+ case SPI_NBITS_DUAL: -+ opcode = OP_OS2ID; -+ break; -+ case SPI_NBITS_QUAD: -+ opcode = OP_OS2IQ; -+ break; -+ } -+ } else { -+ switch (xfer->tx_nbits) { -+ case SPI_NBITS_SINGLE: -+ opcode = OP_OUTS; -+ break; -+ case SPI_NBITS_DUAL: -+ opcode = OP_OUTD; -+ break; -+ case SPI_NBITS_QUAD: -+ opcode = OP_OUTQ; -+ break; -+ } -+ } -+ -+ opfifo_write(opcode, xfer->len); -+ dfifo_write(buf, xfer->len); -+ -+ return xfer->len; -+} -+ -+size_t max_transfer_size(struct spi_device *spi) -+{ -+ return _ENSPI_MAX_XFER; -+} -+ -+int transfer_one_message(struct spi_controller *ctrl, struct spi_message *msg) -+{ -+ struct spi_transfer *xfer; -+ int next_xfer_is_rx = 0; -+ -+ manual_begin_cmd(); -+ set_cs(0); -+ list_for_each_entry(xfer, &msg->transfers, transfer_list) { -+ if (xfer->tx_buf) { -+ if (!list_is_last(&xfer->transfer_list, &msg->transfers) -+ && list_next_entry(xfer, transfer_list)->rx_buf != NULL) -+ next_xfer_is_rx = 1; -+ else -+ next_xfer_is_rx = 0; -+ msg->actual_length += xfer_write(xfer, next_xfer_is_rx); -+ } else if (xfer->rx_buf) { -+ msg->actual_length += xfer_read(xfer); -+ } -+ } -+ set_cs(1); -+ manual_end_cmd(); -+ -+ msg->status = 0; -+ spi_finalize_current_message(ctrl); -+ -+ return 0; -+} -+ -+static int spi_probe(struct platform_device *pdev) -+{ -+ struct spi_controller *ctrl; -+ int err; -+ -+ ctrl = devm_spi_alloc_master(&pdev->dev, 0); -+ if (!ctrl) { -+ dev_err(&pdev->dev, "Error allocating SPI controller\n"); -+ return -ENOMEM; -+ } -+ -+ iobase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); -+ if (IS_ERR(iobase)) { -+ dev_err(&pdev->dev, "Could not map SPI register address"); -+ return -ENOMEM; -+ } -+ -+ init_hw(); -+ -+ ctrl->dev.of_node = pdev->dev.of_node; -+ ctrl->flags = SPI_CONTROLLER_HALF_DUPLEX; -+ ctrl->mode_bits = SPI_RX_DUAL | SPI_TX_DUAL; -+ ctrl->max_transfer_size = max_transfer_size; -+ ctrl->transfer_one_message = transfer_one_message; -+ err = devm_spi_register_controller(&pdev->dev, ctrl); -+ if (err) { -+ dev_err(&pdev->dev, "Could not register SPI controller\n"); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static const struct of_device_id spi_of_ids[] = { -+ { .compatible = "airoha,en7523-spi" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, spi_of_ids); -+ -+static struct platform_driver spi_driver = { -+ .probe = spi_probe, -+ .driver = { -+ .name = "airoha-en7523-spi", -+ .of_match_table = spi_of_ids, -+ }, -+}; -+ -+module_platform_driver(spi_driver); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Bert Vermeulen "); -+MODULE_DESCRIPTION("Airoha EN7523 SPI driver"); diff --git a/target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch b/target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch deleted file mode 100644 index 888df7552e..0000000000 --- a/target/linux/econet/patches-6.12/301-spi-Airoha-adapt-to-support-en75-mips.patch +++ /dev/null @@ -1,56 +0,0 @@ -Subject: Adapt Airoha EN7523 SPI to work with EcoNet EN751221 - -The SPI driver from Airoha EN7523 is copied here in it's original form -so this patch makes three updates to it in order to make it work -correctly in the EcoNet EN751221 context. - -The main change here is that the chip select operation is sent twice. -This pattern is borrowed from the vendor code and it prevents write -operations from being lost sporadically on the EN751221. - -Signed-off-by: Caleb James DeLisle ---- ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -372,7 +372,7 @@ config SPI_DLN2 - - config SPI_AIROHA_EN7523 - bool "Airoha EN7523 SPI controller support" -- depends on ARCH_AIROHA -+ depends on ARCH_AIROHA || ECONET - help - This enables SPI controller support for the Airoha EN7523 SoC. - ---- a/drivers/spi/spi-en7523.c -+++ b/drivers/spi/spi-en7523.c -@@ -82,10 +82,11 @@ static void opfifo_write(u32 cmd, u32 le - - static void set_cs(int state) - { -- if (state) -- opfifo_write(OP_CSH, 1); -- else -- opfifo_write(OP_CSL, 1); -+ u32 cmd = state ? OP_CSH : OP_CSL; -+ -+ /* EN751221 drops writes if we don't send this twice. */ -+ opfifo_write(cmd, 1); -+ opfifo_write(cmd, 1); - } - - static void manual_begin_cmd(void) -@@ -226,12 +227,12 @@ static int xfer_write(struct spi_transfe - return xfer->len; - } - --size_t max_transfer_size(struct spi_device *spi) -+static size_t max_transfer_size(struct spi_device *spi) - { - return _ENSPI_MAX_XFER; - } - --int transfer_one_message(struct spi_controller *ctrl, struct spi_message *msg) -+static int transfer_one_message(struct spi_controller *ctrl, struct spi_message *msg) - { - struct spi_transfer *xfer; - int next_xfer_is_rx = 0; diff --git a/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch b/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch deleted file mode 100644 index 8556633d01..0000000000 --- a/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch +++ /dev/null @@ -1,21 +0,0 @@ -spi: airoha-snfi: enable for EcoNet EN7528 - -Enable the Airoha SNFI (SPI NAND Flash Interface) driver for EcoNet -EN7528 SoC. The EN7528 shares the same SPI controller and NFI DMA -engine as the Airoha EN7523/EN7581, with identical register layouts. - -Using the DMA-capable SNFI driver provides significantly better -performance compared to the manual mode spi-en7523 driver. - -Signed-off-by: Ahmed Naseef ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -59,7 +59,7 @@ comment "SPI Master Controller Drivers" - - config SPI_AIROHA_SNFI - tristate "Airoha SPI NAND Flash Interface" -- depends on ARCH_AIROHA || COMPILE_TEST -+ depends on ARCH_AIROHA || ECONET || COMPILE_TEST - depends on SPI_MASTER - select REGMAP_MMIO - help diff --git a/target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch b/target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch deleted file mode 100644 index a550bbfae5..0000000000 --- a/target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -391,6 +391,7 @@ config MACH_DECSTATION - config ECONET - bool "EcoNet MIPS family" - select BOOT_RAW -+ select DMA_NONCOHERENT - select DEBUG_ZBOOT if DEBUG_KERNEL - select EARLY_PRINTK_8250 - select ECONET_EN751221_TIMER ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -71,7 +71,7 @@ config USB_XHCI_HISTB - config USB_XHCI_MTK - tristate "xHCI support for MediaTek SoCs" - select MFD_SYSCON -- depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || COMPILE_TEST -+ depends on (MIPS && SOC_MT7621) || ECONET || ARCH_MEDIATEK || COMPILE_TEST - help - Say 'Y' to enable the support for the xHCI host controller - found in MediaTek SoCs. diff --git a/target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch b/target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch deleted file mode 100644 index 09e86ff5c9..0000000000 --- a/target/linux/econet/patches-6.12/320-gpio-en7523-enable-for-econet-mips.patch +++ /dev/null @@ -1,17 +0,0 @@ -gpio: en7523: enable for EcoNet MIPS platform - -The Airoha EN7523 GPIO controller is also found on EcoNet EN7528 -MIPS SoC. Allow building the driver when ECONET is selected. - -Signed-off-by: Ahmed Naseef ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -271,7 +271,7 @@ config GPIO_EM - - config GPIO_EN7523 - tristate "Airoha GPIO support" -- depends on ARCH_AIROHA -+ depends on ARCH_AIROHA || ECONET - default ARCH_AIROHA - select GPIO_GENERIC - select GPIOLIB_IRQCHIP diff --git a/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch b/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch deleted file mode 100644 index 486208f71a..0000000000 --- a/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch +++ /dev/null @@ -1,206 +0,0 @@ ---- /dev/null -+++ b/drivers/tty/serial/8250/8250_en7523.c -@@ -0,0 +1,94 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Airoha EN7523 driver. -+ * -+ * Copyright (c) 2022 Genexis Sweden AB -+ * Author: Benjamin Larsson -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "8250.h" -+ -+ -+/* The Airoha UART is 16550-compatible except for the baud rate calculation. -+ * -+ * crystal_clock = 20 MHz -+ * xindiv_clock = crystal_clock / clock_div -+ * (x/y) = XYD, 32 bit register with 16 bits of x and and then 16 bits of y -+ * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), -+ * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] -+ * -+ * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) -+ * -+ * XYD_y seems to need to be larger then XYD_x for things to work. -+ * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values -+ * for usual baud rates. -+ * -+ * Selecting divider needs to fulfill -+ * 1.8432 MHz <= xindiv_clk <= APB clock / 2 -+ * The clocks are unknown but a divider of value 1 did not work. -+ * -+ * Optimally the XYD, BRD and XINCLK_DIVCNT registers could be searched to -+ * find values that gives the least error for every baud rate. But searching -+ * the space takes time and in practise only a few rates are of interest. -+ * With some value combinations not working a tested subset is used giving -+ * a usable range from 110 to 460800 baud. -+ */ -+ -+#define CLOCK_DIV_TAB_ELEMS 3 -+#define XYD_Y 65000 -+#define XINDIV_CLOCK 20000000 -+#define UART_BRDL_20M 0x01 -+#define UART_BRDH_20M 0x00 -+ -+static int clock_div_tab[] = { 10, 4, 2}; -+static int clock_div_reg[] = { 4, 2, 1}; -+ -+ -+int en7523_set_uart_baud_rate (struct uart_port *port, unsigned int baud) -+{ -+ struct uart_8250_port *up = up_to_u8250p(port); -+ unsigned int xyd_x, nom, denom; -+ int i; -+ -+ /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */ -+ serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); -+ -+ /* set baud rate calculation defaults */ -+ -+ /* set BRDIV ([BRDH,BRDL]) to 1 */ -+ serial_port_out(port, UART_BRDL, UART_BRDL_20M); -+ serial_port_out(port, UART_BRDH, UART_BRDH_20M); -+ -+ /* calculate XYD_x and XINCLKDR register */ -+ -+ for (i = 0 ; i < CLOCK_DIV_TAB_ELEMS ; i++) { -+ denom = (XINDIV_CLOCK/40) / clock_div_tab[i]; -+ nom = (baud * (XYD_Y/40)); -+ xyd_x = ((nom/denom) << 4); -+ if (xyd_x < XYD_Y) break; -+ } -+ -+ serial_port_out(port, UART_XINCLKDR, clock_div_reg[i]); -+ serial_port_out(port, UART_XYD, (xyd_x<<16) | XYD_Y); -+ -+ /* unset DLAB */ -+ serial_port_out(port, UART_LCR, up->lcr); -+ -+ return 0; -+} -+ -+EXPORT_SYMBOL_GPL(en7523_set_uart_baud_rate); ---- a/drivers/tty/serial/8250/8250_of.c -+++ b/drivers/tty/serial/8250/8250_of.c -@@ -341,6 +341,7 @@ static const struct of_device_id of_plat - { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, - { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, - { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, -+ { .compatible = "airoha,en7523-uart", .data = (void *)PORT_AIROHA, }, - { /* end of list */ }, - }; - MODULE_DEVICE_TABLE(of, of_platform_serial_table); ---- a/drivers/tty/serial/8250/8250_port.c -+++ b/drivers/tty/serial/8250/8250_port.c -@@ -319,6 +319,14 @@ static const struct serial8250_config ua - .rxtrig_bytes = {1, 8, 16, 30}, - .flags = UART_CAP_FIFO | UART_CAP_AFE, - }, -+ [PORT_AIROHA] = { -+ .name = "Airoha 16550", -+ .fifo_size = 8, -+ .tx_loadsz = 1, -+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01, -+ .rxtrig_bytes = {1, 4}, -+ .flags = UART_CAP_FIFO, -+ }, - }; - - /* Uart divisor latch read */ -@@ -2841,6 +2849,12 @@ serial8250_do_set_termios(struct uart_po - - serial8250_set_divisor(port, baud, quot, frac); - -+#ifdef CONFIG_SERIAL_8250_AIROHA -+ /* Airoha SoCs have custom registers for baud rate settings */ -+ if (port->type == PORT_AIROHA) -+ en7523_set_uart_baud_rate(port, baud); -+#endif -+ - /* - * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR - * is written without DLAB set, this mode will be disabled. ---- a/drivers/tty/serial/8250/Kconfig -+++ b/drivers/tty/serial/8250/Kconfig -@@ -355,6 +355,16 @@ config SERIAL_8250_ACORN - system, say Y to this option. The driver can handle 1, 2, or 3 port - cards. If unsure, say N. - -+config SERIAL_8250_AIROHA -+ tristate "Airoha UART support" -+ depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250 -+ help -+ Selecting this option enables an Airoha SoC specific baud rate -+ calculation routine on an otherwise 16550 compatible UART hardware. -+ -+ If you have an Airoha based board and want to use the serial port, -+ say Y to this option. If unsure, say N. -+ - config SERIAL_8250_BCM2835AUX - tristate "BCM2835 auxiliar mini UART support" - depends on ARCH_BCM2835 || COMPILE_TEST ---- a/drivers/tty/serial/8250/Makefile -+++ b/drivers/tty/serial/8250/Makefile -@@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 825 - - obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o - obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o -+obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_en7523.o - obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o - obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o - obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o ---- a/include/uapi/linux/serial_reg.h -+++ b/include/uapi/linux/serial_reg.h -@@ -383,5 +383,17 @@ - #define UART_ALTR_EN_TXFIFO_LW 0x01 /* Enable the TX FIFO Low Watermark */ - #define UART_ALTR_TX_LOW 0x41 /* Tx FIFO Low Watermark */ - -+/* -+ * These are definitions for the Airoha EN75XX uart registers -+ * Normalized because of 32 bits registers. -+ */ -+#define UART_BRDL 0 -+#define UART_BRDH 1 -+#define UART_XINCLKDR 10 -+#define UART_XYD 11 -+#define UART_TXLVLCNT 12 -+#define UART_RXLVLCNT 13 -+#define UART_FINTLVL 14 -+ - #endif /* _LINUX_SERIAL_REG_H */ - ---- a/include/uapi/linux/serial_core.h -+++ b/include/uapi/linux/serial_core.h -@@ -31,6 +31,7 @@ - #define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */ - #define PORT_RT2880 29 /* Ralink RT2880 internal UART */ - #define PORT_16550A_FSL64 30 /* Freescale 16550 UART with 64 FIFOs */ -+#define PORT_AIROHA 31 /* Airoha 16550 UART */ - - /* - * ARM specific type numbers. These are not currently guaranteed ---- a/include/linux/serial_8250.h -+++ b/include/linux/serial_8250.h -@@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart - void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, - unsigned int quot); - int fsl8250_handle_irq(struct uart_port *port); -+int en7523_set_uart_baud_rate(struct uart_port *port, unsigned int baud); - int serial8250_handle_irq(struct uart_port *port, unsigned int iir); - u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); - void serial8250_read_char(struct uart_8250_port *up, u16 lsr); diff --git a/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch b/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch deleted file mode 100644 index b25d02e969..0000000000 --- a/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch +++ /dev/null @@ -1,18 +0,0 @@ -serial: 8250: airoha: add EcoNet platform support - -The EcoNet EN75xx SoCs use the same UART IP core as the Airoha -AN7523 SoCs. Add ECONET to the Kconfig dependency to enable -the Airoha UART driver for EcoNet platforms. - -Signed-off-by: Ahmed Naseef ---- a/drivers/tty/serial/8250/Kconfig -+++ b/drivers/tty/serial/8250/Kconfig -@@ -357,7 +357,7 @@ config SERIAL_8250_ACORN - - config SERIAL_8250_AIROHA - tristate "Airoha UART support" -- depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250 -+ depends on (ARCH_AIROHA || ECONET || COMPILE_TEST) && OF && SERIAL_8250 - help - Selecting this option enables an Airoha SoC specific baud rate - calculation routine on an otherwise 16550 compatible UART hardware. diff --git a/target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch b/target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch deleted file mode 100644 index 91e184bd96..0000000000 --- a/target/linux/econet/patches-6.12/901-nand-enable-en75-bbt.patch +++ /dev/null @@ -1,40 +0,0 @@ -Subject: Add EcoNet bad block table - -The EcoNet BBT/BMT is used for resolving bad blocks in the flash. -It is implemented in the EcoNet bootloader so you cannot safely -access flash without using it. - -Signed-off-by: Caleb James DeLisle ---- ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -3,7 +3,7 @@ - nandcore-objs := core.o bbt.o - obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o - obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o --obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o -+obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o mtk_bmt_v2.o mtk_bmt_bbt.o mtk_bmt_nmbm.o en75_bmt.o - obj-$(CONFIG_SPI_QPIC_SNAND) += qpic_common.o - obj-$(CONFIG_MTD_NAND_QCOM) += qpic_common.o - obj-y += onenand/ ---- a/drivers/mtd/nand/mtk_bmt.h -+++ b/drivers/mtd/nand/mtk_bmt.h -@@ -77,6 +77,7 @@ extern struct bmt_desc bmtd; - extern const struct mtk_bmt_ops mtk_bmt_v2_ops; - extern const struct mtk_bmt_ops mtk_bmt_bbt_ops; - extern const struct mtk_bmt_ops mtk_bmt_nmbm_ops; -+extern const struct mtk_bmt_ops en75_bmt_ops; - - static inline u32 blk_pg(u16 block) - { ---- a/drivers/mtd/nand/mtk_bmt.c -+++ b/drivers/mtd/nand/mtk_bmt.c -@@ -421,6 +421,8 @@ int mtk_bmt_attach(struct mtd_info *mtd) - bmtd.ops = &mtk_bmt_nmbm_ops; - else if (of_property_read_bool(np, "mediatek,bbt")) - bmtd.ops = &mtk_bmt_bbt_ops; -+ else if (of_property_read_bool(np, "econet,bmt")) -+ bmtd.ops = &en75_bmt_ops; - else - return 0; - diff --git a/target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch b/target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch deleted file mode 100644 index 2dc81292ec..0000000000 --- a/target/linux/econet/patches-6.12/902-snand-mtk-bmt-support.patch +++ /dev/null @@ -1,34 +0,0 @@ ---- a/drivers/mtd/nand/spi/core.c -+++ b/drivers/mtd/nand/spi/core.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) - { -@@ -1604,6 +1605,7 @@ static int spinand_probe(struct spi_mem - if (ret) - return ret; - -+ mtk_bmt_attach(mtd); - ret = mtd_device_register(mtd, NULL, 0); - if (ret) - goto err_spinand_cleanup; -@@ -1611,6 +1613,7 @@ static int spinand_probe(struct spi_mem - return 0; - - err_spinand_cleanup: -+ mtk_bmt_detach(mtd); - spinand_cleanup(spinand); - - return ret; -@@ -1629,6 +1632,7 @@ static int spinand_remove(struct spi_mem - if (ret) - return ret; - -+ mtk_bmt_detach(mtd); - spinand_cleanup(spinand); - - return 0; diff --git a/target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch b/target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch deleted file mode 100644 index 37dc36cacc..0000000000 --- a/target/linux/econet/patches-6.12/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch +++ /dev/null @@ -1,176 +0,0 @@ -From f3fa5911b1f094e164c497f7b10d94d92852e285 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 14 Jan 2026 17:54:05 +0000 -Subject: [PATCH] dt-bindings: clock, reset: Add econet EN751221 bindings - -Add clock and reset bindings for EN751221 based on the Airoha EN7523 SCU -driver. - -Signed-off-by: Caleb James DeLisle ---- -The EN751221 has the same bifurcation of SCU as EN7581 so we use -the same chip-scu as airoha,en7581-chip-scu. ---- - .../bindings/clock/airoha,en7523-scu.yaml | 17 +++++++- - .../mips/econet,en751221-chip-scu.yaml | 42 +++++++++++++++++++ - .../dt-bindings/clock/econet,en751221-scu.h | 14 +++++++ - .../dt-bindings/reset/econet,en751221-scu.h | 41 ++++++++++++++++++ - 4 files changed, 113 insertions(+), 1 deletion(-) - create mode 100644 Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml - create mode 100644 include/dt-bindings/clock/econet,en751221-scu.h - create mode 100644 include/dt-bindings/reset/econet,en751221-scu.h - ---- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml -+++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml -@@ -32,6 +32,7 @@ properties: - - enum: - - airoha,en7523-scu - - airoha,en7581-scu -+ - econet,en751221-scu - - reg: - items: -@@ -67,7 +68,10 @@ allOf: - - if: - properties: - compatible: -- const: airoha,en7581-scu -+ items: -+ - enum: -+ - airoha,en7581-scu -+ - econet,en751221-scu - then: - properties: - reg: -@@ -98,3 +102,14 @@ examples: - #reset-cells = <1>; - }; - }; -+ -+ - | -+ soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ scuclk: clock-controller@1fb00000 { -+ compatible = "econet,en751221-scu"; -+ reg = <0x1fb00000 0x970>; -+ }; -+ }; -\ No newline at end of file ---- /dev/null -+++ b/Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml -@@ -0,0 +1,42 @@ -+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/arm/airoha,en7581-chip-scu.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet Chip SCU Controller for EN751221 SoC -+ -+maintainers: -+ - Caleb James DeLisle -+ -+description: -+ The EcoNet chip-scu block provides a configuration interface for clock, -+ io-muxing and other functionalities used by multiple controllers (e.g. clock, -+ pinctrl, ecc) on EN751221 SoC. -+ -+properties: -+ compatible: -+ items: -+ - enum: -+ - econet,en751221-chip-scu -+ - const: syscon -+ -+ reg: -+ maxItems: 1 -+ -+required: -+ - compatible -+ - reg -+ -+additionalProperties: false -+ -+examples: -+ - | -+ soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ syscon@1fa20000 { -+ compatible = "econet,en751221-chip-scu", "syscon"; -+ reg = <0x1fa20000 0x388>; -+ }; -+ }; ---- /dev/null -+++ b/include/dt-bindings/clock/econet,en751221-scu.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+ -+#ifndef _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ -+#define _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ -+ -+#define EN751221_CLK_PCIE 0 -+#define EN751221_CLK_SPI 1 -+#define EN751221_CLK_BUS 2 -+#define EN751221_CLK_CPU 3 -+#define EN751221_CLK_HPT 4 -+#define EN751221_CLK_GSW 5 -+ -+#define EN751221_MAX_CLKS 6 -+ -+#endif /* _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ */ -\ No newline at end of file ---- /dev/null -+++ b/include/dt-bindings/reset/econet,en751221-scu.h -@@ -0,0 +1,49 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+ -+#ifndef __DT_BINDINGS_RESET_CONTROLLER_ECONET_EN751221_H_ -+#define __DT_BINDINGS_RESET_CONTROLLER_ECONET_EN751221_H_ -+ -+#define EN751221_XPON_PHY_RST 0 -+#define EN751221_PCM1_ZSI_ISI_RST 1 -+#define EN751221_FE_QDMA1_RST 2 -+#define EN751221_FE_QDMA2_RST 3 -+#define EN751221_FE_UNZIP_RST 4 -+#define EN751221_PCM2_RST 5 -+#define EN751221_PTM_MAC_RST 6 -+#define EN751221_CRYPTO_RST 7 -+#define EN751221_SAR_RST 8 -+#define EN751221_TIMER_RST 9 -+#define EN751221_INTC_RST 10 -+#define EN751221_BONDING_RST 11 -+#define EN751221_PCM1_RST 12 -+#define EN751221_UART_RST 13 -+#define EN751221_GPIO_RST 14 -+#define EN751221_GDMA_RST 15 -+#define EN751221_I2C_MASTER_RST 16 -+#define EN751221_PCM2_ZSI_ISI_RST 17 -+#define EN751221_SFC_RST 18 -+#define EN751221_UART2_RST 19 -+#define EN751221_GDMP_RST 20 -+#define EN751221_FE_RST 21 -+#define EN751221_USB_HOST_P0_RST 22 -+#define EN751221_GSW_RST 23 -+#define EN751221_SFC2_PCM_RST 24 -+#define EN751221_PCIE0_RST 25 -+#define EN751221_PCIE1_RST 26 -+#define EN751221_CPU_TIMER_RST 27 -+#define EN751221_PCIE_HB_RST 28 -+#define EN751221_SIMIF_RST 29 -+#define EN751221_XPON_MAC_RST 30 -+#define EN751221_GFAST_RST 31 -+#define EN751221_CPU_TIMER2_RST 32 -+#define EN751221_UART3_RST 33 -+#define EN751221_UART4_RST 34 -+#define EN751221_UART5_RST 35 -+#define EN751221_I2C2_RST 36 -+#define EN751221_XSI_MAC_RST 37 -+#define EN751221_XSI_PHY_RST 38 -+#define EN751221_DMT_RST 39 -+#define EN751221_USB_PHY_P0_RST 40 -+#define EN751221_USB_PHY_P1_RST 41 -+ -+#endif /* __DT_BINDINGS_RESET_CONTROLLER_ECONET_EN751221_H_ */ diff --git a/target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch b/target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch deleted file mode 100644 index 021043a13d..0000000000 --- a/target/linux/econet/patches-6.12/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch +++ /dev/null @@ -1,364 +0,0 @@ -From 1dfb29374a040ba80d378b3465f4e0bcb67f4ba3 Mon Sep 17 00:00:00 2001 -From: Caleb James DeLisle -Date: Wed, 14 Jan 2026 18:06:13 +0000 -Subject: [PATCH] clk: airoha: Add econet EN751221 clock/reset support to - en7523-scu - -EcoNet EN751221 clock/reset driver is significantly similar to the -EN7523 / EN7581, however the EN751221 does not have a neat batch of clock -divider registers so there are fewer known clocks, and the frequency of -each clock is derived differently. This clock driver will probably work -correctly on EN751627, EN7528, and EN7580. - -Signed-off-by: Caleb James DeLisle ---- - drivers/clk/Kconfig | 6 +- - drivers/clk/clk-en7523.c | 182 +++++++++++++++++++++++++++++++++++++++ - 2 files changed, 185 insertions(+), 3 deletions(-) - ---- a/drivers/clk/Kconfig -+++ b/drivers/clk/Kconfig -@@ -210,13 +210,13 @@ config COMMON_CLK_CS2000_CP - If you say yes here you get support for the CS2000 clock multiplier. - - config COMMON_CLK_EN7523 -- bool "Clock driver for Airoha EN7523 SoC system clocks" -+ bool "Clock driver for Airoha/EcoNet SoC system clocks" - depends on OF -- depends on ARCH_AIROHA || COMPILE_TEST -+ depends on ARCH_AIROHA || ECONET || COMPILE_TEST - default ARCH_AIROHA - help - This driver provides the fixed clocks and gates present on Airoha -- ARM silicon. -+ and EcoNet silicon. - - config COMMON_CLK_EP93XX - tristate "Clock driver for Cirrus Logic ep93xx SoC" ---- a/drivers/clk/clk-en7523.c -+++ b/drivers/clk/clk-en7523.c -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0-only - -+#include - #include - #include - #include -@@ -11,6 +12,8 @@ - #include - #include - #include -+#include -+#include - - #define RST_NR_PER_BANK 32 - -@@ -33,15 +36,47 @@ - #define REG_RESET_CONTROL_PCIEHB BIT(29) - #define REG_RESET_CONTROL_PCIE1 BIT(27) - #define REG_RESET_CONTROL_PCIE2 BIT(26) -+#define REG_HIR 0x064 -+#define REG_HIR_MASK GENMASK(31, 16) - /* EN7581 */ - #define REG_NP_SCU_PCIC 0x88 - #define REG_NP_SCU_SSTR 0x9c - #define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13) - #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) - #define REG_CRYPTO_CLKSRC2 0x20c -+/* EN751221 */ -+#define EN751221_REG_SPI_DIV 0x0cc -+#define EN751221_REG_SPI_DIV_MASK GENMASK(31,8) -+#define EN751221_SPI_BASE 500000000 -+#define EN751221_SPI_BASE_EN7526C 400000000 -+#define EN751221_REG_BUS 0x284 -+#define EN751221_REG_BUS_MASK GENMASK(21,12) -+#define EN751221_REG_SSR3 0x094 -+#define EN751221_REG_SSR3_GSW_MASK GENMASK(9,8) - - #define REG_RST_CTRL2 0x830 - #define REG_RST_CTRL1 0x834 -+#define EN751221_REG_RST_DMT 0x84 -+#define EN751221_REG_RST_USB 0xec -+ -+enum en_hir { -+ HIR_UNKNOWN = -1, -+ HIR_TC3169 = 0, -+ HIR_TC3182 = 1, -+ HIR_RT65168 = 2, -+ HIR_RT63165 = 3, -+ HIR_RT63365 = 4, -+ HIR_MT751020 = 5, -+ HIR_MT7505 = 6, -+ HIR_EN751221 = 7, -+ HIR_EN7526C = 8, -+ HIR_EN751627 = 9, -+ HIR_EN7580 = 10, -+ HIR_EN7528 = 11, -+ HIR_EN7523 = 12, -+ HIR_EN7581 = 13, -+ HIR_MAX = 14, -+}; - - struct en_clk_desc { - int id; -@@ -93,6 +128,8 @@ static const u32 bus7581_base[] = { 6000 - static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; - static const u32 crypto_base[] = { 540000000, 480000000 }; - static const u32 emmc7581_base[] = { 200000000, 150000000 }; -+/* EN751221 */ -+static const u32 gsw751221_base[] = { 500000000, 250000000, 400000000, 200000000 }; - - static const struct en_clk_desc en7523_base_clks[] = { - { -@@ -300,6 +337,13 @@ static const u16 en7581_rst_ofs[] = { - REG_RST_CTRL1, - }; - -+static const u16 en751221_rst_ofs[] = { -+ REG_RST_CTRL2, -+ REG_RST_CTRL1, -+ EN751221_REG_RST_DMT, -+ EN751221_REG_RST_USB, -+}; -+ - static const u16 en7523_rst_map[] = { - /* RST_CTRL2 */ - [EN7523_XPON_PHY_RST] = 0, -@@ -405,8 +449,61 @@ static const u16 en7581_rst_map[] = { - [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31, - }; - -+static const u16 en751221_rst_map[] = { -+ /* RST_CTRL2 */ -+ [EN751221_XPON_PHY_RST] = 0, -+ [EN751221_GFAST_RST] = 1, -+ [EN751221_CPU_TIMER2_RST] = 2, -+ [EN751221_UART3_RST] = 3, -+ [EN751221_UART4_RST] = 4, -+ [EN751221_UART5_RST] = 5, -+ [EN751221_I2C2_RST] = 6, -+ [EN751221_XSI_MAC_RST] = 7, -+ [EN751221_XSI_PHY_RST] = 8, -+ -+ /* RST_CTRL1 */ -+ [EN751221_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0, -+ [EN751221_FE_QDMA1_RST] = RST_NR_PER_BANK + 1, -+ [EN751221_FE_QDMA2_RST] = RST_NR_PER_BANK + 2, -+ [EN751221_FE_UNZIP_RST] = RST_NR_PER_BANK + 3, -+ [EN751221_PCM2_RST] = RST_NR_PER_BANK + 4, -+ [EN751221_PTM_MAC_RST] = RST_NR_PER_BANK + 5, -+ [EN751221_CRYPTO_RST] = RST_NR_PER_BANK + 6, -+ [EN751221_SAR_RST] = RST_NR_PER_BANK + 7, -+ [EN751221_TIMER_RST] = RST_NR_PER_BANK + 8, -+ [EN751221_INTC_RST] = RST_NR_PER_BANK + 9, -+ [EN751221_BONDING_RST] = RST_NR_PER_BANK + 10, -+ [EN751221_PCM1_RST] = RST_NR_PER_BANK + 11, -+ [EN751221_UART_RST] = RST_NR_PER_BANK + 12, -+ [EN751221_GPIO_RST] = RST_NR_PER_BANK + 13, -+ [EN751221_GDMA_RST] = RST_NR_PER_BANK + 14, -+ [EN751221_I2C_MASTER_RST] = RST_NR_PER_BANK + 16, -+ [EN751221_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17, -+ [EN751221_SFC_RST] = RST_NR_PER_BANK + 18, -+ [EN751221_UART2_RST] = RST_NR_PER_BANK + 19, -+ [EN751221_GDMP_RST] = RST_NR_PER_BANK + 20, -+ [EN751221_FE_RST] = RST_NR_PER_BANK + 21, -+ [EN751221_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22, -+ [EN751221_GSW_RST] = RST_NR_PER_BANK + 23, -+ [EN751221_SFC2_PCM_RST] = RST_NR_PER_BANK + 25, -+ [EN751221_PCIE0_RST] = RST_NR_PER_BANK + 26, -+ [EN751221_PCIE1_RST] = RST_NR_PER_BANK + 27, -+ [EN751221_CPU_TIMER_RST] = RST_NR_PER_BANK + 28, -+ [EN751221_PCIE_HB_RST] = RST_NR_PER_BANK + 29, -+ [EN751221_SIMIF_RST] = RST_NR_PER_BANK + 30, -+ [EN751221_XPON_MAC_RST] = RST_NR_PER_BANK + 31, -+ -+ /* RST_DMT */ -+ [EN751221_DMT_RST] = 2 * RST_NR_PER_BANK + 0, -+ -+ /* RST_USB */ -+ [EN751221_USB_PHY_P0_RST] = 3 * RST_NR_PER_BANK + 6, -+ [EN751221_USB_PHY_P1_RST] = 3 * RST_NR_PER_BANK + 7, -+}; -+ - static int en7581_reset_register(struct device *dev, void __iomem *base, -- const u16 *rst_map, int nr_resets); -+ const u16 *rst_map, int nr_resets, -+ const u16 *rst_reg_ofs); - - static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) - { -@@ -604,7 +701,8 @@ static int en7523_clk_hw_init(struct pla - en7523_register_clocks(&pdev->dev, clk_data, base, np_base); - - return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map, -- ARRAY_SIZE(en7523_rst_map)); -+ ARRAY_SIZE(en7523_rst_map), -+ en7581_rst_ofs); - } - - static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, -@@ -705,7 +803,8 @@ static const struct reset_control_ops en - }; - - static int en7581_reset_register(struct device *dev, void __iomem *base, -- const u16 *rst_map, int nr_resets) -+ const u16 *rst_map, int nr_resets, -+ const u16 *rst_reg_ofs) - { - struct en_rst_data *rst_data; - -@@ -713,7 +812,7 @@ static int en7581_reset_register(struct - if (!rst_data) - return -ENOMEM; - -- rst_data->bank_ofs = en7581_rst_ofs; -+ rst_data->bank_ofs = rst_reg_ofs; - rst_data->idx_map = rst_map; - rst_data->base = base; - -@@ -752,7 +851,123 @@ static int en7581_clk_hw_init(struct pla - writel(val | 3, base + REG_NP_SCU_PCIC); - - return en7581_reset_register(&pdev->dev, base, en7581_rst_map, -- ARRAY_SIZE(en7581_rst_map)); -+ ARRAY_SIZE(en7581_rst_map), -+ en7581_rst_ofs); -+} -+ -+static enum en_hir get_hw_id(void __iomem *np_base) -+{ -+ u32 val = FIELD_GET(REG_HIR_MASK, readl(np_base + REG_HIR)); -+ -+ if (val < HIR_MAX) -+ return (enum en_hir) val; -+ -+ return HIR_UNKNOWN; -+} -+ -+static void en751221_try_register_clk(struct device *dev, int key, -+ struct clk_hw_onecell_data *clk_data, -+ const char *name, u32 rate) -+{ -+ struct clk_hw *hw; -+ -+ hw = clk_hw_register_fixed_rate(dev, name, NULL, 0, rate); -+ if (IS_ERR(hw)) -+ pr_err("Failed to register clk %s: %pe\n", name, hw); -+ else -+ clk_data->hws[key] = hw; -+} -+ -+static void en751221_register_clocks(struct device *dev, -+ struct clk_hw_onecell_data *clk_data, -+ struct regmap *map, void __iomem *np_base) -+{ -+ enum en_hir hid = get_hw_id(np_base); -+ struct clk_hw *hw; -+ u32 rate; -+ u32 div; -+ int err; -+ -+ /* PCI */ -+ hw = en7523_register_pcie_clk(dev, np_base); -+ clk_data->hws[EN751221_CLK_PCIE] = hw; -+ -+ /* SPI */ -+ rate = EN751221_SPI_BASE; -+ if (hid == HIR_EN7526C) -+ rate = EN751221_SPI_BASE_EN7526C; -+ -+ err = regmap_read(map, EN751221_REG_SPI_DIV, &div); -+ if (err) { -+ pr_err("Failed reading fixed clk div %s: %d\n", -+ "spi", err); -+ } else { -+ div = FIELD_GET(EN751221_REG_SPI_DIV_MASK, div) * 2; -+ if (!div) -+ div = 40; -+ -+ en751221_try_register_clk(dev, EN751221_CLK_SPI, clk_data, -+ "spi", rate / div); -+ } -+ -+ /* BUS */ -+ rate = FIELD_GET(EN751221_REG_BUS_MASK, -+ readl(np_base + EN751221_REG_BUS)); -+ rate *= 1000000; -+ en751221_try_register_clk(dev, EN751221_CLK_BUS, clk_data, "bus", -+ rate); -+ -+ /* CPU */ -+ en751221_try_register_clk(dev, EN751221_CLK_CPU, clk_data, "cpu", -+ rate * 4); -+ -+ /* HPT */ -+ switch (hid) { -+ case HIR_EN751221: -+ case HIR_EN751627: -+ case HIR_EN7526C: -+ case HIR_EN7580: -+ case HIR_EN7528: -+ rate = 200000000; -+ break; -+ case HIR_MT7505: -+ rate = 100000000; -+ break; -+ case HIR_MT751020: -+ rate = 800000000 / 3; -+ break; -+ default: -+ rate = 250000000; -+ } -+ en751221_try_register_clk(dev, EN751221_CLK_HPT, clk_data, "hpt", -+ rate); -+ -+ /* GSW */ -+ rate = FIELD_GET(EN751221_REG_SSR3_GSW_MASK, -+ readl(np_base + EN751221_REG_SSR3)); -+ en751221_try_register_clk(dev, EN751221_CLK_GSW, clk_data, "gsw", -+ gsw751221_base[rate]); -+} -+ -+static int en751221_clk_hw_init(struct platform_device *pdev, -+ struct clk_hw_onecell_data *clk_data) -+{ -+ struct regmap *map; -+ void __iomem *base; -+ -+ map = syscon_regmap_lookup_by_compatible("econet,en751221-chip-scu"); -+ if (IS_ERR(map)) -+ return PTR_ERR(map); -+ -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ en751221_register_clocks(&pdev->dev, clk_data, map, base); -+ -+ return en7581_reset_register(&pdev->dev, base, en751221_rst_map, -+ ARRAY_SIZE(en751221_rst_map), -+ en751221_rst_ofs); - } - - static int en7523_clk_probe(struct platform_device *pdev) -@@ -799,9 +1014,20 @@ static const struct en_clk_soc_data en75 - .hw_init = en7581_clk_hw_init, - }; - -+static const struct en_clk_soc_data en751221_data = { -+ .num_clocks = EN751221_MAX_CLKS, -+ .pcie_ops = { -+ .is_enabled = en7523_pci_is_enabled, -+ .prepare = en7523_pci_prepare, -+ .unprepare = en7523_pci_unprepare, -+ }, -+ .hw_init = en751221_clk_hw_init, -+}; -+ - static const struct of_device_id of_match_clk_en7523[] = { - { .compatible = "airoha,en7523-scu", .data = &en7523_data }, - { .compatible = "airoha,en7581-scu", .data = &en7581_data }, -+ { .compatible = "econet,en751221-scu", .data = &en751221_data }, - { /* sentinel */ } - }; - diff --git a/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch b/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch deleted file mode 100644 index ee8d1bdab9..0000000000 --- a/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch +++ /dev/null @@ -1,373 +0,0 @@ ---- a/drivers/pci/controller/Kconfig -+++ b/drivers/pci/controller/Kconfig -@@ -187,7 +187,7 @@ config PCI_MVEBU - - config PCIE_MEDIATEK - tristate "MediaTek PCIe controller" -- depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST -+ depends on ARCH_AIROHA || ARCH_MEDIATEK || ECONET || COMPILE_TEST - depends on OF - depends on PCI_MSI - help ---- a/arch/mips/econet/Kconfig -+++ b/arch/mips/econet/Kconfig -@@ -14,7 +14,9 @@ choice - select COMMON_CLK - select CPU_BIG_ENDIAN - select ECONET_EN751221_INTC -+ select HAVE_PCI - select IRQ_MIPS_CPU -+ select PCI_DRIVERS_GENERIC - select SMP - select SMP_UP - select SYS_SUPPORTS_SMP -@@ -28,9 +30,11 @@ choice - bool "EN7528 family" - select COMMON_CLK - select CPU_LITTLE_ENDIAN -+ select HAVE_PCI - select IRQ_MIPS_CPU - select MIPS_CPU_SCACHE - select MIPS_GIC -+ select PCI_DRIVERS_GENERIC - select SMP - select SMP_UP - select SYS_SUPPORTS_HIGHMEM ---- a/drivers/pci/controller/pcie-mediatek.c -+++ b/drivers/pci/controller/pcie-mediatek.c -@@ -76,6 +76,7 @@ - - #define PCIE_CONF_VEND_ID 0x100 - #define PCIE_CONF_DEVICE_ID 0x102 -+#define PCIE_CONF_REV_CLASS 0x104 - #define PCIE_CONF_CLASS_ID 0x106 - - #define PCIE_INT_MASK 0x420 -@@ -88,6 +89,11 @@ - #define MSI_MASK BIT(23) - #define MTK_MSI_IRQS_NUM 32 - -+#define EN7528_HOST_MODE 0x00804201 -+#define EN7528_LINKUP_REG 0x50 -+#define EN7528_RC0_LINKUP BIT(1) -+#define EN7528_RC1_LINKUP BIT(2) -+ - #define PCIE_AHB_TRANS_BASE0_L 0x438 - #define PCIE_AHB_TRANS_BASE0_H 0x43c - #define AHB2PCIE_SIZE(x) ((x) & GENMASK(4, 0)) -@@ -750,6 +756,86 @@ static int mtk_pcie_startup_port_v2(stru - return 0; - } - -+static int mtk_pcie_startup_port_en7528(struct mtk_pcie_port *port) -+{ -+ struct mtk_pcie *pcie = port->pcie; -+ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); -+ struct resource *mem = NULL; -+ struct resource_entry *entry; -+ u32 val, link_mask; -+ int err; -+ -+ entry = resource_list_first_type(&host->windows, IORESOURCE_MEM); -+ if (entry) -+ mem = entry->res; -+ if (!mem) -+ return -EINVAL; -+ -+ if (!pcie->cfg) { -+ dev_err(pcie->dev, "EN7528: pciecfg syscon not available\n"); -+ return -EINVAL; -+ } -+ -+ /* Assert all reset signals */ -+ writel(0, port->base + PCIE_RST_CTRL); -+ -+ /* -+ * Enable PCIe link down reset, if link status changed from link up to -+ * link down, this will reset MAC control registers and configuration -+ * space. -+ */ -+ writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL); -+ -+ /* -+ * Described in PCIe CEM specification sections 2.2 (PERST# Signal) and -+ * 2.2.1 (Initial Power-Up (G3 to S0)). The deassertion of PERST# -+ * should be delayed 100ms (TPVPERL) for the power and clock to become -+ * stable. -+ */ -+ msleep(100); -+ -+ /* De-assert PHY, PE, PIPE, MAC and configuration reset */ -+ val = readl(port->base + PCIE_RST_CTRL); -+ val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB | -+ PCIE_MAC_SRSTB | PCIE_CRSTB; -+ writel(val, port->base + PCIE_RST_CTRL); -+ -+ writel(PCIE_CLASS_CODE | PCIE_REVISION_ID, -+ port->base + PCIE_CONF_REV_CLASS); -+ writel(EN7528_HOST_MODE, port->base); -+ -+ link_mask = (port->slot == 0) ? EN7528_RC0_LINKUP : EN7528_RC1_LINKUP; -+ -+ /* 100ms timeout value should be enough for Gen1/2 training */ -+ err = regmap_read_poll_timeout(pcie->cfg, EN7528_LINKUP_REG, val, -+ !!(val & link_mask), 20, -+ 100 * USEC_PER_MSEC); -+ if (err) { -+ dev_err(pcie->dev, "EN7528: port%d link timeout\n", port->slot); -+ return -ETIMEDOUT; -+ } -+ -+ /* Set INTx mask */ -+ val = readl(port->base + PCIE_INT_MASK); -+ val &= ~INTX_MASK; -+ writel(val, port->base + PCIE_INT_MASK); -+ -+ if (IS_ENABLED(CONFIG_PCI_MSI)) -+ mtk_pcie_enable_msi(port); -+ -+ /* Set AHB to PCIe translation windows */ -+ val = lower_32_bits(mem->start) | -+ AHB2PCIE_SIZE(fls(resource_size(mem))); -+ writel(val, port->base + PCIE_AHB_TRANS_BASE0_L); -+ -+ val = upper_32_bits(mem->start); -+ writel(val, port->base + PCIE_AHB_TRANS_BASE0_H); -+ -+ writel(WIN_ENABLE, port->base + PCIE_AXI_WINDOW0); -+ -+ return 0; -+} -+ - static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus, - unsigned int devfn, int where) - { -@@ -1116,6 +1202,20 @@ static int mtk_pcie_probe(struct platfor - if (err) - goto put_resources; - -+ /* Retrain Gen1 links to reach Gen2 where supported */ -+ if (pcie->soc->startup == mtk_pcie_startup_port_en7528) { -+ struct pci_bus *bus = host->bus; -+ struct pci_dev *rc = NULL; -+ -+ while ((rc = pci_get_class(PCI_CLASS_BRIDGE_PCI << 8, rc))) { -+ if (rc->bus != bus) -+ continue; -+ if (!pcie_retrain_link(rc, true)) -+ dev_info(dev, "port%d link retrained\n", -+ PCI_SLOT(rc->devfn)); -+ } -+ } -+ - return 0; - - put_resources: -@@ -1225,12 +1325,19 @@ static const struct mtk_pcie_soc mtk_pci - .setup_irq = mtk_pcie_setup_irq, - }; - -+static const struct mtk_pcie_soc mtk_pcie_soc_en7528 = { -+ .ops = &mtk_pcie_ops_v2, -+ .startup = mtk_pcie_startup_port_en7528, -+ .setup_irq = mtk_pcie_setup_irq, -+}; -+ - static const struct of_device_id mtk_pcie_ids[] = { - { .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 }, - { .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 }, - { .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_mt2712 }, - { .compatible = "mediatek,mt7622-pcie", .data = &mtk_pcie_soc_mt7622 }, - { .compatible = "mediatek,mt7629-pcie", .data = &mtk_pcie_soc_mt7629 }, -+ { .compatible = "econet,en7528-pcie", .data = &mtk_pcie_soc_en7528 }, - {}, - }; - MODULE_DEVICE_TABLE(of, mtk_pcie_ids); ---- a/drivers/phy/Kconfig -+++ b/drivers/phy/Kconfig -@@ -82,6 +82,17 @@ config PHY_AIROHA_PCIE - This driver create the basic PHY instance and provides initialize - callback for PCIe GEN3 port. - -+config PHY_EN7528_PCIE -+ tristate "EcoNet EN7528 PCIe PHY Driver" -+ depends on ECONET || COMPILE_TEST -+ depends on OF -+ select GENERIC_PHY -+ select REGMAP_MMIO -+ help -+ Say Y here to add support for EcoNet EN7528 PCIe PHY driver. -+ This driver provides PHY initialization for the two PCIe ports -+ on EN7528 SoC. -+ - source "drivers/phy/allwinner/Kconfig" - source "drivers/phy/amlogic/Kconfig" - source "drivers/phy/broadcom/Kconfig" ---- a/drivers/phy/Makefile -+++ b/drivers/phy/Makefile -@@ -11,6 +11,7 @@ obj-$(CONFIG_PHY_XGENE) += phy-xgene.o - obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o - obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o - obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o -+obj-$(CONFIG_PHY_EN7528_PCIE) += phy-en7528-pcie.o - obj-y += allwinner/ \ - amlogic/ \ - broadcom/ \ ---- /dev/null -+++ b/drivers/phy/phy-en7528-pcie.c -@@ -0,0 +1,155 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright (C) 2026 Ahmed Naseef -+ * -+ * EcoNet EN7528 PCIe PHY Driver -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct en7528_pcie_phy_op { -+ u32 reg; -+ u32 mask; -+ u32 val; -+}; -+ -+struct en7528_pcie_phy { -+ struct regmap *regmap; -+ const struct en7528_pcie_phy_op *data; -+}; -+ -+/* Port 0 PHY: set LCDDS_CLK_PH_INV for PLL operation */ -+static const struct en7528_pcie_phy_op en7528_phy_port0[] = { -+ { -+ .reg = 0x4a0, -+ .mask = BIT(5), -+ .val = BIT(5), -+ }, -+ { /* sentinel */ } -+}; -+ -+/* Port 1 PHY: Rx impedance tuning, target R -5 Ohm */ -+static const struct en7528_pcie_phy_op en7528_phy_port1[] = { -+ { -+ .reg = 0xb2c, -+ .mask = GENMASK(13, 12), -+ .val = BIT(12), -+ }, -+ { /* sentinel */ } -+}; -+ -+/* EN751221 Port 1 PHY */ -+static const struct en7528_pcie_phy_op en751221_phy_port1[] = { -+ /* Rx Detection Timing for 7512 E1, 16*8 clock cycles */ -+ { -+ .reg = 0xa28, -+ .mask = GENMASK(17, 9), -+ .val = 16 << 9, -+ }, -+ /* Same for different power mode */ -+ { -+ .reg = 0xa2c, -+ .mask = GENMASK(8, 0), -+ .val = 16, -+ }, -+ { /* sentinel */ } -+}; -+ -+static int en7528_pcie_phy_init(struct phy *phy) -+{ -+ struct en7528_pcie_phy *ephy = phy_get_drvdata(phy); -+ const struct en7528_pcie_phy_op *data = ephy->data; -+ int i, ret; -+ -+ for (i = 0; data[i].mask || data[i].val; i++) { -+ if (i) -+ usleep_range(1000, 2000); -+ -+ ret = regmap_update_bits(ephy->regmap, data[i].reg, -+ data[i].mask, data[i].val); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static const struct phy_ops en7528_pcie_phy_ops = { -+ .init = en7528_pcie_phy_init, -+ .owner = THIS_MODULE, -+}; -+ -+static int en7528_pcie_phy_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ const struct en7528_pcie_phy_op *data; -+ struct regmap_config regmap_config = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_stride = 4, -+ }; -+ struct phy_provider *provider; -+ struct en7528_pcie_phy *ephy; -+ void __iomem *base; -+ struct phy *phy; -+ int i; -+ -+ data = of_device_get_match_data(dev); -+ if (!data) -+ return -EINVAL; -+ -+ ephy = devm_kzalloc(dev, sizeof(*ephy), GFP_KERNEL); -+ if (!ephy) -+ return -ENOMEM; -+ -+ ephy->data = data; -+ -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ for (i = 0; data[i].mask || data[i].val; i++) -+ if (data[i].reg > regmap_config.max_register) -+ regmap_config.max_register = data[i].reg; -+ -+ ephy->regmap = devm_regmap_init_mmio(dev, base, ®map_config); -+ if (IS_ERR(ephy->regmap)) -+ return PTR_ERR(ephy->regmap); -+ -+ phy = devm_phy_create(dev, dev->of_node, &en7528_pcie_phy_ops); -+ if (IS_ERR(phy)) -+ return PTR_ERR(phy); -+ -+ phy_set_drvdata(phy, ephy); -+ -+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); -+ -+ return PTR_ERR_OR_ZERO(provider); -+} -+ -+static const struct of_device_id en7528_pcie_phy_ids[] = { -+ { .compatible = "econet,en7528-pcie-phy0", .data = en7528_phy_port0 }, -+ { .compatible = "econet,en7528-pcie-phy1", .data = en7528_phy_port1 }, -+ { .compatible = "econet,en751221-pcie-phy0", .data = en7528_phy_port0 }, -+ { .compatible = "econet,en751221-pcie-phy1", .data = en751221_phy_port1 }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, en7528_pcie_phy_ids); -+ -+static struct platform_driver en7528_pcie_phy_driver = { -+ .probe = en7528_pcie_phy_probe, -+ .driver = { -+ .name = "en7528-pcie-phy", -+ .of_match_table = en7528_pcie_phy_ids, -+ }, -+}; -+module_platform_driver(en7528_pcie_phy_driver); -+ -+MODULE_AUTHOR("Ahmed Naseef "); -+MODULE_DESCRIPTION("EcoNet EN7528 PCIe PHY driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch b/target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch deleted file mode 100644 index 872843549d..0000000000 --- a/target/linux/econet/patches-6.12/913-pcie-fix-bogus-prefetch-window.patch +++ /dev/null @@ -1,38 +0,0 @@ -Subject: [PATCH] PCI: Skip bridge window reads when window is not supported - -pci_read_bridge_io() and pci_read_bridge_mmio_pref() read bridge window -registers unconditionally. If the registers are hardwired to zero -(not implemented), both base and limit will be 0. Since (0 <= 0) is -true, a bogus window [mem 0x00000000-0x000fffff] or [io 0x0000-0x0fff] -gets created. - -pci_read_bridge_windows() already detects unsupported windows by -testing register writability and sets io_window/pref_window flags -accordingly. Check these flags at the start of pci_read_bridge_io() -and pci_read_bridge_mmio_pref() to skip reading registers when the -window is not supported. - -Suggested-by: Bjorn Helgaas -Signed-off-by: Ahmed Naseef ---- a/drivers/pci/probe.c -+++ b/drivers/pci/probe.c -@@ -349,6 +349,9 @@ static void pci_read_bridge_io(struct pc - unsigned long io_mask, io_granularity, base, limit; - struct pci_bus_region region; - -+ if (!dev->io_window) -+ return; -+ - io_mask = PCI_IO_RANGE_MASK; - io_granularity = 0x1000; - if (dev->io_window_1k) { -@@ -410,6 +413,9 @@ static void pci_read_bridge_mmio_pref(st - pci_bus_addr_t base, limit; - struct pci_bus_region region; - -+ if (!dev->pref_window) -+ return; -+ - pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); - pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); - base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; diff --git a/target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch b/target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch deleted file mode 100644 index 308703c630..0000000000 --- a/target/linux/econet/patches-6.12/914-phy-add-en7528-usb-phy-driver.patch +++ /dev/null @@ -1,358 +0,0 @@ -From: Ahmed Naseef -Subject: phy: add EN7528 USB PHY driver - -Add USB PHY driver for EcoNet EN7528 SoC. - -Based on GPL vendor code at https://github.com/keenetic/kernel-49 -and the Airoha AN7581 USB PHY driver by Christian Marangi. - -Signed-off-by: Ahmed Naseef ---- a/drivers/phy/Kconfig -+++ b/drivers/phy/Kconfig -@@ -93,6 +93,17 @@ config PHY_EN7528_PCIE - This driver provides PHY initialization for the two PCIe ports - on EN7528 SoC. - -+config PHY_EN7528_USB -+ tristate "EcoNet EN7528 USB PHY Driver" -+ depends on ECONET || COMPILE_TEST -+ depends on OF -+ select GENERIC_PHY -+ select REGMAP_MMIO -+ help -+ Say 'Y' here to add support for EcoNet EN7528 USB PHY driver. -+ This driver creates the basic PHY instance and provides -+ initialization callback for the USB port. -+ - source "drivers/phy/allwinner/Kconfig" - source "drivers/phy/amlogic/Kconfig" - source "drivers/phy/broadcom/Kconfig" ---- a/drivers/phy/Makefile -+++ b/drivers/phy/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy- - obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o - obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o - obj-$(CONFIG_PHY_EN7528_PCIE) += phy-en7528-pcie.o -+obj-$(CONFIG_PHY_EN7528_USB) += phy-en7528-usb.o - obj-y += allwinner/ \ - amlogic/ \ - broadcom/ \ ---- /dev/null -+++ b/drivers/phy/phy-en7528-usb.c -@@ -0,0 +1,316 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * EcoNet EN7528 USB PHY driver -+ * -+ * Based on GPL vendor code at https://github.com/keenetic/kernel-49 -+ * and the Airoha AN7581 USB PHY driver by -+ * Christian Marangi -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Frequency Meter registers (shared across ports) */ -+#define EN7528_USB_PHY_FMCR0 0x100 -+#define EN7528_USB_PHY_MONCLK_SEL GENMASK(27, 26) -+#define EN7528_USB_PHY_FREQDET_EN BIT(24) -+#define EN7528_USB_PHY_CYCLECNT GENMASK(23, 0) -+#define EN7528_USB_PHY_FMMONR0 0x10c -+#define EN7528_USB_PHY_FMMONR1 0x110 -+#define EN7528_USB_PHY_FRCK_EN BIT(8) -+ -+/* U2 PHY port bases */ -+#define EN7528_USB_PHY_U2_P0_BASE 0x300 -+#define EN7528_USB_PHY_U2_P1_BASE 0x1300 -+#define EN7528_USB_PHY_NUM_U2_PORTS 2 -+ -+/* U2 PHY register offsets (relative to port base) */ -+#define EN7528_USB_PHY_ACR0 0x10 -+#define EN7528_USB_PHY_HSTX_SRCAL_EN BIT(23) -+#define EN7528_USB_PHY_HSTX_SRCTRL GENMASK(18, 16) -+#define EN7528_USB_PHY_ACR3 0x1c -+#define EN7528_USB_PHY_ACR3_ENABLE 0xC0240000 -+ -+/* U3 PHYA registers (base at +0xb00) */ -+#define EN7528_USB_PHY_U3_PHYA_REG11 0xb2c -+#define EN7528_USB_PHY_RX_IMPSEL GENMASK(13, 12) -+ -+#define EN7528_USB_PHY_FM_DET_CYCLE_CNT 1024 -+#define EN7528_USB_PHY_REF_CK 20 /* MHz */ -+#define EN7528_USB_PHY_SR_COEF 28 -+#define EN7528_USB_PHY_SR_COEF_DIVISOR 1000 -+#define EN7528_USB_PHY_DEFAULT_SR 4 -+ -+#define EN7528_USB_PHY_FREQDET_SLEEP 1000 /* 1ms */ -+#define EN7528_USB_PHY_FREQDET_TIMEOUT (EN7528_USB_PHY_FREQDET_SLEEP * 10) -+ -+static const unsigned int en7528_u2_port_bases[EN7528_USB_PHY_NUM_U2_PORTS] = { -+ EN7528_USB_PHY_U2_P0_BASE, -+ EN7528_USB_PHY_U2_P1_BASE, -+}; -+ -+struct en7528_usb_phy_instance { -+ struct phy *phy; -+ u32 type; -+}; -+ -+enum en7528_usb_phy_type { -+ EN7528_PHY_USB2, -+ EN7528_PHY_USB3, -+ -+ EN7528_PHY_USB_MAX, -+}; -+ -+struct en7528_usb_phy_priv { -+ struct device *dev; -+ struct regmap *regmap; -+ -+ struct en7528_usb_phy_instance *phys[EN7528_PHY_USB_MAX]; -+}; -+ -+static void en7528_usb_phy_slew_rate_calibration(struct en7528_usb_phy_priv *priv, -+ unsigned int port_id, -+ unsigned int port_base) -+{ -+ unsigned int acr0 = port_base + EN7528_USB_PHY_ACR0; -+ u32 fm_out; -+ u32 srctrl; -+ -+ /* Enable HS TX SR calibration */ -+ regmap_set_bits(priv->regmap, acr0, -+ EN7528_USB_PHY_HSTX_SRCAL_EN); -+ -+ usleep_range(1000, 1500); -+ -+ /* Enable free run clock */ -+ regmap_set_bits(priv->regmap, EN7528_USB_PHY_FMMONR1, -+ EN7528_USB_PHY_FRCK_EN); -+ -+ /* Select monitor clock: port 0 = MONCLK_SEL 0, port 1 = MONCLK_SEL 1 */ -+ regmap_update_bits(priv->regmap, EN7528_USB_PHY_FMCR0, -+ EN7528_USB_PHY_MONCLK_SEL, -+ FIELD_PREP(EN7528_USB_PHY_MONCLK_SEL, port_id)); -+ -+ /* Set cycle count */ -+ regmap_update_bits(priv->regmap, EN7528_USB_PHY_FMCR0, -+ EN7528_USB_PHY_CYCLECNT, -+ FIELD_PREP(EN7528_USB_PHY_CYCLECNT, -+ EN7528_USB_PHY_FM_DET_CYCLE_CNT)); -+ -+ /* Enable frequency meter */ -+ regmap_set_bits(priv->regmap, EN7528_USB_PHY_FMCR0, -+ EN7528_USB_PHY_FREQDET_EN); -+ -+ /* Timeout can happen and we will apply default value at the end */ -+ (void)regmap_read_poll_timeout(priv->regmap, EN7528_USB_PHY_FMMONR0, -+ fm_out, fm_out, -+ EN7528_USB_PHY_FREQDET_SLEEP, -+ EN7528_USB_PHY_FREQDET_TIMEOUT); -+ -+ /* Disable frequency meter */ -+ regmap_clear_bits(priv->regmap, EN7528_USB_PHY_FMCR0, -+ EN7528_USB_PHY_FREQDET_EN); -+ -+ /* Disable free run clock */ -+ regmap_clear_bits(priv->regmap, EN7528_USB_PHY_FMMONR1, -+ EN7528_USB_PHY_FRCK_EN); -+ -+ /* Disable HS TX SR calibration */ -+ regmap_clear_bits(priv->regmap, acr0, -+ EN7528_USB_PHY_HSTX_SRCAL_EN); -+ -+ usleep_range(1000, 1500); -+ -+ if (!fm_out) { -+ srctrl = EN7528_USB_PHY_DEFAULT_SR; -+ dev_err(priv->dev, "port%u: frequency not detected, using default SR calibration.\n", -+ port_id); -+ } else { -+ /* (1024 / FM_OUT) * REF_CK * SR_COEF */ -+ srctrl = EN7528_USB_PHY_REF_CK * EN7528_USB_PHY_SR_COEF; -+ srctrl = (srctrl * EN7528_USB_PHY_FM_DET_CYCLE_CNT) / fm_out; -+ srctrl = DIV_ROUND_CLOSEST(srctrl, EN7528_USB_PHY_SR_COEF_DIVISOR); -+ dev_dbg(priv->dev, "port%u: SR calibration applied: %x\n", -+ port_id, srctrl); -+ } -+ -+ regmap_update_bits(priv->regmap, acr0, -+ EN7528_USB_PHY_HSTX_SRCTRL, -+ FIELD_PREP(EN7528_USB_PHY_HSTX_SRCTRL, srctrl)); -+} -+ -+static int en7528_usb_phy_init(struct phy *phy) -+{ -+ struct en7528_usb_phy_instance *instance = phy_get_drvdata(phy); -+ struct en7528_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent); -+ unsigned int i; -+ -+ switch (instance->type) { -+ case PHY_TYPE_USB2: -+ /* Enable both U2 PHY ports before calibration */ -+ for (i = 0; i < EN7528_USB_PHY_NUM_U2_PORTS; i++) -+ regmap_write(priv->regmap, -+ en7528_u2_port_bases[i] + EN7528_USB_PHY_ACR3, -+ EN7528_USB_PHY_ACR3_ENABLE); -+ break; -+ case PHY_TYPE_USB3: -+ /* Combo PHY Rx R mean value too high, tune -5 Ohm */ -+ regmap_update_bits(priv->regmap, -+ EN7528_USB_PHY_U3_PHYA_REG11, -+ EN7528_USB_PHY_RX_IMPSEL, -+ FIELD_PREP(EN7528_USB_PHY_RX_IMPSEL, 0x1)); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int en7528_usb_phy_power_on(struct phy *phy) -+{ -+ struct en7528_usb_phy_instance *instance = phy_get_drvdata(phy); -+ struct en7528_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent); -+ unsigned int i; -+ -+ if (instance->type != PHY_TYPE_USB2) -+ return 0; -+ -+ /* Calibrate slew rate for both U2 PHY ports */ -+ for (i = 0; i < EN7528_USB_PHY_NUM_U2_PORTS; i++) -+ en7528_usb_phy_slew_rate_calibration(priv, i, -+ en7528_u2_port_bases[i]); -+ -+ return 0; -+} -+ -+static const struct phy_ops en7528_usb_phy_ops = { -+ .init = en7528_usb_phy_init, -+ .power_on = en7528_usb_phy_power_on, -+ .owner = THIS_MODULE, -+}; -+ -+static struct phy *en7528_usb_phy_xlate(struct device *dev, -+ const struct of_phandle_args *args) -+{ -+ struct en7528_usb_phy_priv *priv = dev_get_drvdata(dev); -+ struct en7528_usb_phy_instance *instance = NULL; -+ unsigned int index, phy_type; -+ -+ if (args->args_count != 1) { -+ dev_err(dev, "invalid number of cells in 'phy' property\n"); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ phy_type = args->args[0]; -+ if (!(phy_type == PHY_TYPE_USB2 || phy_type == PHY_TYPE_USB3)) { -+ dev_err(dev, "unsupported device type: %d\n", phy_type); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ for (index = 0; index < EN7528_PHY_USB_MAX; index++) -+ if (priv->phys[index] && -+ phy_type == priv->phys[index]->type) { -+ instance = priv->phys[index]; -+ break; -+ } -+ -+ if (!instance) { -+ dev_err(dev, "failed to find appropriate phy\n"); -+ return ERR_PTR(-EINVAL); -+ } -+ -+ return instance->phy; -+} -+ -+static const struct regmap_config en7528_usb_phy_regmap_config = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_stride = 4, -+ .max_register = EN7528_USB_PHY_U2_P1_BASE + EN7528_USB_PHY_ACR3, -+}; -+ -+static int en7528_usb_phy_probe(struct platform_device *pdev) -+{ -+ struct phy_provider *phy_provider; -+ struct en7528_usb_phy_priv *priv; -+ struct device *dev = &pdev->dev; -+ unsigned int index; -+ void *base; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->dev = dev; -+ -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ priv->regmap = devm_regmap_init_mmio(dev, base, -+ &en7528_usb_phy_regmap_config); -+ if (IS_ERR(priv->regmap)) -+ return PTR_ERR(priv->regmap); -+ -+ platform_set_drvdata(pdev, priv); -+ -+ for (index = 0; index < EN7528_PHY_USB_MAX; index++) { -+ struct en7528_usb_phy_instance *instance; -+ enum en7528_usb_phy_type phy_type; -+ -+ switch (index) { -+ case EN7528_PHY_USB2: -+ phy_type = PHY_TYPE_USB2; -+ break; -+ case EN7528_PHY_USB3: -+ phy_type = PHY_TYPE_USB3; -+ break; -+ default: -+ continue; -+ } -+ -+ instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); -+ if (!instance) -+ return -ENOMEM; -+ -+ instance->type = phy_type; -+ priv->phys[index] = instance; -+ -+ instance->phy = devm_phy_create(dev, NULL, &en7528_usb_phy_ops); -+ if (IS_ERR(instance->phy)) -+ return dev_err_probe(dev, PTR_ERR(instance->phy), -+ "failed to create phy\n"); -+ -+ phy_set_drvdata(instance->phy, instance); -+ } -+ -+ phy_provider = devm_of_phy_provider_register(dev, -+ en7528_usb_phy_xlate); -+ -+ return PTR_ERR_OR_ZERO(phy_provider); -+} -+ -+static const struct of_device_id en7528_usb_phy_match[] = { -+ { .compatible = "econet,en7528-usb-phy" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, en7528_usb_phy_match); -+ -+static struct platform_driver en7528_usb_phy_driver = { -+ .probe = en7528_usb_phy_probe, -+ .driver = { -+ .name = "en7528-usb-phy", -+ .of_match_table = en7528_usb_phy_match, -+ }, -+}; -+ -+module_platform_driver(en7528_usb_phy_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("EcoNet EN7528 USB PHY driver"); diff --git a/target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch b/target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch deleted file mode 100644 index 78e5ca5d4c..0000000000 --- a/target/linux/econet/patches-6.12/915-usb-xhci-mtk-add-en7528-ltssm-quirk.patch +++ /dev/null @@ -1,58 +0,0 @@ -From: Ahmed Naseef -Subject: usb: xhci-mtk: add EN7528 LTSSM timing quirk - -EN7528 needs LTSSM Timing Parameter 5 configured to fix -TD 6.5 compliance test failures. - -Based on GPL vendor code: -https://github.com/keenetic/kernel-49/commit/ee0e0b7cf28c208cd5b892ea96180ffae0de9b7f - -Signed-off-by: Ahmed Naseef ---- a/drivers/usb/host/xhci-mtk.c -+++ b/drivers/usb/host/xhci-mtk.c -@@ -80,6 +80,8 @@ - #define SS_GEN2_EOF_CFG 0x990 - #define SSG2EOF_OFFSET 0x3c - -+#define XHCI_MTK_LTSSM_TIMING_PARAMETER5 0x251c -+ - #define XSEOF_OFFSET_MASK GENMASK(11, 0) - - /* usb remote wakeup registers in syscon */ -@@ -191,6 +193,18 @@ static void xhci_mtk_rxfifo_depth_set(st - writel(value, hcd->regs + HSCH_CFG1); - } - -+/* EN7528: fix TD 6.5 compliance test failure */ -+static void xhci_mtk_ltssm_quirk(struct xhci_hcd_mtk *mtk) -+{ -+ struct device *dev = mtk->dev; -+ struct usb_hcd *hcd = mtk->hcd; -+ -+ if (!of_device_is_compatible(dev->of_node, "econet,en7528-xhci")) -+ return; -+ -+ writel(0x203e8, hcd->regs + XHCI_MTK_LTSSM_TIMING_PARAMETER5); -+} -+ - static void xhci_mtk_init_quirk(struct xhci_hcd_mtk *mtk) - { - /* workaround only for mt8195 */ -@@ -198,6 +212,9 @@ static void xhci_mtk_init_quirk(struct x - - /* workaround for SoCs using SSUSB about before IPM v1.6.0 */ - xhci_mtk_rxfifo_depth_set(mtk); -+ -+ /* EN7528 LTSSM timing fix */ -+ xhci_mtk_ltssm_quirk(mtk); - } - - static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) -@@ -846,6 +863,7 @@ static const struct dev_pm_ops xhci_mtk_ - static const struct of_device_id mtk_xhci_of_match[] = { - { .compatible = "mediatek,mt8173-xhci"}, - { .compatible = "mediatek,mt8195-xhci"}, -+ { .compatible = "econet,en7528-xhci"}, - { .compatible = "mediatek,mtk-xhci"}, - { }, - }; From 34ac128d6d7a0bd00038a2387ce3feb6b92dde8d Mon Sep 17 00:00:00 2001 From: Ahmed Naseef Date: Fri, 19 Jun 2026 16:29:12 +0400 Subject: [PATCH 092/228] econet: replace pending patches with upstream backports The EN751221 clock/reset bindings and driver, along with the PCI bridge window fix, have all been accepted upstream. Replace the downstream patches with the exact versions merged upstream and add the kernel version tag: 910: dt-bindings: clock, reset: Add econet EN751221 (v7.1, 35af99f7482673) 911: clk: airoha: Add econet EN751221 clock/reset support (v7.1, d8b034525fd954) 913: PCI: Prevent assignment to unsupported bridge windows (v7.1, 92427ab4378faa) Refresh the patches as a result. Signed-off-by: Ahmed Naseef Link: https://github.com/openwrt/openwrt/pull/23879 Signed-off-by: Jonas Jelonek --- .../886-uart-add-en7523-support.patch | 2 +- ...-reset-add-econet-en751221-bindings.patch} | 131 +++++++----------- ...onet-en751221-clock-reset-support-t.patch} | 67 ++++----- .../913-pcie-fix-bogus-prefetch-window.patch | 38 ----- ...gnment-to-unsupported-bridge-windows.patch | 66 +++++++++ 5 files changed, 145 insertions(+), 159 deletions(-) rename target/linux/econet/patches-6.18/{910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch => 910-v7.1-dt-bindings-clock-reset-add-econet-en751221-bindings.patch} (55%) rename target/linux/econet/patches-6.18/{911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch => 911-v7.1-clk-airoha-add-econet-en751221-clock-reset-support-t.patch} (88%) delete mode 100644 target/linux/econet/patches-6.18/913-pcie-fix-bogus-prefetch-window.patch create mode 100644 target/linux/econet/patches-6.18/913-v7.1-PCI-Prevent-assignment-to-unsupported-bridge-windows.patch diff --git a/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch b/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch index f143e33695..8d691ce0ec 100644 --- a/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch +++ b/target/linux/econet/patches-6.18/886-uart-add-en7523-support.patch @@ -122,7 +122,7 @@ }; /* Uart divisor latch read */ -@@ -2782,6 +2790,11 @@ serial8250_do_set_termios(struct uart_po +@@ -2785,6 +2793,11 @@ serial8250_do_set_termios(struct uart_po serial8250_set_ier(port, termios); serial8250_set_efr(port, termios); serial8250_set_divisor(port, baud, quot, frac); diff --git a/target/linux/econet/patches-6.18/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch b/target/linux/econet/patches-6.18/910-v7.1-dt-bindings-clock-reset-add-econet-en751221-bindings.patch similarity index 55% rename from target/linux/econet/patches-6.18/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch rename to target/linux/econet/patches-6.18/910-v7.1-dt-bindings-clock-reset-add-econet-en751221-bindings.patch index 37dc36cacc..e2780081cb 100644 --- a/target/linux/econet/patches-6.18/910-dt-bindings-clock-reset-add-econet-en751221-bindings.patch +++ b/target/linux/econet/patches-6.18/910-v7.1-dt-bindings-clock-reset-add-econet-en751221-bindings.patch @@ -1,22 +1,23 @@ -From f3fa5911b1f094e164c497f7b10d94d92852e285 Mon Sep 17 00:00:00 2001 +From 35af99f7482673bf5f5391fd33caf266f4f62aeb Mon Sep 17 00:00:00 2001 From: Caleb James DeLisle -Date: Wed, 14 Jan 2026 17:54:05 +0000 -Subject: [PATCH] dt-bindings: clock, reset: Add econet EN751221 bindings +Date: Thu, 12 Mar 2026 16:24:48 +0000 +Subject: [PATCH] dt-bindings: clock, reset: Add econet EN751221 -Add clock and reset bindings for EN751221 based on the Airoha EN7523 SCU -driver. +Add clock and reset bindings for EN751221 as well as a "chip-scu" which is +an additional regmap that is used by the clock driver as well as others. +This split of the SCU across two register areas is the same as the Airoha +AN758x family. Signed-off-by: Caleb James DeLisle +Reviewed-by: Rob Herring (Arm) +Signed-off-by: Stephen Boyd --- -The EN751221 has the same bifurcation of SCU as EN7581 so we use -the same chip-scu as airoha,en7581-chip-scu. ---- - .../bindings/clock/airoha,en7523-scu.yaml | 17 +++++++- - .../mips/econet,en751221-chip-scu.yaml | 42 +++++++++++++++++++ - .../dt-bindings/clock/econet,en751221-scu.h | 14 +++++++ - .../dt-bindings/reset/econet,en751221-scu.h | 41 ++++++++++++++++++ - 4 files changed, 113 insertions(+), 1 deletion(-) - create mode 100644 Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml + .../bindings/clock/airoha,en7523-scu.yaml | 6 ++- + .../devicetree/bindings/mfd/syscon.yaml | 2 + + MAINTAINERS | 2 + + .../dt-bindings/clock/econet,en751221-scu.h | 12 +++++ + .../dt-bindings/reset/econet,en751221-scu.h | 49 +++++++++++++++++++ + 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 include/dt-bindings/clock/econet,en751221-scu.h create mode 100644 include/dt-bindings/reset/econet,en751221-scu.h @@ -30,82 +31,54 @@ the same chip-scu as airoha,en7581-chip-scu. reg: items: -@@ -67,7 +68,10 @@ allOf: +@@ -67,7 +68,9 @@ allOf: - if: properties: compatible: - const: airoha,en7581-scu -+ items: -+ - enum: -+ - airoha,en7581-scu -+ - econet,en751221-scu ++ enum: ++ - airoha,en7581-scu ++ - econet,en751221-scu then: properties: reg: -@@ -98,3 +102,14 @@ examples: +@@ -98,3 +101,4 @@ examples: #reset-cells = <1>; }; }; + -+ - | -+ soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ scuclk: clock-controller@1fb00000 { -+ compatible = "econet,en751221-scu"; -+ reg = <0x1fb00000 0x970>; -+ }; -+ }; -\ No newline at end of file ---- /dev/null -+++ b/Documentation/devicetree/bindings/mips/econet,en751221-chip-scu.yaml -@@ -0,0 +1,42 @@ -+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/arm/airoha,en7581-chip-scu.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: EcoNet Chip SCU Controller for EN751221 SoC -+ -+maintainers: -+ - Caleb James DeLisle -+ -+description: -+ The EcoNet chip-scu block provides a configuration interface for clock, -+ io-muxing and other functionalities used by multiple controllers (e.g. clock, -+ pinctrl, ecc) on EN751221 SoC. -+ -+properties: -+ compatible: -+ items: -+ - enum: +--- a/Documentation/devicetree/bindings/mfd/syscon.yaml ++++ b/Documentation/devicetree/bindings/mfd/syscon.yaml +@@ -61,6 +61,7 @@ select: + - cirrus,ep7209-syscon2 + - cirrus,ep7209-syscon3 + - cnxt,cx92755-uc + - econet,en751221-chip-scu -+ - const: syscon -+ -+ reg: -+ maxItems: 1 -+ -+required: -+ - compatible -+ - reg -+ -+additionalProperties: false -+ -+examples: -+ - | -+ soc { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ syscon@1fa20000 { -+ compatible = "econet,en751221-chip-scu", "syscon"; -+ reg = <0x1fa20000 0x388>; -+ }; -+ }; + - freecom,fsg-cs2-system-controller + - fsl,imx93-aonmix-ns-syscfg + - fsl,imx93-wakeupmix-syscfg +@@ -169,6 +170,7 @@ properties: + - cirrus,ep7209-syscon2 + - cirrus,ep7209-syscon3 + - cnxt,cx92755-uc ++ - econet,en751221-chip-scu + - freecom,fsg-cs2-system-controller + - fsl,imx93-aonmix-ns-syscfg + - fsl,imx93-wakeupmix-syscfg +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -8839,6 +8839,8 @@ F: arch/mips/boot/dts/econet/ + F: arch/mips/econet/ + F: drivers/clocksource/timer-econet-en751221.c + F: drivers/irqchip/irq-econet-en751221.c ++F: include/dt-bindings/clock/econet,en751221-scu.h ++F: include/dt-bindings/reset/econet,en751221-scu.h + + ECRYPT FILE SYSTEM + M: Tyler Hicks --- /dev/null +++ b/include/dt-bindings/clock/econet,en751221-scu.h -@@ -0,0 +1,15 @@ +@@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ + +#ifndef _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ @@ -115,13 +88,9 @@ the same chip-scu as airoha,en7581-chip-scu. +#define EN751221_CLK_SPI 1 +#define EN751221_CLK_BUS 2 +#define EN751221_CLK_CPU 3 -+#define EN751221_CLK_HPT 4 -+#define EN751221_CLK_GSW 5 -+ -+#define EN751221_MAX_CLKS 6 ++#define EN751221_CLK_GSW 4 + +#endif /* _DT_BINDINGS_CLOCK_ECONET_EN751221_SCU_H_ */ -\ No newline at end of file --- /dev/null +++ b/include/dt-bindings/reset/econet,en751221-scu.h @@ -0,0 +1,49 @@ diff --git a/target/linux/econet/patches-6.18/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch b/target/linux/econet/patches-6.18/911-v7.1-clk-airoha-add-econet-en751221-clock-reset-support-t.patch similarity index 88% rename from target/linux/econet/patches-6.18/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch rename to target/linux/econet/patches-6.18/911-v7.1-clk-airoha-add-econet-en751221-clock-reset-support-t.patch index 61fd157b5c..4630e7eed1 100644 --- a/target/linux/econet/patches-6.18/911-clk-airoha-add-econet-en751221-clock-reset-support-t.patch +++ b/target/linux/econet/patches-6.18/911-v7.1-clk-airoha-add-econet-en751221-clock-reset-support-t.patch @@ -1,6 +1,6 @@ -From 1dfb29374a040ba80d378b3465f4e0bcb67f4ba3 Mon Sep 17 00:00:00 2001 +From d8b034525fd9541f23c5a3c54cd1dbe716570e97 Mon Sep 17 00:00:00 2001 From: Caleb James DeLisle -Date: Wed, 14 Jan 2026 18:06:13 +0000 +Date: Thu, 12 Mar 2026 16:24:49 +0000 Subject: [PATCH] clk: airoha: Add econet EN751221 clock/reset support to en7523-scu @@ -11,10 +11,12 @@ each clock is derived differently. This clock driver will probably work correctly on EN751627, EN7528, and EN7580. Signed-off-by: Caleb James DeLisle +Reviewed-by: Brian Masney +Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 6 +- - drivers/clk/clk-en7523.c | 182 +++++++++++++++++++++++++++++++++++++++ - 2 files changed, 185 insertions(+), 3 deletions(-) + drivers/clk/clk-en7523.c | 223 ++++++++++++++++++++++++++++++++++++++- + 2 files changed, 221 insertions(+), 8 deletions(-) --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -53,7 +55,7 @@ Signed-off-by: Caleb James DeLisle #define RST_NR_PER_BANK 32 -@@ -33,15 +36,47 @@ +@@ -33,15 +36,50 @@ #define REG_RESET_CONTROL_PCIEHB BIT(29) #define REG_RESET_CONTROL_PCIE1 BIT(27) #define REG_RESET_CONTROL_PCIE2 BIT(26) @@ -67,19 +69,22 @@ Signed-off-by: Caleb James DeLisle #define REG_CRYPTO_CLKSRC2 0x20c +/* EN751221 */ +#define EN751221_REG_SPI_DIV 0x0cc -+#define EN751221_REG_SPI_DIV_MASK GENMASK(31,8) ++#define EN751221_REG_SPI_DIV_MASK GENMASK(31, 8) +#define EN751221_SPI_BASE 500000000 +#define EN751221_SPI_BASE_EN7526C 400000000 ++#define EN751221_SPI_DIV_DEFAULT 40 +#define EN751221_REG_BUS 0x284 -+#define EN751221_REG_BUS_MASK GENMASK(21,12) ++#define EN751221_REG_BUS_MASK GENMASK(21, 12) +#define EN751221_REG_SSR3 0x094 -+#define EN751221_REG_SSR3_GSW_MASK GENMASK(9,8) ++#define EN751221_REG_SSR3_GSW_MASK GENMASK(9, 8) #define REG_RST_CTRL2 0x830 #define REG_RST_CTRL1 0x834 +#define EN751221_REG_RST_DMT 0x84 +#define EN751221_REG_RST_USB 0xec + ++#define EN751221_MAX_CLKS 5 ++ +enum en_hir { + HIR_UNKNOWN = -1, + HIR_TC3169 = 0, @@ -101,7 +106,7 @@ Signed-off-by: Caleb James DeLisle struct en_clk_desc { int id; -@@ -93,6 +128,8 @@ static const u32 bus7581_base[] = { 6000 +@@ -93,6 +131,8 @@ static const u32 bus7581_base[] = { 6000 static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; static const u32 crypto_base[] = { 540000000, 480000000 }; static const u32 emmc7581_base[] = { 200000000, 150000000 }; @@ -110,7 +115,7 @@ Signed-off-by: Caleb James DeLisle static const struct en_clk_desc en7523_base_clks[] = { { -@@ -300,6 +337,13 @@ static const u16 en7581_rst_ofs[] = { +@@ -300,6 +340,13 @@ static const u16 en7581_rst_ofs[] = { REG_RST_CTRL1, }; @@ -124,7 +129,7 @@ Signed-off-by: Caleb James DeLisle static const u16 en7523_rst_map[] = { /* RST_CTRL2 */ [EN7523_XPON_PHY_RST] = 0, -@@ -405,8 +449,61 @@ static const u16 en7581_rst_map[] = { +@@ -405,8 +452,61 @@ static const u16 en7581_rst_map[] = { [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31, }; @@ -187,7 +192,7 @@ Signed-off-by: Caleb James DeLisle static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) { -@@ -604,7 +701,8 @@ static int en7523_clk_hw_init(struct pla +@@ -604,7 +704,8 @@ static int en7523_clk_hw_init(struct pla en7523_register_clocks(&pdev->dev, clk_data, base, np_base); return en7581_reset_register(&pdev->dev, np_base, en7523_rst_map, @@ -197,7 +202,7 @@ Signed-off-by: Caleb James DeLisle } static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, -@@ -705,7 +803,8 @@ static const struct reset_control_ops en +@@ -705,7 +806,8 @@ static const struct reset_control_ops en }; static int en7581_reset_register(struct device *dev, void __iomem *base, @@ -207,7 +212,7 @@ Signed-off-by: Caleb James DeLisle { struct en_rst_data *rst_data; -@@ -713,7 +812,7 @@ static int en7581_reset_register(struct +@@ -713,7 +815,7 @@ static int en7581_reset_register(struct if (!rst_data) return -ENOMEM; @@ -216,7 +221,7 @@ Signed-off-by: Caleb James DeLisle rst_data->idx_map = rst_map; rst_data->base = base; -@@ -752,7 +851,123 @@ static int en7581_clk_hw_init(struct pla +@@ -752,7 +854,107 @@ static int en7581_clk_hw_init(struct pla writel(val | 3, base + REG_NP_SCU_PCIC); return en7581_reset_register(&pdev->dev, base, en7581_rst_map, @@ -230,7 +235,9 @@ Signed-off-by: Caleb James DeLisle + u32 val = FIELD_GET(REG_HIR_MASK, readl(np_base + REG_HIR)); + + if (val < HIR_MAX) -+ return (enum en_hir) val; ++ return (enum en_hir)val; ++ ++ pr_warn("Unable to determine EcoNet SoC\n"); + + return HIR_UNKNOWN; +} @@ -241,6 +248,9 @@ Signed-off-by: Caleb James DeLisle +{ + struct clk_hw *hw; + ++ if (WARN_ON_ONCE(key >= EN751221_MAX_CLKS)) ++ return; ++ + hw = clk_hw_register_fixed_rate(dev, name, NULL, 0, rate); + if (IS_ERR(hw)) + pr_err("Failed to register clk %s: %pe\n", name, hw); @@ -274,7 +284,7 @@ Signed-off-by: Caleb James DeLisle + } else { + div = FIELD_GET(EN751221_REG_SPI_DIV_MASK, div) * 2; + if (!div) -+ div = 40; ++ div = EN751221_SPI_DIV_DEFAULT; + + en751221_try_register_clk(dev, EN751221_CLK_SPI, clk_data, + "spi", rate / div); @@ -291,27 +301,6 @@ Signed-off-by: Caleb James DeLisle + en751221_try_register_clk(dev, EN751221_CLK_CPU, clk_data, "cpu", + rate * 4); + -+ /* HPT */ -+ switch (hid) { -+ case HIR_EN751221: -+ case HIR_EN751627: -+ case HIR_EN7526C: -+ case HIR_EN7580: -+ case HIR_EN7528: -+ rate = 200000000; -+ break; -+ case HIR_MT7505: -+ rate = 100000000; -+ break; -+ case HIR_MT751020: -+ rate = 800000000 / 3; -+ break; -+ default: -+ rate = 250000000; -+ } -+ en751221_try_register_clk(dev, EN751221_CLK_HPT, clk_data, "hpt", -+ rate); -+ + /* GSW */ + rate = FIELD_GET(EN751221_REG_SSR3_GSW_MASK, + readl(np_base + EN751221_REG_SSR3)); @@ -341,7 +330,7 @@ Signed-off-by: Caleb James DeLisle } static int en7523_clk_probe(struct platform_device *pdev) -@@ -799,9 +1014,20 @@ static const struct en_clk_soc_data en75 +@@ -799,9 +1001,20 @@ static const struct en_clk_soc_data en75 .hw_init = en7581_clk_hw_init, }; diff --git a/target/linux/econet/patches-6.18/913-pcie-fix-bogus-prefetch-window.patch b/target/linux/econet/patches-6.18/913-pcie-fix-bogus-prefetch-window.patch deleted file mode 100644 index 306db192f0..0000000000 --- a/target/linux/econet/patches-6.18/913-pcie-fix-bogus-prefetch-window.patch +++ /dev/null @@ -1,38 +0,0 @@ -Subject: [PATCH] PCI: Skip bridge window reads when window is not supported - -pci_read_bridge_io() and pci_read_bridge_mmio_pref() read bridge window -registers unconditionally. If the registers are hardwired to zero -(not implemented), both base and limit will be 0. Since (0 <= 0) is -true, a bogus window [mem 0x00000000-0x000fffff] or [io 0x0000-0x0fff] -gets created. - -pci_read_bridge_windows() already detects unsupported windows by -testing register writability and sets io_window/pref_window flags -accordingly. Check these flags at the start of pci_read_bridge_io() -and pci_read_bridge_mmio_pref() to skip reading registers when the -window is not supported. - -Suggested-by: Bjorn Helgaas -Signed-off-by: Ahmed Naseef ---- a/drivers/pci/probe.c -+++ b/drivers/pci/probe.c -@@ -396,6 +396,9 @@ static void pci_read_bridge_io(struct pc - unsigned long io_mask, io_granularity, base, limit; - struct pci_bus_region region; - -+ if (!dev->io_window) -+ return; -+ - io_mask = PCI_IO_RANGE_MASK; - io_granularity = 0x1000; - if (dev->io_window_1k) { -@@ -466,6 +469,9 @@ static void pci_read_bridge_mmio_pref(st - pci_bus_addr_t base, limit; - struct pci_bus_region region; - -+ if (!dev->pref_window) -+ return; -+ - pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); - pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); - base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; diff --git a/target/linux/econet/patches-6.18/913-v7.1-PCI-Prevent-assignment-to-unsupported-bridge-windows.patch b/target/linux/econet/patches-6.18/913-v7.1-PCI-Prevent-assignment-to-unsupported-bridge-windows.patch new file mode 100644 index 0000000000..8c12e61245 --- /dev/null +++ b/target/linux/econet/patches-6.18/913-v7.1-PCI-Prevent-assignment-to-unsupported-bridge-windows.patch @@ -0,0 +1,66 @@ +From 92427ab4378faa168d6953d0f8574b8fc1edcc14 Mon Sep 17 00:00:00 2001 +From: Ahmed Naseef +Date: Thu, 12 Mar 2026 16:53:32 +0000 +Subject: [PATCH] PCI: Prevent assignment to unsupported bridge windows + +Previously, pci_read_bridge_io() and pci_read_bridge_mmio_pref() +unconditionally set resource type flags (IORESOURCE_IO or IORESOURCE_MEM | +IORESOURCE_PREFETCH) when reading bridge window registers. For windows that +are not implemented in hardware, this may cause the allocator to assign +space for a window that doesn't exist. + +For example, the EcoNET EN7528 SoC Root Port doesn't support the +prefetchable window, but since a downstream device had a prefetchable BAR, +the allocator mistakenly assigned a prefetchable window: + + pci 0001:00:01.0: [14c3:0811] type 01 class 0x060400 PCIe Root Port + pci 0001:00:01.0: PCI bridge to [bus 01-ff] + pci 0001:00:01.0: bridge window [mem 0x28000000-0x280fffff]: assigned + pci 0001:00:01.0: bridge window [mem 0x28100000-0x282fffff pref]: assigned + pci 0001:01:00.0: BAR 0 [mem 0x28100000-0x281fffff 64bit pref]: assigned + +pci_read_bridge_windows() already detects unsupported windows by testing +register writability and sets dev->io_window/pref_window accordingly. + +Check dev->io_window/pref_window so we don't set the resource flags for +unsupported windows, which prevents the allocator from assigning space to +them. + +After this commit, the prefetchable BAR is correctly allocated from the +non-prefetchable window: + + pci 0001:00:01.0: bridge window [mem 0x28000000-0x281fffff]: assigned + pci 0001:01:00.0: BAR 0 [mem 0x28000000-0x280fffff 64bit pref]: assigned + +Suggested-by: Bjorn Helgaas +Link: https://lore.kernel.org/all/20260113210259.GA715789@bhelgaas/ +Signed-off-by: Ahmed Naseef +Signed-off-by: Caleb James DeLisle +Signed-off-by: Bjorn Helgaas +Link: https://patch.msgid.link/20260312165332.569772-4-cjd@cjdns.fr +--- + drivers/pci/probe.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -396,6 +396,9 @@ static void pci_read_bridge_io(struct pc + unsigned long io_mask, io_granularity, base, limit; + struct pci_bus_region region; + ++ if (!dev->io_window) ++ return; ++ + io_mask = PCI_IO_RANGE_MASK; + io_granularity = 0x1000; + if (dev->io_window_1k) { +@@ -466,6 +469,9 @@ static void pci_read_bridge_mmio_pref(st + pci_bus_addr_t base, limit; + struct pci_bus_region region; + ++ if (!dev->pref_window) ++ return; ++ + pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo); + pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo); + base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16; From e42e9c8133fbd0dce7abfe1ec696383745448078 Mon Sep 17 00:00:00 2001 From: Shine <4c.fce2@proton.me> Date: Mon, 2 Feb 2026 23:06:44 +0100 Subject: [PATCH 093/228] packages: arm-trusted-firmware-tools: fix build on musl host Due to POSIX style ioctl() declaration in MUSL, arm-trusted-firmware-tools fails to build on MUSL based hosts with -Werror and -pedantic GCC switches enabled. Alpine Linux, for example, fixes this with an unconditional cast to "int". This commit tries to apply this cast only for MUSL based build hosts, while keeping the type as-is where the cast isn't needed. Maybe overkill, but cleaner than an unconditional cast. Fixes: #13339 Signed-off-by: Shine <4c.fce2@proton.me> Link: https://github.com/openwrt/openwrt/pull/21957 Signed-off-by: Jonas Jelonek --- package/boot/arm-trusted-firmware-tools/Makefile | 8 +++++++- .../patches/003-fiptool_musl_fix.patch | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch diff --git a/package/boot/arm-trusted-firmware-tools/Makefile b/package/boot/arm-trusted-firmware-tools/Makefile index dd0ed66a21..b709112ce3 100644 --- a/package/boot/arm-trusted-firmware-tools/Makefile +++ b/package/boot/arm-trusted-firmware-tools/Makefile @@ -29,10 +29,16 @@ define Package/arm-trusted-firmware-tools BUILDONLY:=1 endef +ifeq ($(shell uname -s),Linux) + HOST_MUSL_FLAG:=$(shell [ "$$(2>&1 ldd --version | head -n 1 | cut -d ' ' -f1)" = "musl" ] && echo " -D__MUSL__") +else + HOST_MUSL_FLAG:= +endif + define Host/Compile $(MAKE) -C \ $(HOST_BUILD_DIR)/tools/fiptool \ - CPPFLAGS="$(HOST_CFLAGS)" \ + CPPFLAGS="$(HOST_CFLAGS)$(HOST_MUSL_FLAG)" \ LDFLAGS="$(HOST_LDFLAGS)" \ OPENSSL_DIR="$(STAGING_DIR_HOST)" endef diff --git a/package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch b/package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch new file mode 100644 index 0000000000..f421e91ef0 --- /dev/null +++ b/package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch @@ -0,0 +1,14 @@ +--- a/tools/fiptool/fiptool.c ++++ b/tools/fiptool/fiptool.c +@@ -318,7 +318,11 @@ + + #ifdef BLKGETSIZE64 + if ((st.st_mode & S_IFBLK) != 0) ++#ifdef __MUSL__ ++ if (ioctl(fileno(fp), (int)BLKGETSIZE64, &st_size) == -1) ++#else + if (ioctl(fileno(fp), BLKGETSIZE64, &st_size) == -1) ++#endif + log_err("ioctl %s", filename); + #endif + From 255f4c8e606a0d66885c920a353ca5832b3b6e25 Mon Sep 17 00:00:00 2001 From: Shine <4c.fce2@proton.me> Date: Mon, 2 Feb 2026 23:06:44 +0100 Subject: [PATCH 094/228] packages: nftables: fix build on host with busybox ash Numeric for loops are a bashism and won't work in BusyBox' ash. Replace with a portable equivalent. Backport of a post-1.1.6 nftables fix. Signed-off-by: Shine <4c.fce2@proton.me> Link: https://github.com/openwrt/openwrt/pull/21957 Signed-off-by: Jonas Jelonek --- .../utils/nftables/patches/001-for-bash-syntax.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 package/network/utils/nftables/patches/001-for-bash-syntax.patch diff --git a/package/network/utils/nftables/patches/001-for-bash-syntax.patch b/package/network/utils/nftables/patches/001-for-bash-syntax.patch new file mode 100644 index 0000000000..8db917b5d6 --- /dev/null +++ b/package/network/utils/nftables/patches/001-for-bash-syntax.patch @@ -0,0 +1,11 @@ +--- a/configure ++++ b/configure +@@ -17940,7 +17940,7 @@ + echo " ${STABLE_RELEASE}" + echo "};" + echo "static char nftbuildstamp[] = {" +- for ((i = 56; i >= 0; i-= 8)); do ++ for i in `seq 56 -8 0`; do + echo " ((uint64_t)MAKE_STAMP >> $i) & 0xff," + done + echo "};" From a9b59370155fdc03341ef784d9948c27fcb8f810 Mon Sep 17 00:00:00 2001 From: Shine <4c.fce2@proton.me> Date: Mon, 2 Feb 2026 23:06:44 +0100 Subject: [PATCH 095/228] tools: bc: fix build on musl host Fix declaration of getenv() in getopt.c Backport from bc 1.08.2. Signed-off-by: Shine <4c.fce2@proton.me> Link: https://github.com/openwrt/openwrt/pull/21957 Signed-off-by: Jonas Jelonek --- tools/bc/patches/001-getopt-declaration.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tools/bc/patches/001-getopt-declaration.patch diff --git a/tools/bc/patches/001-getopt-declaration.patch b/tools/bc/patches/001-getopt-declaration.patch new file mode 100644 index 0000000000..c64be8dc03 --- /dev/null +++ b/tools/bc/patches/001-getopt-declaration.patch @@ -0,0 +1,11 @@ +--- a/lib/getopt.c ++++ b/lib/getopt.c +@@ -197,7 +197,7 @@ static char *posixly_correct; + whose names are inconsistent. */ + + #ifndef getenv +-extern char *getenv (); ++extern char *getenv (const char *); + #endif + + #endif /* not __GNU_LIBRARY__ */ From 9f385a71a72a62b2ff016bf0e1e78ec328d5f6fd Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sun, 21 Jun 2026 17:49:40 +0200 Subject: [PATCH 096/228] package: nftables: bump PKG_RELEASE Bump the PKG_RELEASE as it was missed when adding a patch. Fixes: 255f4c8e60 ("packages: nftables: fix build on host with busybox ash") Signed-off-by: Jonas Jelonek --- package/network/utils/nftables/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/utils/nftables/Makefile b/package/network/utils/nftables/Makefile index ff0d04b6c4..fbcf77e554 100644 --- a/package/network/utils/nftables/Makefile +++ b/package/network/utils/nftables/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=nftables PKG_VERSION:=1.1.6 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files From 9863b15fce74442dfeae98859a6bfe7b8be8ff5c Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Mon, 16 Feb 2026 20:47:33 -0800 Subject: [PATCH 097/228] bcm53xx: nvmem conversions Add upstream patches for devices with nvram definitions in dts. For others, replace * with all devices that have no nvram definitions. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22181 Signed-off-by: Jonas Jelonek --- .../bcm53xx/base-files/etc/board.d/02_network | 25 ++-- ...-Specify-switch-ports-for-remaining-.patch | 133 ------------------ ...M5301X-EA9200-set-WAN-MAC-from-nvram.patch | 36 +++++ ...301X-panamera-set-WAN-MAC-from-nvram.patch | 36 +++++ ...RM-dts-BCM5301X-AC87U-specify-switch.patch | 69 +++++++++ ...M-dts-BCM5301X-EA6300-specify-switch.patch | 71 ++++++++++ ...s-BCM5301X-phicomm-k3-specify-switch.patch | 75 ++++++++++ ...-Specify-switch-ports-for-remaining-.patch | 133 ------------------ ...M5301X-EA9200-set-WAN-MAC-from-nvram.patch | 36 +++++ ...301X-panamera-set-WAN-MAC-from-nvram.patch | 36 +++++ ...RM-dts-BCM5301X-AC87U-specify-switch.patch | 69 +++++++++ ...M-dts-BCM5301X-EA6300-specify-switch.patch | 71 ++++++++++ ...s-BCM5301X-phicomm-k3-specify-switch.patch | 75 ++++++++++ 13 files changed, 590 insertions(+), 275 deletions(-) create mode 100644 target/linux/bcm53xx/patches-6.12/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch create mode 100644 target/linux/bcm53xx/patches-6.12/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch create mode 100644 target/linux/bcm53xx/patches-6.12/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch create mode 100644 target/linux/bcm53xx/patches-6.12/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch create mode 100644 target/linux/bcm53xx/patches-6.12/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch create mode 100644 target/linux/bcm53xx/patches-6.18/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch create mode 100644 target/linux/bcm53xx/patches-6.18/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch create mode 100644 target/linux/bcm53xx/patches-6.18/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch create mode 100644 target/linux/bcm53xx/patches-6.18/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch create mode 100644 target/linux/bcm53xx/patches-6.18/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch diff --git a/target/linux/bcm53xx/base-files/etc/board.d/02_network b/target/linux/bcm53xx/base-files/etc/board.d/02_network index 7e9caf6522..1b8baed147 100644 --- a/target/linux/bcm53xx/base-files/etc/board.d/02_network +++ b/target/linux/bcm53xx/base-files/etc/board.d/02_network @@ -53,21 +53,28 @@ bcm53xx_setup_macs() wan_macaddr="$(nvram get wan_hwaddr)" case "$board" in - dlink,dir-885l | \ - linksys,ea9200 | \ - linksys,panamera | \ netgear,r7900 | \ netgear,r8000 | \ netgear,r8500) etXmacaddr=$(nvram get et2macaddr) offset=1 ;; - luxul,xwr-3100-v1 | \ - luxul,xwr-3150-v1) - etXmacaddr=$(nvram get et0macaddr) - offset=5 - ;; - *) + asus,rt-ac3200|\ + asus,rt-ac5300|\ + asus,rt-ac56u|\ + asus,rt-ac68u|\ + asus,rt-n18u|\ + buffalo,wxr-1900dhp|\ + buffalo,wzr-600dhp2|\ + buffalo,wzr-900dhp|\ + buffalo,wzr-1750dhp|\ + dlink,dir-890l|\ + linksys,ea6500-v2|\ + netgear,r6250-v1|\ + netgear,r6300-v2|\ + netgear,r7000|\ + smartrg,sr400ac|\ + tenda,ac9) etXmacaddr=$(nvram get et0macaddr) offset=1 ;; diff --git a/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch b/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch index db49e5b164..c09a690cb8 100644 --- a/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch +++ b/target/linux/bcm53xx/patches-6.12/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch @@ -140,50 +140,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts -+++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts -@@ -46,3 +46,41 @@ - &usb3_phy { - status = "okay"; - }; -+ -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "lan1"; -+ }; -+ -+ port@1 { -+ label = "lan2"; -+ }; -+ -+ port@2 { -+ label = "lan3"; -+ }; -+ -+ port@3 { -+ label = "lan4"; -+ }; -+ -+ port@4 { -+ label = "wan"; -+ }; -+ -+ port@5 { -+ label = "cpu"; -+ }; -+ -+ port@7 { -+ status = "disabled"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; --- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts +++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts @@ -43,3 +43,41 @@ @@ -316,52 +272,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts -+++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts -@@ -77,6 +77,43 @@ - status = "okay"; - }; - -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "wan"; -+ -+ nvmem-cells = <&et1macaddr 1>; -+ nvmem-cell-names = "mac-address"; -+ }; -+ -+ port@1 { -+ label = "lan1"; -+ }; -+ -+ port@2 { -+ label = "lan2"; -+ }; -+ -+ port@3 { -+ label = "lan3"; -+ }; -+ -+ port@5 { -+ status = "disabled"; -+ }; -+ -+ port@7 { -+ label = "cpu"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; -+ - &nandcs { - partitions { - compatible = "fixed-partitions"; --- a/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts +++ b/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts @@ -130,3 +130,41 @@ @@ -494,49 +404,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts -+++ b/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts -@@ -38,6 +38,40 @@ - status = "okay"; - }; - -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "lan1"; -+ }; -+ -+ port@1 { -+ label = "lan2"; -+ }; -+ -+ port@2 { -+ label = "lan3"; -+ }; -+ -+ port@3 { -+ label = "wan"; -+ }; -+ -+ port@5 { -+ label = "cpu"; -+ }; -+ -+ port@7 { -+ status = "disabled"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; -+ - &nandcs { - partitions { - compatible = "fixed-partitions"; --- a/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts +++ b/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts @@ -91,6 +91,44 @@ diff --git a/target/linux/bcm53xx/patches-6.12/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch b/target/linux/bcm53xx/patches-6.12/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch new file mode 100644 index 0000000000..3abec78a61 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch @@ -0,0 +1,36 @@ +From 3482a3f37240826c825d05fceebbfe5877f587d4 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:20:16 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: EA9200: set WAN MAC from nvram + +The MAC address from the stock firmare is offset by 1. Define it +properly to avoid having to override it in userspace. + +Signed-off-by: Rosen Penev +--- + arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts +@@ -25,6 +25,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x180000>; ++ ++ et2macaddr: et2macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -70,6 +74,9 @@ + + port@4 { + label = "wan"; ++ ++ nvmem-cells = <&et2macaddr 1>; ++ nvmem-cell-names = "mac-address"; + }; + + port@5 { diff --git a/target/linux/bcm53xx/patches-6.12/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch b/target/linux/bcm53xx/patches-6.12/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch new file mode 100644 index 0000000000..a775f7e1f0 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch @@ -0,0 +1,36 @@ +From cbbaa1f69301755409bc3ddbf2401c8b87a73658 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:30:02 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: panamera: set WAN MAC from nvram + +The MAC address from the stock firmare is offset by 1. Define it +properly to avoid having to override it in userspace. + +Signed-off-by: Rosen Penev +--- + arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts +@@ -25,6 +25,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x100000>; ++ ++ et2macaddr: et2macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -230,6 +234,9 @@ + + port@4 { + label = "wan"; ++ ++ nvmem-cells = <&et2macaddr 1>; ++ nvmem-cell-names = "mac-address"; + }; + + port@5 { diff --git a/target/linux/bcm53xx/patches-6.12/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch b/target/linux/bcm53xx/patches-6.12/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch new file mode 100644 index 0000000000..cefe251e0d --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch @@ -0,0 +1,69 @@ +From cdcbe55d86588aa8c296847a445c1b1a59f4a617 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:58:58 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: AC87U: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +RT-AC87U. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../dts/broadcom/bcm4709-asus-rt-ac87u.dts | 40 +++++++++++++++++++ + 1 file changed, 40 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts +@@ -26,6 +26,9 @@ + }; + + nvram@1c080000 { ++ compatible = "brcm,nvram"; ++ reg = <0x1c080000 0x180000>; ++ + et1macaddr: et1macaddr { + #nvmem-cell-cells = <1>; + }; +@@ -77,6 +80,43 @@ + status = "okay"; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ ++ nvmem-cells = <&et1macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@5 { ++ status = "disabled"; ++ }; ++ ++ port@7 { ++ label = "cpu"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; diff --git a/target/linux/bcm53xx/patches-6.12/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch b/target/linux/bcm53xx/patches-6.12/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch new file mode 100644 index 0000000000..259cd312ab --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch @@ -0,0 +1,71 @@ +From c4c21947b9a641131afe07d6c5f1abd3ff6b8bb0 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 21:05:09 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: EA6300: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +EA6300. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../broadcom/bcm4708-linksys-ea6300-v1.dts | 45 +++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts +@@ -24,6 +24,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x180000>; ++ ++ et0macaddr: et0macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -46,3 +50,44 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ ++ nvmem-cells = <&et0macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-6.12/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch b/target/linux/bcm53xx/patches-6.12/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch new file mode 100644 index 0000000000..84aa912e11 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.12/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch @@ -0,0 +1,75 @@ +From 22785d47e3a5a8e5321586a9776a70a5e88148a2 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 21:13:49 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: phicomm-k3: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +K3. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../boot/dts/broadcom/bcm47094-phicomm-k3.dts | 46 +++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts +@@ -19,6 +19,15 @@ + <0x88000000 0x18000000>; + }; + ++ nvram@1c080000 { ++ compatible = "brcm,nvram"; ++ reg = <0x1c080000 0x100000>; ++ ++ et0macaddr: et0macaddr { ++ #nvmem-cell-cells = <1>; ++ }; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + +@@ -38,6 +47,43 @@ + status = "okay"; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "wan"; ++ ++ nvmem-cells = <&et0macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; diff --git a/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch b/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch index db49e5b164..c09a690cb8 100644 --- a/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch +++ b/target/linux/bcm53xx/patches-6.18/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch @@ -140,50 +140,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts -+++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts -@@ -46,3 +46,41 @@ - &usb3_phy { - status = "okay"; - }; -+ -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "lan1"; -+ }; -+ -+ port@1 { -+ label = "lan2"; -+ }; -+ -+ port@2 { -+ label = "lan3"; -+ }; -+ -+ port@3 { -+ label = "lan4"; -+ }; -+ -+ port@4 { -+ label = "wan"; -+ }; -+ -+ port@5 { -+ label = "cpu"; -+ }; -+ -+ port@7 { -+ status = "disabled"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; --- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts +++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts @@ -43,3 +43,41 @@ @@ -316,52 +272,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts -+++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts -@@ -77,6 +77,43 @@ - status = "okay"; - }; - -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "wan"; -+ -+ nvmem-cells = <&et1macaddr 1>; -+ nvmem-cell-names = "mac-address"; -+ }; -+ -+ port@1 { -+ label = "lan1"; -+ }; -+ -+ port@2 { -+ label = "lan2"; -+ }; -+ -+ port@3 { -+ label = "lan3"; -+ }; -+ -+ port@5 { -+ status = "disabled"; -+ }; -+ -+ port@7 { -+ label = "cpu"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; -+ - &nandcs { - partitions { - compatible = "fixed-partitions"; --- a/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts +++ b/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts @@ -130,3 +130,41 @@ @@ -494,49 +404,6 @@ Signed-off-by: Rafał Miłecki + }; + }; +}; ---- a/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts -+++ b/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts -@@ -38,6 +38,40 @@ - status = "okay"; - }; - -+&srab { -+ status = "okay"; -+ -+ ports { -+ port@0 { -+ label = "lan1"; -+ }; -+ -+ port@1 { -+ label = "lan2"; -+ }; -+ -+ port@2 { -+ label = "lan3"; -+ }; -+ -+ port@3 { -+ label = "wan"; -+ }; -+ -+ port@5 { -+ label = "cpu"; -+ }; -+ -+ port@7 { -+ status = "disabled"; -+ }; -+ -+ port@8 { -+ status = "disabled"; -+ }; -+ }; -+}; -+ - &nandcs { - partitions { - compatible = "fixed-partitions"; --- a/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts +++ b/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts @@ -91,6 +91,44 @@ diff --git a/target/linux/bcm53xx/patches-6.18/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch b/target/linux/bcm53xx/patches-6.18/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch new file mode 100644 index 0000000000..3abec78a61 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/311-ARM-dts-BCM5301X-EA9200-set-WAN-MAC-from-nvram.patch @@ -0,0 +1,36 @@ +From 3482a3f37240826c825d05fceebbfe5877f587d4 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:20:16 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: EA9200: set WAN MAC from nvram + +The MAC address from the stock firmare is offset by 1. Define it +properly to avoid having to override it in userspace. + +Signed-off-by: Rosen Penev +--- + arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts +@@ -25,6 +25,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x180000>; ++ ++ et2macaddr: et2macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -70,6 +74,9 @@ + + port@4 { + label = "wan"; ++ ++ nvmem-cells = <&et2macaddr 1>; ++ nvmem-cell-names = "mac-address"; + }; + + port@5 { diff --git a/target/linux/bcm53xx/patches-6.18/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch b/target/linux/bcm53xx/patches-6.18/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch new file mode 100644 index 0000000000..a775f7e1f0 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/312-ARM-dts-BCM5301X-panamera-set-WAN-MAC-from-nvram.patch @@ -0,0 +1,36 @@ +From cbbaa1f69301755409bc3ddbf2401c8b87a73658 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:30:02 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: panamera: set WAN MAC from nvram + +The MAC address from the stock firmare is offset by 1. Define it +properly to avoid having to override it in userspace. + +Signed-off-by: Rosen Penev +--- + arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-linksys-panamera.dts +@@ -25,6 +25,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x100000>; ++ ++ et2macaddr: et2macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -230,6 +234,9 @@ + + port@4 { + label = "wan"; ++ ++ nvmem-cells = <&et2macaddr 1>; ++ nvmem-cell-names = "mac-address"; + }; + + port@5 { diff --git a/target/linux/bcm53xx/patches-6.18/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch b/target/linux/bcm53xx/patches-6.18/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch new file mode 100644 index 0000000000..cefe251e0d --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/313-ARM-dts-BCM5301X-AC87U-specify-switch.patch @@ -0,0 +1,69 @@ +From cdcbe55d86588aa8c296847a445c1b1a59f4a617 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 20:58:58 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: AC87U: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +RT-AC87U. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../dts/broadcom/bcm4709-asus-rt-ac87u.dts | 40 +++++++++++++++++++ + 1 file changed, 40 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts +@@ -26,6 +26,9 @@ + }; + + nvram@1c080000 { ++ compatible = "brcm,nvram"; ++ reg = <0x1c080000 0x180000>; ++ + et1macaddr: et1macaddr { + #nvmem-cell-cells = <1>; + }; +@@ -77,6 +80,43 @@ + status = "okay"; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ ++ nvmem-cells = <&et1macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@5 { ++ status = "disabled"; ++ }; ++ ++ port@7 { ++ label = "cpu"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; diff --git a/target/linux/bcm53xx/patches-6.18/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch b/target/linux/bcm53xx/patches-6.18/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch new file mode 100644 index 0000000000..259cd312ab --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/314-ARM-dts-BCM5301X-EA6300-specify-switch.patch @@ -0,0 +1,71 @@ +From c4c21947b9a641131afe07d6c5f1abd3ff6b8bb0 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 21:05:09 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: EA6300: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +EA6300. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../broadcom/bcm4708-linksys-ea6300-v1.dts | 45 +++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts +@@ -24,6 +24,10 @@ + nvram@1c080000 { + compatible = "brcm,nvram"; + reg = <0x1c080000 0x180000>; ++ ++ et0macaddr: et0macaddr { ++ #nvmem-cell-cells = <1>; ++ }; + }; + + gpio-keys { +@@ -46,3 +50,44 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ ++ nvmem-cells = <&et0macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-6.18/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch b/target/linux/bcm53xx/patches-6.18/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch new file mode 100644 index 0000000000..84aa912e11 --- /dev/null +++ b/target/linux/bcm53xx/patches-6.18/315-ARM-dts-BCM5301X-phicomm-k3-specify-switch.patch @@ -0,0 +1,75 @@ +From 22785d47e3a5a8e5321586a9776a70a5e88148a2 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 17 Feb 2026 21:13:49 -0800 +Subject: [PATCH] ARM: dts: BCM5301X: phicomm-k3: specify switch + +bcm-ns.dtsi specifies a default layout that is not correct for the +K3. Also allows setting the WAN MAC address properly. + +Signed-off-by: Rosen Penev +--- + .../boot/dts/broadcom/bcm47094-phicomm-k3.dts | 46 +++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts +@@ -19,6 +19,15 @@ + <0x88000000 0x18000000>; + }; + ++ nvram@1c080000 { ++ compatible = "brcm,nvram"; ++ reg = <0x1c080000 0x100000>; ++ ++ et0macaddr: et0macaddr { ++ #nvmem-cell-cells = <1>; ++ }; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + +@@ -38,6 +47,43 @@ + status = "okay"; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "wan"; ++ ++ nvmem-cells = <&et0macaddr 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; From a4095b1f32da2a21cb481d793d439d3def290378 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Wed, 3 Jun 2026 20:20:01 +0800 Subject: [PATCH 098/228] rockchip: replace nvmem otp patch with upstream Replace the rockchip-otp patch with the upstream version. Also backports OTP support for RK3562 and RK3568 SoCs. Signed-off-by: Chukun Pan Link: https://github.com/openwrt/openwrt/pull/23770 Signed-off-by: Jonas Jelonek --- ...p-Handle-internal-word_size-in-main.patch} | 9 ++- ...rockchip-otp-Add-support-for-RK3568.patch} | 9 ++- ...-rockchip-otp-Add-support-for-RK3562.patch | 33 +++++++++ ...rockchip-otp-Add-support-for-RK3528.patch} | 11 ++- ...hip-Enable-OTP-controller-for-RK3562.patch | 69 ++++++++++++++++++ ...hip-Enable-OTP-controller-for-RK356x.patch | 70 +++++++++++++++++++ ...ip-Enable-OTP-controller-for-RK3528.patch} | 20 +++--- 7 files changed, 203 insertions(+), 18 deletions(-) rename target/linux/rockchip/patches-6.18/{162-01-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch => 038-1-v7.1-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch} (92%) rename target/linux/rockchip/patches-6.18/{162-02-nvmem-rockchip-otp-Add-support-for-RK3568.patch => 038-2-v7.1-nvmem-rockchip-otp-Add-support-for-RK3568.patch} (89%) create mode 100644 target/linux/rockchip/patches-6.18/038-3-v7.1-nvmem-rockchip-otp-Add-support-for-RK3562.patch rename target/linux/rockchip/patches-6.18/{162-03-nvmem-rockchip-otp-Add-support-for-RK3528.patch => 038-4-v7.1-nvmem-rockchip-otp-Add-support-for-RK3528.patch} (73%) create mode 100644 target/linux/rockchip/patches-6.18/072-1-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3562.patch create mode 100644 target/linux/rockchip/patches-6.18/072-2-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK356x.patch rename target/linux/rockchip/patches-6.18/{163-01-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch => 072-3-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch} (73%) diff --git a/target/linux/rockchip/patches-6.18/162-01-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch b/target/linux/rockchip/patches-6.18/038-1-v7.1-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch similarity index 92% rename from target/linux/rockchip/patches-6.18/162-01-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch rename to target/linux/rockchip/patches-6.18/038-1-v7.1-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch index c339e6144d..43b9c7951e 100644 --- a/target/linux/rockchip/patches-6.18/162-01-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch +++ b/target/linux/rockchip/patches-6.18/038-1-v7.1-nvmem-rockchip-otp-Handle-internal-word_size-in-main.patch @@ -1,6 +1,6 @@ -From 7f6f8fc3ee62f6eb633320c7989d4ba502787e3c Mon Sep 17 00:00:00 2001 +From 6c403594354d59fb288978c5a23008da89ba2741 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Sun, 16 Mar 2025 19:18:58 +0000 +Date: Fri, 27 Mar 2026 13:17:48 +0000 Subject: [PATCH] nvmem: rockchip-otp: Handle internal word_size in main reg_read op @@ -19,8 +19,13 @@ specific read_reg operation and allow code reuse in a future RK3568 reg_read operation. Signed-off-by: Jonas Karlman +Tested-by: Willy Tarreau +Signed-off-by: Heiko Stuebner Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Link: https://patch.msgid.link/20260327131751.3026030-7-srini@kernel.org +Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/rockchip-otp.c | 72 ++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/target/linux/rockchip/patches-6.18/162-02-nvmem-rockchip-otp-Add-support-for-RK3568.patch b/target/linux/rockchip/patches-6.18/038-2-v7.1-nvmem-rockchip-otp-Add-support-for-RK3568.patch similarity index 89% rename from target/linux/rockchip/patches-6.18/162-02-nvmem-rockchip-otp-Add-support-for-RK3568.patch rename to target/linux/rockchip/patches-6.18/038-2-v7.1-nvmem-rockchip-otp-Add-support-for-RK3568.patch index 98c3a31334..07fafb0d00 100644 --- a/target/linux/rockchip/patches-6.18/162-02-nvmem-rockchip-otp-Add-support-for-RK3568.patch +++ b/target/linux/rockchip/patches-6.18/038-2-v7.1-nvmem-rockchip-otp-Add-support-for-RK3568.patch @@ -1,15 +1,18 @@ -From 24ddbf99c76a352cc1931ccb5118bca0656034b8 Mon Sep 17 00:00:00 2001 +From 902fa931a2095566de6be12c8153f7fa9b31ab5f Mon Sep 17 00:00:00 2001 From: Finley Xiao -Date: Tue, 15 Apr 2025 18:32:02 +0800 +Date: Fri, 27 Mar 2026 13:17:49 +0000 Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3568 This adds the necessary data for handling otp the rk3568. Signed-off-by: Finley Xiao Signed-off-by: Kever Yang +Signed-off-by: Heiko Stuebner Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner -Signed-off-by: Jonas Karlman +Signed-off-by: Srinivas Kandagatla +Link: https://patch.msgid.link/20260327131751.3026030-8-srini@kernel.org +Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/rockchip-otp.c | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/target/linux/rockchip/patches-6.18/038-3-v7.1-nvmem-rockchip-otp-Add-support-for-RK3562.patch b/target/linux/rockchip/patches-6.18/038-3-v7.1-nvmem-rockchip-otp-Add-support-for-RK3562.patch new file mode 100644 index 0000000000..49396b5b6c --- /dev/null +++ b/target/linux/rockchip/patches-6.18/038-3-v7.1-nvmem-rockchip-otp-Add-support-for-RK3562.patch @@ -0,0 +1,33 @@ +From 7efe11aace70faa2199bc42d8949cd289b2998da Mon Sep 17 00:00:00 2001 +From: Finley Xiao +Date: Fri, 27 Mar 2026 13:17:50 +0000 +Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3562 + +This adds the necessary data for handling otp on the rk3562. + +Signed-off-by: Finley Xiao +Signed-off-by: Kever Yang +Signed-off-by: Heiko Stuebner +Tested-by: Willy Tarreau +Reviewed-by: Heiko Stuebner +Signed-off-by: Srinivas Kandagatla +Signed-off-by: Jonas Karlman +Link: https://patch.msgid.link/20260327131751.3026030-9-srini@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/rockchip-otp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/nvmem/rockchip-otp.c ++++ b/drivers/nvmem/rockchip-otp.c +@@ -377,6 +377,10 @@ static const struct of_device_id rockchi + .data = &px30_data, + }, + { ++ .compatible = "rockchip,rk3562-otp", ++ .data = &rk3568_data, ++ }, ++ { + .compatible = "rockchip,rk3568-otp", + .data = &rk3568_data, + }, diff --git a/target/linux/rockchip/patches-6.18/162-03-nvmem-rockchip-otp-Add-support-for-RK3528.patch b/target/linux/rockchip/patches-6.18/038-4-v7.1-nvmem-rockchip-otp-Add-support-for-RK3528.patch similarity index 73% rename from target/linux/rockchip/patches-6.18/162-03-nvmem-rockchip-otp-Add-support-for-RK3528.patch rename to target/linux/rockchip/patches-6.18/038-4-v7.1-nvmem-rockchip-otp-Add-support-for-RK3528.patch index eed7271c57..b8b50cb71a 100644 --- a/target/linux/rockchip/patches-6.18/162-03-nvmem-rockchip-otp-Add-support-for-RK3528.patch +++ b/target/linux/rockchip/patches-6.18/038-4-v7.1-nvmem-rockchip-otp-Add-support-for-RK3528.patch @@ -1,12 +1,17 @@ -From 249b07e24d3d1d47b7ec23d5f09a56837b66d7f5 Mon Sep 17 00:00:00 2001 +From a255f352b0e0c06d4b91233f112ddd35eac89947 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Sun, 16 Mar 2025 00:05:45 +0000 +Date: Fri, 27 Mar 2026 13:17:51 +0000 Subject: [PATCH] nvmem: rockchip-otp: Add support for RK3528 Add support for the OTP controller in RK3528. The OTPC is similar to the OTPC in RK3562 and RK3568, exept for a missing phy clock and reset. Signed-off-by: Jonas Karlman +Signed-off-by: Heiko Stuebner +Tested-by: Willy Tarreau +Signed-off-by: Srinivas Kandagatla +Link: https://patch.msgid.link/20260327131751.3026030-10-srini@kernel.org +Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/rockchip-otp.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) @@ -40,6 +45,6 @@ Signed-off-by: Jonas Karlman + .data = &rk3528_data, + }, + { - .compatible = "rockchip,rk3568-otp", + .compatible = "rockchip,rk3562-otp", .data = &rk3568_data, }, diff --git a/target/linux/rockchip/patches-6.18/072-1-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3562.patch b/target/linux/rockchip/patches-6.18/072-1-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3562.patch new file mode 100644 index 0000000000..640bf450e9 --- /dev/null +++ b/target/linux/rockchip/patches-6.18/072-1-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3562.patch @@ -0,0 +1,69 @@ +From 2448f33ff93ca9e41ce419e4bc7257010fa70a04 Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Thu, 12 Mar 2026 22:30:17 +0100 +Subject: [PATCH] arm64: dts: rockchip: Enable OTP controller for RK3562 + +Enable the One Time Programmable Controller (OTPC) in RK3562 and add +an initial nvmem fixed layout. + +Signed-off-by: Heiko Stuebner +Link: https://patch.msgid.link/20260312213019.13965-2-heiko@sntech.de +--- + arch/arm64/boot/dts/rockchip/rk3562.dtsi | 46 ++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3562.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3562.dtsi +@@ -1093,6 +1093,52 @@ + status = "disabled"; + }; + ++ otp: efuse@ff930000 { ++ compatible = "rockchip,rk3562-otp"; ++ reg = <0x0 0xff930000 0x0 0x4000>; ++ clocks = <&cru CLK_USER_OTPC_NS>, <&cru PCLK_OTPC_NS>, ++ <&cru PCLK_OTPPHY>, <&cru CLK_SBPI_OTPC_NS>; ++ clock-names = "otp", "apb_pclk", "phy", "sbpi"; ++ resets = <&cru SRST_USER_OTPC_NS>, <&cru SRST_P_OTPC_NS>, ++ <&cru SRST_P_OTPPHY>, <&cru SRST_SBPI_OTPC_NS>; ++ reset-names = "otp", "apb", "phy", "sbpi"; ++ ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ cpu_code: cpu-code@2 { ++ reg = <0x02 0x2>; ++ }; ++ ++ otp_cpu_version: cpu-version@8 { ++ reg = <0x08 0x1>; ++ bits = <3 3>; ++ }; ++ ++ otp_id: id@a { ++ reg = <0x0a 0x10>; ++ }; ++ ++ cpu_leakage: cpu-leakage@1a { ++ reg = <0x1a 0x1>; ++ }; ++ ++ log_leakage: log-leakage@1b { ++ reg = <0x1b 0x1>; ++ }; ++ ++ npu_leakage: npu-leakage@1c { ++ reg = <0x1c 0x1>; ++ }; ++ ++ gpu_leakage: gpu-leakage@1d { ++ reg = <0x1d 0x1>; ++ }; ++ }; ++ }; ++ + dmac: dma-controller@ff990000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0xff990000 0x0 0x4000>; diff --git a/target/linux/rockchip/patches-6.18/072-2-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK356x.patch b/target/linux/rockchip/patches-6.18/072-2-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK356x.patch new file mode 100644 index 0000000000..38058285d9 --- /dev/null +++ b/target/linux/rockchip/patches-6.18/072-2-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK356x.patch @@ -0,0 +1,70 @@ +From fae36d252e3344eefd95a94c026c170003805917 Mon Sep 17 00:00:00 2001 +From: Heiko Stuebner +Date: Thu, 12 Mar 2026 22:30:18 +0100 +Subject: [PATCH] arm64: dts: rockchip: Enable OTP controller for RK356x + +Enable the One Time Programmable Controller (OTPC) in RK356x and add +an initial nvmem fixed layout. + +Tested-by: Diederik de Haas # NanoPi R5S, PineNote +Signed-off-by: Heiko Stuebner +Link: https://patch.msgid.link/20260312213019.13965-3-heiko@sntech.de +--- + arch/arm64/boot/dts/rockchip/rk356x-base.dtsi | 46 +++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x-base.dtsi +@@ -1057,6 +1057,52 @@ + status = "disabled"; + }; + ++ otp: efuse@fe38c000 { ++ compatible = "rockchip,rk3568-otp"; ++ reg = <0x0 0xfe38c000 0x0 0x4000>; ++ clocks = <&cru CLK_OTPC_NS_USR>, <&cru PCLK_OTPC_NS>, ++ <&cru PCLK_OTPPHY>, <&cru CLK_OTPC_NS_SBPI>; ++ clock-names = "otp", "apb_pclk", "phy", "sbpi"; ++ resets = <&cru SRST_OTPC_NS_USR>, <&cru SRST_P_OTPC_NS>, ++ <&cru SRST_OTPPHY>, <&cru SRST_OTPC_NS_SBPI>; ++ reset-names = "otp", "apb", "phy", "sbpi"; ++ ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ cpu_code: cpu-code@2 { ++ reg = <0x02 0x2>; ++ }; ++ ++ otp_cpu_version: cpu-version@8 { ++ reg = <0x08 0x1>; ++ bits = <3 3>; ++ }; ++ ++ otp_id: id@a { ++ reg = <0x0a 0x10>; ++ }; ++ ++ cpu_leakage: cpu-leakage@1a { ++ reg = <0x1a 0x1>; ++ }; ++ ++ log_leakage: log-leakage@1b { ++ reg = <0x1b 0x1>; ++ }; ++ ++ npu_leakage: npu-leakage@1c { ++ reg = <0x1c 0x1>; ++ }; ++ ++ gpu_leakage: gpu-leakage@1d { ++ reg = <0x1d 0x1>; ++ }; ++ }; ++ }; ++ + i2s0_8ch: i2s@fe400000 { + compatible = "rockchip,rk3568-i2s-tdm"; + reg = <0x0 0xfe400000 0x0 0x1000>; diff --git a/target/linux/rockchip/patches-6.18/163-01-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch b/target/linux/rockchip/patches-6.18/072-3-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch similarity index 73% rename from target/linux/rockchip/patches-6.18/163-01-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch rename to target/linux/rockchip/patches-6.18/072-3-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch index ebd710c764..47dc01a2be 100644 --- a/target/linux/rockchip/patches-6.18/163-01-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch +++ b/target/linux/rockchip/patches-6.18/072-3-v7.1-arm64-dts-rockchip-Enable-OTP-controller-for-RK3528.patch @@ -1,31 +1,31 @@ -From 8a50a4471e4b0db33a74c01229a7ad386918344b Mon Sep 17 00:00:00 2001 +From 8c2c73084bd10237a9bc8f1d5fd49fe3107e4562 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Sun, 16 Mar 2025 00:06:43 +0000 +Date: Thu, 12 Mar 2026 22:30:19 +0100 Subject: [PATCH] arm64: dts: rockchip: Enable OTP controller for RK3528 Enable the One Time Programmable Controller (OTPC) in RK3528 and add an initial nvmem fixed layout. Signed-off-by: Jonas Karlman +Signed-off-by: Heiko Stuebner +Link: https://patch.msgid.link/20260312213019.13965-4-heiko@sntech.de --- - arch/arm64/boot/dts/rockchip/rk3528.dtsi | 49 ++++++++++++++++++++++++ - 1 file changed, 49 insertions(+) + arch/arm64/boot/dts/rockchip/rk3528.dtsi | 47 ++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi -@@ -1190,6 +1190,55 @@ +@@ -1190,6 +1190,53 @@ status = "disabled"; }; -+ otp: nvmem@ffce0000 { ++ otp: efuse@ffce0000 { + compatible = "rockchip,rk3528-otp"; + reg = <0x0 0xffce0000 0x0 0x4000>; -+ clocks = <&cru CLK_USER_OTPC_NS>, -+ <&cru PCLK_OTPC_NS>, ++ clocks = <&cru CLK_USER_OTPC_NS>, <&cru PCLK_OTPC_NS>, + <&cru CLK_SBPI_OTPC_NS>; + clock-names = "otp", "apb_pclk", "sbpi"; -+ resets = <&cru SRST_USER_OTPC_NS>, -+ <&cru SRST_P_OTPC_NS>, ++ resets = <&cru SRST_USER_OTPC_NS>, <&cru SRST_P_OTPC_NS>, + <&cru SRST_SBPI_OTPC_NS>; + reset-names = "otp", "apb", "sbpi"; + From c97b4da1a83c6943cf01b1073bc4adfe58ff862e Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Thu, 4 Jun 2026 20:26:19 +0800 Subject: [PATCH 099/228] rockchip: replace rk3528 usb patch with upstream Replace the RK3528 USB driver and DT patch with the upstream version. Signed-off-by: Chukun Pan Link: https://github.com/openwrt/openwrt/pull/23770 Signed-off-by: Jonas Jelonek --- ...-usb2-Simplify-rockchip-usbgrf-hand.patch} | 11 +++-- ...nno-usb2-Add-clkout_ctl_phy-support.patch} | 8 +++- ...ip-inno-usb2-Add-support-for-RK3528.patch} | 45 ++++++++++++------- ...s-rockchip-Add-USB-nodes-for-RK3528.patch} | 28 +++++++----- ...p-Enable-USB-2.0-ports-on-Radxa-E20.patch} | 39 +++++++++++----- ...hip-Add-TSADC-controller-for-RK3528.patch} | 4 +- 6 files changed, 93 insertions(+), 42 deletions(-) rename target/linux/rockchip/patches-6.18/{160-01-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-handling.patch => 039-1-v7.2-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-hand.patch} (95%) rename target/linux/rockchip/patches-6.18/{160-02-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch => 039-2-v7.2-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch} (92%) rename target/linux/rockchip/patches-6.18/{160-03-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch => 039-3-v7.2-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch} (75%) rename target/linux/rockchip/patches-6.18/{163-02-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch => 073-1-v7.2-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch} (78%) rename target/linux/rockchip/patches-6.18/{164-arm64-dts-rockchip-Enable-USB-2-0-ports-on-Radxa-E20C.patch => 073-2-v7.2-arm64-dts-rockchip-Enable-USB-2.0-ports-on-Radxa-E20.patch} (61%) rename target/linux/rockchip/patches-6.18/{163-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch => 161-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch} (98%) diff --git a/target/linux/rockchip/patches-6.18/160-01-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-handling.patch b/target/linux/rockchip/patches-6.18/039-1-v7.2-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-hand.patch similarity index 95% rename from target/linux/rockchip/patches-6.18/160-01-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-handling.patch rename to target/linux/rockchip/patches-6.18/039-1-v7.2-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-hand.patch index a16fedf8b5..281f3dd83e 100644 --- a/target/linux/rockchip/patches-6.18/160-01-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-handling.patch +++ b/target/linux/rockchip/patches-6.18/039-1-v7.2-phy-rockchip-inno-usb2-Simplify-rockchip-usbgrf-hand.patch @@ -1,7 +1,8 @@ -From 4e7d472b61625804f585035a54364a6620bf803a Mon Sep 17 00:00:00 2001 +From be29cd958f5393004a24cd7b5b1da88dd90a651b Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Wed, 23 Jul 2025 12:23:00 +0000 -Subject: [PATCH] phy: rockchip: inno-usb2: Simplify rockchip,usbgrf handling +Date: Tue, 5 May 2026 19:04:07 +0200 +Subject: [PATCH] phy: rockchip: inno-usb2: Simplify rockchip,usbgrf + handling The logic to decide if usbgrf or grf should be used is more complex than it needs to be. For RK3568, RV1108 and soon RK3528 we can assign the @@ -15,6 +16,10 @@ The only expected change from this is that RK3528 can be supported because of an addition of a of_property_present() check. Signed-off-by: Jonas Karlman +Signed-off-by: Heiko Stuebner +Reviewed-by: Neil Armstrong +Link: https://patch.msgid.link/20260505170410.3265305-3-heiko@sntech.de +Signed-off-by: Vinod Koul --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 68 +++++-------------- 1 file changed, 18 insertions(+), 50 deletions(-) diff --git a/target/linux/rockchip/patches-6.18/160-02-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch b/target/linux/rockchip/patches-6.18/039-2-v7.2-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch similarity index 92% rename from target/linux/rockchip/patches-6.18/160-02-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch rename to target/linux/rockchip/patches-6.18/039-2-v7.2-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch index b977ae1130..f10df5409e 100644 --- a/target/linux/rockchip/patches-6.18/160-02-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch +++ b/target/linux/rockchip/patches-6.18/039-2-v7.2-phy-rockchip-inno-usb2-Add-clkout_ctl_phy-support.patch @@ -1,6 +1,6 @@ -From 6b767459cf9295f10ee95b8ab78fbce5991132ed Mon Sep 17 00:00:00 2001 +From 2775541de0580ab1cd077dfef710e6316563d567 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Wed, 23 Jul 2025 12:23:02 +0000 +Date: Tue, 5 May 2026 19:04:09 +0200 Subject: [PATCH] phy: rockchip: inno-usb2: Add clkout_ctl_phy support The 480m clk is controlled using regs in the PHY address space and not @@ -10,6 +10,10 @@ Add a clkout_ctl_phy usb2phy_reg to handle enable/disable of the 480m clk on these SoCs. Signed-off-by: Jonas Karlman +Signed-off-by: Heiko Stuebner +Reviewed-by: Neil Armstrong +Link: https://patch.msgid.link/20260505170410.3265305-5-heiko@sntech.de +Signed-off-by: Vinod Koul --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/target/linux/rockchip/patches-6.18/160-03-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch b/target/linux/rockchip/patches-6.18/039-3-v7.2-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch similarity index 75% rename from target/linux/rockchip/patches-6.18/160-03-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch rename to target/linux/rockchip/patches-6.18/039-3-v7.2-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch index bce862b913..08bccd70ec 100644 --- a/target/linux/rockchip/patches-6.18/160-03-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch +++ b/target/linux/rockchip/patches-6.18/039-3-v7.2-phy-rockchip-inno-usb2-Add-support-for-RK3528.patch @@ -1,6 +1,6 @@ -From 8faac4ef6206a1c771e1c016e205dcee8164d618 Mon Sep 17 00:00:00 2001 +From 864b3617df827865a95a06f06f09a8d57a795b91 Mon Sep 17 00:00:00 2001 From: Jianwei Zheng -Date: Wed, 23 Jul 2025 12:23:03 +0000 +Date: Tue, 5 May 2026 19:04:10 +0200 Subject: [PATCH] phy: rockchip: inno-usb2: Add support for RK3528 The RK3528 has a single USB2PHY with a otg and host port. @@ -18,46 +18,61 @@ PHY tuning for RK3528: which uses dwc3 controller to improve fs/ls devices compatibility with long cables. -This is based on vendor kernel linux-stan-6.1-rkr5 tag. +Undocumented magic-values are based on the linux-stan-6.1-rkr5 tag of +the vendor-kernel. Signed-off-by: Jianwei Zheng Signed-off-by: Jonas Karlman +Signed-off-by: Heiko Stuebner +Reviewed-by: Neil Armstrong +Link: https://patch.msgid.link/20260505170410.3265305-6-heiko@sntech.de +Signed-off-by: Vinod Koul --- - drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 74 +++++++++++++++++++ - 1 file changed, 74 insertions(+) + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 84 +++++++++++++++++++ + 1 file changed, 84 insertions(+) --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c -@@ -1511,6 +1511,28 @@ static int rk3128_usb2phy_tuning(struct +@@ -1511,6 +1511,38 @@ static int rk3128_usb2phy_tuning(struct BIT(2) << BIT_WRITEABLE_SHIFT | 0); } +static int rk3528_usb2phy_tuning(struct rockchip_usb2phy *rphy) +{ -+ int ret = 0; ++ int ret; + + /* Turn off otg port differential receiver in suspend mode */ -+ ret |= regmap_write(rphy->phy_base, 0x30, BIT(18) | 0x0000); ++ ret = regmap_write(rphy->phy_base, 0x30, BIT(18) | 0x0000); ++ if (ret) ++ return ret; + + /* Turn off host port differential receiver in suspend mode */ -+ ret |= regmap_write(rphy->phy_base, 0x430, BIT(18) | 0x0000); ++ ret = regmap_write(rphy->phy_base, 0x430, BIT(18) | 0x0000); ++ if (ret) ++ return ret; + + /* Set otg port HS eye height to 400mv (default is 450mv) */ -+ ret |= regmap_write(rphy->phy_base, 0x30, GENMASK(22, 20) | 0x0000); ++ ret = regmap_write(rphy->phy_base, 0x30, GENMASK(22, 20) | 0x0000); ++ if (ret) ++ return ret; + + /* Set host port HS eye height to 400mv (default is 450mv) */ -+ ret |= regmap_write(rphy->phy_base, 0x430, GENMASK(22, 20) | 0x0000); ++ ret = regmap_write(rphy->phy_base, 0x430, GENMASK(22, 20) | 0x0000); ++ if (ret) ++ return ret; + + /* Choose the Tx fs/ls data as linestate from TX driver for otg port */ -+ ret |= regmap_write(rphy->phy_base, 0x94, GENMASK(22, 19) | 0x0018); ++ ret = regmap_write(rphy->phy_base, 0x94, GENMASK(22, 19) | 0x0018); ++ if (ret) ++ return ret; + -+ return ret; ++ return 0; +} + static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy) { int ret; -@@ -1924,6 +1946,57 @@ static const struct rockchip_usb2phy_cfg +@@ -1924,6 +1956,57 @@ static const struct rockchip_usb2phy_cfg { /* sentinel */ } }; @@ -115,7 +130,7 @@ Signed-off-by: Jonas Karlman static const struct rockchip_usb2phy_cfg rk3562_phy_cfgs[] = { { .reg = 0xff740000, -@@ -2291,6 +2364,7 @@ static const struct of_device_id rockchi +@@ -2291,6 +2374,7 @@ static const struct of_device_id rockchi { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs }, { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, diff --git a/target/linux/rockchip/patches-6.18/163-02-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch b/target/linux/rockchip/patches-6.18/073-1-v7.2-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch similarity index 78% rename from target/linux/rockchip/patches-6.18/163-02-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch rename to target/linux/rockchip/patches-6.18/073-1-v7.2-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch index 041cb4f3d1..95972977f0 100644 --- a/target/linux/rockchip/patches-6.18/163-02-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch +++ b/target/linux/rockchip/patches-6.18/073-1-v7.2-arm64-dts-rockchip-Add-USB-nodes-for-RK3528.patch @@ -1,23 +1,28 @@ -From a41519d8b438adc154debd433c3a1436ebb93a10 Mon Sep 17 00:00:00 2001 +From 5f3ae9b12a6c523992a7216bbc4420ac33450b79 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Wed, 23 Jul 2025 12:23:05 +0000 +Date: Fri, 29 May 2026 21:03:51 +0200 Subject: [PATCH] arm64: dts: rockchip: Add USB nodes for RK3528 -Rockchip RK3528 has one USB 3.0 DWC3 controller, a USB 2.0 EHCI/OHCI -controller and uses a USB2PHY for USB 2.0. The DWC3 controller may also -use the Naneng Combo PHY for USB3. +Rockchip RK3528 has one USB 3.0 DWC3 controller and oneUSB 2.0 EHCI/OHCI +controller and uses an Innosilicon-USB2PHY for USB 2.0. The DWC3 +controller additionally uses the Naneng Combo PHY for USB3. Add device tree nodes to describe these USB controllers along with the USB 2.0 PHYs. +[moved snps,dis_u2_susphy_quirk here from individual boards, + describe both usb2+3 default phy connections, usb2 boards can override] + Signed-off-by: Jonas Karlman +Signed-off-by: Heiko Stuebner +Link: https://patch.msgid.link/20260529190355.4148175-2-heiko@sntech.de --- - arch/arm64/boot/dts/rockchip/rk3528.dtsi | 77 ++++++++++++++++++++++++ - 1 file changed, 77 insertions(+) + arch/arm64/boot/dts/rockchip/rk3528.dtsi | 80 ++++++++++++++++++++++++ + 1 file changed, 80 insertions(+) --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi -@@ -336,6 +336,30 @@ +@@ -336,6 +336,33 @@ }; }; @@ -32,6 +37,8 @@ Signed-off-by: Jonas Karlman + power-domains = <&power RK3528_PD_VPU>; + resets = <&cru SRST_A_USB3OTG>; + dr_mode = "otg"; ++ phys = <&usb2phy_otg>, <&combphy PHY_TYPE_USB3>; ++ phy-names = "usb2-phy", "usb3-phy"; + phy_type = "utmi_wide"; + snps,dis_enblslpm_quirk; + snps,dis_rxdet_inp3_quirk; @@ -40,6 +47,7 @@ Signed-off-by: Jonas Karlman + snps,dis-u1-entry-quirk; + snps,dis-u2-entry-quirk; + snps,dis-u2-freeclk-exists-quirk; ++ snps,dis_u2_susphy_quirk; + snps,parkmode-disable-hs-quirk; + snps,parkmode-disable-ss-quirk; + status = "disabled"; @@ -48,7 +56,7 @@ Signed-off-by: Jonas Karlman gic: interrupt-controller@fed01000 { compatible = "arm,gic-400"; reg = <0x0 0xfed01000 0 0x1000>, -@@ -349,6 +373,30 @@ +@@ -349,6 +376,30 @@ #interrupt-cells = <3>; }; @@ -79,7 +87,7 @@ Signed-off-by: Jonas Karlman qos_crypto_a: qos@ff200000 { compatible = "rockchip,rk3528-qos", "syscon"; reg = <0x0 0xff200000 0x0 0x20>; -@@ -1275,6 +1323,35 @@ +@@ -1273,6 +1324,35 @@ rockchip,pipe-phy-grf = <&pipe_phy_grf>; status = "disabled"; }; diff --git a/target/linux/rockchip/patches-6.18/164-arm64-dts-rockchip-Enable-USB-2-0-ports-on-Radxa-E20C.patch b/target/linux/rockchip/patches-6.18/073-2-v7.2-arm64-dts-rockchip-Enable-USB-2.0-ports-on-Radxa-E20.patch similarity index 61% rename from target/linux/rockchip/patches-6.18/164-arm64-dts-rockchip-Enable-USB-2-0-ports-on-Radxa-E20C.patch rename to target/linux/rockchip/patches-6.18/073-2-v7.2-arm64-dts-rockchip-Enable-USB-2.0-ports-on-Radxa-E20.patch index 24e690c7cd..bb4ba5b7fb 100644 --- a/target/linux/rockchip/patches-6.18/164-arm64-dts-rockchip-Enable-USB-2-0-ports-on-Radxa-E20C.patch +++ b/target/linux/rockchip/patches-6.18/073-2-v7.2-arm64-dts-rockchip-Enable-USB-2.0-ports-on-Radxa-E20.patch @@ -1,21 +1,28 @@ -From d78af3aa816344d6e76dd77fbaf410fcbfa58bef Mon Sep 17 00:00:00 2001 +From e897bcf81dd920bf80ace6d98ec6f9645c5b50f2 Mon Sep 17 00:00:00 2001 From: Jonas Karlman -Date: Wed, 23 Jul 2025 12:23:06 +0000 +Date: Fri, 29 May 2026 21:03:52 +0200 Subject: [PATCH] arm64: dts: rockchip: Enable USB 2.0 ports on Radxa E20C -The Radxa E20C has one USB2.0 Type-A HOST port and one USB2.0 Type-C OTG -port. +The Radxa E20C has one USB2.0 Type-A HOST port and one USB2.0 Type-C port. + +The Type-C port is conneced to a FE1.1s_QFN USB hub on the board, with its +ports being connected to the XHCI usb controller and an usb-uart bridge. + +This also means, the XHCI controller can only be used in device-mode. Add support for using the USB 2.0 ports on Radxa E20C. Signed-off-by: Jonas Karlman +[set xhci to peripheral and add comment about the outward-facing hub] +Signed-off-by: Heiko Stuebner +Link: https://patch.msgid.link/20260529190355.4148175-3-heiko@sntech.de --- - .../boot/dts/rockchip/rk3528-radxa-e20c.dts | 48 +++++++++++++++++++ - 1 file changed, 48 insertions(+) + .../boot/dts/rockchip/rk3528-radxa-e20c.dts | 60 +++++++++++++++++++ + 1 file changed, 60 insertions(+) --- a/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts +++ b/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts -@@ -136,6 +136,18 @@ +@@ -134,6 +134,18 @@ regulator-max-microvolt = <5000000>; }; @@ -34,7 +41,7 @@ Signed-off-by: Jonas Karlman vccio_sd: regulator-vccio-sd { compatible = "regulator-gpio"; gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; -@@ -275,6 +287,12 @@ +@@ -273,6 +285,12 @@ rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; }; }; @@ -47,7 +54,7 @@ Signed-off-by: Jonas Karlman }; &pwm1 { -@@ -322,3 +340,33 @@ +@@ -320,3 +338,45 @@ pinctrl-0 = <&uart0m0_xfer>; status = "okay"; }; @@ -60,12 +67,24 @@ Signed-off-by: Jonas Karlman + status = "okay"; +}; + ++/* ++ * The usb controller can only work in peripheral mode, as it is ++ * connected to one of the ports of an outward-facing usb hub. ++ * ++ * type_c-port (hub-input) ++ * | ++ * usb-hub ++ * | | ++ * uart-usb usb-host0 ++ * | ++ * uart0 ++ */ +&usb_host0_xhci { ++ dr_mode = "peripheral"; + extcon = <&usb2phy>; + maximum-speed = "high-speed"; + phys = <&usb2phy_otg>; + phy-names = "usb2-phy"; -+ snps,dis_u2_susphy_quirk; + status = "okay"; +}; + diff --git a/target/linux/rockchip/patches-6.18/163-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch b/target/linux/rockchip/patches-6.18/161-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch similarity index 98% rename from target/linux/rockchip/patches-6.18/163-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch rename to target/linux/rockchip/patches-6.18/161-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch index 21d609e216..2d04e6c851 100644 --- a/target/linux/rockchip/patches-6.18/163-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch +++ b/target/linux/rockchip/patches-6.18/161-03-arm64-dts-rockchip-Add-TSADC-controller-for-RK3528.patch @@ -102,7 +102,7 @@ Signed-off-by: Jonas Karlman timer { compatible = "arm,armv8-timer"; interrupts = , -@@ -689,6 +739,7 @@ +@@ -692,6 +742,7 @@ assigned-clock-rates = <297000000>, <300000000>; clocks = <&cru ACLK_GPU_MALI>, <&scmi_clk SCMI_CLK_GPU>; clock-names = "bus", "core"; @@ -110,7 +110,7 @@ Signed-off-by: Jonas Karlman interrupts = , , , -@@ -1031,6 +1082,33 @@ +@@ -1034,6 +1085,33 @@ status = "disabled"; }; From 58ba08c4935bcd96e5d1b76ccf929cd73cbd3dc5 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Fri, 5 Jun 2026 20:08:18 +0800 Subject: [PATCH 100/228] rockchip: enable dwc3 usb dual-role mode for otg Most Rockchip boards have an OTG port. Enable DWC3 USB Dual-role mode for the OTG port to fix the following error: Configuration mismatch. dr_mode forced to host Signed-off-by: Chukun Pan Link: https://github.com/openwrt/openwrt/pull/23770 Signed-off-by: Jonas Jelonek --- target/linux/rockchip/armv8/config-6.18 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/target/linux/rockchip/armv8/config-6.18 b/target/linux/rockchip/armv8/config-6.18 index 9c1f1d4a30..c1213b5da5 100644 --- a/target/linux/rockchip/armv8/config-6.18 +++ b/target/linux/rockchip/armv8/config-6.18 @@ -733,11 +733,14 @@ CONFIG_UNMAP_KERNEL_AT_EL0=y CONFIG_USB=y CONFIG_USB_COMMON=y CONFIG_USB_DWC3=y -CONFIG_USB_DWC3_HOST=y +CONFIG_USB_DWC3_DUAL_ROLE=y +# CONFIG_USB_DWC3_GADGET is not set +# CONFIG_USB_DWC3_HOST is not set CONFIG_USB_DWC3_OF_SIMPLE=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD_PLATFORM=y # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_GADGET=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD_PLATFORM=y CONFIG_USB_PHY=y From 7aec4efba8ec1b40a83e6141930a6235da7882fb Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 20 Jun 2026 13:19:44 -0700 Subject: [PATCH 101/228] kernel: replace BUG_ON/BUG with WARN_ON/WARN_ON BUG() and BUG_ON() are deprecated - they destabilize the system and make debugging impossible. Replace with: - WARN_ON() + return error for assertion failures - WARN_ON_ONCE() for bounds checks - WARN_ON() + return -EPERM for in_interrupt() guards Assisted-by: Opencode:Big-Pickle Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23892 Signed-off-by: Jonas Jelonek --- target/linux/generic/files/drivers/net/phy/ar8216.c | 3 ++- target/linux/generic/files/drivers/net/phy/rtl8306.c | 9 ++++++--- .../linux/generic/files/drivers/net/phy/rtl8366_smi.c | 11 +++++++---- target/linux/generic/files/drivers/net/phy/swconfig.c | 3 ++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 71bf0bf04d..1f47c35753 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -2315,7 +2315,8 @@ ar8xxx_mib_init(struct ar8xxx_priv *priv) if (!ar8xxx_has_mib_counters(priv)) return 0; - BUG_ON(!priv->chip->mib_decs || !priv->chip->num_mibs); + if (WARN_ON(!priv->chip->mib_decs || !priv->chip->num_mibs)) + return -EINVAL; len = priv->dev.ports * priv->chip->num_mibs * sizeof(*priv->mib_stats); diff --git a/target/linux/generic/files/drivers/net/phy/rtl8306.c b/target/linux/generic/files/drivers/net/phy/rtl8306.c index a4b26642e2..5ddb874bf8 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8306.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8306.c @@ -266,7 +266,8 @@ rtl_set_page(struct rtl_priv *priv, unsigned int page) if (priv->page == page) return; - BUG_ON(page > RTL8306_NUM_PAGES); + if (WARN_ON_ONCE(page > RTL8306_NUM_PAGES)) + return; pgsel = bus->read(bus, 0, RTL8306_REG_PAGE); pgsel &= ~(RTL8306_REG_PAGE_LO | RTL8306_REG_PAGE_HI); if (page & (1 << 0)) @@ -320,7 +321,8 @@ rtl_get(struct switch_dev *dev, enum rtl_regidx s) const struct rtl_reg *r = &rtl_regs[s]; u16 val; - BUG_ON(s >= ARRAY_SIZE(rtl_regs)); + if (WARN_ON_ONCE(s >= ARRAY_SIZE(rtl_regs))) + return 0; if (r->bits == 0) /* unimplemented */ return 0; @@ -343,7 +345,8 @@ rtl_set(struct switch_dev *dev, enum rtl_regidx s, unsigned int val) const struct rtl_reg *r = &rtl_regs[s]; u16 mask = 0xffff; - BUG_ON(s >= ARRAY_SIZE(rtl_regs)); + if (WARN_ON_ONCE(s >= ARRAY_SIZE(rtl_regs))) + return -EINVAL; if (r->bits == 0) /* unimplemented */ return 0; diff --git a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c index aa8ef0bba2..84c6e7eca2 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c @@ -257,7 +257,8 @@ static int __rtl8366_mdio_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) u32 phy_id = smi->phy_id; struct mii_bus *mbus = smi->ext_mbus; - BUG_ON(in_interrupt()); + if (WARN_ON(in_interrupt())) + return -EPERM; mutex_lock(&mbus->mdio_lock); /* Write Start command to register 29 */ @@ -279,7 +280,7 @@ static int __rtl8366_mdio_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) mbus->write(mbus, phy_id, MDC_MDIO_CTRL1_REG, MDC_MDIO_READ_OP); /* Write Start command to register 29 */ - mbus->write(smi->ext_mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); + mbus->write(mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); /* Read data from register 25 */ *data = mbus->read(mbus, phy_id, MDC_MDIO_DATA_READ_REG); @@ -294,7 +295,8 @@ static int __rtl8366_mdio_write_reg(struct rtl8366_smi *smi, u32 addr, u32 data) u32 phy_id = smi->phy_id; struct mii_bus *mbus = smi->ext_mbus; - BUG_ON(in_interrupt()); + if (WARN_ON(in_interrupt())) + return -EPERM; mutex_lock(&mbus->mdio_lock); @@ -1344,7 +1346,8 @@ struct rtl8366_smi *rtl8366_smi_alloc(struct device *parent) { struct rtl8366_smi *smi; - BUG_ON(!parent); + if (WARN_ON(!parent)) + return NULL; smi = kzalloc(sizeof(*smi), GFP_KERNEL); if (!smi) { diff --git a/target/linux/generic/files/drivers/net/phy/swconfig.c b/target/linux/generic/files/drivers/net/phy/swconfig.c index f902ddc918..37c8ef7469 100644 --- a/target/linux/generic/files/drivers/net/phy/swconfig.c +++ b/target/linux/generic/files/drivers/net/phy/swconfig.c @@ -1114,7 +1114,8 @@ register_switch(struct switch_dev *dev, struct net_device *netdev) if (!dev->alias) dev->alias = netdev->name; } - BUG_ON(!dev->alias); + if (WARN_ON(!dev->alias)) + return -EINVAL; /* Make sure swdev_id doesn't overflow */ if (swdev_id == INT_MAX) { From 337246399914c899942d54bb57c36d3ef3df61b2 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 20 Jun 2026 13:21:46 -0700 Subject: [PATCH 102/228] kernel: replace open-coded arithmetic in allocators Dynamic size calculations in allocator arguments can overflow, leading to undersized allocations. Replace with: - kcalloc() for count * sizeof() patterns - devm_kcalloc() for managed allocations - array_size()/size_add()/size_mul() for complex cases Assisted-by: Opencode:Big-Pickle Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23892 Signed-off-by: Jonas Jelonek --- .../files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c | 2 +- .../files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c | 10 +++++----- .../files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c | 2 +- .../files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c | 2 +- .../generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c | 2 +- .../generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c | 2 +- .../generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c | 2 +- .../files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c | 2 +- .../files/drivers/mtd/mtdsplit/mtdsplit_jimage.c | 2 +- .../generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c | 2 +- .../files/drivers/mtd/mtdsplit/mtdsplit_minor.c | 2 +- .../files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c | 2 +- .../files/drivers/mtd/mtdsplit/mtdsplit_seama.c | 2 +- .../files/drivers/mtd/mtdsplit/mtdsplit_tplink.c | 2 +- .../generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c | 2 +- .../files/drivers/mtd/mtdsplit/mtdsplit_uimage.c | 2 +- .../generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c | 2 +- target/linux/generic/files/drivers/net/phy/ar8216.c | 7 ++----- target/linux/generic/files/drivers/net/phy/swconfig.c | 6 ++---- .../430-mtd-add-myloader-partition-parser.patch | 4 ++-- .../430-mtd-add-myloader-partition-parser.patch | 4 ++-- 21 files changed, 29 insertions(+), 34 deletions(-) diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c index 3a4b8a754f..cdb9bf0d77 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c @@ -127,7 +127,7 @@ static int bcm63xx_parse_partitions(struct mtd_info *master, if (mtd_check_rootfs_magic(master, rootfs_offset, NULL)) pr_warn("rootfs magic not found\n"); - parts = kzalloc(BCM63XX_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(BCM63XX_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c index 1cafc91fde..d8bcfb7f6e 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c @@ -200,7 +200,7 @@ static int parse_bcm_wfi(struct mtd_info *master, if (ret) return ret; - parts = kzalloc(num_parts * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(num_parts, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -348,7 +348,7 @@ static int mtdsplit_parse_bcm_wfi_split(struct mtd_info *master, kfree(buf); if (ret > 0) { - parts = kzalloc((ret + 1) * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(ret + 1, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -362,7 +362,7 @@ static int mtdsplit_parse_bcm_wfi_split(struct mtd_info *master, *pparts = parts; } else { - parts = kzalloc(BCM_WFI_SPLIT_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(BCM_WFI_SPLIT_PARTS, sizeof(*parts), GFP_KERNEL); parts[0].name = PART_IMAGE_1; parts[0].offset = img1_off; @@ -480,7 +480,7 @@ static int mtdsplit_parse_ser_wfi(struct mtd_info *master, kfree(buf); if (ret > 0) { - parts = kzalloc((ret + 1) * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(ret + 1, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; @@ -494,7 +494,7 @@ static int mtdsplit_parse_ser_wfi(struct mtd_info *master, *pparts = parts; } else { - parts = kzalloc(BCM_WFI_SPLIT_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(BCM_WFI_SPLIT_PARTS, sizeof(*parts), GFP_KERNEL); parts[0].name = PART_IMAGE_1; parts[0].offset = img1_off; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c index 3f2d79601a..4cb5d90aa7 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c @@ -71,7 +71,7 @@ static int mtdsplit_parse_brnimage(struct mtd_info *master, */ rootfs_size = master->size - rootfs_offset - BRNIMAGE_FOOTER_SIZE; - parts = kzalloc(BRNIMAGE_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(BRNIMAGE_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c index a3474c9dc2..c9d68f1393 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c @@ -54,7 +54,7 @@ static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd, if (err) return err; - parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c index db29054357..68e85cc9bf 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c @@ -244,7 +244,7 @@ static int mtdsplit_parse_elf(struct mtd_info *mtd, return -ENOENT; } - parts = kzalloc(ELF_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(ELF_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c index 55004a6d36..e6a61d7811 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c @@ -64,7 +64,7 @@ static int mtdsplit_parse_eva(struct mtd_info *master, if (err) return err; - parts = kzalloc(EVA_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(EVA_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c index b2042808e6..7f38e6d30c 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c @@ -272,7 +272,7 @@ mtdsplit_fit_parse(struct mtd_info *mtd, rootfs_size = mtd->size - rootfs_offset; - parts = kzalloc(2 * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(2, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c index a7b2b6ea7e..3bb585d344 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c @@ -140,7 +140,7 @@ static int mtdsplit_h3c_vfs_parse(struct mtd_info *mtd, if (err) return err; - parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c index a0ea81cfd6..19a5e1a571 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c @@ -108,7 +108,7 @@ static int __mtdsplit_parse_jimage(struct mtd_info *master, enum mtdsplit_part_type type; nr_parts = 2; - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c index 6dcffd0420..4467224270 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c @@ -69,7 +69,7 @@ static int mtdsplit_parse_lzma(struct mtd_info *master, if (err) return err; - parts = kzalloc(LZMA_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(LZMA_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c index bf1959f50a..71c937868a 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c @@ -88,7 +88,7 @@ static int mtdsplit_parse_minor(struct mtd_info *master, if (err) return err; - parts = kzalloc(MINOR_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(MINOR_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c index 78c9c4dae0..846652137d 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c @@ -95,7 +95,7 @@ static int mtdsplit_parse_owrt_prolog(struct mtd_info *master, if (ret) return ret; - parts = kzalloc(OWRT_PROLOG_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(OWRT_PROLOG_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c index 5d49171b1f..9f7063fa23 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c @@ -75,7 +75,7 @@ static int mtdsplit_parse_seama(struct mtd_info *master, return err; } - parts = kzalloc(SEAMA_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(SEAMA_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c index 8909c107a0..ba446be300 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c @@ -137,7 +137,7 @@ static int mtdsplit_parse_tplink(struct mtd_info *master, return err; } - parts = kzalloc(TPLINK_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(TPLINK_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c index 46a93ba38e..3621b53f74 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c @@ -71,7 +71,7 @@ mtdsplit_parse_trx(struct mtd_info *master, int ret; nr_parts = 2; - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c index fe824cbda6..f693cef3ad 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c @@ -139,7 +139,7 @@ static int __mtdsplit_parse_uimage(struct mtd_info *master, enum mtdsplit_part_type type; nr_parts = 2; - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c index dfd6058ae7..84c8b97e93 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c @@ -102,7 +102,7 @@ static int mtdsplit_parse_wrgg(struct mtd_info *master, if (err) return err; - parts = kzalloc(WRGG_NR_PARTS * sizeof(*parts), GFP_KERNEL); + parts = kcalloc(WRGG_NR_PARTS, sizeof(*parts), GFP_KERNEL); if (!parts) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index 1f47c35753..a01590c9eb 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -2310,17 +2310,14 @@ next_attempt: static int ar8xxx_mib_init(struct ar8xxx_priv *priv) { - unsigned int len; - if (!ar8xxx_has_mib_counters(priv)) return 0; if (WARN_ON(!priv->chip->mib_decs || !priv->chip->num_mibs)) return -EINVAL; - len = priv->dev.ports * priv->chip->num_mibs * - sizeof(*priv->mib_stats); - priv->mib_stats = kzalloc(len, GFP_KERNEL); + priv->mib_stats = kcalloc(array_size(priv->dev.ports, priv->chip->num_mibs), + sizeof(*priv->mib_stats), GFP_KERNEL); if (!priv->mib_stats) return -ENOMEM; diff --git a/target/linux/generic/files/drivers/net/phy/swconfig.c b/target/linux/generic/files/drivers/net/phy/swconfig.c index 37c8ef7469..d57c112802 100644 --- a/target/linux/generic/files/drivers/net/phy/swconfig.c +++ b/target/linux/generic/files/drivers/net/phy/swconfig.c @@ -1123,12 +1123,10 @@ register_switch(struct switch_dev *dev, struct net_device *netdev) } if (dev->ports > 0) { - dev->portbuf = kzalloc(sizeof(struct switch_port) * - dev->ports, GFP_KERNEL); + dev->portbuf = kcalloc(dev->ports, sizeof(struct switch_port), GFP_KERNEL); if (!dev->portbuf) return -ENOMEM; - dev->portmap = kzalloc(sizeof(struct switch_portmap) * - dev->ports, GFP_KERNEL); + dev->portmap = kcalloc(dev->ports, sizeof(struct switch_portmap), GFP_KERNEL); if (!dev->portmap) { kfree(dev->portbuf); return -ENOMEM; diff --git a/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch index 8ce112357a..e1fe9a46bc 100644 --- a/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch +++ b/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch @@ -149,8 +149,8 @@ Signed-off-by: Adrian Schmutzler + num_parts++; + } + -+ mtd_parts = kzalloc((num_parts * sizeof(*mtd_part) + -+ num_parts * PART_NAME_LEN), GFP_KERNEL); ++ mtd_parts = kzalloc(size_add(size_mul(num_parts, sizeof(*mtd_part)), ++ size_mul(num_parts, PART_NAME_LEN)), GFP_KERNEL); + + if (!mtd_parts) { + ret = -ENOMEM; diff --git a/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch index 8ce112357a..e1fe9a46bc 100644 --- a/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch +++ b/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch @@ -149,8 +149,8 @@ Signed-off-by: Adrian Schmutzler + num_parts++; + } + -+ mtd_parts = kzalloc((num_parts * sizeof(*mtd_part) + -+ num_parts * PART_NAME_LEN), GFP_KERNEL); ++ mtd_parts = kzalloc(size_add(size_mul(num_parts, sizeof(*mtd_part)), ++ size_mul(num_parts, PART_NAME_LEN)), GFP_KERNEL); + + if (!mtd_parts) { + ret = -ENOMEM; From 35ee4f8d31199095b9e62046adf52fd08e368ecb Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 20 Jun 2026 13:07:38 -0700 Subject: [PATCH 103/228] kernel: replace strncpy with safer alternatives strncpy is deprecated. Replace with: - strscpy() for NUL-terminated destinations - strscpy_pad() for NUL-terminated destinations with zero-padding - memcpy() for fixed-length in-place overwrites (bootargs mangle/cmdline replacement) Assisted-by: Opencode:Big-Pickle Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23892 Signed-off-by: Jonas Jelonek --- target/linux/generic/files/drivers/net/phy/rtl8306.c | 8 ++++---- .../linux/generic/files/drivers/net/phy/swconfig_leds.c | 3 +-- .../430-mtd-add-myloader-partition-parser.patch | 6 +++--- .../linux/generic/pending-6.12/920-mangle_bootargs.patch | 4 ++-- .../430-mtd-add-myloader-partition-parser.patch | 6 +++--- .../linux/generic/pending-6.18/920-mangle_bootargs.patch | 4 ++-- .../patches-6.12/0911-arm64-cmdline-replacement.patch | 2 +- 7 files changed, 16 insertions(+), 17 deletions(-) diff --git a/target/linux/generic/files/drivers/net/phy/rtl8306.c b/target/linux/generic/files/drivers/net/phy/rtl8306.c index 5ddb874bf8..b91c493689 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8306.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8306.c @@ -898,19 +898,19 @@ rtl8306_config_init(struct phy_device *pdev) switch(chiptype) { case 0: case 2: - strncpy(priv->hwname, RTL_NAME_S, sizeof(priv->hwname)); + strscpy(priv->hwname, RTL_NAME_S, sizeof(priv->hwname)); priv->type = RTL_TYPE_S; break; case 1: - strncpy(priv->hwname, RTL_NAME_SD, sizeof(priv->hwname)); + strscpy(priv->hwname, RTL_NAME_SD, sizeof(priv->hwname)); priv->type = RTL_TYPE_SD; break; case 3: - strncpy(priv->hwname, RTL_NAME_SDM, sizeof(priv->hwname)); + strscpy(priv->hwname, RTL_NAME_SDM, sizeof(priv->hwname)); priv->type = RTL_TYPE_SDM; break; default: - strncpy(priv->hwname, RTL_NAME_UNKNOWN, sizeof(priv->hwname)); + strscpy(priv->hwname, RTL_NAME_UNKNOWN, sizeof(priv->hwname)); break; } diff --git a/target/linux/generic/files/drivers/net/phy/swconfig_leds.c b/target/linux/generic/files/drivers/net/phy/swconfig_leds.c index 1fcd4432b5..b0970b00e8 100644 --- a/target/linux/generic/files/drivers/net/phy/swconfig_leds.c +++ b/target/linux/generic/files/drivers/net/phy/swconfig_leds.c @@ -237,8 +237,7 @@ static ssize_t swconfig_trig_mode_store(struct device *dev, char *p, *token; /* take a copy since we don't want to trash the inbound buffer when using strsep */ - strncpy(copybuf, buf, sizeof(copybuf)); - copybuf[sizeof(copybuf) - 1] = 0; + strscpy(copybuf, buf, sizeof(copybuf)); p = copybuf; while ((token = strsep(&p, " \t\n")) != NULL) { diff --git a/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch index e1fe9a46bc..8d308c989e 100644 --- a/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch +++ b/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch @@ -160,7 +160,7 @@ Signed-off-by: Adrian Schmutzler + mtd_part = mtd_parts; + names = (char *)&mtd_parts[num_parts]; + -+ strncpy(names, "myloader", PART_NAME_LEN); ++ strscpy_pad(names, "myloader", PART_NAME_LEN); + mtd_part->name = names; + mtd_part->offset = 0; + mtd_part->size = offset; @@ -168,7 +168,7 @@ Signed-off-by: Adrian Schmutzler + mtd_part++; + names += PART_NAME_LEN; + -+ strncpy(names, "partition_table", PART_NAME_LEN); ++ strscpy_pad(names, "partition_table", PART_NAME_LEN); + mtd_part->name = names; + mtd_part->offset = offset; + mtd_part->size = blocklen; @@ -183,7 +183,7 @@ Signed-off-by: Adrian Schmutzler + continue; + + if ((buf->names[i][0]) && (buf->names[i][0] != '\xff')) -+ strncpy(names, buf->names[i], PART_NAME_LEN); ++ strscpy_pad(names, buf->names[i], PART_NAME_LEN); + else + snprintf(names, PART_NAME_LEN, "partition%d", i); + diff --git a/target/linux/generic/pending-6.12/920-mangle_bootargs.patch b/target/linux/generic/pending-6.12/920-mangle_bootargs.patch index c3b2f9dd50..636bf8f90e 100644 --- a/target/linux/generic/pending-6.12/920-mangle_bootargs.patch +++ b/target/linux/generic/pending-6.12/920-mangle_bootargs.patch @@ -44,12 +44,12 @@ Signed-off-by: Imre Kaloz + rootdev = strstr(command_line, "root=/dev/mtdblock"); + + if (rootdev) -+ strncpy(rootdev, "mangled_rootblock=", 18); ++ memcpy(rootdev, "mangled_rootblock=", 18); + + rootfs = strstr(command_line, "rootfstype"); + + if (rootfs) -+ strncpy(rootfs, "mangled_fs", 10); ++ memcpy(rootfs, "mangled_fs", 10); + +} +#else diff --git a/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch index e1fe9a46bc..8d308c989e 100644 --- a/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch +++ b/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch @@ -160,7 +160,7 @@ Signed-off-by: Adrian Schmutzler + mtd_part = mtd_parts; + names = (char *)&mtd_parts[num_parts]; + -+ strncpy(names, "myloader", PART_NAME_LEN); ++ strscpy_pad(names, "myloader", PART_NAME_LEN); + mtd_part->name = names; + mtd_part->offset = 0; + mtd_part->size = offset; @@ -168,7 +168,7 @@ Signed-off-by: Adrian Schmutzler + mtd_part++; + names += PART_NAME_LEN; + -+ strncpy(names, "partition_table", PART_NAME_LEN); ++ strscpy_pad(names, "partition_table", PART_NAME_LEN); + mtd_part->name = names; + mtd_part->offset = offset; + mtd_part->size = blocklen; @@ -183,7 +183,7 @@ Signed-off-by: Adrian Schmutzler + continue; + + if ((buf->names[i][0]) && (buf->names[i][0] != '\xff')) -+ strncpy(names, buf->names[i], PART_NAME_LEN); ++ strscpy_pad(names, buf->names[i], PART_NAME_LEN); + else + snprintf(names, PART_NAME_LEN, "partition%d", i); + diff --git a/target/linux/generic/pending-6.18/920-mangle_bootargs.patch b/target/linux/generic/pending-6.18/920-mangle_bootargs.patch index b91a9e10ac..57942caced 100644 --- a/target/linux/generic/pending-6.18/920-mangle_bootargs.patch +++ b/target/linux/generic/pending-6.18/920-mangle_bootargs.patch @@ -44,12 +44,12 @@ Signed-off-by: Imre Kaloz + rootdev = strstr(command_line, "root=/dev/mtdblock"); + + if (rootdev) -+ strncpy(rootdev, "mangled_rootblock=", 18); ++ memcpy(rootdev, "mangled_rootblock=", 18); + + rootfs = strstr(command_line, "rootfstype"); + + if (rootfs) -+ strncpy(rootfs, "mangled_fs", 10); ++ memcpy(rootfs, "mangled_fs", 10); + +} +#else diff --git a/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch b/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch index 8e72f181a6..b376265a5c 100644 --- a/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch +++ b/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch @@ -91,7 +91,7 @@ Signed-off-by: Qiyuan Zhang + *(cur_ptr + offset) = *cur_ptr; + } + -+ strncpy(s_ptr, p, r_len - 1); ++ memcpy(s_ptr, p, r_len - 1); + + pr_info("Kernel command line after replacement: %s\n", cmdline); + } else { From a8282f563dbfde98acc40b41aa210ab15841b2e8 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 20 Jun 2026 16:52:51 -0700 Subject: [PATCH 104/228] kernel: handle bootargs-override the same everywhere l is an int. No need for a cast. Also might as well use l since it's available. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23892 Signed-off-by: Jonas Jelonek --- .../ipq806x/patches-6.12/900-arm-add-cmdline-override.patch | 2 +- .../mediatek/patches-6.18/901-arm-add-cmdline-override.patch | 2 +- .../mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch | 2 +- .../mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch b/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch index cd5c8c016d..d9e964d018 100644 --- a/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch +++ b/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch @@ -29,7 +29,7 @@ +#ifdef CONFIG_CMDLINE_OVERRIDE + p = of_get_flat_dt_prop(node, "bootargs-override", &l); + if (p != NULL && l > 0) -+ strscpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE)); ++ strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); +#endif + handle_cmdline: diff --git a/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch b/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch index 505ba385df..d1a4376bed 100644 --- a/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch +++ b/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch @@ -43,7 +43,7 @@ Signed-off-by: Yoonji Park +#ifdef CONFIG_CMDLINE_OVERRIDE + p = of_get_flat_dt_prop(node, "bootargs-override", &l); + if (p != NULL && l > 0) -+ strscpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE)); ++ strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); +#endif + handle_cmdline: diff --git a/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch b/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch index e7fb4bcd1b..2e526d6a30 100644 --- a/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch +++ b/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch @@ -29,7 +29,7 @@ +#ifdef CONFIG_CMDLINE_OVERRIDE + p = of_get_flat_dt_prop(node, "bootargs-override", &l); + if (p != NULL && l > 0) -+ strscpy(cmdline, p, COMMAND_LINE_SIZE); ++ strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); +#endif + handle_cmdline: diff --git a/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch b/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch index 2fe98ff9ad..6479766765 100644 --- a/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch +++ b/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch @@ -29,7 +29,7 @@ +#ifdef CONFIG_CMDLINE_OVERRIDE + p = of_get_flat_dt_prop(node, "bootargs-override", &l); + if (p != NULL && l > 0) -+ strscpy(cmdline, p, COMMAND_LINE_SIZE); ++ strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); +#endif + handle_cmdline: From ec26a78f1ea87682b59322f4703761a12aa12471 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 20 Jun 2026 22:02:34 -0700 Subject: [PATCH 105/228] kernel: fix wrong strlcat call strlcat takes the total buffer size, not the remaining space. Passing strlen(cmdline) + l caused it to truncate by one byte when the appended string fit within the buffer. This is also more consistent with the rest of the file. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23892 Signed-off-by: Jonas Jelonek --- target/linux/generic/hack-6.12/920-device_tree_cmdline.patch | 2 +- target/linux/generic/hack-6.18/920-device_tree_cmdline.patch | 2 +- .../ipq806x/patches-6.12/900-arm-add-cmdline-override.patch | 2 +- .../mediatek/patches-6.18/901-arm-add-cmdline-override.patch | 2 +- .../mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch | 2 +- .../mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch | 2 +- .../patches-6.12/0911-arm64-cmdline-replacement.patch | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/target/linux/generic/hack-6.12/920-device_tree_cmdline.patch b/target/linux/generic/hack-6.12/920-device_tree_cmdline.patch index 4763e82421..2f89dcec70 100644 --- a/target/linux/generic/hack-6.12/920-device_tree_cmdline.patch +++ b/target/linux/generic/hack-6.12/920-device_tree_cmdline.patch @@ -15,7 +15,7 @@ Subject: [PATCH] of/ftd: add device tree cmdline strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); + p = of_get_flat_dt_prop(node, "bootargs-append", &l); + if (p != NULL && l > 0) -+ strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); ++ strlcat(cmdline, p, COMMAND_LINE_SIZE); handle_cmdline: /* diff --git a/target/linux/generic/hack-6.18/920-device_tree_cmdline.patch b/target/linux/generic/hack-6.18/920-device_tree_cmdline.patch index 8bc6704d48..40c42e7bfb 100644 --- a/target/linux/generic/hack-6.18/920-device_tree_cmdline.patch +++ b/target/linux/generic/hack-6.18/920-device_tree_cmdline.patch @@ -15,7 +15,7 @@ Subject: [PATCH] of/ftd: add device tree cmdline strscpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); + p = of_get_flat_dt_prop(node, "bootargs-append", &l); + if (p != NULL && l > 0) -+ strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); ++ strlcat(cmdline, p, COMMAND_LINE_SIZE); handle_cmdline: /* diff --git a/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch b/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch index d9e964d018..1e4834527c 100644 --- a/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch +++ b/target/linux/ipq806x/patches-6.12/900-arm-add-cmdline-override.patch @@ -19,7 +19,7 @@ +++ b/drivers/of/fdt.c @@ -1053,6 +1053,17 @@ int __init early_init_dt_scan_chosen(cha if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + strlcat(cmdline, p, COMMAND_LINE_SIZE); + /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different + * device tree option of chosen/bootargs-override. This is diff --git a/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch b/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch index d1a4376bed..ebc4fb8b72 100644 --- a/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch +++ b/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch @@ -33,7 +33,7 @@ Signed-off-by: Yoonji Park +++ b/drivers/of/fdt.c @@ -1120,6 +1120,17 @@ int __init early_init_dt_scan_chosen(cha if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + strlcat(cmdline, p, COMMAND_LINE_SIZE); + /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different + * device tree option of chosen/bootargs-override. This is diff --git a/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch b/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch index 2e526d6a30..bdd45edfac 100644 --- a/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch +++ b/target/linux/mpc85xx/patches-6.12/102-powerpc-add-cmdline-override.patch @@ -19,7 +19,7 @@ +++ b/drivers/of/fdt.c @@ -1053,6 +1053,17 @@ int __init early_init_dt_scan_chosen(cha if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + strlcat(cmdline, p, COMMAND_LINE_SIZE); + /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different + * device tree option of chosen/bootargs-override. This is diff --git a/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch b/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch index 6479766765..f2ea1febb7 100644 --- a/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch +++ b/target/linux/mpc85xx/patches-6.18/102-powerpc-add-cmdline-override.patch @@ -19,7 +19,7 @@ +++ b/drivers/of/fdt.c @@ -1120,6 +1120,17 @@ int __init early_init_dt_scan_chosen(cha if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + strlcat(cmdline, p, COMMAND_LINE_SIZE); + /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different + * device tree option of chosen/bootargs-override. This is diff --git a/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch b/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch index b376265a5c..127677d220 100644 --- a/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch +++ b/target/linux/qualcommax/patches-6.12/0911-arm64-cmdline-replacement.patch @@ -102,4 +102,4 @@ Signed-off-by: Qiyuan Zhang + p = of_get_flat_dt_prop(node, "bootargs-append", &l); if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); + strlcat(cmdline, p, COMMAND_LINE_SIZE); From 4e2920fc0885d766519295cf7d3b84af589d7489 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Mon, 22 Jun 2026 08:08:35 +0000 Subject: [PATCH 106/228] package: nftables: replace patch with proper backport A patch was added without proper header and not obvious that it's a backport. Replace that patch with a backport of the upstream commit. Patch 001-build-simplify-the-instantiation-of-nftversion-h.patch rebased, all others refreshed. Fixes: 255f4c8e60 ("packages: nftables: fix build on host with busybox ash") Link: https://github.com/openwrt/openwrt/pull/23910 Signed-off-by: Jonas Jelonek --- package/network/utils/nftables/Makefile | 2 +- ...ld-fix-configure-with-non-bash-shell.patch | 29 +++++++++++++++++++ ...fy-the-instantiation-of-nftversion-h.patch | 13 +++------ .../patches/001-for-bash-syntax.patch | 11 ------- ...e-build-time-stamp-once-at-configure.patch | 8 +---- ...URCE_DATE_EPOCH-for-build-time-stamp.patch | 4 +-- 6 files changed, 36 insertions(+), 31 deletions(-) create mode 100644 package/network/utils/nftables/patches/000-build-fix-configure-with-non-bash-shell.patch delete mode 100644 package/network/utils/nftables/patches/001-for-bash-syntax.patch diff --git a/package/network/utils/nftables/Makefile b/package/network/utils/nftables/Makefile index fbcf77e554..6075ebb5af 100644 --- a/package/network/utils/nftables/Makefile +++ b/package/network/utils/nftables/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=nftables PKG_VERSION:=1.1.6 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files diff --git a/package/network/utils/nftables/patches/000-build-fix-configure-with-non-bash-shell.patch b/package/network/utils/nftables/patches/000-build-fix-configure-with-non-bash-shell.patch new file mode 100644 index 0000000000..03c2d4809b --- /dev/null +++ b/package/network/utils/nftables/patches/000-build-fix-configure-with-non-bash-shell.patch @@ -0,0 +1,29 @@ +From 2e3c68f26d5bd60c8ea7467fa9018c282a7d8c47 Mon Sep 17 00:00:00 2001 +From: Jan Palus +Date: Sat, 6 Dec 2025 00:43:58 +0100 +Subject: build: fix ./configure with non-bash shell + + CONFIG_SHELL=/bin/dash ./configure + +breaks with: + + ./config.status: 2044: Syntax error: Bad for loop variable + +Fixes: 64c07e38f049 ("table: Embed creating nft version into userdata") +Signed-off-by: Jan Palus +Signed-off-by: Pablo Neira Ayuso +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/configure.ac ++++ b/configure.ac +@@ -157,7 +157,7 @@ AC_CONFIG_COMMANDS([nftversion.h], [ + echo " ${STABLE_RELEASE}" + echo "};" + echo "static char nftbuildstamp[[]] = {" +- for ((i = 56; i >= 0; i-= 8)); do ++ for i in `seq 56 -8 0`; do + echo " ((uint64_t)MAKE_STAMP >> $i) & 0xff," + done + echo "};" diff --git a/package/network/utils/nftables/patches/001-build-simplify-the-instantiation-of-nftversion-h.patch b/package/network/utils/nftables/patches/001-build-simplify-the-instantiation-of-nftversion-h.patch index 64ca9b228d..933c0b599a 100644 --- a/package/network/utils/nftables/patches/001-build-simplify-the-instantiation-of-nftversion-h.patch +++ b/package/network/utils/nftables/patches/001-build-simplify-the-instantiation-of-nftversion-h.patch @@ -1,7 +1,7 @@ From 2a0ec8a7246e5c5eb85270e3d4de43e20a00c577 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Wed, 28 Jan 2026 18:31:05 +0000 -Subject: [PATCH] build: simplify the instantation of nftversion.h +Subject: build: simplify the instantation of nftversion.h Add an nftversion.h.in autoconf input file which configure uses to instantiate nftversion.h in the usual way. @@ -14,11 +14,9 @@ Signed-off-by: Phil Sutter 2 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 nftversion.h.in -diff --git a/configure.ac b/configure.ac -index 6825474..2c61072 100644 --- a/configure.ac +++ b/configure.ac -@@ -147,22 +147,8 @@ AM_CONDITIONAL([BUILD_SERVICE], [test "x$unitdir" != x]) +@@ -147,22 +147,8 @@ AM_CONDITIONAL([BUILD_SERVICE], [test "x AC_ARG_WITH([stable-release], [AS_HELP_STRING([--with-stable-release], [Stable release number])], [], [with_stable_release=0]) @@ -32,7 +30,7 @@ index 6825474..2c61072 100644 - echo " ${STABLE_RELEASE}" - echo "};" - echo "static char nftbuildstamp[[]] = {" -- for ((i = 56; i >= 0; i-= 8)); do +- for i in `seq 56 -8 0`; do - echo " ((uint64_t)MAKE_STAMP >> $i) & 0xff," - done - echo "};" @@ -43,7 +41,7 @@ index 6825474..2c61072 100644 # Current date should be fetched exactly once per build, # so have 'make' call date and pass the value to every 'gcc' call AC_SUBST([MAKE_STAMP], ["\$(shell date +%s)"]) -@@ -175,6 +161,7 @@ AM_CONDITIONAL([BUILD_DISTCHECK], [test "x$enable_distcheck" = "xyes"]) +@@ -175,6 +161,7 @@ AM_CONDITIONAL([BUILD_DISTCHECK], [test AC_CONFIG_FILES([ \ Makefile \ libnftables.pc \ @@ -51,9 +49,6 @@ index 6825474..2c61072 100644 ]) AC_OUTPUT -diff --git a/nftversion.h.in b/nftversion.h.in -new file mode 100644 -index 0000000..6f89771 --- /dev/null +++ b/nftversion.h.in @@ -0,0 +1,19 @@ diff --git a/package/network/utils/nftables/patches/001-for-bash-syntax.patch b/package/network/utils/nftables/patches/001-for-bash-syntax.patch deleted file mode 100644 index 8db917b5d6..0000000000 --- a/package/network/utils/nftables/patches/001-for-bash-syntax.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/configure -+++ b/configure -@@ -17940,7 +17940,7 @@ - echo " ${STABLE_RELEASE}" - echo "};" - echo "static char nftbuildstamp[] = {" -- for ((i = 56; i >= 0; i-= 8)); do -+ for i in `seq 56 -8 0`; do - echo " ((uint64_t)MAKE_STAMP >> $i) & 0xff," - done - echo "};" diff --git a/package/network/utils/nftables/patches/002-build-generate-build-time-stamp-once-at-configure.patch b/package/network/utils/nftables/patches/002-build-generate-build-time-stamp-once-at-configure.patch index eae6a5bc07..82b19b1dbc 100644 --- a/package/network/utils/nftables/patches/002-build-generate-build-time-stamp-once-at-configure.patch +++ b/package/network/utils/nftables/patches/002-build-generate-build-time-stamp-once-at-configure.patch @@ -19,8 +19,6 @@ Signed-off-by: Phil Sutter nftversion.h.in | 18 ++++++++++-------- 3 files changed, 11 insertions(+), 13 deletions(-) -diff --git a/Makefile.am b/Makefile.am -index b134330..ceb2225 100644 --- a/Makefile.am +++ b/Makefile.am @@ -159,8 +159,6 @@ AM_CFLAGS = \ @@ -32,11 +30,9 @@ index b134330..ceb2225 100644 $(NULL) AM_YFLAGS = -d -Wno-yacc -diff --git a/configure.ac b/configure.ac -index 2c61072..9859072 100644 --- a/configure.ac +++ b/configure.ac -@@ -149,9 +149,7 @@ AC_ARG_WITH([stable-release], [AS_HELP_STRING([--with-stable-release], +@@ -149,9 +149,7 @@ AC_ARG_WITH([stable-release], [AS_HELP_S [], [with_stable_release=0]) AC_SUBST([STABLE_RELEASE],[$with_stable_release]) AC_SUBST([NFT_VERSION], [$(echo "${VERSION}" | tr '.' ',')]) @@ -47,8 +43,6 @@ index 2c61072..9859072 100644 AC_ARG_ENABLE([distcheck], AS_HELP_STRING([--enable-distcheck], [Build for distcheck]), -diff --git a/nftversion.h.in b/nftversion.h.in -index 6f89771..325b9dc 100644 --- a/nftversion.h.in +++ b/nftversion.h.in @@ -1,19 +1,21 @@ diff --git a/package/network/utils/nftables/patches/003-build-support-SOURCE_DATE_EPOCH-for-build-time-stamp.patch b/package/network/utils/nftables/patches/003-build-support-SOURCE_DATE_EPOCH-for-build-time-stamp.patch index c37c77b7d2..83b014c7da 100644 --- a/package/network/utils/nftables/patches/003-build-support-SOURCE_DATE_EPOCH-for-build-time-stamp.patch +++ b/package/network/utils/nftables/patches/003-build-support-SOURCE_DATE_EPOCH-for-build-time-stamp.patch @@ -18,11 +18,9 @@ Signed-off-by: Phil Sutter configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/configure.ac b/configure.ac -index 9859072..0226086 100644 --- a/configure.ac +++ b/configure.ac -@@ -149,7 +149,7 @@ AC_ARG_WITH([stable-release], [AS_HELP_STRING([--with-stable-release], +@@ -149,7 +149,7 @@ AC_ARG_WITH([stable-release], [AS_HELP_S [], [with_stable_release=0]) AC_SUBST([STABLE_RELEASE],[$with_stable_release]) AC_SUBST([NFT_VERSION], [$(echo "${VERSION}" | tr '.' ',')]) From d3e13c05f7165130cae4cff1efe892fc10f0229d Mon Sep 17 00:00:00 2001 From: Sayantan Nandy Date: Fri, 19 Jun 2026 12:18:29 +0530 Subject: [PATCH 107/228] airoha: account for L2 overhead in PPE MTU configuration The PPE egress MTU register and WAN MTU register compare against L2 frame length without FCS, as confirmed by the hardware reset value of 0x05EA (1514 = ETH_HLEN + 1500). Account for VLAN_ETH_HLEN when programming these registers to prevent valid VLAN-tagged frames from being incorrectly dropped by hardware. Signed-off-by: Sayantan Nandy [ add commit description ] Link: https://github.com/openwrt/openwrt/pull/23875 Signed-off-by: Christian Marangi --- ...L2-overhead-in-PPE-MTU-configuration.patch | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 target/linux/airoha/patches-6.18/920-16-net-airoha-Account-for-L2-overhead-in-PPE-MTU-configuration.patch diff --git a/target/linux/airoha/patches-6.18/920-16-net-airoha-Account-for-L2-overhead-in-PPE-MTU-configuration.patch b/target/linux/airoha/patches-6.18/920-16-net-airoha-Account-for-L2-overhead-in-PPE-MTU-configuration.patch new file mode 100644 index 0000000000..5aac6bd031 --- /dev/null +++ b/target/linux/airoha/patches-6.18/920-16-net-airoha-Account-for-L2-overhead-in-PPE-MTU-configuration.patch @@ -0,0 +1,79 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sayantan Nandy +Date: Thu, 19 Jun 2026 12:00:00 +0530 +Subject: [PATCH] net: airoha: Account for L2 overhead in PPE MTU configuration + +The PPE egress MTU register and WAN MTU register compare against L2 +frame length without FCS, as confirmed by the hardware reset value of +0x05EA (1514 = ETH_HLEN + 1500). + +Account for VLAN_ETH_HLEN when programming these registers to prevent +valid VLAN-tagged frames from being incorrectly dropped by hardware. + +Rename the local variable from 'mtu' to 'len' in airoha_ppe_set_mtu() +since it now represents a frame length rather than an L3 MTU value. + +Fixes: 99e204d255c9 ("net: airoha: Rework MTU configuration") + +Signed-off-by: Sayantan Nandy +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + drivers/net/ethernet/airoha/airoha_ppe.c | 7 ++++--- + 2 files changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2115,7 +2116,7 @@ static void airoha_dev_set_mtu(struct ne + if (!airoha_is_lan_gdm_dev(dev)) + airoha_fe_rmw(dev->eth, REG_WAN_MTU0, + WAN_MTU0_MASK, +- FIELD_PREP(WAN_MTU0_MASK, netdev->mtu)); ++ FIELD_PREP(WAN_MTU0_MASK, netdev->mtu + VLAN_ETH_HLEN)); + } + + static int airoha_dev_open(struct net_device *netdev) +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -107,7 +108,7 @@ void airoha_ppe_set_mtu(struct airoha_gd + struct airoha_eth *eth = dev->eth; + struct airoha_qdma *qdma; + int i, ppe_id, index; +- u32 mtu = 0; ++ u32 len = 0; + + qdma = airoha_qdma_deref(dev); + for (i = 0; i < ARRAY_SIZE(port->devs); i++) { +@@ -124,14 +125,15 @@ void airoha_ppe_set_mtu(struct airoha_gd + + netdev = netdev_from_priv(d); + if (netif_running(netdev)) +- mtu = max_t(u32, mtu, netdev->mtu); ++ len = max_t(u32, len, netdev->mtu); + } + ++ len += VLAN_ETH_HLEN; + ppe_id = !airoha_is_lan_gdm_dev(dev) && airoha_ppe_is_enabled(eth, 1); + index = port->id == AIROHA_GDM4_IDX ? 7 : port->id; + airoha_fe_rmw(eth, REG_PPE_MTU(ppe_id, index), + FP_EGRESS_MTU_MASK(index), +- __field_prep(FP_EGRESS_MTU_MASK(index), mtu)); ++ __field_prep(FP_EGRESS_MTU_MASK(index), len)); + } + + static void airoha_ppe_hw_init(struct airoha_ppe *ppe) From 47d1bf564ff438781be3aa4fa8c1183734173293 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Mon, 22 Jun 2026 08:35:06 +0000 Subject: [PATCH 108/228] tools: bc: update to 1.08.2 Changelog included in source tar. Removed patches: - 000-getopt-prototype.patch - 001-getopt-declaration.patch Both patch changes are included upstream in this version. Link: https://github.com/openwrt/openwrt/pull/23911 Signed-off-by: Jonas Jelonek --- tools/bc/Makefile | 6 +++--- tools/bc/patches/000-getopt-prototype.patch | 18 ------------------ tools/bc/patches/001-getopt-declaration.patch | 11 ----------- 3 files changed, 3 insertions(+), 32 deletions(-) delete mode 100644 tools/bc/patches/000-getopt-prototype.patch delete mode 100644 tools/bc/patches/001-getopt-declaration.patch diff --git a/tools/bc/Makefile b/tools/bc/Makefile index e86a68c05b..1523ad1f65 100644 --- a/tools/bc/Makefile +++ b/tools/bc/Makefile @@ -7,11 +7,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bc -PKG_VERSION:=1.08.1 +PKG_VERSION:=1.08.2 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=@GNU/bc -PKG_HASH:=515430115b3334c636317503460a0950dff79940aa3259ce2c1aa67c2881d023 +PKG_HASH:=ae470fec429775653e042015edc928d07c8c3b2fc59765172a330d3d87785f86 PKG_CPE_ID:=cpe:/a:gnu:bc diff --git a/tools/bc/patches/000-getopt-prototype.patch b/tools/bc/patches/000-getopt-prototype.patch deleted file mode 100644 index ca6246963b..0000000000 --- a/tools/bc/patches/000-getopt-prototype.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/h/getopt.h -+++ b/h/getopt.h -@@ -135,15 +135,7 @@ struct option - arguments to the option '\0'. This behavior is specific to the GNU - `getopt'. */ - --#ifdef __GNU_LIBRARY__ --/* Many other libraries have conflicting prototypes for getopt, with -- differences in the consts, in stdlib.h. To avoid compilation -- errors, only prototype getopt for the GNU C library. */ - extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); --#else /* not __GNU_LIBRARY__ */ --extern int getopt (); --#endif /* __GNU_LIBRARY__ */ -- - #ifndef __need_getopt - extern int getopt_long (int ___argc, char *const *___argv, - const char *__shortopts, diff --git a/tools/bc/patches/001-getopt-declaration.patch b/tools/bc/patches/001-getopt-declaration.patch deleted file mode 100644 index c64be8dc03..0000000000 --- a/tools/bc/patches/001-getopt-declaration.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/lib/getopt.c -+++ b/lib/getopt.c -@@ -197,7 +197,7 @@ static char *posixly_correct; - whose names are inconsistent. */ - - #ifndef getenv --extern char *getenv (); -+extern char *getenv (const char *); - #endif - - #endif /* not __GNU_LIBRARY__ */ From 947e0d8c638c4704e79a93b0c30a73d53649cabd Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Fri, 19 Jun 2026 20:52:54 +0000 Subject: [PATCH 109/228] realtek: pcs: fix comment A comment sentence misses a word which likely confuses readers. Add the missing word before everyone forgets what it might be. Link: https://github.com/openwrt/openwrt/pull/23904 Signed-off-by: Jonas Jelonek --- target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index d03bc77707..2e5193069e 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -1682,7 +1682,7 @@ static int rtpcs_930x_sds_set_pll_select(struct rtpcs_serdes *sds, enum rtpcs_sd struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); int pbit = (sds == even_sds) ? 4 : 6; - /* Selecting the PLL a SerDes is done in the even lane register */ + /* Selecting the PLL a SerDes uses is done in the even lane register */ /* bit 0 is force-bit, bit 1 is PLL selector */ return rtpcs_sds_write_bits(even_sds, 0x20, 0x12, pbit + 1, pbit, (pll << 1) | BIT(0)); From 9be7947ac362f1ac6a6052ccd832529dd9121bd0 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Fri, 19 Jun 2026 21:36:32 +0000 Subject: [PATCH 110/228] realtek: pcs: add macro for USXGMII AN opcode Instead of hardcoding the USXGMII AN opcode values and potentially losing track of what they actually mean, add a define for them. Actually only one is used, however the other one gets a macro too for documentation purpose. Link: https://github.com/openwrt/openwrt/pull/23904 Signed-off-by: Jonas Jelonek --- .../realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 2e5193069e..1880286873 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -25,6 +25,10 @@ #define RTPCS_SPEED_2500 5 #define RTPCS_SPEED_5000 6 +/* USXGMII-AN opcodes. RTK variant unused but kept for documentation */ +#define RTPCS_USXGMII_AN_OPC_STD 0x03 +#define RTPCS_USXGMII_AN_OPC_RTK 0xaa + #define RTPCS_838X_CPU_PORT 28 #define RTPCS_838X_SERDES_CNT 6 #define RTPCS_838X_MAC_LINK_DUP_STS 0xa19c @@ -3015,8 +3019,8 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd return ret; if (!is_xsgmii) - /* opcode 0x03: standard/generic USXGMII mode */ - rtpcs_93xx_sds_usxgmii_config(sds, 0x03, 0xa4, 0, 1, 0x1); + rtpcs_93xx_sds_usxgmii_config(sds, RTPCS_USXGMII_AN_OPC_STD, + 0xa4, 0, 1, 0x1); break; default: @@ -3826,7 +3830,7 @@ static int rtpcs_931x_sds_config_hw_mode(struct rtpcs_serdes *sds, rtpcs_931x_sds_reset_leq_dfe(sds); rtpcs_931x_sds_rx_reset(sds); - rtpcs_93xx_sds_usxgmii_config(sds, 0x03, 0xa4, 0, 1, 0x1); + rtpcs_93xx_sds_usxgmii_config(sds, RTPCS_USXGMII_AN_OPC_STD, 0xa4, 0, 1, 0x1); break; case RTPCS_SDS_MODE_QSGMII: From 06cb5f1b2150ce798e803fa0408f3c63dfd8b0cb Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sat, 20 Jun 2026 08:11:09 +0000 Subject: [PATCH 111/228] realtek: pcs: drop unused modify helper Drop the unused rtpcs_sds_modify helper. Other helpers already provide what we need. Link: https://github.com/openwrt/openwrt/pull/23904 Signed-off-by: Jonas Jelonek --- .../realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 1880286873..2337dba530 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -416,16 +416,6 @@ static int rtpcs_sds_xsg_write(struct rtpcs_serdes *sds, int page, int regnum, u /* Other helpers */ -__maybe_unused -static int rtpcs_sds_modify(struct rtpcs_serdes *sds, int page, int regnum, - u16 mask, u16 set) -{ - int mmd_regnum = rtpcs_sds_to_mmd(page, regnum); - - return mdiobus_c45_modify(sds->ctrl->bus, sds->id, MDIO_MMD_VEND1, - mmd_regnum, mask, set); -} - static struct rtpcs_serdes *rtpcs_sds_get_even(struct rtpcs_serdes *sds) { u32 even_sds = sds->id & ~1; From 4ac14efb868f3aea4f6f9bf42f119811697c6142 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sat, 20 Jun 2026 08:13:00 +0000 Subject: [PATCH 112/228] realtek: pcs: drop wrong __maybe_unused Some functions specify __maybe_unused from former times although they are clearly used. Remove those attributes. Link: https://github.com/openwrt/openwrt/pull/23904 Signed-off-by: Jonas Jelonek --- target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 2337dba530..627abb65ab 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -395,7 +395,6 @@ static int rtpcs_sds_write_field(struct rtpcs_serdes *sds, const struct rtpcs_sd return sds->ops->write(sds, field->page, field->reg, field->msb, field->lsb, value); } -__maybe_unused static int rtpcs_sds_xsg_write_bits(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, int bitlow, u16 value) { @@ -405,7 +404,6 @@ static int rtpcs_sds_xsg_write_bits(struct rtpcs_serdes *sds, int page, int regn return sds->ops->xsg_write(sds, page, regnum, bithigh, bitlow, value); } -__maybe_unused static int rtpcs_sds_xsg_write(struct rtpcs_serdes *sds, int page, int regnum, u16 value) { if (!sds->ops->xsg_write) From f3b7cfcb5839ce00fcfb26fb08379f08ce7217f4 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sun, 21 Jun 2026 14:41:06 +0000 Subject: [PATCH 113/228] realtek: pcs: rename 'determine_hw_mode' to 'select_hw_mode' Rename the 'determine_hw_mode' to 'select_hw_mode' to better express what the function does. Based on the requested interface, the number of links on a SerDes and the capabilities, it selects a suitable hardware mode. 'determine' is clunkier and less expressive in this case. Link: https://github.com/openwrt/openwrt/pull/23904 Signed-off-by: Jonas Jelonek --- .../realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 627abb65ab..0cab0af37d 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -450,9 +450,8 @@ static struct rtpcs_link *rtpcs_phylink_pcs_to_link(struct phylink_pcs *pcs) return container_of(pcs, struct rtpcs_link, pcs); } -static int rtpcs_sds_determine_hw_mode(struct rtpcs_serdes *sds, - phy_interface_t if_mode, - enum rtpcs_sds_mode *hw_mode) +static int rtpcs_sds_select_hw_mode(struct rtpcs_serdes *sds, phy_interface_t if_mode, + enum rtpcs_sds_mode *hw_mode) { u8 n_links = sds->num_of_links; @@ -4032,7 +4031,7 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, enum rtpcs_sds_mode hw_mode; int ret; - ret = rtpcs_sds_determine_hw_mode(sds, interface, &hw_mode); + ret = rtpcs_sds_select_hw_mode(sds, interface, &hw_mode); if (ret < 0) { dev_err(ctrl->dev, "SerDes %u doesn't support %s mode\n", sds->id, phy_modes(interface)); From 0a7becdce1c3fbcb3b41c163bde4c6e575b818c8 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sun, 21 Jun 2026 10:53:59 +0000 Subject: [PATCH 114/228] realtek: pcs: rtl931x: use xsg_write instead of open-coded pattern The xsg_write operation for RTL931x already offers the correct procedure writing to both page + 0x40 and page + 0x80. Though, this wasn't used so far because this pattern was still open-coded where needed. Replace that with the xsg_write helper call. In clear_symerr, this deliberately changes the exact sequence of operations a bit. However, this shouldn't have any practical effect and testing shows no issues. Link: https://github.com/openwrt/openwrt/pull/23904 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 0cab0af37d..db7c25d397 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -3178,21 +3178,13 @@ static void rtpcs_931x_sds_clear_symerr(struct rtpcs_serdes *sds, case RTPCS_SDS_MODE_SGMII: case RTPCS_SDS_MODE_XSGMII: for (int i = 0; i < 4; ++i) { - rtpcs_sds_write_bits(sds, 0x41, 0x18, 2, 0, i); - rtpcs_sds_write_bits(sds, 0x41, 0x3, 15, 8, 0x0); - rtpcs_sds_write_bits(sds, 0x41, 0x2, 15, 0, 0x0); + rtpcs_sds_xsg_write_bits(sds, 0x1, 0x18, 2, 0, i); + rtpcs_sds_xsg_write_bits(sds, 0x1, 0x3, 15, 8, 0x0); + rtpcs_sds_xsg_write(sds, 0x1, 0x2, 0x0); } - for (int i = 0; i < 4; ++i) { - rtpcs_sds_write_bits(sds, 0x81, 0x18, 2, 0, i); - rtpcs_sds_write_bits(sds, 0x81, 0x3, 15, 8, 0x0); - rtpcs_sds_write_bits(sds, 0x81, 0x2, 15, 0, 0x0); - } - - rtpcs_sds_write_bits(sds, 0x41, 0x0, 15, 0, 0x0); - rtpcs_sds_write_bits(sds, 0x41, 0x1, 15, 8, 0x0); - rtpcs_sds_write_bits(sds, 0x81, 0x0, 15, 0, 0x0); - rtpcs_sds_write_bits(sds, 0x81, 0x1, 15, 8, 0x0); + rtpcs_sds_xsg_write(sds, 0x1, 0x0, 0x0); + rtpcs_sds_xsg_write_bits(sds, 0x1, 0x1, 15, 8, 0x0); break; case RTPCS_SDS_MODE_1000BASEX: rtpcs_sds_write_bits(sds, 0x41, 0x18, 2, 0, 0x0); @@ -3540,11 +3532,7 @@ static int rtpcs_931x_sds_config_polarity(struct rtpcs_serdes *sds, unsigned int /* xsg_*_inv */ val = (rx_val << 1) | tx_val; - ret = rtpcs_sds_write_bits(sds, 0x40, 0x0, 9, 8, val); - if (ret) - return ret; - - return rtpcs_sds_write_bits(sds, 0x80, 0x0, 9, 8, val); + return rtpcs_sds_xsg_write_bits(sds, 0x0, 0x0, 9, 8, val); } static const struct rtpcs_sds_tx_config rtpcs_931x_sds_tx_cfg_v1[] = { @@ -3804,8 +3792,7 @@ static int rtpcs_931x_sds_config_hw_mode(struct rtpcs_serdes *sds, break; case RTPCS_SDS_MODE_XSGMII: - rtpcs_sds_write_bits(sds, 0x40, 0xE, 12, 12, 1); - rtpcs_sds_write_bits(sds, 0x80, 0xE, 12, 12, 1); + rtpcs_sds_xsg_write_bits(sds, 0x0, 0xe, 12, 12, 0x1); break; case RTPCS_SDS_MODE_USXGMII_10GSXGMII: From 8ebf189e60fe9e703d8a687ea1da25f0fe25862a Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sun, 21 Jun 2026 14:07:39 +0000 Subject: [PATCH 115/228] realtek: pcs: drop unused cmu_band code For RTL930x and RTL931x, there were some functions to get and set the CMU band. However, they were used nearly nowhere and even the SDK doesn't use them for active SerDes configuration. Drop them to reduce dead code. Dropping the cmu_band_set call from RTL931x configuration has no negative effect. We do not know where this call originally came from. It was introduced 51c8f76612 ("realtek: improve MAC config handling for all SoCs") but without any explanation why and where it came from. The SDK doesn't have it and it may be overwritten again in the later CMU setup when parts of the SerDes are reset. Link: https://github.com/openwrt/openwrt/pull/23904 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 71 +------------------ 1 file changed, 1 insertion(+), 70 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index db7c25d397..d1bfdbf4f6 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -3030,33 +3030,6 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd return 0; } -__always_unused -static int rtpcs_930x_sds_cmu_band_get(struct rtpcs_serdes *sds) -{ - struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); - struct rtpcs_serdes *odd_sds = rtpcs_sds_get_odd(sds); - u32 page; - u32 en; - u32 cmu_band; - -/* page = rtl9300_sds_cmu_page_get(sds); */ - page = 0x25; /* 10GR and 1000BX */ - - rtpcs_sds_write_bits(even_sds, page, 0x1c, 15, 15, 1); - rtpcs_sds_write_bits(odd_sds, page, 0x1c, 15, 15, 1); - - en = rtpcs_sds_read_bits(even_sds, page, 27, 1, 1); - if (!en) { /* Auto mode */ - rtpcs_sds_write(even_sds, 0x1f, 0x02, 31); - - cmu_band = rtpcs_sds_read_bits(even_sds, 0x1f, 0x15, 5, 1); - } else { - cmu_band = rtpcs_sds_read_bits(even_sds, page, 30, 4, 0); - } - - return cmu_band; -} - static int rtpcs_930x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_media media, enum rtpcs_sds_mode hw_mode) { @@ -3290,6 +3263,7 @@ static int rtpcs_931x_sds_activate(struct rtpcs_serdes *sds) return rtpcs_931x_sds_power(sds, true); } +__maybe_unused static void rtpcs_931x_sds_reset(struct rtpcs_serdes *sds) { u32 o_mode, f_bit; @@ -3444,46 +3418,6 @@ static int rtpcs_931x_sds_reconfigure_to_pll(struct rtpcs_serdes *sds, enum rtpc return rtpcs_931x_sds_power(sds, true); } -static int rtpcs_931x_sds_cmu_band_set(struct rtpcs_serdes *sds, - bool enable, u32 band, - enum rtpcs_sds_mode hw_mode) -{ - struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); - int page = rtpcs_931x_sds_cmu_page_get(hw_mode); - int en_val; - - if (page < 0) - return -EINVAL; - - page += 1; - en_val = enable ? 0 : 1; - - rtpcs_sds_write_bits(even_sds, page, 0x7, 13, 13, en_val); - rtpcs_sds_write_bits(even_sds, page, 0x7, 11, 11, en_val); - rtpcs_sds_write_bits(even_sds, page, 0x7, 4, 0, band); - - rtpcs_931x_sds_reset(even_sds); - - return 0; -} - -__maybe_unused -static int rtpcs_931x_sds_cmu_band_get(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); - int page = rtpcs_931x_sds_cmu_page_get(hw_mode); - - if (page < 0) - return -EINVAL; - - page += 1; - rtpcs_sds_write(even_sds, 0x1f, 0x02, 73); - rtpcs_sds_write_bits(even_sds, page, 0x5, 15, 15, 0x1); - - return rtpcs_sds_read_bits(even_sds, 0x1f, 0x15, 8, 3); -} - __always_unused static int rtpcs_931x_sds_link_sts_get(struct rtpcs_serdes *sds) { @@ -3786,9 +3720,6 @@ static int rtpcs_931x_sds_config_hw_mode(struct rtpcs_serdes *sds, case RTPCS_SDS_MODE_SGMII: rtpcs_sds_write_bits(sds, 0x24, 0x9, 15, 15, 0); - - /* TODO: where does this come from? SDK doesn't have this. */ - rtpcs_931x_sds_cmu_band_set(sds, true, 62, RTPCS_SDS_MODE_SGMII); break; case RTPCS_SDS_MODE_XSGMII: From 8db23dc91a015bf843f1e3fbd0891574594e86f9 Mon Sep 17 00:00:00 2001 From: Kenneth Kasilag Date: Sun, 21 Jun 2026 23:26:43 +0000 Subject: [PATCH 116/228] qualcommbe: fix pwm period calculation During testing on the Askey SBE1V1K, it was noticed that only very low PWM frequencies would work, and 100% duty cycles also did not work. Comparing the proposed upstream pwm-ipq driver to the downstream vendor driver, `ipq_pwm_apply()` fixed pwm_div at its maximum and derived only pre_div from the requested period. Since the period spans `(pre_div + 1) * (pwm_div + 1)` input clocks, pinning pwm_div near its maximum forces pre_div towards zero for short periods: once pre_div rounds to 0 the shortest representable period is `(pwm_div + 1) / clk_rate` (~2.7 ms, i.e. ~366 Hz, at a 24 MHz clock), and any shorter request is silently stretched to that. The high duration then truncates to 0, so the output collapses to ~0% duty. Since 4-wire fans commonly expect a ~25kHz PWM, it was effectively unusable, since every duty cycle programs a ~zero high time. Search for the (pre_div, pwm_div) pair whose period best approximates the request instead of fixing pwm_div. Starting pre_div at the smallest value that keeps pwm_div within its field and stopping once pre_div exceeds pwm_div bounds the loop and keeps pwm_div as large as possible for fine duty resolution. For a 25 kHz request at 24 MHz this selects pre_div = 0, pwm_div = 959, giving full 0..960 duty resolution. While reworking the high-duration computation, round it to nearest rather than truncating, so mid-range duty cycles are not biased low, and clamp it to pwm_div + 1. Rounding, or a 100% duty request, could otherwise push hi_dur past the period length and overflow the 16-bit HI_DURATION field. Also compute hi_div in `get_state()` in 64-bit; `hi_dur * (pre_div + 1)` can exceed 32 bits before the existing promotion. Fixes: 01fb4a6daadb ("qualcommbe: update pwm patches and add missing symbol") Signed-off-by: Kenneth Kasilag Link: https://github.com/openwrt/openwrt/pull/23916 Signed-off-by: Markus Stockhausen --- .../0403-pwm-fix-period-calculation.patch | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch diff --git a/target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch b/target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch new file mode 100644 index 0000000000..78bce5fa11 --- /dev/null +++ b/target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch @@ -0,0 +1,166 @@ +From 314b696c26589f53cd9c1d1ca35edcfaddd362fb Mon Sep 17 00:00:00 2001 +From: Kenneth Kasilag +Date: Sun, 21 Jun 2026 23:26:43 +0000 +Subject: [PATCH] qualcommbe: fix pwm period calculation + +During testing on the Askey SBE1V1K, it was noticed that only very low +PWM frequencies would work, and 100% duty cycles also did not work. + +Comparing the proposed upstream pwm-ipq driver to the downstream vendor +driver, `ipq_pwm_apply()` fixed pwm_div at its maximum and derived only +pre_div from the requested period. Since the period spans +`(pre_div + 1) * (pwm_div + 1)` input clocks, pinning pwm_div near its +maximum forces pre_div towards zero for short periods: once pre_div +rounds to 0 the shortest representable period is +`(pwm_div + 1) / clk_rate` (~2.7 ms, i.e. ~366 Hz, at a 24 MHz clock), +and any shorter request is silently stretched to that. The high +duration then truncates to 0, so the output collapses to ~0% duty. + +Since 4-wire fans commonly expect a ~25kHz PWM, it was effectively +unusable, since every duty cycle programs a ~zero high time. + +Search for the (pre_div, pwm_div) pair whose period best approximates +the request instead of fixing pwm_div. Starting pre_div at the smallest +value that keeps pwm_div within its field and stopping once pre_div +exceeds pwm_div bounds the loop and keeps pwm_div as large as possible +for fine duty resolution. For a 25 kHz request at 24 MHz this selects +pre_div = 0, pwm_div = 959, giving full 0..960 duty resolution. + +While reworking the high-duration computation, round it to nearest +rather than truncating, so mid-range duty cycles are not biased low, and +clamp it to pwm_div + 1. Rounding, or a 100% duty request, could +otherwise push hi_dur past the period length and overflow the 16-bit +HI_DURATION field. + +Also compute hi_div in `get_state()` in 64-bit; `hi_dur * (pre_div + 1)` +can exceed 32 bits before the existing promotion. + +Fixes: 01fb4a6daadb ("qualcommbe: update pwm patches and add missing symbol") +Signed-off-by: Kenneth Kasilag +--- + drivers/pwm/pwm-ipq.c | 122 ++++++++++++++---- + 1 file changed, 108 insertions(+), 14 deletions(-) + +diff --git a/drivers/pwm/pwm-ipq.c b/drivers/pwm/pwm-ipq.c +index 3619091b546d12..0b616def6ae4cd 100644 +--- a/drivers/pwm/pwm-ipq.c ++++ b/drivers/pwm/pwm-ipq.c +@@ -89,10 +89,10 @@ static int ipq_pwm_apply(struct pwm_chip + const struct pwm_state *state) + { + struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip); +- unsigned int pre_div, pwm_div; +- u64 period_ns, duty_ns; ++ unsigned int pre_div, pwm_div, best_pre_div, best_pwm_div; ++ u64 period_ns, duty_ns, period_rate, min_diff; + unsigned long val = 0; +- unsigned long hi_dur; ++ u64 hi_dur; + + if (state->polarity != PWM_POLARITY_NORMAL) + return -EINVAL; +@@ -107,20 +107,86 @@ static int ipq_pwm_apply(struct pwm_chip + period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS); + duty_ns = min(state->duty_cycle, period_ns); + +- pwm_div = IPQ_PWM_MAX_DIV - 1; +- pre_div = mul_u64_u64_div_u64(period_ns, ipq_chip->clk_rate, +- (u64)NSEC_PER_SEC * (pwm_div + 1)); +- pre_div = (pre_div > 0) ? pre_div - 1 : 0; ++ /* ++ * The period spans (pre_div + 1) * (pwm_div + 1) input clocks. Rather ++ * than fixing pwm_div at its maximum (which gives usable duty ++ * resolution only for long periods and collapses to ~0% for short ++ * periods) search for the (pre_div, pwm_div) split whose period best ++ * approximates the request while leaving pwm_div large enough to ++ * resolve the duty cycle. ++ */ ++ if (ipq_chip->clk_rate > 16ULL * GIGA) ++ return -EINVAL; ++ period_rate = period_ns * ipq_chip->clk_rate; ++ ++ best_pre_div = IPQ_PWM_MAX_DIV; ++ best_pwm_div = IPQ_PWM_MAX_DIV; ++ min_diff = period_rate; ++ ++ /* ++ * Smaller pre_div than this cannot represent the period (pwm_div would ++ * have to exceed its field), so start the search there. ++ */ ++ pre_div = div64_u64(period_rate, ++ (u64)NSEC_PER_SEC * (IPQ_PWM_MAX_DIV + 1)); ++ ++ for (; pre_div <= IPQ_PWM_MAX_DIV; pre_div++) { ++ u64 remainder; ++ ++ pwm_div = div64_u64_rem(period_rate, ++ (u64)NSEC_PER_SEC * (pre_div + 1), ++ &remainder); ++ /* pwm_div is unsigned; the swap check below catches underflow */ ++ pwm_div--; ++ ++ /* ++ * Swapping pre_div and pwm_div yields the same period but a ++ * larger pwm_div gives finer duty resolution, so once pre_div ++ * exceeds pwm_div every further candidate is strictly worse. ++ */ ++ if (pre_div > pwm_div) ++ break; ++ ++ /* need room for 100% duty, where hi_dur == pwm_div + 1 */ ++ if (pwm_div > IPQ_PWM_MAX_DIV - 1) ++ continue; ++ ++ if (remainder < min_diff) { ++ best_pre_div = pre_div; ++ best_pwm_div = pwm_div; ++ min_diff = remainder; ++ ++ if (min_diff == 0) ++ break; ++ } ++ } + +- if (pre_div > IPQ_PWM_MAX_DIV) +- pre_div = IPQ_PWM_MAX_DIV; ++ pre_div = best_pre_div; ++ pwm_div = best_pwm_div; ++ ++ /* ++ * If the search found no usable candidate, best_pwm_div is left at ++ * IPQ_PWM_MAX_DIV; cap it so pwm_div + 1 still fits the 16-bit field ++ * and 100% duty remains expressible. ++ */ ++ if (pwm_div > IPQ_PWM_MAX_DIV - 1) ++ pwm_div = IPQ_PWM_MAX_DIV - 1; + + /* +- * high duration = pwm duty * (pwm div + 1) +- * pwm duty = duty_ns / period_ns ++ * high duration = duty_ratio * (pwm_div + 1) ++ * = duty_ns * clk_rate / ((pre_div + 1) * NSEC_PER_SEC) ++ * ++ * Round to nearest to avoid biasing every duty cycle low, then clamp ++ * to (pwm_div + 1): rounding or a 100% request can otherwise push ++ * hi_dur past the period, overflowing the 16-bit HI_DURATION field ++ * (which would alias a full-on request down to a near-zero high time) ++ * and asking the hardware to stay high beyond one period. pwm_div is ++ * at most IPQ_PWM_MAX_DIV - 1, so pwm_div + 1 always fits the field. + */ +- hi_dur = mul_u64_u64_div_u64(duty_ns, ipq_chip->clk_rate, +- (u64)(pre_div + 1) * NSEC_PER_SEC); ++ hi_dur = DIV64_U64_ROUND_CLOSEST(duty_ns * ipq_chip->clk_rate, ++ (u64)(pre_div + 1) * NSEC_PER_SEC); ++ if (hi_dur > (u64)pwm_div + 1) ++ hi_dur = (u64)pwm_div + 1; + + val = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) | + FIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div); +@@ -164,7 +230,7 @@ static int ipq_pwm_get_state(struct pwm_ + state->period = DIV64_U64_ROUND_UP(effective_div * NSEC_PER_SEC, + ipq_chip->clk_rate); + +- hi_div = hi_dur * (pre_div + 1); ++ hi_div = (u64)hi_dur * (pre_div + 1); + state->duty_cycle = DIV64_U64_ROUND_UP(hi_div * NSEC_PER_SEC, + ipq_chip->clk_rate); From d6d6c309d82412b67375e3ce70310c073e548db5 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 20 Jun 2026 14:13:12 -0700 Subject: [PATCH 117/228] kernel: use module_mtd_part_parser for mtdsplit Remove boilerplate. Also added deregister for bcm_wifi for consistency. Not needed as it's builtin but still good to have. There's a slight change from subsys_initcall to module_init. Not really an issue for mtd drivers. No driver in linux upstream's drivers/mtd uses subsys_initcall. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23893 Signed-off-by: Jonas Jelonek --- .../drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c | 9 +-------- .../drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c | 8 ++++++++ .../drivers/mtd/mtdsplit/mtdsplit_brnimage.c | 9 +-------- .../files/drivers/mtd/mtdsplit/mtdsplit_elf.c | 9 +-------- .../files/drivers/mtd/mtdsplit/mtdsplit_eva.c | 9 +-------- .../files/drivers/mtd/mtdsplit/mtdsplit_fit.c | 13 +------------ .../drivers/mtd/mtdsplit/mtdsplit_jimage.c | 13 +------------ .../files/drivers/mtd/mtdsplit/mtdsplit_lzma.c | 9 +-------- .../files/drivers/mtd/mtdsplit/mtdsplit_minor.c | 9 +-------- .../drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c | 9 +-------- .../files/drivers/mtd/mtdsplit/mtdsplit_seama.c | 9 +-------- .../drivers/mtd/mtdsplit/mtdsplit_squashfs.c | 9 +-------- .../drivers/mtd/mtdsplit/mtdsplit_tplink.c | 9 +-------- .../files/drivers/mtd/mtdsplit/mtdsplit_trx.c | 9 +-------- .../drivers/mtd/mtdsplit/mtdsplit_uimage.c | 13 +------------ .../files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c | 9 +-------- .../430-mtd-add-myloader-partition-parser.patch | 17 ++--------------- .../430-mtd-add-myloader-partition-parser.patch | 17 ++--------------- 18 files changed, 27 insertions(+), 162 deletions(-) diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c index cdb9bf0d77..e66e730991 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c @@ -176,11 +176,4 @@ static struct mtd_part_parser mtdsplit_bcm63xx_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_bcm63xx_init(void) -{ - register_mtd_parser(&mtdsplit_bcm63xx_parser); - - return 0; -} - -module_init(mtdsplit_bcm63xx_init); +module_mtd_part_parser(mtdsplit_bcm63xx_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c index d8bcfb7f6e..41e87e3b5c 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c @@ -532,4 +532,12 @@ static int __init mtdsplit_bcm_wfi_init(void) return 0; } +static void __exit mtdsplit_bcm_wfi_exit(void) +{ + deregister_mtd_parser(&mtdsplit_bcm_wfi_parser); + deregister_mtd_parser(&mtdsplit_bcm_wfi_split_parser); + deregister_mtd_parser(&mtdsplit_ser_wfi_parser); +} + module_init(mtdsplit_bcm_wfi_init); +module_exit(mtdsplit_bcm_wfi_exit); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c index 4cb5d90aa7..f029f726de 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_brnimage.c @@ -94,11 +94,4 @@ static struct mtd_part_parser mtdsplit_brnimage_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_brnimage_init(void) -{ - register_mtd_parser(&mtdsplit_brnimage_parser); - - return 0; -} - -subsys_initcall(mtdsplit_brnimage_init); +module_mtd_part_parser(mtdsplit_brnimage_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c index 68e85cc9bf..ca85ea8e5d 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_elf.c @@ -277,11 +277,4 @@ static struct mtd_part_parser mtdsplit_elf_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_elf_init(void) -{ - register_mtd_parser(&mtdsplit_elf_parser); - - return 0; -} - -subsys_initcall(mtdsplit_elf_init); +module_mtd_part_parser(mtdsplit_elf_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c index e6a61d7811..93fe5b5e74 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_eva.c @@ -93,11 +93,4 @@ static struct mtd_part_parser mtdsplit_eva_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_eva_init(void) -{ - register_mtd_parser(&mtdsplit_eva_parser); - - return 0; -} - -subsys_initcall(mtdsplit_eva_init); +module_mtd_part_parser(mtdsplit_eva_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c index 7f38e6d30c..2afc19d09f 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_fit.c @@ -351,15 +351,4 @@ static struct mtd_part_parser uimage_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -/************************************************** - * Init - **************************************************/ - -static int __init mtdsplit_fit_init(void) -{ - register_mtd_parser(&uimage_parser); - - return 0; -} - -module_init(mtdsplit_fit_init); +module_mtd_part_parser(uimage_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c index 19a5e1a571..c921593b98 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_jimage.c @@ -270,15 +270,4 @@ static struct mtd_part_parser jimage_generic_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -/************************************************** - * Init - **************************************************/ - -static int __init mtdsplit_jimage_init(void) -{ - register_mtd_parser(&jimage_generic_parser); - - return 0; -} - -module_init(mtdsplit_jimage_init); +module_mtd_part_parser(jimage_generic_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c index 4467224270..71e01ac7ea 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_lzma.c @@ -99,11 +99,4 @@ static struct mtd_part_parser mtdsplit_lzma_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_lzma_init(void) -{ - register_mtd_parser(&mtdsplit_lzma_parser); - - return 0; -} - -subsys_initcall(mtdsplit_lzma_init); +module_mtd_part_parser(mtdsplit_lzma_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c index 71c937868a..55cb9ce25b 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_minor.c @@ -118,11 +118,4 @@ static struct mtd_part_parser mtdsplit_minor_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_minor_init(void) -{ - register_mtd_parser(&mtdsplit_minor_parser); - - return 0; -} - -subsys_initcall(mtdsplit_minor_init); +module_mtd_part_parser(mtdsplit_minor_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c index 846652137d..c675aff9f3 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_owrt_prolog.c @@ -124,11 +124,4 @@ static struct mtd_part_parser mtdsplit_owrt_prolog_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_owrt_prolog_init(void) -{ - register_mtd_parser(&mtdsplit_owrt_prolog_parser); - - return 0; -} - -subsys_initcall(mtdsplit_owrt_prolog_init); +module_mtd_part_parser(mtdsplit_owrt_prolog_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c index 9f7063fa23..5c39397730 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_seama.c @@ -108,11 +108,4 @@ static struct mtd_part_parser mtdsplit_seama_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_seama_init(void) -{ - register_mtd_parser(&mtdsplit_seama_parser); - - return 0; -} - -subsys_initcall(mtdsplit_seama_init); +module_mtd_part_parser(mtdsplit_seama_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_squashfs.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_squashfs.c index f6353da65b..ba929c5e38 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_squashfs.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_squashfs.c @@ -62,11 +62,4 @@ static struct mtd_part_parser mtdsplit_squashfs_parser = { .type = MTD_PARSER_TYPE_ROOTFS, }; -static int __init mtdsplit_squashfs_init(void) -{ - register_mtd_parser(&mtdsplit_squashfs_parser); - - return 0; -} - -subsys_initcall(mtdsplit_squashfs_init); +module_mtd_part_parser(mtdsplit_squashfs_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c index ba446be300..03cc7dd2f3 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_tplink.c @@ -166,11 +166,4 @@ static struct mtd_part_parser mtdsplit_tplink_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_tplink_init(void) -{ - register_mtd_parser(&mtdsplit_tplink_parser); - - return 0; -} - -subsys_initcall(mtdsplit_tplink_init); +module_mtd_part_parser(mtdsplit_tplink_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c index 3621b53f74..869b92cdf1 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_trx.c @@ -145,11 +145,4 @@ static struct mtd_part_parser trx_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_trx_init(void) -{ - register_mtd_parser(&trx_parser); - - return 0; -} - -module_init(mtdsplit_trx_init); +module_mtd_part_parser(trx_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c index f693cef3ad..a2d2ba1622 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_uimage.c @@ -269,15 +269,4 @@ static struct mtd_part_parser uimage_generic_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -/************************************************** - * Init - **************************************************/ - -static int __init mtdsplit_uimage_init(void) -{ - register_mtd_parser(&uimage_generic_parser); - - return 0; -} - -module_init(mtdsplit_uimage_init); +module_mtd_part_parser(uimage_generic_parser); diff --git a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c index 84c8b97e93..319990a876 100644 --- a/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c +++ b/target/linux/generic/files/drivers/mtd/mtdsplit/mtdsplit_wrgg.c @@ -132,11 +132,4 @@ static struct mtd_part_parser mtdsplit_wrgg_parser = { .type = MTD_PARSER_TYPE_FIRMWARE, }; -static int __init mtdsplit_wrgg_init(void) -{ - register_mtd_parser(&mtdsplit_wrgg_parser); - - return 0; -} - -subsys_initcall(mtdsplit_wrgg_init); +module_mtd_part_parser(mtdsplit_wrgg_parser); diff --git a/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch index 8d308c989e..a6b1c613f3 100644 --- a/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch +++ b/target/linux/generic/pending-6.12/430-mtd-add-myloader-partition-parser.patch @@ -45,7 +45,7 @@ Signed-off-by: Adrian Schmutzler ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o --- /dev/null +++ b/drivers/mtd/parsers/myloader.c -@@ -0,0 +1,181 @@ +@@ -0,0 +1,168 @@ +/* + * Parse MyLoader-style flash partition tables and produce a Linux partition + * array to match. @@ -209,20 +209,7 @@ Signed-off-by: Adrian Schmutzler + .name = "MyLoader", +}; + -+static int __init myloader_mtd_parser_init(void) -+{ -+ register_mtd_parser(&myloader_mtd_parser); -+ -+ return 0; -+} -+ -+static void __exit myloader_mtd_parser_exit(void) -+{ -+ deregister_mtd_parser(&myloader_mtd_parser); -+} -+ -+module_init(myloader_mtd_parser_init); -+module_exit(myloader_mtd_parser_exit); ++module_mtd_part_parser(myloader_mtd_parser); + +MODULE_AUTHOR("Gabor Juhos "); +MODULE_DESCRIPTION("Parsing code for MyLoader partition tables"); diff --git a/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch b/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch index 8d308c989e..a6b1c613f3 100644 --- a/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch +++ b/target/linux/generic/pending-6.18/430-mtd-add-myloader-partition-parser.patch @@ -45,7 +45,7 @@ Signed-off-by: Adrian Schmutzler ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o --- /dev/null +++ b/drivers/mtd/parsers/myloader.c -@@ -0,0 +1,181 @@ +@@ -0,0 +1,168 @@ +/* + * Parse MyLoader-style flash partition tables and produce a Linux partition + * array to match. @@ -209,20 +209,7 @@ Signed-off-by: Adrian Schmutzler + .name = "MyLoader", +}; + -+static int __init myloader_mtd_parser_init(void) -+{ -+ register_mtd_parser(&myloader_mtd_parser); -+ -+ return 0; -+} -+ -+static void __exit myloader_mtd_parser_exit(void) -+{ -+ deregister_mtd_parser(&myloader_mtd_parser); -+} -+ -+module_init(myloader_mtd_parser_init); -+module_exit(myloader_mtd_parser_exit); ++module_mtd_part_parser(myloader_mtd_parser); + +MODULE_AUTHOR("Gabor Juhos "); +MODULE_DESCRIPTION("Parsing code for MyLoader partition tables"); From 4cc28f945f16d8810eed409d05cff7965c4cc5de Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Sat, 20 Jun 2026 10:00:30 +0800 Subject: [PATCH 118/228] kernel: reorder kernel config symbols Sort kernel configuration files alphabetically. Signed-off-by: Shiji Yang Link: https://github.com/openwrt/openwrt/pull/23886 Signed-off-by: Jonas Jelonek --- target/linux/airoha/en7523/config-6.18 | 2 +- target/linux/d1/config-6.18 | 2 +- target/linux/generic/config-6.12 | 2 +- target/linux/generic/config-6.18 | 7 ++----- target/linux/mpc85xx/config-6.18 | 2 +- target/linux/realtek/rtl931x/config-6.18 | 2 +- target/linux/sunxi/config-6.18 | 2 +- 7 files changed, 8 insertions(+), 11 deletions(-) diff --git a/target/linux/airoha/en7523/config-6.18 b/target/linux/airoha/en7523/config-6.18 index eefe1353a4..3e60f19b7c 100644 --- a/target/linux/airoha/en7523/config-6.18 +++ b/target/linux/airoha/en7523/config-6.18 @@ -221,8 +221,8 @@ CONFIG_OLD_SIGSUSPEND3=y CONFIG_OUTER_CACHE=y CONFIG_OUTER_CACHE_SYNC=y CONFIG_PADATA=y -CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PAGE_BLOCK_MAX_ORDER=10 +CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y diff --git a/target/linux/d1/config-6.18 b/target/linux/d1/config-6.18 index ab1a8b3e4d..fd6e6b0fe8 100644 --- a/target/linux/d1/config-6.18 +++ b/target/linux/d1/config-6.18 @@ -119,6 +119,7 @@ CONFIG_ERRATA_THEAD_MAE=y CONFIG_EXCLUSIVE_SYSTEM_RAM=y CONFIG_EXT4_FS=y CONFIG_EXTCON=y +CONFIG_F2FS_FS=y CONFIG_FAILOVER=y CONFIG_FHANDLE=y CONFIG_FIXED_PHY=y @@ -128,7 +129,6 @@ CONFIG_FONT_AUTOSELECT=y CONFIG_FONT_SUPPORT=y CONFIG_FPU=y CONFIG_FRAME_POINTER=y -CONFIG_F2FS_FS=y CONFIG_FS_IOMAP=y CONFIG_FS_MBCACHE=y CONFIG_FUNCTION_ALIGNMENT=0 diff --git a/target/linux/generic/config-6.12 b/target/linux/generic/config-6.12 index 3a914f94f9..25946519ad 100644 --- a/target/linux/generic/config-6.12 +++ b/target/linux/generic/config-6.12 @@ -2168,6 +2168,7 @@ CONFIG_FS_STACK=y # CONFIG_FUSION_SPI is not set CONFIG_FUTEX=y CONFIG_FUTEX_PI=y +# CONFIG_FWNODE_PCS is not set # CONFIG_FW_CFG_SYSFS is not set # CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set CONFIG_FW_LOADER=y @@ -2176,7 +2177,6 @@ CONFIG_FW_LOADER=y CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y # CONFIG_FW_UPLOAD is not set -# CONFIG_FWNODE_PCS is not set # CONFIG_FXAS21002C is not set # CONFIG_FXLS8962AF_I2C is not set # CONFIG_FXLS8962AF_SPI is not set diff --git a/target/linux/generic/config-6.18 b/target/linux/generic/config-6.18 index c56af80734..e532458b42 100644 --- a/target/linux/generic/config-6.18 +++ b/target/linux/generic/config-6.18 @@ -1636,7 +1636,6 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D is not set # CONFIG_DRM_PANEL_HIMAX_HX8279 is not set # CONFIG_DRM_PANEL_HIMAX_HX83102 is not set -# CONFIG_DRM_PANEL_HIMAX_HX83112B is not set # CONFIG_DRM_PANEL_HIMAX_HX83112A is not set # CONFIG_DRM_PANEL_HIMAX_HX83112B is not set # CONFIG_DRM_PANEL_HIMAX_HX8394 is not set @@ -1676,7 +1675,6 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_NOVATEK_NT36672E is not set # CONFIG_DRM_PANEL_NOVATEK_NT37801 is not set # CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set -# CONFIG_DRM_PANEL_NOVATEK_NT37801 is not set # CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set # CONFIG_DRM_PANEL_ORISETECH_OTA5601A is not set # CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set @@ -1706,7 +1704,6 @@ CONFIG_DQL=y # CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS427AP24 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set -# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS427AP24 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E8AA5X01_AMS561RA01 is not set # CONFIG_DRM_PANEL_SAMSUNG_SOFEF00 is not set @@ -1773,9 +1770,9 @@ CONFIG_DQL=y # CONFIG_DRM_TI_DLPC3433 is not set # CONFIG_DRM_TI_SN65DSI83 is not set # CONFIG_DRM_TI_SN65DSI86 is not set +# CONFIG_DRM_TI_TDP158 is not set # CONFIG_DRM_TI_TFP410 is not set # CONFIG_DRM_TI_TPD12S015 is not set -# CONFIG_DRM_TI_TDP158 is not set # CONFIG_DRM_TOSHIBA_TC358762 is not set # CONFIG_DRM_TOSHIBA_TC358764 is not set # CONFIG_DRM_TOSHIBA_TC358767 is not set @@ -2270,6 +2267,7 @@ CONFIG_FUTEX=y CONFIG_FUTEX_PI=y CONFIG_FUTEX_PRIVATE_HASH=y # CONFIG_FWCTL is not set +# CONFIG_FWNODE_PCS is not set # CONFIG_FW_CFG_SYSFS is not set # CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set CONFIG_FW_LOADER=y @@ -2278,7 +2276,6 @@ CONFIG_FW_LOADER=y CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y # CONFIG_FW_UPLOAD is not set -# CONFIG_FWNODE_PCS is not set # CONFIG_FXAS21002C is not set # CONFIG_FXLS8962AF_I2C is not set # CONFIG_FXLS8962AF_SPI is not set diff --git a/target/linux/mpc85xx/config-6.18 b/target/linux/mpc85xx/config-6.18 index 142d6249db..80b19b2d89 100644 --- a/target/linux/mpc85xx/config-6.18 +++ b/target/linux/mpc85xx/config-6.18 @@ -187,11 +187,11 @@ CONFIG_OF_KOBJ=y CONFIG_OF_MDIO=y CONFIG_OLD_SIGACTION=y CONFIG_OLD_SIGSUSPEND=y -CONFIG_PAGE_BLOCK_MAX_ORDER=10 # CONFIG_P1010_RDB is not set # CONFIG_P1022_DS is not set # CONFIG_P1022_RDK is not set # CONFIG_P1023_RDB is not set +CONFIG_PAGE_BLOCK_MAX_ORDER=10 CONFIG_PAGE_OFFSET=0xc0000000 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y diff --git a/target/linux/realtek/rtl931x/config-6.18 b/target/linux/realtek/rtl931x/config-6.18 index cdc6233afa..5f97d95869 100644 --- a/target/linux/realtek/rtl931x/config-6.18 +++ b/target/linux/realtek/rtl931x/config-6.18 @@ -1,10 +1,10 @@ +CONFIG_AQUANTIA_PHY=y CONFIG_ARCH_32BIT_OFF_T=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_KEEP_MEMBLOCK=y CONFIG_ARCH_MMAP_RND_BITS_MAX=15 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_AQUANTIA_PHY=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 diff --git a/target/linux/sunxi/config-6.18 b/target/linux/sunxi/config-6.18 index c5d8692aab..346faaa8a1 100644 --- a/target/linux/sunxi/config-6.18 +++ b/target/linux/sunxi/config-6.18 @@ -459,6 +459,7 @@ CONFIG_SND_SIMPLE_CARD=y CONFIG_SND_SIMPLE_CARD_UTILS=y CONFIG_SND_SOC=y CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SUN20I_D1_CODEC_ANALOG is not set # CONFIG_SND_SUN4I_I2S is not set # CONFIG_SND_SUN4I_SPDIF is not set # CONFIG_SND_SUN50I_DMIC is not set @@ -476,7 +477,6 @@ CONFIG_SPI_SUN6I=y CONFIG_SRCU=y CONFIG_STMMAC_ETH=y CONFIG_STMMAC_PLATFORM=y -# CONFIG_SND_SUN20I_D1_CODEC_ANALOG is not set # CONFIG_SUN20I_GPADC is not set # CONFIG_SUN20I_PPU is not set CONFIG_SUN4I_A10_CCU=y From 8eb0fd0ed5a435df515b74ff71d2e3e54aefc742 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Fri, 19 Jun 2026 21:50:12 +0800 Subject: [PATCH 119/228] kernel: bump 6.12 to 6.12.94 Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.12.94 New kconfig symbols: - ARM64_ERRATUM_4118414: enabled on ARM Cortex-A76 and newer targets. - ARM64_ERRATUM_4193714: enabled on ARM C1-Pro and newer targets. All patches are automatically refreshed. Signed-off-by: Shiji Yang Link: https://github.com/openwrt/openwrt/pull/23886 Signed-off-by: Jonas Jelonek --- target/linux/armsr/armv8/config-6.12 | 2 ++ .../ath79/patches-6.12/900-unaligned_access_hacks.patch | 4 ++-- target/linux/bcm27xx/bcm2712/config-6.12 | 1 + ...22-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch | 4 ++-- .../patches-6.12/950-0344-sdhci-Add-SD-Express-hook.patch | 2 +- ...ivers-mmc-add-debugfs-entries-for-SD-extension-reg.patch | 2 +- ...c-sdhci-extend-maximum-ADMA-transfer-length-to-4Mi.patch | 2 +- ...c-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch | 4 ++-- ...0-0502-Bluetooth-hci_sync-Fix-crash-on-NULL-parent.patch | 2 +- ...m-vc4-Make-v3d-paths-unavailable-on-any-generation.patch | 2 +- .../patches-6.12/950-0777-drm-v3d-Remove-v3d-cpu_job.patch | 2 +- ...1-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch | 4 ++-- ...20-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch | 2 +- ...-net-phy-support-active-high-property-for-PHY-LEDs.patch | 2 +- target/linux/generic/config-6.12 | 2 ++ .../hack-6.12/780-usb-net-MeigLink_modem_support.patch | 6 +++--- target/linux/generic/hack-6.12/901-debloat_sock_diag.patch | 2 +- target/linux/generic/hack-6.12/902-debloat_proc.patch | 2 +- target/linux/generic/kernel-6.12 | 4 ++-- .../generic/pending-6.12/103-kbuild-export-SUBARCH.patch | 2 +- ...t-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch | 2 +- .../703-phy-add-detach-callback-to-struct-phy_driver.patch | 2 +- 22 files changed, 31 insertions(+), 26 deletions(-) diff --git a/target/linux/armsr/armv8/config-6.12 b/target/linux/armsr/armv8/config-6.12 index 6463660b5a..a1176c0585 100644 --- a/target/linux/armsr/armv8/config-6.12 +++ b/target/linux/armsr/armv8/config-6.12 @@ -83,6 +83,8 @@ CONFIG_ARM64_ERRATUM_2441007=y CONFIG_ARM64_ERRATUM_2441009=y CONFIG_ARM64_ERRATUM_2457168=y CONFIG_ARM64_ERRATUM_2658417=y +CONFIG_ARM64_ERRATUM_4118414=y +CONFIG_ARM64_ERRATUM_4193714=y CONFIG_ARM64_ERRATUM_819472=y CONFIG_ARM64_ERRATUM_824069=y CONFIG_ARM64_ERRATUM_826319=y diff --git a/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch b/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch index e26aaebab3..71ecaa9ce1 100644 --- a/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch +++ b/target/linux/ath79/patches-6.12/900-unaligned_access_hacks.patch @@ -259,7 +259,7 @@ SVN-Revision: 35130 #include #include #include -@@ -915,10 +916,10 @@ static void tcp_v6_send_response(const s +@@ -912,10 +913,10 @@ static void tcp_v6_send_response(const s topt = (__be32 *)(t1 + 1); if (tsecr) { @@ -701,7 +701,7 @@ SVN-Revision: 35130 +#include struct net; - + extern struct net init_net; --- a/include/uapi/linux/in.h +++ b/include/uapi/linux/in.h @@ -93,7 +93,7 @@ enum { diff --git a/target/linux/bcm27xx/bcm2712/config-6.12 b/target/linux/bcm27xx/bcm2712/config-6.12 index eaf00f4bf6..47ceac7024 100644 --- a/target/linux/bcm27xx/bcm2712/config-6.12 +++ b/target/linux/bcm27xx/bcm2712/config-6.12 @@ -30,6 +30,7 @@ CONFIG_ARM64_ERRATUM_1165522=y CONFIG_ARM64_ERRATUM_1286807=y CONFIG_ARM64_ERRATUM_1463225=y CONFIG_ARM64_ERRATUM_3194386=y +CONFIG_ARM64_ERRATUM_4118414=y CONFIG_ARM64_HW_AFDBM=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y CONFIG_ARM64_PA_BITS=48 diff --git a/target/linux/bcm27xx/patches-6.12/950-0322-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch b/target/linux/bcm27xx/patches-6.12/950-0322-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch index 4e0895dc45..b50b49f2a4 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0322-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0322-Bluetooth-hci_sync-Add-fallback-bd-address-prop.patch @@ -20,7 +20,7 @@ Signed-off-by: Phil Elwell --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c -@@ -4942,6 +4942,7 @@ static const struct { +@@ -4961,6 +4961,7 @@ static const struct { */ static int hci_dev_setup_sync(struct hci_dev *hdev) { @@ -28,7 +28,7 @@ Signed-off-by: Phil Elwell int ret = 0; bool invalid_bdaddr; size_t i; -@@ -4970,7 +4971,8 @@ static int hci_dev_setup_sync(struct hci +@@ -4989,7 +4990,8 @@ static int hci_dev_setup_sync(struct hci test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); if (!ret) { if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks) && diff --git a/target/linux/bcm27xx/patches-6.12/950-0344-sdhci-Add-SD-Express-hook.patch b/target/linux/bcm27xx/patches-6.12/950-0344-sdhci-Add-SD-Express-hook.patch index 2b695742ed..64c0bfb700 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0344-sdhci-Add-SD-Express-hook.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0344-sdhci-Add-SD-Express-hook.patch @@ -51,7 +51,7 @@ sdhci: remove PYA0_INTR_BUG quirk. Add quirks to disable some of the higher SDR }; /*****************************************************************************\ -@@ -4572,6 +4582,15 @@ int sdhci_setup_host(struct sdhci_host * +@@ -4573,6 +4583,15 @@ int sdhci_setup_host(struct sdhci_host * !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) mmc->caps |= MMC_CAP_UHS_DDR50; diff --git a/target/linux/bcm27xx/patches-6.12/950-0434-drivers-mmc-add-debugfs-entries-for-SD-extension-reg.patch b/target/linux/bcm27xx/patches-6.12/950-0434-drivers-mmc-add-debugfs-entries-for-SD-extension-reg.patch index eafdd01140..1cc5a26d0a 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0434-drivers-mmc-add-debugfs-entries-for-SD-extension-reg.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0434-drivers-mmc-add-debugfs-entries-for-SD-extension-reg.patch @@ -13,7 +13,7 @@ Signed-off-by: Jonathan Bell --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c -@@ -1915,8 +1915,8 @@ static int mmc_init_card(struct mmc_host +@@ -1917,8 +1917,8 @@ static int mmc_init_card(struct mmc_host host->cqe_enabled = true; if (card->ext_csd.cmdq_en) { diff --git a/target/linux/bcm27xx/patches-6.12/950-0437-mmc-sdhci-extend-maximum-ADMA-transfer-length-to-4Mi.patch b/target/linux/bcm27xx/patches-6.12/950-0437-mmc-sdhci-extend-maximum-ADMA-transfer-length-to-4Mi.patch index 39c26127fb..5c6296a2b5 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0437-mmc-sdhci-extend-maximum-ADMA-transfer-length-to-4Mi.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0437-mmc-sdhci-extend-maximum-ADMA-transfer-length-to-4Mi.patch @@ -23,7 +23,7 @@ Signed-off-by: Jonathan Bell BUG_ON(data->blksz > host->mmc->max_blk_size); BUG_ON(data->blocks > 65535); -@@ -4716,11 +4716,16 @@ int sdhci_setup_host(struct sdhci_host * +@@ -4717,11 +4717,16 @@ int sdhci_setup_host(struct sdhci_host * spin_lock_init(&host->lock); /* diff --git a/target/linux/bcm27xx/patches-6.12/950-0440-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch b/target/linux/bcm27xx/patches-6.12/950-0440-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch index df94ea0ca5..995105eff6 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0440-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0440-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch @@ -85,7 +85,7 @@ Signed-off-by: Jonathan Bell void mmc_blk_mq_recovery(struct mmc_queue *mq) --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c -@@ -1657,6 +1657,7 @@ static int mmc_init_card(struct mmc_host +@@ -1659,6 +1659,7 @@ static int mmc_init_card(struct mmc_host card->ocr = ocr; card->type = MMC_TYPE_MMC; card->rca = 1; @@ -93,7 +93,7 @@ Signed-off-by: Jonathan Bell memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); } -@@ -1922,6 +1923,7 @@ static int mmc_init_card(struct mmc_host +@@ -1924,6 +1925,7 @@ static int mmc_init_card(struct mmc_host pr_info("%s: Host Software Queue enabled\n", mmc_hostname(host)); } diff --git a/target/linux/bcm27xx/patches-6.12/950-0502-Bluetooth-hci_sync-Fix-crash-on-NULL-parent.patch b/target/linux/bcm27xx/patches-6.12/950-0502-Bluetooth-hci_sync-Fix-crash-on-NULL-parent.patch index ee48969572..98c428e7a8 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0502-Bluetooth-hci_sync-Fix-crash-on-NULL-parent.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0502-Bluetooth-hci_sync-Fix-crash-on-NULL-parent.patch @@ -15,7 +15,7 @@ Signed-off-by: Phil Elwell --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c -@@ -4942,7 +4942,8 @@ static const struct { +@@ -4961,7 +4961,8 @@ static const struct { */ static int hci_dev_setup_sync(struct hci_dev *hdev) { diff --git a/target/linux/bcm27xx/patches-6.12/950-0588-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch b/target/linux/bcm27xx/patches-6.12/950-0588-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch index 1c5725d7aa..5b43bbf224 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0588-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0588-drm-vc4-Make-v3d-paths-unavailable-on-any-generation.patch @@ -569,7 +569,7 @@ Signed-off-by: Dave Stevenson for (i = 0; i < exec->shader_state_count; i++) { --- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c +++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c -@@ -786,7 +786,7 @@ vc4_validate_shader(struct drm_gem_dma_o +@@ -787,7 +787,7 @@ vc4_validate_shader(struct drm_gem_dma_o struct vc4_validated_shader_info *validated_shader = NULL; struct vc4_shader_validation_state validation_state; diff --git a/target/linux/bcm27xx/patches-6.12/950-0777-drm-v3d-Remove-v3d-cpu_job.patch b/target/linux/bcm27xx/patches-6.12/950-0777-drm-v3d-Remove-v3d-cpu_job.patch index 620f208543..436740ffbc 100644 --- a/target/linux/bcm27xx/patches-6.12/950-0777-drm-v3d-Remove-v3d-cpu_job.patch +++ b/target/linux/bcm27xx/patches-6.12/950-0777-drm-v3d-Remove-v3d-cpu_job.patch @@ -35,7 +35,7 @@ Link: https://patchwork.freedesktop.org/patch/msgid/20250113154741.67520-2-mcana --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c -@@ -663,8 +663,6 @@ v3d_cpu_job_run(struct drm_sched_job *sc +@@ -664,8 +664,6 @@ v3d_cpu_job_run(struct drm_sched_job *sc struct v3d_cpu_job *job = to_cpu_job(sched_job); struct v3d_dev *v3d = job->base.v3d; diff --git a/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch index 846d9df36d..c0ab7ac5e2 100644 --- a/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch +++ b/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch @@ -16,7 +16,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c -@@ -6237,19 +6237,26 @@ static const struct phylink_pcs_ops mvpp +@@ -6256,19 +6256,26 @@ static const struct phylink_pcs_ops mvpp .pcs_config = mvpp2_xlg_pcs_config, }; @@ -51,7 +51,7 @@ Signed-off-by: Jakub Kicinski } static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs, -@@ -6356,7 +6363,7 @@ static void mvpp2_gmac_pcs_an_restart(st +@@ -6375,7 +6382,7 @@ static void mvpp2_gmac_pcs_an_restart(st } static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = { diff --git a/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch b/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch index f54f471ab6..d09e95681e 100644 --- a/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch +++ b/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch @@ -458,7 +458,7 @@ Signed-off-by: Jakub Kicinski { } --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c -@@ -5835,7 +5835,7 @@ MODULE_DESCRIPTION("Micrel PHY driver"); +@@ -5836,7 +5836,7 @@ MODULE_DESCRIPTION("Micrel PHY driver"); MODULE_AUTHOR("David J. Choi"); MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch b/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch index 95e8638c39..d009115686 100644 --- a/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch +++ b/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch @@ -19,7 +19,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -3382,11 +3382,17 @@ static int of_phy_led(struct phy_device +@@ -3385,11 +3385,17 @@ static int of_phy_led(struct phy_device if (index > U8_MAX) return -EINVAL; diff --git a/target/linux/generic/config-6.12 b/target/linux/generic/config-6.12 index 25946519ad..e9e782af41 100644 --- a/target/linux/generic/config-6.12 +++ b/target/linux/generic/config-6.12 @@ -363,6 +363,8 @@ CONFIG_ARM64_CNP=y # CONFIG_ARM64_ERRATUM_2966298 is not set # CONFIG_ARM64_ERRATUM_3117295 is not set # CONFIG_ARM64_ERRATUM_3194386 is not set +# CONFIG_ARM64_ERRATUM_4118414 is not set +# CONFIG_ARM64_ERRATUM_4193714 is not set # CONFIG_ARM64_ERRATUM_819472 is not set # CONFIG_ARM64_ERRATUM_824069 is not set # CONFIG_ARM64_ERRATUM_826319 is not set diff --git a/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch index eff038fbd0..feeb329ca1 100644 --- a/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-6.12/780-usb-net-MeigLink_modem_support.patch @@ -32,7 +32,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c -@@ -247,6 +247,11 @@ static void option_instat_callback(struc +@@ -248,6 +248,11 @@ static void option_instat_callback(struc #define UBLOX_PRODUCT_R410M 0x90b2 /* These Yuga products use Qualcomm's vendor ID */ #define YUGA_PRODUCT_CLM920_NC5 0x9625 @@ -44,7 +44,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support #define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ -@@ -1156,6 +1161,11 @@ static const struct usb_device_id option +@@ -1159,6 +1164,11 @@ static const struct usb_device_id option { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */ .driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) }, @@ -56,7 +56,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support /* Quectel products using Qualcomm vendor ID */ { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)}, { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20), -@@ -1197,6 +1207,11 @@ static const struct usb_device_id option +@@ -1200,6 +1210,11 @@ static const struct usb_device_id option .driver_info = ZLP }, { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), .driver_info = RSVD(4) }, diff --git a/target/linux/generic/hack-6.12/901-debloat_sock_diag.patch b/target/linux/generic/hack-6.12/901-debloat_sock_diag.patch index 17a22d0528..0091ec29bb 100644 --- a/target/linux/generic/hack-6.12/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-6.12/901-debloat_sock_diag.patch @@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, u32)); INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, -@@ -2342,9 +2359,11 @@ static void __sk_free(struct sock *sk) +@@ -2347,9 +2364,11 @@ static void __sk_free(struct sock *sk) if (likely(sk->sk_net_refcnt)) sock_inuse_add(sock_net(sk), -1); diff --git a/target/linux/generic/hack-6.12/902-debloat_proc.patch b/target/linux/generic/hack-6.12/902-debloat_proc.patch index fe45d47ec5..7beda5de63 100644 --- a/target/linux/generic/hack-6.12/902-debloat_proc.patch +++ b/target/linux/generic/hack-6.12/902-debloat_proc.patch @@ -331,7 +331,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -4285,6 +4285,8 @@ static __net_initdata struct pernet_oper +@@ -4294,6 +4294,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { diff --git a/target/linux/generic/kernel-6.12 b/target/linux/generic/kernel-6.12 index 2c776bd716..424db9bb4e 100644 --- a/target/linux/generic/kernel-6.12 +++ b/target/linux/generic/kernel-6.12 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.12 = .93 -LINUX_KERNEL_HASH-6.12.93 = 492648a87c0b69c5ac7f43be64792b9000e3439550d4e82e4a14710c49094fa3 +LINUX_VERSION-6.12 = .94 +LINUX_KERNEL_HASH-6.12.94 = e998a232b9418db3301cb58468e291a4f41d6ab8306029b30d991f56251dc8d2 diff --git a/target/linux/generic/pending-6.12/103-kbuild-export-SUBARCH.patch b/target/linux/generic/pending-6.12/103-kbuild-export-SUBARCH.patch index f11976b9e3..a47479b7ca 100644 --- a/target/linux/generic/pending-6.12/103-kbuild-export-SUBARCH.patch +++ b/target/linux/generic/pending-6.12/103-kbuild-export-SUBARCH.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -593,7 +593,7 @@ export RUSTC_BOOTSTRAP := 1 +@@ -594,7 +594,7 @@ export RUSTC_BOOTSTRAP := 1 # Allows finding `.clippy.toml` in out-of-srctree builds. export CLIPPY_CONF_DIR := $(srctree) diff --git a/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch b/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch index 21f08fac78..800613b392 100644 --- a/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch +++ b/target/linux/generic/pending-6.12/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch @@ -96,7 +96,7 @@ Signed-off-by: Felix Fietkau } --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -2557,7 +2557,7 @@ void sk_setup_caps(struct sock *sk, stru +@@ -2562,7 +2562,7 @@ void sk_setup_caps(struct sock *sk, stru icsk->icsk_ack.dst_quick_ack = dst_metric(dst, RTAX_QUICKACK); } if (sk->sk_route_caps & NETIF_F_GSO) diff --git a/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch index 474470b806..5c8dbcc3fe 100644 --- a/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -2035,6 +2035,9 @@ void phy_detach(struct phy_device *phyde +@@ -2038,6 +2038,9 @@ void phy_detach(struct phy_device *phyde phydev->devlink = NULL; } From c430788f5dadac8c397715d121790627b1e595a9 Mon Sep 17 00:00:00 2001 From: John Audia Date: Fri, 19 Jun 2026 15:19:24 -0400 Subject: [PATCH 120/228] kernel: bump 6.18 to 6.18.36 Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.18.36 Removed upstreamed: airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch[1] airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch[2] All other patches automatically rebased via update_kernel.sh A new option was introduced with this release[3]. Updated configs on affected targets: armsr/armv8 and rockchip/armv8. 1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.18.36&id=6f829e2c17a53a35321268339cd252aff6d6d723 2. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.18.36&id=01f7d4b504580664d36faea5671cde5e3f0d8a5b 3. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/diff/arch/arm64/Kconfig?id=v6.18.36&id2=v6.18.35 Build system: x86/64 Build-tested: x86/64-glibc Run-tested: x86/64-glibc Signed-off-by: John Audia Link: https://github.com/openwrt/openwrt/pull/23887 Signed-off-by: Jonas Jelonek --- ...issing-stats-to-ethtool_eth_mac_stat.patch | 2 +- ...airoha-Add-get_link-ethtool-callback.patch | 2 +- ...t-default-ppe-cpu-port-in-airoha_dev.patch | 4 +- ...-airoha-implement-get_link_ksettings.patch | 2 +- ...-__field_prep-for-non-constant-masks.patch | 6 +-- ...flow-control-source-port-mapping-dep.patch | 2 +- ...GDM-forward-port-configuration-in-nd.patch | 12 ++--- ...t-QDMA-block-according-LAN-WAN-confi.patch | 16 +++--- ...-PPE-default-cput-port-in-airoha_ppe.patch | 6 +-- ...-offloading-until-all-net_devices-ar.patch | 2 +- ...on-net_device-pointer-in-airoha_dev_.patch | 8 +-- ...on-net_device-pointer-in-HTB-callbac.patch | 12 ++--- ...on-net_device-pointer-in-ETS-callbac.patch | 12 ++--- ...ypo-in-airoha_set_gdm2_loopback-rout.patch | 4 +- ...PE-cpu-port-configuration-for-GDM2-l.patch | 6 +-- ...e-get_src_port_id-callback-in-get_sp.patch | 10 ++-- ...roha-Introduce-airoha_gdm_dev-struct.patch | 54 +++++++++---------- ...airoha_qdma-pointer-in-airoha_gdm_de.patch | 48 ++++++++--------- ...on-airoha_gdm_dev-pointer-in-airoha_.patch | 2 +- ...qos_sq_bmap-in-airoha_gdm_dev-struct.patch | 14 ++--- ...cpu-fwd-_tx_packets-in-airoha_gdm_de.patch | 2 +- ...e-airoha_set_gdm2_loopback-in-airoha.patch | 4 +- ...se-after-free-in-metadata-dst-teardo.patch | 37 ------------- ...t-extack-error-to-the-user-if-airoha.patch | 2 +- ...ULL-check-for-of_reserved_mem_lookup.patch | 41 -------------- ...-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch | 2 +- target/linux/armsr/armv8/config-6.18 | 1 + ...esence-via-I2C-when-no-MOD_DEF0-GPIO.patch | 4 +- ...upport-for-5Gbit-Link-Speeds-and-EEE.patch | 2 +- ...Add-support-for-the-RTL8157-hardware.patch | 4 +- target/linux/generic/config-6.18 | 1 + .../780-usb-net-MeigLink_modem_support.patch | 6 +-- .../hack-6.18/901-debloat_sock_diag.patch | 2 +- .../generic/hack-6.18/902-debloat_proc.patch | 2 +- target/linux/generic/kernel-6.18 | 4 +- .../103-kbuild-export-SUBARCH.patch | 2 +- ..._F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch | 2 +- ...detach-callback-to-struct-phy_driver.patch | 2 +- .../901-arm-add-cmdline-override.patch | 2 +- ...ze-i2c_block_size-at-adapter-configu.patch | 4 +- ...14-net-phy-sfp-add-support-for-SMBus.patch | 2 +- target/linux/rockchip/armv8/config-6.18 | 1 + 42 files changed, 139 insertions(+), 214 deletions(-) delete mode 100644 target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch delete mode 100644 target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch diff --git a/target/linux/airoha/patches-6.18/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch b/target/linux/airoha/patches-6.18/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch index 010b4fe6a4..0e579c4923 100644 --- a/target/linux/airoha/patches-6.18/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch +++ b/target/linux/airoha/patches-6.18/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2160,8 +2160,12 @@ static void airoha_ethtool_get_mac_stats +@@ -2163,8 +2163,12 @@ static void airoha_ethtool_get_mac_stats airoha_update_hw_stats(port); do { start = u64_stats_fetch_begin(&port->stats.syncp); diff --git a/target/linux/airoha/patches-6.18/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch b/target/linux/airoha/patches-6.18/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch index 6ceae92cd2..f1f81fa08c 100644 --- a/target/linux/airoha/patches-6.18/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch +++ b/target/linux/airoha/patches-6.18/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch @@ -15,7 +15,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2908,6 +2908,7 @@ static const struct ethtool_ops airoha_e +@@ -2911,6 +2911,7 @@ static const struct ethtool_ops airoha_e .get_drvinfo = airoha_ethtool_get_drvinfo, .get_eth_mac_stats = airoha_ethtool_get_mac_stats, .get_rmon_stats = airoha_ethtool_get_rmon_stats, diff --git a/target/linux/airoha/patches-6.18/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch b/target/linux/airoha/patches-6.18/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch index 477d6e2d9d..e9a82de897 100644 --- a/target/linux/airoha/patches-6.18/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch +++ b/target/linux/airoha/patches-6.18/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch @@ -47,7 +47,7 @@ Signed-off-by: Paolo Abeni /* enable 1:N vlan action, init vlan table */ airoha_fe_set(eth, REG_MC_VLAN_EN, MC_VLAN_EN_MASK); -@@ -1853,8 +1834,10 @@ static int airhoha_set_gdm2_loopback(str +@@ -1856,8 +1837,10 @@ static int airhoha_set_gdm2_loopback(str static int airoha_dev_init(struct net_device *dev) { struct airoha_gdm_port *port = netdev_priv(dev); @@ -60,7 +60,7 @@ Signed-off-by: Paolo Abeni airoha_set_macaddr(port, dev->dev_addr); -@@ -1872,16 +1855,27 @@ static int airoha_dev_init(struct net_de +@@ -1875,16 +1858,27 @@ static int airoha_dev_init(struct net_de fallthrough; case AIROHA_GDM2_IDX: if (airoha_ppe_is_enabled(eth, 1)) { diff --git a/target/linux/airoha/patches-6.18/120-v7.0-net-airoha-implement-get_link_ksettings.patch b/target/linux/airoha/patches-6.18/120-v7.0-net-airoha-implement-get_link_ksettings.patch index 17e57d7c97..a15c17057e 100644 --- a/target/linux/airoha/patches-6.18/120-v7.0-net-airoha-implement-get_link_ksettings.patch +++ b/target/linux/airoha/patches-6.18/120-v7.0-net-airoha-implement-get_link_ksettings.patch @@ -16,7 +16,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2902,6 +2902,7 @@ static const struct ethtool_ops airoha_e +@@ -2905,6 +2905,7 @@ static const struct ethtool_ops airoha_e .get_drvinfo = airoha_ethtool_get_drvinfo, .get_eth_mac_stats = airoha_ethtool_get_mac_stats, .get_rmon_stats = airoha_ethtool_get_rmon_stats, diff --git a/target/linux/airoha/patches-6.18/125-v7.1-net-airoha-Rely-__field_prep-for-non-constant-masks.patch b/target/linux/airoha/patches-6.18/125-v7.1-net-airoha-Rely-__field_prep-for-non-constant-masks.patch index 91260a9794..ac7e6ebdb1 100644 --- a/target/linux/airoha/patches-6.18/125-v7.1-net-airoha-Rely-__field_prep-for-non-constant-masks.patch +++ b/target/linux/airoha/patches-6.18/125-v7.1-net-airoha-Rely-__field_prep-for-non-constant-masks.patch @@ -15,7 +15,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1821,7 +1821,7 @@ static int airhoha_set_gdm2_loopback(str +@@ -1824,7 +1824,7 @@ static int airhoha_set_gdm2_loopback(str airoha_fe_rmw(eth, REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)), SP_CPORT_MASK(val), @@ -24,7 +24,7 @@ Signed-off-by: Jakub Kicinski if (port->id != AIROHA_GDM3_IDX && airoha_is_7581(eth)) airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, -@@ -1875,7 +1875,7 @@ static int airoha_dev_init(struct net_de +@@ -1878,7 +1878,7 @@ static int airoha_dev_init(struct net_de ppe_id = pse_port == FE_PSE_PORT_PPE2 ? 1 : 0; airoha_fe_rmw(eth, REG_PPE_DFT_CPORT0(ppe_id), DFT_CPORT_MASK(port->id), @@ -33,7 +33,7 @@ Signed-off-by: Jakub Kicinski return 0; } -@@ -2235,7 +2235,7 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2238,7 +2238,7 @@ static int airoha_qdma_set_chan_tx_sched airoha_qdma_rmw(port->qdma, REG_CHAN_QOS_MODE(channel >> 3), CHAN_QOS_MODE_MASK(channel), diff --git a/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch b/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch index 6be83a301b..8a4479bc2c 100644 --- a/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch +++ b/target/linux/airoha/patches-6.18/126-v7.1-net-airoha-Make-flow-control-source-port-mapping-dep.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1823,10 +1823,12 @@ static int airhoha_set_gdm2_loopback(str +@@ -1826,10 +1826,12 @@ static int airhoha_set_gdm2_loopback(str SP_CPORT_MASK(val), __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2)); diff --git a/target/linux/airoha/patches-6.18/127-v7.1-net-airoha-Move-GDM-forward-port-configuration-in-nd.patch b/target/linux/airoha/patches-6.18/127-v7.1-net-airoha-Move-GDM-forward-port-configuration-in-nd.patch index 3b49e76b22..e44102acde 100644 --- a/target/linux/airoha/patches-6.18/127-v7.1-net-airoha-Move-GDM-forward-port-configuration-in-nd.patch +++ b/target/linux/airoha/patches-6.18/127-v7.1-net-airoha-Move-GDM-forward-port-configuration-in-nd.patch @@ -18,7 +18,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1708,6 +1708,7 @@ static int airoha_dev_open(struct net_de +@@ -1711,6 +1711,7 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + dev->mtu + ETH_FCS_LEN; struct airoha_gdm_port *port = netdev_priv(dev); struct airoha_qdma *qdma = port->qdma; @@ -26,7 +26,7 @@ Signed-off-by: Paolo Abeni netif_tx_start_all_queues(dev); err = airoha_set_vip_for_gdm_port(port, true); -@@ -1731,6 +1732,14 @@ static int airoha_dev_open(struct net_de +@@ -1734,6 +1735,14 @@ static int airoha_dev_open(struct net_de GLOBAL_CFG_RX_DMA_EN_MASK); atomic_inc(&qdma->users); @@ -41,7 +41,7 @@ Signed-off-by: Paolo Abeni return 0; } -@@ -1745,6 +1754,9 @@ static int airoha_dev_stop(struct net_de +@@ -1748,6 +1757,9 @@ static int airoha_dev_stop(struct net_de for (i = 0; i < dev->num_tx_queues; i++) netdev_tx_reset_subqueue(dev, i); @@ -51,7 +51,7 @@ Signed-off-by: Paolo Abeni if (atomic_dec_and_test(&qdma->users)) { airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK | -@@ -1838,7 +1850,7 @@ static int airoha_dev_init(struct net_de +@@ -1841,7 +1853,7 @@ static int airoha_dev_init(struct net_de struct airoha_gdm_port *port = netdev_priv(dev); struct airoha_qdma *qdma = port->qdma; struct airoha_eth *eth = qdma->eth; @@ -60,7 +60,7 @@ Signed-off-by: Paolo Abeni u8 ppe_id; airoha_set_macaddr(port, dev->dev_addr); -@@ -1859,7 +1871,7 @@ static int airoha_dev_init(struct net_de +@@ -1862,7 +1874,7 @@ static int airoha_dev_init(struct net_de if (airoha_ppe_is_enabled(eth, 1)) { /* For PPE2 always use secondary cpu port. */ fe_cpu_port = FE_PSE_PORT_CDM2; @@ -69,7 +69,7 @@ Signed-off-by: Paolo Abeni break; } fallthrough; -@@ -1868,13 +1880,11 @@ static int airoha_dev_init(struct net_de +@@ -1871,13 +1883,11 @@ static int airoha_dev_init(struct net_de /* For PPE1 select cpu port according to the running QDMA. */ fe_cpu_port = qdma_id ? FE_PSE_PORT_CDM2 : FE_PSE_PORT_CDM1; diff --git a/target/linux/airoha/patches-6.18/129-v7.1-net-airoha-select-QDMA-block-according-LAN-WAN-confi.patch b/target/linux/airoha/patches-6.18/129-v7.1-net-airoha-select-QDMA-block-according-LAN-WAN-confi.patch index f8e489d9b7..2119016a60 100644 --- a/target/linux/airoha/patches-6.18/129-v7.1-net-airoha-select-QDMA-block-according-LAN-WAN-confi.patch +++ b/target/linux/airoha/patches-6.18/129-v7.1-net-airoha-select-QDMA-block-according-LAN-WAN-confi.patch @@ -39,7 +39,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1848,11 +1848,13 @@ static int airhoha_set_gdm2_loopback(str +@@ -1851,11 +1851,13 @@ static int airhoha_set_gdm2_loopback(str static int airoha_dev_init(struct net_device *dev) { struct airoha_gdm_port *port = netdev_priv(dev); @@ -55,7 +55,7 @@ Signed-off-by: Paolo Abeni airoha_set_macaddr(port, dev->dev_addr); switch (port->id) { -@@ -1876,7 +1878,7 @@ static int airoha_dev_init(struct net_de +@@ -1879,7 +1881,7 @@ static int airoha_dev_init(struct net_de } fallthrough; default: { @@ -64,7 +64,7 @@ Signed-off-by: Paolo Abeni /* For PPE1 select cpu port according to the running QDMA. */ fe_cpu_port = qdma_id ? FE_PSE_PORT_CDM2 : FE_PSE_PORT_CDM1; -@@ -2963,11 +2965,10 @@ bool airoha_is_valid_gdm_port(struct air +@@ -2966,11 +2968,10 @@ bool airoha_is_valid_gdm_port(struct air } static int airoha_alloc_gdm_port(struct airoha_eth *eth, @@ -77,7 +77,7 @@ Signed-off-by: Paolo Abeni struct net_device *dev; int err, p; u32 id; -@@ -2998,7 +2999,6 @@ static int airoha_alloc_gdm_port(struct +@@ -3001,7 +3002,6 @@ static int airoha_alloc_gdm_port(struct return -ENOMEM; } @@ -85,7 +85,7 @@ Signed-off-by: Paolo Abeni dev->netdev_ops = &airoha_netdev_ops; dev->ethtool_ops = &airoha_ethtool_ops; dev->max_mtu = AIROHA_MAX_MTU; -@@ -3010,7 +3010,6 @@ static int airoha_alloc_gdm_port(struct +@@ -3013,7 +3013,6 @@ static int airoha_alloc_gdm_port(struct dev->features |= dev->hw_features; dev->vlan_features = dev->hw_features; dev->dev.of_node = np; @@ -93,7 +93,7 @@ Signed-off-by: Paolo Abeni SET_NETDEV_DEV(dev, eth->dev); /* reserve hw queues for HTB offloading */ -@@ -3031,7 +3030,7 @@ static int airoha_alloc_gdm_port(struct +@@ -3034,7 +3033,7 @@ static int airoha_alloc_gdm_port(struct port = netdev_priv(dev); u64_stats_init(&port->stats.syncp); spin_lock_init(&port->stats.lock); @@ -102,7 +102,7 @@ Signed-off-by: Paolo Abeni port->dev = dev; port->id = id; /* XXX: Read nbq from DTS */ -@@ -3133,7 +3132,6 @@ static int airoha_probe(struct platform_ +@@ -3136,7 +3135,6 @@ static int airoha_probe(struct platform_ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) airoha_qdma_start_napi(ð->qdma[i]); @@ -110,7 +110,7 @@ Signed-off-by: Paolo Abeni for_each_child_of_node(pdev->dev.of_node, np) { if (!of_device_is_compatible(np, "airoha,eth-mac")) continue; -@@ -3141,7 +3139,7 @@ static int airoha_probe(struct platform_ +@@ -3144,7 +3142,7 @@ static int airoha_probe(struct platform_ if (!of_device_is_available(np)) continue; diff --git a/target/linux/airoha/patches-6.18/132-v7.1-net-airoha-Reset-PPE-default-cput-port-in-airoha_ppe.patch b/target/linux/airoha/patches-6.18/132-v7.1-net-airoha-Reset-PPE-default-cput-port-in-airoha_ppe.patch index 7262c7f3c7..6b28275fb4 100644 --- a/target/linux/airoha/patches-6.18/132-v7.1-net-airoha-Reset-PPE-default-cput-port-in-airoha_ppe.patch +++ b/target/linux/airoha/patches-6.18/132-v7.1-net-airoha-Reset-PPE-default-cput-port-in-airoha_ppe.patch @@ -32,7 +32,7 @@ Signed-off-by: Lorenzo Bianconi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1849,8 +1849,7 @@ static int airoha_dev_init(struct net_de +@@ -1852,8 +1852,7 @@ static int airoha_dev_init(struct net_de { struct airoha_gdm_port *port = netdev_priv(dev); struct airoha_eth *eth = port->eth; @@ -42,7 +42,7 @@ Signed-off-by: Lorenzo Bianconi /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; -@@ -1868,28 +1867,13 @@ static int airoha_dev_init(struct net_de +@@ -1871,28 +1870,13 @@ static int airoha_dev_init(struct net_de if (err) return err; } @@ -75,7 +75,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -1992,7 +1976,7 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -1995,7 +1979,7 @@ static u32 airoha_get_dsa_tag(struct sk_ #endif } diff --git a/target/linux/airoha/patches-6.18/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch b/target/linux/airoha/patches-6.18/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch index b0112a08ba..cc7ae728da 100644 --- a/target/linux/airoha/patches-6.18/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch +++ b/target/linux/airoha/patches-6.18/134-v7.1-net-airoha-Delay-offloading-until-all-net_devices-ar.patch @@ -26,7 +26,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -3040,6 +3040,8 @@ static int airoha_register_gdm_devices(s +@@ -3043,6 +3043,8 @@ static int airoha_register_gdm_devices(s return err; } diff --git a/target/linux/airoha/patches-6.18/142-01-v7.1-net-airoha-Rely-on-net_device-pointer-in-airoha_dev_.patch b/target/linux/airoha/patches-6.18/142-01-v7.1-net-airoha-Rely-on-net_device-pointer-in-airoha_dev_.patch index a66538984f..f00ec63915 100644 --- a/target/linux/airoha/patches-6.18/142-01-v7.1-net-airoha-Rely-on-net_device-pointer-in-airoha_dev_.patch +++ b/target/linux/airoha/patches-6.18/142-01-v7.1-net-airoha-Rely-on-net_device-pointer-in-airoha_dev_.patch @@ -20,7 +20,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2752,7 +2752,7 @@ static int airoha_dev_setup_tc_block_cb( +@@ -2755,7 +2755,7 @@ static int airoha_dev_setup_tc_block_cb( } } @@ -29,7 +29,7 @@ Signed-off-by: Jakub Kicinski struct flow_block_offload *f) { flow_setup_cb_t *cb = airoha_dev_setup_tc_block_cb; -@@ -2765,12 +2765,12 @@ static int airoha_dev_setup_tc_block(str +@@ -2768,12 +2768,12 @@ static int airoha_dev_setup_tc_block(str f->driver_block_list = &block_cb_list; switch (f->command) { case FLOW_BLOCK_BIND: @@ -44,7 +44,7 @@ Signed-off-by: Jakub Kicinski if (IS_ERR(block_cb)) return PTR_ERR(block_cb); -@@ -2779,7 +2779,7 @@ static int airoha_dev_setup_tc_block(str +@@ -2782,7 +2782,7 @@ static int airoha_dev_setup_tc_block(str list_add_tail(&block_cb->driver_list, &block_cb_list); return 0; case FLOW_BLOCK_UNBIND: @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski if (!block_cb) return -ENOENT; -@@ -2878,7 +2878,7 @@ static int airoha_dev_tc_setup(struct ne +@@ -2881,7 +2881,7 @@ static int airoha_dev_tc_setup(struct ne return airoha_tc_setup_qdisc_htb(port, type_data); case TC_SETUP_BLOCK: case TC_SETUP_FT: diff --git a/target/linux/airoha/patches-6.18/142-02-v7.1-net-airoha-Rely-on-net_device-pointer-in-HTB-callbac.patch b/target/linux/airoha/patches-6.18/142-02-v7.1-net-airoha-Rely-on-net_device-pointer-in-HTB-callbac.patch index faad31a588..6f64a8c35b 100644 --- a/target/linux/airoha/patches-6.18/142-02-v7.1-net-airoha-Rely-on-net_device-pointer-in-HTB-callbac.patch +++ b/target/linux/airoha/patches-6.18/142-02-v7.1-net-airoha-Rely-on-net_device-pointer-in-HTB-callbac.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2557,10 +2557,11 @@ static int airoha_qdma_set_trtcm_token_b +@@ -2560,10 +2560,11 @@ static int airoha_qdma_set_trtcm_token_b mode, val); } @@ -32,7 +32,7 @@ Signed-off-by: Jakub Kicinski int i, err; for (i = 0; i <= TRTCM_PEAK_MODE; i++) { -@@ -2580,21 +2581,20 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2583,21 +2584,20 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -58,7 +58,7 @@ Signed-off-by: Jakub Kicinski if (err) { NL_SET_ERR_MSG_MOD(opt->extack, "failed configuring htb offload"); -@@ -2606,7 +2606,7 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2609,7 +2609,7 @@ static int airoha_tc_htb_alloc_leaf_queu err = netif_set_real_num_tx_queues(dev, num_tx_queues + 1); if (err) { @@ -67,7 +67,7 @@ Signed-off-by: Jakub Kicinski NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); return err; -@@ -2793,44 +2793,47 @@ static int airoha_dev_setup_tc_block(str +@@ -2796,44 +2796,47 @@ static int airoha_dev_setup_tc_block(str } } @@ -123,7 +123,7 @@ Signed-off-by: Jakub Kicinski if (!test_bit(channel, port->qos_sq_bmap)) { NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); -@@ -2842,23 +2845,23 @@ static int airoha_tc_get_htb_get_leaf_qu +@@ -2845,23 +2848,23 @@ static int airoha_tc_get_htb_get_leaf_qu return 0; } @@ -152,7 +152,7 @@ Signed-off-by: Jakub Kicinski default: return -EOPNOTSUPP; } -@@ -2875,7 +2878,7 @@ static int airoha_dev_tc_setup(struct ne +@@ -2878,7 +2881,7 @@ static int airoha_dev_tc_setup(struct ne case TC_SETUP_QDISC_ETS: return airoha_tc_setup_qdisc_ets(port, type_data); case TC_SETUP_QDISC_HTB: diff --git a/target/linux/airoha/patches-6.18/142-03-v7.1-net-airoha-Rely-on-net_device-pointer-in-ETS-callbac.patch b/target/linux/airoha/patches-6.18/142-03-v7.1-net-airoha-Rely-on-net_device-pointer-in-ETS-callbac.patch index a9400d1fb8..8c3cdb49a5 100644 --- a/target/linux/airoha/patches-6.18/142-03-v7.1-net-airoha-Rely-on-net_device-pointer-in-ETS-callbac.patch +++ b/target/linux/airoha/patches-6.18/142-03-v7.1-net-airoha-Rely-on-net_device-pointer-in-ETS-callbac.patch @@ -19,7 +19,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2203,10 +2203,11 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2206,10 +2206,11 @@ airoha_ethtool_get_rmon_stats(struct net } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -32,7 +32,7 @@ Signed-off-by: Jakub Kicinski int i; for (i = 0; i < AIROHA_NUM_TX_RING; i++) -@@ -2238,17 +2239,15 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2241,17 +2242,15 @@ static int airoha_qdma_set_chan_tx_sched return 0; } @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski struct tc_ets_qopt_offload *opt) { struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params; -@@ -2289,20 +2288,21 @@ static int airoha_qdma_set_tx_ets_sched( +@@ -2292,20 +2291,21 @@ static int airoha_qdma_set_tx_ets_sched( else if (nstrict < AIROHA_NUM_QOS_QUEUES - 1) mode = nstrict + 1; @@ -78,7 +78,7 @@ Signed-off-by: Jakub Kicinski _bstats_update(opt->stats.bstats, 0, tx_packets); port->cpu_tx_packets = cpu_tx_packets; -@@ -2311,7 +2311,7 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2314,7 +2314,7 @@ static int airoha_qdma_get_tx_ets_stats( return 0; } @@ -87,7 +87,7 @@ Signed-off-by: Jakub Kicinski struct tc_ets_qopt_offload *opt) { int channel; -@@ -2324,12 +2324,12 @@ static int airoha_tc_setup_qdisc_ets(str +@@ -2327,12 +2327,12 @@ static int airoha_tc_setup_qdisc_ets(str switch (opt->command) { case TC_ETS_REPLACE: @@ -103,7 +103,7 @@ Signed-off-by: Jakub Kicinski default: return -EOPNOTSUPP; } -@@ -2872,11 +2872,9 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -2875,11 +2875,9 @@ static int airoha_tc_setup_qdisc_htb(str static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type, void *type_data) { diff --git a/target/linux/airoha/patches-6.18/143-v7.1-net-airoha-Fix-typo-in-airoha_set_gdm2_loopback-rout.patch b/target/linux/airoha/patches-6.18/143-v7.1-net-airoha-Fix-typo-in-airoha_set_gdm2_loopback-rout.patch index 5a491bd59e..572f9cd0fb 100644 --- a/target/linux/airoha/patches-6.18/143-v7.1-net-airoha-Fix-typo-in-airoha_set_gdm2_loopback-rout.patch +++ b/target/linux/airoha/patches-6.18/143-v7.1-net-airoha-Fix-typo-in-airoha_set_gdm2_loopback-rout.patch @@ -15,7 +15,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1786,7 +1786,7 @@ static int airoha_dev_set_macaddr(struct +@@ -1789,7 +1789,7 @@ static int airoha_dev_set_macaddr(struct return 0; } @@ -24,7 +24,7 @@ Signed-off-by: Jakub Kicinski { struct airoha_eth *eth = port->qdma->eth; u32 val, pse_port, chan; -@@ -1862,7 +1862,7 @@ static int airoha_dev_init(struct net_de +@@ -1865,7 +1865,7 @@ static int airoha_dev_init(struct net_de if (!eth->ports[1]) { int err; diff --git a/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch b/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch index 56ac972956..4d82199c07 100644 --- a/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch +++ b/target/linux/airoha/patches-6.18/147-v7.1-net-airoha-Fix-PPE-cpu-port-configuration-for-GDM2-l.patch @@ -24,7 +24,7 @@ Signed-off-by: Paolo Abeni --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1791,7 +1791,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1794,7 +1794,7 @@ static int airoha_set_gdm2_loopback(stru { struct airoha_eth *eth = port->qdma->eth; u32 val, pse_port, chan; @@ -33,7 +33,7 @@ Signed-off-by: Paolo Abeni airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(AIROHA_GDM2_IDX), FE_PSE_PORT_DROP); -@@ -1835,6 +1835,9 @@ static int airoha_set_gdm2_loopback(stru +@@ -1838,6 +1838,9 @@ static int airoha_set_gdm2_loopback(stru SP_CPORT_MASK(val), __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2)); @@ -43,7 +43,7 @@ Signed-off-by: Paolo Abeni if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); -@@ -1873,7 +1876,8 @@ static int airoha_dev_init(struct net_de +@@ -1876,7 +1879,8 @@ static int airoha_dev_init(struct net_de } for (i = 0; i < eth->soc->num_ppe; i++) diff --git a/target/linux/airoha/patches-6.18/155-v7.2-net-airoha-Rename-get_src_port_id-callback-in-get_sp.patch b/target/linux/airoha/patches-6.18/155-v7.2-net-airoha-Rename-get_src_port_id-callback-in-get_sp.patch index 65e0a597e0..fba30f3206 100644 --- a/target/linux/airoha/patches-6.18/155-v7.2-net-airoha-Rename-get_src_port_id-callback-in-get_sp.patch +++ b/target/linux/airoha/patches-6.18/155-v7.2-net-airoha-Rename-get_src_port_id-callback-in-get_sp.patch @@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1822,7 +1822,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1825,7 +1825,7 @@ static int airoha_set_gdm2_loopback(stru airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX)); airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX)); @@ -26,7 +26,7 @@ Signed-off-by: Jakub Kicinski if (src_port < 0) return src_port; -@@ -3196,7 +3196,7 @@ static const char * const en7581_xsi_rst +@@ -3199,7 +3199,7 @@ static const char * const en7581_xsi_rst "xfp-mac", }; @@ -35,7 +35,7 @@ Signed-off-by: Jakub Kicinski { switch (port->id) { case AIROHA_GDM3_IDX: -@@ -3249,7 +3249,7 @@ static const char * const an7583_xsi_rst +@@ -3252,7 +3252,7 @@ static const char * const an7583_xsi_rst "xfp-mac", }; @@ -44,7 +44,7 @@ Signed-off-by: Jakub Kicinski { switch (port->id) { case AIROHA_GDM3_IDX: -@@ -3297,7 +3297,7 @@ static const struct airoha_eth_soc_data +@@ -3300,7 +3300,7 @@ static const struct airoha_eth_soc_data .num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names), .num_ppe = 2, .ops = { @@ -53,7 +53,7 @@ Signed-off-by: Jakub Kicinski .get_vip_port = airoha_en7581_get_vip_port, }, }; -@@ -3308,7 +3308,7 @@ static const struct airoha_eth_soc_data +@@ -3311,7 +3311,7 @@ static const struct airoha_eth_soc_data .num_xsi_rsts = ARRAY_SIZE(an7583_xsi_rsts_names), .num_ppe = 1, .ops = { diff --git a/target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch b/target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch index f6c5f766f2..c095e00cfc 100644 --- a/target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch +++ b/target/linux/airoha/patches-6.18/161-01-v7.2-net-airoha-Introduce-airoha_gdm_dev-struct.patch @@ -88,7 +88,7 @@ Signed-off-by: Jakub Kicinski } } q->txq_stopped = false; -@@ -1700,19 +1707,20 @@ static void airoha_update_hw_stats(struc +@@ -1703,19 +1710,20 @@ static void airoha_update_hw_stats(struc spin_unlock(&port->stats.lock); } @@ -114,7 +114,7 @@ Signed-off-by: Jakub Kicinski airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), GDM_STAG_EN_MASK); else -@@ -1740,16 +1748,17 @@ static int airoha_dev_open(struct net_de +@@ -1743,16 +1751,17 @@ static int airoha_dev_open(struct net_de return 0; } @@ -137,7 +137,7 @@ Signed-off-by: Jakub Kicinski airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id), FE_PSE_PORT_DROP); -@@ -1770,16 +1779,17 @@ static int airoha_dev_stop(struct net_de +@@ -1773,16 +1782,17 @@ static int airoha_dev_stop(struct net_de return 0; } @@ -159,7 +159,7 @@ Signed-off-by: Jakub Kicinski return 0; } -@@ -1845,16 +1855,17 @@ static int airoha_set_gdm2_loopback(stru +@@ -1848,16 +1858,17 @@ static int airoha_set_gdm2_loopback(stru return 0; } @@ -182,7 +182,7 @@ Signed-off-by: Jakub Kicinski switch (port->id) { case AIROHA_GDM3_IDX: -@@ -1879,10 +1890,11 @@ static int airoha_dev_init(struct net_de +@@ -1882,10 +1893,11 @@ static int airoha_dev_init(struct net_de return 0; } @@ -196,7 +196,7 @@ Signed-off-by: Jakub Kicinski unsigned int start; airoha_update_hw_stats(port); -@@ -1901,36 +1913,39 @@ static void airoha_dev_get_stats64(struc +@@ -1904,36 +1916,39 @@ static void airoha_dev_get_stats64(struc } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -243,7 +243,7 @@ Signed-off-by: Jakub Kicinski } static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev) -@@ -1994,9 +2009,10 @@ int airoha_get_fe_port(struct airoha_gdm +@@ -1997,9 +2012,10 @@ int airoha_get_fe_port(struct airoha_gdm } static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, @@ -256,7 +256,7 @@ Signed-off-by: Jakub Kicinski struct airoha_qdma *qdma = port->qdma; u32 nr_frags, tag, msg0, msg1, len; struct airoha_queue_entry *e; -@@ -2009,7 +2025,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2012,7 +2028,7 @@ static netdev_tx_t airoha_dev_xmit(struc u8 fport; qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb)); @@ -265,7 +265,7 @@ Signed-off-by: Jakub Kicinski msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK, qid / AIROHA_NUM_QOS_QUEUES) | -@@ -2045,7 +2061,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2048,7 +2064,7 @@ static netdev_tx_t airoha_dev_xmit(struc spin_lock_bh(&q->lock); @@ -274,7 +274,7 @@ Signed-off-by: Jakub Kicinski nr_frags = 1 + skb_shinfo(skb)->nr_frags; if (q->queued + nr_frags >= q->ndesc) { -@@ -2069,9 +2085,9 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2072,9 +2088,9 @@ static netdev_tx_t airoha_dev_xmit(struc dma_addr_t addr; u32 val; @@ -286,7 +286,7 @@ Signed-off-by: Jakub Kicinski goto error_unmap; list_move_tail(&e->list, &tx_list); -@@ -2120,7 +2136,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2123,7 +2139,7 @@ static netdev_tx_t airoha_dev_xmit(struc error_unmap: list_for_each_entry(e, &tx_list, list) { @@ -295,7 +295,7 @@ Signed-off-by: Jakub Kicinski DMA_TO_DEVICE); e->dma_addr = 0; } -@@ -2129,25 +2145,27 @@ error_unmap: +@@ -2132,25 +2148,27 @@ error_unmap: spin_unlock_bh(&q->lock); error: dev_kfree_skb_any(skb); @@ -328,7 +328,7 @@ Signed-off-by: Jakub Kicinski unsigned int start; airoha_update_hw_stats(port); -@@ -2175,11 +2193,12 @@ static const struct ethtool_rmon_hist_ra +@@ -2178,11 +2196,12 @@ static const struct ethtool_rmon_hist_ra }; static void @@ -343,7 +343,7 @@ Signed-off-by: Jakub Kicinski struct airoha_hw_stats *hw_stats = &port->stats; unsigned int start; -@@ -2204,11 +2223,12 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2207,11 +2226,12 @@ airoha_ethtool_get_rmon_stats(struct net } while (u64_stats_fetch_retry(&port->stats.syncp, start)); } @@ -358,7 +358,7 @@ Signed-off-by: Jakub Kicinski int i; for (i = 0; i < AIROHA_NUM_TX_RING; i++) -@@ -2293,10 +2313,12 @@ static int airoha_qdma_set_tx_ets_sched( +@@ -2296,10 +2316,12 @@ static int airoha_qdma_set_tx_ets_sched( ARRAY_SIZE(w)); } @@ -373,7 +373,7 @@ Signed-off-by: Jakub Kicinski u64 cpu_tx_packets = airoha_qdma_rr(port->qdma, REG_CNTR_VAL(channel << 1)); u64 fwd_tx_packets = airoha_qdma_rr(port->qdma, -@@ -2558,11 +2580,12 @@ static int airoha_qdma_set_trtcm_token_b +@@ -2561,11 +2583,12 @@ static int airoha_qdma_set_trtcm_token_b mode, val); } @@ -388,7 +388,7 @@ Signed-off-by: Jakub Kicinski int i, err; for (i = 0; i <= TRTCM_PEAK_MODE; i++) { -@@ -2582,20 +2605,22 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2585,20 +2608,22 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -415,7 +415,7 @@ Signed-off-by: Jakub Kicinski if (err) { NL_SET_ERR_MSG_MOD(opt->extack, "failed configuring htb offload"); -@@ -2605,9 +2630,10 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2608,9 +2633,10 @@ static int airoha_tc_htb_alloc_leaf_queu if (opt->command == TC_HTB_NODE_MODIFY) return 0; @@ -428,7 +428,7 @@ Signed-off-by: Jakub Kicinski NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); return err; -@@ -2697,11 +2723,12 @@ static int airoha_tc_matchall_act_valida +@@ -2700,11 +2726,12 @@ static int airoha_tc_matchall_act_valida return 0; } @@ -443,7 +443,7 @@ Signed-off-by: Jakub Kicinski u32 rate = 0, bucket_size = 0; switch (f->command) { -@@ -2736,18 +2763,19 @@ static int airoha_dev_tc_matchall(struct +@@ -2739,18 +2766,19 @@ static int airoha_dev_tc_matchall(struct static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { @@ -467,7 +467,7 @@ Signed-off-by: Jakub Kicinski default: return -EOPNOTSUPP; } -@@ -2794,47 +2822,51 @@ static int airoha_dev_setup_tc_block(str +@@ -2797,47 +2825,51 @@ static int airoha_dev_setup_tc_block(str } } @@ -531,7 +531,7 @@ Signed-off-by: Jakub Kicinski if (!test_bit(channel, port->qos_sq_bmap)) { NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); -@@ -2870,8 +2902,8 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -2873,8 +2905,8 @@ static int airoha_tc_setup_qdisc_htb(str return 0; } @@ -542,7 +542,7 @@ Signed-off-by: Jakub Kicinski { switch (type) { case TC_SETUP_QDISC_ETS: -@@ -2937,25 +2969,81 @@ static void airoha_metadata_dst_free(str +@@ -2940,25 +2972,81 @@ static void airoha_metadata_dst_free(str } } @@ -628,7 +628,7 @@ Signed-off-by: Jakub Kicinski int err, p; u32 id; -@@ -2977,53 +3065,22 @@ static int airoha_alloc_gdm_port(struct +@@ -2980,53 +3068,22 @@ static int airoha_alloc_gdm_port(struct return -EINVAL; } @@ -689,7 +689,7 @@ Signed-off-by: Jakub Kicinski } static int airoha_register_gdm_devices(struct airoha_eth *eth) -@@ -3037,7 +3094,7 @@ static int airoha_register_gdm_devices(s +@@ -3040,7 +3097,7 @@ static int airoha_register_gdm_devices(s if (!port) continue; @@ -698,7 +698,7 @@ Signed-off-by: Jakub Kicinski if (err) return err; } -@@ -3146,12 +3203,14 @@ error_napi_stop: +@@ -3149,12 +3206,14 @@ error_napi_stop: for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; @@ -715,7 +715,7 @@ Signed-off-by: Jakub Kicinski airoha_metadata_dst_free(port); } airoha_hw_cleanup(eth); -@@ -3172,11 +3231,14 @@ static void airoha_remove(struct platfor +@@ -3175,11 +3234,14 @@ static void airoha_remove(struct platfor for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { struct airoha_gdm_port *port = eth->ports[i]; diff --git a/target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch b/target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch index 78388f5c63..bca63f5ec6 100644 --- a/target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch +++ b/target/linux/airoha/patches-6.18/161-02-v7.2-net-airoha-Move-airoha_qdma-pointer-in-airoha_gdm_de.patch @@ -75,7 +75,7 @@ Signed-off-by: Jakub Kicinski for (j = 0; j < dev->dev->num_tx_queues; j++) { if (airoha_qdma_get_txq(qdma, j) != qid) continue; -@@ -1563,9 +1567,10 @@ static void airoha_qdma_stop_napi(struct +@@ -1566,9 +1570,10 @@ static void airoha_qdma_stop_napi(struct } } @@ -88,7 +88,7 @@ Signed-off-by: Jakub Kicinski u32 val, i = 0; spin_lock(&port->stats.lock); -@@ -1712,11 +1717,11 @@ static int airoha_dev_open(struct net_de +@@ -1715,11 +1720,11 @@ static int airoha_dev_open(struct net_de int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN; struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -102,7 +102,7 @@ Signed-off-by: Jakub Kicinski if (err) return err; -@@ -1752,11 +1757,11 @@ static int airoha_dev_stop(struct net_de +@@ -1755,11 +1760,11 @@ static int airoha_dev_stop(struct net_de { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -116,7 +116,7 @@ Signed-off-by: Jakub Kicinski for (i = 0; i < netdev->num_tx_queues; i++) netdev_tx_reset_subqueue(netdev, i); -@@ -1782,21 +1787,21 @@ static int airoha_dev_stop(struct net_de +@@ -1785,21 +1790,21 @@ static int airoha_dev_stop(struct net_de static int airoha_dev_set_macaddr(struct net_device *netdev, void *p) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -142,7 +142,7 @@ Signed-off-by: Jakub Kicinski u32 val, pse_port, chan; int i, src_port; -@@ -1843,7 +1848,7 @@ static int airoha_set_gdm2_loopback(stru +@@ -1846,7 +1851,7 @@ static int airoha_set_gdm2_loopback(stru __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2)); for (i = 0; i < eth->soc->num_ppe; i++) @@ -151,7 +151,7 @@ Signed-off-by: Jakub Kicinski if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) { u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq); -@@ -1863,9 +1868,9 @@ static int airoha_dev_init(struct net_de +@@ -1866,9 +1871,9 @@ static int airoha_dev_init(struct net_de int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ @@ -164,7 +164,7 @@ Signed-off-by: Jakub Kicinski switch (port->id) { case AIROHA_GDM3_IDX: -@@ -1874,7 +1879,7 @@ static int airoha_dev_init(struct net_de +@@ -1877,7 +1882,7 @@ static int airoha_dev_init(struct net_de if (!eth->ports[1]) { int err; @@ -173,7 +173,7 @@ Signed-off-by: Jakub Kicinski if (err) return err; } -@@ -1884,8 +1889,7 @@ static int airoha_dev_init(struct net_de +@@ -1887,8 +1892,7 @@ static int airoha_dev_init(struct net_de } for (i = 0; i < eth->soc->num_ppe; i++) @@ -183,7 +183,7 @@ Signed-off-by: Jakub Kicinski return 0; } -@@ -1897,7 +1901,7 @@ static void airoha_dev_get_stats64(struc +@@ -1900,7 +1904,7 @@ static void airoha_dev_get_stats64(struc struct airoha_gdm_port *port = dev->port; unsigned int start; @@ -192,7 +192,7 @@ Signed-off-by: Jakub Kicinski do { start = u64_stats_fetch_begin(&port->stats.syncp); storage->rx_packets = port->stats.rx_ok_pkts; -@@ -1917,8 +1921,8 @@ static int airoha_dev_change_mtu(struct +@@ -1920,8 +1924,8 @@ static int airoha_dev_change_mtu(struct { struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -202,7 +202,7 @@ Signed-off-by: Jakub Kicinski airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), GDM_LONG_LEN_MASK, -@@ -1992,10 +1996,10 @@ static u32 airoha_get_dsa_tag(struct sk_ +@@ -1995,10 +1999,10 @@ static u32 airoha_get_dsa_tag(struct sk_ #endif } @@ -216,7 +216,7 @@ Signed-off-by: Jakub Kicinski switch (eth->soc->version) { case 0x7583: -@@ -2012,8 +2016,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2015,8 +2019,7 @@ static netdev_tx_t airoha_dev_xmit(struc struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -226,7 +226,7 @@ Signed-off-by: Jakub Kicinski u32 nr_frags, tag, msg0, msg1, len; struct airoha_queue_entry *e; struct netdev_queue *txq; -@@ -2051,7 +2054,7 @@ static netdev_tx_t airoha_dev_xmit(struc +@@ -2054,7 +2057,7 @@ static netdev_tx_t airoha_dev_xmit(struc } } @@ -235,7 +235,7 @@ Signed-off-by: Jakub Kicinski msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) | FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); -@@ -2154,8 +2157,7 @@ static void airoha_ethtool_get_drvinfo(s +@@ -2157,8 +2160,7 @@ static void airoha_ethtool_get_drvinfo(s struct ethtool_drvinfo *info) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -245,7 +245,7 @@ Signed-off-by: Jakub Kicinski strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver)); strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info)); -@@ -2168,7 +2170,7 @@ static void airoha_ethtool_get_mac_stats +@@ -2171,7 +2173,7 @@ static void airoha_ethtool_get_mac_stats struct airoha_gdm_port *port = dev->port; unsigned int start; @@ -254,7 +254,7 @@ Signed-off-by: Jakub Kicinski do { start = u64_stats_fetch_begin(&port->stats.syncp); stats->FramesTransmittedOK = port->stats.tx_ok_pkts; -@@ -2208,7 +2210,7 @@ airoha_ethtool_get_rmon_stats(struct net +@@ -2211,7 +2213,7 @@ airoha_ethtool_get_rmon_stats(struct net ARRAY_SIZE(hw_stats->rx_len) + 1); *ranges = airoha_ethtool_rmon_ranges; @@ -263,7 +263,7 @@ Signed-off-by: Jakub Kicinski do { int i; -@@ -2228,18 +2230,17 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2231,18 +2233,17 @@ static int airoha_qdma_set_chan_tx_sched const u16 *weights, u8 n_weights) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -284,7 +284,7 @@ Signed-off-by: Jakub Kicinski TWRR_RW_CMD_MASK | FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | -@@ -2247,13 +2248,12 @@ static int airoha_qdma_set_chan_tx_sched +@@ -2250,13 +2251,12 @@ static int airoha_qdma_set_chan_tx_sched err = read_poll_timeout(airoha_qdma_rr, status, status & TWRR_RW_CMD_DONE, USEC_PER_MSEC, 10 * USEC_PER_MSEC, @@ -300,7 +300,7 @@ Signed-off-by: Jakub Kicinski CHAN_QOS_MODE_MASK(channel), __field_prep(CHAN_QOS_MODE_MASK(channel), mode)); -@@ -2319,9 +2319,9 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2322,9 +2322,9 @@ static int airoha_qdma_get_tx_ets_stats( struct airoha_gdm_dev *dev = netdev_priv(netdev); struct airoha_gdm_port *port = dev->port; @@ -312,7 +312,7 @@ Signed-off-by: Jakub Kicinski REG_CNTR_VAL((channel << 1) + 1)); u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) + (fwd_tx_packets - port->fwd_tx_packets); -@@ -2585,17 +2585,16 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2588,17 +2588,16 @@ static int airoha_qdma_set_tx_rate_limit u32 bucket_size) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -332,7 +332,7 @@ Signed-off-by: Jakub Kicinski REG_EGRESS_TRTCM_CFG, i, rate, bucket_size); if (err) -@@ -2645,11 +2644,11 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2648,11 +2647,11 @@ static int airoha_tc_htb_alloc_leaf_queu return 0; } @@ -346,7 +346,7 @@ Signed-off-by: Jakub Kicinski int i; for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { -@@ -2728,7 +2727,6 @@ static int airoha_dev_tc_matchall(struct +@@ -2731,7 +2730,6 @@ static int airoha_dev_tc_matchall(struct { enum trtcm_unit_type unit_type = TRTCM_BYTE_UNIT; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -354,7 +354,7 @@ Signed-off-by: Jakub Kicinski u32 rate = 0, bucket_size = 0; switch (f->command) { -@@ -2753,7 +2751,7 @@ static int airoha_dev_tc_matchall(struct +@@ -2756,7 +2754,7 @@ static int airoha_dev_tc_matchall(struct fallthrough; } case TC_CLSMATCHALL_DESTROY: @@ -363,7 +363,7 @@ Signed-off-by: Jakub Kicinski unit_type); default: return -EOPNOTSUPP; -@@ -2765,8 +2763,7 @@ static int airoha_dev_setup_tc_block_cb( +@@ -2768,8 +2766,7 @@ static int airoha_dev_setup_tc_block_cb( { struct net_device *netdev = cb_priv; struct airoha_gdm_dev *dev = netdev_priv(netdev); diff --git a/target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch b/target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch index 072089fe8b..8aeede07f3 100644 --- a/target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch +++ b/target/linux/airoha/patches-6.18/161-03-v7.2-net-airoha-Rely-on-airoha_gdm_dev-pointer-in-airoha_.patch @@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski val = (addr[0] << 16) | (addr[1] << 8) | addr[2]; airoha_fe_wr(eth, reg, val); -@@ -1868,7 +1866,7 @@ static int airoha_dev_init(struct net_de +@@ -1871,7 +1869,7 @@ static int airoha_dev_init(struct net_de int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ diff --git a/target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch b/target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch index b35b1b0a69..f87c99a35f 100644 --- a/target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch +++ b/target/linux/airoha/patches-6.18/161-04-v7.2-net-airoha-Move-qos_sq_bmap-in-airoha_gdm_dev-struct.patch @@ -22,7 +22,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2602,30 +2602,40 @@ static int airoha_qdma_set_tx_rate_limit +@@ -2605,30 +2605,40 @@ static int airoha_qdma_set_tx_rate_limit return 0; } @@ -75,7 +75,7 @@ Signed-off-by: Jakub Kicinski err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1); if (err) { -@@ -2633,13 +2643,17 @@ static int airoha_tc_htb_alloc_leaf_queu +@@ -2636,13 +2646,17 @@ static int airoha_tc_htb_alloc_leaf_queu opt->quantum); NL_SET_ERR_MSG_MOD(opt->extack, "failed setting real_num_tx_queues"); @@ -95,7 +95,7 @@ Signed-off-by: Jakub Kicinski } static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev, -@@ -2820,11 +2834,13 @@ static int airoha_dev_setup_tc_block(str +@@ -2823,11 +2837,13 @@ static int airoha_dev_setup_tc_block(str static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -111,7 +111,7 @@ Signed-off-by: Jakub Kicinski } static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev, -@@ -2832,9 +2848,8 @@ static int airoha_tc_htb_delete_leaf_que +@@ -2835,9 +2851,8 @@ static int airoha_tc_htb_delete_leaf_que { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -122,7 +122,7 @@ Signed-off-by: Jakub Kicinski NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); return -EINVAL; } -@@ -2847,10 +2862,9 @@ static int airoha_tc_htb_delete_leaf_que +@@ -2850,10 +2865,9 @@ static int airoha_tc_htb_delete_leaf_que static int airoha_tc_htb_destroy(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -134,7 +134,7 @@ Signed-off-by: Jakub Kicinski airoha_tc_remove_htb_queue(netdev, q); return 0; -@@ -2861,9 +2875,8 @@ static int airoha_tc_get_htb_get_leaf_qu +@@ -2864,9 +2878,8 @@ static int airoha_tc_get_htb_get_leaf_qu { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; struct airoha_gdm_dev *dev = netdev_priv(netdev); @@ -145,7 +145,7 @@ Signed-off-by: Jakub Kicinski NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); return -EINVAL; } -@@ -2882,6 +2895,7 @@ static int airoha_tc_setup_qdisc_htb(str +@@ -2885,6 +2898,7 @@ static int airoha_tc_setup_qdisc_htb(str case TC_HTB_DESTROY: return airoha_tc_htb_destroy(dev); case TC_HTB_NODE_MODIFY: diff --git a/target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch b/target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch index cb62a387b6..df6ca1ca1c 100644 --- a/target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch +++ b/target/linux/airoha/patches-6.18/161-05-v7.2-net-airoha-Move-cpu-fwd-_tx_packets-in-airoha_gdm_de.patch @@ -21,7 +21,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2315,19 +2315,17 @@ static int airoha_qdma_get_tx_ets_stats( +@@ -2318,19 +2318,17 @@ static int airoha_qdma_get_tx_ets_stats( struct tc_ets_qopt_offload *opt) { struct airoha_gdm_dev *dev = netdev_priv(netdev); diff --git a/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch b/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch index eaf4d8e426..3e84250b0f 100644 --- a/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch +++ b/target/linux/airoha/patches-6.18/161-06-v7.2-net-airoha-Rename-airoha_set_gdm2_loopback-in-airoha.patch @@ -18,7 +18,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1796,7 +1796,7 @@ static int airoha_dev_set_macaddr(struct +@@ -1799,7 +1799,7 @@ static int airoha_dev_set_macaddr(struct return 0; } @@ -27,7 +27,7 @@ Signed-off-by: Jakub Kicinski { struct airoha_gdm_port *port = dev->port; struct airoha_eth *eth = dev->eth; -@@ -1877,7 +1877,7 @@ static int airoha_dev_init(struct net_de +@@ -1880,7 +1880,7 @@ static int airoha_dev_init(struct net_de if (!eth->ports[1]) { int err; diff --git a/target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch b/target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch deleted file mode 100644 index 7ea6058ac4..0000000000 --- a/target/linux/airoha/patches-6.18/162-v7.2-net-airoha-Fix-use-after-free-in-metadata-dst-teardo.patch +++ /dev/null @@ -1,37 +0,0 @@ -From b38cae85d1c45ff189d7ecb6ac36f41cdc3d84d0 Mon Sep 17 00:00:00 2001 -From: Lorenzo Bianconi -Date: Tue, 2 Jun 2026 11:21:04 +0200 -Subject: [PATCH] net: airoha: Fix use-after-free in metadata dst teardown - -airoha_metadata_dst_free() runs metadata_dst_free() which frees the -metadata_dst with kfree() immediately, bypassing the RCU grace period. -In the RX path, skb_dst_set_noref() sets a non-refcounted pointer from -the skb to the metadata_dst. This function requires RCU read-side -protection and the dst must remain valid until all RCU readers complete. -Since metadata_dst_free() calls kfree() directly, an use-after-free can -occur if any skb still holds a noref pointer to the dst when the driver -tears it down. -Replace metadata_dst_free() with dst_release() which properly goes -through the refcount path: when the refcount drops to zero, it schedules -the actual free via call_rcu_hurry(), ensuring all RCU readers have -completed before the memory is freed. - -Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor") -Signed-off-by: Lorenzo Bianconi -Link: https://patch.msgid.link/20260602-airoha-mtk-metadata-uaf-fix-v1-1-3aaa99d83351@kernel.org -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/airoha/airoha_eth.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2972,7 +2972,7 @@ static void airoha_metadata_dst_free(str - if (!port->dsa_meta[i]) - continue; - -- metadata_dst_free(port->dsa_meta[i]); -+ dst_release(&port->dsa_meta[i]->dst); - } - } - diff --git a/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch b/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch index 6e4807b0e3..3534bb72e1 100644 --- a/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch +++ b/target/linux/airoha/patches-6.18/163-v7.2-net-airoha-Report-extack-error-to-the-user-if-airoha.patch @@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -2605,13 +2605,19 @@ static int airoha_tc_htb_modify_queue(st +@@ -2608,13 +2608,19 @@ static int airoha_tc_htb_modify_queue(st { u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */ diff --git a/target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch b/target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch deleted file mode 100644 index 830198151c..0000000000 --- a/target/linux/airoha/patches-6.18/164-v7.2-net-airoha-Add-NULL-check-for-of_reserved_mem_lookup.patch +++ /dev/null @@ -1,41 +0,0 @@ -From f9f25118faa4dd2b6e3d14a03d123bbdbd59925d Mon Sep 17 00:00:00 2001 -From: ZhaoJinming -Date: Thu, 4 Jun 2026 15:03:52 +0800 -Subject: [PATCH] net: airoha: Add NULL check for of_reserved_mem_lookup() in - airoha_qdma_init_hfwd_queues() - -of_reserved_mem_lookup() may return NULL if the reserved memory region -referenced by the "memory-region" phandle is not found in the reserved -memory table (e.g. due to a misconfigured DTS or a removed -memory-region node). The current code dereferences the returned -pointer without checking for NULL, leading to a kernel NULL pointer -dereference at the following lines: - - dma_addr = rmem->base; // line 1156 - num_desc = div_u64(rmem->size, buf_size); // line 1160 - -Add a NULL check after of_reserved_mem_lookup() and return -ENODEV if -the lookup fails, which is consistent with the existing error handling -for of_parse_phandle() failure in the same code block. - -Fixes: 3a1ce9e3d01b ("net: airoha: Add the capability to allocate hwfd buffers via reserved-memory") -Cc: stable@vger.kernel.org -Signed-off-by: ZhaoJinming -Acked-by: Lorenzo Bianconi -Signed-off-by: Jakub Kicinski ---- - drivers/net/ethernet/airoha/airoha_eth.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/ethernet/airoha/airoha_eth.c -+++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -1159,6 +1159,9 @@ static int airoha_qdma_init_hfwd_queues( - - rmem = of_reserved_mem_lookup(np); - of_node_put(np); -+ if (!rmem) -+ return -ENODEV; -+ - dma_addr = rmem->base; - /* Compute the number of hw descriptors according to the - * reserved memory size and the payload buffer size diff --git a/target/linux/airoha/patches-6.18/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch b/target/linux/airoha/patches-6.18/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch index 2b978e1160..cc710daead 100644 --- a/target/linux/airoha/patches-6.18/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch +++ b/target/linux/airoha/patches-6.18/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch @@ -107,7 +107,7 @@ Signed-off-by: Christian Marangi module_phy_driver(as21xxx_drivers); --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1882,7 +1882,8 @@ void phy_detach(struct phy_device *phyde +@@ -1885,7 +1885,8 @@ void phy_detach(struct phy_device *phyde } /* Assert the reset signal */ diff --git a/target/linux/armsr/armv8/config-6.18 b/target/linux/armsr/armv8/config-6.18 index 80d325e44e..0e132297fb 100644 --- a/target/linux/armsr/armv8/config-6.18 +++ b/target/linux/armsr/armv8/config-6.18 @@ -91,6 +91,7 @@ CONFIG_ARM64_ERRATUM_2441007=y CONFIG_ARM64_ERRATUM_2441009=y CONFIG_ARM64_ERRATUM_2457168=y CONFIG_ARM64_ERRATUM_2658417=y +CONFIG_ARM64_ERRATUM_4118414=y CONFIG_ARM64_ERRATUM_4193714=y CONFIG_ARM64_ERRATUM_819472=y CONFIG_ARM64_ERRATUM_824069=y diff --git a/target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch b/target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch index aca784e753..30787e6a27 100644 --- a/target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch +++ b/target/linux/generic/backport-6.18/711-v7.2-net-phy-sfp-detect-presence-via-I2C-when-no-MOD_DEF0-GPIO.patch @@ -74,7 +74,7 @@ Signed-off-by: Jakub Kicinski /* Access rules: * state_hw_drive: st_mutex held * state_hw_mask: st_mutex held -@@ -860,6 +877,45 @@ static int sfp_read(struct sfp *sfp, boo +@@ -861,6 +878,45 @@ static int sfp_read(struct sfp *sfp, boo return sfp->read(sfp, a2, addr, buf, len); } @@ -120,7 +120,7 @@ Signed-off-by: Jakub Kicinski static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len) { return sfp->write(sfp, a2, addr, buf, len); -@@ -3158,9 +3214,30 @@ static int sfp_probe(struct platform_dev +@@ -3159,9 +3215,30 @@ static int sfp_probe(struct platform_dev sfp->get_state = sfp_gpio_get_state; sfp->set_state = sfp_gpio_set_state; diff --git a/target/linux/generic/backport-6.18/746-v7.1-r8152-Add-support-for-5Gbit-Link-Speeds-and-EEE.patch b/target/linux/generic/backport-6.18/746-v7.1-r8152-Add-support-for-5Gbit-Link-Speeds-and-EEE.patch index 49bac39bcf..851333aab4 100644 --- a/target/linux/generic/backport-6.18/746-v7.1-r8152-Add-support-for-5Gbit-Link-Speeds-and-EEE.patch +++ b/target/linux/generic/backport-6.18/746-v7.1-r8152-Add-support-for-5Gbit-Link-Speeds-and-EEE.patch @@ -221,7 +221,7 @@ Signed-off-by: Paolo Abeni eee->eee_enabled = tp->eee_en; if (speed & _1000bps) -@@ -9381,6 +9440,11 @@ static int rtl8152_probe_once(struct usb +@@ -9386,6 +9445,11 @@ static int rtl8152_probe_once(struct usb } else { tp->speed = SPEED_1000; } diff --git a/target/linux/generic/backport-6.18/747-v7.1-r8152-Add-support-for-the-RTL8157-hardware.patch b/target/linux/generic/backport-6.18/747-v7.1-r8152-Add-support-for-the-RTL8157-hardware.patch index 459c2dba11..e1da5c1321 100644 --- a/target/linux/generic/backport-6.18/747-v7.1-r8152-Add-support-for-the-RTL8157-hardware.patch +++ b/target/linux/generic/backport-6.18/747-v7.1-r8152-Add-support-for-the-RTL8157-hardware.patch @@ -1535,7 +1535,7 @@ Signed-off-by: Paolo Abeni default: version = RTL_VER_UNKNOWN; dev_info(&udev->dev, "Unknown version 0x%04x\n", ocp_data); -@@ -9411,6 +9954,7 @@ static int rtl8152_probe_once(struct usb +@@ -9416,6 +9959,7 @@ static int rtl8152_probe_once(struct usb case RTL_VER_12: case RTL_VER_13: case RTL_VER_15: @@ -1543,7 +1543,7 @@ Signed-off-by: Paolo Abeni netdev->max_mtu = size_to_mtu(16 * 1024); break; case RTL_VER_01: -@@ -9571,6 +10115,7 @@ static const struct usb_device_id rtl815 +@@ -9576,6 +10120,7 @@ static const struct usb_device_id rtl815 { USB_DEVICE(VENDOR_ID_REALTEK, 0x8153) }, { USB_DEVICE(VENDOR_ID_REALTEK, 0x8155) }, { USB_DEVICE(VENDOR_ID_REALTEK, 0x8156) }, diff --git a/target/linux/generic/config-6.18 b/target/linux/generic/config-6.18 index e532458b42..2460aa1b03 100644 --- a/target/linux/generic/config-6.18 +++ b/target/linux/generic/config-6.18 @@ -397,6 +397,7 @@ CONFIG_ARM64_CNP=y # CONFIG_ARM64_ERRATUM_2966298 is not set # CONFIG_ARM64_ERRATUM_3117295 is not set # CONFIG_ARM64_ERRATUM_3194386 is not set +# CONFIG_ARM64_ERRATUM_4118414 is not set # CONFIG_ARM64_ERRATUM_819472 is not set # CONFIG_ARM64_ERRATUM_824069 is not set # CONFIG_ARM64_ERRATUM_826319 is not set diff --git a/target/linux/generic/hack-6.18/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-6.18/780-usb-net-MeigLink_modem_support.patch index eff038fbd0..feeb329ca1 100644 --- a/target/linux/generic/hack-6.18/780-usb-net-MeigLink_modem_support.patch +++ b/target/linux/generic/hack-6.18/780-usb-net-MeigLink_modem_support.patch @@ -32,7 +32,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c -@@ -247,6 +247,11 @@ static void option_instat_callback(struc +@@ -248,6 +248,11 @@ static void option_instat_callback(struc #define UBLOX_PRODUCT_R410M 0x90b2 /* These Yuga products use Qualcomm's vendor ID */ #define YUGA_PRODUCT_CLM920_NC5 0x9625 @@ -44,7 +44,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support #define QUECTEL_VENDOR_ID 0x2c7c /* These Quectel products use Quectel's vendor ID */ -@@ -1156,6 +1161,11 @@ static const struct usb_device_id option +@@ -1159,6 +1164,11 @@ static const struct usb_device_id option { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */ .driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) }, @@ -56,7 +56,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support /* Quectel products using Qualcomm vendor ID */ { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)}, { USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20), -@@ -1197,6 +1207,11 @@ static const struct usb_device_id option +@@ -1200,6 +1210,11 @@ static const struct usb_device_id option .driver_info = ZLP }, { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), .driver_info = RSVD(4) }, diff --git a/target/linux/generic/hack-6.18/901-debloat_sock_diag.patch b/target/linux/generic/hack-6.18/901-debloat_sock_diag.patch index 1308c0d971..69be731568 100644 --- a/target/linux/generic/hack-6.18/901-debloat_sock_diag.patch +++ b/target/linux/generic/hack-6.18/901-debloat_sock_diag.patch @@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau INDIRECT_CALLABLE_DECLARE(struct dst_entry *ip6_dst_check(struct dst_entry *, u32)); INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, -@@ -2406,9 +2423,11 @@ static void __sk_free(struct sock *sk) +@@ -2411,9 +2428,11 @@ static void __sk_free(struct sock *sk) if (likely(sk->sk_net_refcnt)) sock_inuse_add(sock_net(sk), -1); diff --git a/target/linux/generic/hack-6.18/902-debloat_proc.patch b/target/linux/generic/hack-6.18/902-debloat_proc.patch index e6829065a4..4afc1e8c5a 100644 --- a/target/linux/generic/hack-6.18/902-debloat_proc.patch +++ b/target/linux/generic/hack-6.18/902-debloat_proc.patch @@ -331,7 +331,7 @@ Signed-off-by: Felix Fietkau --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -4349,6 +4349,8 @@ static __net_initdata struct pernet_oper +@@ -4358,6 +4358,8 @@ static __net_initdata struct pernet_oper static int __init proto_init(void) { diff --git a/target/linux/generic/kernel-6.18 b/target/linux/generic/kernel-6.18 index b268a2d8f1..1efcc0734e 100644 --- a/target/linux/generic/kernel-6.18 +++ b/target/linux/generic/kernel-6.18 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.18 = .35 -LINUX_KERNEL_HASH-6.18.35 = f78602932219125e211c5f5bfd84edcfd4ec5ce88fc944f8248413f665bef236 +LINUX_VERSION-6.18 = .36 +LINUX_KERNEL_HASH-6.18.36 = fbab86c9f471c81075b280cca30bd85d790c060063a1245859b6344b07c9c44e diff --git a/target/linux/generic/pending-6.18/103-kbuild-export-SUBARCH.patch b/target/linux/generic/pending-6.18/103-kbuild-export-SUBARCH.patch index 8d204b98f6..0f0bd49092 100644 --- a/target/linux/generic/pending-6.18/103-kbuild-export-SUBARCH.patch +++ b/target/linux/generic/pending-6.18/103-kbuild-export-SUBARCH.patch @@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau --- a/Makefile +++ b/Makefile -@@ -628,7 +628,7 @@ export RUSTC_BOOTSTRAP := 1 +@@ -629,7 +629,7 @@ export RUSTC_BOOTSTRAP := 1 # Allows finding `.clippy.toml` in out-of-srctree builds. export CLIPPY_CONF_DIR := $(srctree) diff --git a/target/linux/generic/pending-6.18/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch b/target/linux/generic/pending-6.18/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch index f3d96f6bb2..bf140cc4f0 100644 --- a/target/linux/generic/pending-6.18/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch +++ b/target/linux/generic/pending-6.18/681-net-remove-NETIF_F_GSO_FRAGLIST-from-NETIF_F_GSO_SOF.patch @@ -96,7 +96,7 @@ Signed-off-by: Felix Fietkau } --- a/net/core/sock.c +++ b/net/core/sock.c -@@ -2620,7 +2620,7 @@ void sk_setup_caps(struct sock *sk, stru +@@ -2625,7 +2625,7 @@ void sk_setup_caps(struct sock *sk, stru icsk->icsk_ack.dst_quick_ack = dst_metric(dst, RTAX_QUICKACK); } if (sk->sk_route_caps & NETIF_F_GSO) diff --git a/target/linux/generic/pending-6.18/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.18/703-phy-add-detach-callback-to-struct-phy_driver.patch index 97f7d3f3da..baa9dc7a52 100644 --- a/target/linux/generic/pending-6.18/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-6.18/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1836,6 +1836,9 @@ void phy_detach(struct phy_device *phyde +@@ -1839,6 +1839,9 @@ void phy_detach(struct phy_device *phyde phydev->devlink = NULL; } diff --git a/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch b/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch index ebc4fb8b72..66cbf9b6a1 100644 --- a/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch +++ b/target/linux/mediatek/patches-6.18/901-arm-add-cmdline-override.patch @@ -51,7 +51,7 @@ Signed-off-by: Yoonji Park * CONFIG_CMDLINE is meant to be a default in case nothing else --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig -@@ -2398,6 +2398,14 @@ config CMDLINE_FORCE +@@ -2436,6 +2436,14 @@ config CMDLINE_FORCE endchoice diff --git a/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch b/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch index b1cac719cb..534d15a6fa 100644 --- a/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch +++ b/target/linux/realtek/patches-6.18/705-v7.1-net-sfp-initialize-i2c_block_size-at-adapter-configu.patch @@ -31,8 +31,8 @@ Signed-off-by: Jakub Kicinski --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c -@@ -841,6 +841,7 @@ static int sfp_i2c_configure(struct sfp - return -EINVAL; +@@ -1815,6 +1815,7 @@ static int sfp_hwmon_insert(struct sfp * + sfp->hwmon_tries = R_PROBE_RETRY_SLOW; } + sfp->i2c_block_size = sfp->i2c_max_block_size; diff --git a/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch b/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch index ceeaae4c75..42362fc0fd 100644 --- a/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch +++ b/target/linux/realtek/patches-6.18/714-net-phy-sfp-add-support-for-SMBus.patch @@ -40,7 +40,7 @@ Signed-off-by: Antoine Tenart static void sfp_i2c_mdiobus_destroy(struct sfp *sfp) { mdiobus_unregister(sfp->i2c_mii); -@@ -2172,9 +2195,15 @@ static void sfp_sm_fault(struct sfp *sfp +@@ -2173,9 +2196,15 @@ static void sfp_sm_fault(struct sfp *sfp static int sfp_sm_add_mdio_bus(struct sfp *sfp) { diff --git a/target/linux/rockchip/armv8/config-6.18 b/target/linux/rockchip/armv8/config-6.18 index c1213b5da5..098f1ac4f9 100644 --- a/target/linux/rockchip/armv8/config-6.18 +++ b/target/linux/rockchip/armv8/config-6.18 @@ -38,6 +38,7 @@ CONFIG_ARM64_ERRATUM_2441007=y CONFIG_ARM64_ERRATUM_2441009=y CONFIG_ARM64_ERRATUM_2658417=y CONFIG_ARM64_ERRATUM_3117295=y +CONFIG_ARM64_ERRATUM_4118414=y CONFIG_ARM64_ERRATUM_819472=y CONFIG_ARM64_ERRATUM_824069=y CONFIG_ARM64_ERRATUM_826319=y From ea57b794fccc9c3dfd838e9991e4167d0eab2ce0 Mon Sep 17 00:00:00 2001 From: Kenneth Kasilag Date: Sun, 21 Jun 2026 22:37:38 +0000 Subject: [PATCH 121/228] qualcommbe: use kernel 6.18 by default and drop 6.12 Switch the qualcommbe target to use kernel 6.18 and drop 6.12. Kernel 6.18 for qualcommbe resolves some issues regarding PCS support and reduces maintenance load maintaining two kernel branches. Signed-off-by: Kenneth Kasilag Link: https://github.com/openwrt/openwrt/pull/23908 Signed-off-by: Jonas Jelonek --- target/linux/qualcommbe/Makefile | 3 +- target/linux/qualcommbe/config-6.12 | 618 ---- ...s-PCI-qcom-Document-the-IPQ9574-PCIe.patch | 101 - ...qcom-ipq9574-Add-PCIe-PHYs-and-contr.patch | 468 --- ...qcom-ipq9574-Enable-PCIe-PHYs-and-co.patch | 152 - ...s-clock-qcom-Add-CMN-PLL-clock-contr.patch | 132 - ...dd-CMN-PLL-clock-controller-driver-f.patch | 501 --- ...64-dts-qcom-ipq9574-Add-CMN-PLL-node.patch | 122 - ...qcom-ipq9574-Update-xo_board_clk-to-.patch | 48 - ...ndings-Introduce-qcom-spi-qpic-snand.patch | 105 - ...s-clock-gcc-ipq9574-Add-definition-f.patch | 25 - ...s-clock-Add-ipq9574-NSSCC-clock-and-.patch | 415 --- ...cc-ipq9574-Add-support-for-gpll0_out.patch | 49 - ...dd-NSS-clock-Controller-driver-for-I.patch | 3160 ----------------- ...onfig-Build-NSS-Clock-Controller-dri.patch | 29 - ...ve-PHY-package-code-from-phy_device..patch | 524 --- ...d-getters-for-public-members-in-stru.patch | 60 - ...rm64-dts-qcom-ipq9574-Add-nsscc-node.patch | 54 - ...pq9574-fix-the-msi-interrupt-numbers.patch | 44 - ...ts-qcom-ipq9574-Add-SPI-nand-support.patch | 50 - ...-ipq9574-Enable-SPI-NAND-for-ipq9574.patch | 68 - ...64-dts-qcom-ipq9574-Remove-eMMC-node.patch | 37 - ...ts-qcom-Add-IPQ9574-MDIO-device-node.patch | 49 - ...m-ipq9574-Use-usb-phy-for-node-names.patch | 34 - ...pq9574-add-QPIC-SPI-NAND-default-par.patch | 51 - ...dd-partition-table-for-ipq9574-rdp-c.patch | 174 - ...Document-Qualcomm-QCA8084-PHY-packag.patch | 536 --- ...08x-Add-QCA8084-ethernet-phy-support.patch | 144 - ...Add-config_init-function-for-QCA8084.patch | 85 - ...Add-link_change_notify-function-for-.patch | 90 - ...Add-register-access-support-routines.patch | 125 - ...y-qca808x-Add-QCA8084-probe-function.patch | 162 - ...Add-package-clocks-and-resets-for-QC.patch | 135 - ...8x-Add-QCA8084-package-init-function.patch | 177 - ...pcs-Add-Ethernet-PCS-for-Qualcomm-IP.patch | 234 -- ...-PCS-driver-for-Qualcomm-IPQ9574-SoC.patch | 301 -- ...9574-Add-PCS-instantiation-and-phyli.patch | 555 --- ...9574-Add-USXGMII-interface-mode-supp.patch | 272 -- ...maintainer-for-Qualcomm-IPQ9574-PCS-.patch | 31 - ...ts-qcom-ipq9574-add-PCS-uniphy-nodes.patch | 139 - ...net-Add-PPE-for-Qualcomm-IPQ9574-SoC.patch | 432 --- ...Add-PPE-driver-documentation-for-Qua.patch | 227 -- ...lcomm-Add-PPE-driver-for-IPQ9574-SoC.patch | 339 -- ...lcomm-Initialize-PPE-buffer-manageme.patch | 328 -- ...lcomm-Initialize-PPE-queue-managemen.patch | 320 -- ...lcomm-Initialize-the-PPE-scheduler-s.patch | 1000 ------ ...alcomm-Initialize-PPE-queue-settings.patch | 522 --- ...lcomm-Initialize-PPE-service-code-se.patch | 384 -- ...lcomm-Initialize-PPE-port-control-se.patch | 215 -- ...lcomm-Initialize-PPE-RSS-hash-settin.patch | 344 -- ...lcomm-Initialize-PPE-queue-to-Ethern.patch | 122 - ...lcomm-Initialize-PPE-L2-bridge-setti.patch | 193 - ...lcomm-Add-PPE-debugfs-support-for-PP.patch | 950 ----- ...d-maintainer-for-Qualcomm-PPE-driver.patch | 30 - ...et-qualcomm-Add-PPE-scheduler-config.patch | 201 -- ...lcomm-Add-phylink-support-for-PPE-MA.patch | 1040 ------ ...lcomm-Add-PPE-port-MAC-MIB-statistic.patch | 673 ---- ...lcomm-Add-PPE-port-MAC-address-and-E.patch | 172 - ...lcomm-Add-API-to-configure-PPE-port-.patch | 78 - ...lcomm-Add-EDMA-support-for-QCOM-IPQ9.patch | 932 ----- ...lcomm-Add-netdevice-support-for-QCOM.patch | 397 --- ...qualcomm-Add-Rx-Ethernet-DMA-support.patch | 2454 ------------- ...qualcomm-Add-Tx-Ethernet-DMA-support.patch | 2363 ------------ ...lcomm-Add-miscellaneous-error-interr.patch | 730 ---- ...ualcomm-Add-ethtool-support-for-EDMA.patch | 344 -- ...lcomm-Add-module-parameters-for-driv.patch | 286 -- ...t-qualcomm-Add-sysctl-for-RPS-bitmap.patch | 145 - ...lcomm-Add-support-for-label-property.patch | 48 - ...lcomm-ppe-Fix-unmet-dependency-with-.patch | 30 - ...lcomm-ppe-select-correct-PCS-depende.patch | 24 - ...com-Add-IPQ9574-PPE-base-device-node.patch | 72 - ...4-dts-qcom-Add-EDMA-node-for-IPQ9574.patch | 91 - ...ts-qcom-Add-IPQ9574-RDP433-port-node.patch | 197 - ...dd-AQR-NVMEM-node-for-IPQ9574-RDP433.patch | 33 - ...dd-label-to-EDMA-port-for-IPQ9574-RD.patch | 62 - ...ttach-required-NSSNOC-clock-to-PM-do.patch | 73 - ...ipq9574-add-NSSNOC-clock-to-nss-node.patch | 42 - ...nsscc-ipq9574-fix-port5-clock-config.patch | 46 - ...ASER-interface-mode-support-to-IPQ-U.patch | 136 - ...BASEX-interface-mode-support-to-IPQ-.patch | 166 - ...BASEX-interface-mode-support-to-IPQ-.patch | 104 - ...QXGMII-interface-mode-support-to-IPQ.patch | 267 -- ...hy-control-MISC2-register-for-2.5G-s.patch | 70 - ...q-uniphy-fix-USXGMII-link-up-failure.patch | 24 - ...om-ipq9574-Update-IPQ9574-PCS-driver.patch | 282 -- ...y-Add-phy_package_remove_once-helper.patch | 36 - ...Add-QCA8084-SerDes-probe-and-remove-.patch | 437 --- ...08x-Add-QCA8084-SerDes-init-function.patch | 446 --- ...808x-Add-QCA8084-SerDes-speed-config.patch | 251 -- ...-dt-bindings-pwm-add-IPQ6018-binding.patch | 181 - ...river-for-qualcomm-ipq6018-pwm-block.patch | 403 --- ...-arm64-dts-qcom-ipq9574-add-pwm-node.patch | 144 - 92 files changed, 1 insertion(+), 28944 deletions(-) delete mode 100644 target/linux/qualcommbe/config-6.12 delete mode 100644 target/linux/qualcommbe/patches-6.12/0002-v6.13-dt-bindings-PCI-qcom-Document-the-IPQ9574-PCIe.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0004-v6.14-arm64-dts-qcom-ipq9574-Add-PCIe-PHYs-and-contr.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0005-v6.14-arm64-dts-qcom-ipq9574-Enable-PCIe-PHYs-and-co.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0006-v6.14-dt-bindings-clock-qcom-Add-CMN-PLL-clock-contr.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0007-v6.14-clk-qcom-Add-CMN-PLL-clock-controller-driver-f.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0008-v6.14-arm64-dts-qcom-ipq9574-Add-CMN-PLL-node.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0009-v6.14-arm64-dts-qcom-ipq9574-Update-xo_board_clk-to-.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0016-v6.15-spi-dt-bindings-Introduce-qcom-spi-qpic-snand.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0018-v6.15-dt-bindings-clock-gcc-ipq9574-Add-definition-f.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0019-v6.15-dt-bindings-clock-Add-ipq9574-NSSCC-clock-and-.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0020-v6.15-clk-qcom-gcc-ipq9574-Add-support-for-gpll0_out.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0021-v6.15-clk-qcom-Add-NSS-clock-Controller-driver-for-I.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0022-v6.15-arm64-defconfig-Build-NSS-Clock-Controller-dri.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0023-v6.15-net-phy-move-PHY-package-code-from-phy_device..patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0024-v6.15-net-phy-add-getters-for-public-members-in-stru.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0100-arm64-dts-qcom-ipq9574-Add-nsscc-node.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0101-arm64-dts-qcom-ipq9574-fix-the-msi-interrupt-numbers.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0103-arm64-dts-qcom-ipq9574-Add-SPI-nand-support.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0104-arm64-dts-qcom-ipq9574-Enable-SPI-NAND-for-ipq9574.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0105-arm64-dts-qcom-ipq9574-Remove-eMMC-node.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0301-arm64-dts-qcom-Add-IPQ9574-MDIO-device-node.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0302-arm64-dts-qcom-ipq9574-Use-usb-phy-for-node-names.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0304-arm64-dts-qcom-ipq9574-add-QPIC-SPI-NAND-default-par.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0305-arm64-dts-qcom-add-partition-table-for-ipq9574-rdp-c.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0306-dt-bindings-net-Document-Qualcomm-QCA8084-PHY-packag.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0307-net-phy-qca808x-Add-QCA8084-ethernet-phy-support.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0308-net-phy-qca808x-Add-config_init-function-for-QCA8084.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0309-net-phy-qca808x-Add-link_change_notify-function-for-.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0310-net-phy-qca808x-Add-register-access-support-routines.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0311-net-phy-qca808x-Add-QCA8084-probe-function.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0312-net-phy-qca808x-Add-package-clocks-and-resets-for-QC.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0313-net-phy-qca808x-Add-QCA8084-package-init-function.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0314-dt-bindings-net-pcs-Add-Ethernet-PCS-for-Qualcomm-IP.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0315-net-pcs-Add-PCS-driver-for-Qualcomm-IPQ9574-SoC.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0317-net-pcs-qcom-ipq9574-Add-USXGMII-interface-mode-supp.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0318-MAINTAINERS-Add-maintainer-for-Qualcomm-IPQ9574-PCS-.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0323-dt-bindings-net-Add-PPE-for-Qualcomm-IPQ9574-SoC.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0324-docs-networking-Add-PPE-driver-documentation-for-Qua.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0325-net-ethernet-qualcomm-Add-PPE-driver-for-IPQ9574-SoC.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0326-net-ethernet-qualcomm-Initialize-PPE-buffer-manageme.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0327-net-ethernet-qualcomm-Initialize-PPE-queue-managemen.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0328-net-ethernet-qualcomm-Initialize-the-PPE-scheduler-s.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0329-net-ethernet-qualcomm-Initialize-PPE-queue-settings.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0330-net-ethernet-qualcomm-Initialize-PPE-service-code-se.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0331-net-ethernet-qualcomm-Initialize-PPE-port-control-se.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0332-net-ethernet-qualcomm-Initialize-PPE-RSS-hash-settin.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0333-net-ethernet-qualcomm-Initialize-PPE-queue-to-Ethern.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0334-net-ethernet-qualcomm-Initialize-PPE-L2-bridge-setti.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0335-net-ethernet-qualcomm-Add-PPE-debugfs-support-for-PP.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0336-MAINTAINERS-Add-maintainer-for-Qualcomm-PPE-driver.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0337-net-ethernet-qualcomm-Add-PPE-scheduler-config.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0338-net-ethernet-qualcomm-Add-phylink-support-for-PPE-MA.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0339-net-ethernet-qualcomm-Add-PPE-port-MAC-MIB-statistic.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0340-net-ethernet-qualcomm-Add-PPE-port-MAC-address-and-E.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0341-net-ethernet-qualcomm-Add-API-to-configure-PPE-port-.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0342-net-ethernet-qualcomm-Add-EDMA-support-for-QCOM-IPQ9.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0343-net-ethernet-qualcomm-Add-netdevice-support-for-QCOM.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0344-net-ethernet-qualcomm-Add-Rx-Ethernet-DMA-support.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0345-net-ethernet-qualcomm-Add-Tx-Ethernet-DMA-support.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0346-net-ethernet-qualcomm-Add-miscellaneous-error-interr.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0347-net-ethernet-qualcomm-Add-ethtool-support-for-EDMA.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0348-net-ethernet-qualcomm-Add-module-parameters-for-driv.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0349-net-ethernet-qualcomm-Add-sysctl-for-RPS-bitmap.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0350-net-ethernet-qualcomm-Add-support-for-label-property.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0351-net-ethernet-qualcomm-ppe-Fix-unmet-dependency-with-.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0352-net-ethernet-qualcomm-ppe-select-correct-PCS-depende.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0353-arm64-dts-qcom-Add-IPQ9574-PPE-base-device-node.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0354-arm64-dts-qcom-Add-EDMA-node-for-IPQ9574.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0355-arm64-dts-qcom-Add-IPQ9574-RDP433-port-node.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0356-arm64-dts-qcom-add-AQR-NVMEM-node-for-IPQ9574-RDP433.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0357-arm64-dts-qcom-Add-label-to-EDMA-port-for-IPQ9574-RD.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0358-clk-qcom-nsscc-Attach-required-NSSNOC-clock-to-PM-do.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0359-arm64-dts-qcom-ipq9574-add-NSSNOC-clock-to-nss-node.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0360-clk-qcom-nsscc-ipq9574-fix-port5-clock-config.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0370-net-phy-Add-phy_package_remove_once-helper.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0371-net-phy-qca808x-Add-QCA8084-SerDes-probe-and-remove-.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0372-net-phy-qca808x-Add-QCA8084-SerDes-init-function.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0373-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0374-dt-bindings-pwm-add-IPQ6018-binding.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0375-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0376-arm64-dts-qcom-ipq9574-add-pwm-node.patch diff --git a/target/linux/qualcommbe/Makefile b/target/linux/qualcommbe/Makefile index 8e5200f6cf..8570945bd4 100644 --- a/target/linux/qualcommbe/Makefile +++ b/target/linux/qualcommbe/Makefile @@ -8,8 +8,7 @@ KERNELNAME:=Image CPU_TYPE:=cortex-a53 SUBTARGETS:=ipq95xx -KERNEL_PATCHVER:=6.12 -KERNEL_TESTING_PATCHVER:=6.18 +KERNEL_PATCHVER:=6.18 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ diff --git a/target/linux/qualcommbe/config-6.12 b/target/linux/qualcommbe/config-6.12 deleted file mode 100644 index 5178c3bf24..0000000000 --- a/target/linux/qualcommbe/config-6.12 +++ /dev/null @@ -1,618 +0,0 @@ -CONFIG_64BIT=y -CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y -CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y -CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_FORCE_MAX_ORDER=10 -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y -CONFIG_ARCH_MMAP_RND_BITS=18 -CONFIG_ARCH_MMAP_RND_BITS_MAX=24 -CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 -CONFIG_ARCH_PKEY_BITS=3 -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ARCH_QCOM=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANTS_EXECMEM_LATE=y -CONFIG_ARCH_WANTS_NO_INSTR=y -CONFIG_ARCH_WANTS_THP_SWAP=y -CONFIG_ARM64=y -CONFIG_ARM64_4K_PAGES=y -CONFIG_ARM64_ERRATUM_1165522=y -CONFIG_ARM64_ERRATUM_1286807=y -CONFIG_ARM64_ERRATUM_2051678=y -CONFIG_ARM64_ERRATUM_2054223=y -CONFIG_ARM64_ERRATUM_2067961=y -CONFIG_ARM64_ERRATUM_2077057=y -CONFIG_ARM64_ERRATUM_2658417=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_PA_BITS=48 -CONFIG_ARM64_PA_BITS_48=y -CONFIG_ARM64_PLATFORM_DEVICES=y -CONFIG_ARM64_PTR_AUTH=y -CONFIG_ARM64_PTR_AUTH_KERNEL=y -CONFIG_ARM64_SVE=y -CONFIG_ARM64_TAGGED_ADDR_ABI=y -CONFIG_ARM64_VA_BITS=39 -CONFIG_ARM64_VA_BITS_39=y -CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y -CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y -CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_GIC=y -CONFIG_ARM_GIC_V2M=y -CONFIG_ARM_GIC_V3=y -CONFIG_ARM_GIC_V3_ITS=y -# CONFIG_ARM_MHU_V2 is not set -# CONFIG_ARM_MHU_V3 is not set -CONFIG_ARM_PSCI_CPUIDLE=y -CONFIG_ARM_PSCI_FW=y -# CONFIG_ARM_QCOM_CPUFREQ_HW is not set -CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y -CONFIG_AT803X_PHY=y -CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_AUXILIARY_BUS=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y -CONFIG_BLK_PM=y -CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y -CONFIG_CC_HAVE_SHADOW_CALL_STACK=y -CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y -# CONFIG_CLK_QCM2290_GPUCC is not set -# CONFIG_CLK_X1E80100_CAMCC is not set -# CONFIG_CLK_X1E80100_DISPCC is not set -# CONFIG_CLK_X1E80100_GCC is not set -# CONFIG_CLK_X1E80100_GPUCC is not set -# CONFIG_CLK_X1E80100_TCSRCC is not set -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_QCOM=y -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -# CONFIG_COMPAT_32BIT_TIME is not set -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -CONFIG_COREDUMP=y -CONFIG_CPUFREQ_DT=y -CONFIG_CPUFREQ_DT_PLATDEV=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_THERMAL=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MITIGATIONS=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_THERMAL=y -CONFIG_CRC16=y -CONFIG_CRC8=y -CONFIG_CRYPTO_AUTHENC=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DEV_QCE=y -CONFIG_CRYPTO_DEV_QCE_AEAD=y -# CONFIG_CRYPTO_DEV_QCE_ENABLE_AEAD is not set -CONFIG_CRYPTO_DEV_QCE_ENABLE_ALL=y -# CONFIG_CRYPTO_DEV_QCE_ENABLE_SHA is not set -# CONFIG_CRYPTO_DEV_QCE_ENABLE_SKCIPHER is not set -CONFIG_CRYPTO_DEV_QCE_SHA=y -CONFIG_CRYPTO_DEV_QCE_SKCIPHER=y -CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN=512 -CONFIG_CRYPTO_DEV_QCOM_RNG=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_DES=y -CONFIG_CRYPTO_LIB_GF128MUL=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_XTS=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -CONFIG_DEV_COREDUMP=y -CONFIG_DMADEVICES=y -CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y -CONFIG_DMA_DIRECT_REMAP=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_NEED_SYNC=y -CONFIG_DMA_OF=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DTC=y -CONFIG_DT_IDLE_STATES=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FRAME_POINTER=y -CONFIG_FS_IOMAP=y -CONFIG_FUNCTION_ALIGNMENT=4 -CONFIG_FUNCTION_ALIGNMENT_4B=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_DEVICES=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_CSUM=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOREMAP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GLOB=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_CDEV=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HWMON=y -CONFIG_HWSPINLOCK=y -CONFIG_HWSPINLOCK_QCOM=y -CONFIG_HW_RANDOM=y -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_HELPER_AUTO=y -# CONFIG_I2C_QCOM_CCI is not set -CONFIG_I2C_QUP=y -CONFIG_IIO=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INTERCONNECT=y -CONFIG_INTERCONNECT_CLK=y -# CONFIG_INTERCONNECT_QCOM is not set -CONFIG_IPQ_APSS_6018=y -CONFIG_IPQ_APSS_PLL=y -# CONFIG_IPQ_CMN_PLL is not set -# CONFIG_IPQ_GCC_4019 is not set -# CONFIG_IPQ_GCC_5018 is not set -# CONFIG_IPQ_GCC_5332 is not set -# CONFIG_IPQ_GCC_6018 is not set -# CONFIG_IPQ_GCC_8074 is not set -# CONFIG_IPQ_GCC_9574 is not set -# CONFIG_IPQ_NSSCC_QCA8K is not set -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MSI_LIB=y -CONFIG_IRQ_WORK=y -# CONFIG_KPSS_XCC is not set -CONFIG_LEDS_TLC591XX=y -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LRU_GEN_WALKS_MMU=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MAILBOX=y -# CONFIG_MAILBOX_TEST is not set -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MDIO_IPQ4019=y -# CONFIG_MFD_QCOM_RPM is not set -CONFIG_MFD_SYSCON=y -CONFIG_MIGRATION=y -# CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY is not set -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_BLOCK_MINORS=32 -CONFIG_MMC_CQHCI=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_IO_ACCESSORS=y -CONFIG_MMC_SDHCI_MSM=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMU_LAZY_TLB_REFCOUNT=y -CONFIG_MODULES_USE_ELF_RELA=y -# CONFIG_MSM_GCC_8916 is not set -# CONFIG_MSM_GCC_8917 is not set -# CONFIG_MSM_GCC_8939 is not set -# CONFIG_MSM_GCC_8976 is not set -# CONFIG_MSM_GCC_8994 is not set -# CONFIG_MSM_GCC_8996 is not set -# CONFIG_MSM_GCC_8998 is not set -# CONFIG_MSM_GPUCC_8998 is not set -# CONFIG_MSM_MMCC_8996 is not set -# CONFIG_MSM_MMCC_8998 is not set -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_QCOM=y -CONFIG_MTD_QCOMSMEM_PARTS=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NET_EGRESS=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_INGRESS=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_XGRESS=y -CONFIG_NLS=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=4 -# CONFIG_NSM is not set -CONFIG_NVMEM=y -CONFIG_NVMEM_LAYOUTS=y -CONFIG_NVMEM_LAYOUT_U_BOOT_ENV=y -CONFIG_NVMEM_QCOM_QFPROM=y -# CONFIG_NVMEM_QCOM_SEC_QFPROM is not set -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_PADATA=y -CONFIG_PAGE_POOL=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -CONFIG_PARTITION_PERCPU=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEASPM=y -CONFIG_PCIEASPM_DEFAULT=y -# CONFIG_PCIEASPM_PERFORMANCE is not set -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_DW=y -CONFIG_PCIE_DW_HOST=y -CONFIG_PCIE_PME=y -CONFIG_PCIE_QCOM=y -CONFIG_PCIE_QCOM_COMMON=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_MSI=y -# CONFIG_PCS_QCOM_IPQ9574 is not set -CONFIG_PER_VMA_LOCK=y -CONFIG_PGTABLE_LEVELS=3 -CONFIG_PHYLIB=y -CONFIG_PHYLIB_LEDS=y -CONFIG_PHYS_ADDR_T_64BIT=y -# CONFIG_PHY_QCOM_APQ8064_SATA is not set -# CONFIG_PHY_QCOM_EDP is not set -# CONFIG_PHY_QCOM_EUSB2_REPEATER is not set -# CONFIG_PHY_QCOM_IPQ4019_USB is not set -# CONFIG_PHY_QCOM_IPQ806X_SATA is not set -# CONFIG_PHY_QCOM_IPQ806X_USB is not set -# CONFIG_PHY_QCOM_M31_USB is not set -# CONFIG_PHY_QCOM_PCIE2 is not set -CONFIG_PHY_QCOM_QMP=y -CONFIG_PHY_QCOM_QMP_COMBO=y -CONFIG_PHY_QCOM_QMP_PCIE=y -CONFIG_PHY_QCOM_QMP_PCIE_8996=y -CONFIG_PHY_QCOM_QMP_UFS=y -CONFIG_PHY_QCOM_QMP_USB=y -# CONFIG_PHY_QCOM_QMP_USB_LEGACY is not set -CONFIG_PHY_QCOM_QUSB2=y -# CONFIG_PHY_QCOM_SGMII_ETH is not set -# CONFIG_PHY_QCOM_SNPS_EUSB2 is not set -# CONFIG_PHY_QCOM_USB_HS_28NM is not set -# CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2 is not set -# CONFIG_PHY_QCOM_USB_SS is not set -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_IPQ5018 is not set -# CONFIG_PINCTRL_IPQ5332 is not set -# CONFIG_PINCTRL_IPQ6018 is not set -# CONFIG_PINCTRL_IPQ8074 is not set -# CONFIG_PINCTRL_IPQ9574 is not set -CONFIG_PINCTRL_MSM=y -# CONFIG_PINCTRL_MSM8916 is not set -# CONFIG_PINCTRL_MSM8976 is not set -# CONFIG_PINCTRL_MSM8994 is not set -# CONFIG_PINCTRL_MSM8996 is not set -# CONFIG_PINCTRL_MSM8998 is not set -# CONFIG_PINCTRL_QCM2290 is not set -# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set -# CONFIG_PINCTRL_QCS404 is not set -# CONFIG_PINCTRL_QDU1000 is not set -# CONFIG_PINCTRL_SA8775P is not set -# CONFIG_PINCTRL_SC7180 is not set -# CONFIG_PINCTRL_SC8280XP is not set -# CONFIG_PINCTRL_SDM660 is not set -# CONFIG_PINCTRL_SDM670 is not set -# CONFIG_PINCTRL_SDM845 is not set -# CONFIG_PINCTRL_SDX75 is not set -# CONFIG_PINCTRL_SM4450 is not set -# CONFIG_PINCTRL_SM6350 is not set -# CONFIG_PINCTRL_SM6375 is not set -# CONFIG_PINCTRL_SM7150 is not set -# CONFIG_PINCTRL_SM8150 is not set -# CONFIG_PINCTRL_SM8250 is not set -# CONFIG_PINCTRL_SM8450 is not set -# CONFIG_PINCTRL_SM8550 is not set -# CONFIG_PINCTRL_SM8650 is not set -# CONFIG_PINCTRL_X1E80100 is not set -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_OPP=y -CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y -CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_MSM is not set -CONFIG_POWER_SUPPLY=y -CONFIG_PRINTK_TIME=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PWM=y -CONFIG_PWM_IPQ=y -CONFIG_QCA807X_PHY=y -CONFIG_QCA808X_PHY=y -# CONFIG_QCM_DISPCC_2290 is not set -# CONFIG_QCM_GCC_2290 is not set -# CONFIG_QCOM_A53PLL is not set -# CONFIG_QCOM_AOSS_QMP is not set -CONFIG_QCOM_APCS_IPC=y -# CONFIG_QCOM_APR is not set -CONFIG_QCOM_BAM_DMA=y -# CONFIG_QCOM_CLK_APCC_MSM8996 is not set -# CONFIG_QCOM_CLK_APCS_MSM8916 is not set -# CONFIG_QCOM_COMMAND_DB is not set -# CONFIG_QCOM_CPR is not set -# CONFIG_QCOM_CPUCP_MBOX is not set -# CONFIG_QCOM_EBI2 is not set -# CONFIG_QCOM_FASTRPC is not set -# CONFIG_QCOM_GENI_SE is not set -# CONFIG_QCOM_GSBI is not set -# CONFIG_QCOM_HFPLL is not set -# CONFIG_QCOM_ICC_BWMON is not set -# CONFIG_QCOM_IPA is not set -# CONFIG_QCOM_IPCC is not set -# CONFIG_QCOM_LLCC is not set -CONFIG_QCOM_MDT_LOADER=y -# CONFIG_QCOM_MPM is not set -CONFIG_QCOM_NET_PHYLIB=y -# CONFIG_QCOM_OCMEM is not set -# CONFIG_QCOM_PDC is not set -CONFIG_QCOM_PIL_INFO=y -# CONFIG_QCOM_PPE is not set -# CONFIG_QCOM_Q6V5_ADSP is not set -CONFIG_QCOM_Q6V5_COMMON=y -# CONFIG_QCOM_Q6V5_MSS is not set -# CONFIG_QCOM_Q6V5_PAS is not set -CONFIG_QCOM_Q6V5_WCSS=y -# CONFIG_QCOM_QSEECOM is not set -# CONFIG_QCOM_RAMP_CTRL is not set -# CONFIG_QCOM_RMTFS_MEM is not set -# CONFIG_QCOM_RPMH is not set -# CONFIG_QCOM_RPM_MASTER_STATS is not set -CONFIG_QCOM_RPROC_COMMON=y -CONFIG_QCOM_SCM=y -# CONFIG_QCOM_SMD_RPM is not set -CONFIG_QCOM_SMEM=y -CONFIG_QCOM_SMEM_STATE=y -CONFIG_QCOM_SMP2P=y -# CONFIG_QCOM_SMSM is not set -CONFIG_QCOM_SOCINFO=y -# CONFIG_QCOM_SPM is not set -# CONFIG_QCOM_STATS is not set -# CONFIG_QCOM_SYSMON is not set -CONFIG_QCOM_TSENS=y -CONFIG_QCOM_TZMEM=y -CONFIG_QCOM_TZMEM_MODE_GENERIC=y -# CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE is not set -# CONFIG_QCOM_WCNSS_CTRL is not set -# CONFIG_QCOM_WCNSS_PIL is not set -CONFIG_QCOM_WDT=y -# CONFIG_QCS_GCC_404 is not set -# CONFIG_QCS_Q6SSTOP_404 is not set -# CONFIG_QCS_TURING_404 is not set -# CONFIG_QDU_ECPRICC_1000 is not set -# CONFIG_QDU_GCC_1000 is not set -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -# CONFIG_REGULATOR_VQMMC_IPQ4019 is not set -CONFIG_RELOCATABLE=y -CONFIG_REMOTEPROC=y -CONFIG_REMOTEPROC_CDEV=y -CONFIG_RESET_CONTROLLER=y -# CONFIG_RESET_QCOM_AOSS is not set -# CONFIG_RESET_QCOM_PDC is not set -CONFIG_RFS_ACCEL=y -CONFIG_RODATA_FULL_DEFAULT_ENABLED=y -CONFIG_RPMSG=y -CONFIG_RPMSG_CHAR=y -# CONFIG_RPMSG_CTRL is not set -# CONFIG_RPMSG_NS is not set -CONFIG_RPMSG_QCOM_GLINK=y -CONFIG_RPMSG_QCOM_GLINK_RPM=y -CONFIG_RPMSG_QCOM_GLINK_SMEM=y -CONFIG_RPMSG_QCOM_SMD=y -# CONFIG_RPMSG_TTY is not set -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -# CONFIG_SA_GCC_8775P is not set -# CONFIG_SA_GPUCC_8775P is not set -# CONFIG_SCHED_CORE is not set -CONFIG_SCHED_HW_PRESSURE=y -CONFIG_SCHED_MC=y -CONFIG_SCHED_SMT=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -# CONFIG_SCSI_LOWLEVEL is not set -# CONFIG_SCSI_PROC_FS is not set -# CONFIG_SC_CAMCC_7280 is not set -# CONFIG_SC_CAMCC_8280XP is not set -# CONFIG_SC_DISPCC_7180 is not set -# CONFIG_SC_DISPCC_8280XP is not set -# CONFIG_SC_GCC_7180 is not set -# CONFIG_SC_GCC_8280XP is not set -# CONFIG_SC_GPUCC_7180 is not set -# CONFIG_SC_LPASSCC_7280 is not set -# CONFIG_SC_LPASSCC_8280XP is not set -# CONFIG_SC_LPASS_CORECC_7180 is not set -# CONFIG_SC_LPASS_CORECC_7280 is not set -# CONFIG_SC_VIDEOCC_7180 is not set -# CONFIG_SDM_CAMCC_845 is not set -# CONFIG_SDM_DISPCC_845 is not set -# CONFIG_SDM_GCC_660 is not set -# CONFIG_SDM_GCC_845 is not set -# CONFIG_SDM_GPUCC_845 is not set -# CONFIG_SDM_LPASSCC_845 is not set -# CONFIG_SDM_VIDEOCC_845 is not set -# CONFIG_SDX_GCC_75 is not set -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_MSM=y -CONFIG_SERIAL_MSM_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -# CONFIG_SM_CAMCC_4450 is not set -# CONFIG_SM_CAMCC_6350 is not set -# CONFIG_SM_CAMCC_7150 is not set -# CONFIG_SM_CAMCC_8150 is not set -# CONFIG_SM_CAMCC_8450 is not set -# CONFIG_SM_CAMCC_8550 is not set -# CONFIG_SM_CAMCC_8650 is not set -# CONFIG_SM_GCC_4450 is not set -# CONFIG_SM_GCC_7150 is not set -# CONFIG_SM_GCC_8150 is not set -# CONFIG_SM_GCC_8250 is not set -# CONFIG_SM_GCC_8450 is not set -# CONFIG_SM_GCC_8550 is not set -# CONFIG_SM_GCC_8650 is not set -# CONFIG_SM_GPUCC_4450 is not set -# CONFIG_SM_GPUCC_6115 is not set -# CONFIG_SM_GPUCC_6125 is not set -# CONFIG_SM_GPUCC_6350 is not set -# CONFIG_SM_GPUCC_6375 is not set -# CONFIG_SM_GPUCC_8150 is not set -# CONFIG_SM_GPUCC_8250 is not set -# CONFIG_SM_GPUCC_8350 is not set -# CONFIG_SM_GPUCC_8450 is not set -# CONFIG_SM_GPUCC_8550 is not set -# CONFIG_SM_GPUCC_8650 is not set -# CONFIG_SM_TCSRCC_8550 is not set -# CONFIG_SM_TCSRCC_8650 is not set -# CONFIG_SM_VIDEOCC_7150 is not set -# CONFIG_SM_VIDEOCC_8150 is not set -# CONFIG_SM_VIDEOCC_8250 is not set -# CONFIG_SM_VIDEOCC_8350 is not set -# CONFIG_SM_VIDEOCC_8450 is not set -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BUS=y -CONFIG_SOFTIRQ_ON_OWN_STACK=y -CONFIG_SPARSEMEM=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -# CONFIG_SPI_QPIC_SNAND is not set -CONFIG_SPI_QUP=y -CONFIG_SPLIT_PMD_PTLOCKS=y -CONFIG_SPLIT_PTE_PTLOCKS=y -CONFIG_SWIOTLB=y -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_HWMON=y -CONFIG_THERMAL_OF=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TOOLS_SUPPORT_RELR=y -CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -CONFIG_UBIFS_FS_ADVANCED_COMPR=y -# CONFIG_UCLAMP_TASK is not set -CONFIG_UNMAP_KERNEL_AT_EL0=y -CONFIG_USB=y -CONFIG_USB_COMMON=y -CONFIG_USB_SUPPORT=y -CONFIG_USER_STACKTRACE_SUPPORT=y -CONFIG_VDSO_GETRANDOM=y -CONFIG_VIRTIO=y -CONFIG_VIRTIO_ANCHOR=y -# CONFIG_VIRTIO_BLK is not set -# CONFIG_VIRTIO_DEBUG is not set -# CONFIG_VIRTIO_NET is not set -CONFIG_VMAP_STACK=y -CONFIG_WANT_DEV_COREDUMP=y -CONFIG_WATCHDOG_CORE=y -CONFIG_WATCHDOG_SYSFS=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZONE_DMA32=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/qualcommbe/patches-6.12/0002-v6.13-dt-bindings-PCI-qcom-Document-the-IPQ9574-PCIe.patch b/target/linux/qualcommbe/patches-6.12/0002-v6.13-dt-bindings-PCI-qcom-Document-the-IPQ9574-PCIe.patch deleted file mode 100644 index 2c883030e3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0002-v6.13-dt-bindings-PCI-qcom-Document-the-IPQ9574-PCIe.patch +++ /dev/null @@ -1,101 +0,0 @@ -From e3ccffe9335ce3bdba93640588fab4560d18485e Mon Sep 17 00:00:00 2001 -From: devi priya -Date: Thu, 1 Aug 2024 11:18:00 +0530 -Subject: [PATCH 02/22] v6.13: dt-bindings: PCI: qcom: Document the IPQ9574 - PCIe controller -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Document the PCIe controller on IPQ9574 platform. - -Link: https://lore.kernel.org/r/20240801054803.3015572-2-quic_srichara@quicinc.com -Signed-off-by: devi priya -Signed-off-by: Sricharan Ramabadhran -Signed-off-by: Krzysztof Wilczyński -Reviewed-by: Krzysztof Kozlowski -Reviewed-by: Manivannan Sadhasivam ---- - .../devicetree/bindings/pci/qcom,pcie.yaml | 50 +++++++++++++++++++ - 1 file changed, 50 insertions(+) - ---- a/Documentation/devicetree/bindings/pci/qcom,pcie.yaml -+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.yaml -@@ -26,6 +26,7 @@ properties: - - qcom,pcie-ipq8064-v2 - - qcom,pcie-ipq8074 - - qcom,pcie-ipq8074-gen3 -+ - qcom,pcie-ipq9574 - - qcom,pcie-msm8996 - - qcom,pcie-qcs404 - - qcom,pcie-sdm845 -@@ -164,6 +165,7 @@ allOf: - enum: - - qcom,pcie-ipq6018 - - qcom,pcie-ipq8074-gen3 -+ - qcom,pcie-ipq9574 - then: - properties: - reg: -@@ -405,6 +407,53 @@ allOf: - compatible: - contains: - enum: -+ - qcom,pcie-ipq9574 -+ then: -+ properties: -+ clocks: -+ minItems: 6 -+ maxItems: 6 -+ clock-names: -+ items: -+ - const: axi_m # AXI Master clock -+ - const: axi_s # AXI Slave clock -+ - const: axi_bridge -+ - const: rchng -+ - const: ahb -+ - const: aux -+ -+ resets: -+ minItems: 8 -+ maxItems: 8 -+ reset-names: -+ items: -+ - const: pipe # PIPE reset -+ - const: sticky # Core Sticky reset -+ - const: axi_s_sticky # AXI Slave Sticky reset -+ - const: axi_s # AXI Slave reset -+ - const: axi_m_sticky # AXI Master Sticky reset -+ - const: axi_m # AXI Master reset -+ - const: aux # AUX Reset -+ - const: ahb # AHB Reset -+ -+ interrupts: -+ minItems: 8 -+ interrupt-names: -+ items: -+ - const: msi0 -+ - const: msi1 -+ - const: msi2 -+ - const: msi3 -+ - const: msi4 -+ - const: msi5 -+ - const: msi6 -+ - const: msi7 -+ -+ - if: -+ properties: -+ compatible: -+ contains: -+ enum: - - qcom,pcie-qcs404 - then: - properties: -@@ -510,6 +559,7 @@ allOf: - - qcom,pcie-ipq8064v2 - - qcom,pcie-ipq8074 - - qcom,pcie-ipq8074-gen3 -+ - qcom,pcie-ipq9574 - - qcom,pcie-qcs404 - then: - required: diff --git a/target/linux/qualcommbe/patches-6.12/0004-v6.14-arm64-dts-qcom-ipq9574-Add-PCIe-PHYs-and-contr.patch b/target/linux/qualcommbe/patches-6.12/0004-v6.14-arm64-dts-qcom-ipq9574-Add-PCIe-PHYs-and-contr.patch deleted file mode 100644 index 9b0deb29db..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0004-v6.14-arm64-dts-qcom-ipq9574-Add-PCIe-PHYs-and-contr.patch +++ /dev/null @@ -1,468 +0,0 @@ -From acb06ebe2d1f043fd597f5c33aff048ae1804293 Mon Sep 17 00:00:00 2001 -From: devi priya -Date: Thu, 1 Aug 2024 11:18:01 +0530 -Subject: [PATCH 04/22] v6.14: arm64: dts: qcom: ipq9574: Add PCIe PHYs and - controller nodes - -Add PCIe0, PCIe1, PCIe2, PCIe3 (and corresponding PHY) devices -found on IPQ9574 platform. The PCIe0 & PCIe1 are 1-lane Gen3 -host whereas PCIe2 & PCIe3 are 2-lane Gen3 host. - -Signed-off-by: devi priya -Signed-off-by: Sricharan Ramabadhran -Link: https://lore.kernel.org/r/20240801054803.3015572-3-quic_srichara@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 420 +++++++++++++++++++++++++- - 1 file changed, 416 insertions(+), 4 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -226,6 +226,52 @@ - reg = <0x00060000 0x6000>; - }; - -+ pcie0_phy: phy@84000 { -+ compatible = "qcom,ipq9574-qmp-gen3x1-pcie-phy"; -+ reg = <0x00084000 0x1000>; -+ -+ clocks = <&gcc GCC_PCIE0_AUX_CLK>, -+ <&gcc GCC_PCIE0_AHB_CLK>, -+ <&gcc GCC_PCIE0_PIPE_CLK>; -+ clock-names = "aux", "cfg_ahb", "pipe"; -+ -+ assigned-clocks = <&gcc GCC_PCIE0_AUX_CLK>; -+ assigned-clock-rates = <20000000>; -+ -+ resets = <&gcc GCC_PCIE0_PHY_BCR>, -+ <&gcc GCC_PCIE0PHY_PHY_BCR>; -+ reset-names = "phy", "common"; -+ -+ #clock-cells = <0>; -+ clock-output-names = "gcc_pcie0_pipe_clk_src"; -+ -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ pcie2_phy: phy@8c000 { -+ compatible = "qcom,ipq9574-qmp-gen3x2-pcie-phy"; -+ reg = <0x0008c000 0x2000>; -+ -+ clocks = <&gcc GCC_PCIE2_AUX_CLK>, -+ <&gcc GCC_PCIE2_AHB_CLK>, -+ <&gcc GCC_PCIE2_PIPE_CLK>; -+ clock-names = "aux", "cfg_ahb", "pipe"; -+ -+ assigned-clocks = <&gcc GCC_PCIE2_AUX_CLK>; -+ assigned-clock-rates = <20000000>; -+ -+ resets = <&gcc GCC_PCIE2_PHY_BCR>, -+ <&gcc GCC_PCIE2PHY_PHY_BCR>; -+ reset-names = "phy", "common"; -+ -+ #clock-cells = <0>; -+ clock-output-names = "gcc_pcie2_pipe_clk_src"; -+ -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ - rng: rng@e3000 { - compatible = "qcom,prng-ee"; - reg = <0x000e3000 0x1000>; -@@ -243,6 +289,52 @@ - status = "disabled"; - }; - -+ pcie3_phy: phy@f4000 { -+ compatible = "qcom,ipq9574-qmp-gen3x2-pcie-phy"; -+ reg = <0x000f4000 0x2000>; -+ -+ clocks = <&gcc GCC_PCIE3_AUX_CLK>, -+ <&gcc GCC_PCIE3_AHB_CLK>, -+ <&gcc GCC_PCIE3_PIPE_CLK>; -+ clock-names = "aux", "cfg_ahb", "pipe"; -+ -+ assigned-clocks = <&gcc GCC_PCIE3_AUX_CLK>; -+ assigned-clock-rates = <20000000>; -+ -+ resets = <&gcc GCC_PCIE3_PHY_BCR>, -+ <&gcc GCC_PCIE3PHY_PHY_BCR>; -+ reset-names = "phy", "common"; -+ -+ #clock-cells = <0>; -+ clock-output-names = "gcc_pcie3_pipe_clk_src"; -+ -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ pcie1_phy: phy@fc000 { -+ compatible = "qcom,ipq9574-qmp-gen3x1-pcie-phy"; -+ reg = <0x000fc000 0x1000>; -+ -+ clocks = <&gcc GCC_PCIE1_AUX_CLK>, -+ <&gcc GCC_PCIE1_AHB_CLK>, -+ <&gcc GCC_PCIE1_PIPE_CLK>; -+ clock-names = "aux", "cfg_ahb", "pipe"; -+ -+ assigned-clocks = <&gcc GCC_PCIE1_AUX_CLK>; -+ assigned-clock-rates = <20000000>; -+ -+ resets = <&gcc GCC_PCIE1_PHY_BCR>, -+ <&gcc GCC_PCIE1PHY_PHY_BCR>; -+ reset-names = "phy", "common"; -+ -+ #clock-cells = <0>; -+ clock-output-names = "gcc_pcie1_pipe_clk_src"; -+ -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ - qfprom: efuse@a4000 { - compatible = "qcom,ipq9574-qfprom", "qcom,qfprom"; - reg = <0x000a4000 0x5a1>; -@@ -311,10 +403,10 @@ - clocks = <&xo_board_clk>, - <&sleep_clk>, - <0>, -- <0>, -- <0>, -- <0>, -- <0>, -+ <&pcie0_phy>, -+ <&pcie1_phy>, -+ <&pcie2_phy>, -+ <&pcie3_phy>, - <0>; - #clock-cells = <1>; - #reset-cells = <1>; -@@ -758,6 +850,326 @@ - status = "disabled"; - }; - }; -+ -+ pcie1: pcie@10000000 { -+ compatible = "qcom,pcie-ipq9574"; -+ reg = <0x10000000 0xf1d>, -+ <0x10000f20 0xa8>, -+ <0x10001000 0x1000>, -+ <0x000f8000 0x4000>, -+ <0x10100000 0x1000>; -+ reg-names = "dbi", "elbi", "atu", "parf", "config"; -+ device_type = "pci"; -+ linux,pci-domain = <1>; -+ bus-range = <0x00 0xff>; -+ num-lanes = <1>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ ranges = <0x01000000 0x0 0x00000000 0x10200000 0x0 0x100000>, -+ <0x02000000 0x0 0x10300000 0x10300000 0x0 0x7d00000>; -+ -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "msi0", -+ "msi1", -+ "msi2", -+ "msi3", -+ "msi4", -+ "msi5", -+ "msi6", -+ "msi7"; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &intc 0 0 35 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 2 &intc 0 0 49 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 3 &intc 0 0 84 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 4 &intc 0 0 85 IRQ_TYPE_LEVEL_HIGH>; -+ -+ clocks = <&gcc GCC_PCIE1_AXI_M_CLK>, -+ <&gcc GCC_PCIE1_AXI_S_CLK>, -+ <&gcc GCC_PCIE1_AXI_S_BRIDGE_CLK>, -+ <&gcc GCC_PCIE1_RCHNG_CLK>, -+ <&gcc GCC_PCIE1_AHB_CLK>, -+ <&gcc GCC_PCIE1_AUX_CLK>; -+ clock-names = "axi_m", -+ "axi_s", -+ "axi_bridge", -+ "rchng", -+ "ahb", -+ "aux"; -+ -+ resets = <&gcc GCC_PCIE1_PIPE_ARES>, -+ <&gcc GCC_PCIE1_CORE_STICKY_ARES>, -+ <&gcc GCC_PCIE1_AXI_S_STICKY_ARES>, -+ <&gcc GCC_PCIE1_AXI_S_ARES>, -+ <&gcc GCC_PCIE1_AXI_M_STICKY_ARES>, -+ <&gcc GCC_PCIE1_AXI_M_ARES>, -+ <&gcc GCC_PCIE1_AUX_ARES>, -+ <&gcc GCC_PCIE1_AHB_ARES>; -+ reset-names = "pipe", -+ "sticky", -+ "axi_s_sticky", -+ "axi_s", -+ "axi_m_sticky", -+ "axi_m", -+ "aux", -+ "ahb"; -+ -+ phys = <&pcie1_phy>; -+ phy-names = "pciephy"; -+ interconnects = <&gcc MASTER_ANOC_PCIE1 &gcc SLAVE_ANOC_PCIE1>, -+ <&gcc MASTER_SNOC_PCIE1 &gcc SLAVE_SNOC_PCIE1>; -+ interconnect-names = "pcie-mem", "cpu-pcie"; -+ status = "disabled"; -+ }; -+ -+ pcie3: pcie@18000000 { -+ compatible = "qcom,pcie-ipq9574"; -+ reg = <0x18000000 0xf1d>, -+ <0x18000f20 0xa8>, -+ <0x18001000 0x1000>, -+ <0x000f0000 0x4000>, -+ <0x18100000 0x1000>; -+ reg-names = "dbi", "elbi", "atu", "parf", "config"; -+ device_type = "pci"; -+ linux,pci-domain = <3>; -+ bus-range = <0x00 0xff>; -+ num-lanes = <2>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ ranges = <0x01000000 0x0 0x00000000 0x18200000 0x0 0x100000>, -+ <0x02000000 0x0 0x18300000 0x18300000 0x0 0x7d00000>; -+ -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "msi0", -+ "msi1", -+ "msi2", -+ "msi3", -+ "msi4", -+ "msi5", -+ "msi6", -+ "msi7"; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &intc 0 0 189 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 2 &intc 0 0 190 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 3 &intc 0 0 191 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 4 &intc 0 0 192 IRQ_TYPE_LEVEL_HIGH>; -+ -+ clocks = <&gcc GCC_PCIE3_AXI_M_CLK>, -+ <&gcc GCC_PCIE3_AXI_S_CLK>, -+ <&gcc GCC_PCIE3_AXI_S_BRIDGE_CLK>, -+ <&gcc GCC_PCIE3_RCHNG_CLK>, -+ <&gcc GCC_PCIE3_AHB_CLK>, -+ <&gcc GCC_PCIE3_AUX_CLK>; -+ clock-names = "axi_m", -+ "axi_s", -+ "axi_bridge", -+ "rchng", -+ "ahb", -+ "aux"; -+ -+ resets = <&gcc GCC_PCIE3_PIPE_ARES>, -+ <&gcc GCC_PCIE3_CORE_STICKY_ARES>, -+ <&gcc GCC_PCIE3_AXI_S_STICKY_ARES>, -+ <&gcc GCC_PCIE3_AXI_S_ARES>, -+ <&gcc GCC_PCIE3_AXI_M_STICKY_ARES>, -+ <&gcc GCC_PCIE3_AXI_M_ARES>, -+ <&gcc GCC_PCIE3_AUX_ARES>, -+ <&gcc GCC_PCIE3_AHB_ARES>; -+ reset-names = "pipe", -+ "sticky", -+ "axi_s_sticky", -+ "axi_s", -+ "axi_m_sticky", -+ "axi_m", -+ "aux", -+ "ahb"; -+ -+ phys = <&pcie3_phy>; -+ phy-names = "pciephy"; -+ interconnects = <&gcc MASTER_ANOC_PCIE3 &gcc SLAVE_ANOC_PCIE3>, -+ <&gcc MASTER_SNOC_PCIE3 &gcc SLAVE_SNOC_PCIE3>; -+ interconnect-names = "pcie-mem", "cpu-pcie"; -+ status = "disabled"; -+ }; -+ -+ pcie2: pcie@20000000 { -+ compatible = "qcom,pcie-ipq9574"; -+ reg = <0x20000000 0xf1d>, -+ <0x20000f20 0xa8>, -+ <0x20001000 0x1000>, -+ <0x00088000 0x4000>, -+ <0x20100000 0x1000>; -+ reg-names = "dbi", "elbi", "atu", "parf", "config"; -+ device_type = "pci"; -+ linux,pci-domain = <2>; -+ bus-range = <0x00 0xff>; -+ num-lanes = <2>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ ranges = <0x01000000 0x0 0x00000000 0x20200000 0x0 0x100000>, -+ <0x02000000 0x0 0x20300000 0x20300000 0x0 0x7d00000>; -+ -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "msi0", -+ "msi1", -+ "msi2", -+ "msi3", -+ "msi4", -+ "msi5", -+ "msi6", -+ "msi7"; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &intc 0 0 164 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 2 &intc 0 0 165 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 3 &intc 0 0 186 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 4 &intc 0 0 187 IRQ_TYPE_LEVEL_HIGH>; -+ -+ clocks = <&gcc GCC_PCIE2_AXI_M_CLK>, -+ <&gcc GCC_PCIE2_AXI_S_CLK>, -+ <&gcc GCC_PCIE2_AXI_S_BRIDGE_CLK>, -+ <&gcc GCC_PCIE2_RCHNG_CLK>, -+ <&gcc GCC_PCIE2_AHB_CLK>, -+ <&gcc GCC_PCIE2_AUX_CLK>; -+ clock-names = "axi_m", -+ "axi_s", -+ "axi_bridge", -+ "rchng", -+ "ahb", -+ "aux"; -+ -+ resets = <&gcc GCC_PCIE2_PIPE_ARES>, -+ <&gcc GCC_PCIE2_CORE_STICKY_ARES>, -+ <&gcc GCC_PCIE2_AXI_S_STICKY_ARES>, -+ <&gcc GCC_PCIE2_AXI_S_ARES>, -+ <&gcc GCC_PCIE2_AXI_M_STICKY_ARES>, -+ <&gcc GCC_PCIE2_AXI_M_ARES>, -+ <&gcc GCC_PCIE2_AUX_ARES>, -+ <&gcc GCC_PCIE2_AHB_ARES>; -+ reset-names = "pipe", -+ "sticky", -+ "axi_s_sticky", -+ "axi_s", -+ "axi_m_sticky", -+ "axi_m", -+ "aux", -+ "ahb"; -+ -+ phys = <&pcie2_phy>; -+ phy-names = "pciephy"; -+ interconnects = <&gcc MASTER_ANOC_PCIE2 &gcc SLAVE_ANOC_PCIE2>, -+ <&gcc MASTER_SNOC_PCIE2 &gcc SLAVE_SNOC_PCIE2>; -+ interconnect-names = "pcie-mem", "cpu-pcie"; -+ status = "disabled"; -+ }; -+ -+ pcie0: pci@28000000 { -+ compatible = "qcom,pcie-ipq9574"; -+ reg = <0x28000000 0xf1d>, -+ <0x28000f20 0xa8>, -+ <0x28001000 0x1000>, -+ <0x00080000 0x4000>, -+ <0x28100000 0x1000>; -+ reg-names = "dbi", "elbi", "atu", "parf", "config"; -+ device_type = "pci"; -+ linux,pci-domain = <0>; -+ bus-range = <0x00 0xff>; -+ num-lanes = <1>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ ranges = <0x01000000 0x0 0x00000000 0x28200000 0x0 0x100000>, -+ <0x02000000 0x0 0x28300000 0x28300000 0x0 0x7d00000>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "msi0", -+ "msi1", -+ "msi2", -+ "msi3", -+ "msi4", -+ "msi5", -+ "msi6", -+ "msi7"; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &intc 0 0 75 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 2 &intc 0 0 78 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 3 &intc 0 0 79 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 4 &intc 0 0 83 IRQ_TYPE_LEVEL_HIGH>; -+ -+ clocks = <&gcc GCC_PCIE0_AXI_M_CLK>, -+ <&gcc GCC_PCIE0_AXI_S_CLK>, -+ <&gcc GCC_PCIE0_AXI_S_BRIDGE_CLK>, -+ <&gcc GCC_PCIE0_RCHNG_CLK>, -+ <&gcc GCC_PCIE0_AHB_CLK>, -+ <&gcc GCC_PCIE0_AUX_CLK>; -+ clock-names = "axi_m", -+ "axi_s", -+ "axi_bridge", -+ "rchng", -+ "ahb", -+ "aux"; -+ -+ resets = <&gcc GCC_PCIE0_PIPE_ARES>, -+ <&gcc GCC_PCIE0_CORE_STICKY_ARES>, -+ <&gcc GCC_PCIE0_AXI_S_STICKY_ARES>, -+ <&gcc GCC_PCIE0_AXI_S_ARES>, -+ <&gcc GCC_PCIE0_AXI_M_STICKY_ARES>, -+ <&gcc GCC_PCIE0_AXI_M_ARES>, -+ <&gcc GCC_PCIE0_AUX_ARES>, -+ <&gcc GCC_PCIE0_AHB_ARES>; -+ reset-names = "pipe", -+ "sticky", -+ "axi_s_sticky", -+ "axi_s", -+ "axi_m_sticky", -+ "axi_m", -+ "aux", -+ "ahb"; -+ -+ phys = <&pcie0_phy>; -+ phy-names = "pciephy"; -+ interconnects = <&gcc MASTER_ANOC_PCIE0 &gcc SLAVE_ANOC_PCIE0>, -+ <&gcc MASTER_SNOC_PCIE0 &gcc SLAVE_SNOC_PCIE0>; -+ interconnect-names = "pcie-mem", "cpu-pcie"; -+ status = "disabled"; -+ }; -+ - }; - - thermal-zones { diff --git a/target/linux/qualcommbe/patches-6.12/0005-v6.14-arm64-dts-qcom-ipq9574-Enable-PCIe-PHYs-and-co.patch b/target/linux/qualcommbe/patches-6.12/0005-v6.14-arm64-dts-qcom-ipq9574-Enable-PCIe-PHYs-and-co.patch deleted file mode 100644 index f07e422966..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0005-v6.14-arm64-dts-qcom-ipq9574-Enable-PCIe-PHYs-and-co.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 695cb0b8f9c525fe6d3ffbc349bc6087acd71201 Mon Sep 17 00:00:00 2001 -From: devi priya -Date: Thu, 1 Aug 2024 11:18:02 +0530 -Subject: [PATCH 05/22] v6.14: arm64: dts: qcom: ipq9574: Enable PCIe PHYs and - controllers - -Enable the PCIe controller and PHY nodes corresponding to RDP 433. - -Signed-off-by: devi priya -Signed-off-by: Sricharan Ramabadhran -Link: https://lore.kernel.org/r/20240801054803.3015572-4-quic_srichara@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 113 ++++++++++++++++++++ - 1 file changed, 113 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -@@ -8,6 +8,7 @@ - - /dts-v1/; - -+#include - #include "ipq9574-rdp-common.dtsi" - - / { -@@ -15,6 +16,45 @@ - compatible = "qcom,ipq9574-ap-al02-c7", "qcom,ipq9574"; - }; - -+&pcie1_phy { -+ status = "okay"; -+}; -+ -+&pcie1 { -+ pinctrl-0 = <&pcie1_default>; -+ pinctrl-names = "default"; -+ -+ perst-gpios = <&tlmm 26 GPIO_ACTIVE_LOW>; -+ wake-gpios = <&tlmm 27 GPIO_ACTIVE_LOW>; -+ status = "okay"; -+}; -+ -+&pcie2_phy { -+ status = "okay"; -+}; -+ -+&pcie2 { -+ pinctrl-0 = <&pcie2_default>; -+ pinctrl-names = "default"; -+ -+ perst-gpios = <&tlmm 29 GPIO_ACTIVE_LOW>; -+ wake-gpios = <&tlmm 30 GPIO_ACTIVE_LOW>; -+ status = "okay"; -+}; -+ -+&pcie3_phy { -+ status = "okay"; -+}; -+ -+&pcie3 { -+ pinctrl-0 = <&pcie3_default>; -+ pinctrl-names = "default"; -+ -+ perst-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; -+ wake-gpios = <&tlmm 33 GPIO_ACTIVE_LOW>; -+ status = "okay"; -+}; -+ - &sdhc_1 { - pinctrl-0 = <&sdc_default_state>; - pinctrl-names = "default"; -@@ -28,6 +68,79 @@ - }; - - &tlmm { -+ -+ pcie1_default: pcie1-default-state { -+ clkreq-n-pins { -+ pins = "gpio25"; -+ function = "pcie1_clk"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ -+ perst-n-pins { -+ pins = "gpio26"; -+ function = "gpio"; -+ drive-strength = <8>; -+ bias-pull-down; -+ output-low; -+ }; -+ -+ wake-n-pins { -+ pins = "gpio27"; -+ function = "pcie1_wake"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ }; -+ -+ pcie2_default: pcie2-default-state { -+ clkreq-n-pins { -+ pins = "gpio28"; -+ function = "pcie2_clk"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ -+ perst-n-pins { -+ pins = "gpio29"; -+ function = "gpio"; -+ drive-strength = <8>; -+ bias-pull-down; -+ output-low; -+ }; -+ -+ wake-n-pins { -+ pins = "gpio30"; -+ function = "pcie2_wake"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ }; -+ -+ pcie3_default: pcie3-default-state { -+ clkreq-n-pins { -+ pins = "gpio31"; -+ function = "pcie3_clk"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ -+ perst-n-pins { -+ pins = "gpio32"; -+ function = "gpio"; -+ drive-strength = <8>; -+ bias-pull-up; -+ output-low; -+ }; -+ -+ wake-n-pins { -+ pins = "gpio33"; -+ function = "pcie3_wake"; -+ drive-strength = <6>; -+ bias-pull-up; -+ }; -+ }; -+ - sdc_default_state: sdc-default-state { - clk-pins { - pins = "gpio5"; diff --git a/target/linux/qualcommbe/patches-6.12/0006-v6.14-dt-bindings-clock-qcom-Add-CMN-PLL-clock-contr.patch b/target/linux/qualcommbe/patches-6.12/0006-v6.14-dt-bindings-clock-qcom-Add-CMN-PLL-clock-contr.patch deleted file mode 100644 index f0087764a1..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0006-v6.14-dt-bindings-clock-qcom-Add-CMN-PLL-clock-contr.patch +++ /dev/null @@ -1,132 +0,0 @@ -From f4b785b3360c594bb10bd6f1dc5096b3e93f86d9 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Fri, 3 Jan 2025 15:31:34 +0800 -Subject: [PATCH 06/22] v6.14: dt-bindings: clock: qcom: Add CMN PLL clock - controller for IPQ SoC - -The CMN PLL controller provides clocks to networking hardware blocks -and to GCC on Qualcomm IPQ9574 SoC. It receives input clock from the -on-chip Wi-Fi, and produces output clocks at fixed rates. These output -rates are predetermined, and are unrelated to the input clock rate. -The primary purpose of CMN PLL is to supply clocks to the networking -hardware such as PPE (packet process engine), PCS and the externally -connected switch or PHY device. The CMN PLL block also outputs fixed -rate clocks to GCC, such as 24 MHZ as XO clock and 32 KHZ as sleep -clock supplied to GCC. - -Signed-off-by: Luo Jie -Reviewed-by: Krzysztof Kozlowski -Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-1-c89fb4d4849d@quicinc.com -Signed-off-by: Bjorn Andersson ---- - .../bindings/clock/qcom,ipq9574-cmn-pll.yaml | 77 +++++++++++++++++++ - include/dt-bindings/clock/qcom,ipq-cmn-pll.h | 22 ++++++ - 2 files changed, 99 insertions(+) - create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml - create mode 100644 include/dt-bindings/clock/qcom,ipq-cmn-pll.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml -@@ -0,0 +1,77 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/clock/qcom,ipq9574-cmn-pll.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm CMN PLL Clock Controller on IPQ SoC -+ -+maintainers: -+ - Bjorn Andersson -+ - Luo Jie -+ -+description: -+ The CMN (or common) PLL clock controller expects a reference -+ input clock. This reference clock is from the on-board Wi-Fi. -+ The CMN PLL supplies a number of fixed rate output clocks to -+ the devices providing networking functions and to GCC. These -+ networking hardware include PPE (packet process engine), PCS -+ and the externally connected switch or PHY devices. The CMN -+ PLL block also outputs fixed rate clocks to GCC. The PLL's -+ primary function is to enable fixed rate output clocks for -+ networking hardware functions used with the IPQ SoC. -+ -+properties: -+ compatible: -+ enum: -+ - qcom,ipq9574-cmn-pll -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ items: -+ - description: The reference clock. The supported clock rates include -+ 25000000, 31250000, 40000000, 48000000, 50000000 and 96000000 HZ. -+ - description: The AHB clock -+ - description: The SYS clock -+ description: -+ The reference clock is the source clock of CMN PLL, which is from the -+ Wi-Fi. The AHB and SYS clocks must be enabled to access CMN PLL -+ clock registers. -+ -+ clock-names: -+ items: -+ - const: ref -+ - const: ahb -+ - const: sys -+ -+ "#clock-cells": -+ const: 1 -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - clock-names -+ - "#clock-cells" -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ -+ cmn_pll: clock-controller@9b000 { -+ compatible = "qcom,ipq9574-cmn-pll"; -+ reg = <0x0009b000 0x800>; -+ clocks = <&cmn_pll_ref_clk>, -+ <&gcc GCC_CMN_12GPLL_AHB_CLK>, -+ <&gcc GCC_CMN_12GPLL_SYS_CLK>; -+ clock-names = "ref", "ahb", "sys"; -+ #clock-cells = <1>; -+ assigned-clocks = <&cmn_pll CMN_PLL_CLK>; -+ assigned-clock-rates-u64 = /bits/ 64 <12000000000>; -+ }; -+... ---- /dev/null -+++ b/include/dt-bindings/clock/qcom,ipq-cmn-pll.h -@@ -0,0 +1,22 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef _DT_BINDINGS_CLK_QCOM_IPQ_CMN_PLL_H -+#define _DT_BINDINGS_CLK_QCOM_IPQ_CMN_PLL_H -+ -+/* CMN PLL core clock. */ -+#define CMN_PLL_CLK 0 -+ -+/* The output clocks from CMN PLL of IPQ9574. */ -+#define XO_24MHZ_CLK 1 -+#define SLEEP_32KHZ_CLK 2 -+#define PCS_31P25MHZ_CLK 3 -+#define NSS_1200MHZ_CLK 4 -+#define PPE_353MHZ_CLK 5 -+#define ETH0_50MHZ_CLK 6 -+#define ETH1_50MHZ_CLK 7 -+#define ETH2_50MHZ_CLK 8 -+#define ETH_25MHZ_CLK 9 -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0007-v6.14-clk-qcom-Add-CMN-PLL-clock-controller-driver-f.patch b/target/linux/qualcommbe/patches-6.12/0007-v6.14-clk-qcom-Add-CMN-PLL-clock-controller-driver-f.patch deleted file mode 100644 index edbbf8e13d..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0007-v6.14-clk-qcom-Add-CMN-PLL-clock-controller-driver-f.patch +++ /dev/null @@ -1,501 +0,0 @@ -From 51c937f5d7a3b239b637555bbd4dc0017b5cccba Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Fri, 3 Jan 2025 15:31:35 +0800 -Subject: [PATCH 07/22] v6.14: clk: qcom: Add CMN PLL clock controller driver - for IPQ SoC - -The CMN PLL clock controller supplies clocks to the hardware -blocks that together make up the Ethernet function on Qualcomm -IPQ SoCs and to GCC. The driver is initially supported for -IPQ9574 SoC. - -The CMN PLL clock controller expects a reference input clock -from the on-board Wi-Fi block acting as clock source. The input -reference clock needs to be configured to one of the supported -clock rates. - -The controller supplies a number of fixed-rate output clocks. -For the IPQ9574, there is one output clock of 353 MHZ to PPE -(Packet Process Engine) hardware block, three 50 MHZ output -clocks and an additional 25 MHZ output clock supplied to the -connected Ethernet devices. The PLL also supplies a 24 MHZ -clock as XO and a 32 KHZ sleep clock to GCC, and one 31.25 -MHZ clock to PCS. - -Signed-off-by: Luo Jie -Acked-by: Konrad Dybcio -Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-2-c89fb4d4849d@quicinc.com -Signed-off-by: Bjorn Andersson ---- - drivers/clk/qcom/Kconfig | 9 + - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/ipq-cmn-pll.c | 435 +++++++++++++++++++++++++++++++++ - 3 files changed, 445 insertions(+) - create mode 100644 drivers/clk/qcom/ipq-cmn-pll.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -190,6 +190,15 @@ config IPQ_APSS_6018 - Say Y if you want to support CPU frequency scaling on - ipq based devices. - -+config IPQ_CMN_PLL -+ tristate "IPQ CMN PLL Clock Controller" -+ help -+ Support for CMN PLL clock controller on IPQ platform. The -+ CMN PLL consumes the AHB/SYS clocks from GCC and supplies -+ the output clocks to the networking hardware and GCC blocks. -+ Say Y or M if you want to support CMN PLL clock on the IPQ -+ based devices. -+ - config IPQ_GCC_4019 - tristate "IPQ4019 Global Clock Controller" - help ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -29,6 +29,7 @@ obj-$(CONFIG_CLK_X1E80100_TCSRCC) += tcs - obj-$(CONFIG_CLK_QCM2290_GPUCC) += gpucc-qcm2290.o - obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o - obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o -+obj-$(CONFIG_IPQ_CMN_PLL) += ipq-cmn-pll.o - obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o - obj-$(CONFIG_IPQ_GCC_5018) += gcc-ipq5018.o - obj-$(CONFIG_IPQ_GCC_5332) += gcc-ipq5332.o ---- /dev/null -+++ b/drivers/clk/qcom/ipq-cmn-pll.c -@@ -0,0 +1,435 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* -+ * CMN PLL block expects the reference clock from on-board Wi-Fi block, -+ * and supplies fixed rate clocks as output to the networking hardware -+ * blocks and to GCC. The networking related blocks include PPE (packet -+ * process engine), the externally connected PHY or switch devices, and -+ * the PCS. -+ * -+ * On the IPQ9574 SoC, there are three clocks with 50 MHZ and one clock -+ * with 25 MHZ which are output from the CMN PLL to Ethernet PHY (or switch), -+ * and one clock with 353 MHZ to PPE. The other fixed rate output clocks -+ * are supplied to GCC (24 MHZ as XO and 32 KHZ as sleep clock), and to PCS -+ * with 31.25 MHZ. -+ * -+ * +---------+ -+ * | GCC | -+ * +--+---+--+ -+ * AHB CLK| |SYS CLK -+ * V V -+ * +-------+---+------+ -+ * | +-------------> eth0-50mhz -+ * REF CLK | IPQ9574 | -+ * -------->+ +-------------> eth1-50mhz -+ * | CMN PLL block | -+ * | +-------------> eth2-50mhz -+ * | | -+ * +----+----+----+---+-------------> eth-25mhz -+ * | | | -+ * V V V -+ * GCC PCS NSS/PPE -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define CMN_PLL_REFCLK_SRC_SELECTION 0x28 -+#define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8) -+ -+#define CMN_PLL_LOCKED 0x64 -+#define CMN_PLL_CLKS_LOCKED BIT(8) -+ -+#define CMN_PLL_POWER_ON_AND_RESET 0x780 -+#define CMN_ANA_EN_SW_RSTN BIT(6) -+ -+#define CMN_PLL_REFCLK_CONFIG 0x784 -+#define CMN_PLL_REFCLK_EXTERNAL BIT(9) -+#define CMN_PLL_REFCLK_DIV GENMASK(8, 4) -+#define CMN_PLL_REFCLK_INDEX GENMASK(3, 0) -+ -+#define CMN_PLL_CTRL 0x78c -+#define CMN_PLL_CTRL_LOCK_DETECT_EN BIT(15) -+ -+#define CMN_PLL_DIVIDER_CTRL 0x794 -+#define CMN_PLL_DIVIDER_CTRL_FACTOR GENMASK(9, 0) -+ -+/** -+ * struct cmn_pll_fixed_output_clk - CMN PLL output clocks information -+ * @id: Clock specifier to be supplied -+ * @name: Clock name to be registered -+ * @rate: Clock rate -+ */ -+struct cmn_pll_fixed_output_clk { -+ unsigned int id; -+ const char *name; -+ unsigned long rate; -+}; -+ -+/** -+ * struct clk_cmn_pll - CMN PLL hardware specific data -+ * @regmap: hardware regmap. -+ * @hw: handle between common and hardware-specific interfaces -+ */ -+struct clk_cmn_pll { -+ struct regmap *regmap; -+ struct clk_hw hw; -+}; -+ -+#define CLK_PLL_OUTPUT(_id, _name, _rate) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .rate = _rate, \ -+} -+ -+#define to_clk_cmn_pll(_hw) container_of(_hw, struct clk_cmn_pll, hw) -+ -+static const struct regmap_config ipq_cmn_pll_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = 0x7fc, -+ .fast_io = true, -+}; -+ -+static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = { -+ CLK_PLL_OUTPUT(XO_24MHZ_CLK, "xo-24mhz", 24000000UL), -+ CLK_PLL_OUTPUT(SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL), -+ CLK_PLL_OUTPUT(PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL), -+ CLK_PLL_OUTPUT(NSS_1200MHZ_CLK, "nss-1200mhz", 1200000000UL), -+ CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL), -+ CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL), -+ CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL), -+ CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL), -+ CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL), -+}; -+ -+/* -+ * CMN PLL has the single parent clock, which supports the several -+ * possible parent clock rates, each parent clock rate is reflected -+ * by the specific reference index value in the hardware. -+ */ -+static int ipq_cmn_pll_find_freq_index(unsigned long parent_rate) -+{ -+ int index = -EINVAL; -+ -+ switch (parent_rate) { -+ case 25000000: -+ index = 3; -+ break; -+ case 31250000: -+ index = 4; -+ break; -+ case 40000000: -+ index = 6; -+ break; -+ case 48000000: -+ case 96000000: -+ /* -+ * Parent clock rate 48 MHZ and 96 MHZ take the same value -+ * of reference clock index. 96 MHZ needs the source clock -+ * divider to be programmed as 2. -+ */ -+ index = 7; -+ break; -+ case 50000000: -+ index = 8; -+ break; -+ default: -+ break; -+ } -+ -+ return index; -+} -+ -+static unsigned long clk_cmn_pll_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw); -+ u32 val, factor; -+ -+ /* -+ * The value of CMN_PLL_DIVIDER_CTRL_FACTOR is automatically adjusted -+ * by HW according to the parent clock rate. -+ */ -+ regmap_read(cmn_pll->regmap, CMN_PLL_DIVIDER_CTRL, &val); -+ factor = FIELD_GET(CMN_PLL_DIVIDER_CTRL_FACTOR, val); -+ -+ return parent_rate * 2 * factor; -+} -+ -+static int clk_cmn_pll_determine_rate(struct clk_hw *hw, -+ struct clk_rate_request *req) -+{ -+ int ret; -+ -+ /* Validate the rate of the single parent clock. */ -+ ret = ipq_cmn_pll_find_freq_index(req->best_parent_rate); -+ -+ return ret < 0 ? ret : 0; -+} -+ -+/* -+ * This function is used to initialize the CMN PLL to enable the fixed -+ * rate output clocks. It is expected to be configured once. -+ */ -+static int clk_cmn_pll_set_rate(struct clk_hw *hw, unsigned long rate, -+ unsigned long parent_rate) -+{ -+ struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw); -+ int ret, index; -+ u32 val; -+ -+ /* -+ * Configure the reference input clock selection as per the given -+ * parent clock. The output clock rates are always of fixed value. -+ */ -+ index = ipq_cmn_pll_find_freq_index(parent_rate); -+ if (index < 0) -+ return index; -+ -+ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG, -+ CMN_PLL_REFCLK_INDEX, -+ FIELD_PREP(CMN_PLL_REFCLK_INDEX, index)); -+ if (ret) -+ return ret; -+ -+ /* -+ * Update the source clock rate selection and source clock -+ * divider as 2 when the parent clock rate is 96 MHZ. -+ */ -+ if (parent_rate == 96000000) { -+ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG, -+ CMN_PLL_REFCLK_DIV, -+ FIELD_PREP(CMN_PLL_REFCLK_DIV, 2)); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_SRC_SELECTION, -+ CMN_PLL_REFCLK_SRC_DIV, -+ FIELD_PREP(CMN_PLL_REFCLK_SRC_DIV, 0)); -+ if (ret) -+ return ret; -+ } -+ -+ /* Enable PLL locked detect. */ -+ ret = regmap_set_bits(cmn_pll->regmap, CMN_PLL_CTRL, -+ CMN_PLL_CTRL_LOCK_DETECT_EN); -+ if (ret) -+ return ret; -+ -+ /* -+ * Reset the CMN PLL block to ensure the updated configurations -+ * take effect. -+ */ -+ ret = regmap_clear_bits(cmn_pll->regmap, CMN_PLL_POWER_ON_AND_RESET, -+ CMN_ANA_EN_SW_RSTN); -+ if (ret) -+ return ret; -+ -+ usleep_range(1000, 1200); -+ ret = regmap_set_bits(cmn_pll->regmap, CMN_PLL_POWER_ON_AND_RESET, -+ CMN_ANA_EN_SW_RSTN); -+ if (ret) -+ return ret; -+ -+ /* Stability check of CMN PLL output clocks. */ -+ return regmap_read_poll_timeout(cmn_pll->regmap, CMN_PLL_LOCKED, val, -+ (val & CMN_PLL_CLKS_LOCKED), -+ 100, 100 * USEC_PER_MSEC); -+} -+ -+static const struct clk_ops clk_cmn_pll_ops = { -+ .recalc_rate = clk_cmn_pll_recalc_rate, -+ .determine_rate = clk_cmn_pll_determine_rate, -+ .set_rate = clk_cmn_pll_set_rate, -+}; -+ -+static struct clk_hw *ipq_cmn_pll_clk_hw_register(struct platform_device *pdev) -+{ -+ struct clk_parent_data pdata = { .index = 0 }; -+ struct device *dev = &pdev->dev; -+ struct clk_init_data init = {}; -+ struct clk_cmn_pll *cmn_pll; -+ struct regmap *regmap; -+ void __iomem *base; -+ int ret; -+ -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return ERR_CAST(base); -+ -+ regmap = devm_regmap_init_mmio(dev, base, &ipq_cmn_pll_regmap_config); -+ if (IS_ERR(regmap)) -+ return ERR_CAST(regmap); -+ -+ cmn_pll = devm_kzalloc(dev, sizeof(*cmn_pll), GFP_KERNEL); -+ if (!cmn_pll) -+ return ERR_PTR(-ENOMEM); -+ -+ init.name = "cmn_pll"; -+ init.parent_data = &pdata; -+ init.num_parents = 1; -+ init.ops = &clk_cmn_pll_ops; -+ -+ cmn_pll->hw.init = &init; -+ cmn_pll->regmap = regmap; -+ -+ ret = devm_clk_hw_register(dev, &cmn_pll->hw); -+ if (ret) -+ return ERR_PTR(ret); -+ -+ return &cmn_pll->hw; -+} -+ -+static int ipq_cmn_pll_register_clks(struct platform_device *pdev) -+{ -+ const struct cmn_pll_fixed_output_clk *fixed_clk; -+ struct clk_hw_onecell_data *hw_data; -+ struct device *dev = &pdev->dev; -+ struct clk_hw *cmn_pll_hw; -+ unsigned int num_clks; -+ struct clk_hw *hw; -+ int ret, i; -+ -+ fixed_clk = ipq9574_output_clks; -+ num_clks = ARRAY_SIZE(ipq9574_output_clks); -+ -+ hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, num_clks + 1), -+ GFP_KERNEL); -+ if (!hw_data) -+ return -ENOMEM; -+ -+ /* -+ * Register the CMN PLL clock, which is the parent clock of -+ * the fixed rate output clocks. -+ */ -+ cmn_pll_hw = ipq_cmn_pll_clk_hw_register(pdev); -+ if (IS_ERR(cmn_pll_hw)) -+ return PTR_ERR(cmn_pll_hw); -+ -+ /* Register the fixed rate output clocks. */ -+ for (i = 0; i < num_clks; i++) { -+ hw = clk_hw_register_fixed_rate_parent_hw(dev, fixed_clk[i].name, -+ cmn_pll_hw, 0, -+ fixed_clk[i].rate); -+ if (IS_ERR(hw)) { -+ ret = PTR_ERR(hw); -+ goto unregister_fixed_clk; -+ } -+ -+ hw_data->hws[fixed_clk[i].id] = hw; -+ } -+ -+ /* -+ * Provide the CMN PLL clock. The clock rate of CMN PLL -+ * is configured to 12 GHZ by DT property assigned-clock-rates-u64. -+ */ -+ hw_data->hws[CMN_PLL_CLK] = cmn_pll_hw; -+ hw_data->num = num_clks + 1; -+ -+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data); -+ if (ret) -+ goto unregister_fixed_clk; -+ -+ platform_set_drvdata(pdev, hw_data); -+ -+ return 0; -+ -+unregister_fixed_clk: -+ while (i > 0) -+ clk_hw_unregister(hw_data->hws[fixed_clk[--i].id]); -+ -+ return ret; -+} -+ -+static int ipq_cmn_pll_clk_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ int ret; -+ -+ ret = devm_pm_runtime_enable(dev); -+ if (ret) -+ return ret; -+ -+ ret = devm_pm_clk_create(dev); -+ if (ret) -+ return ret; -+ -+ /* -+ * To access the CMN PLL registers, the GCC AHB & SYS clocks -+ * of CMN PLL block need to be enabled. -+ */ -+ ret = pm_clk_add(dev, "ahb"); -+ if (ret) -+ return dev_err_probe(dev, ret, "Fail to add AHB clock\n"); -+ -+ ret = pm_clk_add(dev, "sys"); -+ if (ret) -+ return dev_err_probe(dev, ret, "Fail to add SYS clock\n"); -+ -+ ret = pm_runtime_resume_and_get(dev); -+ if (ret) -+ return ret; -+ -+ /* Register CMN PLL clock and fixed rate output clocks. */ -+ ret = ipq_cmn_pll_register_clks(pdev); -+ pm_runtime_put(dev); -+ if (ret) -+ return dev_err_probe(dev, ret, -+ "Fail to register CMN PLL clocks\n"); -+ -+ return 0; -+} -+ -+static void ipq_cmn_pll_clk_remove(struct platform_device *pdev) -+{ -+ struct clk_hw_onecell_data *hw_data = platform_get_drvdata(pdev); -+ int i; -+ -+ /* -+ * The clock with index CMN_PLL_CLK is unregistered by -+ * device management. -+ */ -+ for (i = 0; i < hw_data->num; i++) { -+ if (i != CMN_PLL_CLK) -+ clk_hw_unregister(hw_data->hws[i]); -+ } -+} -+ -+static const struct dev_pm_ops ipq_cmn_pll_pm_ops = { -+ SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) -+}; -+ -+static const struct of_device_id ipq_cmn_pll_clk_ids[] = { -+ { .compatible = "qcom,ipq9574-cmn-pll", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ipq_cmn_pll_clk_ids); -+ -+static struct platform_driver ipq_cmn_pll_clk_driver = { -+ .probe = ipq_cmn_pll_clk_probe, -+ .remove = ipq_cmn_pll_clk_remove, -+ .driver = { -+ .name = "ipq_cmn_pll", -+ .of_match_table = ipq_cmn_pll_clk_ids, -+ .pm = &ipq_cmn_pll_pm_ops, -+ }, -+}; -+module_platform_driver(ipq_cmn_pll_clk_driver); -+ -+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ CMN PLL Driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/qualcommbe/patches-6.12/0008-v6.14-arm64-dts-qcom-ipq9574-Add-CMN-PLL-node.patch b/target/linux/qualcommbe/patches-6.12/0008-v6.14-arm64-dts-qcom-ipq9574-Add-CMN-PLL-node.patch deleted file mode 100644 index b29bbda235..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0008-v6.14-arm64-dts-qcom-ipq9574-Add-CMN-PLL-node.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 20a3597d994c8ac372bbb66d9f11bccb7f405154 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Fri, 3 Jan 2025 15:31:37 +0800 -Subject: [PATCH 08/22] v6.14: arm64: dts: qcom: ipq9574: Add CMN PLL node - -The CMN PLL clock controller allows selection of an input clock rate -from a defined set of input clock rates. It in-turn supplies fixed -rate output clocks to the hardware blocks that provide the ethernet -functions such as PPE (Packet Process Engine) and connected switch or -PHY, and to GCC. - -The reference clock of CMN PLL is routed from XO to the CMN PLL through -the internal WiFi block. -.XO (48 MHZ or 96 MHZ)-->WiFi (multiplier/divider)-->48 MHZ to CMN PLL. - -The reference input clock from WiFi to CMN PLL is fully controlled by -the bootstrap pins which select the XO frequency (48 MHZ or 96 MHZ). -Based on this frequency, the divider in the internal Wi-Fi block is -automatically configured by hardware (1 for 48 MHZ, 2 for 96 MHZ), to -ensure output clock to CMN PLL is 48 MHZ. - -Signed-off-by: Luo Jie -Reviewed-by: Konrad Dybcio -Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-4-c89fb4d4849d@quicinc.com -Signed-off-by: Bjorn Andersson ---- - .../boot/dts/qcom/ipq9574-rdp-common.dtsi | 17 +++++++++++- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 26 ++++++++++++++++++- - 2 files changed, 41 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -@@ -3,7 +3,7 @@ - * IPQ9574 RDP board common device tree source - * - * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. -- * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved. - */ - - /dts-v1/; -@@ -171,6 +171,21 @@ - status = "okay"; - }; - -+/* -+ * The bootstrap pins for the board select the XO clock frequency -+ * (48 MHZ or 96 MHZ used for different RDP type board). This setting -+ * automatically enables the right dividers, to ensure the reference -+ * clock output from WiFi to the CMN PLL is 48 MHZ. -+ */ -+&ref_48mhz_clk { -+ clock-div = <1>; -+ clock-mult = <1>; -+}; -+ - &xo_board_clk { - clock-frequency = <24000000>; - }; -+ -+&xo_clk { -+ clock-frequency = <48000000>; -+}; ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -3,10 +3,11 @@ - * IPQ9574 SoC device tree source - * - * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. -- * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved. - */ - - #include -+#include - #include - #include - #include -@@ -19,6 +20,12 @@ - #size-cells = <2>; - - clocks { -+ ref_48mhz_clk: ref-48mhz-clk { -+ compatible = "fixed-factor-clock"; -+ clocks = <&xo_clk>; -+ #clock-cells = <0>; -+ }; -+ - sleep_clk: sleep-clk { - compatible = "fixed-clock"; - #clock-cells = <0>; -@@ -28,6 +35,11 @@ - compatible = "fixed-clock"; - #clock-cells = <0>; - }; -+ -+ xo_clk: xo-clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ }; - }; - - cpus { -@@ -335,6 +347,18 @@ - status = "disabled"; - }; - -+ cmn_pll: clock-controller@9b000 { -+ compatible = "qcom,ipq9574-cmn-pll"; -+ reg = <0x0009b000 0x800>; -+ clocks = <&ref_48mhz_clk>, -+ <&gcc GCC_CMN_12GPLL_AHB_CLK>, -+ <&gcc GCC_CMN_12GPLL_SYS_CLK>; -+ clock-names = "ref", "ahb", "sys"; -+ #clock-cells = <1>; -+ assigned-clocks = <&cmn_pll CMN_PLL_CLK>; -+ assigned-clock-rates-u64 = /bits/ 64 <12000000000>; -+ }; -+ - qfprom: efuse@a4000 { - compatible = "qcom,ipq9574-qfprom", "qcom,qfprom"; - reg = <0x000a4000 0x5a1>; diff --git a/target/linux/qualcommbe/patches-6.12/0009-v6.14-arm64-dts-qcom-ipq9574-Update-xo_board_clk-to-.patch b/target/linux/qualcommbe/patches-6.12/0009-v6.14-arm64-dts-qcom-ipq9574-Update-xo_board_clk-to-.patch deleted file mode 100644 index 0268c5c28e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0009-v6.14-arm64-dts-qcom-ipq9574-Update-xo_board_clk-to-.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 62307c5e153de617cb0827509fb964df051caaac Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Fri, 3 Jan 2025 15:31:38 +0800 -Subject: [PATCH 09/22] v6.14: arm64: dts: qcom: ipq9574: Update xo_board_clk - to use fixed factor clock - -xo_board_clk is fixed to 24 MHZ, which is routed from WiFi output clock -48 MHZ (also being the reference clock of CMN PLL) divided 2 by analog -block routing channel. - -Reviewed-by: Konrad Dybcio -Signed-off-by: Luo Jie -Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-5-c89fb4d4849d@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi | 7 ++++++- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 3 ++- - 2 files changed, 8 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -@@ -182,8 +182,13 @@ - clock-mult = <1>; - }; - -+/* -+ * The frequency of xo_board_clk is fixed to 24 MHZ, which is routed -+ * from WiFi output clock 48 MHZ divided by 2. -+ */ - &xo_board_clk { -- clock-frequency = <24000000>; -+ clock-div = <2>; -+ clock-mult = <1>; - }; - - &xo_clk { ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -32,7 +32,8 @@ - }; - - xo_board_clk: xo-board-clk { -- compatible = "fixed-clock"; -+ compatible = "fixed-factor-clock"; -+ clocks = <&ref_48mhz_clk>; - #clock-cells = <0>; - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0016-v6.15-spi-dt-bindings-Introduce-qcom-spi-qpic-snand.patch b/target/linux/qualcommbe/patches-6.12/0016-v6.15-spi-dt-bindings-Introduce-qcom-spi-qpic-snand.patch deleted file mode 100644 index 6a1627a67e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0016-v6.15-spi-dt-bindings-Introduce-qcom-spi-qpic-snand.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 66fde1c5d29006127cc4fc5a12a0c42415c098bd Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Mon, 24 Feb 2025 16:44:13 +0530 -Subject: [PATCH 16/22] v6.15: spi: dt-bindings: Introduce qcom,spi-qpic-snand - -Document the QPIC-SPI-NAND flash controller present in the IPQ SoCs. -It can work both in serial and parallel mode and supports typical -SPI-NAND page cache operations. - -Reviewed-by: Krzysztof Kozlowski -Reviewed-by: Rob Herring (Arm) -Signed-off-by: Md Sadre Alam -Link: https://patch.msgid.link/20250224111414.2809669-2-quic_mdalam@quicinc.com -Signed-off-by: Mark Brown ---- - .../bindings/spi/qcom,spi-qpic-snand.yaml | 83 +++++++++++++++++++ - 1 file changed, 83 insertions(+) - create mode 100644 Documentation/devicetree/bindings/spi/qcom,spi-qpic-snand.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qpic-snand.yaml -@@ -0,0 +1,83 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/spi/qcom,spi-qpic-snand.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm QPIC NAND controller -+ -+maintainers: -+ - Md sadre Alam -+ -+description: -+ The QCOM QPIC-SPI-NAND flash controller is an extended version of -+ the QCOM QPIC NAND flash controller. It can work both in serial -+ and parallel mode. It supports typical SPI-NAND page cache -+ operations in single, dual or quad IO mode with pipelined ECC -+ encoding/decoding using the QPIC ECC HW engine. -+ -+allOf: -+ - $ref: /schemas/spi/spi-controller.yaml# -+ -+properties: -+ compatible: -+ enum: -+ - qcom,ipq9574-snand -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ maxItems: 3 -+ -+ clock-names: -+ items: -+ - const: core -+ - const: aon -+ - const: iom -+ -+ dmas: -+ items: -+ - description: tx DMA channel -+ - description: rx DMA channel -+ - description: cmd DMA channel -+ -+ dma-names: -+ items: -+ - const: tx -+ - const: rx -+ - const: cmd -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - clock-names -+ -+unevaluatedProperties: false -+ -+examples: -+ - | -+ #include -+ spi@79b0000 { -+ compatible = "qcom,ipq9574-snand"; -+ reg = <0x1ac00000 0x800>; -+ -+ clocks = <&gcc GCC_QPIC_CLK>, -+ <&gcc GCC_QPIC_AHB_CLK>, -+ <&gcc GCC_QPIC_IO_MACRO_CLK>; -+ clock-names = "core", "aon", "iom"; -+ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ flash@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ nand-ecc-engine = <&qpic_nand>; -+ nand-ecc-strength = <4>; -+ nand-ecc-step-size = <512>; -+ }; -+ }; diff --git a/target/linux/qualcommbe/patches-6.12/0018-v6.15-dt-bindings-clock-gcc-ipq9574-Add-definition-f.patch b/target/linux/qualcommbe/patches-6.12/0018-v6.15-dt-bindings-clock-gcc-ipq9574-Add-definition-f.patch deleted file mode 100644 index dfe655df94..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0018-v6.15-dt-bindings-clock-gcc-ipq9574-Add-definition-f.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 25ce13ad8852f14835e650132ccf4fc0bf127699 Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:54 +0530 -Subject: [PATCH 18/22] v6.15: dt-bindings: clock: gcc-ipq9574: Add definition - for GPLL0_OUT_AUX - -Add the definition for GPLL0_OUT_AUX clock. - -Acked-by: Krzysztof Kozlowski -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-2-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - include/dt-bindings/clock/qcom,ipq9574-gcc.h | 1 + - 1 file changed, 1 insertion(+) - ---- a/include/dt-bindings/clock/qcom,ipq9574-gcc.h -+++ b/include/dt-bindings/clock/qcom,ipq9574-gcc.h -@@ -220,4 +220,5 @@ - #define GCC_PCIE1_PIPE_CLK 211 - #define GCC_PCIE2_PIPE_CLK 212 - #define GCC_PCIE3_PIPE_CLK 213 -+#define GPLL0_OUT_AUX 214 - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0019-v6.15-dt-bindings-clock-Add-ipq9574-NSSCC-clock-and-.patch b/target/linux/qualcommbe/patches-6.12/0019-v6.15-dt-bindings-clock-Add-ipq9574-NSSCC-clock-and-.patch deleted file mode 100644 index 0552b07b1e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0019-v6.15-dt-bindings-clock-Add-ipq9574-NSSCC-clock-and-.patch +++ /dev/null @@ -1,415 +0,0 @@ -From 5ed04d121a8d24cc3151aa57a21a6c944ad6d7f3 Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:56 +0530 -Subject: [PATCH 19/22] v6.15: dt-bindings: clock: Add ipq9574 NSSCC clock and - reset definitions - -Add NSSCC clock and reset definitions for ipq9574. - -Reviewed-by: Krzysztof Kozlowski -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-4-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - .../bindings/clock/qcom,ipq9574-nsscc.yaml | 98 +++++++++++ - .../dt-bindings/clock/qcom,ipq9574-nsscc.h | 152 ++++++++++++++++++ - .../dt-bindings/reset/qcom,ipq9574-nsscc.h | 134 +++++++++++++++ - 3 files changed, 384 insertions(+) - create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml - create mode 100644 include/dt-bindings/clock/qcom,ipq9574-nsscc.h - create mode 100644 include/dt-bindings/reset/qcom,ipq9574-nsscc.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-nsscc.yaml -@@ -0,0 +1,98 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/clock/qcom,ipq9574-nsscc.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm Networking Sub System Clock & Reset Controller on IPQ9574 -+ -+maintainers: -+ - Bjorn Andersson -+ - Anusha Rao -+ -+description: | -+ Qualcomm networking sub system clock control module provides the clocks, -+ resets on IPQ9574 -+ -+ See also:: -+ include/dt-bindings/clock/qcom,ipq9574-nsscc.h -+ include/dt-bindings/reset/qcom,ipq9574-nsscc.h -+ -+properties: -+ compatible: -+ const: qcom,ipq9574-nsscc -+ -+ clocks: -+ items: -+ - description: Board XO source -+ - description: CMN_PLL NSS 1200MHz (Bias PLL cc) clock source -+ - description: CMN_PLL PPE 353MHz (Bias PLL ubi nc) clock source -+ - description: GCC GPLL0 OUT AUX clock source -+ - description: Uniphy0 NSS Rx clock source -+ - description: Uniphy0 NSS Tx clock source -+ - description: Uniphy1 NSS Rx clock source -+ - description: Uniphy1 NSS Tx clock source -+ - description: Uniphy2 NSS Rx clock source -+ - description: Uniphy2 NSS Tx clock source -+ - description: GCC NSSCC clock source -+ -+ '#interconnect-cells': -+ const: 1 -+ -+ clock-names: -+ items: -+ - const: xo -+ - const: nss_1200 -+ - const: ppe_353 -+ - const: gpll0_out -+ - const: uniphy0_rx -+ - const: uniphy0_tx -+ - const: uniphy1_rx -+ - const: uniphy1_tx -+ - const: uniphy2_rx -+ - const: uniphy2_tx -+ - const: bus -+ -+required: -+ - compatible -+ - clocks -+ - clock-names -+ -+allOf: -+ - $ref: qcom,gcc.yaml# -+ -+unevaluatedProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ clock-controller@39b00000 { -+ compatible = "qcom,ipq9574-nsscc"; -+ reg = <0x39b00000 0x80000>; -+ clocks = <&xo_board_clk>, -+ <&cmn_pll NSS_1200MHZ_CLK>, -+ <&cmn_pll PPE_353MHZ_CLK>, -+ <&gcc GPLL0_OUT_AUX>, -+ <&uniphy 0>, -+ <&uniphy 1>, -+ <&uniphy 2>, -+ <&uniphy 3>, -+ <&uniphy 4>, -+ <&uniphy 5>, -+ <&gcc GCC_NSSCC_CLK>; -+ clock-names = "xo", -+ "nss_1200", -+ "ppe_353", -+ "gpll0_out", -+ "uniphy0_rx", -+ "uniphy0_tx", -+ "uniphy1_rx", -+ "uniphy1_tx", -+ "uniphy2_rx", -+ "uniphy2_tx", -+ "bus"; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ }; -+... ---- /dev/null -+++ b/include/dt-bindings/clock/qcom,ipq9574-nsscc.h -@@ -0,0 +1,152 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2023, 2025 The Linux Foundation. All rights reserved. -+ */ -+ -+#ifndef _DT_BINDINGS_CLOCK_IPQ_NSSCC_9574_H -+#define _DT_BINDINGS_CLOCK_IPQ_NSSCC_9574_H -+ -+#define NSS_CC_CE_APB_CLK 0 -+#define NSS_CC_CE_AXI_CLK 1 -+#define NSS_CC_CE_CLK_SRC 2 -+#define NSS_CC_CFG_CLK_SRC 3 -+#define NSS_CC_CLC_AXI_CLK 4 -+#define NSS_CC_CLC_CLK_SRC 5 -+#define NSS_CC_CRYPTO_CLK 6 -+#define NSS_CC_CRYPTO_CLK_SRC 7 -+#define NSS_CC_CRYPTO_PPE_CLK 8 -+#define NSS_CC_HAQ_AHB_CLK 9 -+#define NSS_CC_HAQ_AXI_CLK 10 -+#define NSS_CC_HAQ_CLK_SRC 11 -+#define NSS_CC_IMEM_AHB_CLK 12 -+#define NSS_CC_IMEM_CLK_SRC 13 -+#define NSS_CC_IMEM_QSB_CLK 14 -+#define NSS_CC_INT_CFG_CLK_SRC 15 -+#define NSS_CC_NSS_CSR_CLK 16 -+#define NSS_CC_NSSNOC_CE_APB_CLK 17 -+#define NSS_CC_NSSNOC_CE_AXI_CLK 18 -+#define NSS_CC_NSSNOC_CLC_AXI_CLK 19 -+#define NSS_CC_NSSNOC_CRYPTO_CLK 20 -+#define NSS_CC_NSSNOC_HAQ_AHB_CLK 21 -+#define NSS_CC_NSSNOC_HAQ_AXI_CLK 22 -+#define NSS_CC_NSSNOC_IMEM_AHB_CLK 23 -+#define NSS_CC_NSSNOC_IMEM_QSB_CLK 24 -+#define NSS_CC_NSSNOC_NSS_CSR_CLK 25 -+#define NSS_CC_NSSNOC_PPE_CFG_CLK 26 -+#define NSS_CC_NSSNOC_PPE_CLK 27 -+#define NSS_CC_NSSNOC_UBI32_AHB0_CLK 28 -+#define NSS_CC_NSSNOC_UBI32_AXI0_CLK 29 -+#define NSS_CC_NSSNOC_UBI32_INT0_AHB_CLK 30 -+#define NSS_CC_NSSNOC_UBI32_NC_AXI0_1_CLK 31 -+#define NSS_CC_NSSNOC_UBI32_NC_AXI0_CLK 32 -+#define NSS_CC_PORT1_MAC_CLK 33 -+#define NSS_CC_PORT1_RX_CLK 34 -+#define NSS_CC_PORT1_RX_CLK_SRC 35 -+#define NSS_CC_PORT1_RX_DIV_CLK_SRC 36 -+#define NSS_CC_PORT1_TX_CLK 37 -+#define NSS_CC_PORT1_TX_CLK_SRC 38 -+#define NSS_CC_PORT1_TX_DIV_CLK_SRC 39 -+#define NSS_CC_PORT2_MAC_CLK 40 -+#define NSS_CC_PORT2_RX_CLK 41 -+#define NSS_CC_PORT2_RX_CLK_SRC 42 -+#define NSS_CC_PORT2_RX_DIV_CLK_SRC 43 -+#define NSS_CC_PORT2_TX_CLK 44 -+#define NSS_CC_PORT2_TX_CLK_SRC 45 -+#define NSS_CC_PORT2_TX_DIV_CLK_SRC 46 -+#define NSS_CC_PORT3_MAC_CLK 47 -+#define NSS_CC_PORT3_RX_CLK 48 -+#define NSS_CC_PORT3_RX_CLK_SRC 49 -+#define NSS_CC_PORT3_RX_DIV_CLK_SRC 50 -+#define NSS_CC_PORT3_TX_CLK 51 -+#define NSS_CC_PORT3_TX_CLK_SRC 52 -+#define NSS_CC_PORT3_TX_DIV_CLK_SRC 53 -+#define NSS_CC_PORT4_MAC_CLK 54 -+#define NSS_CC_PORT4_RX_CLK 55 -+#define NSS_CC_PORT4_RX_CLK_SRC 56 -+#define NSS_CC_PORT4_RX_DIV_CLK_SRC 57 -+#define NSS_CC_PORT4_TX_CLK 58 -+#define NSS_CC_PORT4_TX_CLK_SRC 59 -+#define NSS_CC_PORT4_TX_DIV_CLK_SRC 60 -+#define NSS_CC_PORT5_MAC_CLK 61 -+#define NSS_CC_PORT5_RX_CLK 62 -+#define NSS_CC_PORT5_RX_CLK_SRC 63 -+#define NSS_CC_PORT5_RX_DIV_CLK_SRC 64 -+#define NSS_CC_PORT5_TX_CLK 65 -+#define NSS_CC_PORT5_TX_CLK_SRC 66 -+#define NSS_CC_PORT5_TX_DIV_CLK_SRC 67 -+#define NSS_CC_PORT6_MAC_CLK 68 -+#define NSS_CC_PORT6_RX_CLK 69 -+#define NSS_CC_PORT6_RX_CLK_SRC 70 -+#define NSS_CC_PORT6_RX_DIV_CLK_SRC 71 -+#define NSS_CC_PORT6_TX_CLK 72 -+#define NSS_CC_PORT6_TX_CLK_SRC 73 -+#define NSS_CC_PORT6_TX_DIV_CLK_SRC 74 -+#define NSS_CC_PPE_CLK_SRC 75 -+#define NSS_CC_PPE_EDMA_CFG_CLK 76 -+#define NSS_CC_PPE_EDMA_CLK 77 -+#define NSS_CC_PPE_SWITCH_BTQ_CLK 78 -+#define NSS_CC_PPE_SWITCH_CFG_CLK 79 -+#define NSS_CC_PPE_SWITCH_CLK 80 -+#define NSS_CC_PPE_SWITCH_IPE_CLK 81 -+#define NSS_CC_UBI0_CLK_SRC 82 -+#define NSS_CC_UBI0_DIV_CLK_SRC 83 -+#define NSS_CC_UBI1_CLK_SRC 84 -+#define NSS_CC_UBI1_DIV_CLK_SRC 85 -+#define NSS_CC_UBI2_CLK_SRC 86 -+#define NSS_CC_UBI2_DIV_CLK_SRC 87 -+#define NSS_CC_UBI32_AHB0_CLK 88 -+#define NSS_CC_UBI32_AHB1_CLK 89 -+#define NSS_CC_UBI32_AHB2_CLK 90 -+#define NSS_CC_UBI32_AHB3_CLK 91 -+#define NSS_CC_UBI32_AXI0_CLK 92 -+#define NSS_CC_UBI32_AXI1_CLK 93 -+#define NSS_CC_UBI32_AXI2_CLK 94 -+#define NSS_CC_UBI32_AXI3_CLK 95 -+#define NSS_CC_UBI32_CORE0_CLK 96 -+#define NSS_CC_UBI32_CORE1_CLK 97 -+#define NSS_CC_UBI32_CORE2_CLK 98 -+#define NSS_CC_UBI32_CORE3_CLK 99 -+#define NSS_CC_UBI32_INTR0_AHB_CLK 100 -+#define NSS_CC_UBI32_INTR1_AHB_CLK 101 -+#define NSS_CC_UBI32_INTR2_AHB_CLK 102 -+#define NSS_CC_UBI32_INTR3_AHB_CLK 103 -+#define NSS_CC_UBI32_NC_AXI0_CLK 104 -+#define NSS_CC_UBI32_NC_AXI1_CLK 105 -+#define NSS_CC_UBI32_NC_AXI2_CLK 106 -+#define NSS_CC_UBI32_NC_AXI3_CLK 107 -+#define NSS_CC_UBI32_UTCM0_CLK 108 -+#define NSS_CC_UBI32_UTCM1_CLK 109 -+#define NSS_CC_UBI32_UTCM2_CLK 110 -+#define NSS_CC_UBI32_UTCM3_CLK 111 -+#define NSS_CC_UBI3_CLK_SRC 112 -+#define NSS_CC_UBI3_DIV_CLK_SRC 113 -+#define NSS_CC_UBI_AXI_CLK_SRC 114 -+#define NSS_CC_UBI_NC_AXI_BFDCD_CLK_SRC 115 -+#define NSS_CC_UNIPHY_PORT1_RX_CLK 116 -+#define NSS_CC_UNIPHY_PORT1_TX_CLK 117 -+#define NSS_CC_UNIPHY_PORT2_RX_CLK 118 -+#define NSS_CC_UNIPHY_PORT2_TX_CLK 119 -+#define NSS_CC_UNIPHY_PORT3_RX_CLK 120 -+#define NSS_CC_UNIPHY_PORT3_TX_CLK 121 -+#define NSS_CC_UNIPHY_PORT4_RX_CLK 122 -+#define NSS_CC_UNIPHY_PORT4_TX_CLK 123 -+#define NSS_CC_UNIPHY_PORT5_RX_CLK 124 -+#define NSS_CC_UNIPHY_PORT5_TX_CLK 125 -+#define NSS_CC_UNIPHY_PORT6_RX_CLK 126 -+#define NSS_CC_UNIPHY_PORT6_TX_CLK 127 -+#define NSS_CC_XGMAC0_PTP_REF_CLK 128 -+#define NSS_CC_XGMAC0_PTP_REF_DIV_CLK_SRC 129 -+#define NSS_CC_XGMAC1_PTP_REF_CLK 130 -+#define NSS_CC_XGMAC1_PTP_REF_DIV_CLK_SRC 131 -+#define NSS_CC_XGMAC2_PTP_REF_CLK 132 -+#define NSS_CC_XGMAC2_PTP_REF_DIV_CLK_SRC 133 -+#define NSS_CC_XGMAC3_PTP_REF_CLK 134 -+#define NSS_CC_XGMAC3_PTP_REF_DIV_CLK_SRC 135 -+#define NSS_CC_XGMAC4_PTP_REF_CLK 136 -+#define NSS_CC_XGMAC4_PTP_REF_DIV_CLK_SRC 137 -+#define NSS_CC_XGMAC5_PTP_REF_CLK 138 -+#define NSS_CC_XGMAC5_PTP_REF_DIV_CLK_SRC 139 -+#define UBI32_PLL 140 -+#define UBI32_PLL_MAIN 141 -+ -+#endif ---- /dev/null -+++ b/include/dt-bindings/reset/qcom,ipq9574-nsscc.h -@@ -0,0 +1,134 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2023, 2025 The Linux Foundation. All rights reserved. -+ */ -+ -+#ifndef _DT_BINDINGS_RESET_IPQ_NSSCC_9574_H -+#define _DT_BINDINGS_RESET_IPQ_NSSCC_9574_H -+ -+#define EDMA_HW_RESET 0 -+#define NSS_CC_CE_BCR 1 -+#define NSS_CC_CLC_BCR 2 -+#define NSS_CC_EIP197_BCR 3 -+#define NSS_CC_HAQ_BCR 4 -+#define NSS_CC_IMEM_BCR 5 -+#define NSS_CC_MAC_BCR 6 -+#define NSS_CC_PPE_BCR 7 -+#define NSS_CC_UBI_BCR 8 -+#define NSS_CC_UNIPHY_BCR 9 -+#define UBI3_CLKRST_CLAMP_ENABLE 10 -+#define UBI3_CORE_CLAMP_ENABLE 11 -+#define UBI2_CLKRST_CLAMP_ENABLE 12 -+#define UBI2_CORE_CLAMP_ENABLE 13 -+#define UBI1_CLKRST_CLAMP_ENABLE 14 -+#define UBI1_CORE_CLAMP_ENABLE 15 -+#define UBI0_CLKRST_CLAMP_ENABLE 16 -+#define UBI0_CORE_CLAMP_ENABLE 17 -+#define NSSNOC_NSS_CSR_ARES 18 -+#define NSS_CSR_ARES 19 -+#define PPE_BTQ_ARES 20 -+#define PPE_IPE_ARES 21 -+#define PPE_ARES 22 -+#define PPE_CFG_ARES 23 -+#define PPE_EDMA_ARES 24 -+#define PPE_EDMA_CFG_ARES 25 -+#define CRY_PPE_ARES 26 -+#define NSSNOC_PPE_ARES 27 -+#define NSSNOC_PPE_CFG_ARES 28 -+#define PORT1_MAC_ARES 29 -+#define PORT2_MAC_ARES 30 -+#define PORT3_MAC_ARES 31 -+#define PORT4_MAC_ARES 32 -+#define PORT5_MAC_ARES 33 -+#define PORT6_MAC_ARES 34 -+#define XGMAC0_PTP_REF_ARES 35 -+#define XGMAC1_PTP_REF_ARES 36 -+#define XGMAC2_PTP_REF_ARES 37 -+#define XGMAC3_PTP_REF_ARES 38 -+#define XGMAC4_PTP_REF_ARES 39 -+#define XGMAC5_PTP_REF_ARES 40 -+#define HAQ_AHB_ARES 41 -+#define HAQ_AXI_ARES 42 -+#define NSSNOC_HAQ_AHB_ARES 43 -+#define NSSNOC_HAQ_AXI_ARES 44 -+#define CE_APB_ARES 45 -+#define CE_AXI_ARES 46 -+#define NSSNOC_CE_APB_ARES 47 -+#define NSSNOC_CE_AXI_ARES 48 -+#define CRYPTO_ARES 49 -+#define NSSNOC_CRYPTO_ARES 50 -+#define NSSNOC_NC_AXI0_1_ARES 51 -+#define UBI0_CORE_ARES 52 -+#define UBI1_CORE_ARES 53 -+#define UBI2_CORE_ARES 54 -+#define UBI3_CORE_ARES 55 -+#define NC_AXI0_ARES 56 -+#define UTCM0_ARES 57 -+#define NC_AXI1_ARES 58 -+#define UTCM1_ARES 59 -+#define NC_AXI2_ARES 60 -+#define UTCM2_ARES 61 -+#define NC_AXI3_ARES 62 -+#define UTCM3_ARES 63 -+#define NSSNOC_NC_AXI0_ARES 64 -+#define AHB0_ARES 65 -+#define INTR0_AHB_ARES 66 -+#define AHB1_ARES 67 -+#define INTR1_AHB_ARES 68 -+#define AHB2_ARES 69 -+#define INTR2_AHB_ARES 70 -+#define AHB3_ARES 71 -+#define INTR3_AHB_ARES 72 -+#define NSSNOC_AHB0_ARES 73 -+#define NSSNOC_INT0_AHB_ARES 74 -+#define AXI0_ARES 75 -+#define AXI1_ARES 76 -+#define AXI2_ARES 77 -+#define AXI3_ARES 78 -+#define NSSNOC_AXI0_ARES 79 -+#define IMEM_QSB_ARES 80 -+#define NSSNOC_IMEM_QSB_ARES 81 -+#define IMEM_AHB_ARES 82 -+#define NSSNOC_IMEM_AHB_ARES 83 -+#define UNIPHY_PORT1_RX_ARES 84 -+#define UNIPHY_PORT1_TX_ARES 85 -+#define UNIPHY_PORT2_RX_ARES 86 -+#define UNIPHY_PORT2_TX_ARES 87 -+#define UNIPHY_PORT3_RX_ARES 88 -+#define UNIPHY_PORT3_TX_ARES 89 -+#define UNIPHY_PORT4_RX_ARES 90 -+#define UNIPHY_PORT4_TX_ARES 91 -+#define UNIPHY_PORT5_RX_ARES 92 -+#define UNIPHY_PORT5_TX_ARES 93 -+#define UNIPHY_PORT6_RX_ARES 94 -+#define UNIPHY_PORT6_TX_ARES 95 -+#define PORT1_RX_ARES 96 -+#define PORT1_TX_ARES 97 -+#define PORT2_RX_ARES 98 -+#define PORT2_TX_ARES 99 -+#define PORT3_RX_ARES 100 -+#define PORT3_TX_ARES 101 -+#define PORT4_RX_ARES 102 -+#define PORT4_TX_ARES 103 -+#define PORT5_RX_ARES 104 -+#define PORT5_TX_ARES 105 -+#define PORT6_RX_ARES 106 -+#define PORT6_TX_ARES 107 -+#define PPE_FULL_RESET 108 -+#define UNIPHY0_SOFT_RESET 109 -+#define UNIPHY1_SOFT_RESET 110 -+#define UNIPHY2_SOFT_RESET 111 -+#define UNIPHY_PORT1_ARES 112 -+#define UNIPHY_PORT2_ARES 113 -+#define UNIPHY_PORT3_ARES 114 -+#define UNIPHY_PORT4_ARES 115 -+#define UNIPHY_PORT5_ARES 116 -+#define UNIPHY_PORT6_ARES 117 -+#define NSSPORT1_RESET 118 -+#define NSSPORT2_RESET 119 -+#define NSSPORT3_RESET 120 -+#define NSSPORT4_RESET 121 -+#define NSSPORT5_RESET 122 -+#define NSSPORT6_RESET 123 -+ -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0020-v6.15-clk-qcom-gcc-ipq9574-Add-support-for-gpll0_out.patch b/target/linux/qualcommbe/patches-6.12/0020-v6.15-clk-qcom-gcc-ipq9574-Add-support-for-gpll0_out.patch deleted file mode 100644 index 357fb18a71..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0020-v6.15-clk-qcom-gcc-ipq9574-Add-support-for-gpll0_out.patch +++ /dev/null @@ -1,49 +0,0 @@ -From c4e7d95921b074980ffd389254bcbfc045dd2a49 Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:55 +0530 -Subject: [PATCH 20/22] v6.15: clk: qcom: gcc-ipq9574: Add support for - gpll0_out_aux clock - -Add support for gpll0_out_aux clock which acts as the parent for -certain networking subsystem (nss) clocks. - -Reviewed-by: Dmitry Baryshkov -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-3-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - drivers/clk/qcom/gcc-ipq9574.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq9574.c -+++ b/drivers/clk/qcom/gcc-ipq9574.c -@@ -108,6 +108,20 @@ static struct clk_alpha_pll_postdiv gpll - }, - }; - -+static struct clk_alpha_pll_postdiv gpll0_out_aux = { -+ .offset = 0x20000, -+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "gpll0_out_aux", -+ .parent_hws = (const struct clk_hw *[]) { -+ &gpll0_main.clkr.hw -+ }, -+ .num_parents = 1, -+ .ops = &clk_alpha_pll_postdiv_ro_ops, -+ }, -+}; -+ - static struct clk_alpha_pll gpll4_main = { - .offset = 0x22000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT_EVO], -@@ -4222,6 +4236,7 @@ static struct clk_regmap *gcc_ipq9574_cl - [GCC_PCIE1_PIPE_CLK] = &gcc_pcie1_pipe_clk.clkr, - [GCC_PCIE2_PIPE_CLK] = &gcc_pcie2_pipe_clk.clkr, - [GCC_PCIE3_PIPE_CLK] = &gcc_pcie3_pipe_clk.clkr, -+ [GPLL0_OUT_AUX] = &gpll0_out_aux.clkr, - }; - - static const struct qcom_reset_map gcc_ipq9574_resets[] = { diff --git a/target/linux/qualcommbe/patches-6.12/0021-v6.15-clk-qcom-Add-NSS-clock-Controller-driver-for-I.patch b/target/linux/qualcommbe/patches-6.12/0021-v6.15-clk-qcom-Add-NSS-clock-Controller-driver-for-I.patch deleted file mode 100644 index e6d95f8bf3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0021-v6.15-clk-qcom-Add-NSS-clock-Controller-driver-for-I.patch +++ /dev/null @@ -1,3160 +0,0 @@ -From 8b42bea7cf2a21e854becf29760a947bef5cde0b Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:57 +0530 -Subject: [PATCH 21/22] v6.15: clk: qcom: Add NSS clock Controller driver for - IPQ9574 - -Add Networking Sub System Clock Controller (NSSCC) driver for ipq9574 based -devices. - -Reviewed-by: Konrad Dybcio -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-5-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - drivers/clk/qcom/Kconfig | 7 + - drivers/clk/qcom/Makefile | 1 + - drivers/clk/qcom/nsscc-ipq9574.c | 3110 ++++++++++++++++++++++++++++++ - 3 files changed, 3118 insertions(+) - create mode 100644 drivers/clk/qcom/nsscc-ipq9574.c - ---- a/drivers/clk/qcom/Kconfig -+++ b/drivers/clk/qcom/Kconfig -@@ -264,6 +264,13 @@ config IPQ_GCC_9574 - i2c, USB, SD/eMMC, etc. Select this for the root clock - of ipq9574. - -+config IPQ_NSSCC_9574 -+ tristate "IPQ9574 NSS Clock Controller" -+ depends on ARM64 || COMPILE_TEST -+ depends on IPQ_GCC_9574 -+ help -+ Support for NSS clock controller on ipq9574 devices. -+ - config IPQ_NSSCC_QCA8K - tristate "QCA8K(QCA8386 or QCA8084) NSS Clock Controller" - depends on MDIO_BUS ---- a/drivers/clk/qcom/Makefile -+++ b/drivers/clk/qcom/Makefile -@@ -37,6 +37,7 @@ obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq601 - obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o - obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o - obj-$(CONFIG_IPQ_GCC_9574) += gcc-ipq9574.o -+obj-$(CONFIG_IPQ_NSSCC_9574) += nsscc-ipq9574.o - obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o - obj-$(CONFIG_IPQ_NSSCC_QCA8K) += nsscc-qca8k.o - obj-$(CONFIG_MDM_GCC_9607) += gcc-mdm9607.o ---- /dev/null -+++ b/drivers/clk/qcom/nsscc-ipq9574.c -@@ -0,0 +1,3110 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2021, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "clk-alpha-pll.h" -+#include "clk-branch.h" -+#include "clk-pll.h" -+#include "clk-rcg.h" -+#include "clk-regmap.h" -+#include "clk-regmap-divider.h" -+#include "clk-regmap-mux.h" -+#include "common.h" -+#include "reset.h" -+ -+/* Need to match the order of clocks in DT binding */ -+enum { -+ DT_XO, -+ DT_BIAS_PLL_CC_CLK, -+ DT_BIAS_PLL_UBI_NC_CLK, -+ DT_GCC_GPLL0_OUT_AUX, -+ DT_UNIPHY0_NSS_RX_CLK, -+ DT_UNIPHY0_NSS_TX_CLK, -+ DT_UNIPHY1_NSS_RX_CLK, -+ DT_UNIPHY1_NSS_TX_CLK, -+ DT_UNIPHY2_NSS_RX_CLK, -+ DT_UNIPHY2_NSS_TX_CLK, -+}; -+ -+enum { -+ P_XO, -+ P_BIAS_PLL_CC_CLK, -+ P_BIAS_PLL_UBI_NC_CLK, -+ P_GCC_GPLL0_OUT_AUX, -+ P_UBI32_PLL_OUT_MAIN, -+ P_UNIPHY0_NSS_RX_CLK, -+ P_UNIPHY0_NSS_TX_CLK, -+ P_UNIPHY1_NSS_RX_CLK, -+ P_UNIPHY1_NSS_TX_CLK, -+ P_UNIPHY2_NSS_RX_CLK, -+ P_UNIPHY2_NSS_TX_CLK, -+}; -+ -+static const struct alpha_pll_config ubi32_pll_config = { -+ .l = 0x3e, -+ .alpha = 0x6666, -+ .config_ctl_val = 0x200d4aa8, -+ .config_ctl_hi_val = 0x3c, -+ .main_output_mask = BIT(0), -+ .aux_output_mask = BIT(1), -+ .pre_div_val = 0x0, -+ .pre_div_mask = BIT(12), -+ .post_div_val = 0x0, -+ .post_div_mask = GENMASK(9, 8), -+ .alpha_en_mask = BIT(24), -+ .test_ctl_val = 0x1c0000c0, -+ .test_ctl_hi_val = 0x4000, -+}; -+ -+static struct clk_alpha_pll ubi32_pll_main = { -+ .offset = 0x28000, -+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_NSS_HUAYRA], -+ .flags = SUPPORTS_DYNAMIC_UPDATE, -+ .clkr = { -+ .hw.init = &(const struct clk_init_data) { -+ .name = "ubi32_pll_main", -+ .parent_data = &(const struct clk_parent_data) { -+ .index = DT_XO, -+ }, -+ .num_parents = 1, -+ .ops = &clk_alpha_pll_huayra_ops, -+ }, -+ }, -+}; -+ -+static struct clk_alpha_pll_postdiv ubi32_pll = { -+ .offset = 0x28000, -+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_NSS_HUAYRA], -+ .width = 2, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "ubi32_pll", -+ .parent_hws = (const struct clk_hw *[]) { -+ &ubi32_pll_main.clkr.hw -+ }, -+ .num_parents = 1, -+ .ops = &clk_alpha_pll_postdiv_ro_ops, -+ .flags = CLK_SET_RATE_PARENT, -+ }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_0[] = { -+ { P_XO, 0 }, -+ { P_BIAS_PLL_CC_CLK, 1 }, -+ { P_UNIPHY0_NSS_RX_CLK, 2 }, -+ { P_UNIPHY0_NSS_TX_CLK, 3 }, -+ { P_UNIPHY1_NSS_RX_CLK, 4 }, -+ { P_UNIPHY1_NSS_TX_CLK, 5 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_0[] = { -+ { .index = DT_XO }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+ { .index = DT_UNIPHY0_NSS_RX_CLK }, -+ { .index = DT_UNIPHY0_NSS_TX_CLK }, -+ { .index = DT_UNIPHY1_NSS_RX_CLK }, -+ { .index = DT_UNIPHY1_NSS_TX_CLK }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_1[] = { -+ { P_XO, 0 }, -+ { P_BIAS_PLL_UBI_NC_CLK, 1 }, -+ { P_GCC_GPLL0_OUT_AUX, 2 }, -+ { P_BIAS_PLL_CC_CLK, 6 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_1[] = { -+ { .index = DT_XO }, -+ { .index = DT_BIAS_PLL_UBI_NC_CLK }, -+ { .index = DT_GCC_GPLL0_OUT_AUX }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_2[] = { -+ { P_XO, 0 }, -+ { P_UBI32_PLL_OUT_MAIN, 1 }, -+ { P_GCC_GPLL0_OUT_AUX, 2 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_2[] = { -+ { .index = DT_XO }, -+ { .hw = &ubi32_pll.clkr.hw }, -+ { .index = DT_GCC_GPLL0_OUT_AUX }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_3[] = { -+ { P_XO, 0 }, -+ { P_BIAS_PLL_CC_CLK, 1 }, -+ { P_GCC_GPLL0_OUT_AUX, 2 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_3[] = { -+ { .index = DT_XO }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+ { .index = DT_GCC_GPLL0_OUT_AUX }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_4[] = { -+ { P_XO, 0 }, -+ { P_BIAS_PLL_CC_CLK, 1 }, -+ { P_UNIPHY0_NSS_RX_CLK, 2 }, -+ { P_UNIPHY0_NSS_TX_CLK, 3 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_4[] = { -+ { .index = DT_XO }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+ { .index = DT_UNIPHY0_NSS_RX_CLK }, -+ { .index = DT_UNIPHY0_NSS_TX_CLK }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_5[] = { -+ { P_XO, 0 }, -+ { P_BIAS_PLL_CC_CLK, 1 }, -+ { P_UNIPHY2_NSS_RX_CLK, 2 }, -+ { P_UNIPHY2_NSS_TX_CLK, 3 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_5[] = { -+ { .index = DT_XO }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+ { .index = DT_UNIPHY2_NSS_RX_CLK }, -+ { .index = DT_UNIPHY2_NSS_TX_CLK }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_6[] = { -+ { P_XO, 0 }, -+ { P_GCC_GPLL0_OUT_AUX, 2 }, -+ { P_BIAS_PLL_CC_CLK, 6 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_6[] = { -+ { .index = DT_XO }, -+ { .index = DT_GCC_GPLL0_OUT_AUX }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+}; -+ -+static const struct parent_map nss_cc_parent_map_7[] = { -+ { P_XO, 0 }, -+ { P_UBI32_PLL_OUT_MAIN, 1 }, -+ { P_GCC_GPLL0_OUT_AUX, 2 }, -+ { P_BIAS_PLL_CC_CLK, 6 }, -+}; -+ -+static const struct clk_parent_data nss_cc_parent_data_7[] = { -+ { .index = DT_XO }, -+ { .hw = &ubi32_pll.clkr.hw }, -+ { .index = DT_GCC_GPLL0_OUT_AUX }, -+ { .index = DT_BIAS_PLL_CC_CLK }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_ce_clk_src[] = { -+ F(24000000, P_XO, 1, 0, 0), -+ F(353000000, P_BIAS_PLL_UBI_NC_CLK, 1, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_ce_clk_src = { -+ .cmd_rcgr = 0x28404, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_1, -+ .freq_tbl = ftbl_nss_cc_ce_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ce_clk_src", -+ .parent_data = nss_cc_parent_data_1, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_cfg_clk_src[] = { -+ F(100000000, P_GCC_GPLL0_OUT_AUX, 8, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_cfg_clk_src = { -+ .cmd_rcgr = 0x28104, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_3, -+ .freq_tbl = ftbl_nss_cc_cfg_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_cfg_clk_src", -+ .parent_data = nss_cc_parent_data_3, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_3), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_clc_clk_src[] = { -+ F(533333333, P_GCC_GPLL0_OUT_AUX, 1.5, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_clc_clk_src = { -+ .cmd_rcgr = 0x28604, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_6, -+ .freq_tbl = ftbl_nss_cc_clc_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_clc_clk_src", -+ .parent_data = nss_cc_parent_data_6, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_6), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_crypto_clk_src[] = { -+ F(24000000, P_XO, 1, 0, 0), -+ F(300000000, P_BIAS_PLL_CC_CLK, 4, 0, 0), -+ F(600000000, P_BIAS_PLL_CC_CLK, 2, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_crypto_clk_src = { -+ .cmd_rcgr = 0x16008, -+ .mnd_width = 16, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_3, -+ .freq_tbl = ftbl_nss_cc_crypto_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_crypto_clk_src", -+ .parent_data = nss_cc_parent_data_3, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_3), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_haq_clk_src = { -+ .cmd_rcgr = 0x28304, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_1, -+ .freq_tbl = ftbl_nss_cc_ce_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_haq_clk_src", -+ .parent_data = nss_cc_parent_data_1, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_imem_clk_src = { -+ .cmd_rcgr = 0xe008, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_1, -+ .freq_tbl = ftbl_nss_cc_ce_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_imem_clk_src", -+ .parent_data = nss_cc_parent_data_1, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_int_cfg_clk_src[] = { -+ F(200000000, P_GCC_GPLL0_OUT_AUX, 4, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_int_cfg_clk_src = { -+ .cmd_rcgr = 0x287b4, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_3, -+ .freq_tbl = ftbl_nss_cc_int_cfg_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_int_cfg_clk_src", -+ .parent_data = nss_cc_parent_data_3, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_3), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port1_rx_clk_src_25[] = { -+ C(P_UNIPHY0_NSS_RX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY0_NSS_RX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port1_rx_clk_src_125[] = { -+ C(P_UNIPHY0_NSS_RX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port1_rx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port1_rx_clk_src_25), -+ FMS(78125000, P_UNIPHY0_NSS_RX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port1_rx_clk_src_125), -+ FMS(312500000, P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), -+ { } -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port1_tx_clk_src_25[] = { -+ C(P_UNIPHY0_NSS_TX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY0_NSS_TX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port1_tx_clk_src_125[] = { -+ C(P_UNIPHY0_NSS_TX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port1_tx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port1_tx_clk_src_25), -+ FMS(78125000, P_UNIPHY0_NSS_TX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port1_tx_clk_src_125), -+ FMS(312500000, P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), -+ { } -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_25[] = { -+ C(P_UNIPHY1_NSS_RX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY0_NSS_RX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_125[] = { -+ C(P_UNIPHY1_NSS_RX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_312p5[] = { -+ C(P_UNIPHY1_NSS_RX_CLK, 1, 0, 0), -+ C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port5_rx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port5_rx_clk_src_25), -+ FMS(78125000, P_UNIPHY1_NSS_RX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port5_rx_clk_src_125), -+ FMS(156250000, P_UNIPHY1_NSS_RX_CLK, 2, 0, 0), -+ FM(312500000, ftbl_nss_cc_port5_rx_clk_src_312p5), -+ { } -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_25[] = { -+ C(P_UNIPHY1_NSS_TX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY0_NSS_TX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_125[] = { -+ C(P_UNIPHY1_NSS_TX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_312p5[] = { -+ C(P_UNIPHY1_NSS_TX_CLK, 1, 0, 0), -+ C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port5_tx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port5_tx_clk_src_25), -+ FMS(78125000, P_UNIPHY1_NSS_TX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port5_tx_clk_src_125), -+ FMS(156250000, P_UNIPHY1_NSS_TX_CLK, 2, 0, 0), -+ FM(312500000, ftbl_nss_cc_port5_tx_clk_src_312p5), -+ { } -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port6_rx_clk_src_25[] = { -+ C(P_UNIPHY2_NSS_RX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY2_NSS_RX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port6_rx_clk_src_125[] = { -+ C(P_UNIPHY2_NSS_RX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY2_NSS_RX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port6_rx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port6_rx_clk_src_25), -+ FMS(78125000, P_UNIPHY2_NSS_RX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port6_rx_clk_src_125), -+ FMS(156250000, P_UNIPHY2_NSS_RX_CLK, 2, 0, 0), -+ FMS(312500000, P_UNIPHY2_NSS_RX_CLK, 1, 0, 0), -+ { } -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port6_tx_clk_src_25[] = { -+ C(P_UNIPHY2_NSS_TX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY2_NSS_TX_CLK, 5, 0, 0), -+}; -+ -+static const struct freq_conf ftbl_nss_cc_port6_tx_clk_src_125[] = { -+ C(P_UNIPHY2_NSS_TX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY2_NSS_TX_CLK, 1, 0, 0), -+}; -+ -+static const struct freq_multi_tbl ftbl_nss_cc_port6_tx_clk_src[] = { -+ FMS(24000000, P_XO, 1, 0, 0), -+ FM(25000000, ftbl_nss_cc_port6_tx_clk_src_25), -+ FMS(78125000, P_UNIPHY2_NSS_TX_CLK, 4, 0, 0), -+ FM(125000000, ftbl_nss_cc_port6_tx_clk_src_125), -+ FMS(156250000, P_UNIPHY2_NSS_TX_CLK, 2, 0, 0), -+ FMS(312500000, P_UNIPHY2_NSS_TX_CLK, 1, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_port1_rx_clk_src = { -+ .cmd_rcgr = 0x28110, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_rx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port1_tx_clk_src = { -+ .cmd_rcgr = 0x2811c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_tx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port2_rx_clk_src = { -+ .cmd_rcgr = 0x28128, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_rx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port2_tx_clk_src = { -+ .cmd_rcgr = 0x28134, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_tx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port3_rx_clk_src = { -+ .cmd_rcgr = 0x28140, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_rx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port3_tx_clk_src = { -+ .cmd_rcgr = 0x2814c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_tx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port4_rx_clk_src = { -+ .cmd_rcgr = 0x28158, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_rx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port4_tx_clk_src = { -+ .cmd_rcgr = 0x28164, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_4, -+ .freq_multi_tbl = ftbl_nss_cc_port1_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_tx_clk_src", -+ .parent_data = nss_cc_parent_data_4, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_4), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port5_rx_clk_src = { -+ .cmd_rcgr = 0x28170, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_0, -+ .freq_multi_tbl = ftbl_nss_cc_port5_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_rx_clk_src", -+ .parent_data = nss_cc_parent_data_0, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_0), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port5_tx_clk_src = { -+ .cmd_rcgr = 0x2817c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_0, -+ .freq_multi_tbl = ftbl_nss_cc_port5_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_tx_clk_src", -+ .parent_data = nss_cc_parent_data_0, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_0), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port6_rx_clk_src = { -+ .cmd_rcgr = 0x28188, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_5, -+ .freq_multi_tbl = ftbl_nss_cc_port6_rx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_rx_clk_src", -+ .parent_data = nss_cc_parent_data_5, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_5), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_port6_tx_clk_src = { -+ .cmd_rcgr = 0x28194, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_5, -+ .freq_multi_tbl = ftbl_nss_cc_port6_tx_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_tx_clk_src", -+ .parent_data = nss_cc_parent_data_5, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_5), -+ .ops = &clk_rcg2_fm_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ppe_clk_src = { -+ .cmd_rcgr = 0x28204, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_1, -+ .freq_tbl = ftbl_nss_cc_ce_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_clk_src", -+ .parent_data = nss_cc_parent_data_1, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static const struct freq_tbl ftbl_nss_cc_ubi0_clk_src[] = { -+ F(24000000, P_XO, 1, 0, 0), -+ F(187200000, P_UBI32_PLL_OUT_MAIN, 8, 0, 0), -+ F(748800000, P_UBI32_PLL_OUT_MAIN, 2, 0, 0), -+ F(1497600000, P_UBI32_PLL_OUT_MAIN, 1, 0, 0), -+ F(1689600000, P_UBI32_PLL_OUT_MAIN, 1, 0, 0), -+ { } -+}; -+ -+static struct clk_rcg2 nss_cc_ubi0_clk_src = { -+ .cmd_rcgr = 0x28704, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_2, -+ .freq_tbl = ftbl_nss_cc_ubi0_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi0_clk_src", -+ .parent_data = nss_cc_parent_data_2, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_2), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ubi1_clk_src = { -+ .cmd_rcgr = 0x2870c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_2, -+ .freq_tbl = ftbl_nss_cc_ubi0_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi1_clk_src", -+ .parent_data = nss_cc_parent_data_2, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_2), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ubi2_clk_src = { -+ .cmd_rcgr = 0x28714, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_2, -+ .freq_tbl = ftbl_nss_cc_ubi0_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi2_clk_src", -+ .parent_data = nss_cc_parent_data_2, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_2), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ubi3_clk_src = { -+ .cmd_rcgr = 0x2871c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_2, -+ .freq_tbl = ftbl_nss_cc_ubi0_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi3_clk_src", -+ .parent_data = nss_cc_parent_data_2, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_2), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ubi_axi_clk_src = { -+ .cmd_rcgr = 0x28724, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_7, -+ .freq_tbl = ftbl_nss_cc_clc_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi_axi_clk_src", -+ .parent_data = nss_cc_parent_data_7, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_7), -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_rcg2 nss_cc_ubi_nc_axi_bfdcd_clk_src = { -+ .cmd_rcgr = 0x2872c, -+ .mnd_width = 0, -+ .hid_width = 5, -+ .parent_map = nss_cc_parent_map_1, -+ .freq_tbl = ftbl_nss_cc_ce_clk_src, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi_nc_axi_bfdcd_clk_src", -+ .parent_data = nss_cc_parent_data_1, -+ .num_parents = ARRAY_SIZE(nss_cc_parent_data_1), -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_rcg2_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port1_rx_div_clk_src = { -+ .reg = 0x28118, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port1_tx_div_clk_src = { -+ .reg = 0x28124, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port2_rx_div_clk_src = { -+ .reg = 0x28130, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port2_tx_div_clk_src = { -+ .reg = 0x2813c, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port3_rx_div_clk_src = { -+ .reg = 0x28148, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port3_tx_div_clk_src = { -+ .reg = 0x28154, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port4_rx_div_clk_src = { -+ .reg = 0x28160, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port4_tx_div_clk_src = { -+ .reg = 0x2816c, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port5_rx_div_clk_src = { -+ .reg = 0x28178, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port5_tx_div_clk_src = { -+ .reg = 0x28184, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port6_rx_div_clk_src = { -+ .reg = 0x28190, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_rx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_rx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_port6_tx_div_clk_src = { -+ .reg = 0x2819c, -+ .shift = 0, -+ .width = 9, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_tx_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_tx_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_ubi0_div_clk_src = { -+ .reg = 0x287a4, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi0_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi0_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_ubi1_div_clk_src = { -+ .reg = 0x287a8, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi1_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi1_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_ubi2_div_clk_src = { -+ .reg = 0x287ac, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi2_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi2_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_ubi3_div_clk_src = { -+ .reg = 0x287b0, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi3_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi3_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac0_ptp_ref_div_clk_src = { -+ .reg = 0x28214, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac0_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac1_ptp_ref_div_clk_src = { -+ .reg = 0x28218, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac1_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac2_ptp_ref_div_clk_src = { -+ .reg = 0x2821c, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac2_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac3_ptp_ref_div_clk_src = { -+ .reg = 0x28220, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac3_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac4_ptp_ref_div_clk_src = { -+ .reg = 0x28224, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac4_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_regmap_div nss_cc_xgmac5_ptp_ref_div_clk_src = { -+ .reg = 0x28228, -+ .shift = 0, -+ .width = 4, -+ .clkr.hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac5_ptp_ref_div_clk_src", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_regmap_div_ro_ops, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ce_apb_clk = { -+ .halt_reg = 0x2840c, -+ .clkr = { -+ .enable_reg = 0x2840c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ce_apb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ce_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ce_axi_clk = { -+ .halt_reg = 0x28410, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28410, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ce_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ce_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_clc_axi_clk = { -+ .halt_reg = 0x2860c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2860c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_clc_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_clc_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_crypto_clk = { -+ .halt_reg = 0x1601c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x1601c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_crypto_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_crypto_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_crypto_ppe_clk = { -+ .halt_reg = 0x28240, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28240, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_crypto_ppe_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_haq_ahb_clk = { -+ .halt_reg = 0x2830c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2830c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_haq_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_haq_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_haq_axi_clk = { -+ .halt_reg = 0x28310, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28310, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_haq_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_haq_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_imem_ahb_clk = { -+ .halt_reg = 0xe018, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0xe018, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_imem_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_imem_qsb_clk = { -+ .halt_reg = 0xe010, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0xe010, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_imem_qsb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_imem_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nss_csr_clk = { -+ .halt_reg = 0x281d0, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281d0, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nss_csr_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ce_apb_clk = { -+ .halt_reg = 0x28414, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28414, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ce_apb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ce_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ce_axi_clk = { -+ .halt_reg = 0x28418, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28418, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ce_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ce_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_clc_axi_clk = { -+ .halt_reg = 0x28610, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28610, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_clc_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_clc_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_crypto_clk = { -+ .halt_reg = 0x16020, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x16020, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_crypto_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_crypto_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_haq_ahb_clk = { -+ .halt_reg = 0x28314, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28314, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_haq_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_haq_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_haq_axi_clk = { -+ .halt_reg = 0x28318, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28318, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_haq_axi_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_haq_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_imem_ahb_clk = { -+ .halt_reg = 0xe01c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0xe01c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_imem_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_imem_qsb_clk = { -+ .halt_reg = 0xe014, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0xe014, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_imem_qsb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_imem_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_nss_csr_clk = { -+ .halt_reg = 0x281d4, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281d4, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_nss_csr_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ppe_cfg_clk = { -+ .halt_reg = 0x28248, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28248, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ppe_cfg_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ppe_clk = { -+ .halt_reg = 0x28244, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28244, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ppe_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ubi32_ahb0_clk = { -+ .halt_reg = 0x28788, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28788, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ubi32_ahb0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ubi32_axi0_clk = { -+ .halt_reg = 0x287a0, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x287a0, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ubi32_axi0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_axi_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ubi32_int0_ahb_clk = { -+ .halt_reg = 0x2878c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2878c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ubi32_int0_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_int_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ubi32_nc_axi0_1_clk = { -+ .halt_reg = 0x287bc, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x287bc, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ubi32_nc_axi0_1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_nssnoc_ubi32_nc_axi0_clk = { -+ .halt_reg = 0x28764, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28764, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_nssnoc_ubi32_nc_axi0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port1_mac_clk = { -+ .halt_reg = 0x2824c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2824c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port1_rx_clk = { -+ .halt_reg = 0x281a0, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281a0, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port1_tx_clk = { -+ .halt_reg = 0x281a4, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281a4, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port1_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port2_mac_clk = { -+ .halt_reg = 0x28250, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28250, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port2_rx_clk = { -+ .halt_reg = 0x281a8, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281a8, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port2_tx_clk = { -+ .halt_reg = 0x281ac, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281ac, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port2_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port3_mac_clk = { -+ .halt_reg = 0x28254, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28254, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port3_rx_clk = { -+ .halt_reg = 0x281b0, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281b0, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port3_tx_clk = { -+ .halt_reg = 0x281b4, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281b4, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port3_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port4_mac_clk = { -+ .halt_reg = 0x28258, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28258, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port4_rx_clk = { -+ .halt_reg = 0x281b8, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281b8, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port4_tx_clk = { -+ .halt_reg = 0x281bc, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281bc, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port4_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port5_mac_clk = { -+ .halt_reg = 0x2825c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2825c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port5_rx_clk = { -+ .halt_reg = 0x281c0, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281c0, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port5_tx_clk = { -+ .halt_reg = 0x281c4, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281c4, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port5_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port6_mac_clk = { -+ .halt_reg = 0x28260, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28260, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_mac_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port6_rx_clk = { -+ .halt_reg = 0x281c8, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281c8, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_port6_tx_clk = { -+ .halt_reg = 0x281cc, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x281cc, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_port6_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_edma_cfg_clk = { -+ .halt_reg = 0x2823c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2823c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_edma_cfg_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_edma_clk = { -+ .halt_reg = 0x28238, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28238, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_edma_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_switch_btq_clk = { -+ .halt_reg = 0x2827c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2827c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_switch_btq_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_switch_cfg_clk = { -+ .halt_reg = 0x28234, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28234, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_switch_cfg_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_switch_clk = { -+ .halt_reg = 0x28230, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28230, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_switch_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ppe_switch_ipe_clk = { -+ .halt_reg = 0x2822c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2822c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ppe_switch_ipe_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ppe_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_ahb0_clk = { -+ .halt_reg = 0x28768, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28768, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_ahb0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_ahb1_clk = { -+ .halt_reg = 0x28770, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28770, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_ahb1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_ahb2_clk = { -+ .halt_reg = 0x28778, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28778, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_ahb2_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_ahb3_clk = { -+ .halt_reg = 0x28780, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28780, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_ahb3_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_axi0_clk = { -+ .halt_reg = 0x28790, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28790, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_axi0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_axi_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_axi1_clk = { -+ .halt_reg = 0x28794, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28794, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_axi1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_axi_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_axi2_clk = { -+ .halt_reg = 0x28798, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28798, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_axi2_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_axi_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_axi3_clk = { -+ .halt_reg = 0x2879c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2879c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_axi3_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_axi_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_core0_clk = { -+ .halt_reg = 0x28734, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28734, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_core0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi0_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_core1_clk = { -+ .halt_reg = 0x28738, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28738, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_core1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi1_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_core2_clk = { -+ .halt_reg = 0x2873c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2873c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_core2_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi2_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_core3_clk = { -+ .halt_reg = 0x28740, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28740, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_core3_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi3_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_intr0_ahb_clk = { -+ .halt_reg = 0x2876c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2876c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_intr0_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_int_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_intr1_ahb_clk = { -+ .halt_reg = 0x28774, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28774, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_intr1_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_int_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_intr2_ahb_clk = { -+ .halt_reg = 0x2877c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2877c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_intr2_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_int_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_intr3_ahb_clk = { -+ .halt_reg = 0x28784, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28784, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_intr3_ahb_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_int_cfg_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_nc_axi0_clk = { -+ .halt_reg = 0x28744, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28744, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_nc_axi0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_nc_axi1_clk = { -+ .halt_reg = 0x2874c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2874c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_nc_axi1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_nc_axi2_clk = { -+ .halt_reg = 0x28754, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28754, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_nc_axi2_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_nc_axi3_clk = { -+ .halt_reg = 0x2875c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2875c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_nc_axi3_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_utcm0_clk = { -+ .halt_reg = 0x28748, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28748, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_utcm0_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_utcm1_clk = { -+ .halt_reg = 0x28750, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28750, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_utcm1_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_utcm2_clk = { -+ .halt_reg = 0x28758, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28758, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_utcm2_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_ubi32_utcm3_clk = { -+ .halt_reg = 0x28760, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28760, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_ubi32_utcm3_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port1_rx_clk = { -+ .halt_reg = 0x28904, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28904, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port1_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port1_tx_clk = { -+ .halt_reg = 0x28908, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28908, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port1_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port1_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port2_rx_clk = { -+ .halt_reg = 0x2890c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2890c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port2_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port2_tx_clk = { -+ .halt_reg = 0x28910, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28910, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port2_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port2_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port3_rx_clk = { -+ .halt_reg = 0x28914, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28914, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port3_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port3_tx_clk = { -+ .halt_reg = 0x28918, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28918, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port3_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port3_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port4_rx_clk = { -+ .halt_reg = 0x2891c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2891c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port4_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port4_tx_clk = { -+ .halt_reg = 0x28920, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28920, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port4_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port4_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port5_rx_clk = { -+ .halt_reg = 0x28924, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28924, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port5_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port5_tx_clk = { -+ .halt_reg = 0x28928, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28928, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port5_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port5_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port6_rx_clk = { -+ .halt_reg = 0x2892c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2892c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port6_rx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_rx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_uniphy_port6_tx_clk = { -+ .halt_reg = 0x28930, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28930, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_uniphy_port6_tx_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_port6_tx_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac0_ptp_ref_clk = { -+ .halt_reg = 0x28264, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28264, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac0_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac0_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac1_ptp_ref_clk = { -+ .halt_reg = 0x28268, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28268, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac1_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac1_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac2_ptp_ref_clk = { -+ .halt_reg = 0x2826c, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x2826c, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac2_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac2_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac3_ptp_ref_clk = { -+ .halt_reg = 0x28270, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28270, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac3_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac3_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac4_ptp_ref_clk = { -+ .halt_reg = 0x28274, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28274, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac4_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac4_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_branch nss_cc_xgmac5_ptp_ref_clk = { -+ .halt_reg = 0x28278, -+ .halt_check = BRANCH_HALT, -+ .clkr = { -+ .enable_reg = 0x28278, -+ .enable_mask = BIT(0), -+ .hw.init = &(const struct clk_init_data) { -+ .name = "nss_cc_xgmac5_ptp_ref_clk", -+ .parent_data = &(const struct clk_parent_data) { -+ .hw = &nss_cc_xgmac5_ptp_ref_div_clk_src.clkr.hw, -+ }, -+ .num_parents = 1, -+ .flags = CLK_SET_RATE_PARENT, -+ .ops = &clk_branch2_ops, -+ }, -+ }, -+}; -+ -+static struct clk_regmap *nss_cc_ipq9574_clocks[] = { -+ [NSS_CC_CE_APB_CLK] = &nss_cc_ce_apb_clk.clkr, -+ [NSS_CC_CE_AXI_CLK] = &nss_cc_ce_axi_clk.clkr, -+ [NSS_CC_CE_CLK_SRC] = &nss_cc_ce_clk_src.clkr, -+ [NSS_CC_CFG_CLK_SRC] = &nss_cc_cfg_clk_src.clkr, -+ [NSS_CC_CLC_AXI_CLK] = &nss_cc_clc_axi_clk.clkr, -+ [NSS_CC_CLC_CLK_SRC] = &nss_cc_clc_clk_src.clkr, -+ [NSS_CC_CRYPTO_CLK] = &nss_cc_crypto_clk.clkr, -+ [NSS_CC_CRYPTO_CLK_SRC] = &nss_cc_crypto_clk_src.clkr, -+ [NSS_CC_CRYPTO_PPE_CLK] = &nss_cc_crypto_ppe_clk.clkr, -+ [NSS_CC_HAQ_AHB_CLK] = &nss_cc_haq_ahb_clk.clkr, -+ [NSS_CC_HAQ_AXI_CLK] = &nss_cc_haq_axi_clk.clkr, -+ [NSS_CC_HAQ_CLK_SRC] = &nss_cc_haq_clk_src.clkr, -+ [NSS_CC_IMEM_AHB_CLK] = &nss_cc_imem_ahb_clk.clkr, -+ [NSS_CC_IMEM_CLK_SRC] = &nss_cc_imem_clk_src.clkr, -+ [NSS_CC_IMEM_QSB_CLK] = &nss_cc_imem_qsb_clk.clkr, -+ [NSS_CC_INT_CFG_CLK_SRC] = &nss_cc_int_cfg_clk_src.clkr, -+ [NSS_CC_NSS_CSR_CLK] = &nss_cc_nss_csr_clk.clkr, -+ [NSS_CC_NSSNOC_CE_APB_CLK] = &nss_cc_nssnoc_ce_apb_clk.clkr, -+ [NSS_CC_NSSNOC_CE_AXI_CLK] = &nss_cc_nssnoc_ce_axi_clk.clkr, -+ [NSS_CC_NSSNOC_CLC_AXI_CLK] = &nss_cc_nssnoc_clc_axi_clk.clkr, -+ [NSS_CC_NSSNOC_CRYPTO_CLK] = &nss_cc_nssnoc_crypto_clk.clkr, -+ [NSS_CC_NSSNOC_HAQ_AHB_CLK] = &nss_cc_nssnoc_haq_ahb_clk.clkr, -+ [NSS_CC_NSSNOC_HAQ_AXI_CLK] = &nss_cc_nssnoc_haq_axi_clk.clkr, -+ [NSS_CC_NSSNOC_IMEM_AHB_CLK] = &nss_cc_nssnoc_imem_ahb_clk.clkr, -+ [NSS_CC_NSSNOC_IMEM_QSB_CLK] = &nss_cc_nssnoc_imem_qsb_clk.clkr, -+ [NSS_CC_NSSNOC_NSS_CSR_CLK] = &nss_cc_nssnoc_nss_csr_clk.clkr, -+ [NSS_CC_NSSNOC_PPE_CFG_CLK] = &nss_cc_nssnoc_ppe_cfg_clk.clkr, -+ [NSS_CC_NSSNOC_PPE_CLK] = &nss_cc_nssnoc_ppe_clk.clkr, -+ [NSS_CC_NSSNOC_UBI32_AHB0_CLK] = &nss_cc_nssnoc_ubi32_ahb0_clk.clkr, -+ [NSS_CC_NSSNOC_UBI32_AXI0_CLK] = &nss_cc_nssnoc_ubi32_axi0_clk.clkr, -+ [NSS_CC_NSSNOC_UBI32_INT0_AHB_CLK] = -+ &nss_cc_nssnoc_ubi32_int0_ahb_clk.clkr, -+ [NSS_CC_NSSNOC_UBI32_NC_AXI0_1_CLK] = -+ &nss_cc_nssnoc_ubi32_nc_axi0_1_clk.clkr, -+ [NSS_CC_NSSNOC_UBI32_NC_AXI0_CLK] = -+ &nss_cc_nssnoc_ubi32_nc_axi0_clk.clkr, -+ [NSS_CC_PORT1_MAC_CLK] = &nss_cc_port1_mac_clk.clkr, -+ [NSS_CC_PORT1_RX_CLK] = &nss_cc_port1_rx_clk.clkr, -+ [NSS_CC_PORT1_RX_CLK_SRC] = &nss_cc_port1_rx_clk_src.clkr, -+ [NSS_CC_PORT1_RX_DIV_CLK_SRC] = &nss_cc_port1_rx_div_clk_src.clkr, -+ [NSS_CC_PORT1_TX_CLK] = &nss_cc_port1_tx_clk.clkr, -+ [NSS_CC_PORT1_TX_CLK_SRC] = &nss_cc_port1_tx_clk_src.clkr, -+ [NSS_CC_PORT1_TX_DIV_CLK_SRC] = &nss_cc_port1_tx_div_clk_src.clkr, -+ [NSS_CC_PORT2_MAC_CLK] = &nss_cc_port2_mac_clk.clkr, -+ [NSS_CC_PORT2_RX_CLK] = &nss_cc_port2_rx_clk.clkr, -+ [NSS_CC_PORT2_RX_CLK_SRC] = &nss_cc_port2_rx_clk_src.clkr, -+ [NSS_CC_PORT2_RX_DIV_CLK_SRC] = &nss_cc_port2_rx_div_clk_src.clkr, -+ [NSS_CC_PORT2_TX_CLK] = &nss_cc_port2_tx_clk.clkr, -+ [NSS_CC_PORT2_TX_CLK_SRC] = &nss_cc_port2_tx_clk_src.clkr, -+ [NSS_CC_PORT2_TX_DIV_CLK_SRC] = &nss_cc_port2_tx_div_clk_src.clkr, -+ [NSS_CC_PORT3_MAC_CLK] = &nss_cc_port3_mac_clk.clkr, -+ [NSS_CC_PORT3_RX_CLK] = &nss_cc_port3_rx_clk.clkr, -+ [NSS_CC_PORT3_RX_CLK_SRC] = &nss_cc_port3_rx_clk_src.clkr, -+ [NSS_CC_PORT3_RX_DIV_CLK_SRC] = &nss_cc_port3_rx_div_clk_src.clkr, -+ [NSS_CC_PORT3_TX_CLK] = &nss_cc_port3_tx_clk.clkr, -+ [NSS_CC_PORT3_TX_CLK_SRC] = &nss_cc_port3_tx_clk_src.clkr, -+ [NSS_CC_PORT3_TX_DIV_CLK_SRC] = &nss_cc_port3_tx_div_clk_src.clkr, -+ [NSS_CC_PORT4_MAC_CLK] = &nss_cc_port4_mac_clk.clkr, -+ [NSS_CC_PORT4_RX_CLK] = &nss_cc_port4_rx_clk.clkr, -+ [NSS_CC_PORT4_RX_CLK_SRC] = &nss_cc_port4_rx_clk_src.clkr, -+ [NSS_CC_PORT4_RX_DIV_CLK_SRC] = &nss_cc_port4_rx_div_clk_src.clkr, -+ [NSS_CC_PORT4_TX_CLK] = &nss_cc_port4_tx_clk.clkr, -+ [NSS_CC_PORT4_TX_CLK_SRC] = &nss_cc_port4_tx_clk_src.clkr, -+ [NSS_CC_PORT4_TX_DIV_CLK_SRC] = &nss_cc_port4_tx_div_clk_src.clkr, -+ [NSS_CC_PORT5_MAC_CLK] = &nss_cc_port5_mac_clk.clkr, -+ [NSS_CC_PORT5_RX_CLK] = &nss_cc_port5_rx_clk.clkr, -+ [NSS_CC_PORT5_RX_CLK_SRC] = &nss_cc_port5_rx_clk_src.clkr, -+ [NSS_CC_PORT5_RX_DIV_CLK_SRC] = &nss_cc_port5_rx_div_clk_src.clkr, -+ [NSS_CC_PORT5_TX_CLK] = &nss_cc_port5_tx_clk.clkr, -+ [NSS_CC_PORT5_TX_CLK_SRC] = &nss_cc_port5_tx_clk_src.clkr, -+ [NSS_CC_PORT5_TX_DIV_CLK_SRC] = &nss_cc_port5_tx_div_clk_src.clkr, -+ [NSS_CC_PORT6_MAC_CLK] = &nss_cc_port6_mac_clk.clkr, -+ [NSS_CC_PORT6_RX_CLK] = &nss_cc_port6_rx_clk.clkr, -+ [NSS_CC_PORT6_RX_CLK_SRC] = &nss_cc_port6_rx_clk_src.clkr, -+ [NSS_CC_PORT6_RX_DIV_CLK_SRC] = &nss_cc_port6_rx_div_clk_src.clkr, -+ [NSS_CC_PORT6_TX_CLK] = &nss_cc_port6_tx_clk.clkr, -+ [NSS_CC_PORT6_TX_CLK_SRC] = &nss_cc_port6_tx_clk_src.clkr, -+ [NSS_CC_PORT6_TX_DIV_CLK_SRC] = &nss_cc_port6_tx_div_clk_src.clkr, -+ [NSS_CC_PPE_CLK_SRC] = &nss_cc_ppe_clk_src.clkr, -+ [NSS_CC_PPE_EDMA_CFG_CLK] = &nss_cc_ppe_edma_cfg_clk.clkr, -+ [NSS_CC_PPE_EDMA_CLK] = &nss_cc_ppe_edma_clk.clkr, -+ [NSS_CC_PPE_SWITCH_BTQ_CLK] = &nss_cc_ppe_switch_btq_clk.clkr, -+ [NSS_CC_PPE_SWITCH_CFG_CLK] = &nss_cc_ppe_switch_cfg_clk.clkr, -+ [NSS_CC_PPE_SWITCH_CLK] = &nss_cc_ppe_switch_clk.clkr, -+ [NSS_CC_PPE_SWITCH_IPE_CLK] = &nss_cc_ppe_switch_ipe_clk.clkr, -+ [NSS_CC_UBI0_CLK_SRC] = &nss_cc_ubi0_clk_src.clkr, -+ [NSS_CC_UBI0_DIV_CLK_SRC] = &nss_cc_ubi0_div_clk_src.clkr, -+ [NSS_CC_UBI1_CLK_SRC] = &nss_cc_ubi1_clk_src.clkr, -+ [NSS_CC_UBI1_DIV_CLK_SRC] = &nss_cc_ubi1_div_clk_src.clkr, -+ [NSS_CC_UBI2_CLK_SRC] = &nss_cc_ubi2_clk_src.clkr, -+ [NSS_CC_UBI2_DIV_CLK_SRC] = &nss_cc_ubi2_div_clk_src.clkr, -+ [NSS_CC_UBI32_AHB0_CLK] = &nss_cc_ubi32_ahb0_clk.clkr, -+ [NSS_CC_UBI32_AHB1_CLK] = &nss_cc_ubi32_ahb1_clk.clkr, -+ [NSS_CC_UBI32_AHB2_CLK] = &nss_cc_ubi32_ahb2_clk.clkr, -+ [NSS_CC_UBI32_AHB3_CLK] = &nss_cc_ubi32_ahb3_clk.clkr, -+ [NSS_CC_UBI32_AXI0_CLK] = &nss_cc_ubi32_axi0_clk.clkr, -+ [NSS_CC_UBI32_AXI1_CLK] = &nss_cc_ubi32_axi1_clk.clkr, -+ [NSS_CC_UBI32_AXI2_CLK] = &nss_cc_ubi32_axi2_clk.clkr, -+ [NSS_CC_UBI32_AXI3_CLK] = &nss_cc_ubi32_axi3_clk.clkr, -+ [NSS_CC_UBI32_CORE0_CLK] = &nss_cc_ubi32_core0_clk.clkr, -+ [NSS_CC_UBI32_CORE1_CLK] = &nss_cc_ubi32_core1_clk.clkr, -+ [NSS_CC_UBI32_CORE2_CLK] = &nss_cc_ubi32_core2_clk.clkr, -+ [NSS_CC_UBI32_CORE3_CLK] = &nss_cc_ubi32_core3_clk.clkr, -+ [NSS_CC_UBI32_INTR0_AHB_CLK] = &nss_cc_ubi32_intr0_ahb_clk.clkr, -+ [NSS_CC_UBI32_INTR1_AHB_CLK] = &nss_cc_ubi32_intr1_ahb_clk.clkr, -+ [NSS_CC_UBI32_INTR2_AHB_CLK] = &nss_cc_ubi32_intr2_ahb_clk.clkr, -+ [NSS_CC_UBI32_INTR3_AHB_CLK] = &nss_cc_ubi32_intr3_ahb_clk.clkr, -+ [NSS_CC_UBI32_NC_AXI0_CLK] = &nss_cc_ubi32_nc_axi0_clk.clkr, -+ [NSS_CC_UBI32_NC_AXI1_CLK] = &nss_cc_ubi32_nc_axi1_clk.clkr, -+ [NSS_CC_UBI32_NC_AXI2_CLK] = &nss_cc_ubi32_nc_axi2_clk.clkr, -+ [NSS_CC_UBI32_NC_AXI3_CLK] = &nss_cc_ubi32_nc_axi3_clk.clkr, -+ [NSS_CC_UBI32_UTCM0_CLK] = &nss_cc_ubi32_utcm0_clk.clkr, -+ [NSS_CC_UBI32_UTCM1_CLK] = &nss_cc_ubi32_utcm1_clk.clkr, -+ [NSS_CC_UBI32_UTCM2_CLK] = &nss_cc_ubi32_utcm2_clk.clkr, -+ [NSS_CC_UBI32_UTCM3_CLK] = &nss_cc_ubi32_utcm3_clk.clkr, -+ [NSS_CC_UBI3_CLK_SRC] = &nss_cc_ubi3_clk_src.clkr, -+ [NSS_CC_UBI3_DIV_CLK_SRC] = &nss_cc_ubi3_div_clk_src.clkr, -+ [NSS_CC_UBI_AXI_CLK_SRC] = &nss_cc_ubi_axi_clk_src.clkr, -+ [NSS_CC_UBI_NC_AXI_BFDCD_CLK_SRC] = -+ &nss_cc_ubi_nc_axi_bfdcd_clk_src.clkr, -+ [NSS_CC_UNIPHY_PORT1_RX_CLK] = &nss_cc_uniphy_port1_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT1_TX_CLK] = &nss_cc_uniphy_port1_tx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT2_RX_CLK] = &nss_cc_uniphy_port2_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT2_TX_CLK] = &nss_cc_uniphy_port2_tx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT3_RX_CLK] = &nss_cc_uniphy_port3_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT3_TX_CLK] = &nss_cc_uniphy_port3_tx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT4_RX_CLK] = &nss_cc_uniphy_port4_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT4_TX_CLK] = &nss_cc_uniphy_port4_tx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT5_RX_CLK] = &nss_cc_uniphy_port5_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT5_TX_CLK] = &nss_cc_uniphy_port5_tx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT6_RX_CLK] = &nss_cc_uniphy_port6_rx_clk.clkr, -+ [NSS_CC_UNIPHY_PORT6_TX_CLK] = &nss_cc_uniphy_port6_tx_clk.clkr, -+ [NSS_CC_XGMAC0_PTP_REF_CLK] = &nss_cc_xgmac0_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC0_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac0_ptp_ref_div_clk_src.clkr, -+ [NSS_CC_XGMAC1_PTP_REF_CLK] = &nss_cc_xgmac1_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC1_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac1_ptp_ref_div_clk_src.clkr, -+ [NSS_CC_XGMAC2_PTP_REF_CLK] = &nss_cc_xgmac2_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC2_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac2_ptp_ref_div_clk_src.clkr, -+ [NSS_CC_XGMAC3_PTP_REF_CLK] = &nss_cc_xgmac3_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC3_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac3_ptp_ref_div_clk_src.clkr, -+ [NSS_CC_XGMAC4_PTP_REF_CLK] = &nss_cc_xgmac4_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC4_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac4_ptp_ref_div_clk_src.clkr, -+ [NSS_CC_XGMAC5_PTP_REF_CLK] = &nss_cc_xgmac5_ptp_ref_clk.clkr, -+ [NSS_CC_XGMAC5_PTP_REF_DIV_CLK_SRC] = -+ &nss_cc_xgmac5_ptp_ref_div_clk_src.clkr, -+ [UBI32_PLL] = &ubi32_pll.clkr, -+ [UBI32_PLL_MAIN] = &ubi32_pll_main.clkr, -+}; -+ -+static const struct qcom_reset_map nss_cc_ipq9574_resets[] = { -+ [NSS_CC_CE_BCR] = { 0x28400, 0 }, -+ [NSS_CC_CLC_BCR] = { 0x28600, 0 }, -+ [NSS_CC_EIP197_BCR] = { 0x16004, 0 }, -+ [NSS_CC_HAQ_BCR] = { 0x28300, 0 }, -+ [NSS_CC_IMEM_BCR] = { 0xe004, 0 }, -+ [NSS_CC_MAC_BCR] = { 0x28100, 0 }, -+ [NSS_CC_PPE_BCR] = { 0x28200, 0 }, -+ [NSS_CC_UBI_BCR] = { 0x28700, 0 }, -+ [NSS_CC_UNIPHY_BCR] = { 0x28900, 0 }, -+ [UBI3_CLKRST_CLAMP_ENABLE] = { 0x28a04, 9 }, -+ [UBI3_CORE_CLAMP_ENABLE] = { 0x28a04, 8 }, -+ [UBI2_CLKRST_CLAMP_ENABLE] = { 0x28a04, 7 }, -+ [UBI2_CORE_CLAMP_ENABLE] = { 0x28a04, 6 }, -+ [UBI1_CLKRST_CLAMP_ENABLE] = { 0x28a04, 5 }, -+ [UBI1_CORE_CLAMP_ENABLE] = { 0x28a04, 4 }, -+ [UBI0_CLKRST_CLAMP_ENABLE] = { 0x28a04, 3 }, -+ [UBI0_CORE_CLAMP_ENABLE] = { 0x28a04, 2 }, -+ [NSSNOC_NSS_CSR_ARES] = { 0x28a04, 1 }, -+ [NSS_CSR_ARES] = { 0x28a04, 0 }, -+ [PPE_BTQ_ARES] = { 0x28a08, 20 }, -+ [PPE_IPE_ARES] = { 0x28a08, 19 }, -+ [PPE_ARES] = { 0x28a08, 18 }, -+ [PPE_CFG_ARES] = { 0x28a08, 17 }, -+ [PPE_EDMA_ARES] = { 0x28a08, 16 }, -+ [PPE_EDMA_CFG_ARES] = { 0x28a08, 15 }, -+ [CRY_PPE_ARES] = { 0x28a08, 14 }, -+ [NSSNOC_PPE_ARES] = { 0x28a08, 13 }, -+ [NSSNOC_PPE_CFG_ARES] = { 0x28a08, 12 }, -+ [PORT1_MAC_ARES] = { 0x28a08, 11 }, -+ [PORT2_MAC_ARES] = { 0x28a08, 10 }, -+ [PORT3_MAC_ARES] = { 0x28a08, 9 }, -+ [PORT4_MAC_ARES] = { 0x28a08, 8 }, -+ [PORT5_MAC_ARES] = { 0x28a08, 7 }, -+ [PORT6_MAC_ARES] = { 0x28a08, 6 }, -+ [XGMAC0_PTP_REF_ARES] = { 0x28a08, 5 }, -+ [XGMAC1_PTP_REF_ARES] = { 0x28a08, 4 }, -+ [XGMAC2_PTP_REF_ARES] = { 0x28a08, 3 }, -+ [XGMAC3_PTP_REF_ARES] = { 0x28a08, 2 }, -+ [XGMAC4_PTP_REF_ARES] = { 0x28a08, 1 }, -+ [XGMAC5_PTP_REF_ARES] = { 0x28a08, 0 }, -+ [HAQ_AHB_ARES] = { 0x28a0c, 3 }, -+ [HAQ_AXI_ARES] = { 0x28a0c, 2 }, -+ [NSSNOC_HAQ_AHB_ARES] = { 0x28a0c, 1 }, -+ [NSSNOC_HAQ_AXI_ARES] = { 0x28a0c, 0 }, -+ [CE_APB_ARES] = { 0x28a10, 3 }, -+ [CE_AXI_ARES] = { 0x28a10, 2 }, -+ [NSSNOC_CE_APB_ARES] = { 0x28a10, 1 }, -+ [NSSNOC_CE_AXI_ARES] = { 0x28a10, 0 }, -+ [CRYPTO_ARES] = { 0x28a14, 1 }, -+ [NSSNOC_CRYPTO_ARES] = { 0x28a14, 0 }, -+ [NSSNOC_NC_AXI0_1_ARES] = { 0x28a1c, 28 }, -+ [UBI0_CORE_ARES] = { 0x28a1c, 27 }, -+ [UBI1_CORE_ARES] = { 0x28a1c, 26 }, -+ [UBI2_CORE_ARES] = { 0x28a1c, 25 }, -+ [UBI3_CORE_ARES] = { 0x28a1c, 24 }, -+ [NC_AXI0_ARES] = { 0x28a1c, 23 }, -+ [UTCM0_ARES] = { 0x28a1c, 22 }, -+ [NC_AXI1_ARES] = { 0x28a1c, 21 }, -+ [UTCM1_ARES] = { 0x28a1c, 20 }, -+ [NC_AXI2_ARES] = { 0x28a1c, 19 }, -+ [UTCM2_ARES] = { 0x28a1c, 18 }, -+ [NC_AXI3_ARES] = { 0x28a1c, 17 }, -+ [UTCM3_ARES] = { 0x28a1c, 16 }, -+ [NSSNOC_NC_AXI0_ARES] = { 0x28a1c, 15 }, -+ [AHB0_ARES] = { 0x28a1c, 14 }, -+ [INTR0_AHB_ARES] = { 0x28a1c, 13 }, -+ [AHB1_ARES] = { 0x28a1c, 12 }, -+ [INTR1_AHB_ARES] = { 0x28a1c, 11 }, -+ [AHB2_ARES] = { 0x28a1c, 10 }, -+ [INTR2_AHB_ARES] = { 0x28a1c, 9 }, -+ [AHB3_ARES] = { 0x28a1c, 8 }, -+ [INTR3_AHB_ARES] = { 0x28a1c, 7 }, -+ [NSSNOC_AHB0_ARES] = { 0x28a1c, 6 }, -+ [NSSNOC_INT0_AHB_ARES] = { 0x28a1c, 5 }, -+ [AXI0_ARES] = { 0x28a1c, 4 }, -+ [AXI1_ARES] = { 0x28a1c, 3 }, -+ [AXI2_ARES] = { 0x28a1c, 2 }, -+ [AXI3_ARES] = { 0x28a1c, 1 }, -+ [NSSNOC_AXI0_ARES] = { 0x28a1c, 0 }, -+ [IMEM_QSB_ARES] = { 0x28a20, 3 }, -+ [NSSNOC_IMEM_QSB_ARES] = { 0x28a20, 2 }, -+ [IMEM_AHB_ARES] = { 0x28a20, 1 }, -+ [NSSNOC_IMEM_AHB_ARES] = { 0x28a20, 0 }, -+ [UNIPHY_PORT1_RX_ARES] = { 0x28a24, 23 }, -+ [UNIPHY_PORT1_TX_ARES] = { 0x28a24, 22 }, -+ [UNIPHY_PORT2_RX_ARES] = { 0x28a24, 21 }, -+ [UNIPHY_PORT2_TX_ARES] = { 0x28a24, 20 }, -+ [UNIPHY_PORT3_RX_ARES] = { 0x28a24, 19 }, -+ [UNIPHY_PORT3_TX_ARES] = { 0x28a24, 18 }, -+ [UNIPHY_PORT4_RX_ARES] = { 0x28a24, 17 }, -+ [UNIPHY_PORT4_TX_ARES] = { 0x28a24, 16 }, -+ [UNIPHY_PORT5_RX_ARES] = { 0x28a24, 15 }, -+ [UNIPHY_PORT5_TX_ARES] = { 0x28a24, 14 }, -+ [UNIPHY_PORT6_RX_ARES] = { 0x28a24, 13 }, -+ [UNIPHY_PORT6_TX_ARES] = { 0x28a24, 12 }, -+ [PORT1_RX_ARES] = { 0x28a24, 11 }, -+ [PORT1_TX_ARES] = { 0x28a24, 10 }, -+ [PORT2_RX_ARES] = { 0x28a24, 9 }, -+ [PORT2_TX_ARES] = { 0x28a24, 8 }, -+ [PORT3_RX_ARES] = { 0x28a24, 7 }, -+ [PORT3_TX_ARES] = { 0x28a24, 6 }, -+ [PORT4_RX_ARES] = { 0x28a24, 5 }, -+ [PORT4_TX_ARES] = { 0x28a24, 4 }, -+ [PORT5_RX_ARES] = { 0x28a24, 3 }, -+ [PORT5_TX_ARES] = { 0x28a24, 2 }, -+ [PORT6_RX_ARES] = { 0x28a24, 1 }, -+ [PORT6_TX_ARES] = { 0x28a24, 0 }, -+ [PPE_FULL_RESET] = { .reg = 0x28a08, .bitmask = GENMASK(20, 17) }, -+ [UNIPHY0_SOFT_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(23, 14) }, -+ [UNIPHY1_SOFT_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(15, 14) }, -+ [UNIPHY2_SOFT_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(13, 12) }, -+ [UNIPHY_PORT1_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(23, 22) }, -+ [UNIPHY_PORT2_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(21, 20) }, -+ [UNIPHY_PORT3_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(19, 18) }, -+ [UNIPHY_PORT4_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(17, 16) }, -+ [UNIPHY_PORT5_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(15, 14) }, -+ [UNIPHY_PORT6_ARES] = { .reg = 0x28a24, .bitmask = GENMASK(13, 12) }, -+ [NSSPORT1_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(11, 10) }, -+ [NSSPORT2_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(9, 8) }, -+ [NSSPORT3_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(7, 6) }, -+ [NSSPORT4_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(5, 4) }, -+ [NSSPORT5_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(3, 2) }, -+ [NSSPORT6_RESET] = { .reg = 0x28a24, .bitmask = GENMASK(1, 0) }, -+ [EDMA_HW_RESET] = { .reg = 0x28a08, .bitmask = GENMASK(16, 15) }, -+}; -+ -+static const struct regmap_config nss_cc_ipq9574_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = 0x28a34, -+ .fast_io = true, -+}; -+ -+static struct qcom_icc_hws_data icc_ipq9574_nss_hws[] = { -+ { MASTER_NSSNOC_PPE, SLAVE_NSSNOC_PPE, NSS_CC_NSSNOC_PPE_CLK }, -+ { MASTER_NSSNOC_PPE_CFG, SLAVE_NSSNOC_PPE_CFG, NSS_CC_NSSNOC_PPE_CFG_CLK }, -+ { MASTER_NSSNOC_NSS_CSR, SLAVE_NSSNOC_NSS_CSR, NSS_CC_NSSNOC_NSS_CSR_CLK }, -+ { MASTER_NSSNOC_IMEM_QSB, SLAVE_NSSNOC_IMEM_QSB, NSS_CC_NSSNOC_IMEM_QSB_CLK }, -+ { MASTER_NSSNOC_IMEM_AHB, SLAVE_NSSNOC_IMEM_AHB, NSS_CC_NSSNOC_IMEM_AHB_CLK }, -+}; -+ -+#define IPQ_NSSCC_ID (9574 * 2) /* some unique value */ -+ -+static const struct qcom_cc_desc nss_cc_ipq9574_desc = { -+ .config = &nss_cc_ipq9574_regmap_config, -+ .clks = nss_cc_ipq9574_clocks, -+ .num_clks = ARRAY_SIZE(nss_cc_ipq9574_clocks), -+ .resets = nss_cc_ipq9574_resets, -+ .num_resets = ARRAY_SIZE(nss_cc_ipq9574_resets), -+ .icc_hws = icc_ipq9574_nss_hws, -+ .num_icc_hws = ARRAY_SIZE(icc_ipq9574_nss_hws), -+ .icc_first_node_id = IPQ_NSSCC_ID, -+}; -+ -+static const struct dev_pm_ops nss_cc_ipq9574_pm_ops = { -+ SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) -+}; -+ -+static const struct of_device_id nss_cc_ipq9574_match_table[] = { -+ { .compatible = "qcom,ipq9574-nsscc" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, nss_cc_ipq9574_match_table); -+ -+static int nss_cc_ipq9574_probe(struct platform_device *pdev) -+{ -+ struct regmap *regmap; -+ int ret; -+ -+ ret = devm_pm_runtime_enable(&pdev->dev); -+ if (ret) -+ return dev_err_probe(&pdev->dev, ret, "Fail to enable runtime PM\n"); -+ -+ ret = devm_pm_clk_create(&pdev->dev); -+ if (ret) -+ return dev_err_probe(&pdev->dev, ret, "Fail to create PM clock\n"); -+ -+ ret = pm_clk_add(&pdev->dev, "bus"); -+ if (ret) -+ return dev_err_probe(&pdev->dev, ret, "Fail to add bus clock\n"); -+ -+ ret = pm_runtime_resume_and_get(&pdev->dev); -+ if (ret) -+ return dev_err_probe(&pdev->dev, ret, "Fail to resume\n"); -+ -+ regmap = qcom_cc_map(pdev, &nss_cc_ipq9574_desc); -+ if (IS_ERR(regmap)) { -+ pm_runtime_put(&pdev->dev); -+ return dev_err_probe(&pdev->dev, PTR_ERR(regmap), -+ "Fail to map clock controller registers\n"); -+ } -+ -+ clk_alpha_pll_configure(&ubi32_pll_main, regmap, &ubi32_pll_config); -+ -+ ret = qcom_cc_really_probe(&pdev->dev, &nss_cc_ipq9574_desc, regmap); -+ pm_runtime_put(&pdev->dev); -+ -+ return ret; -+} -+ -+static struct platform_driver nss_cc_ipq9574_driver = { -+ .probe = nss_cc_ipq9574_probe, -+ .driver = { -+ .name = "qcom,nsscc-ipq9574", -+ .of_match_table = nss_cc_ipq9574_match_table, -+ .pm = &nss_cc_ipq9574_pm_ops, -+ .sync_state = icc_sync_state, -+ }, -+}; -+ -+module_platform_driver(nss_cc_ipq9574_driver); -+ -+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. NSSCC IPQ9574 Driver"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/qualcommbe/patches-6.12/0022-v6.15-arm64-defconfig-Build-NSS-Clock-Controller-dri.patch b/target/linux/qualcommbe/patches-6.12/0022-v6.15-arm64-defconfig-Build-NSS-Clock-Controller-dri.patch deleted file mode 100644 index 2a2ad000c2..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0022-v6.15-arm64-defconfig-Build-NSS-Clock-Controller-dri.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 8f1b61ea1cb98735aa15a8875d729c21a2169fb9 Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:59 +0530 -Subject: [PATCH 22/22] v6.15: arm64: defconfig: Build NSS Clock Controller - driver for IPQ9574 - -NSSCC driver is needed to enable the ethernet interfaces present -in RDP433 based on IPQ9574. Since this is not necessary for bootup -enabling it as a module. - -Reviewed-by: Krzysztof Kozlowski -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-7-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/configs/defconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/configs/defconfig -+++ b/arch/arm64/configs/defconfig -@@ -1312,6 +1312,7 @@ CONFIG_IPQ_GCC_5332=y - CONFIG_IPQ_GCC_6018=y - CONFIG_IPQ_GCC_8074=y - CONFIG_IPQ_GCC_9574=y -+CONFIG_IPQ_NSSCC_9574=m - CONFIG_MSM_GCC_8916=y - CONFIG_MSM_MMCC_8994=m - CONFIG_MSM_GCC_8994=y diff --git a/target/linux/qualcommbe/patches-6.12/0023-v6.15-net-phy-move-PHY-package-code-from-phy_device..patch b/target/linux/qualcommbe/patches-6.12/0023-v6.15-net-phy-move-PHY-package-code-from-phy_device..patch deleted file mode 100644 index 3ea7f813d6..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0023-v6.15-net-phy-move-PHY-package-code-from-phy_device..patch +++ /dev/null @@ -1,524 +0,0 @@ -From 986ec7ee75f2f1f7f93eb0e05f61f297f6123fce Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 3 Mar 2025 21:14:02 +0100 -Subject: [PATCH] v6.15: net: phy: move PHY package code from phy_device.c to - own source file - -This patch is the first step in moving the PHY package related code -to its own source file. No functional change intended. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/57df5c19-fbcd-45a7-9afd-cd4f74d7fa76@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/Makefile | 3 +- - drivers/net/phy/phy_device.c | 237 --------------------------------- - drivers/net/phy/phy_package.c | 244 ++++++++++++++++++++++++++++++++++ - 3 files changed, 246 insertions(+), 238 deletions(-) - create mode 100644 drivers/net/phy/phy_package.c - ---- a/drivers/net/phy/Makefile -+++ b/drivers/net/phy/Makefile -@@ -2,7 +2,8 @@ - # Makefile for Linux PHY drivers - - libphy-y := phy.o phy-c45.o phy-core.o phy_device.o \ -- linkmode.o phy_link_topology.o -+ linkmode.o phy_link_topology.o \ -+ phy_package.o - mdio-bus-y += mdio_bus.o mdio_device.o - - ifdef CONFIG_MDIO_DEVICE ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -1781,243 +1781,6 @@ bool phy_driver_is_genphy_10g(struct phy - EXPORT_SYMBOL_GPL(phy_driver_is_genphy_10g); - - /** -- * phy_package_join - join a common PHY group -- * @phydev: target phy_device struct -- * @base_addr: cookie and base PHY address of PHY package for offset -- * calculation of global register access -- * @priv_size: if non-zero allocate this amount of bytes for private data -- * -- * This joins a PHY group and provides a shared storage for all phydevs in -- * this group. This is intended to be used for packages which contain -- * more than one PHY, for example a quad PHY transceiver. -- * -- * The base_addr parameter serves as cookie which has to have the same values -- * for all members of one group and as the base PHY address of the PHY package -- * for offset calculation to access generic registers of a PHY package. -- * Usually, one of the PHY addresses of the different PHYs in the package -- * provides access to these global registers. -- * The address which is given here, will be used in the phy_package_read() -- * and phy_package_write() convenience functions as base and added to the -- * passed offset in those functions. -- * -- * This will set the shared pointer of the phydev to the shared storage. -- * If this is the first call for a this cookie the shared storage will be -- * allocated. If priv_size is non-zero, the given amount of bytes are -- * allocated for the priv member. -- * -- * Returns < 1 on error, 0 on success. Esp. calling phy_package_join() -- * with the same cookie but a different priv_size is an error. -- */ --int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size) --{ -- struct mii_bus *bus = phydev->mdio.bus; -- struct phy_package_shared *shared; -- int ret; -- -- if (base_addr < 0 || base_addr >= PHY_MAX_ADDR) -- return -EINVAL; -- -- mutex_lock(&bus->shared_lock); -- shared = bus->shared[base_addr]; -- if (!shared) { -- ret = -ENOMEM; -- shared = kzalloc(sizeof(*shared), GFP_KERNEL); -- if (!shared) -- goto err_unlock; -- if (priv_size) { -- shared->priv = kzalloc(priv_size, GFP_KERNEL); -- if (!shared->priv) -- goto err_free; -- shared->priv_size = priv_size; -- } -- shared->base_addr = base_addr; -- shared->np = NULL; -- refcount_set(&shared->refcnt, 1); -- bus->shared[base_addr] = shared; -- } else { -- ret = -EINVAL; -- if (priv_size && priv_size != shared->priv_size) -- goto err_unlock; -- refcount_inc(&shared->refcnt); -- } -- mutex_unlock(&bus->shared_lock); -- -- phydev->shared = shared; -- -- return 0; -- --err_free: -- kfree(shared); --err_unlock: -- mutex_unlock(&bus->shared_lock); -- return ret; --} --EXPORT_SYMBOL_GPL(phy_package_join); -- --/** -- * of_phy_package_join - join a common PHY group in PHY package -- * @phydev: target phy_device struct -- * @priv_size: if non-zero allocate this amount of bytes for private data -- * -- * This is a variant of phy_package_join for PHY package defined in DT. -- * -- * The parent node of the @phydev is checked as a valid PHY package node -- * structure (by matching the node name "ethernet-phy-package") and the -- * base_addr for the PHY package is passed to phy_package_join. -- * -- * With this configuration the shared struct will also have the np value -- * filled to use additional DT defined properties in PHY specific -- * probe_once and config_init_once PHY package OPs. -- * -- * Returns < 0 on error, 0 on success. Esp. calling phy_package_join() -- * with the same cookie but a different priv_size is an error. Or a parent -- * node is not detected or is not valid or doesn't match the expected node -- * name for PHY package. -- */ --int of_phy_package_join(struct phy_device *phydev, size_t priv_size) --{ -- struct device_node *node = phydev->mdio.dev.of_node; -- struct device_node *package_node; -- u32 base_addr; -- int ret; -- -- if (!node) -- return -EINVAL; -- -- package_node = of_get_parent(node); -- if (!package_node) -- return -EINVAL; -- -- if (!of_node_name_eq(package_node, "ethernet-phy-package")) { -- ret = -EINVAL; -- goto exit; -- } -- -- if (of_property_read_u32(package_node, "reg", &base_addr)) { -- ret = -EINVAL; -- goto exit; -- } -- -- ret = phy_package_join(phydev, base_addr, priv_size); -- if (ret) -- goto exit; -- -- phydev->shared->np = package_node; -- -- return 0; --exit: -- of_node_put(package_node); -- return ret; --} --EXPORT_SYMBOL_GPL(of_phy_package_join); -- --/** -- * phy_package_leave - leave a common PHY group -- * @phydev: target phy_device struct -- * -- * This leaves a PHY group created by phy_package_join(). If this phydev -- * was the last user of the shared data between the group, this data is -- * freed. Resets the phydev->shared pointer to NULL. -- */ --void phy_package_leave(struct phy_device *phydev) --{ -- struct phy_package_shared *shared = phydev->shared; -- struct mii_bus *bus = phydev->mdio.bus; -- -- if (!shared) -- return; -- -- /* Decrease the node refcount on leave if present */ -- if (shared->np) -- of_node_put(shared->np); -- -- if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { -- bus->shared[shared->base_addr] = NULL; -- mutex_unlock(&bus->shared_lock); -- kfree(shared->priv); -- kfree(shared); -- } -- -- phydev->shared = NULL; --} --EXPORT_SYMBOL_GPL(phy_package_leave); -- --static void devm_phy_package_leave(struct device *dev, void *res) --{ -- phy_package_leave(*(struct phy_device **)res); --} -- --/** -- * devm_phy_package_join - resource managed phy_package_join() -- * @dev: device that is registering this PHY package -- * @phydev: target phy_device struct -- * @base_addr: cookie and base PHY address of PHY package for offset -- * calculation of global register access -- * @priv_size: if non-zero allocate this amount of bytes for private data -- * -- * Managed phy_package_join(). Shared storage fetched by this function, -- * phy_package_leave() is automatically called on driver detach. See -- * phy_package_join() for more information. -- */ --int devm_phy_package_join(struct device *dev, struct phy_device *phydev, -- int base_addr, size_t priv_size) --{ -- struct phy_device **ptr; -- int ret; -- -- ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), -- GFP_KERNEL); -- if (!ptr) -- return -ENOMEM; -- -- ret = phy_package_join(phydev, base_addr, priv_size); -- -- if (!ret) { -- *ptr = phydev; -- devres_add(dev, ptr); -- } else { -- devres_free(ptr); -- } -- -- return ret; --} --EXPORT_SYMBOL_GPL(devm_phy_package_join); -- --/** -- * devm_of_phy_package_join - resource managed of_phy_package_join() -- * @dev: device that is registering this PHY package -- * @phydev: target phy_device struct -- * @priv_size: if non-zero allocate this amount of bytes for private data -- * -- * Managed of_phy_package_join(). Shared storage fetched by this function, -- * phy_package_leave() is automatically called on driver detach. See -- * of_phy_package_join() for more information. -- */ --int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, -- size_t priv_size) --{ -- struct phy_device **ptr; -- int ret; -- -- ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), -- GFP_KERNEL); -- if (!ptr) -- return -ENOMEM; -- -- ret = of_phy_package_join(phydev, priv_size); -- -- if (!ret) { -- *ptr = phydev; -- devres_add(dev, ptr); -- } else { -- devres_free(ptr); -- } -- -- return ret; --} --EXPORT_SYMBOL_GPL(devm_of_phy_package_join); -- --/** - * phy_detach - detach a PHY device from its network device - * @phydev: target phy_device struct - * ---- /dev/null -+++ b/drivers/net/phy/phy_package.c -@@ -0,0 +1,244 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * PHY package support -+ */ -+ -+#include -+#include -+ -+/** -+ * phy_package_join - join a common PHY group -+ * @phydev: target phy_device struct -+ * @base_addr: cookie and base PHY address of PHY package for offset -+ * calculation of global register access -+ * @priv_size: if non-zero allocate this amount of bytes for private data -+ * -+ * This joins a PHY group and provides a shared storage for all phydevs in -+ * this group. This is intended to be used for packages which contain -+ * more than one PHY, for example a quad PHY transceiver. -+ * -+ * The base_addr parameter serves as cookie which has to have the same values -+ * for all members of one group and as the base PHY address of the PHY package -+ * for offset calculation to access generic registers of a PHY package. -+ * Usually, one of the PHY addresses of the different PHYs in the package -+ * provides access to these global registers. -+ * The address which is given here, will be used in the phy_package_read() -+ * and phy_package_write() convenience functions as base and added to the -+ * passed offset in those functions. -+ * -+ * This will set the shared pointer of the phydev to the shared storage. -+ * If this is the first call for a this cookie the shared storage will be -+ * allocated. If priv_size is non-zero, the given amount of bytes are -+ * allocated for the priv member. -+ * -+ * Returns < 1 on error, 0 on success. Esp. calling phy_package_join() -+ * with the same cookie but a different priv_size is an error. -+ */ -+int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size) -+{ -+ struct mii_bus *bus = phydev->mdio.bus; -+ struct phy_package_shared *shared; -+ int ret; -+ -+ if (base_addr < 0 || base_addr >= PHY_MAX_ADDR) -+ return -EINVAL; -+ -+ mutex_lock(&bus->shared_lock); -+ shared = bus->shared[base_addr]; -+ if (!shared) { -+ ret = -ENOMEM; -+ shared = kzalloc(sizeof(*shared), GFP_KERNEL); -+ if (!shared) -+ goto err_unlock; -+ if (priv_size) { -+ shared->priv = kzalloc(priv_size, GFP_KERNEL); -+ if (!shared->priv) -+ goto err_free; -+ shared->priv_size = priv_size; -+ } -+ shared->base_addr = base_addr; -+ shared->np = NULL; -+ refcount_set(&shared->refcnt, 1); -+ bus->shared[base_addr] = shared; -+ } else { -+ ret = -EINVAL; -+ if (priv_size && priv_size != shared->priv_size) -+ goto err_unlock; -+ refcount_inc(&shared->refcnt); -+ } -+ mutex_unlock(&bus->shared_lock); -+ -+ phydev->shared = shared; -+ -+ return 0; -+ -+err_free: -+ kfree(shared); -+err_unlock: -+ mutex_unlock(&bus->shared_lock); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(phy_package_join); -+ -+/** -+ * of_phy_package_join - join a common PHY group in PHY package -+ * @phydev: target phy_device struct -+ * @priv_size: if non-zero allocate this amount of bytes for private data -+ * -+ * This is a variant of phy_package_join for PHY package defined in DT. -+ * -+ * The parent node of the @phydev is checked as a valid PHY package node -+ * structure (by matching the node name "ethernet-phy-package") and the -+ * base_addr for the PHY package is passed to phy_package_join. -+ * -+ * With this configuration the shared struct will also have the np value -+ * filled to use additional DT defined properties in PHY specific -+ * probe_once and config_init_once PHY package OPs. -+ * -+ * Returns < 0 on error, 0 on success. Esp. calling phy_package_join() -+ * with the same cookie but a different priv_size is an error. Or a parent -+ * node is not detected or is not valid or doesn't match the expected node -+ * name for PHY package. -+ */ -+int of_phy_package_join(struct phy_device *phydev, size_t priv_size) -+{ -+ struct device_node *node = phydev->mdio.dev.of_node; -+ struct device_node *package_node; -+ u32 base_addr; -+ int ret; -+ -+ if (!node) -+ return -EINVAL; -+ -+ package_node = of_get_parent(node); -+ if (!package_node) -+ return -EINVAL; -+ -+ if (!of_node_name_eq(package_node, "ethernet-phy-package")) { -+ ret = -EINVAL; -+ goto exit; -+ } -+ -+ if (of_property_read_u32(package_node, "reg", &base_addr)) { -+ ret = -EINVAL; -+ goto exit; -+ } -+ -+ ret = phy_package_join(phydev, base_addr, priv_size); -+ if (ret) -+ goto exit; -+ -+ phydev->shared->np = package_node; -+ -+ return 0; -+exit: -+ of_node_put(package_node); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(of_phy_package_join); -+ -+/** -+ * phy_package_leave - leave a common PHY group -+ * @phydev: target phy_device struct -+ * -+ * This leaves a PHY group created by phy_package_join(). If this phydev -+ * was the last user of the shared data between the group, this data is -+ * freed. Resets the phydev->shared pointer to NULL. -+ */ -+void phy_package_leave(struct phy_device *phydev) -+{ -+ struct phy_package_shared *shared = phydev->shared; -+ struct mii_bus *bus = phydev->mdio.bus; -+ -+ if (!shared) -+ return; -+ -+ /* Decrease the node refcount on leave if present */ -+ if (shared->np) -+ of_node_put(shared->np); -+ -+ if (refcount_dec_and_mutex_lock(&shared->refcnt, &bus->shared_lock)) { -+ bus->shared[shared->base_addr] = NULL; -+ mutex_unlock(&bus->shared_lock); -+ kfree(shared->priv); -+ kfree(shared); -+ } -+ -+ phydev->shared = NULL; -+} -+EXPORT_SYMBOL_GPL(phy_package_leave); -+ -+static void devm_phy_package_leave(struct device *dev, void *res) -+{ -+ phy_package_leave(*(struct phy_device **)res); -+} -+ -+/** -+ * devm_phy_package_join - resource managed phy_package_join() -+ * @dev: device that is registering this PHY package -+ * @phydev: target phy_device struct -+ * @base_addr: cookie and base PHY address of PHY package for offset -+ * calculation of global register access -+ * @priv_size: if non-zero allocate this amount of bytes for private data -+ * -+ * Managed phy_package_join(). Shared storage fetched by this function, -+ * phy_package_leave() is automatically called on driver detach. See -+ * phy_package_join() for more information. -+ */ -+int devm_phy_package_join(struct device *dev, struct phy_device *phydev, -+ int base_addr, size_t priv_size) -+{ -+ struct phy_device **ptr; -+ int ret; -+ -+ ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), -+ GFP_KERNEL); -+ if (!ptr) -+ return -ENOMEM; -+ -+ ret = phy_package_join(phydev, base_addr, priv_size); -+ -+ if (!ret) { -+ *ptr = phydev; -+ devres_add(dev, ptr); -+ } else { -+ devres_free(ptr); -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(devm_phy_package_join); -+ -+/** -+ * devm_of_phy_package_join - resource managed of_phy_package_join() -+ * @dev: device that is registering this PHY package -+ * @phydev: target phy_device struct -+ * @priv_size: if non-zero allocate this amount of bytes for private data -+ * -+ * Managed of_phy_package_join(). Shared storage fetched by this function, -+ * phy_package_leave() is automatically called on driver detach. See -+ * of_phy_package_join() for more information. -+ */ -+int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, -+ size_t priv_size) -+{ -+ struct phy_device **ptr; -+ int ret; -+ -+ ptr = devres_alloc(devm_phy_package_leave, sizeof(*ptr), -+ GFP_KERNEL); -+ if (!ptr) -+ return -ENOMEM; -+ -+ ret = of_phy_package_join(phydev, priv_size); -+ -+ if (!ret) { -+ *ptr = phydev; -+ devres_add(dev, ptr); -+ } else { -+ devres_free(ptr); -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(devm_of_phy_package_join); diff --git a/target/linux/qualcommbe/patches-6.12/0024-v6.15-net-phy-add-getters-for-public-members-in-stru.patch b/target/linux/qualcommbe/patches-6.12/0024-v6.15-net-phy-add-getters-for-public-members-in-stru.patch deleted file mode 100644 index a05083d6fe..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0024-v6.15-net-phy-add-getters-for-public-members-in-stru.patch +++ /dev/null @@ -1,60 +0,0 @@ -From e9ee1dd2ff2c130b2fb2bd01936224a8a6b49a7e Mon Sep 17 00:00:00 2001 -From: Heiner Kallweit -Date: Mon, 3 Mar 2025 21:15:09 +0100 -Subject: [PATCH] v6.15: net: phy: add getters for public members in struct - phy_package_shared - -Add getters for public members, this prepares for making struct -phy_package_shared private to phylib. Declare the getters in a new header -file phylib.h, which will be used by PHY drivers only. - -Signed-off-by: Heiner Kallweit -Link: https://patch.msgid.link/c6da0b27-4479-4717-9e16-643821b76bd8@gmail.com -Signed-off-by: Jakub Kicinski ---- - drivers/net/phy/phy_package.c | 14 ++++++++++++++ - drivers/net/phy/phylib.h | 15 +++++++++++++++ - 2 files changed, 29 insertions(+) - create mode 100644 drivers/net/phy/phylib.h - ---- a/drivers/net/phy/phy_package.c -+++ b/drivers/net/phy/phy_package.c -@@ -6,6 +6,20 @@ - #include - #include - -+#include "phylib.h" -+ -+struct device_node *phy_package_get_node(struct phy_device *phydev) -+{ -+ return phydev->shared->np; -+} -+EXPORT_SYMBOL_GPL(phy_package_get_node); -+ -+void *phy_package_get_priv(struct phy_device *phydev) -+{ -+ return phydev->shared->priv; -+} -+EXPORT_SYMBOL_GPL(phy_package_get_priv); -+ - /** - * phy_package_join - join a common PHY group - * @phydev: target phy_device struct ---- /dev/null -+++ b/drivers/net/phy/phylib.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+/* -+ * phylib header -+ */ -+ -+#ifndef __PHYLIB_H -+#define __PHYLIB_H -+ -+struct device_node; -+struct phy_device; -+ -+struct device_node *phy_package_get_node(struct phy_device *phydev); -+void *phy_package_get_priv(struct phy_device *phydev); -+ -+#endif /* __PHYLIB_H */ diff --git a/target/linux/qualcommbe/patches-6.12/0100-arm64-dts-qcom-ipq9574-Add-nsscc-node.patch b/target/linux/qualcommbe/patches-6.12/0100-arm64-dts-qcom-ipq9574-Add-nsscc-node.patch deleted file mode 100644 index c38a7eb09f..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0100-arm64-dts-qcom-ipq9574-Add-nsscc-node.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 52ebd52aa1906961142a2aba55d47a53b956847c Mon Sep 17 00:00:00 2001 -From: Devi Priya -Date: Thu, 13 Mar 2025 16:33:58 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq9574: Add nsscc node - -Add a node for the nss clock controller found on ipq9574 based devices. - -Reviewed-by: Konrad Dybcio -Signed-off-by: Devi Priya -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313110359.242491-6-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 29 +++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -1195,6 +1195,35 @@ - status = "disabled"; - }; - -+ nsscc: clock-controller@39b00000 { -+ compatible = "qcom,ipq9574-nsscc"; -+ reg = <0x39b00000 0x80000>; -+ clocks = <&xo_board_clk>, -+ <&cmn_pll NSS_1200MHZ_CLK>, -+ <&cmn_pll PPE_353MHZ_CLK>, -+ <&gcc GPLL0_OUT_AUX>, -+ <0>, -+ <0>, -+ <0>, -+ <0>, -+ <0>, -+ <0>, -+ <&gcc GCC_NSSCC_CLK>; -+ clock-names = "xo", -+ "nss_1200", -+ "ppe_353", -+ "gpll0_out", -+ "uniphy0_rx", -+ "uniphy0_tx", -+ "uniphy1_rx", -+ "uniphy1_tx", -+ "uniphy2_rx", -+ "uniphy2_tx", -+ "bus"; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ #interconnect-cells = <1>; -+ }; - }; - - thermal-zones { diff --git a/target/linux/qualcommbe/patches-6.12/0101-arm64-dts-qcom-ipq9574-fix-the-msi-interrupt-numbers.patch b/target/linux/qualcommbe/patches-6.12/0101-arm64-dts-qcom-ipq9574-fix-the-msi-interrupt-numbers.patch deleted file mode 100644 index b09fccf32b..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0101-arm64-dts-qcom-ipq9574-fix-the-msi-interrupt-numbers.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 2f2f5ae4d52ea882ba58f6b2fa6373a3d3db2bce Mon Sep 17 00:00:00 2001 -From: Manikanta Mylavarapu -Date: Thu, 13 Mar 2025 12:44:22 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq9574: fix the msi interrupt numbers of - pcie3 - -The MSI interrupt numbers of the PCIe3 controller are incorrect. Due -to this, the functional bring up of the QDSP6 processor on the PCIe -endpoint has failed. Correct the MSI interrupt numbers to properly -bring up the QDSP6 processor on the PCIe endpoint. - -Fixes: d80c7fbfa908 ("arm64: dts: qcom: ipq9574: Add PCIe PHYs and controller nodes") -Signed-off-by: Manikanta Mylavarapu -Link: https://lore.kernel.org/r/20250313071422.510-1-quic_mmanikan@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -974,14 +974,14 @@ - ranges = <0x01000000 0x0 0x00000000 0x18200000 0x0 0x100000>, - <0x02000000 0x0 0x18300000 0x18300000 0x0 0x7d00000>; - -- interrupts = , -- , -- , -- , -- , -- , -- , -- ; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; - interrupt-names = "msi0", - "msi1", - "msi2", diff --git a/target/linux/qualcommbe/patches-6.12/0103-arm64-dts-qcom-ipq9574-Add-SPI-nand-support.patch b/target/linux/qualcommbe/patches-6.12/0103-arm64-dts-qcom-ipq9574-Add-SPI-nand-support.patch deleted file mode 100644 index 7bec20d943..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0103-arm64-dts-qcom-ipq9574-Add-SPI-nand-support.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 583299efa34c4a484b211f84c63aee78b6c2b469 Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Thu, 6 Mar 2025 17:03:55 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq9574: Add SPI nand support - -Add SPI NAND support for ipq9574 SoC. - -Signed-off-by: Md Sadre Alam -Link: https://lore.kernel.org/r/20250306113357.126602-2-quic_mdalam@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -675,6 +675,33 @@ - status = "disabled"; - }; - -+ qpic_bam: dma-controller@7984000 { -+ compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0"; -+ reg = <0x07984000 0x1c000>; -+ interrupts = ; -+ clocks = <&gcc GCC_QPIC_AHB_CLK>; -+ clock-names = "bam_clk"; -+ #dma-cells = <1>; -+ qcom,ee = <0>; -+ status = "disabled"; -+ }; -+ -+ qpic_nand: spi@79b0000 { -+ compatible = "qcom,ipq9574-snand"; -+ reg = <0x079b0000 0x10000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ clocks = <&gcc GCC_QPIC_CLK>, -+ <&gcc GCC_QPIC_AHB_CLK>, -+ <&gcc GCC_QPIC_IO_MACRO_CLK>; -+ clock-names = "core", "aon", "iom"; -+ dmas = <&qpic_bam 0>, -+ <&qpic_bam 1>, -+ <&qpic_bam 2>; -+ dma-names = "tx", "rx", "cmd"; -+ status = "disabled"; -+ }; -+ - usb_0_qusbphy: phy@7b000 { - compatible = "qcom,ipq9574-qusb2-phy"; - reg = <0x0007b000 0x180>; diff --git a/target/linux/qualcommbe/patches-6.12/0104-arm64-dts-qcom-ipq9574-Enable-SPI-NAND-for-ipq9574.patch b/target/linux/qualcommbe/patches-6.12/0104-arm64-dts-qcom-ipq9574-Enable-SPI-NAND-for-ipq9574.patch deleted file mode 100644 index 393923a343..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0104-arm64-dts-qcom-ipq9574-Enable-SPI-NAND-for-ipq9574.patch +++ /dev/null @@ -1,68 +0,0 @@ -From a7c88bc81632974c0708308493aefb1f871b65fa Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Thu, 6 Mar 2025 17:03:56 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq9574: Enable SPI NAND for ipq9574 - -Enable SPI NAND support for ipq9574 SoC. - -Reviewed-by: Konrad Dybcio -Signed-off-by: Md Sadre Alam -Link: https://lore.kernel.org/r/20250306113357.126602-3-quic_mdalam@quicinc.com -Signed-off-by: Bjorn Andersson ---- - .../boot/dts/qcom/ipq9574-rdp-common.dtsi | 44 +++++++++++++++++++ - 1 file changed, 44 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -@@ -146,6 +146,50 @@ - drive-strength = <8>; - bias-pull-up; - }; -+ -+ qpic_snand_default_state: qpic-snand-default-state { -+ clock-pins { -+ pins = "gpio5"; -+ function = "qspi_clk"; -+ drive-strength = <8>; -+ bias-disable; -+ }; -+ -+ cs-pins { -+ pins = "gpio4"; -+ function = "qspi_cs"; -+ drive-strength = <8>; -+ bias-disable; -+ }; -+ -+ data-pins { -+ pins = "gpio0", "gpio1", "gpio2", "gpio3"; -+ function = "qspi_data"; -+ drive-strength = <8>; -+ bias-disable; -+ }; -+ }; -+}; -+ -+&qpic_bam { -+ status = "okay"; -+}; -+ -+&qpic_nand { -+ pinctrl-0 = <&qpic_snand_default_state>; -+ pinctrl-names = "default"; -+ -+ status = "okay"; -+ -+ flash@0 { -+ compatible = "spi-nand"; -+ reg = <0>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ nand-ecc-engine = <&qpic_nand>; -+ nand-ecc-strength = <4>; -+ nand-ecc-step-size = <512>; -+ }; - }; - - &usb_0_dwc3 { diff --git a/target/linux/qualcommbe/patches-6.12/0105-arm64-dts-qcom-ipq9574-Remove-eMMC-node.patch b/target/linux/qualcommbe/patches-6.12/0105-arm64-dts-qcom-ipq9574-Remove-eMMC-node.patch deleted file mode 100644 index d188539aaa..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0105-arm64-dts-qcom-ipq9574-Remove-eMMC-node.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0156e327aa854be5eb9cbec9d020be1026b5b446 Mon Sep 17 00:00:00 2001 -From: Md Sadre Alam -Date: Thu, 6 Mar 2025 17:03:57 +0530 -Subject: [PATCH] arm64: dts: qcom: ipq9574: Remove eMMC node - -Remove eMMC node for rdp433, since rdp433 -default boot mode is norplusnand - -Reviewed-by: Konrad Dybcio -Signed-off-by: Md Sadre Alam -Link: https://lore.kernel.org/r/20250306113357.126602-4-quic_mdalam@quicinc.com -Signed-off-by: Bjorn Andersson ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 12 ------------ - 1 file changed, 12 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -@@ -55,18 +55,6 @@ - status = "okay"; - }; - --&sdhc_1 { -- pinctrl-0 = <&sdc_default_state>; -- pinctrl-names = "default"; -- mmc-ddr-1_8v; -- mmc-hs200-1_8v; -- mmc-hs400-1_8v; -- mmc-hs400-enhanced-strobe; -- max-frequency = <384000000>; -- bus-width = <8>; -- status = "okay"; --}; -- - &tlmm { - - pcie1_default: pcie1-default-state { diff --git a/target/linux/qualcommbe/patches-6.12/0301-arm64-dts-qcom-Add-IPQ9574-MDIO-device-node.patch b/target/linux/qualcommbe/patches-6.12/0301-arm64-dts-qcom-Add-IPQ9574-MDIO-device-node.patch deleted file mode 100644 index c094e6e016..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0301-arm64-dts-qcom-Add-IPQ9574-MDIO-device-node.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 657833a74f532262d415fa2ca354b69f4a97353c Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Thu, 23 Nov 2023 15:41:20 +0800 -Subject: [PATCH] arm64: dts: qcom: Add IPQ9574 MDIO device node - -The MDIO bus master block is used to accessing the MDIO slave -device (such as PHY device), the dedicated MDIO PINs needs to -be configured. - -Change-Id: Ia64083529e693256dbd8f8af4071c02afdded8f9 -Signed-off-by: Luo Jie ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -295,6 +295,8 @@ - mdio: mdio@90000 { - compatible = "qcom,ipq9574-mdio", "qcom,ipq4019-mdio"; - reg = <0x00090000 0x64>; -+ pinctrl-0 = <&mdio_pins>; -+ pinctrl-names = "default"; - #address-cells = <1>; - #size-cells = <0>; - clocks = <&gcc GCC_MDIO_AHB_CLK>; -@@ -414,6 +416,22 @@ - interrupt-controller; - #interrupt-cells = <2>; - -+ mdio_pins: mdio-pins { -+ mdc-state { -+ pins = "gpio38"; -+ function = "mdc"; -+ drive-strength = <8>; -+ bias-disable; -+ }; -+ -+ mdio-state { -+ pins = "gpio39"; -+ function = "mdio"; -+ drive-strength = <8>; -+ bias-pull-up; -+ }; -+ }; -+ - uart2_pins: uart2-state { - pins = "gpio34", "gpio35"; - function = "blsp2_uart"; diff --git a/target/linux/qualcommbe/patches-6.12/0302-arm64-dts-qcom-ipq9574-Use-usb-phy-for-node-names.patch b/target/linux/qualcommbe/patches-6.12/0302-arm64-dts-qcom-ipq9574-Use-usb-phy-for-node-names.patch deleted file mode 100644 index cc7192158a..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0302-arm64-dts-qcom-ipq9574-Use-usb-phy-for-node-names.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 91467ca0db1654644b2168f882f223d47dcfb9c1 Mon Sep 17 00:00:00 2001 -From: Alexandru Gagniuc -Date: Sat, 30 Mar 2024 20:03:30 -0500 -Subject: [PATCH] arm64: dts: qcom: ipq9574: Use 'usb-phy' for node names - -The devicetree spec allows node names of "usb-phy". So be more -specific for the USB PHYs, and name the nodes "usb-phy" instead of -just "phy". - -Signed-off-by: Alexandru Gagniuc ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -720,7 +720,7 @@ - status = "disabled"; - }; - -- usb_0_qusbphy: phy@7b000 { -+ usb_0_qusbphy: usb-phy@7b000 { - compatible = "qcom,ipq9574-qusb2-phy"; - reg = <0x0007b000 0x180>; - #phy-cells = <0>; -@@ -734,7 +734,7 @@ - status = "disabled"; - }; - -- usb_0_qmpphy: phy@7d000 { -+ usb_0_qmpphy: usb-phy@7d000 { - compatible = "qcom,ipq9574-qmp-usb3-phy"; - reg = <0x0007d000 0xa00>; - #phy-cells = <0>; diff --git a/target/linux/qualcommbe/patches-6.12/0304-arm64-dts-qcom-ipq9574-add-QPIC-SPI-NAND-default-par.patch b/target/linux/qualcommbe/patches-6.12/0304-arm64-dts-qcom-ipq9574-add-QPIC-SPI-NAND-default-par.patch deleted file mode 100644 index b76039c448..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0304-arm64-dts-qcom-ipq9574-add-QPIC-SPI-NAND-default-par.patch +++ /dev/null @@ -1,51 +0,0 @@ -From be44d0251a2540f3b8d7205e0bc6659704366711 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 30 Jan 2025 00:39:30 +0100 -Subject: [PATCH] arm64: dts: qcom: ipq9574: add QPIC SPI NAND default - partition nodes - -Add QPIC SPI NAND default partition nodes for RDP reference board. - -Signed-off-by: Christian Marangi ---- - .../boot/dts/qcom/ipq9574-rdp-common.dtsi | 28 +++++++++++++++++++ - 1 file changed, 28 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -@@ -189,6 +189,35 @@ - nand-ecc-engine = <&qpic_nand>; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "0:training"; -+ reg = <0x0 0x80000>; -+ read-only; -+ }; -+ -+ partition@80000 { -+ label = "0:license"; -+ reg = <0x80000 0x40000>; -+ read-only; -+ }; -+ -+ partition@c0000 { -+ label = "rootfs"; -+ reg = <0xc0000 0x3c00000>; -+ linux,rootfs; -+ }; -+ -+ partition@3cc0000 { -+ label = "rootfs_1"; -+ reg = <0x3cc0000 0x3c00000>; -+ }; -+ }; - }; - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0305-arm64-dts-qcom-add-partition-table-for-ipq9574-rdp-c.patch b/target/linux/qualcommbe/patches-6.12/0305-arm64-dts-qcom-add-partition-table-for-ipq9574-rdp-c.patch deleted file mode 100644 index 04314f59ea..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0305-arm64-dts-qcom-add-partition-table-for-ipq9574-rdp-c.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 47c7ae9715d76054d98e8407dbb8ca1cf42fd587 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 9 Dec 2024 17:50:31 +0100 -Subject: [PATCH] arm64: dts: qcom: add partition table for ipq9574 rdp common - -Add partition table for ipq9574 SoC common to every RDB board. - -Signed-off-by: Christian Marangi ---- - .../boot/dts/qcom/ipq9574-rdp-common.dtsi | 146 +++++++++++++++++- - 1 file changed, 145 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp-common.dtsi -@@ -74,11 +74,158 @@ - status = "okay"; - - flash@0 { -- compatible = "micron,n25q128a11", "jedec,spi-nor"; -+ compatible = "jedec,spi-nor"; - reg = <0>; - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; -+ -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "0:sbl1"; -+ reg = <0x0 0xc0000>; -+ read-only; -+ }; -+ -+ partition@c0000 { -+ label = "0:mibib"; -+ reg = <0xc0000 0x10000>; -+ read-only; -+ }; -+ -+ partition@d0000 { -+ label = "0:bootconfig"; -+ reg = <0xd0000 0x20000>; -+ read-only; -+ }; -+ -+ partition@f0000 { -+ label = "0:bootconfig1"; -+ reg = <0xf0000 0x20000>; -+ read-only; -+ }; -+ -+ partition@110000 { -+ label = "0:qsee"; -+ reg = <0x110000 0x180000>; -+ read-only; -+ }; -+ -+ partition@290000 { -+ label = "0:qsee_1"; -+ reg = <0x290000 0x180000>; -+ read-only; -+ }; -+ -+ partition@410000 { -+ label = "0:devcfg"; -+ reg = <0x410000 0x10000>; -+ read-only; -+ }; -+ -+ partition@420000 { -+ label = "0:devcfg_1"; -+ reg = <0x420000 0x10000>; -+ read-only; -+ }; -+ -+ partition@430000 { -+ label = "0:apdp"; -+ reg = <0x430000 0x10000>; -+ read-only; -+ }; -+ -+ partition@440000 { -+ label = "0:apdp_1"; -+ reg = <0x440000 0x10000>; -+ read-only; -+ }; -+ -+ partition@450000 { -+ label = "0:tme"; -+ reg = <0x450000 0x40000>; -+ read-only; -+ }; -+ -+ partition@490000 { -+ label = "0:tme_1"; -+ reg = <0x490000 0x40000>; -+ read-only; -+ }; -+ -+ partition@4d0000 { -+ label = "0:rpm"; -+ reg = <0x4d0000 0x20000>; -+ read-only; -+ }; -+ -+ partition@4f0000 { -+ label = "0:rpm_1"; -+ reg = <0x4f0000 0x20000>; -+ read-only; -+ }; -+ -+ partition@510000 { -+ label = "0:cdt"; -+ reg = <0x510000 0x10000>; -+ read-only; -+ }; -+ -+ partition@520000 { -+ label = "0:cdt_1"; -+ reg = <0x520000 0x10000>; -+ read-only; -+ }; -+ -+ partition@530000 { -+ label = "0:appsblenv"; -+ reg = <0x530000 0x10000>; -+ -+ nvmem-layout { -+ compatible = "u-boot,env"; -+ -+ macaddr_lan: ethaddr { -+ #nvmem-cell-cells = <1>; -+ }; -+ }; -+ }; -+ -+ partition@540000 { -+ label = "0:appsbl"; -+ reg = <0x540000 0xa0000>; -+ read-only; -+ }; -+ -+ partition@5e0000 { -+ label = "0:appsbl_1"; -+ reg = <0x5e0000 0xa0000>; -+ read-only; -+ }; -+ -+ partition@680000 { -+ label = "0:art"; -+ reg = <0x680000 0x100000>; -+ read-only; -+ }; -+ -+ partition@780000 { -+ label = "0:ethphyfw"; -+ reg = <0x780000 0x80000>; -+ read-only; -+ -+ nvmem-layout { -+ compatible = "fixed-layout"; -+ -+ aqr_fw: aqr-fw@0 { -+ reg = <0x0 0x5fc02>; -+ }; -+ }; -+ }; -+ }; - }; - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0306-dt-bindings-net-Document-Qualcomm-QCA8084-PHY-packag.patch b/target/linux/qualcommbe/patches-6.12/0306-dt-bindings-net-Document-Qualcomm-QCA8084-PHY-packag.patch deleted file mode 100644 index a9223c5a35..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0306-dt-bindings-net-Document-Qualcomm-QCA8084-PHY-packag.patch +++ /dev/null @@ -1,536 +0,0 @@ -From 7b1c4e22532ded6b20ee41936fa38b5ca1e61ff9 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 29 Jan 2024 17:57:20 +0800 -Subject: [PATCH] dt-bindings: net: Document Qualcomm QCA8084 PHY package - -QCA8084 is quad PHY chip, which integrates 4 PHYs, 2 PCS -interfaces (PCS0 and PCS1) and clock controller, which can -also be integrated to the switch chip named as QCA8386. - -1. MDIO address of 4 PHYs, 2 PCS and 1 XPCS (PCS1 includes - PCS and XPCS, PCS0 includes PCS) can be configured. -2. The package mode of PHY is optionally configured for the - interface mode of two PCSes working correctly. -3. The package level clock and reset need to be initialized. -4. The clock and reset per PHY device need to be initialized - so that the PHY register can be accessed. - -Change-Id: Idb2338d2673152cbd3c57e95968faa59e9d4a80f -Signed-off-by: Luo Jie -Alex G: Update to match the patches that will be upstream. -Signed-off-by: Alexandru Gagniuc ---- - .../devicetree/bindings/net/qcom,qca8084.yaml | 488 ++++++++++++++++++ - include/dt-bindings/net/qcom,qca808x.h | 14 + - 2 files changed, 502 insertions(+) - create mode 100644 Documentation/devicetree/bindings/net/qcom,qca8084.yaml - create mode 100644 include/dt-bindings/net/qcom,qca808x.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/qcom,qca8084.yaml -@@ -0,0 +1,488 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/net/qcom,qca8084.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm QCA8084 Ethernet Quad PHY -+ -+maintainers: -+ - Luo Jie -+ -+description: -+ Qualcomm QCA8084 is PHY package of four-port Ethernet transceiver, -+ the Ethernet port supports link speed 10/100/1000/2500 Mbps. -+ There are two PCSes (PCS0 and PCS1) integrated in the PHY -+ package, PCS1 includes XPCS and PCS to support the interface -+ mode 10G-QXGMII and SGMII, PCS0 includes a PCS to support the -+ interface mode SGMII only. There is also a clock controller -+ integrated in the PHY package. This four-port Ethernet -+ transceiver can also be integrated to the switch chip named -+ as QCA8386. The PHY package mode needs to be configured as the -+ correct value to apply the interface mode of two PCSes as -+ mentioned below. -+ -+ QCA8084 expects an input reference clock 50 MHZ as the clock -+ source of the integrated clock controller, the integrated -+ clock controller supplies the clocks and resets to the -+ integrated PHY, PCS and PHY package. -+ -+ - | -+ +--| |--+-------------------+--| |--+ -+ | PCS1 |<------------+---->| PCS0 | -+ +-------+ | +-------+ -+ | | | -+ Ref 50M clk +--------+ | | -+ ------------>| | clk & rst | | -+ GPIO Reset |QCA8K-CC+------------+ | -+ ------------>| | | | -+ +--------+ | | -+ | V | -+ +--------+--------+--------+--------+ -+ | PHY0 | PHY1 | PHY2 | PHY3 | -+ +--------+--------+--------+--------+ -+ -+properties: -+ compatible: -+ const: qcom,qca8084-package -+ -+ clocks: -+ description: -+ PHY package level initial common clocks, which are needed to -+ be enabled after GPIO reset on the PHY package, these clocks -+ are supplied from the PHY integrated clock controller (QCA8K-CC). -+ items: -+ - description: APB bridge clock -+ - description: AHB clock -+ - description: Security control clock -+ - description: TLMM clock -+ - description: TLMM AHB clock -+ - description: CNOC AHB clock -+ - description: MDIO AHB clock -+ -+ clock-names: -+ items: -+ - const: apb_bridge -+ - const: ahb -+ - const: sec_ctrl_ahb -+ - const: tlmm -+ - const: tlmm_ahb -+ - const: cnoc_ahb -+ - const: mdio_ahb -+ -+ resets: -+ description: -+ PHY package level initial common reset, which are needed to -+ be deasserted after GPIO reset on the PHY package, this reset -+ is provided by the PHY integrated clock controller to do PHY -+ DSP reset. -+ maxItems: 1 -+ -+ qcom,package-mode: -+ description: | -+ The package mode of PHY supports to be configured as 3 modes -+ to apply the combinations of interface mode of two PCSes -+ correctly. This value should use one of the values defined in -+ dt-bindings/net/qcom,qca808x.h. The package mode 10G-QXGMII of -+ Quad PHY is used by default. -+ -+ package mode PCS1 PCS0 -+ phy mode (0) 10G-QXGMII for not used -+ PHY0-PHY3 -+ -+ switch mode (1) SGMII for SGMII for -+ switch MAC0 switch MAC5 (optional) -+ -+ switch bypass MAC5 (2) SGMII for SGMII for -+ switch MAC0 PHY3 -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ enum: [0, 1, 2] -+ default: 0 -+ -+ qcom,phy-addr-fixup: -+ description: -+ MDIO address for PHY0-PHY3, PCS0 and PCS1 including PCS and XPCS, -+ which can be optionally customized by programming the security -+ control register of PHY package. The hardware default MDIO address -+ of PHY0-PHY3, PCS0 and PCS1 including PCS and XPCS is 0-6. -+ $ref: /schemas/types.yaml#/definitions/uint32-array -+ minItems: 7 -+ maxItems: 7 -+ -+patternProperties: -+ ^ethernet-phy@[a-f0-9]+$: -+ unevaluatedProperties: false -+ $ref: ethernet-phy.yaml# -+ -+ properties: -+ compatible: -+ const: ethernet-phy-id004d.d180 -+ -+ qcom,xpcs-channel: -+ description: -+ When PCS1 works on the interface mode 10G-QXGMII, the integrated -+ XPCS including 4 channels is used to connected with the Quad PHYs, -+ each PHY needs to be specified the XPCS channel ID to deliver the -+ PHY link status to the XPCS. -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ enum: [0, 1, 2, 3] -+ -+ required: -+ - compatible -+ - reg -+ - clocks -+ - resets -+ -+ ^pcs-phy@[a-f0-9]+$: -+ type: object -+ additionalProperties: false -+ description: -+ PCS device has the independent MDIO address, which controls -+ the interface mode used and provides the clocks such as -+ 312.5 MHZ as RX and TX root clocks to the integrated clock -+ controller. -+ properties: -+ compatible: -+ const: qcom,qca8k-pcs-phy -+ -+ reg: -+ items: -+ - description: PCS MDIO address. -+ -+ clocks: -+ items: -+ - description: PCS clock. -+ - description: PCS RX root clock. -+ - description: PCS TX root clock. -+ -+ clock-names: -+ items: -+ - const: pcs -+ - const: pcs_rx_root -+ - const: pcs_tx_root -+ -+ resets: -+ items: -+ - description: PCS reset. -+ -+ required: -+ - compatible -+ - reg -+ - clocks -+ - resets -+ -+ ^xpcs-phy@[a-f0-9]+$: -+ type: object -+ additionalProperties: false -+ description: -+ XPCS device has the independent MDIO address, which includes 4 -+ channels to connect with Quad PHYs. -+ properties: -+ compatible: -+ const: qcom,qca8k-xpcs-phy -+ -+ reg: -+ items: -+ - description: XPCS MDIO address. -+ -+ resets: -+ items: -+ - description: XPCS reset. -+ -+ '#address-cells': -+ const: 1 -+ -+ '#size-cells': -+ const: 0 -+ -+ required: -+ - compatible -+ - reg -+ - resets -+ - '#address-cells' -+ - '#size-cells' -+ -+ patternProperties: -+ "^channel@[0-3]+$": -+ type: object -+ additionalProperties: false -+ description: -+ XPCS is used to support 10G-QXGMII mode, which inlcudes 4 channels -+ to be connected with Quad PHYs, each channels has the dedicated -+ clocks and resets from the integrated clock controller of QCA8084. -+ -+ properties: -+ reg: -+ items: -+ - description: XPCS channel ID -+ -+ clocks: -+ items: -+ - description: XPCS XGMII RX clock -+ - description: XPCS XGMII TX clock -+ - description: XPCS RX clock -+ - description: XPCS TX clock -+ - description: Port RX clock -+ - description: Port TX clock -+ - description: RX source clock -+ - description: TX source clock -+ -+ clock-names: -+ items: -+ - const: xgmii_rx -+ - const: xgmii_tx -+ - const: xpcs_rx -+ - const: xpcs_tx -+ - const: port_rx -+ - const: port_tx -+ - const: rx_src -+ - const: tx_src -+ -+ resets: -+ items: -+ - description: XPCS XGMII RX reset -+ - description: XPCS XGMII TX reset -+ - description: XPCS RX reset -+ - description: XPCS TX reset -+ - description: Port RX reset -+ - description: Port TX reset -+ -+ reset-names: -+ items: -+ - const: xgmii_rx -+ - const: xgmii_tx -+ - const: xpcs_rx -+ - const: xpcs_tx -+ - const: port_rx -+ - const: port_tx -+ -+ required: -+ - reg -+ - clocks -+ - clock-names -+ - resets -+ - reset-names -+ -+required: -+ - compatible -+ - clocks -+ - clock-names -+ - resets -+ -+allOf: -+ - $ref: ethernet-phy-package.yaml# -+ -+unevaluatedProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ -+ mdio { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ ethernet-phy-package@1 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "qcom,qca8084-package"; -+ reg = <1>; -+ clocks = <&qca8k_nsscc NSS_CC_APB_BRIDGE_CLK>, -+ <&qca8k_nsscc NSS_CC_AHB_CLK>, -+ <&qca8k_nsscc NSS_CC_SEC_CTRL_AHB_CLK>, -+ <&qca8k_nsscc NSS_CC_TLMM_CLK>, -+ <&qca8k_nsscc NSS_CC_TLMM_AHB_CLK>, -+ <&qca8k_nsscc NSS_CC_CNOC_AHB_CLK>, -+ <&qca8k_nsscc NSS_CC_MDIO_AHB_CLK>; -+ clock-names = "apb_bridge", -+ "ahb", -+ "sec_ctrl_ahb", -+ "tlmm", -+ "tlmm_ahb", -+ "cnoc_ahb", -+ "mdio_ahb"; -+ resets = <&qca8k_nsscc NSS_CC_GEPHY_FULL_ARES>; -+ qcom,package-mode = ; -+ qcom,phy-addr-fixup = <1 2 3 4 5 6 7>; -+ -+ ethernet-phy@1 { -+ compatible = "ethernet-phy-id004d.d180"; -+ reg = <1>; -+ clocks = <&qca8k_nsscc NSS_CC_GEPHY0_SYS_CLK>; -+ resets = <&qca8k_nsscc NSS_CC_GEPHY0_SYS_ARES>; -+ qcom,xpcs-channel = <0>; -+ }; -+ -+ ethernet-phy@2 { -+ compatible = "ethernet-phy-id004d.d180"; -+ reg = <2>; -+ clocks = <&qca8k_nsscc NSS_CC_GEPHY1_SYS_CLK>; -+ resets = <&qca8k_nsscc NSS_CC_GEPHY1_SYS_ARES>; -+ qcom,xpcs-channel = <1>; -+ }; -+ -+ ethernet-phy@3 { -+ compatible = "ethernet-phy-id004d.d180"; -+ reg = <3>; -+ clocks = <&qca8k_nsscc NSS_CC_GEPHY2_SYS_CLK>; -+ resets = <&qca8k_nsscc NSS_CC_GEPHY2_SYS_ARES>; -+ qcom,xpcs-channel = <2>; -+ }; -+ -+ ethernet-phy@4 { -+ compatible = "ethernet-phy-id004d.d180"; -+ reg = <4>; -+ clocks = <&qca8k_nsscc NSS_CC_GEPHY3_SYS_CLK>; -+ resets = <&qca8k_nsscc NSS_CC_GEPHY3_SYS_ARES>; -+ qcom,xpcs-channel = <3>; -+ }; -+ -+ pcs-phy@6 { -+ compatible = "qcom,qca8k-pcs-phy"; -+ reg = <6>; -+ clocks = <&qca8k_nsscc NSS_CC_SRDS1_SYS_CLK>, -+ <&qca8k_uniphy1_tx312p5m>, -+ <&qca8k_uniphy1_rx312p5m>; -+ clock-names = "pcs", "pcs_rx_root", "pcs_tx_root"; -+ resets = <&qca8k_nsscc NSS_CC_SRDS1_SYS_ARES>; -+ }; -+ -+ xpcs-phy@7 { -+ compatible = "qcom,qca8k-xpcs-phy"; -+ reg = <7>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ resets = <&qca8k_nsscc NSS_CC_XPCS_ARES>; -+ -+ channel@0 { -+ reg = <0>; -+ clocks = <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_XGMII_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_XGMII_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_GEPHY0_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_GEPHY0_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC1_RX_CLK_SRC>, -+ <&qca8k_nsscc NSS_CC_MAC1_TX_CLK_SRC>; -+ clock-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx", -+ "rx_src", -+ "tx_src"; -+ resets = <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_XGMII_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_XGMII_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC1_SRDS1_CH0_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC1_GEPHY0_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC1_GEPHY0_TX_ARES>; -+ reset-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx"; -+ }; -+ -+ channel@1 { -+ reg = <1>; -+ clocks = <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_XGMII_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_XGMII_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_GEPHY1_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_GEPHY1_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC2_RX_CLK_SRC>, -+ <&qca8k_nsscc NSS_CC_MAC2_TX_CLK_SRC>; -+ clock-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx", -+ "rx_src", -+ "tx_src"; -+ resets = <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_XGMII_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_XGMII_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC2_SRDS1_CH1_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC2_GEPHY1_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC2_GEPHY1_TX_ARES>; -+ reset-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx"; -+ }; -+ -+ channel@2 { -+ reg = <2>; -+ clocks = <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_XGMII_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_XGMII_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_GEPHY2_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_GEPHY2_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC3_RX_CLK_SRC>, -+ <&qca8k_nsscc NSS_CC_MAC3_TX_CLK_SRC>; -+ clock-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx", -+ "rx_src", -+ "tx_src"; -+ resets = <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_XGMII_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_XGMII_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC3_SRDS1_CH2_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC3_GEPHY2_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC3_GEPHY2_TX_ARES>; -+ reset-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx"; -+ }; -+ -+ channel@3 { -+ reg = <3>; -+ clocks = <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_XGMII_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_XGMII_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_GEPHY3_RX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_GEPHY3_TX_CLK>, -+ <&qca8k_nsscc NSS_CC_MAC4_RX_CLK_SRC>, -+ <&qca8k_nsscc NSS_CC_MAC4_TX_CLK_SRC>; -+ clock-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx", -+ "rx_src", -+ "tx_src"; -+ resets = <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_XGMII_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_XGMII_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_TX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC4_SRDS1_CH3_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC4_GEPHY3_RX_ARES>, -+ <&qca8k_nsscc NSS_CC_MAC4_GEPHY3_TX_ARES>; -+ reset-names = "xgmii_rx", -+ "xgmii_tx", -+ "xpcs_rx", -+ "xpcs_tx", -+ "port_rx", -+ "port_tx"; -+ }; -+ }; -+ }; -+ }; ---- /dev/null -+++ b/include/dt-bindings/net/qcom,qca808x.h -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Device Tree constants for the Qualcomm QCA808X PHYs -+ */ -+ -+#ifndef _DT_BINDINGS_QCOM_QCA808X_H -+#define _DT_BINDINGS_QCOM_QCA808X_H -+ -+/* PHY package modes of QCA8084 to apply the interface modes of two PCSes. */ -+#define QCA808X_PCS1_10G_QXGMII_PCS0_UNUNSED 0 -+#define QCA808X_PCS1_SGMII_MAC_PCS0_SGMII_MAC 1 -+#define QCA808X_PCS1_SGMII_MAC_PCS0_SGMII_PHY 2 -+ -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0307-net-phy-qca808x-Add-QCA8084-ethernet-phy-support.patch b/target/linux/qualcommbe/patches-6.12/0307-net-phy-qca808x-Add-QCA8084-ethernet-phy-support.patch deleted file mode 100644 index 360517f9b5..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0307-net-phy-qca808x-Add-QCA8084-ethernet-phy-support.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 60c44842f9611be237ab3f68afe8ebf2d9595fb2 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Thu, 6 Apr 2023 18:09:07 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 ethernet phy support - -Add QCA8084 Quad-PHY support, which is a four-port PHY with -maximum link capability of 2.5 Gbps. The features of each port -are almost same as QCA8081. The slave seed and fast retrain -configs are not needed for QCA8084. It includes two PCSes. - -PCS0 of QCA8084 supports the interface modes: -PHY_INTERFACE_MODE_2500BASEX and PHY_INTERFACE_MODE_SGMII. - -PCS1 of QCA8084 supports the interface modes: -PHY_INTERFACE_MODE_10G_QXGMII, PHY_INTERFACE_MODE_2500BASEX and -PHY_INTERFACE_MODE_SGMII. - -The additional CDT configurations needed for QCA8084 compared -with QCA8081. - -Change-Id: I12555fa70662682474ab4432204405b5e752fef6 -Signed-off-by: Luo Jie -Alex G: Update to match the patches that will be upstream. -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/qca808x.c | 65 ++++++++++++++++++++++++++++++++-- - 1 file changed, 63 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -86,9 +86,16 @@ - #define QCA8081_PHY_FIFO_RSTN BIT(11) - - #define QCA8081_PHY_ID 0x004dd101 -+#define QCA8084_PHY_ID 0x004dd180 -+ -+#define QCA8084_MMD3_CDT_PULSE_CTRL 0x8075 -+#define QCA8084_CDT_PULSE_THRESH_VAL 0xa060 -+ -+#define QCA8084_MMD3_CDT_NEAR_CTRL 0x807f -+#define QCA8084_CDT_NEAR_BYPASS BIT(15) - - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); --MODULE_AUTHOR("Matus Ujhelyi"); -+MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); - - struct qca808x_priv { -@@ -153,13 +160,18 @@ static bool qca808x_is_prefer_master(str - - static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev) - { -- return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); -+ return phydev_id_compare(phydev, QCA8081_PHY_ID) && -+ linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, -+ phydev->supported); - } - - static bool qca808x_is_1g_only(struct phy_device *phydev) - { - int ret; - -+ if (!phydev_id_compare(phydev, QCA8081_PHY_ID)) -+ return false; -+ - ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); - if (ret < 0) - return true; -@@ -273,6 +285,23 @@ static int qca808x_read_status(struct ph - return ret; - - if (phydev->link) { -+ /* There are two PCSes available for QCA8084, which support -+ * the following interface modes. -+ * -+ * 1. PHY_INTERFACE_MODE_10G_QXGMII utilizes PCS1 for all -+ * available 4 ports, which is for all link speeds. -+ * -+ * 2. PHY_INTERFACE_MODE_2500BASEX utilizes PCS0 for the -+ * fourth port, which is only for the link speed 2500M same -+ * as QCA8081. -+ * -+ * 3. PHY_INTERFACE_MODE_SGMII utilizes PCS0 for the fourth -+ * port, which is for the link speed 10M, 100M and 1000M same -+ * as QCA8081. -+ */ -+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) -+ return 0; -+ - if (phydev->speed == SPEED_2500) - phydev->interface = PHY_INTERFACE_MODE_2500BASEX; - else -@@ -352,6 +381,18 @@ static int qca808x_cable_test_start(stru - phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060); - phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060); - -+ if (phydev_id_compare(phydev, QCA8084_PHY_ID)) { -+ /* Adjust the positive and negative pulse thereshold of CDT. */ -+ phy_write_mmd(phydev, MDIO_MMD_PCS, -+ QCA8084_MMD3_CDT_PULSE_CTRL, -+ QCA8084_CDT_PULSE_THRESH_VAL); -+ -+ /* Disable the near bypass of CDT. */ -+ phy_modify_mmd(phydev, MDIO_MMD_PCS, -+ QCA8084_MMD3_CDT_NEAR_CTRL, -+ QCA8084_CDT_NEAR_BYPASS, 0); -+ } -+ - return 0; - } - -@@ -651,12 +692,32 @@ static struct phy_driver qca808x_driver[ - .led_hw_control_set = qca808x_led_hw_control_set, - .led_hw_control_get = qca808x_led_hw_control_get, - .led_polarity_set = qca808x_led_polarity_set, -+}, { -+ /* Qualcomm QCA8084 */ -+ PHY_ID_MATCH_MODEL(QCA8084_PHY_ID), -+ .name = "Qualcomm QCA8084", -+ .flags = PHY_POLL_CABLE_TEST, -+ .config_intr = at803x_config_intr, -+ .handle_interrupt = at803x_handle_interrupt, -+ .get_tunable = at803x_get_tunable, -+ .set_tunable = at803x_set_tunable, -+ .set_wol = at803x_set_wol, -+ .get_wol = at803x_get_wol, -+ .get_features = qca808x_get_features, -+ .config_aneg = qca808x_config_aneg, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_status = qca808x_read_status, -+ .soft_reset = qca808x_soft_reset, -+ .cable_test_start = qca808x_cable_test_start, -+ .cable_test_get_status = qca808x_cable_test_get_status, - }, }; - - module_phy_driver(qca808x_driver); - - static const struct mdio_device_id __maybe_unused qca808x_tbl[] = { - { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) }, -+ { PHY_ID_MATCH_MODEL(QCA8084_PHY_ID) }, - { } - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0308-net-phy-qca808x-Add-config_init-function-for-QCA8084.patch b/target/linux/qualcommbe/patches-6.12/0308-net-phy-qca808x-Add-config_init-function-for-QCA8084.patch deleted file mode 100644 index 8ac94c84c7..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0308-net-phy-qca808x-Add-config_init-function-for-QCA8084.patch +++ /dev/null @@ -1,85 +0,0 @@ -From c052b9a4ab869cc54976402b3f9dbdef5bdb9f27 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Wed, 8 Nov 2023 16:18:02 +0800 -Subject: [PATCH] net: phy: qca808x: Add config_init function for QCA8084 - -1. The ADC of QCA8084 PHY must be configured as edge inverted -and falling whenever it is initialized or reset. In addition, -the default MSE (Mean square error) threshold value is adjusted, -which comes into play during link partner detection to detect -the valid link signal. - -2. Add the possible interface modes. - When QCA8084 works on the interface mode SGMII or 2500BASE-X, the - interface mode can be switched according to the PHY link speed. - - When QCA8084 works on the 10G-QXGMII mode, which will be the only - possible interface mode. - -Change-Id: I832c0d0b069e95cc411a8a7b680a5f60e1d6041a -Signed-off-by: Luo Jie ---- - drivers/net/phy/qcom/qca808x.c | 38 ++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -94,6 +94,15 @@ - #define QCA8084_MMD3_CDT_NEAR_CTRL 0x807f - #define QCA8084_CDT_NEAR_BYPASS BIT(15) - -+/* QCA8084 ADC clock edge */ -+#define QCA8084_ADC_CLK_SEL 0x8b80 -+#define QCA8084_ADC_CLK_SEL_ACLK GENMASK(7, 4) -+#define QCA8084_ADC_CLK_SEL_ACLK_FALL 0xf -+#define QCA8084_ADC_CLK_SEL_ACLK_RISE 0x0 -+ -+#define QCA8084_MSE_THRESHOLD 0x800a -+#define QCA8084_MSE_THRESHOLD_2P5G_VAL 0x51c6 -+ - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); -@@ -663,6 +672,34 @@ static int qca808x_led_polarity_set(stru - active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); - } - -+static int qca8084_config_init(struct phy_device *phydev) -+{ -+ int ret; -+ -+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) -+ __set_bit(PHY_INTERFACE_MODE_10G_QXGMII, -+ phydev->possible_interfaces); -+ else -+ qca808x_fill_possible_interfaces(phydev); -+ -+ /* Configure the ADC to convert the signal using falling edge -+ * instead of the default rising edge. -+ */ -+ ret = at803x_debug_reg_mask(phydev, QCA8084_ADC_CLK_SEL, -+ QCA8084_ADC_CLK_SEL_ACLK, -+ FIELD_PREP(QCA8084_ADC_CLK_SEL_ACLK, -+ QCA8084_ADC_CLK_SEL_ACLK_FALL)); -+ if (ret < 0) -+ return ret; -+ -+ /* Adjust MSE threshold value to avoid link issue with -+ * some link partner. -+ */ -+ return phy_write_mmd(phydev, MDIO_MMD_PMAPMD, -+ QCA8084_MSE_THRESHOLD, -+ QCA8084_MSE_THRESHOLD_2P5G_VAL); -+} -+ - static struct phy_driver qca808x_driver[] = { - { - /* Qualcomm QCA8081 */ -@@ -711,6 +748,7 @@ static struct phy_driver qca808x_driver[ - .soft_reset = qca808x_soft_reset, - .cable_test_start = qca808x_cable_test_start, - .cable_test_get_status = qca808x_cable_test_get_status, -+ .config_init = qca8084_config_init, - }, }; - - module_phy_driver(qca808x_driver); diff --git a/target/linux/qualcommbe/patches-6.12/0309-net-phy-qca808x-Add-link_change_notify-function-for-.patch b/target/linux/qualcommbe/patches-6.12/0309-net-phy-qca808x-Add-link_change_notify-function-for-.patch deleted file mode 100644 index e00a582831..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0309-net-phy-qca808x-Add-link_change_notify-function-for-.patch +++ /dev/null @@ -1,90 +0,0 @@ -From aec49c172cd9c739c1d97ff2d42b9718bb20b609 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Wed, 8 Nov 2023 18:01:14 +0800 -Subject: [PATCH] net: phy: qca808x: Add link_change_notify function for - QCA8084 - -When the link is changed, QCA8084 needs to do the fifo reset and -adjust the IPG level for the 10G-QXGMII link on the speed 1000M. - -Change-Id: I21de802c78496fb95f1c5119fe3894c9fdebbd65 -Signed-off-by: Luo Jie ---- - drivers/net/phy/qcom/qca808x.c | 52 ++++++++++++++++++++++++++++++++++ - 1 file changed, 52 insertions(+) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -103,6 +103,14 @@ - #define QCA8084_MSE_THRESHOLD 0x800a - #define QCA8084_MSE_THRESHOLD_2P5G_VAL 0x51c6 - -+/* QCA8084 FIFO reset control */ -+#define QCA8084_FIFO_CONTROL 0x19 -+#define QCA8084_FIFO_MAC_2_PHY BIT(1) -+#define QCA8084_FIFO_PHY_2_MAC BIT(0) -+ -+#define QCA8084_MMD7_IPG_OP 0x901d -+#define QCA8084_IPG_10_TO_11_EN BIT(0) -+ - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); -@@ -700,6 +708,49 @@ static int qca8084_config_init(struct ph - QCA8084_MSE_THRESHOLD_2P5G_VAL); - } - -+static void qca8084_link_change_notify(struct phy_device *phydev) -+{ -+ int ret; -+ -+ /* Assert the FIFO between PHY and MAC. */ -+ ret = phy_modify(phydev, QCA8084_FIFO_CONTROL, -+ QCA8084_FIFO_MAC_2_PHY | QCA8084_FIFO_PHY_2_MAC, -+ 0); -+ if (ret) { -+ phydev_err(phydev, "Asserting PHY FIFO failed\n"); -+ return; -+ } -+ -+ /* If the PHY is in 10G_QXGMII mode, the FIFO needs to be kept in -+ * reset state when link is down, otherwise the FIFO needs to be -+ * de-asserted after waiting 50 ms to make the assert completed. -+ */ -+ if (phydev->interface != PHY_INTERFACE_MODE_10G_QXGMII || -+ phydev->link) { -+ msleep(50); -+ -+ /* Deassert the FIFO between PHY and MAC. */ -+ ret = phy_modify(phydev, QCA8084_FIFO_CONTROL, -+ QCA8084_FIFO_MAC_2_PHY | -+ QCA8084_FIFO_PHY_2_MAC, -+ QCA8084_FIFO_MAC_2_PHY | -+ QCA8084_FIFO_PHY_2_MAC); -+ if (ret) { -+ phydev_err(phydev, "De-asserting PHY FIFO failed\n"); -+ return; -+ } -+ } -+ -+ /* Enable IPG level 10 to 11 tuning for link speed 1000M in the -+ * 10G_QXGMII mode. -+ */ -+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) -+ phy_modify_mmd(phydev, MDIO_MMD_AN, QCA8084_MMD7_IPG_OP, -+ QCA8084_IPG_10_TO_11_EN, -+ phydev->speed == SPEED_1000 ? -+ QCA8084_IPG_10_TO_11_EN : 0); -+} -+ - static struct phy_driver qca808x_driver[] = { - { - /* Qualcomm QCA8081 */ -@@ -749,6 +800,7 @@ static struct phy_driver qca808x_driver[ - .cable_test_start = qca808x_cable_test_start, - .cable_test_get_status = qca808x_cable_test_get_status, - .config_init = qca8084_config_init, -+ .link_change_notify = qca8084_link_change_notify, - }, }; - - module_phy_driver(qca808x_driver); diff --git a/target/linux/qualcommbe/patches-6.12/0310-net-phy-qca808x-Add-register-access-support-routines.patch b/target/linux/qualcommbe/patches-6.12/0310-net-phy-qca808x-Add-register-access-support-routines.patch deleted file mode 100644 index c1673ae645..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0310-net-phy-qca808x-Add-register-access-support-routines.patch +++ /dev/null @@ -1,125 +0,0 @@ -From cea8043def0c0867370c2efd5a1cd73bf4d3e5ba Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Wed, 29 Nov 2023 15:21:22 +0800 -Subject: [PATCH] net: phy: qca808x: Add register access support routines for - QCA8084 - -QCA8084 integrates clock controller and security control modules -besides of the PHY and PCS. The 32bit registers in these modules -are accessed using special MDIO sequences to read or write these -registers. - -The MDIO address of PHY and PCS are configured by writing to the -security control register. The package mode for QCA8084 is also -configured in a similar manner. - -Change-Id: I9317307ef9bbc738a6adcbc3ea1be8e6528d711e -Signed-off-by: Luo Jie ---- - drivers/net/phy/qcom/qca808x.c | 88 ++++++++++++++++++++++++++++++++++ - 1 file changed, 88 insertions(+) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -111,6 +111,22 @@ - #define QCA8084_MMD7_IPG_OP 0x901d - #define QCA8084_IPG_10_TO_11_EN BIT(0) - -+/* QCA8084 includes secure control module, which supports customizing the -+ * MDIO address of PHY device and PCS device and configuring package mode -+ * for the interface mode of PCS. The register of secure control is accessed -+ * by MDIO bus with the special MDIO sequences, where the 32 bits register -+ * address is split into 3 MDIO operations with 16 bits address. -+ */ -+#define QCA8084_HIGH_ADDR_PREFIX 0x18 -+#define QCA8084_LOW_ADDR_PREFIX 0x10 -+ -+/* Bottom two bits of REG must be zero */ -+#define QCA8084_MII_REG_MASK GENMASK(4, 0) -+#define QCA8084_MII_PHY_ADDR_MASK GENMASK(7, 5) -+#define QCA8084_MII_PAGE_MASK GENMASK(23, 8) -+#define QCA8084_MII_SW_ADDR_MASK GENMASK(31, 24) -+#define QCA8084_MII_REG_DATA_UPPER_16_BITS BIT(1) -+ - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); -@@ -119,6 +135,78 @@ struct qca808x_priv { - int led_polarity_mode; - }; - -+static int __qca8084_set_page(struct mii_bus *bus, u16 sw_addr, u16 page) -+{ -+ return __mdiobus_write(bus, QCA8084_HIGH_ADDR_PREFIX | (sw_addr >> 5), -+ sw_addr & 0x1f, page); -+} -+ -+static int __qca8084_mii_read(struct mii_bus *bus, u16 addr, u16 reg, u32 *val) -+{ -+ int ret, data; -+ -+ ret = __mdiobus_read(bus, addr, reg); -+ if (ret < 0) -+ return ret; -+ -+ data = ret; -+ ret = __mdiobus_read(bus, addr, -+ reg | QCA8084_MII_REG_DATA_UPPER_16_BITS); -+ if (ret < 0) -+ return ret; -+ -+ *val = data | ret << 16; -+ -+ return 0; -+} -+ -+static int __qca8084_mii_write(struct mii_bus *bus, u16 addr, u16 reg, u32 val) -+{ -+ int ret; -+ -+ ret = __mdiobus_write(bus, addr, reg, lower_16_bits(val)); -+ if (!ret) -+ ret = __mdiobus_write(bus, addr, -+ reg | QCA8084_MII_REG_DATA_UPPER_16_BITS, -+ upper_16_bits(val)); -+ -+ return ret; -+} -+ -+static int qca8084_mii_modify(struct phy_device *phydev, u32 regaddr, -+ u32 clear, u32 set) -+{ -+ u16 reg, addr, page, sw_addr; -+ struct mii_bus *bus; -+ u32 val; -+ int ret; -+ -+ bus = phydev->mdio.bus; -+ mutex_lock(&bus->mdio_lock); -+ -+ reg = FIELD_GET(QCA8084_MII_REG_MASK, regaddr); -+ addr = FIELD_GET(QCA8084_MII_PHY_ADDR_MASK, regaddr); -+ page = FIELD_GET(QCA8084_MII_PAGE_MASK, regaddr); -+ sw_addr = FIELD_GET(QCA8084_MII_SW_ADDR_MASK, regaddr); -+ -+ ret = __qca8084_set_page(bus, sw_addr, page); -+ if (ret < 0) -+ goto qca8084_mii_modify_exit; -+ -+ ret = __qca8084_mii_read(bus, QCA8084_LOW_ADDR_PREFIX | addr, -+ reg, &val); -+ if (ret < 0) -+ goto qca8084_mii_modify_exit; -+ -+ val &= ~clear; -+ val |= set; -+ ret = __qca8084_mii_write(bus, QCA8084_LOW_ADDR_PREFIX | addr, -+ reg, val); -+qca8084_mii_modify_exit: -+ mutex_unlock(&bus->mdio_lock); -+ return ret; -+}; -+ - static int qca808x_phy_fast_retrain_config(struct phy_device *phydev) - { - int ret; diff --git a/target/linux/qualcommbe/patches-6.12/0311-net-phy-qca808x-Add-QCA8084-probe-function.patch b/target/linux/qualcommbe/patches-6.12/0311-net-phy-qca808x-Add-QCA8084-probe-function.patch deleted file mode 100644 index e74fc0b09f..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0311-net-phy-qca808x-Add-QCA8084-probe-function.patch +++ /dev/null @@ -1,162 +0,0 @@ -From a7fe2c13f3188bf01b60fb15063d028c76dd2f1a Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 29 Jan 2024 10:51:38 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 probe function - -Add the PHY package probe function. The MDIO slave address of -PHY, PCS and XPCS can be optionally customized by configuring -the PHY package level register. - -In addition, enable system clock of PHY and de-assert PHY in -the probe function so that the register of PHY device can be -accessed, and the features of PHY can be acquired. - -Change-Id: I2251b9c5c398a21a4ef547a727189a934ad3a44c -Signed-off-by: Luo Jie -Alex G: include - include "phylib.h" for phy_package_*() declarations - select PHY_PACKAGE in Kconfig - use phy_package_get_node() instead of phylib->shared->np -Signed-off-by: Alexandru Gagniuc - -freckup c89414adf2ec7c - -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/Kconfig | 1 + - drivers/net/phy/qcom/qca808x.c | 92 ++++++++++++++++++++++++++++++++++ - 2 files changed, 93 insertions(+) - ---- a/drivers/net/phy/qcom/Kconfig -+++ b/drivers/net/phy/qcom/Kconfig -@@ -18,6 +18,7 @@ config QCA83XX_PHY - config QCA808X_PHY - tristate "Qualcomm QCA808x PHYs" - select QCOM_NET_PHYLIB -+ select PHY_PACKAGE - help - Currently supports the QCA8081 model - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -2,7 +2,11 @@ - - #include - #include -+#include -+#include -+#include - -+#include "../phylib.h" - #include "qcom.h" - - /* ADC threshold */ -@@ -127,6 +131,21 @@ - #define QCA8084_MII_SW_ADDR_MASK GENMASK(31, 24) - #define QCA8084_MII_REG_DATA_UPPER_16_BITS BIT(1) - -+/* QCA8084 integrates 4 PHYs, PCS0 and PCS1(includes PCS and XPCS). */ -+#define QCA8084_MDIO_DEVICE_NUM 7 -+ -+#define QCA8084_PCS_CFG 0xc90f014 -+#define QCA8084_PCS_ADDR0_MASK GENMASK(4, 0) -+#define QCA8084_PCS_ADDR1_MASK GENMASK(9, 5) -+#define QCA8084_PCS_ADDR2_MASK GENMASK(14, 10) -+ -+#define QCA8084_EPHY_CFG 0xc90f018 -+#define QCA8084_EPHY_ADDR0_MASK GENMASK(4, 0) -+#define QCA8084_EPHY_ADDR1_MASK GENMASK(9, 5) -+#define QCA8084_EPHY_ADDR2_MASK GENMASK(14, 10) -+#define QCA8084_EPHY_ADDR3_MASK GENMASK(19, 15) -+#define QCA8084_EPHY_LDO_EN GENMASK(21, 20) -+ - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); -@@ -839,6 +858,78 @@ static void qca8084_link_change_notify(s - QCA8084_IPG_10_TO_11_EN : 0); - } - -+static int qca8084_phy_package_probe_once(struct phy_device *phydev) -+{ -+ int addr[QCA8084_MDIO_DEVICE_NUM] = {0, 1, 2, 3, 4, 5, 6}; -+ struct device_node *np = phy_package_get_node(phydev); -+ int ret, clear, set; -+ -+ /* Program the MDIO address of PHY and PCS optionally, the MDIO -+ * address 0-6 is used for PHY and PCS MDIO devices by default. -+ */ -+ ret = of_property_read_u32_array(np, "qcom,phy-addr-fixup", -+ addr, ARRAY_SIZE(addr)); -+ if (ret && ret != -EINVAL) -+ return ret; -+ -+ /* Configure the MDIO addresses for the four PHY devices. */ -+ clear = QCA8084_EPHY_ADDR0_MASK | QCA8084_EPHY_ADDR1_MASK | -+ QCA8084_EPHY_ADDR2_MASK | QCA8084_EPHY_ADDR3_MASK; -+ set = FIELD_PREP(QCA8084_EPHY_ADDR0_MASK, addr[0]); -+ set |= FIELD_PREP(QCA8084_EPHY_ADDR1_MASK, addr[1]); -+ set |= FIELD_PREP(QCA8084_EPHY_ADDR2_MASK, addr[2]); -+ set |= FIELD_PREP(QCA8084_EPHY_ADDR3_MASK, addr[3]); -+ -+ ret = qca8084_mii_modify(phydev, QCA8084_EPHY_CFG, clear, set); -+ if (ret) -+ return ret; -+ -+ /* Configure the MDIO addresses for PCS0 and PCS1 including -+ * PCS and XPCS. -+ */ -+ clear = QCA8084_PCS_ADDR0_MASK | QCA8084_PCS_ADDR1_MASK | -+ QCA8084_PCS_ADDR2_MASK; -+ set = FIELD_PREP(QCA8084_PCS_ADDR0_MASK, addr[4]); -+ set |= FIELD_PREP(QCA8084_PCS_ADDR1_MASK, addr[5]); -+ set |= FIELD_PREP(QCA8084_PCS_ADDR2_MASK, addr[6]); -+ -+ return qca8084_mii_modify(phydev, QCA8084_PCS_CFG, clear, set); -+} -+ -+static int qca8084_probe(struct phy_device *phydev) -+{ -+ struct device *dev = &phydev->mdio.dev; -+ struct reset_control *rstc; -+ struct clk *clk; -+ int ret; -+ -+ ret = devm_of_phy_package_join(dev, phydev, 0); -+ if (ret) -+ return ret; -+ -+ if (phy_package_probe_once(phydev)) { -+ ret = qca8084_phy_package_probe_once(phydev); -+ if (ret) -+ return ret; -+ } -+ -+ /* Enable clock of PHY device, so that the PHY register -+ * can be accessed to get PHY features. -+ */ -+ clk = devm_clk_get_enabled(dev, NULL); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Enable PHY clock failed\n"); -+ -+ /* De-assert PHY reset after the clock of PHY enabled. */ -+ rstc = devm_reset_control_get_exclusive(dev, NULL); -+ if (IS_ERR(rstc)) -+ return dev_err_probe(dev, PTR_ERR(rstc), -+ "Get PHY reset failed\n"); -+ -+ return reset_control_deassert(rstc); -+} -+ - static struct phy_driver qca808x_driver[] = { - { - /* Qualcomm QCA8081 */ -@@ -889,6 +980,7 @@ static struct phy_driver qca808x_driver[ - .cable_test_get_status = qca808x_cable_test_get_status, - .config_init = qca8084_config_init, - .link_change_notify = qca8084_link_change_notify, -+ .probe = qca8084_probe, - }, }; - - module_phy_driver(qca808x_driver); diff --git a/target/linux/qualcommbe/patches-6.12/0312-net-phy-qca808x-Add-package-clocks-and-resets-for-QC.patch b/target/linux/qualcommbe/patches-6.12/0312-net-phy-qca808x-Add-package-clocks-and-resets-for-QC.patch deleted file mode 100644 index 50346520b3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0312-net-phy-qca808x-Add-package-clocks-and-resets-for-QC.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 57379fe257895b374d35ce6578ecd62ce1cc1a4d Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Tue, 9 Apr 2024 16:30:55 +0800 -Subject: [PATCH] net: phy: qca808x: Add package clocks and resets for QCA8084 - -Parse the PHY package clocks from the PHY package DTS node. -These package level clocks will be enabled in the PHY package -init function. - -Deassert PHY package reset, which is necessary for accessing -the PHY registers. - -Change-Id: I254d0aa0a1155d3618c6f1fc7d7a5b6ecadccbaa -Signed-off-by: Luo Jie -Alex G: Use accessors for struct phy_package_shared - Update to match the patches that will be upstream. -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/qca808x.c | 74 ++++++++++++++++++++++++++++++++-- - 1 file changed, 71 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -150,10 +150,39 @@ MODULE_DESCRIPTION("Qualcomm Atheros QCA - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); - -+enum { -+ APB_BRIDGE_CLK, -+ AHB_CLK, -+ SEC_CTRL_AHB_CLK, -+ TLMM_CLK, -+ TLMM_AHB_CLK, -+ CNOC_AHB_CLK, -+ MDIO_AHB_CLK, -+ MDIO_MASTER_AHB_CLK, -+ SWITCH_CORE_CLK, -+ PACKAGE_CLK_MAX -+}; -+ - struct qca808x_priv { - int led_polarity_mode; - }; - -+struct qca808x_shared_priv { -+ struct clk *clk[PACKAGE_CLK_MAX]; -+}; -+ -+static const char *const qca8084_package_clk_name[PACKAGE_CLK_MAX] = { -+ [APB_BRIDGE_CLK] = "apb_bridge", -+ [AHB_CLK] = "ahb", -+ [SEC_CTRL_AHB_CLK] = "sec_ctrl_ahb", -+ [TLMM_CLK] = "tlmm", -+ [TLMM_AHB_CLK] = "tlmm_ahb", -+ [CNOC_AHB_CLK] = "cnoc_ahb", -+ [MDIO_AHB_CLK] = "mdio_ahb", -+ [MDIO_MASTER_AHB_CLK] = "mdio_master_ahb", -+ [SWITCH_CORE_CLK] = "switch_core", -+}; -+ - static int __qca8084_set_page(struct mii_bus *bus, u16 sw_addr, u16 page) - { - return __mdiobus_write(bus, QCA8084_HIGH_ADDR_PREFIX | (sw_addr >> 5), -@@ -858,11 +887,24 @@ static void qca8084_link_change_notify(s - QCA8084_IPG_10_TO_11_EN : 0); - } - -+/* QCA8084 is a four-port PHY, which integrates the clock controller, -+ * 4 PHY devices and 2 PCS interfaces (PCS0 and PCS1). PCS1 includes -+ * XPCS and PCS to support 10G-QXGMII and SGMII. PCS0 includes one PCS -+ * to support SGMII. -+ * -+ * The clocks and resets are sourced from the integrated clock controller -+ * of the PHY package. This integrated clock controller is driven by a -+ * QCA8K clock provider that supplies the clocks and resets to the four -+ * PHYs, PCS and PHY package. -+ */ - static int qca8084_phy_package_probe_once(struct phy_device *phydev) - { - int addr[QCA8084_MDIO_DEVICE_NUM] = {0, 1, 2, 3, 4, 5, 6}; - struct device_node *np = phy_package_get_node(phydev); -- int ret, clear, set; -+ struct qca808x_shared_priv *shared_priv; -+ struct reset_control *rstc; -+ int i, ret, clear, set; -+ struct clk *clk; - - /* Program the MDIO address of PHY and PCS optionally, the MDIO - * address 0-6 is used for PHY and PCS MDIO devices by default. -@@ -893,17 +935,43 @@ static int qca8084_phy_package_probe_onc - set |= FIELD_PREP(QCA8084_PCS_ADDR1_MASK, addr[5]); - set |= FIELD_PREP(QCA8084_PCS_ADDR2_MASK, addr[6]); - -- return qca8084_mii_modify(phydev, QCA8084_PCS_CFG, clear, set); -+ ret = qca8084_mii_modify(phydev, QCA8084_PCS_CFG, clear, set); -+ if (ret) -+ return ret; -+ -+ shared_priv = phy_package_get_priv(phydev); -+ for (i = 0; i < ARRAY_SIZE(qca8084_package_clk_name); i++) { -+ clk = of_clk_get_by_name(np, qca8084_package_clk_name[i]); -+ if (IS_ERR(clk)) { -+ if (PTR_ERR(clk) == -EINVAL) -+ clk = NULL; -+ else -+ return dev_err_probe(&phydev->mdio.dev, PTR_ERR(clk), -+ "package clock %s not ready\n", -+ qca8084_package_clk_name[i]); -+ } -+ -+ shared_priv->clk[i] = clk; -+ } -+ -+ rstc = of_reset_control_get_exclusive(np, NULL); -+ if (IS_ERR(rstc)) -+ return dev_err_probe(&phydev->mdio.dev, PTR_ERR(rstc), -+ "package reset not ready\n"); -+ -+ /* Deassert PHY package. */ -+ return reset_control_deassert(rstc); - } - - static int qca8084_probe(struct phy_device *phydev) - { -+ struct qca808x_shared_priv *shared_priv; - struct device *dev = &phydev->mdio.dev; - struct reset_control *rstc; - struct clk *clk; - int ret; - -- ret = devm_of_phy_package_join(dev, phydev, 0); -+ ret = devm_of_phy_package_join(dev, phydev, sizeof(*shared_priv)); - if (ret) - return ret; - diff --git a/target/linux/qualcommbe/patches-6.12/0313-net-phy-qca808x-Add-QCA8084-package-init-function.patch b/target/linux/qualcommbe/patches-6.12/0313-net-phy-qca808x-Add-QCA8084-package-init-function.patch deleted file mode 100644 index 5af66c290f..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0313-net-phy-qca808x-Add-QCA8084-package-init-function.patch +++ /dev/null @@ -1,177 +0,0 @@ -From d39dc53424bcc778f1e468015490577e7bf0c7b6 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Thu, 25 Jan 2024 17:13:24 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 package init function - -The package mode of PHY is configured for the interface mode of two -PCSes working correctly. - -The PHY package level clocks are enabled and their rates configured. - -Change-Id: I63d4b22d2a70ee713cc6a6818b0f3c7aa098a5f5 -Signed-off-by: Luo Jie -Alex G: Use phy_package_get_*() accessors - Update to match the patches that will be upstream. -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/qca808x.c | 118 +++++++++++++++++++++++++++++++++ - 1 file changed, 118 insertions(+) - ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0+ - -+#include - #include - #include - #include -@@ -146,6 +147,12 @@ - #define QCA8084_EPHY_ADDR3_MASK GENMASK(19, 15) - #define QCA8084_EPHY_LDO_EN GENMASK(21, 20) - -+#define QCA8084_WORK_MODE_CFG 0xc90f030 -+#define QCA8084_WORK_MODE_MASK GENMASK(5, 0) -+#define QCA8084_WORK_MODE_QXGMII (BIT(5) | GENMASK(3, 0)) -+#define QCA8084_WORK_MODE_SWITCH BIT(4) -+#define QCA8084_WORK_MODE_SWITCH_PORT4_SGMII BIT(5) -+ - MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); - MODULE_AUTHOR("Matus Ujhelyi, Luo Jie"); - MODULE_LICENSE("GPL"); -@@ -168,6 +175,7 @@ struct qca808x_priv { - }; - - struct qca808x_shared_priv { -+ int package_mode; - struct clk *clk[PACKAGE_CLK_MAX]; - }; - -@@ -816,10 +824,111 @@ static int qca808x_led_polarity_set(stru - active_low ? 0 : QCA808X_LED_ACTIVE_HIGH); - } - -+static int qca8084_package_clock_init(struct qca808x_shared_priv *shared_priv) -+{ -+ int ret; -+ -+ /* Configure clock rate 312.5MHZ for the PHY package -+ * APB bridge clock tree. -+ */ -+ ret = clk_set_rate(shared_priv->clk[APB_BRIDGE_CLK], 312500000); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[SWITCH_CORE_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[APB_BRIDGE_CLK]); -+ if (ret) -+ return ret; -+ -+ /* Configure clock rate 104.17MHZ for the PHY package -+ * AHB clock tree. -+ */ -+ ret = clk_set_rate(shared_priv->clk[AHB_CLK], 104170000); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[AHB_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[SEC_CTRL_AHB_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[TLMM_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[TLMM_AHB_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[CNOC_AHB_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(shared_priv->clk[MDIO_MASTER_AHB_CLK]); -+ if (ret) -+ return ret; -+ -+ return clk_prepare_enable(shared_priv->clk[MDIO_AHB_CLK]); -+} -+ -+static int qca8084_phy_package_config_init_once(struct phy_device *phydev) -+{ -+ struct qca808x_shared_priv *shared_priv; -+ int ret, mode; -+ -+ shared_priv = phy_package_get_priv(phydev); -+ switch (shared_priv->package_mode) { -+ case QCA808X_PCS1_10G_QXGMII_PCS0_UNUNSED: -+ mode = QCA8084_WORK_MODE_QXGMII; -+ break; -+ case QCA808X_PCS1_SGMII_MAC_PCS0_SGMII_MAC: -+ mode = QCA8084_WORK_MODE_SWITCH; -+ break; -+ case QCA808X_PCS1_SGMII_MAC_PCS0_SGMII_PHY: -+ mode = QCA8084_WORK_MODE_SWITCH_PORT4_SGMII; -+ break; -+ default: -+ phydev_err(phydev, "Invalid qcom,package-mode %d\n", -+ shared_priv->package_mode); -+ return -EINVAL; -+ } -+ -+ ret = qca8084_mii_modify(phydev, QCA8084_WORK_MODE_CFG, -+ QCA8084_WORK_MODE_MASK, -+ FIELD_PREP(QCA8084_WORK_MODE_MASK, mode)); -+ if (ret) -+ return ret; -+ -+ /* Enable efuse loading into analog circuit */ -+ ret = qca8084_mii_modify(phydev, QCA8084_EPHY_CFG, -+ QCA8084_EPHY_LDO_EN, 0); -+ if (ret) -+ return ret; -+ -+ usleep_range(10000, 11000); -+ -+ /* Initialize the PHY package clock and reset, which is the -+ * necessary config sequence after GPIO reset on the PHY package. -+ */ -+ return qca8084_package_clock_init(shared_priv); -+} -+ - static int qca8084_config_init(struct phy_device *phydev) - { - int ret; - -+ if (phy_package_init_once(phydev)) { -+ ret = qca8084_phy_package_config_init_once(phydev); -+ if (ret) -+ return ret; -+ } -+ - if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) - __set_bit(PHY_INTERFACE_MODE_10G_QXGMII, - phydev->possible_interfaces); -@@ -954,6 +1063,15 @@ static int qca8084_phy_package_probe_onc - shared_priv->clk[i] = clk; - } - -+ /* The package mode 10G-QXGMII of PCS1 is used for Quad PHY and -+ * PCS0 is unused by default. -+ */ -+ shared_priv->package_mode = QCA808X_PCS1_10G_QXGMII_PCS0_UNUNSED; -+ ret = of_property_read_u32(np, "qcom,package-mode", -+ &shared_priv->package_mode); -+ if (ret && ret != -EINVAL) -+ return ret; -+ - rstc = of_reset_control_get_exclusive(np, NULL); - if (IS_ERR(rstc)) - return dev_err_probe(&phydev->mdio.dev, PTR_ERR(rstc), diff --git a/target/linux/qualcommbe/patches-6.12/0314-dt-bindings-net-pcs-Add-Ethernet-PCS-for-Qualcomm-IP.patch b/target/linux/qualcommbe/patches-6.12/0314-dt-bindings-net-pcs-Add-Ethernet-PCS-for-Qualcomm-IP.patch deleted file mode 100644 index 1112d4e072..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0314-dt-bindings-net-pcs-Add-Ethernet-PCS-for-Qualcomm-IP.patch +++ /dev/null @@ -1,234 +0,0 @@ -From 5f650721c4b232a14a1a3e25b686f2234faee961 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 7 Feb 2025 23:53:12 +0800 -Subject: [PATCH] dt-bindings: net: pcs: Add Ethernet PCS for Qualcomm IPQ9574 - SoC - -The 'UNIPHY' PCS block in the IPQ9574 SoC includes PCS and SerDes -functions. It supports different interface modes to enable Ethernet -MAC connections to different types of external PHYs/switch. It includes -PCS functions for 1Gbps and 2.5Gbps interface modes and XPCS functions -for 10Gbps interface modes. There are three UNIPHY (PCS) instances -in IPQ9574 SoC which provide PCS/XPCS functions to the six Ethernet -ports. - -Reviewed-by: Krzysztof Kozlowski -Signed-off-by: Lei Wei ---- - .../bindings/net/pcs/qcom,ipq9574-pcs.yaml | 190 ++++++++++++++++++ - include/dt-bindings/net/qcom,ipq9574-pcs.h | 15 ++ - 2 files changed, 205 insertions(+) - create mode 100644 Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml - create mode 100644 include/dt-bindings/net/qcom,ipq9574-pcs.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml -@@ -0,0 +1,190 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/net/pcs/qcom,ipq9574-pcs.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Ethernet PCS for Qualcomm IPQ9574 SoC -+ -+maintainers: -+ - Lei Wei -+ -+description: -+ The UNIPHY hardware blocks in the Qualcomm IPQ SoC include PCS and SerDes -+ functions. They enable connectivity between the Ethernet MAC inside the -+ PPE (packet processing engine) and external Ethernet PHY/switch. There are -+ three UNIPHY instances in IPQ9574 SoC which provide PCS functions to the -+ six Ethernet ports. -+ -+ For SGMII (1Gbps PHY) or 2500BASE-X (2.5Gbps PHY) interface modes, the PCS -+ function is enabled by using the PCS block inside UNIPHY. For USXGMII (10Gbps -+ PHY), the XPCS block in UNIPHY is used. -+ -+ The SerDes provides 125M (1Gbps mode) or 312.5M (2.5Gbps and 10Gbps modes) -+ RX and TX clocks to the NSSCC (Networking Sub System Clock Controller). The -+ NSSCC divides these clocks and generates the MII RX and TX clocks to each -+ of the MII interfaces between the PCS and MAC, as per the link speeds and -+ interface modes. -+ -+ Different IPQ SoC may support different number of UNIPHYs (PCSes) since the -+ number of ports and their capabilities can be different between these SoCs -+ -+ Below diagram depicts the UNIPHY (PCS) connections for an IPQ9574 SoC based -+ board. In this example, the PCS0 has four GMIIs/XGMIIs, which can connect -+ with four MACs to support QSGMII (4 x 1Gbps) or 10G_QXGMII (4 x 2.5Gbps) -+ interface modes. -+ -+ - +-------+ +---------+ +-------------------------+ -+ +---------+CMN PLL| | GCC | | NSSCC (Divider) | -+ | +----+--+ +----+----+ +--+-------+--------------+ -+ | | | ^ | -+ | 31.25M | SYS/AHB|clk RX/TX|clk +------------+ -+ | ref clk| | | | | -+ | | v | MII RX|TX clk MAC| RX/TX clk -+ |25/50M +--+---------+----------+-------+---+ +-+---------+ -+ |ref clk | | +----------------+ | | | | PPE | -+ v | | | UNIPHY0 V | | V | -+ +-------+ | v | +-----------+ (X)GMII| | | -+ | | | +---+---+ | |--------|------|-- MAC0 | -+ | | | | | | | (X)GMII| | | -+ | Quad | | |SerDes | | PCS/XPCS |--------|------|-- MAC1 | -+ | +<----+ | | | | (X)GMII| | | -+ |(X)GPHY| | | | | |--------|------|-- MAC2 | -+ | | | | | | | (X)GMII| | | -+ | | | +-------+ | |--------|------|-- MAC3 | -+ +-------+ | | | | | | -+ | +-----------+ | | | -+ +-----------------------------------+ | | -+ +--+---------+----------+-------+---+ | | -+ +-------+ | UNIPHY1 | | | -+ | | | +-----------+ | | | -+ |(X)GPHY| | +-------+ | | (X)GMII| | | -+ | +<----+ |SerDes | | PCS/XPCS |--------|------|- MAC4 | -+ | | | | | | | | | | -+ +-------+ | +-------+ | | | | | -+ | +-----------+ | | | -+ +-----------------------------------+ | | -+ +--+---------+----------+-------+---+ | | -+ +-------+ | UNIPHY2 | | | -+ | | | +-----------+ | | | -+ |(X)GPHY| | +-------+ | | (X)GMII| | | -+ | +<----+ |SerDes | | PCS/XPCS |--------|------|- MAC5 | -+ | | | | | | | | | | -+ +-------+ | +-------+ | | | | | -+ | +-----------+ | | | -+ +-----------------------------------+ +-----------+ -+ -+properties: -+ compatible: -+ enum: -+ - qcom,ipq9574-pcs -+ -+ reg: -+ maxItems: 1 -+ -+ '#address-cells': -+ const: 1 -+ -+ '#size-cells': -+ const: 0 -+ -+ clocks: -+ items: -+ - description: System clock -+ - description: AHB clock needed for register interface access -+ -+ clock-names: -+ items: -+ - const: sys -+ - const: ahb -+ -+ '#clock-cells': -+ const: 1 -+ description: See include/dt-bindings/net/qcom,ipq9574-pcs.h for constants -+ -+patternProperties: -+ '^pcs-mii@[0-4]$': -+ type: object -+ description: PCS MII interface. -+ -+ properties: -+ reg: -+ minimum: 0 -+ maximum: 4 -+ description: MII index -+ -+ clocks: -+ items: -+ - description: PCS MII RX clock -+ - description: PCS MII TX clock -+ -+ clock-names: -+ items: -+ - const: rx -+ - const: tx -+ -+ required: -+ - reg -+ - clocks -+ - clock-names -+ -+ additionalProperties: false -+ -+required: -+ - compatible -+ - reg -+ - '#address-cells' -+ - '#size-cells' -+ - clocks -+ - clock-names -+ - '#clock-cells' -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ -+ ethernet-pcs@7a00000 { -+ compatible = "qcom,ipq9574-pcs"; -+ reg = <0x7a00000 0x10000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ clocks = <&gcc GCC_UNIPHY0_SYS_CLK>, -+ <&gcc GCC_UNIPHY0_AHB_CLK>; -+ clock-names = "sys", -+ "ahb"; -+ #clock-cells = <1>; -+ -+ pcs-mii@0 { -+ reg = <0>; -+ clocks = <&nsscc 116>, -+ <&nsscc 117>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs-mii@1 { -+ reg = <1>; -+ clocks = <&nsscc 118>, -+ <&nsscc 119>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs-mii@2 { -+ reg = <2>; -+ clocks = <&nsscc 120>, -+ <&nsscc 121>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs-mii@3 { -+ reg = <3>; -+ clocks = <&nsscc 122>, -+ <&nsscc 123>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ }; ---- /dev/null -+++ b/include/dt-bindings/net/qcom,ipq9574-pcs.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ * -+ * Device Tree constants for the Qualcomm IPQ9574 PCS -+ */ -+ -+#ifndef _DT_BINDINGS_PCS_QCOM_IPQ9574_H -+#define _DT_BINDINGS_PCS_QCOM_IPQ9574_H -+ -+/* The RX and TX clocks which are provided from the SerDes to NSSCC. */ -+#define PCS_RX_CLK 0 -+#define PCS_TX_CLK 1 -+ -+#endif /* _DT_BINDINGS_PCS_QCOM_IPQ9574_H */ diff --git a/target/linux/qualcommbe/patches-6.12/0315-net-pcs-Add-PCS-driver-for-Qualcomm-IPQ9574-SoC.patch b/target/linux/qualcommbe/patches-6.12/0315-net-pcs-Add-PCS-driver-for-Qualcomm-IPQ9574-SoC.patch deleted file mode 100644 index eb0750cf4e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0315-net-pcs-Add-PCS-driver-for-Qualcomm-IPQ9574-SoC.patch +++ /dev/null @@ -1,301 +0,0 @@ -From e404519d9f3e5e7d661cb105d3766d87e37e4ef5 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 7 Feb 2025 23:53:13 +0800 -Subject: [PATCH] net: pcs: Add PCS driver for Qualcomm IPQ9574 SoC - -The 'UNIPHY' PCS hardware block in Qualcomm's IPQ SoC supports -different interface modes to enable Ethernet MAC connections -for different types of external PHYs/switch. Each UNIPHY block -includes a SerDes and PCS/XPCS blocks, and can operate in either -PCS or XPCS modes. It supports 1Gbps and 2.5Gbps interface modes -(Ex: SGMII) using the PCS, and 10Gbps interface modes (Ex: USXGMII) -using the XPCS. There are three UNIPHY (PCS) instances in IPQ9574 -SoC which support the six Ethernet ports in the SoC. - -This patch adds support for the platform driver, probe and clock -registrations for the PCS driver. The platform driver creates an -'ipq_pcs' instance for each of the UNIPHY used on the given board. - -Signed-off-by: Lei Wei ---- - drivers/net/pcs/Kconfig | 9 ++ - drivers/net/pcs/Makefile | 1 + - drivers/net/pcs/pcs-qcom-ipq9574.c | 245 +++++++++++++++++++++++++++++ - 3 files changed, 255 insertions(+) - create mode 100644 drivers/net/pcs/pcs-qcom-ipq9574.c - ---- a/drivers/net/pcs/Kconfig -+++ b/drivers/net/pcs/Kconfig -@@ -43,6 +43,15 @@ config PCS_MTK_USXGMII - 1000Base-X, 2500Base-X and Cisco SGMII are supported on the same - differential pairs via an embedded LynxI PHY. - -+config PCS_QCOM_IPQ9574 -+ tristate "Qualcomm IPQ9574 PCS" -+ depends on OF && (ARCH_QCOM || COMPILE_TEST) -+ depends on HAS_IOMEM && COMMON_CLK -+ help -+ This module provides driver for UNIPHY PCS available on Qualcomm -+ IPQ9574 SoC. The UNIPHY PCS supports both PCS and XPCS functions -+ to support different interface modes for MAC to PHY connections. -+ - config PCS_RZN1_MIIC - tristate "Renesas RZ/N1 MII converter" - depends on OF && (ARCH_RZN1 || COMPILE_TEST) ---- a/drivers/net/pcs/Makefile -+++ b/drivers/net/pcs/Makefile -@@ -8,5 +8,6 @@ pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs. - obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o - obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o - obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o -+obj-$(CONFIG_PCS_QCOM_IPQ9574) += pcs-qcom-ipq9574.o - obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o - obj-$(CONFIG_PCS_MTK_USXGMII) += pcs-mtk-usxgmii.o ---- /dev/null -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -0,0 +1,245 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define XPCS_INDIRECT_ADDR 0x8000 -+#define XPCS_INDIRECT_AHB_ADDR 0x83fc -+#define XPCS_INDIRECT_ADDR_H GENMASK(20, 8) -+#define XPCS_INDIRECT_ADDR_L GENMASK(7, 0) -+#define XPCS_INDIRECT_DATA_ADDR(reg) (FIELD_PREP(GENMASK(15, 10), 0x20) | \ -+ FIELD_PREP(GENMASK(9, 2), \ -+ FIELD_GET(XPCS_INDIRECT_ADDR_L, reg))) -+ -+/* PCS private data */ -+struct ipq_pcs { -+ struct device *dev; -+ void __iomem *base; -+ struct regmap *regmap; -+ phy_interface_t interface; -+ -+ /* RX clock supplied to NSSCC */ -+ struct clk_hw rx_hw; -+ /* TX clock supplied to NSSCC */ -+ struct clk_hw tx_hw; -+}; -+ -+static unsigned long ipq_pcs_clk_rate_get(struct ipq_pcs *qpcs) -+{ -+ switch (qpcs->interface) { -+ case PHY_INTERFACE_MODE_USXGMII: -+ return 312500000; -+ default: -+ return 125000000; -+ } -+} -+ -+/* Return clock rate for the RX clock supplied to NSSCC -+ * as per the interface mode. -+ */ -+static unsigned long ipq_pcs_rx_clk_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct ipq_pcs *qpcs = container_of(hw, struct ipq_pcs, rx_hw); -+ -+ return ipq_pcs_clk_rate_get(qpcs); -+} -+ -+/* Return clock rate for the TX clock supplied to NSSCC -+ * as per the interface mode. -+ */ -+static unsigned long ipq_pcs_tx_clk_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct ipq_pcs *qpcs = container_of(hw, struct ipq_pcs, tx_hw); -+ -+ return ipq_pcs_clk_rate_get(qpcs); -+} -+ -+static int ipq_pcs_clk_determine_rate(struct clk_hw *hw, -+ struct clk_rate_request *req) -+{ -+ switch (req->rate) { -+ case 125000000: -+ case 312500000: -+ return 0; -+ default: -+ return -EINVAL; -+ } -+} -+ -+/* Clock ops for the RX clock supplied to NSSCC */ -+static const struct clk_ops ipq_pcs_rx_clk_ops = { -+ .determine_rate = ipq_pcs_clk_determine_rate, -+ .recalc_rate = ipq_pcs_rx_clk_recalc_rate, -+}; -+ -+/* Clock ops for the TX clock supplied to NSSCC */ -+static const struct clk_ops ipq_pcs_tx_clk_ops = { -+ .determine_rate = ipq_pcs_clk_determine_rate, -+ .recalc_rate = ipq_pcs_tx_clk_recalc_rate, -+}; -+ -+static struct clk_hw *ipq_pcs_clk_hw_get(struct of_phandle_args *clkspec, -+ void *data) -+{ -+ struct ipq_pcs *qpcs = data; -+ -+ switch (clkspec->args[0]) { -+ case PCS_RX_CLK: -+ return &qpcs->rx_hw; -+ case PCS_TX_CLK: -+ return &qpcs->tx_hw; -+ } -+ -+ return ERR_PTR(-EINVAL); -+} -+ -+/* Register the RX and TX clock which are output from SerDes to -+ * the NSSCC. The NSSCC driver assigns the RX and TX clock as -+ * parent, divides them to generate the MII RX and TX clock to -+ * each MII interface of the PCS as per the link speeds and -+ * interface modes. -+ */ -+static int ipq_pcs_clk_register(struct ipq_pcs *qpcs) -+{ -+ struct clk_init_data init = { }; -+ int ret; -+ -+ init.ops = &ipq_pcs_rx_clk_ops; -+ init.name = devm_kasprintf(qpcs->dev, GFP_KERNEL, "%s::rx_clk", -+ dev_name(qpcs->dev)); -+ if (!init.name) -+ return -ENOMEM; -+ -+ qpcs->rx_hw.init = &init; -+ ret = devm_clk_hw_register(qpcs->dev, &qpcs->rx_hw); -+ if (ret) -+ return ret; -+ -+ init.ops = &ipq_pcs_tx_clk_ops; -+ init.name = devm_kasprintf(qpcs->dev, GFP_KERNEL, "%s::tx_clk", -+ dev_name(qpcs->dev)); -+ if (!init.name) -+ return -ENOMEM; -+ -+ qpcs->tx_hw.init = &init; -+ ret = devm_clk_hw_register(qpcs->dev, &qpcs->tx_hw); -+ if (ret) -+ return ret; -+ -+ return devm_of_clk_add_hw_provider(qpcs->dev, ipq_pcs_clk_hw_get, qpcs); -+} -+ -+static int ipq_pcs_regmap_read(void *context, unsigned int reg, -+ unsigned int *val) -+{ -+ struct ipq_pcs *qpcs = context; -+ -+ /* PCS uses direct AHB access while XPCS uses indirect AHB access */ -+ if (reg >= XPCS_INDIRECT_ADDR) { -+ writel(FIELD_GET(XPCS_INDIRECT_ADDR_H, reg), -+ qpcs->base + XPCS_INDIRECT_AHB_ADDR); -+ *val = readl(qpcs->base + XPCS_INDIRECT_DATA_ADDR(reg)); -+ } else { -+ *val = readl(qpcs->base + reg); -+ } -+ -+ return 0; -+} -+ -+static int ipq_pcs_regmap_write(void *context, unsigned int reg, -+ unsigned int val) -+{ -+ struct ipq_pcs *qpcs = context; -+ -+ /* PCS uses direct AHB access while XPCS uses indirect AHB access */ -+ if (reg >= XPCS_INDIRECT_ADDR) { -+ writel(FIELD_GET(XPCS_INDIRECT_ADDR_H, reg), -+ qpcs->base + XPCS_INDIRECT_AHB_ADDR); -+ writel(val, qpcs->base + XPCS_INDIRECT_DATA_ADDR(reg)); -+ } else { -+ writel(val, qpcs->base + reg); -+ } -+ -+ return 0; -+} -+ -+static const struct regmap_config ipq_pcs_regmap_cfg = { -+ .reg_bits = 32, -+ .val_bits = 32, -+ .reg_read = ipq_pcs_regmap_read, -+ .reg_write = ipq_pcs_regmap_write, -+ .fast_io = true, -+}; -+ -+static int ipq9574_pcs_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ipq_pcs *qpcs; -+ struct clk *clk; -+ int ret; -+ -+ qpcs = devm_kzalloc(dev, sizeof(*qpcs), GFP_KERNEL); -+ if (!qpcs) -+ return -ENOMEM; -+ -+ qpcs->dev = dev; -+ -+ qpcs->base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(qpcs->base)) -+ return dev_err_probe(dev, PTR_ERR(qpcs->base), -+ "Failed to ioremap resource\n"); -+ -+ qpcs->regmap = devm_regmap_init(dev, NULL, qpcs, &ipq_pcs_regmap_cfg); -+ if (IS_ERR(qpcs->regmap)) -+ return dev_err_probe(dev, PTR_ERR(qpcs->regmap), -+ "Failed to allocate register map\n"); -+ -+ clk = devm_clk_get_enabled(dev, "sys"); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Failed to enable SYS clock\n"); -+ -+ clk = devm_clk_get_enabled(dev, "ahb"); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Failed to enable AHB clock\n"); -+ -+ ret = ipq_pcs_clk_register(qpcs); -+ if (ret) -+ return ret; -+ -+ platform_set_drvdata(pdev, qpcs); -+ -+ return 0; -+} -+ -+static const struct of_device_id ipq9574_pcs_of_mtable[] = { -+ { .compatible = "qcom,ipq9574-pcs" }, -+ { /* sentinel */ }, -+}; -+MODULE_DEVICE_TABLE(of, ipq9574_pcs_of_mtable); -+ -+static struct platform_driver ipq9574_pcs_driver = { -+ .driver = { -+ .name = "ipq9574_pcs", -+ .suppress_bind_attrs = true, -+ .of_match_table = ipq9574_pcs_of_mtable, -+ }, -+ .probe = ipq9574_pcs_probe, -+}; -+module_platform_driver(ipq9574_pcs_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Qualcomm IPQ9574 PCS driver"); -+MODULE_AUTHOR("Lei Wei "); diff --git a/target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch b/target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch deleted file mode 100644 index 7d071c2e25..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch +++ /dev/null @@ -1,555 +0,0 @@ -From 10b609ddbf4d369c80098efa39451ef3973759b5 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 7 Feb 2025 23:53:14 +0800 -Subject: [PATCH] net: pcs: qcom-ipq9574: Add PCS instantiation and phylink - operations - -This patch adds the following PCS functionality for the PCS driver -for IPQ9574 SoC: - -a.) Parses PCS MII DT nodes and instantiate each MII PCS instance. -b.) Exports PCS instance get and put APIs. The network driver calls -the PCS get API to get and associate the PCS instance with the port -MAC. -c.) PCS phylink operations for SGMII/QSGMII interface modes. - -Signed-off-by: Lei Wei -Alex G: remove phylink_pcs .neg_mode boolean -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 468 +++++++++++++++++++++++++++ - include/linux/pcs/pcs-qcom-ipq9574.h | 15 + - 2 files changed, 483 insertions(+) - create mode 100644 include/linux/pcs/pcs-qcom-ipq9574.h - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -6,12 +6,46 @@ - #include - #include - #include -+#include -+#include -+#include - #include -+#include - #include - #include - - #include - -+/* Maximum number of MIIs per PCS instance. There are 5 MIIs for PSGMII. */ -+#define PCS_MAX_MII_NRS 5 -+ -+#define PCS_CALIBRATION 0x1e0 -+#define PCS_CALIBRATION_DONE BIT(7) -+ -+#define PCS_MODE_CTRL 0x46c -+#define PCS_MODE_SEL_MASK GENMASK(12, 8) -+#define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) -+#define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) -+ -+#define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) -+#define PCS_MII_ADPT_RESET BIT(11) -+#define PCS_MII_FORCE_MODE BIT(3) -+#define PCS_MII_SPEED_MASK GENMASK(2, 1) -+#define PCS_MII_SPEED_1000 FIELD_PREP(PCS_MII_SPEED_MASK, 0x2) -+#define PCS_MII_SPEED_100 FIELD_PREP(PCS_MII_SPEED_MASK, 0x1) -+#define PCS_MII_SPEED_10 FIELD_PREP(PCS_MII_SPEED_MASK, 0x0) -+ -+#define PCS_MII_STS(x) (0x488 + 0x18 * (x)) -+#define PCS_MII_LINK_STS BIT(7) -+#define PCS_MII_STS_DUPLEX_FULL BIT(6) -+#define PCS_MII_STS_SPEED_MASK GENMASK(5, 4) -+#define PCS_MII_STS_SPEED_10 0 -+#define PCS_MII_STS_SPEED_100 1 -+#define PCS_MII_STS_SPEED_1000 2 -+ -+#define PCS_PLL_RESET 0x780 -+#define PCS_ANA_SW_RESET BIT(6) -+ - #define XPCS_INDIRECT_ADDR 0x8000 - #define XPCS_INDIRECT_AHB_ADDR 0x83fc - #define XPCS_INDIRECT_ADDR_H GENMASK(20, 8) -@@ -20,6 +54,18 @@ - FIELD_PREP(GENMASK(9, 2), \ - FIELD_GET(XPCS_INDIRECT_ADDR_L, reg))) - -+/* Per PCS MII private data */ -+struct ipq_pcs_mii { -+ struct ipq_pcs *qpcs; -+ struct phylink_pcs pcs; -+ int index; -+ -+ /* RX clock from NSSCC to PCS MII */ -+ struct clk *rx_clk; -+ /* TX clock from NSSCC to PCS MII */ -+ struct clk *tx_clk; -+}; -+ - /* PCS private data */ - struct ipq_pcs { - struct device *dev; -@@ -31,8 +77,358 @@ struct ipq_pcs { - struct clk_hw rx_hw; - /* TX clock supplied to NSSCC */ - struct clk_hw tx_hw; -+ -+ struct ipq_pcs_mii *qpcs_mii[PCS_MAX_MII_NRS]; - }; - -+#define phylink_pcs_to_qpcs_mii(_pcs) \ -+ container_of(_pcs, struct ipq_pcs_mii, pcs) -+ -+static void ipq_pcs_get_state_sgmii(struct ipq_pcs *qpcs, -+ int index, -+ struct phylink_link_state *state) -+{ -+ unsigned int val; -+ int ret; -+ -+ ret = regmap_read(qpcs->regmap, PCS_MII_STS(index), &val); -+ if (ret) { -+ state->link = 0; -+ return; -+ } -+ -+ state->link = !!(val & PCS_MII_LINK_STS); -+ -+ if (!state->link) -+ return; -+ -+ switch (FIELD_GET(PCS_MII_STS_SPEED_MASK, val)) { -+ case PCS_MII_STS_SPEED_1000: -+ state->speed = SPEED_1000; -+ break; -+ case PCS_MII_STS_SPEED_100: -+ state->speed = SPEED_100; -+ break; -+ case PCS_MII_STS_SPEED_10: -+ state->speed = SPEED_10; -+ break; -+ default: -+ state->link = false; -+ return; -+ } -+ -+ if (val & PCS_MII_STS_DUPLEX_FULL) -+ state->duplex = DUPLEX_FULL; -+ else -+ state->duplex = DUPLEX_HALF; -+} -+ -+static int ipq_pcs_config_mode(struct ipq_pcs *qpcs, -+ phy_interface_t interface) -+{ -+ unsigned int val; -+ int ret; -+ -+ /* Configure PCS interface mode */ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ val = PCS_MODE_SGMII; -+ break; -+ case PHY_INTERFACE_MODE_QSGMII: -+ val = PCS_MODE_QSGMII; -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL, -+ PCS_MODE_SEL_MASK, val); -+ if (ret) -+ return ret; -+ -+ /* PCS PLL reset */ -+ ret = regmap_clear_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); -+ if (ret) -+ return ret; -+ -+ fsleep(1000); -+ ret = regmap_set_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); -+ if (ret) -+ return ret; -+ -+ /* Wait for calibration completion */ -+ ret = regmap_read_poll_timeout(qpcs->regmap, PCS_CALIBRATION, -+ val, val & PCS_CALIBRATION_DONE, -+ 1000, 100000); -+ if (ret) { -+ dev_err(qpcs->dev, "PCS calibration timed-out\n"); -+ return ret; -+ } -+ -+ qpcs->interface = interface; -+ -+ return 0; -+} -+ -+static int ipq_pcs_config_sgmii(struct ipq_pcs *qpcs, -+ int index, -+ unsigned int neg_mode, -+ phy_interface_t interface) -+{ -+ int ret; -+ -+ /* Configure the PCS mode if required */ -+ if (qpcs->interface != interface) { -+ ret = ipq_pcs_config_mode(qpcs, interface); -+ if (ret) -+ return ret; -+ } -+ -+ /* Nothing to do here as in-band autoneg mode is enabled -+ * by default for each PCS MII port. -+ */ -+ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) -+ return 0; -+ -+ /* Set force speed mode */ -+ return regmap_set_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); -+} -+ -+static int ipq_pcs_link_up_config_sgmii(struct ipq_pcs *qpcs, -+ int index, -+ unsigned int neg_mode, -+ int speed) -+{ -+ unsigned int val; -+ int ret; -+ -+ /* PCS speed need not be configured if in-band autoneg is enabled */ -+ if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { -+ /* PCS speed set for force mode */ -+ switch (speed) { -+ case SPEED_1000: -+ val = PCS_MII_SPEED_1000; -+ break; -+ case SPEED_100: -+ val = PCS_MII_SPEED_100; -+ break; -+ case SPEED_10: -+ val = PCS_MII_SPEED_10; -+ break; -+ default: -+ dev_err(qpcs->dev, "Invalid SGMII speed %d\n", speed); -+ return -EINVAL; -+ } -+ -+ ret = regmap_update_bits(qpcs->regmap, PCS_MII_CTRL(index), -+ PCS_MII_SPEED_MASK, val); -+ if (ret) -+ return ret; -+ } -+ -+ /* PCS adapter reset */ -+ ret = regmap_clear_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); -+ if (ret) -+ return ret; -+ -+ return regmap_set_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); -+} -+ -+static int ipq_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, -+ const struct phylink_link_state *state) -+{ -+ switch (state->interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return 0; -+ default: -+ return -EINVAL; -+ } -+} -+ -+static unsigned int ipq_pcs_inband_caps(struct phylink_pcs *pcs, -+ phy_interface_t interface) -+{ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ default: -+ return 0; -+ } -+} -+ -+static int ipq_pcs_enable(struct phylink_pcs *pcs) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ struct ipq_pcs *qpcs = qpcs_mii->qpcs; -+ int index = qpcs_mii->index; -+ int ret; -+ -+ ret = clk_prepare_enable(qpcs_mii->rx_clk); -+ if (ret) { -+ dev_err(qpcs->dev, "Failed to enable MII %d RX clock\n", index); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(qpcs_mii->tx_clk); -+ if (ret) { -+ /* This is a fatal event since phylink does not support unwinding -+ * the state back for this error. So, we only report the error -+ * and do not disable the clocks. -+ */ -+ dev_err(qpcs->dev, "Failed to enable MII %d TX clock\n", index); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void ipq_pcs_disable(struct phylink_pcs *pcs) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ -+ clk_disable_unprepare(qpcs_mii->rx_clk); -+ clk_disable_unprepare(qpcs_mii->tx_clk); -+} -+ -+static void ipq_pcs_get_state(struct phylink_pcs *pcs, -+ struct phylink_link_state *state) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ struct ipq_pcs *qpcs = qpcs_mii->qpcs; -+ int index = qpcs_mii->index; -+ -+ switch (state->interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ ipq_pcs_get_state_sgmii(qpcs, index, state); -+ break; -+ default: -+ break; -+ } -+ -+ dev_dbg_ratelimited(qpcs->dev, -+ "mode=%s/%s/%s link=%u\n", -+ phy_modes(state->interface), -+ phy_speed_to_str(state->speed), -+ phy_duplex_to_str(state->duplex), -+ state->link); -+} -+ -+static int ipq_pcs_config(struct phylink_pcs *pcs, -+ unsigned int neg_mode, -+ phy_interface_t interface, -+ const unsigned long *advertising, -+ bool permit) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ struct ipq_pcs *qpcs = qpcs_mii->qpcs; -+ int index = qpcs_mii->index; -+ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); -+ default: -+ return -EOPNOTSUPP; -+ }; -+} -+ -+static void ipq_pcs_link_up(struct phylink_pcs *pcs, -+ unsigned int neg_mode, -+ phy_interface_t interface, -+ int speed, int duplex) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ struct ipq_pcs *qpcs = qpcs_mii->qpcs; -+ int index = qpcs_mii->index; -+ int ret; -+ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ ret = ipq_pcs_link_up_config_sgmii(qpcs, index, -+ neg_mode, speed); -+ break; -+ default: -+ return; -+ } -+ -+ if (ret) -+ dev_err(qpcs->dev, "PCS link up fail for interface %s\n", -+ phy_modes(interface)); -+} -+ -+static const struct phylink_pcs_ops ipq_pcs_phylink_ops = { -+ .pcs_validate = ipq_pcs_validate, -+ .pcs_inband_caps = ipq_pcs_inband_caps, -+ .pcs_enable = ipq_pcs_enable, -+ .pcs_disable = ipq_pcs_disable, -+ .pcs_get_state = ipq_pcs_get_state, -+ .pcs_config = ipq_pcs_config, -+ .pcs_link_up = ipq_pcs_link_up, -+}; -+ -+/* Parse the PCS MII DT nodes which are child nodes of the PCS node, -+ * and instantiate each MII PCS instance. -+ */ -+static int ipq_pcs_create_miis(struct ipq_pcs *qpcs) -+{ -+ struct device *dev = qpcs->dev; -+ struct ipq_pcs_mii *qpcs_mii; -+ struct device_node *mii_np; -+ u32 index; -+ int ret; -+ -+ for_each_available_child_of_node(dev->of_node, mii_np) { -+ ret = of_property_read_u32(mii_np, "reg", &index); -+ if (ret) { -+ dev_err(dev, "Failed to read MII index\n"); -+ of_node_put(mii_np); -+ return ret; -+ } -+ -+ if (index >= PCS_MAX_MII_NRS) { -+ dev_err(dev, "Invalid MII index\n"); -+ of_node_put(mii_np); -+ return -EINVAL; -+ } -+ -+ qpcs_mii = devm_kzalloc(dev, sizeof(*qpcs_mii), GFP_KERNEL); -+ if (!qpcs_mii) { -+ of_node_put(mii_np); -+ return -ENOMEM; -+ } -+ -+ qpcs_mii->qpcs = qpcs; -+ qpcs_mii->index = index; -+ qpcs_mii->pcs.ops = &ipq_pcs_phylink_ops; -+ qpcs_mii->pcs.poll = true; -+ -+ qpcs_mii->rx_clk = devm_get_clk_from_child(dev, mii_np, "rx"); -+ if (IS_ERR(qpcs_mii->rx_clk)) { -+ of_node_put(mii_np); -+ return dev_err_probe(dev, PTR_ERR(qpcs_mii->rx_clk), -+ "Failed to get MII %d RX clock\n", index); -+ } -+ -+ qpcs_mii->tx_clk = devm_get_clk_from_child(dev, mii_np, "tx"); -+ if (IS_ERR(qpcs_mii->tx_clk)) { -+ of_node_put(mii_np); -+ return dev_err_probe(dev, PTR_ERR(qpcs_mii->tx_clk), -+ "Failed to get MII %d TX clock\n", index); -+ } -+ -+ qpcs->qpcs_mii[index] = qpcs_mii; -+ } -+ -+ return 0; -+} -+ - static unsigned long ipq_pcs_clk_rate_get(struct ipq_pcs *qpcs) - { - switch (qpcs->interface) { -@@ -219,6 +615,10 @@ static int ipq9574_pcs_probe(struct plat - if (ret) - return ret; - -+ ret = ipq_pcs_create_miis(qpcs); -+ if (ret) -+ return ret; -+ - platform_set_drvdata(pdev, qpcs); - - return 0; -@@ -230,6 +630,74 @@ static const struct of_device_id ipq9574 - }; - MODULE_DEVICE_TABLE(of, ipq9574_pcs_of_mtable); - -+/** -+ * ipq_pcs_get() - Get the IPQ PCS MII instance -+ * @np: Device tree node to the PCS MII -+ * -+ * Description: Get the phylink PCS instance for the given PCS MII node @np. -+ * This instance is associated with the specific MII of the PCS and the -+ * corresponding Ethernet netdevice. -+ * -+ * Return: A pointer to the phylink PCS instance or an error-pointer value. -+ */ -+struct phylink_pcs *ipq_pcs_get(struct device_node *np) -+{ -+ struct platform_device *pdev; -+ struct ipq_pcs_mii *qpcs_mii; -+ struct ipq_pcs *qpcs; -+ u32 index; -+ -+ if (of_property_read_u32(np, "reg", &index)) -+ return ERR_PTR(-EINVAL); -+ -+ if (index >= PCS_MAX_MII_NRS) -+ return ERR_PTR(-EINVAL); -+ -+ if (!of_match_node(ipq9574_pcs_of_mtable, np->parent)) -+ return ERR_PTR(-EINVAL); -+ -+ /* Get the parent device */ -+ pdev = of_find_device_by_node(np->parent); -+ if (!pdev) -+ return ERR_PTR(-ENODEV); -+ -+ qpcs = platform_get_drvdata(pdev); -+ if (!qpcs) { -+ put_device(&pdev->dev); -+ -+ /* If probe is not yet completed, return DEFER to -+ * the dependent driver. -+ */ -+ return ERR_PTR(-EPROBE_DEFER); -+ } -+ -+ qpcs_mii = qpcs->qpcs_mii[index]; -+ if (!qpcs_mii) { -+ put_device(&pdev->dev); -+ return ERR_PTR(-ENOENT); -+ } -+ -+ return &qpcs_mii->pcs; -+} -+EXPORT_SYMBOL(ipq_pcs_get); -+ -+/** -+ * ipq_pcs_put() - Release the IPQ PCS MII instance -+ * @pcs: PCS instance -+ * -+ * Description: Release a phylink PCS instance. -+ */ -+void ipq_pcs_put(struct phylink_pcs *pcs) -+{ -+ struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); -+ -+ /* Put reference taken by of_find_device_by_node() in -+ * ipq_pcs_get(). -+ */ -+ put_device(qpcs_mii->qpcs->dev); -+} -+EXPORT_SYMBOL(ipq_pcs_put); -+ - static struct platform_driver ipq9574_pcs_driver = { - .driver = { - .name = "ipq9574_pcs", ---- /dev/null -+++ b/include/linux/pcs/pcs-qcom-ipq9574.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __LINUX_PCS_QCOM_IPQ9574_H -+#define __LINUX_PCS_QCOM_IPQ9574_H -+ -+struct device_node; -+struct phylink_pcs; -+ -+struct phylink_pcs *ipq_pcs_get(struct device_node *np); -+void ipq_pcs_put(struct phylink_pcs *pcs); -+ -+#endif /* __LINUX_PCS_QCOM_IPQ9574_H */ diff --git a/target/linux/qualcommbe/patches-6.12/0317-net-pcs-qcom-ipq9574-Add-USXGMII-interface-mode-supp.patch b/target/linux/qualcommbe/patches-6.12/0317-net-pcs-qcom-ipq9574-Add-USXGMII-interface-mode-supp.patch deleted file mode 100644 index b1cddffc6a..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0317-net-pcs-qcom-ipq9574-Add-USXGMII-interface-mode-supp.patch +++ /dev/null @@ -1,272 +0,0 @@ -From 4923ca63214a4e6bbee1b3f8f6b9b79f0fd3a3be Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 7 Feb 2025 23:53:15 +0800 -Subject: [PATCH] net: pcs: qcom-ipq9574: Add USXGMII interface mode support - -USXGMII mode is enabled by PCS when 10Gbps PHYs are connected, such as -Aquantia 10Gbps PHY. - -Signed-off-by: Lei Wei ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 170 +++++++++++++++++++++++++++++ - 1 file changed, 170 insertions(+) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -26,6 +26,7 @@ - #define PCS_MODE_SEL_MASK GENMASK(12, 8) - #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) - #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) -+#define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) - - #define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) - #define PCS_MII_ADPT_RESET BIT(11) -@@ -54,6 +55,34 @@ - FIELD_PREP(GENMASK(9, 2), \ - FIELD_GET(XPCS_INDIRECT_ADDR_L, reg))) - -+#define XPCS_DIG_CTRL 0x38000 -+#define XPCS_USXG_ADPT_RESET BIT(10) -+#define XPCS_USXG_EN BIT(9) -+ -+#define XPCS_MII_CTRL 0x1f0000 -+#define XPCS_MII_AN_EN BIT(12) -+#define XPCS_DUPLEX_FULL BIT(8) -+#define XPCS_SPEED_MASK (BIT(13) | BIT(6) | BIT(5)) -+#define XPCS_SPEED_10000 (BIT(13) | BIT(6)) -+#define XPCS_SPEED_5000 (BIT(13) | BIT(5)) -+#define XPCS_SPEED_2500 BIT(5) -+#define XPCS_SPEED_1000 BIT(6) -+#define XPCS_SPEED_100 BIT(13) -+#define XPCS_SPEED_10 0 -+ -+#define XPCS_MII_AN_CTRL 0x1f8001 -+#define XPCS_MII_AN_8BIT BIT(8) -+ -+#define XPCS_MII_AN_INTR_STS 0x1f8002 -+#define XPCS_USXG_AN_LINK_STS BIT(14) -+#define XPCS_USXG_AN_SPEED_MASK GENMASK(12, 10) -+#define XPCS_USXG_AN_SPEED_10 0 -+#define XPCS_USXG_AN_SPEED_100 1 -+#define XPCS_USXG_AN_SPEED_1000 2 -+#define XPCS_USXG_AN_SPEED_2500 4 -+#define XPCS_USXG_AN_SPEED_5000 5 -+#define XPCS_USXG_AN_SPEED_10000 3 -+ - /* Per PCS MII private data */ - struct ipq_pcs_mii { - struct ipq_pcs *qpcs; -@@ -123,9 +152,54 @@ static void ipq_pcs_get_state_sgmii(stru - state->duplex = DUPLEX_HALF; - } - -+static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, -+ struct phylink_link_state *state) -+{ -+ unsigned int val; -+ int ret; -+ -+ ret = regmap_read(qpcs->regmap, XPCS_MII_AN_INTR_STS, &val); -+ if (ret) { -+ state->link = 0; -+ return; -+ } -+ -+ state->link = !!(val & XPCS_USXG_AN_LINK_STS); -+ -+ if (!state->link) -+ return; -+ -+ switch (FIELD_GET(XPCS_USXG_AN_SPEED_MASK, val)) { -+ case XPCS_USXG_AN_SPEED_10000: -+ state->speed = SPEED_10000; -+ break; -+ case XPCS_USXG_AN_SPEED_5000: -+ state->speed = SPEED_5000; -+ break; -+ case XPCS_USXG_AN_SPEED_2500: -+ state->speed = SPEED_2500; -+ break; -+ case XPCS_USXG_AN_SPEED_1000: -+ state->speed = SPEED_1000; -+ break; -+ case XPCS_USXG_AN_SPEED_100: -+ state->speed = SPEED_100; -+ break; -+ case XPCS_USXG_AN_SPEED_10: -+ state->speed = SPEED_10; -+ break; -+ default: -+ state->link = false; -+ return; -+ } -+ -+ state->duplex = DUPLEX_FULL; -+} -+ - static int ipq_pcs_config_mode(struct ipq_pcs *qpcs, - phy_interface_t interface) - { -+ unsigned long rate = 125000000; - unsigned int val; - int ret; - -@@ -137,6 +211,10 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_QSGMII: - val = PCS_MODE_QSGMII; - break; -+ case PHY_INTERFACE_MODE_USXGMII: -+ val = PCS_MODE_XPCS; -+ rate = 312500000; -+ break; - default: - return -EOPNOTSUPP; - } -@@ -167,6 +245,21 @@ static int ipq_pcs_config_mode(struct ip - - qpcs->interface = interface; - -+ /* Configure the RX and TX clock to NSSCC as 125M or 312.5M based -+ * on current interface mode. -+ */ -+ ret = clk_set_rate(qpcs->rx_hw.clk, rate); -+ if (ret) { -+ dev_err(qpcs->dev, "Failed to set RX clock rate\n"); -+ return ret; -+ } -+ -+ ret = clk_set_rate(qpcs->tx_hw.clk, rate); -+ if (ret) { -+ dev_err(qpcs->dev, "Failed to set TX clock rate\n"); -+ return ret; -+ } -+ - return 0; - } - -@@ -195,6 +288,29 @@ static int ipq_pcs_config_sgmii(struct i - PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); - } - -+static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs) -+{ -+ int ret; -+ -+ /* Configure the XPCS for USXGMII mode if required */ -+ if (qpcs->interface == PHY_INTERFACE_MODE_USXGMII) -+ return 0; -+ -+ ret = ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_USXGMII); -+ if (ret) -+ return ret; -+ -+ ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_USXG_EN); -+ if (ret) -+ return ret; -+ -+ ret = regmap_set_bits(qpcs->regmap, XPCS_MII_AN_CTRL, XPCS_MII_AN_8BIT); -+ if (ret) -+ return ret; -+ -+ return regmap_set_bits(qpcs->regmap, XPCS_MII_CTRL, XPCS_MII_AN_EN); -+} -+ - static int ipq_pcs_link_up_config_sgmii(struct ipq_pcs *qpcs, - int index, - unsigned int neg_mode, -@@ -237,6 +353,46 @@ static int ipq_pcs_link_up_config_sgmii( - PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); - } - -+static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, int speed) -+{ -+ unsigned int val; -+ int ret; -+ -+ switch (speed) { -+ case SPEED_10000: -+ val = XPCS_SPEED_10000; -+ break; -+ case SPEED_5000: -+ val = XPCS_SPEED_5000; -+ break; -+ case SPEED_2500: -+ val = XPCS_SPEED_2500; -+ break; -+ case SPEED_1000: -+ val = XPCS_SPEED_1000; -+ break; -+ case SPEED_100: -+ val = XPCS_SPEED_100; -+ break; -+ case SPEED_10: -+ val = XPCS_SPEED_10; -+ break; -+ default: -+ dev_err(qpcs->dev, "Invalid USXGMII speed %d\n", speed); -+ return -EINVAL; -+ } -+ -+ /* Configure XPCS speed */ -+ ret = regmap_update_bits(qpcs->regmap, XPCS_MII_CTRL, -+ XPCS_SPEED_MASK, val | XPCS_DUPLEX_FULL); -+ if (ret) -+ return ret; -+ -+ /* XPCS adapter reset */ -+ return regmap_set_bits(qpcs->regmap, -+ XPCS_DIG_CTRL, XPCS_USXG_ADPT_RESET); -+} -+ - static int ipq_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, - const struct phylink_link_state *state) - { -@@ -244,6 +400,11 @@ static int ipq_pcs_validate(struct phyli - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: - return 0; -+ case PHY_INTERFACE_MODE_USXGMII: -+ /* USXGMII only supports full duplex mode */ -+ phylink_clear(supported, 100baseT_Half); -+ phylink_clear(supported, 10baseT_Half); -+ return 0; - default: - return -EINVAL; - } -@@ -255,6 +416,7 @@ static unsigned int ipq_pcs_inband_caps( - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_USXGMII: - return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; - default: - return 0; -@@ -307,6 +469,9 @@ static void ipq_pcs_get_state(struct phy - case PHY_INTERFACE_MODE_QSGMII: - ipq_pcs_get_state_sgmii(qpcs, index, state); - break; -+ case PHY_INTERFACE_MODE_USXGMII: -+ ipq_pcs_get_state_usxgmii(qpcs, state); -+ break; - default: - break; - } -@@ -333,6 +498,8 @@ static int ipq_pcs_config(struct phylink - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); -+ case PHY_INTERFACE_MODE_USXGMII: -+ return ipq_pcs_config_usxgmii(qpcs); - default: - return -EOPNOTSUPP; - }; -@@ -354,6 +521,9 @@ static void ipq_pcs_link_up(struct phyli - ret = ipq_pcs_link_up_config_sgmii(qpcs, index, - neg_mode, speed); - break; -+ case PHY_INTERFACE_MODE_USXGMII: -+ ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); -+ break; - default: - return; - } diff --git a/target/linux/qualcommbe/patches-6.12/0318-MAINTAINERS-Add-maintainer-for-Qualcomm-IPQ9574-PCS-.patch b/target/linux/qualcommbe/patches-6.12/0318-MAINTAINERS-Add-maintainer-for-Qualcomm-IPQ9574-PCS-.patch deleted file mode 100644 index adaf5575fc..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0318-MAINTAINERS-Add-maintainer-for-Qualcomm-IPQ9574-PCS-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 34d10a4eb8fea32bb79e3012dc9d8bd2dffb0df3 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 7 Feb 2025 23:53:16 +0800 -Subject: [PATCH] MAINTAINERS: Add maintainer for Qualcomm IPQ9574 PCS driver - -Add maintainer for the Ethernet PCS driver supported for Qualcomm -IPQ9574 SoC. - -Signed-off-by: Lei Wei ---- - MAINTAINERS | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -19129,6 +19129,15 @@ S: Maintained - F: Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml - F: drivers/regulator/vqmmc-ipq4019-regulator.c - -+QUALCOMM IPQ9574 Ethernet PCS DRIVER -+M: Lei Wei -+L: netdev@vger.kernel.org -+S: Supported -+F: Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml -+F: drivers/net/pcs/pcs-qcom-ipq9574.c -+F: include/dt-bindings/net/qcom,ipq9574-pcs.h -+F: include/linux/pcs/pcs-qcom-ipq9574.h -+ - QUALCOMM NAND CONTROLLER DRIVER - M: Manivannan Sadhasivam - L: linux-mtd@lists.infradead.org diff --git a/target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch b/target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch deleted file mode 100644 index 8196ff601c..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch +++ /dev/null @@ -1,139 +0,0 @@ -From d6f184181b076cbb54f152994f5bc73ce524a67e Mon Sep 17 00:00:00 2001 -From: Alexandru Gagniuc -Date: Sun, 11 May 2025 18:21:00 -0500 -Subject: [PATCH] arm64: dts: qcom: ipq9574: add PCS uniphy nodes - -IPQ9574 has three uniphy blocks. IPQ9554 lacks uniphy1. They take -their system and AHB clocks from NSSCC, and also feed NSSCC with -the clocks that are intended for the PHYs. This is not a cirular -dependency. Add nodes for these uniphy blocks, and the clocks they -feed back to the NSSCC node. - -Signed-off-by: Alexandru Gagniuc ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 100 ++++++++++++++++++++++++-- - 1 file changed, 94 insertions(+), 6 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1247,12 +1248,12 @@ - <&cmn_pll NSS_1200MHZ_CLK>, - <&cmn_pll PPE_353MHZ_CLK>, - <&gcc GPLL0_OUT_AUX>, -- <0>, -- <0>, -- <0>, -- <0>, -- <0>, -- <0>, -+ <&pcs0 0>, -+ <&pcs0 1>, -+ <&pcs1 0>, -+ <&pcs1 1>, -+ <&pcs2 0>, -+ <&pcs2 1>, - <&gcc GCC_NSSCC_CLK>; - clock-names = "xo", - "nss_1200", -@@ -1269,6 +1270,93 @@ - #reset-cells = <1>; - #interconnect-cells = <1>; - }; -+ -+ pcs0: ethernet-pcs@7a00000 { -+ compatible = "qcom,ipq9574-pcs"; -+ reg = <0x7a00000 0x10000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ clocks = <&gcc GCC_UNIPHY0_SYS_CLK>, -+ <&gcc GCC_UNIPHY0_AHB_CLK>; -+ clock-names = "sys", -+ "ahb"; -+ resets = <&gcc GCC_UNIPHY0_XPCS_RESET>; -+ #clock-cells = <1>; -+ -+ pcs0_ch0: pcs-mii@0 { -+ reg = <0>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT1_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT1_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs0_ch1: pcs-mii@1 { -+ reg = <1>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT2_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT2_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs0_ch2: pcs-mii@2 { -+ reg = <2>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT3_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT3_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ -+ pcs0_ch3: pcs-mii@3 { -+ reg = <3>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT4_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT4_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ }; -+ -+ pcs1: ethernet-pcs@7a10000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "qcom,ipq9574-pcs"; -+ reg = <0x7a10000 0x10000>; -+ clocks = <&gcc GCC_UNIPHY1_SYS_CLK>, -+ <&gcc GCC_UNIPHY1_AHB_CLK>; -+ clock-names = "sys", -+ "ahb"; -+ resets = <&gcc GCC_UNIPHY1_XPCS_RESET>; -+ #clock-cells = <1>; -+ -+ pcs1_ch0: pcs-mii@0 { -+ reg = <0>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT5_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT5_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ }; -+ -+ pcs2: ethernet-pcs@7a20000 { -+ compatible = "qcom,ipq9574-pcs"; -+ reg = <0x7a20000 0x10000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ clocks = <&gcc GCC_UNIPHY2_SYS_CLK>, -+ <&gcc GCC_UNIPHY2_AHB_CLK>; -+ clock-names = "sys", -+ "ahb"; -+ resets = <&gcc GCC_UNIPHY2_XPCS_RESET>; -+ #clock-cells = <1>; -+ -+ pcs2_ch0: pcs-mii@0 { -+ reg = <0>; -+ clocks = <&nsscc NSS_CC_UNIPHY_PORT6_RX_CLK>, -+ <&nsscc NSS_CC_UNIPHY_PORT6_TX_CLK>; -+ clock-names = "rx", -+ "tx"; -+ }; -+ }; - }; - - thermal-zones { diff --git a/target/linux/qualcommbe/patches-6.12/0323-dt-bindings-net-Add-PPE-for-Qualcomm-IPQ9574-SoC.patch b/target/linux/qualcommbe/patches-6.12/0323-dt-bindings-net-Add-PPE-for-Qualcomm-IPQ9574-SoC.patch deleted file mode 100644 index 89c09ff9ea..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0323-dt-bindings-net-Add-PPE-for-Qualcomm-IPQ9574-SoC.patch +++ /dev/null @@ -1,432 +0,0 @@ -From 48dc6d2fe28865a5c3d271aeb966b984a8085e7c Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:35 +0800 -Subject: [PATCH] dt-bindings: net: Add PPE for Qualcomm IPQ9574 SoC - -The PPE (packet process engine) hardware block is available in Qualcomm -IPQ chipsets that support PPE architecture, such as IPQ9574. The PPE in -the IPQ9574 SoC includes six ethernet ports (6 GMAC and 6 XGMAC), which -are used to connect with external PHY devices by PCS. It includes an L2 -switch function for bridging packets among the 6 ethernet ports and the -CPU port. The CPU port enables packet transfer between the ethernet -ports and the ARM cores in the SoC, using the ethernet DMA. - -The PPE also includes packet processing offload capabilities for various -networking functions such as route and bridge flows, VLANs, different -tunnel protocols and VPN. - -Signed-off-by: Luo Jie ---- - .../bindings/net/qcom,ipq9574-ppe.yaml | 406 ++++++++++++++++++ - 1 file changed, 406 insertions(+) - create mode 100644 Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml - ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml -@@ -0,0 +1,406 @@ -+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/net/qcom,ipq9574-ppe.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm IPQ packet process engine (PPE) -+ -+maintainers: -+ - Luo Jie -+ - Lei Wei -+ - Suruchi Agarwal -+ - Pavithra R > -+ -+description: -+ The Ethernet functionality in the PPE (Packet Process Engine) is comprised -+ of three components, the switch core, port wrapper and Ethernet DMA. -+ -+ The Switch core in the IPQ9574 PPE has maximum of 6 front panel ports and -+ two FIFO interfaces. One of the two FIFO interfaces is used for Ethernet -+ port to host CPU communication using Ethernet DMA. The other is used -+ communicating to the EIP engine which is used for IPsec offload. On the -+ IPQ9574, the PPE includes 6 GMAC/XGMACs that can be connected with external -+ Ethernet PHY. Switch core also includes BM (Buffer Management), QM (Queue -+ Management) and SCH (Scheduler) modules for supporting the packet processing. -+ -+ The port wrapper provides connections from the 6 GMAC/XGMACS to UNIPHY (PCS) -+ supporting various modes such as SGMII/QSGMII/PSGMII/USXGMII/10G-BASER. There -+ are 3 UNIPHY (PCS) instances supported on the IPQ9574. -+ -+ Ethernet DMA is used to transmit and receive packets between the six Ethernet -+ ports and ARM host CPU. -+ -+ The follow diagram shows the PPE hardware block along with its connectivity -+ to the external hardware blocks such clock hardware blocks (CMNPLL, GCC, -+ NSS clock controller) and ethernet PCS/PHY blocks. For depicting the PHY -+ connectivity, one 4x1 Gbps PHY (QCA8075) and two 10 GBps PHYs are used as an -+ example. -+ - | -+ +---------+ -+ | 48 MHZ | -+ +----+----+ -+ |(clock) -+ v -+ +----+----+ -+ +------| CMN PLL | -+ | +----+----+ -+ | |(clock) -+ | v -+ | +----+----+ +----+----+ (clock) +----+----+ -+ | +---| NSSCC | | GCC |--------->| MDIO | -+ | | +----+----+ +----+----+ +----+----+ -+ | | |(clock & reset) |(clock) -+ | | v v -+ | | +-----------------------------+----------+----------+---------+ -+ | | | +-----+ |EDMA FIFO | | EIP FIFO| -+ | | | | SCH | +----------+ +---------+ -+ | | | +-----+ | | | -+ | | | +------+ +------+ +-------------------+ | -+ | | | | BM | | QM | IPQ9574-PPE | L2/L3 Process | | -+ | | | +------+ +------+ +-------------------+ | -+ | | | | | -+ | | | +-------+ +-------+ +-------+ +-------+ +-------+ +-------+ | -+ | | | | MAC0 | | MAC1 | | MAC2 | | MAC3 | | XGMAC4| |XGMAC5 | | -+ | | | +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ | -+ | | | | | | | | | | -+ | | +-----+---------+---------+---------+---------+---------+-----+ -+ | | | | | | | | -+ | | +---+---------+---------+---------+---+ +---+---+ +---+---+ -+ +--+---->| PCS0 | | PCS1 | | PCS2 | -+ |(clock) +---+---------+---------+---------+---+ +---+---+ +---+---+ -+ | | | | | | | -+ | +---+---------+---------+---------+---+ +---+---+ +---+---+ -+ +------->| QCA8075 PHY | | PHY4 | | PHY5 | -+ (clock) +-------------------------------------+ +-------+ +-------+ -+ -+properties: -+ compatible: -+ enum: -+ - qcom,ipq9574-ppe -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ items: -+ - description: PPE core clock from NSS clock controller -+ - description: PPE APB (Advanced Peripheral Bus) clock from NSS clock controller -+ - description: PPE ingress process engine clock from NSS clock controller -+ - description: PPE BM, QM and scheduler clock from NSS clock controller -+ -+ clock-names: -+ items: -+ - const: ppe -+ - const: apb -+ - const: ipe -+ - const: btq -+ -+ resets: -+ maxItems: 1 -+ description: PPE reset, which is necessary before configuring PPE hardware -+ -+ interconnects: -+ items: -+ - description: Clock path leading to PPE switch core function -+ - description: Clock path leading to PPE register access -+ - description: Clock path leading to QoS generation -+ - description: Clock path leading to timeout reference -+ - description: Clock path leading to NSS NOC from memory NOC -+ - description: Clock path leading to memory NOC from NSS NOC -+ - description: Clock path leading to enhanced memory NOC from NSS NOC -+ -+ interconnect-names: -+ items: -+ - const: ppe -+ - const: ppe_cfg -+ - const: qos_gen -+ - const: timeout_ref -+ - const: nssnoc_memnoc -+ - const: memnoc_nssnoc -+ - const: memnoc_nssnoc_1 -+ -+ ethernet-dma: -+ type: object -+ additionalProperties: false -+ description: -+ EDMA (Ethernet DMA) is used to transmit packets between PPE and ARM -+ host CPU. There are 32 TX descriptor rings, 32 TX completion rings, -+ 24 RX descriptor rings and 8 RX fill rings supported. -+ -+ properties: -+ clocks: -+ items: -+ - description: EDMA system clock from NSS Clock Controller -+ - description: EDMA APB (Advanced Peripheral Bus) clock from -+ NSS Clock Controller -+ -+ clock-names: -+ items: -+ - const: sys -+ - const: apb -+ -+ resets: -+ maxItems: 1 -+ description: EDMA reset from NSS clock controller -+ -+ interrupts: -+ minItems: 29 -+ maxItems: 57 -+ -+ interrupt-names: -+ minItems: 29 -+ maxItems: 57 -+ items: -+ pattern: '^(txcmpl_([0-9]|[1-2][0-9]|3[0-1])|rxdesc_([0-9]|1[0-9]|2[0-3])|misc)$' -+ description: -+ Interrupts "txcmpl_[0-31]" are the Ethernet DMA Tx completion ring interrupts. -+ Interrupts "rxdesc_[0-23]" are the Ethernet DMA Rx Descriptor ring interrupts. -+ Interrupt "misc" is the Ethernet DMA miscellaneous error interrupt. -+ -+ required: -+ - clocks -+ - clock-names -+ - resets -+ - interrupts -+ - interrupt-names -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - clock-names -+ - resets -+ - interconnects -+ - interconnect-names -+ - ethernet-dma -+ -+allOf: -+ - $ref: ethernet-switch.yaml -+ -+unevaluatedProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ -+ ethernet-switch@3a000000 { -+ compatible = "qcom,ipq9574-ppe"; -+ reg = <0x3a000000 0xbef800>; -+ clocks = <&nsscc 80>, -+ <&nsscc 79>, -+ <&nsscc 81>, -+ <&nsscc 78>; -+ clock-names = "ppe", -+ "apb", -+ "ipe", -+ "btq"; -+ resets = <&nsscc 108>; -+ interconnects = <&nsscc MASTER_NSSNOC_PPE &nsscc SLAVE_NSSNOC_PPE>, -+ <&nsscc MASTER_NSSNOC_PPE_CFG &nsscc SLAVE_NSSNOC_PPE_CFG>, -+ <&gcc MASTER_NSSNOC_QOSGEN_REF &gcc SLAVE_NSSNOC_QOSGEN_REF>, -+ <&gcc MASTER_NSSNOC_TIMEOUT_REF &gcc SLAVE_NSSNOC_TIMEOUT_REF>, -+ <&gcc MASTER_MEM_NOC_NSSNOC &gcc SLAVE_MEM_NOC_NSSNOC>, -+ <&gcc MASTER_NSSNOC_MEMNOC &gcc SLAVE_NSSNOC_MEMNOC>, -+ <&gcc MASTER_NSSNOC_MEM_NOC_1 &gcc SLAVE_NSSNOC_MEM_NOC_1>; -+ interconnect-names = "ppe", -+ "ppe_cfg", -+ "qos_gen", -+ "timeout_ref", -+ "nssnoc_memnoc", -+ "memnoc_nssnoc", -+ "memnoc_nssnoc_1"; -+ -+ ethernet-dma { -+ clocks = <&nsscc 77>, -+ <&nsscc 76>; -+ clock-names = "sys", -+ "apb"; -+ resets = <&nsscc 0>; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "txcmpl_8", -+ "txcmpl_9", -+ "txcmpl_10", -+ "txcmpl_11", -+ "txcmpl_12", -+ "txcmpl_13", -+ "txcmpl_14", -+ "txcmpl_15", -+ "txcmpl_16", -+ "txcmpl_17", -+ "txcmpl_18", -+ "txcmpl_19", -+ "txcmpl_20", -+ "txcmpl_21", -+ "txcmpl_22", -+ "txcmpl_23", -+ "txcmpl_24", -+ "txcmpl_25", -+ "txcmpl_26", -+ "txcmpl_27", -+ "txcmpl_28", -+ "txcmpl_29", -+ "txcmpl_30", -+ "txcmpl_31", -+ "rxdesc_20", -+ "rxdesc_21", -+ "rxdesc_22", -+ "rxdesc_23", -+ "misc"; -+ }; -+ -+ ethernet-ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@1 { -+ reg = <1>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy0>; -+ pcs-handle = <&pcs0_mii0>; -+ clocks = <&nsscc 33>, -+ <&nsscc 34>, -+ <&nsscc 37>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 29>, -+ <&nsscc 96>, -+ <&nsscc 97>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy1>; -+ pcs-handle = <&pcs0_mii1>; -+ clocks = <&nsscc 40>, -+ <&nsscc 41>, -+ <&nsscc 44>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 30>, -+ <&nsscc 98>, -+ <&nsscc 99>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy2>; -+ pcs-handle = <&pcs0_mii2>; -+ clocks = <&nsscc 47>, -+ <&nsscc 48>, -+ <&nsscc 51>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 31>, -+ <&nsscc 100>, -+ <&nsscc 101>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy3>; -+ pcs-handle = <&pcs0_mii3>; -+ clocks = <&nsscc 54>, -+ <&nsscc 55>, -+ <&nsscc 58>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 32>, -+ <&nsscc 102>, -+ <&nsscc 103>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@5 { -+ reg = <5>; -+ phy-mode = "usxgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy4>; -+ pcs-handle = <&pcs1_mii0>; -+ clocks = <&nsscc 61>, -+ <&nsscc 62>, -+ <&nsscc 65>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 33>, -+ <&nsscc 104>, -+ <&nsscc 105>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ phy-mode = "usxgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy5>; -+ pcs-handle = <&pcs2_mii0>; -+ clocks = <&nsscc 68>, -+ <&nsscc 69>, -+ <&nsscc 72>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc 34>, -+ <&nsscc 106>, -+ <&nsscc 107>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ }; -+ }; diff --git a/target/linux/qualcommbe/patches-6.12/0324-docs-networking-Add-PPE-driver-documentation-for-Qua.patch b/target/linux/qualcommbe/patches-6.12/0324-docs-networking-Add-PPE-driver-documentation-for-Qua.patch deleted file mode 100644 index 429006c7bc..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0324-docs-networking-Add-PPE-driver-documentation-for-Qua.patch +++ /dev/null @@ -1,227 +0,0 @@ -From 9973b6610830146af1a12fe02d2d6440eb80b0f9 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Sun, 9 Feb 2025 22:29:36 +0800 -Subject: [PATCH] docs: networking: Add PPE driver documentation for Qualcomm - IPQ9574 SoC - -Add description and high-level diagram for PPE, driver overview and -module enable/debug information. - -Signed-off-by: Lei Wei -Signed-off-by: Luo Jie ---- - .../device_drivers/ethernet/index.rst | 1 + - .../ethernet/qualcomm/ppe/ppe.rst | 197 ++++++++++++++++++ - 2 files changed, 198 insertions(+) - create mode 100644 Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst - ---- a/Documentation/networking/device_drivers/ethernet/index.rst -+++ b/Documentation/networking/device_drivers/ethernet/index.rst -@@ -49,6 +49,7 @@ Contents: - neterion/s2io - netronome/nfp - pensando/ionic -+ qualcomm/ppe/ppe - smsc/smc9 - stmicro/stmmac - ti/cpsw ---- /dev/null -+++ b/Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst -@@ -0,0 +1,197 @@ -+.. SPDX-License-Identifier: GPL-2.0 -+ -+=============================================== -+PPE Ethernet Driver for Qualcomm IPQ SoC Family -+=============================================== -+ -+Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ -+Author: Lei Wei -+ -+ -+Contents -+======== -+ -+- `PPE Overview`_ -+- `PPE Driver Overview`_ -+- `PPE Driver Supported SoCs`_ -+- `Enabling the Driver`_ -+- `Debugging`_ -+ -+ -+PPE Overview -+============ -+ -+IPQ (Qualcomm Internet Processor) SoC (System-on-Chip) series is Qualcomm's series of -+networking SoC for Wi-Fi access points. The PPE (Packet Process Engine) is the Ethernet -+packet process engine in the IPQ SoC. -+ -+Below is a simplified hardware diagram of IPQ9574 SoC which includes the PPE engine and -+other blocks which are in the SoC but outside the PPE engine. These blocks work together -+to enable the Ethernet for the IPQ SoC:: -+ -+ +------+ +------+ +------+ +------+ +------+ +------+ start +-------+ -+ |netdev| |netdev| |netdev| |netdev| |netdev| |netdev|<------|PHYLINK| -+ +------+ +------+ +------+ +------+ +------+ +------+ stop +-+-+-+-+ -+ | | | ^ -+ +-------+ +-------------------------+--------+----------------------+ | | | -+ | GCC | | | EDMA | | | | | -+ +---+---+ | PPE +---+----+ | | | | -+ | clk | | | | | | -+ +------>| +-----------------------+------+-----+---------------+ | | | | -+ | | Switch Core |Port0 | |Port7(EIP FIFO)| | | | | -+ | | +---+--+ +------+--------+ | | | | -+ | | | | | | | | | -+ +-------+ | | +------+---------------+----+ | | | | | -+ |CMN PLL| | | +---+ +---+ +----+ | +--------+ | | | | | | -+ +---+---+ | | |BM | |QM | |SCH | | | L2/L3 | ....... | | | | | | -+ | | | | +---+ +---+ +----+ | +--------+ | | | | | | -+ | | | | +------+--------------------+ | | | | | -+ | | | | | | | | | | -+ | v | | +-----+-+-----+-+-----+-+-+---+--+-----+-+-----+ | | | | | -+ | +------+ | | |Port1| |Port2| |Port3| |Port4| |Port5| |Port6| | | | | | -+ | |NSSCC | | | +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ | | mac| | | -+ | +-+-+--+ | | |MAC0 | |MAC1 | |MAC2 | |MAC3 | |MAC4 | |MAC5 | | |<---+ | | -+ | ^ | |clk | | +-----+-+-----+-+-----+-+-----+--+-----+-+-----+ | | ops | | -+ | | | +---->| +----|------|-------|-------|---------|--------|-----+ | | | -+ | | | +---------------------------------------------------------+ | | -+ | | | | | | | | | | | -+ | | | MII clk | QSGMII USXGMII USXGMII | | -+ | | +------------->| | | | | | | | -+ | | +-------------------------+ +---------+ +---------+ | | -+ | |125/312.5M clk| (PCS0) | | (PCS1) | | (PCS2) | pcs ops | | -+ | +--------------+ UNIPHY0 | | UNIPHY1 | | UNIPHY2 |<--------+ | -+ +--------------->| | | | | | | -+ | 31.25M ref clk +-------------------------+ +---------+ +---------+ | -+ | | | | | | | | -+ | +-----------------------------------------------------+ | -+ |25/50M ref clk| +-------------------------+ +------+ +------+ | link | -+ +------------->| | QUAD PHY | | PHY4 | | PHY5 | |---------+ -+ | +-------------------------+ +------+ +------+ | change -+ | | -+ | MDIO bus | -+ +-----------------------------------------------------+ -+ -+The CMN (Common) PLL, NSSCC (Networking Sub System Clock Controller) and GCC (Global -+Clock Controller) blocks are in the SoC and act as clock providers. -+ -+The UNIPHY block is in the SoC and provides the PCS (Physical Coding Sublayer) and -+XPCS (10-Gigabit Physical Coding Sublayer) functions to support different interface -+modes between the PPE MAC and the external PHY. -+ -+This documentation focuses on the descriptions of PPE engine and the PPE driver. -+ -+The Ethernet functionality in the PPE (Packet Process Engine) is comprised of three -+components: the switch core, port wrapper and Ethernet DMA. -+ -+The Switch core in the IPQ9574 PPE has maximum of 6 front panel ports and two FIFO -+interfaces. One of the two FIFO interfaces is used for Ethernet port to host CPU -+communication using Ethernet DMA. The other is used communicating to the EIP engine -+which is used for IPsec offload. On the IPQ9574, the PPE includes 6 GMAC/XGMACs that -+can be connected with external Ethernet PHY. Switch core also includes BM (Buffer -+Management), QM (Queue Management) and SCH (Scheduler) modules for supporting the -+packet processing. -+ -+The port wrapper provides connections from the 6 GMAC/XGMACS to UNIPHY (PCS) supporting -+various modes such as SGMII/QSGMII/PSGMII/USXGMII/10G-BASER. There are 3 UNIPHY (PCS) -+instances supported on the IPQ9574. -+ -+Ethernet DMA is used to transmit and receive packets between the Ethernet subsystem -+and ARM host CPU. -+ -+The following lists the main blocks in the PPE engine which will be driven by this -+PPE driver: -+ -+- BM -+ BM is the hardware buffer manager for the PPE switch ports. -+- QM -+ Queue Manager for managing the egress hardware queues of the PPE switch ports. -+- SCH -+ The scheduler which manages the hardware traffic scheduling for the PPE switch ports. -+- L2 -+ The L2 block performs the packet bridging in the switch core. The bridge domain is -+ represented by the VSI (Virtual Switch Instance) domain in PPE. FDB learning can be -+ enabled based on the VSI domain and bridge forwarding occurs within the VSI domain. -+- MAC -+ The PPE in the IPQ9574 supports up to six MACs (MAC0 to MAC5) which are corresponding -+ to six switch ports (port1 to port6). The MAC block is connected with external PHY -+ through the UNIPHY PCS block. Each MAC block includes the GMAC and XGMAC blocks and -+ the switch port can select to use GMAC or XMAC through a MUX selection according to -+ the external PHY's capability. -+- EDMA (Ethernet DMA) -+ The Ethernet DMA is used to transmit and receive Ethernet packets between the PPE -+ ports and the ARM cores. -+ -+The received packet on a PPE MAC port can be forwarded to another PPE MAC port. It can -+be also forwarded to internal switch port0 so that the packet can be delivered to the -+ARM cores using the Ethernet DMA (EDMA) engine. The Ethernet DMA driver will deliver the -+packet to the corresponding 'netdevice' interface. -+ -+The software instantiations of the PPE MAC (netdevice), PCS and external PHYs interact -+with the Linux PHYLINK framework to manage the connectivity between the PPE ports and -+the connected PHYs, and the port link states. This is also illustrated in above diagram. -+ -+ -+PPE Driver Overview -+=================== -+PPE driver is Ethernet driver for the Qualcomm IPQ SoC. It is a single platform driver -+which includes the PPE part and Ethernet DMA part. The PPE part initializes and drives the -+various blocks in PPE switch core such as BM/QM/L2 blocks and the PPE MACs. The EDMA part -+drives the Ethernet DMA for packet transfer between PPE ports and ARM cores, and enables -+the netdevice driver for the PPE ports. -+ -+The PPE driver files in drivers/net/ethernet/qualcomm/ppe/ are listed as below: -+ -+- Makefile -+- ppe.c -+- ppe.h -+- ppe_config.c -+- ppe_config.h -+- ppe_debugfs.c -+- ppe_debugfs.h -+- ppe_regs.h -+ -+The ppe.c file contains the main PPE platform driver and undertakes the initialization of -+PPE switch core blocks such as QM, BM and L2. The configuration APIs for these hardware -+blocks are provided in the ppe_config.c file. -+ -+The ppe.h defines the PPE device data structure which will be used by PPE driver functions. -+ -+The ppe_debugfs.c enables the PPE statistics counters such as PPE port Rx and Tx counters, -+CPU code counters and queue counters. -+ -+ -+PPE Driver Supported SoCs -+========================= -+ -+The PPE driver supports the following IPQ SoC: -+ -+- IPQ9574 -+ -+ -+Enabling the Driver -+=================== -+ -+The driver is located in the menu structure at: -+ -+ -> Device Drivers -+ -> Network device support (NETDEVICES [=y]) -+ -> Ethernet driver support -+ -> Qualcomm devices -+ -> Qualcomm Technologies, Inc. PPE Ethernet support -+ -+If this driver is built as a module, we can use below commands to install and remove it: -+ -+- insmod qcom-ppe.ko -+- rmmod qcom-ppe.ko -+ -+The PPE driver functionally depends on the CMN PLL and NSSCC clock controller drivers. -+Please make sure the dependent modules are installed before installing the PPE driver -+module. -+ -+ -+Debugging -+========= -+ -+The PPE hardware counters are available in the debugfs and can be checked by the command -+``cat /sys/kernel/debug/ppe/packet_counters``. diff --git a/target/linux/qualcommbe/patches-6.12/0325-net-ethernet-qualcomm-Add-PPE-driver-for-IPQ9574-SoC.patch b/target/linux/qualcommbe/patches-6.12/0325-net-ethernet-qualcomm-Add-PPE-driver-for-IPQ9574-SoC.patch deleted file mode 100644 index f55879ae48..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0325-net-ethernet-qualcomm-Add-PPE-driver-for-IPQ9574-SoC.patch +++ /dev/null @@ -1,339 +0,0 @@ -From d1158f0282304c89217894aa346fc45364b95542 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:37 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add PPE driver for IPQ9574 SoC - -The PPE (Packet Process Engine) hardware block is available -on Qualcomm IPQ SoC that support PPE architecture, such as -IPQ9574. - -The PPE in IPQ9574 includes six integrated ethernet MAC -(for 6 PPE ports), buffer management, queue management and -scheduler functions. The MACs can connect with the external -PHY or switch devices using the UNIPHY PCS block available -in the SoC. - -The PPE also includes various packet processing offload -capabilities such as L3 routing and L2 bridging, VLAN and -tunnel processing offload. It also includes Ethernet DMA -function for transferring packets between ARM cores and -PPE ethernet ports. - -This patch adds the base source files and Makefiles for -the PPE driver such as platform driver registration, -clock initialization, and PPE reset routines. - -Signed-off-by: Luo Jie ---- - drivers/net/ethernet/qualcomm/Kconfig | 15 ++ - drivers/net/ethernet/qualcomm/Makefile | 1 + - drivers/net/ethernet/qualcomm/ppe/Makefile | 7 + - drivers/net/ethernet/qualcomm/ppe/ppe.c | 218 +++++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe.h | 36 ++++ - 5 files changed, 277 insertions(+) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/Makefile - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe.h - ---- a/drivers/net/ethernet/qualcomm/Kconfig -+++ b/drivers/net/ethernet/qualcomm/Kconfig -@@ -61,6 +61,21 @@ config QCOM_EMAC - low power, Receive-Side Scaling (RSS), and IEEE 1588-2008 - Precision Clock Synchronization Protocol. - -+config QCOM_PPE -+ tristate "Qualcomm Technologies, Inc. PPE Ethernet support" -+ depends on HAS_IOMEM && OF -+ depends on COMMON_CLK -+ select REGMAP_MMIO -+ help -+ This driver supports the Qualcomm Technologies, Inc. packet -+ process engine (PPE) available with IPQ SoC. The PPE includes -+ the ethernet MACs, Ethernet DMA (EDMA) and switch core that -+ supports L3 flow offload, L2 switch function, RSS and tunnel -+ offload. -+ -+ To compile this driver as a module, choose M here. The module -+ will be called qcom-ppe. -+ - source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" - - endif # NET_VENDOR_QUALCOMM ---- a/drivers/net/ethernet/qualcomm/Makefile -+++ b/drivers/net/ethernet/qualcomm/Makefile -@@ -11,4 +11,5 @@ qcauart-objs := qca_uart.o - - obj-y += emac/ - -+obj-$(CONFIG_QCOM_PPE) += ppe/ - obj-$(CONFIG_RMNET) += rmnet/ ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -0,0 +1,7 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+# -+# Makefile for the device driver of PPE (Packet Process Engine) in IPQ SoC -+# -+ -+obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o -+qcom-ppe-objs := ppe.o ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c -@@ -0,0 +1,218 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE platform device probe, DTSI parser and PPE clock initializations. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ppe.h" -+ -+#define PPE_PORT_MAX 8 -+#define PPE_CLK_RATE 353000000 -+ -+/* ICC clocks for enabling PPE device. The avg_bw and peak_bw with value 0 -+ * will be updated by the clock rate of PPE. -+ */ -+static const struct icc_bulk_data ppe_icc_data[] = { -+ { -+ .name = "ppe", -+ .avg_bw = 0, -+ .peak_bw = 0, -+ }, -+ { -+ .name = "ppe_cfg", -+ .avg_bw = 0, -+ .peak_bw = 0, -+ }, -+ { -+ .name = "qos_gen", -+ .avg_bw = 6000, -+ .peak_bw = 6000, -+ }, -+ { -+ .name = "timeout_ref", -+ .avg_bw = 6000, -+ .peak_bw = 6000, -+ }, -+ { -+ .name = "nssnoc_memnoc", -+ .avg_bw = 533333, -+ .peak_bw = 533333, -+ }, -+ { -+ .name = "memnoc_nssnoc", -+ .avg_bw = 533333, -+ .peak_bw = 533333, -+ }, -+ { -+ .name = "memnoc_nssnoc_1", -+ .avg_bw = 533333, -+ .peak_bw = 533333, -+ }, -+}; -+ -+static const struct regmap_range ppe_readable_ranges[] = { -+ regmap_reg_range(0x0, 0x1ff), /* Global */ -+ regmap_reg_range(0x400, 0x5ff), /* LPI CSR */ -+ regmap_reg_range(0x1000, 0x11ff), /* GMAC0 */ -+ regmap_reg_range(0x1200, 0x13ff), /* GMAC1 */ -+ regmap_reg_range(0x1400, 0x15ff), /* GMAC2 */ -+ regmap_reg_range(0x1600, 0x17ff), /* GMAC3 */ -+ regmap_reg_range(0x1800, 0x19ff), /* GMAC4 */ -+ regmap_reg_range(0x1a00, 0x1bff), /* GMAC5 */ -+ regmap_reg_range(0xb000, 0xefff), /* PRX CSR */ -+ regmap_reg_range(0xf000, 0x1efff), /* IPE */ -+ regmap_reg_range(0x20000, 0x5ffff), /* PTX CSR */ -+ regmap_reg_range(0x60000, 0x9ffff), /* IPE L2 CSR */ -+ regmap_reg_range(0xb0000, 0xeffff), /* IPO CSR */ -+ regmap_reg_range(0x100000, 0x17ffff), /* IPE PC */ -+ regmap_reg_range(0x180000, 0x1bffff), /* PRE IPO CSR */ -+ regmap_reg_range(0x1d0000, 0x1dffff), /* Tunnel parser */ -+ regmap_reg_range(0x1e0000, 0x1effff), /* Ingress parse */ -+ regmap_reg_range(0x200000, 0x2fffff), /* IPE L3 */ -+ regmap_reg_range(0x300000, 0x3fffff), /* IPE tunnel */ -+ regmap_reg_range(0x400000, 0x4fffff), /* Scheduler */ -+ regmap_reg_range(0x500000, 0x503fff), /* XGMAC0 */ -+ regmap_reg_range(0x504000, 0x507fff), /* XGMAC1 */ -+ regmap_reg_range(0x508000, 0x50bfff), /* XGMAC2 */ -+ regmap_reg_range(0x50c000, 0x50ffff), /* XGMAC3 */ -+ regmap_reg_range(0x510000, 0x513fff), /* XGMAC4 */ -+ regmap_reg_range(0x514000, 0x517fff), /* XGMAC5 */ -+ regmap_reg_range(0x600000, 0x6fffff), /* BM */ -+ regmap_reg_range(0x800000, 0x9fffff), /* QM */ -+ regmap_reg_range(0xb00000, 0xbef800), /* EDMA */ -+}; -+ -+static const struct regmap_access_table ppe_reg_table = { -+ .yes_ranges = ppe_readable_ranges, -+ .n_yes_ranges = ARRAY_SIZE(ppe_readable_ranges), -+}; -+ -+static const struct regmap_config regmap_config_ipq9574 = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .rd_table = &ppe_reg_table, -+ .wr_table = &ppe_reg_table, -+ .max_register = 0xbef800, -+ .fast_io = true, -+}; -+ -+static int ppe_clock_init_and_reset(struct ppe_device *ppe_dev) -+{ -+ unsigned long ppe_rate = ppe_dev->clk_rate; -+ struct device *dev = ppe_dev->dev; -+ struct reset_control *rstc; -+ struct clk_bulk_data *clks; -+ struct clk *clk; -+ int ret, i; -+ -+ for (i = 0; i < ppe_dev->num_icc_paths; i++) { -+ ppe_dev->icc_paths[i].name = ppe_icc_data[i].name; -+ ppe_dev->icc_paths[i].avg_bw = ppe_icc_data[i].avg_bw ? : -+ Bps_to_icc(ppe_rate); -+ ppe_dev->icc_paths[i].peak_bw = ppe_icc_data[i].peak_bw ? : -+ Bps_to_icc(ppe_rate); -+ } -+ -+ ret = devm_of_icc_bulk_get(dev, ppe_dev->num_icc_paths, -+ ppe_dev->icc_paths); -+ if (ret) -+ return ret; -+ -+ ret = icc_bulk_set_bw(ppe_dev->num_icc_paths, ppe_dev->icc_paths); -+ if (ret) -+ return ret; -+ -+ /* The PPE clocks have a common parent clock. Setting the clock -+ * rate of "ppe" ensures the clock rate of all PPE clocks is -+ * configured to the same rate. -+ */ -+ clk = devm_clk_get(dev, "ppe"); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ -+ ret = clk_set_rate(clk, ppe_rate); -+ if (ret) -+ return ret; -+ -+ ret = devm_clk_bulk_get_all_enable(dev, &clks); -+ if (ret < 0) -+ return ret; -+ -+ /* Reset the PPE. */ -+ rstc = devm_reset_control_get_exclusive(dev, NULL); -+ if (IS_ERR(rstc)) -+ return PTR_ERR(rstc); -+ -+ ret = reset_control_assert(rstc); -+ if (ret) -+ return ret; -+ -+ /* The delay 10 ms of assert is necessary for resetting PPE. */ -+ usleep_range(10000, 11000); -+ -+ return reset_control_deassert(rstc); -+} -+ -+static int qcom_ppe_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ppe_device *ppe_dev; -+ void __iomem *base; -+ int ret, num_icc; -+ -+ num_icc = ARRAY_SIZE(ppe_icc_data); -+ ppe_dev = devm_kzalloc(dev, struct_size(ppe_dev, icc_paths, num_icc), -+ GFP_KERNEL); -+ if (!ppe_dev) -+ return -ENOMEM; -+ -+ base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(base)) -+ return dev_err_probe(dev, PTR_ERR(base), "PPE ioremap failed\n"); -+ -+ ppe_dev->regmap = devm_regmap_init_mmio(dev, base, ®map_config_ipq9574); -+ if (IS_ERR(ppe_dev->regmap)) -+ return dev_err_probe(dev, PTR_ERR(ppe_dev->regmap), -+ "PPE initialize regmap failed\n"); -+ ppe_dev->dev = dev; -+ ppe_dev->clk_rate = PPE_CLK_RATE; -+ ppe_dev->num_ports = PPE_PORT_MAX; -+ ppe_dev->num_icc_paths = num_icc; -+ -+ ret = ppe_clock_init_and_reset(ppe_dev); -+ if (ret) -+ return dev_err_probe(dev, ret, "PPE clock config failed\n"); -+ -+ platform_set_drvdata(pdev, ppe_dev); -+ -+ return 0; -+} -+ -+static const struct of_device_id qcom_ppe_of_match[] = { -+ { .compatible = "qcom,ipq9574-ppe" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, qcom_ppe_of_match); -+ -+static struct platform_driver qcom_ppe_driver = { -+ .driver = { -+ .name = "qcom_ppe", -+ .of_match_table = qcom_ppe_of_match, -+ }, -+ .probe = qcom_ppe_probe, -+}; -+module_platform_driver(qcom_ppe_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ PPE driver"); ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h -@@ -0,0 +1,36 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __PPE_H__ -+#define __PPE_H__ -+ -+#include -+#include -+ -+struct device; -+struct regmap; -+ -+/** -+ * struct ppe_device - PPE device private data. -+ * @dev: PPE device structure. -+ * @regmap: PPE register map. -+ * @clk_rate: PPE clock rate. -+ * @num_ports: Number of PPE ports. -+ * @num_icc_paths: Number of interconnect paths. -+ * @icc_paths: Interconnect path array. -+ * -+ * PPE device is the instance of PPE hardware, which is used to -+ * configure PPE packet process modules such as BM (buffer management), -+ * QM (queue management), and scheduler. -+ */ -+struct ppe_device { -+ struct device *dev; -+ struct regmap *regmap; -+ unsigned long clk_rate; -+ unsigned int num_ports; -+ unsigned int num_icc_paths; -+ struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths); -+}; -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0326-net-ethernet-qualcomm-Initialize-PPE-buffer-manageme.patch b/target/linux/qualcommbe/patches-6.12/0326-net-ethernet-qualcomm-Initialize-PPE-buffer-manageme.patch deleted file mode 100644 index 5f38e25b37..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0326-net-ethernet-qualcomm-Initialize-PPE-buffer-manageme.patch +++ /dev/null @@ -1,328 +0,0 @@ -From 6e639ab45348ee7a697db8b481fa6f8555280f58 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:38 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE buffer management for - IPQ9574 - -The BM (Buffer Management) config controls the pause frame generated -on the PPE port. There are maximum 15 BM ports and 4 groups supported, -all BM ports are assigned to group 0 by default. The number of hardware -buffers configured for the port influence the threshold of the flow -control for that port. - -Signed-off-by: Luo Jie ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/ppe.c | 5 + - .../net/ethernet/qualcomm/ppe/ppe_config.c | 195 ++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/ppe_config.h | 12 ++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 59 ++++++ - 5 files changed, 272 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_config.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_config.h - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_regs.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -4,4 +4,4 @@ - # - - obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o --qcom-ppe-objs := ppe.o -+qcom-ppe-objs := ppe.o ppe_config.o ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c -@@ -15,6 +15,7 @@ - #include - - #include "ppe.h" -+#include "ppe_config.h" - - #define PPE_PORT_MAX 8 - #define PPE_CLK_RATE 353000000 -@@ -194,6 +195,10 @@ static int qcom_ppe_probe(struct platfor - if (ret) - return dev_err_probe(dev, ret, "PPE clock config failed\n"); - -+ ret = ppe_hw_config(ppe_dev); -+ if (ret) -+ return dev_err_probe(dev, ret, "PPE HW config failed\n"); -+ - platform_set_drvdata(pdev, ppe_dev); - - return 0; ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -0,0 +1,195 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE HW initialization configs such as BM(buffer management), -+ * QM(queue management) and scheduler configs. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include "ppe.h" -+#include "ppe_config.h" -+#include "ppe_regs.h" -+ -+/** -+ * struct ppe_bm_port_config - PPE BM port configuration. -+ * @port_id_start: The fist BM port ID to configure. -+ * @port_id_end: The last BM port ID to configure. -+ * @pre_alloc: BM port dedicated buffer number. -+ * @in_fly_buf: Buffer number for receiving the packet after pause frame sent. -+ * @ceil: Ceil to generate the back pressure. -+ * @weight: Weight value. -+ * @resume_offset: Resume offset from the threshold value. -+ * @resume_ceil: Ceil to resume from the back pressure state. -+ * @dynamic: Dynamic threshold used or not. -+ * -+ * The is for configuring the threshold that impacts the port -+ * flow control. -+ */ -+struct ppe_bm_port_config { -+ unsigned int port_id_start; -+ unsigned int port_id_end; -+ unsigned int pre_alloc; -+ unsigned int in_fly_buf; -+ unsigned int ceil; -+ unsigned int weight; -+ unsigned int resume_offset; -+ unsigned int resume_ceil; -+ bool dynamic; -+}; -+ -+/* Assign the share buffer number 1550 to group 0 by default. */ -+static const int ipq9574_ppe_bm_group_config = 1550; -+ -+/* The buffer configurations per PPE port. There are 15 BM ports and -+ * 4 BM groups supported by PPE. BM port (0-7) is for EDMA port 0, -+ * BM port (8-13) is for PPE physical port 1-6 and BM port 14 is for -+ * EIP port. -+ */ -+static const struct ppe_bm_port_config ipq9574_ppe_bm_port_config[] = { -+ { -+ /* Buffer configuration for the BM port ID 0 of EDMA. */ -+ .port_id_start = 0, -+ .port_id_end = 0, -+ .pre_alloc = 0, -+ .in_fly_buf = 100, -+ .ceil = 1146, -+ .weight = 7, -+ .resume_offset = 8, -+ .resume_ceil = 0, -+ .dynamic = true, -+ }, -+ { -+ /* Buffer configuration for the BM port ID 1-7 of EDMA. */ -+ .port_id_start = 1, -+ .port_id_end = 7, -+ .pre_alloc = 0, -+ .in_fly_buf = 100, -+ .ceil = 250, -+ .weight = 4, -+ .resume_offset = 36, -+ .resume_ceil = 0, -+ .dynamic = true, -+ }, -+ { -+ /* Buffer configuration for the BM port ID 8-13 of PPE ports. */ -+ .port_id_start = 8, -+ .port_id_end = 13, -+ .pre_alloc = 0, -+ .in_fly_buf = 128, -+ .ceil = 250, -+ .weight = 4, -+ .resume_offset = 36, -+ .resume_ceil = 0, -+ .dynamic = true, -+ }, -+ { -+ /* Buffer configuration for the BM port ID 14 of EIP. */ -+ .port_id_start = 14, -+ .port_id_end = 14, -+ .pre_alloc = 0, -+ .in_fly_buf = 40, -+ .ceil = 250, -+ .weight = 4, -+ .resume_offset = 36, -+ .resume_ceil = 0, -+ .dynamic = true, -+ }, -+}; -+ -+static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, -+ const struct ppe_bm_port_config port_cfg) -+{ -+ u32 reg, val, bm_fc_val[2]; -+ int ret; -+ -+ reg = PPE_BM_PORT_FC_CFG_TBL_ADDR + PPE_BM_PORT_FC_CFG_TBL_INC * bm_port_id; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ bm_fc_val, ARRAY_SIZE(bm_fc_val)); -+ if (ret) -+ return ret; -+ -+ /* Configure BM flow control related threshold. */ -+ PPE_BM_PORT_FC_SET_WEIGHT(bm_fc_val, port_cfg.weight); -+ PPE_BM_PORT_FC_SET_RESUME_OFFSET(bm_fc_val, port_cfg.resume_offset); -+ PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(bm_fc_val, port_cfg.resume_ceil); -+ PPE_BM_PORT_FC_SET_DYNAMIC(bm_fc_val, port_cfg.dynamic); -+ PPE_BM_PORT_FC_SET_REACT_LIMIT(bm_fc_val, port_cfg.in_fly_buf); -+ PPE_BM_PORT_FC_SET_PRE_ALLOC(bm_fc_val, port_cfg.pre_alloc); -+ -+ /* Configure low/high bits of the ceiling for the BM port. */ -+ val = FIELD_GET(GENMASK(2, 0), port_cfg.ceil); -+ PPE_BM_PORT_FC_SET_CEILING_LOW(bm_fc_val, val); -+ val = FIELD_GET(GENMASK(10, 3), port_cfg.ceil); -+ PPE_BM_PORT_FC_SET_CEILING_HIGH(bm_fc_val, val); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ bm_fc_val, ARRAY_SIZE(bm_fc_val)); -+ if (ret) -+ return ret; -+ -+ /* Assign the default group ID 0 to the BM port. */ -+ val = FIELD_PREP(PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, 0); -+ reg = PPE_BM_PORT_GROUP_ID_ADDR + PPE_BM_PORT_GROUP_ID_INC * bm_port_id; -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID, -+ val); -+ if (ret) -+ return ret; -+ -+ /* Enable BM port flow control. */ -+ reg = PPE_BM_PORT_FC_MODE_ADDR + PPE_BM_PORT_FC_MODE_INC * bm_port_id; -+ -+ return regmap_set_bits(ppe_dev->regmap, reg, PPE_BM_PORT_FC_MODE_EN); -+} -+ -+/* Configure the buffer threshold for the port flow control function. */ -+static int ppe_config_bm(struct ppe_device *ppe_dev) -+{ -+ const struct ppe_bm_port_config *port_cfg; -+ unsigned int i, bm_port_id, port_cfg_cnt; -+ u32 reg, val; -+ int ret; -+ -+ /* Configure the allocated buffer number only for group 0. -+ * The buffer number of group 1-3 is already cleared to 0 -+ * after PPE reset during the probe of PPE driver. -+ */ -+ reg = PPE_BM_SHARED_GROUP_CFG_ADDR; -+ val = FIELD_PREP(PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, -+ ipq9574_ppe_bm_group_config); -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT, -+ val); -+ if (ret) -+ goto bm_config_fail; -+ -+ /* Configure buffer thresholds for the BM ports. */ -+ port_cfg = ipq9574_ppe_bm_port_config; -+ port_cfg_cnt = ARRAY_SIZE(ipq9574_ppe_bm_port_config); -+ for (i = 0; i < port_cfg_cnt; i++) { -+ for (bm_port_id = port_cfg[i].port_id_start; -+ bm_port_id <= port_cfg[i].port_id_end; bm_port_id++) { -+ ret = ppe_config_bm_threshold(ppe_dev, bm_port_id, -+ port_cfg[i]); -+ if (ret) -+ goto bm_config_fail; -+ } -+ } -+ -+ return 0; -+ -+bm_config_fail: -+ dev_err(ppe_dev->dev, "PPE BM config error %d\n", ret); -+ return ret; -+} -+ -+int ppe_hw_config(struct ppe_device *ppe_dev) -+{ -+ return ppe_config_bm(ppe_dev); -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __PPE_CONFIG_H__ -+#define __PPE_CONFIG_H__ -+ -+#include "ppe.h" -+ -+int ppe_hw_config(struct ppe_device *ppe_dev); -+#endif ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -0,0 +1,59 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE hardware register and table declarations. */ -+#ifndef __PPE_REGS_H__ -+#define __PPE_REGS_H__ -+ -+#include -+ -+/* There are 15 BM ports and 4 BM groups supported by PPE. -+ * BM port (0-7) is for EDMA port 0, BM port (8-13) is for -+ * PPE physical port 1-6 and BM port 14 is for EIP port. -+ */ -+#define PPE_BM_PORT_FC_MODE_ADDR 0x600100 -+#define PPE_BM_PORT_FC_MODE_ENTRIES 15 -+#define PPE_BM_PORT_FC_MODE_INC 0x4 -+#define PPE_BM_PORT_FC_MODE_EN BIT(0) -+ -+#define PPE_BM_PORT_GROUP_ID_ADDR 0x600180 -+#define PPE_BM_PORT_GROUP_ID_ENTRIES 15 -+#define PPE_BM_PORT_GROUP_ID_INC 0x4 -+#define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID GENMASK(1, 0) -+ -+#define PPE_BM_SHARED_GROUP_CFG_ADDR 0x600290 -+#define PPE_BM_SHARED_GROUP_CFG_ENTRIES 4 -+#define PPE_BM_SHARED_GROUP_CFG_INC 0x4 -+#define PPE_BM_SHARED_GROUP_CFG_SHARED_LIMIT GENMASK(10, 0) -+ -+#define PPE_BM_PORT_FC_CFG_TBL_ADDR 0x601000 -+#define PPE_BM_PORT_FC_CFG_TBL_ENTRIES 15 -+#define PPE_BM_PORT_FC_CFG_TBL_INC 0x10 -+#define PPE_BM_PORT_FC_W0_REACT_LIMIT GENMASK(8, 0) -+#define PPE_BM_PORT_FC_W0_RESUME_THRESHOLD GENMASK(17, 9) -+#define PPE_BM_PORT_FC_W0_RESUME_OFFSET GENMASK(28, 18) -+#define PPE_BM_PORT_FC_W0_CEILING_LOW GENMASK(31, 29) -+#define PPE_BM_PORT_FC_W1_CEILING_HIGH GENMASK(7, 0) -+#define PPE_BM_PORT_FC_W1_WEIGHT GENMASK(10, 8) -+#define PPE_BM_PORT_FC_W1_DYNAMIC BIT(11) -+#define PPE_BM_PORT_FC_W1_PRE_ALLOC GENMASK(22, 12) -+ -+#define PPE_BM_PORT_FC_SET_REACT_LIMIT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_REACT_LIMIT) -+#define PPE_BM_PORT_FC_SET_RESUME_THRESHOLD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_RESUME_THRESHOLD) -+#define PPE_BM_PORT_FC_SET_RESUME_OFFSET(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_RESUME_OFFSET) -+#define PPE_BM_PORT_FC_SET_CEILING_LOW(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_BM_PORT_FC_W0_CEILING_LOW) -+#define PPE_BM_PORT_FC_SET_CEILING_HIGH(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_CEILING_HIGH) -+#define PPE_BM_PORT_FC_SET_WEIGHT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_WEIGHT) -+#define PPE_BM_PORT_FC_SET_DYNAMIC(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_DYNAMIC) -+#define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC) -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0327-net-ethernet-qualcomm-Initialize-PPE-queue-managemen.patch b/target/linux/qualcommbe/patches-6.12/0327-net-ethernet-qualcomm-Initialize-PPE-queue-managemen.patch deleted file mode 100644 index be16222b96..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0327-net-ethernet-qualcomm-Initialize-PPE-queue-managemen.patch +++ /dev/null @@ -1,320 +0,0 @@ -From 9be6c3590ef3c241e6a3cfd05291304a1f973bcf Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:39 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE queue management for - IPQ9574 - -QM (queue management) configurations decide the length of PPE -queues and the queue depth for these queues which are used to -drop packets in events of congestion. - -There are two types of PPE queues - unicast queues (0-255) and -multicast queues (256-299). These queue types are used to forward -different types of traffic, and are configured with different -lengths. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 177 +++++++++++++++++- - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 85 +++++++++ - 2 files changed, 261 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -43,6 +43,29 @@ struct ppe_bm_port_config { - bool dynamic; - }; - -+/** -+ * struct ppe_qm_queue_config - PPE queue config. -+ * @queue_start: PPE start of queue ID. -+ * @queue_end: PPE end of queue ID. -+ * @prealloc_buf: Queue dedicated buffer number. -+ * @ceil: Ceil to start drop packet from queue. -+ * @weight: Weight value. -+ * @resume_offset: Resume offset from the threshold. -+ * @dynamic: Threshold value is decided dynamically or statically. -+ * -+ * Queue configuration decides the threshold to drop packet from PPE -+ * hardware queue. -+ */ -+struct ppe_qm_queue_config { -+ unsigned int queue_start; -+ unsigned int queue_end; -+ unsigned int prealloc_buf; -+ unsigned int ceil; -+ unsigned int weight; -+ unsigned int resume_offset; -+ bool dynamic; -+}; -+ - /* Assign the share buffer number 1550 to group 0 by default. */ - static const int ipq9574_ppe_bm_group_config = 1550; - -@@ -102,6 +125,33 @@ static const struct ppe_bm_port_config i - }, - }; - -+/* Default QM group settings for IPQ9754. */ -+static const int ipq9574_ppe_qm_group_config = 2000; -+ -+/* Default QM settings for unicast and multicast queues for IPQ9754. */ -+static const struct ppe_qm_queue_config ipq9574_ppe_qm_queue_config[] = { -+ { -+ /* QM settings for unicast queues 0 to 255. */ -+ .queue_start = 0, -+ .queue_end = 255, -+ .prealloc_buf = 0, -+ .ceil = 1200, -+ .weight = 7, -+ .resume_offset = 36, -+ .dynamic = true, -+ }, -+ { -+ /* QM settings for multicast queues 256 to 299. */ -+ .queue_start = 256, -+ .queue_end = 299, -+ .prealloc_buf = 0, -+ .ceil = 250, -+ .weight = 0, -+ .resume_offset = 36, -+ .dynamic = false, -+ }, -+}; -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -189,7 +239,132 @@ bm_config_fail: - return ret; - } - -+/* Configure PPE hardware queue depth, which is decided by the threshold -+ * of queue. -+ */ -+static int ppe_config_qm(struct ppe_device *ppe_dev) -+{ -+ const struct ppe_qm_queue_config *queue_cfg; -+ int ret, i, queue_id, queue_cfg_count; -+ u32 reg, multicast_queue_cfg[5]; -+ u32 unicast_queue_cfg[4]; -+ u32 group_cfg[3]; -+ -+ /* Assign the buffer number to the group 0 by default. */ -+ reg = PPE_AC_GRP_CFG_TBL_ADDR; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ group_cfg, ARRAY_SIZE(group_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ -+ PPE_AC_GRP_SET_BUF_LIMIT(group_cfg, ipq9574_ppe_qm_group_config); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ group_cfg, ARRAY_SIZE(group_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ -+ queue_cfg = ipq9574_ppe_qm_queue_config; -+ queue_cfg_count = ARRAY_SIZE(ipq9574_ppe_qm_queue_config); -+ for (i = 0; i < queue_cfg_count; i++) { -+ queue_id = queue_cfg[i].queue_start; -+ -+ /* Configure threshold for dropping packets separately for -+ * unicast and multicast PPE queues. -+ */ -+ while (queue_id <= queue_cfg[i].queue_end) { -+ if (queue_id < PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES) { -+ reg = PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR + -+ PPE_AC_UNICAST_QUEUE_CFG_TBL_INC * queue_id; -+ -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ unicast_queue_cfg, -+ ARRAY_SIZE(unicast_queue_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ -+ PPE_AC_UNICAST_QUEUE_SET_EN(unicast_queue_cfg, true); -+ PPE_AC_UNICAST_QUEUE_SET_GRP_ID(unicast_queue_cfg, 0); -+ PPE_AC_UNICAST_QUEUE_SET_PRE_LIMIT(unicast_queue_cfg, -+ queue_cfg[i].prealloc_buf); -+ PPE_AC_UNICAST_QUEUE_SET_DYNAMIC(unicast_queue_cfg, -+ queue_cfg[i].dynamic); -+ PPE_AC_UNICAST_QUEUE_SET_WEIGHT(unicast_queue_cfg, -+ queue_cfg[i].weight); -+ PPE_AC_UNICAST_QUEUE_SET_THRESHOLD(unicast_queue_cfg, -+ queue_cfg[i].ceil); -+ PPE_AC_UNICAST_QUEUE_SET_GRN_RESUME(unicast_queue_cfg, -+ queue_cfg[i].resume_offset); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ unicast_queue_cfg, -+ ARRAY_SIZE(unicast_queue_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ } else { -+ reg = PPE_AC_MULTICAST_QUEUE_CFG_TBL_ADDR + -+ PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC * queue_id; -+ -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ multicast_queue_cfg, -+ ARRAY_SIZE(multicast_queue_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ -+ PPE_AC_MULTICAST_QUEUE_SET_EN(multicast_queue_cfg, true); -+ PPE_AC_MULTICAST_QUEUE_SET_GRN_GRP_ID(multicast_queue_cfg, 0); -+ PPE_AC_MULTICAST_QUEUE_SET_GRN_PRE_LIMIT(multicast_queue_cfg, -+ queue_cfg[i].prealloc_buf); -+ PPE_AC_MULTICAST_QUEUE_SET_GRN_THRESHOLD(multicast_queue_cfg, -+ queue_cfg[i].ceil); -+ PPE_AC_MULTICAST_QUEUE_SET_GRN_RESUME(multicast_queue_cfg, -+ queue_cfg[i].resume_offset); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ multicast_queue_cfg, -+ ARRAY_SIZE(multicast_queue_cfg)); -+ if (ret) -+ goto qm_config_fail; -+ } -+ -+ /* Enable enqueue. */ -+ reg = PPE_ENQ_OPR_TBL_ADDR + PPE_ENQ_OPR_TBL_INC * queue_id; -+ ret = regmap_clear_bits(ppe_dev->regmap, reg, -+ PPE_ENQ_OPR_TBL_ENQ_DISABLE); -+ if (ret) -+ goto qm_config_fail; -+ -+ /* Enable dequeue. */ -+ reg = PPE_DEQ_OPR_TBL_ADDR + PPE_DEQ_OPR_TBL_INC * queue_id; -+ ret = regmap_clear_bits(ppe_dev->regmap, reg, -+ PPE_DEQ_OPR_TBL_DEQ_DISABLE); -+ if (ret) -+ goto qm_config_fail; -+ -+ queue_id++; -+ } -+ } -+ -+ /* Enable queue counter for all PPE hardware queues. */ -+ ret = regmap_set_bits(ppe_dev->regmap, PPE_EG_BRIDGE_CONFIG_ADDR, -+ PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN); -+ if (ret) -+ goto qm_config_fail; -+ -+ return 0; -+ -+qm_config_fail: -+ dev_err(ppe_dev->dev, "PPE QM config error %d\n", ret); -+ return ret; -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { -- return ppe_config_bm(ppe_dev); -+ int ret; -+ -+ ret = ppe_config_bm(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_config_qm(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -9,6 +9,16 @@ - - #include - -+/* PPE queue counters enable/disable control. */ -+#define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044 -+#define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2) -+ -+/* Table addresses for per-queue dequeue setting. */ -+#define PPE_DEQ_OPR_TBL_ADDR 0x430000 -+#define PPE_DEQ_OPR_TBL_ENTRIES 300 -+#define PPE_DEQ_OPR_TBL_INC 0x10 -+#define PPE_DEQ_OPR_TBL_DEQ_DISABLE BIT(0) -+ - /* There are 15 BM ports and 4 BM groups supported by PPE. - * BM port (0-7) is for EDMA port 0, BM port (8-13) is for - * PPE physical port 1-6 and BM port 14 is for EIP port. -@@ -56,4 +66,79 @@ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_DYNAMIC) - #define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC) -+ -+/* PPE unicast queue (0-255) configurations. */ -+#define PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR 0x848000 -+#define PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES 256 -+#define PPE_AC_UNICAST_QUEUE_CFG_TBL_INC 0x10 -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_EN BIT(0) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_WRED_EN BIT(1) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_FC_EN BIT(2) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_CLR_AWARE BIT(3) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_GRP_ID GENMASK(5, 4) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_PRE_LIMIT GENMASK(16, 6) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_DYNAMIC BIT(17) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_WEIGHT GENMASK(20, 18) -+#define PPE_AC_UNICAST_QUEUE_CFG_W0_THRESHOLD GENMASK(31, 21) -+#define PPE_AC_UNICAST_QUEUE_CFG_W3_GRN_RESUME GENMASK(23, 13) -+ -+#define PPE_AC_UNICAST_QUEUE_SET_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_EN) -+#define PPE_AC_UNICAST_QUEUE_SET_GRP_ID(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_GRP_ID) -+#define PPE_AC_UNICAST_QUEUE_SET_PRE_LIMIT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_PRE_LIMIT) -+#define PPE_AC_UNICAST_QUEUE_SET_DYNAMIC(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_DYNAMIC) -+#define PPE_AC_UNICAST_QUEUE_SET_WEIGHT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_WEIGHT) -+#define PPE_AC_UNICAST_QUEUE_SET_THRESHOLD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_UNICAST_QUEUE_CFG_W0_THRESHOLD) -+#define PPE_AC_UNICAST_QUEUE_SET_GRN_RESUME(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x3, value, PPE_AC_UNICAST_QUEUE_CFG_W3_GRN_RESUME) -+ -+/* PPE multicast queue (256-299) configurations. */ -+#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_ADDR 0x84a000 -+#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_ENTRIES 44 -+#define PPE_AC_MULTICAST_QUEUE_CFG_TBL_INC 0x10 -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_EN BIT(0) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_FC_EN BIT(1) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_CLR_AWARE BIT(2) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_GRP_ID GENMASK(4, 3) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_PRE_LIMIT GENMASK(15, 5) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W0_THRESHOLD GENMASK(26, 16) -+#define PPE_AC_MULTICAST_QUEUE_CFG_W2_RESUME GENMASK(17, 7) -+ -+#define PPE_AC_MULTICAST_QUEUE_SET_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_EN) -+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_GRP_ID(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_GRP_ID) -+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_PRE_LIMIT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_PRE_LIMIT) -+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_THRESHOLD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_AC_MULTICAST_QUEUE_CFG_W0_THRESHOLD) -+#define PPE_AC_MULTICAST_QUEUE_SET_GRN_RESUME(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x2, value, PPE_AC_MULTICAST_QUEUE_CFG_W2_RESUME) -+ -+/* PPE admission control group (0-3) configurations */ -+#define PPE_AC_GRP_CFG_TBL_ADDR 0x84c000 -+#define PPE_AC_GRP_CFG_TBL_ENTRIES 0x4 -+#define PPE_AC_GRP_CFG_TBL_INC 0x10 -+#define PPE_AC_GRP_W0_AC_EN BIT(0) -+#define PPE_AC_GRP_W0_AC_FC_EN BIT(1) -+#define PPE_AC_GRP_W0_CLR_AWARE BIT(2) -+#define PPE_AC_GRP_W0_THRESHOLD_LOW GENMASK(31, 25) -+#define PPE_AC_GRP_W1_THRESHOLD_HIGH GENMASK(3, 0) -+#define PPE_AC_GRP_W1_BUF_LIMIT GENMASK(14, 4) -+#define PPE_AC_GRP_W2_RESUME_GRN GENMASK(15, 5) -+#define PPE_AC_GRP_W2_PRE_ALLOC GENMASK(26, 16) -+ -+#define PPE_AC_GRP_SET_BUF_LIMIT(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_AC_GRP_W1_BUF_LIMIT) -+ -+/* Table addresses for per-queue enqueue setting. */ -+#define PPE_ENQ_OPR_TBL_ADDR 0x85c000 -+#define PPE_ENQ_OPR_TBL_ENTRIES 300 -+#define PPE_ENQ_OPR_TBL_INC 0x10 -+#define PPE_ENQ_OPR_TBL_ENQ_DISABLE BIT(0) - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0328-net-ethernet-qualcomm-Initialize-the-PPE-scheduler-s.patch b/target/linux/qualcommbe/patches-6.12/0328-net-ethernet-qualcomm-Initialize-the-PPE-scheduler-s.patch deleted file mode 100644 index 86949a2f3b..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0328-net-ethernet-qualcomm-Initialize-the-PPE-scheduler-s.patch +++ /dev/null @@ -1,1000 +0,0 @@ -From 333edaf474cd707b0a04c57f255b56bc3c015789 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:40 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize the PPE scheduler - settings - -The PPE scheduler settings determine the priority of scheduling the -packet across the different hardware queues per PPE port. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 788 +++++++++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 37 + - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 97 +++ - 3 files changed, 921 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -16,6 +16,8 @@ - #include "ppe_config.h" - #include "ppe_regs.h" - -+#define PPE_QUEUE_SCH_PRI_NUM 8 -+ - /** - * struct ppe_bm_port_config - PPE BM port configuration. - * @port_id_start: The fist BM port ID to configure. -@@ -66,6 +68,66 @@ struct ppe_qm_queue_config { - bool dynamic; - }; - -+/** -+ * struct ppe_scheduler_bm_config - PPE arbitration for buffer config. -+ * @valid: Arbitration entry valid or not. -+ * @is_egress: Arbitration entry for egress or not. -+ * @port: Port ID to use arbitration entry. -+ * @second_valid: Second port valid or not. -+ * @second_port: Second port to use. -+ * -+ * Configure the scheduler settings for accessing and releasing the PPE buffers. -+ */ -+struct ppe_scheduler_bm_config { -+ bool valid; -+ bool is_egress; -+ unsigned int port; -+ bool second_valid; -+ unsigned int second_port; -+}; -+ -+/** -+ * struct ppe_scheduler_qm_config - PPE arbitration for scheduler config. -+ * @ensch_port_bmp: Port bit map for enqueue scheduler. -+ * @ensch_port: Port ID to enqueue scheduler. -+ * @desch_port: Port ID to dequeue scheduler. -+ * @desch_second_valid: Dequeue for the second port valid or not. -+ * @desch_second_port: Second port ID to dequeue scheduler. -+ * -+ * Configure the scheduler settings for enqueuing and dequeuing packets on -+ * the PPE port. -+ */ -+struct ppe_scheduler_qm_config { -+ unsigned int ensch_port_bmp; -+ unsigned int ensch_port; -+ unsigned int desch_port; -+ bool desch_second_valid; -+ unsigned int desch_second_port; -+}; -+ -+/** -+ * struct ppe_scheduler_port_config - PPE port scheduler config. -+ * @port: Port ID to be scheduled. -+ * @flow_level: Scheduler flow level or not. -+ * @node_id: Node ID, for level 0, queue ID is used. -+ * @loop_num: Loop number of scheduler config. -+ * @pri_max: Max priority configured. -+ * @flow_id: Strict priority ID. -+ * @drr_node_id: Node ID for scheduler. -+ * -+ * PPE port scheduler configuration which decides the priority in the -+ * packet scheduler for the egress port. -+ */ -+struct ppe_scheduler_port_config { -+ unsigned int port; -+ bool flow_level; -+ unsigned int node_id; -+ unsigned int loop_num; -+ unsigned int pri_max; -+ unsigned int flow_id; -+ unsigned int drr_node_id; -+}; -+ - /* Assign the share buffer number 1550 to group 0 by default. */ - static const int ipq9574_ppe_bm_group_config = 1550; - -@@ -152,6 +214,599 @@ static const struct ppe_qm_queue_config - }, - }; - -+/* Scheduler configuration for the assigning and releasing buffers for the -+ * packet passing through PPE, which is different per SoC. -+ */ -+static const struct ppe_scheduler_bm_config ipq9574_ppe_sch_bm_config[] = { -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 7, 0, 0}, -+ {1, 1, 7, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 2, 0, 0}, -+ {1, 1, 2, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 3, 0, 0}, -+ {1, 1, 3, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 7, 0, 0}, -+ {1, 1, 7, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 4, 0, 0}, -+ {1, 1, 4, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 2, 0, 0}, -+ {1, 1, 2, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 7, 0, 0}, -+ {1, 1, 7, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 3, 0, 0}, -+ {1, 1, 3, 0, 0}, -+ {1, 0, 1, 0, 0}, -+ {1, 1, 1, 0, 0}, -+ {1, 0, 0, 0, 0}, -+ {1, 1, 0, 0, 0}, -+ {1, 0, 5, 0, 0}, -+ {1, 1, 5, 0, 0}, -+ {1, 0, 6, 0, 0}, -+ {1, 1, 6, 0, 0}, -+ {1, 0, 4, 0, 0}, -+ {1, 1, 4, 0, 0}, -+ {1, 0, 7, 0, 0}, -+ {1, 1, 7, 0, 0}, -+}; -+ -+/* Scheduler configuration for dispatching packet on PPE queues, which -+ * is different per SoC. -+ */ -+static const struct ppe_scheduler_qm_config ipq9574_ppe_sch_qm_config[] = { -+ {0x98, 6, 0, 1, 1}, -+ {0x94, 5, 6, 1, 3}, -+ {0x86, 0, 5, 1, 4}, -+ {0x8C, 1, 6, 1, 0}, -+ {0x1C, 7, 5, 1, 1}, -+ {0x98, 2, 6, 1, 0}, -+ {0x1C, 5, 7, 1, 1}, -+ {0x34, 3, 6, 1, 0}, -+ {0x8C, 4, 5, 1, 1}, -+ {0x98, 2, 6, 1, 0}, -+ {0x8C, 5, 4, 1, 1}, -+ {0xA8, 0, 6, 1, 2}, -+ {0x98, 5, 1, 1, 0}, -+ {0x98, 6, 5, 1, 2}, -+ {0x89, 1, 6, 1, 4}, -+ {0xA4, 3, 0, 1, 1}, -+ {0x8C, 5, 6, 1, 4}, -+ {0xA8, 0, 2, 1, 1}, -+ {0x98, 6, 5, 1, 0}, -+ {0xC4, 4, 3, 1, 1}, -+ {0x94, 6, 5, 1, 0}, -+ {0x1C, 7, 6, 1, 1}, -+ {0x98, 2, 5, 1, 0}, -+ {0x1C, 6, 7, 1, 1}, -+ {0x1C, 5, 6, 1, 0}, -+ {0x94, 3, 5, 1, 1}, -+ {0x8C, 4, 6, 1, 0}, -+ {0x94, 1, 5, 1, 3}, -+ {0x94, 6, 1, 1, 0}, -+ {0xD0, 3, 5, 1, 2}, -+ {0x98, 6, 0, 1, 1}, -+ {0x94, 5, 6, 1, 3}, -+ {0x94, 1, 5, 1, 0}, -+ {0x98, 2, 6, 1, 1}, -+ {0x8C, 4, 5, 1, 0}, -+ {0x1C, 7, 6, 1, 1}, -+ {0x8C, 0, 5, 1, 4}, -+ {0x89, 1, 6, 1, 2}, -+ {0x98, 5, 0, 1, 1}, -+ {0x94, 6, 5, 1, 3}, -+ {0x92, 0, 6, 1, 2}, -+ {0x98, 1, 5, 1, 0}, -+ {0x98, 6, 2, 1, 1}, -+ {0xD0, 0, 5, 1, 3}, -+ {0x94, 6, 0, 1, 1}, -+ {0x8C, 5, 6, 1, 4}, -+ {0x8C, 1, 5, 1, 0}, -+ {0x1C, 6, 7, 1, 1}, -+ {0x1C, 5, 6, 1, 0}, -+ {0xB0, 2, 3, 1, 1}, -+ {0xC4, 4, 5, 1, 0}, -+ {0x8C, 6, 4, 1, 1}, -+ {0xA4, 3, 6, 1, 0}, -+ {0x1C, 5, 7, 1, 1}, -+ {0x4C, 0, 5, 1, 4}, -+ {0x8C, 6, 0, 1, 1}, -+ {0x34, 7, 6, 1, 3}, -+ {0x94, 5, 0, 1, 1}, -+ {0x98, 6, 5, 1, 2}, -+}; -+ -+static const struct ppe_scheduler_port_config ppe_port_sch_config[] = { -+ { -+ .port = 0, -+ .flow_level = true, -+ .node_id = 0, -+ .loop_num = 1, -+ .pri_max = 1, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 0, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 8, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 16, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 24, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 32, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 40, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 48, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 56, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 256, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 0, -+ .flow_level = false, -+ .node_id = 264, -+ .loop_num = 8, -+ .pri_max = 8, -+ .flow_id = 0, -+ .drr_node_id = 0, -+ }, -+ { -+ .port = 1, -+ .flow_level = true, -+ .node_id = 36, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 1, -+ .drr_node_id = 8, -+ }, -+ { -+ .port = 1, -+ .flow_level = false, -+ .node_id = 144, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 36, -+ .drr_node_id = 48, -+ }, -+ { -+ .port = 1, -+ .flow_level = false, -+ .node_id = 272, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 36, -+ .drr_node_id = 48, -+ }, -+ { -+ .port = 2, -+ .flow_level = true, -+ .node_id = 40, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 2, -+ .drr_node_id = 12, -+ }, -+ { -+ .port = 2, -+ .flow_level = false, -+ .node_id = 160, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 40, -+ .drr_node_id = 64, -+ }, -+ { -+ .port = 2, -+ .flow_level = false, -+ .node_id = 276, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 40, -+ .drr_node_id = 64, -+ }, -+ { -+ .port = 3, -+ .flow_level = true, -+ .node_id = 44, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 3, -+ .drr_node_id = 16, -+ }, -+ { -+ .port = 3, -+ .flow_level = false, -+ .node_id = 176, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 44, -+ .drr_node_id = 80, -+ }, -+ { -+ .port = 3, -+ .flow_level = false, -+ .node_id = 280, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 44, -+ .drr_node_id = 80, -+ }, -+ { -+ .port = 4, -+ .flow_level = true, -+ .node_id = 48, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 4, -+ .drr_node_id = 20, -+ }, -+ { -+ .port = 4, -+ .flow_level = false, -+ .node_id = 192, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 48, -+ .drr_node_id = 96, -+ }, -+ { -+ .port = 4, -+ .flow_level = false, -+ .node_id = 284, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 48, -+ .drr_node_id = 96, -+ }, -+ { -+ .port = 5, -+ .flow_level = true, -+ .node_id = 52, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 5, -+ .drr_node_id = 24, -+ }, -+ { -+ .port = 5, -+ .flow_level = false, -+ .node_id = 208, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 52, -+ .drr_node_id = 112, -+ }, -+ { -+ .port = 5, -+ .flow_level = false, -+ .node_id = 288, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 52, -+ .drr_node_id = 112, -+ }, -+ { -+ .port = 6, -+ .flow_level = true, -+ .node_id = 56, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 6, -+ .drr_node_id = 28, -+ }, -+ { -+ .port = 6, -+ .flow_level = false, -+ .node_id = 224, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 56, -+ .drr_node_id = 128, -+ }, -+ { -+ .port = 6, -+ .flow_level = false, -+ .node_id = 292, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 56, -+ .drr_node_id = 128, -+ }, -+ { -+ .port = 7, -+ .flow_level = true, -+ .node_id = 60, -+ .loop_num = 2, -+ .pri_max = 0, -+ .flow_id = 7, -+ .drr_node_id = 32, -+ }, -+ { -+ .port = 7, -+ .flow_level = false, -+ .node_id = 240, -+ .loop_num = 16, -+ .pri_max = 8, -+ .flow_id = 60, -+ .drr_node_id = 144, -+ }, -+ { -+ .port = 7, -+ .flow_level = false, -+ .node_id = 296, -+ .loop_num = 4, -+ .pri_max = 4, -+ .flow_id = 60, -+ .drr_node_id = 144, -+ }, -+}; -+ -+/* Set the PPE queue level scheduler configuration. */ -+static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev, -+ int node_id, int port, -+ struct ppe_scheduler_cfg scheduler_cfg) -+{ -+ u32 val, reg; -+ int ret; -+ -+ reg = PPE_L0_FLOW_MAP_TBL_ADDR + node_id * PPE_L0_FLOW_MAP_TBL_INC; -+ val = FIELD_PREP(PPE_L0_FLOW_MAP_TBL_FLOW_ID, scheduler_cfg.flow_id); -+ val |= FIELD_PREP(PPE_L0_FLOW_MAP_TBL_C_PRI, scheduler_cfg.pri); -+ val |= FIELD_PREP(PPE_L0_FLOW_MAP_TBL_E_PRI, scheduler_cfg.pri); -+ val |= FIELD_PREP(PPE_L0_FLOW_MAP_TBL_C_NODE_WT, scheduler_cfg.drr_node_wt); -+ val |= FIELD_PREP(PPE_L0_FLOW_MAP_TBL_E_NODE_WT, scheduler_cfg.drr_node_wt); -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_L0_C_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg.flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg.pri) * -+ PPE_L0_C_FLOW_CFG_TBL_INC; -+ val = FIELD_PREP(PPE_L0_C_FLOW_CFG_TBL_NODE_ID, scheduler_cfg.drr_node_id); -+ val |= FIELD_PREP(PPE_L0_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT, scheduler_cfg.unit_is_packet); -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_L0_E_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg.flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg.pri) * -+ PPE_L0_E_FLOW_CFG_TBL_INC; -+ val = FIELD_PREP(PPE_L0_E_FLOW_CFG_TBL_NODE_ID, scheduler_cfg.drr_node_id); -+ val |= FIELD_PREP(PPE_L0_E_FLOW_CFG_TBL_NODE_CREDIT_UNIT, scheduler_cfg.unit_is_packet); -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_L0_FLOW_PORT_MAP_TBL_ADDR + node_id * PPE_L0_FLOW_PORT_MAP_TBL_INC; -+ val = FIELD_PREP(PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM, port); -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_L0_COMP_CFG_TBL_ADDR + node_id * PPE_L0_COMP_CFG_TBL_INC; -+ val = FIELD_PREP(PPE_L0_COMP_CFG_TBL_NODE_METER_LEN, scheduler_cfg.frame_mode); -+ -+ return regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_L0_COMP_CFG_TBL_NODE_METER_LEN, -+ val); -+} -+ -+/* Set the PPE flow level scheduler configuration. */ -+static int ppe_scheduler_l1_queue_map_set(struct ppe_device *ppe_dev, -+ int node_id, int port, -+ struct ppe_scheduler_cfg scheduler_cfg) -+{ -+ u32 val, reg; -+ int ret; -+ -+ val = FIELD_PREP(PPE_L1_FLOW_MAP_TBL_FLOW_ID, scheduler_cfg.flow_id); -+ val |= FIELD_PREP(PPE_L1_FLOW_MAP_TBL_C_PRI, scheduler_cfg.pri); -+ val |= FIELD_PREP(PPE_L1_FLOW_MAP_TBL_E_PRI, scheduler_cfg.pri); -+ val |= FIELD_PREP(PPE_L1_FLOW_MAP_TBL_C_NODE_WT, scheduler_cfg.drr_node_wt); -+ val |= FIELD_PREP(PPE_L1_FLOW_MAP_TBL_E_NODE_WT, scheduler_cfg.drr_node_wt); -+ reg = PPE_L1_FLOW_MAP_TBL_ADDR + node_id * PPE_L1_FLOW_MAP_TBL_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(PPE_L1_C_FLOW_CFG_TBL_NODE_ID, scheduler_cfg.drr_node_id); -+ val |= FIELD_PREP(PPE_L1_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT, scheduler_cfg.unit_is_packet); -+ reg = PPE_L1_C_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg.flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg.pri) * -+ PPE_L1_C_FLOW_CFG_TBL_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(PPE_L1_E_FLOW_CFG_TBL_NODE_ID, scheduler_cfg.drr_node_id); -+ val |= FIELD_PREP(PPE_L1_E_FLOW_CFG_TBL_NODE_CREDIT_UNIT, scheduler_cfg.unit_is_packet); -+ reg = PPE_L1_E_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg.flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg.pri) * -+ PPE_L1_E_FLOW_CFG_TBL_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM, port); -+ reg = PPE_L1_FLOW_PORT_MAP_TBL_ADDR + node_id * PPE_L1_FLOW_PORT_MAP_TBL_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_L1_COMP_CFG_TBL_ADDR + node_id * PPE_L1_COMP_CFG_TBL_INC; -+ val = FIELD_PREP(PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, scheduler_cfg.frame_mode); -+ -+ return regmap_update_bits(ppe_dev->regmap, reg, PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, val); -+} -+ -+/** -+ * ppe_queue_scheduler_set - Configure scheduler for PPE hardware queue -+ * @ppe_dev: PPE device -+ * @node_id: PPE queue ID or flow ID -+ * @flow_level: Flow level scheduler or queue level scheduler -+ * @port: PPE port ID set scheduler configuration -+ * @scheduler_cfg: PPE scheduler configuration -+ * -+ * PPE scheduler configuration supports queue level and flow level on -+ * the PPE egress port. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, -+ int node_id, bool flow_level, int port, -+ struct ppe_scheduler_cfg scheduler_cfg) -+{ -+ if (flow_level) -+ return ppe_scheduler_l1_queue_map_set(ppe_dev, node_id, -+ port, scheduler_cfg); -+ -+ return ppe_scheduler_l0_queue_map_set(ppe_dev, node_id, -+ port, scheduler_cfg); -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -358,6 +1013,133 @@ qm_config_fail: - return ret; - } - -+static int ppe_node_scheduler_config(struct ppe_device *ppe_dev, -+ const struct ppe_scheduler_port_config config) -+{ -+ struct ppe_scheduler_cfg sch_cfg; -+ int ret, i; -+ -+ for (i = 0; i < config.loop_num; i++) { -+ if (!config.pri_max) { -+ /* Round robin scheduler without priority. */ -+ sch_cfg.flow_id = config.flow_id; -+ sch_cfg.pri = 0; -+ sch_cfg.drr_node_id = config.drr_node_id; -+ } else { -+ sch_cfg.flow_id = config.flow_id + (i / config.pri_max); -+ sch_cfg.pri = i % config.pri_max; -+ sch_cfg.drr_node_id = config.drr_node_id + i; -+ } -+ -+ /* Scheduler weight, must be more than 0. */ -+ sch_cfg.drr_node_wt = 1; -+ /* Byte based to be scheduled. */ -+ sch_cfg.unit_is_packet = false; -+ /* Frame + CRC calculated. */ -+ sch_cfg.frame_mode = PPE_SCH_WITH_FRAME_CRC; -+ -+ ret = ppe_queue_scheduler_set(ppe_dev, config.node_id + i, -+ config.flow_level, -+ config.port, -+ sch_cfg); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/* Initialize scheduler settings for PPE buffer utilization and dispatching -+ * packet on PPE queue. -+ */ -+static int ppe_config_scheduler(struct ppe_device *ppe_dev) -+{ -+ const struct ppe_scheduler_port_config *port_cfg; -+ const struct ppe_scheduler_qm_config *qm_cfg; -+ const struct ppe_scheduler_bm_config *bm_cfg; -+ int ret, i, count; -+ u32 val, reg; -+ -+ count = ARRAY_SIZE(ipq9574_ppe_sch_bm_config); -+ bm_cfg = ipq9574_ppe_sch_bm_config; -+ -+ /* Configure the depth of BM scheduler entries. */ -+ val = FIELD_PREP(PPE_BM_SCH_CTRL_SCH_DEPTH, count); -+ val |= FIELD_PREP(PPE_BM_SCH_CTRL_SCH_OFFSET, 0); -+ val |= FIELD_PREP(PPE_BM_SCH_CTRL_SCH_EN, 1); -+ -+ ret = regmap_write(ppe_dev->regmap, PPE_BM_SCH_CTRL_ADDR, val); -+ if (ret) -+ goto sch_config_fail; -+ -+ /* Configure each BM scheduler entry with the valid ingress port and -+ * egress port, the second port takes effect when the specified port -+ * is in the inactive state. -+ */ -+ for (i = 0; i < count; i++) { -+ val = FIELD_PREP(PPE_BM_SCH_CFG_TBL_VALID, bm_cfg[i].valid); -+ val |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_DIR, bm_cfg[i].is_egress); -+ val |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_PORT_NUM, bm_cfg[i].port); -+ val |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_SECOND_PORT_VALID, bm_cfg[i].second_valid); -+ val |= FIELD_PREP(PPE_BM_SCH_CFG_TBL_SECOND_PORT, bm_cfg[i].second_port); -+ -+ reg = PPE_BM_SCH_CFG_TBL_ADDR + i * PPE_BM_SCH_CFG_TBL_INC; -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ goto sch_config_fail; -+ } -+ -+ count = ARRAY_SIZE(ipq9574_ppe_sch_qm_config); -+ qm_cfg = ipq9574_ppe_sch_qm_config; -+ -+ /* Configure the depth of QM scheduler entries. */ -+ val = FIELD_PREP(PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH, count); -+ ret = regmap_write(ppe_dev->regmap, PPE_PSCH_SCH_DEPTH_CFG_ADDR, val); -+ if (ret) -+ goto sch_config_fail; -+ -+ /* Configure each QM scheduler entry with enqueue port and dequeue -+ * port, the second port takes effect when the specified dequeue -+ * port is in the inactive port. -+ */ -+ for (i = 0; i < count; i++) { -+ val = FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_ENS_PORT_BITMAP, -+ qm_cfg[i].ensch_port_bmp); -+ val |= FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_ENS_PORT, -+ qm_cfg[i].ensch_port); -+ val |= FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_DES_PORT, -+ qm_cfg[i].desch_port); -+ val |= FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT_EN, -+ qm_cfg[i].desch_second_valid); -+ val |= FIELD_PREP(PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT, -+ qm_cfg[i].desch_second_port); -+ -+ reg = PPE_PSCH_SCH_CFG_TBL_ADDR + i * PPE_PSCH_SCH_CFG_TBL_INC; -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ goto sch_config_fail; -+ } -+ -+ count = ARRAY_SIZE(ppe_port_sch_config); -+ port_cfg = ppe_port_sch_config; -+ -+ /* Configure scheduler per PPE queue or flow. */ -+ for (i = 0; i < count; i++) { -+ if (port_cfg[i].port >= ppe_dev->num_ports) -+ break; -+ -+ ret = ppe_node_scheduler_config(ppe_dev, port_cfg[i]); -+ if (ret) -+ goto sch_config_fail; -+ } -+ -+ return 0; -+ -+sch_config_fail: -+ dev_err(ppe_dev->dev, "PPE scheduler arbitration config error %d\n", ret); -+ return ret; -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -366,5 +1148,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_config_qm(ppe_dev); -+ ret = ppe_config_qm(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_config_scheduler(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -8,5 +8,42 @@ - - #include "ppe.h" - -+/** -+ * enum ppe_scheduler_frame_mode - PPE scheduler frame mode. -+ * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG, -+ * preamble, Ethernet packet and CRC. -+ * @PPE_SCH_WITH_FRAME_CRC: The scheduled frame includes Ethernet frame and CRC -+ * excluding IPG and preamble. -+ * @PPE_SCH_WITH_L3_PAYLOAD: The scheduled frame includes layer 3 packet data. -+ */ -+enum ppe_scheduler_frame_mode { -+ PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC = 0, -+ PPE_SCH_WITH_FRAME_CRC = 1, -+ PPE_SCH_WITH_L3_PAYLOAD = 2, -+}; -+ -+/** -+ * struct ppe_scheduler_cfg - PPE scheduler configuration. -+ * @flow_id: PPE flow ID. -+ * @pri: Scheduler priority. -+ * @drr_node_id: Node ID for scheduled traffic. -+ * @drr_node_wt: Weight for scheduled traffic. -+ * @unit_is_packet: Packet based or byte based unit for scheduled traffic. -+ * @frame_mode: Packet mode to be scheduled. -+ * -+ * PPE scheduler supports commit rate and exceed rate configurations. -+ */ -+struct ppe_scheduler_cfg { -+ int flow_id; -+ int pri; -+ int drr_node_id; -+ int drr_node_wt; -+ bool unit_is_packet; -+ enum ppe_scheduler_frame_mode frame_mode; -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev); -+int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, -+ int node_id, bool flow_level, int port, -+ struct ppe_scheduler_cfg scheduler_cfg); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -9,16 +9,113 @@ - - #include - -+/* PPE scheduler configurations for buffer manager block. */ -+#define PPE_BM_SCH_CTRL_ADDR 0xb000 -+#define PPE_BM_SCH_CTRL_INC 4 -+#define PPE_BM_SCH_CTRL_SCH_DEPTH GENMASK(7, 0) -+#define PPE_BM_SCH_CTRL_SCH_OFFSET GENMASK(14, 8) -+#define PPE_BM_SCH_CTRL_SCH_EN BIT(31) -+ -+#define PPE_BM_SCH_CFG_TBL_ADDR 0xc000 -+#define PPE_BM_SCH_CFG_TBL_ENTRIES 128 -+#define PPE_BM_SCH_CFG_TBL_INC 0x10 -+#define PPE_BM_SCH_CFG_TBL_PORT_NUM GENMASK(3, 0) -+#define PPE_BM_SCH_CFG_TBL_DIR BIT(4) -+#define PPE_BM_SCH_CFG_TBL_VALID BIT(5) -+#define PPE_BM_SCH_CFG_TBL_SECOND_PORT_VALID BIT(6) -+#define PPE_BM_SCH_CFG_TBL_SECOND_PORT GENMASK(11, 8) -+ - /* PPE queue counters enable/disable control. */ - #define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044 - #define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2) - -+/* Port scheduler global config. */ -+#define PPE_PSCH_SCH_DEPTH_CFG_ADDR 0x400000 -+#define PPE_PSCH_SCH_DEPTH_CFG_INC 4 -+#define PPE_PSCH_SCH_DEPTH_CFG_SCH_DEPTH GENMASK(7, 0) -+ -+/* PPE queue level scheduler configurations. */ -+#define PPE_L0_FLOW_MAP_TBL_ADDR 0x402000 -+#define PPE_L0_FLOW_MAP_TBL_ENTRIES 300 -+#define PPE_L0_FLOW_MAP_TBL_INC 0x10 -+#define PPE_L0_FLOW_MAP_TBL_FLOW_ID GENMASK(5, 0) -+#define PPE_L0_FLOW_MAP_TBL_C_PRI GENMASK(8, 6) -+#define PPE_L0_FLOW_MAP_TBL_E_PRI GENMASK(11, 9) -+#define PPE_L0_FLOW_MAP_TBL_C_NODE_WT GENMASK(21, 12) -+#define PPE_L0_FLOW_MAP_TBL_E_NODE_WT GENMASK(31, 22) -+ -+#define PPE_L0_C_FLOW_CFG_TBL_ADDR 0x404000 -+#define PPE_L0_C_FLOW_CFG_TBL_ENTRIES 512 -+#define PPE_L0_C_FLOW_CFG_TBL_INC 0x10 -+#define PPE_L0_C_FLOW_CFG_TBL_NODE_ID GENMASK(7, 0) -+#define PPE_L0_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(8) -+ -+#define PPE_L0_E_FLOW_CFG_TBL_ADDR 0x406000 -+#define PPE_L0_E_FLOW_CFG_TBL_ENTRIES 512 -+#define PPE_L0_E_FLOW_CFG_TBL_INC 0x10 -+#define PPE_L0_E_FLOW_CFG_TBL_NODE_ID GENMASK(7, 0) -+#define PPE_L0_E_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(8) -+ -+#define PPE_L0_FLOW_PORT_MAP_TBL_ADDR 0x408000 -+#define PPE_L0_FLOW_PORT_MAP_TBL_ENTRIES 300 -+#define PPE_L0_FLOW_PORT_MAP_TBL_INC 0x10 -+#define PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM GENMASK(3, 0) -+ -+#define PPE_L0_COMP_CFG_TBL_ADDR 0x428000 -+#define PPE_L0_COMP_CFG_TBL_ENTRIES 300 -+#define PPE_L0_COMP_CFG_TBL_INC 0x10 -+#define PPE_L0_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0) -+#define PPE_L0_COMP_CFG_TBL_NODE_METER_LEN GENMASK(3, 2) -+ - /* Table addresses for per-queue dequeue setting. */ - #define PPE_DEQ_OPR_TBL_ADDR 0x430000 - #define PPE_DEQ_OPR_TBL_ENTRIES 300 - #define PPE_DEQ_OPR_TBL_INC 0x10 - #define PPE_DEQ_OPR_TBL_DEQ_DISABLE BIT(0) - -+/* PPE flow level scheduler configurations. */ -+#define PPE_L1_FLOW_MAP_TBL_ADDR 0x440000 -+#define PPE_L1_FLOW_MAP_TBL_ENTRIES 64 -+#define PPE_L1_FLOW_MAP_TBL_INC 0x10 -+#define PPE_L1_FLOW_MAP_TBL_FLOW_ID GENMASK(3, 0) -+#define PPE_L1_FLOW_MAP_TBL_C_PRI GENMASK(6, 4) -+#define PPE_L1_FLOW_MAP_TBL_E_PRI GENMASK(9, 7) -+#define PPE_L1_FLOW_MAP_TBL_C_NODE_WT GENMASK(19, 10) -+#define PPE_L1_FLOW_MAP_TBL_E_NODE_WT GENMASK(29, 20) -+ -+#define PPE_L1_C_FLOW_CFG_TBL_ADDR 0x442000 -+#define PPE_L1_C_FLOW_CFG_TBL_ENTRIES 64 -+#define PPE_L1_C_FLOW_CFG_TBL_INC 0x10 -+#define PPE_L1_C_FLOW_CFG_TBL_NODE_ID GENMASK(5, 0) -+#define PPE_L1_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(6) -+ -+#define PPE_L1_E_FLOW_CFG_TBL_ADDR 0x444000 -+#define PPE_L1_E_FLOW_CFG_TBL_ENTRIES 64 -+#define PPE_L1_E_FLOW_CFG_TBL_INC 0x10 -+#define PPE_L1_E_FLOW_CFG_TBL_NODE_ID GENMASK(5, 0) -+#define PPE_L1_E_FLOW_CFG_TBL_NODE_CREDIT_UNIT BIT(6) -+ -+#define PPE_L1_FLOW_PORT_MAP_TBL_ADDR 0x446000 -+#define PPE_L1_FLOW_PORT_MAP_TBL_ENTRIES 64 -+#define PPE_L1_FLOW_PORT_MAP_TBL_INC 0x10 -+#define PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM GENMASK(3, 0) -+ -+#define PPE_L1_COMP_CFG_TBL_ADDR 0x46a000 -+#define PPE_L1_COMP_CFG_TBL_ENTRIES 64 -+#define PPE_L1_COMP_CFG_TBL_INC 0x10 -+#define PPE_L1_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0) -+#define PPE_L1_COMP_CFG_TBL_NODE_METER_LEN GENMASK(3, 2) -+ -+/* PPE port scheduler configurations for egress. */ -+#define PPE_PSCH_SCH_CFG_TBL_ADDR 0x47a000 -+#define PPE_PSCH_SCH_CFG_TBL_ENTRIES 128 -+#define PPE_PSCH_SCH_CFG_TBL_INC 0x10 -+#define PPE_PSCH_SCH_CFG_TBL_DES_PORT GENMASK(3, 0) -+#define PPE_PSCH_SCH_CFG_TBL_ENS_PORT GENMASK(7, 4) -+#define PPE_PSCH_SCH_CFG_TBL_ENS_PORT_BITMAP GENMASK(15, 8) -+#define PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT_EN BIT(16) -+#define PPE_PSCH_SCH_CFG_TBL_DES_SECOND_PORT GENMASK(20, 17) -+ - /* There are 15 BM ports and 4 BM groups supported by PPE. - * BM port (0-7) is for EDMA port 0, BM port (8-13) is for - * PPE physical port 1-6 and BM port 14 is for EIP port. diff --git a/target/linux/qualcommbe/patches-6.12/0329-net-ethernet-qualcomm-Initialize-PPE-queue-settings.patch b/target/linux/qualcommbe/patches-6.12/0329-net-ethernet-qualcomm-Initialize-PPE-queue-settings.patch deleted file mode 100644 index fe29d76e36..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0329-net-ethernet-qualcomm-Initialize-PPE-queue-settings.patch +++ /dev/null @@ -1,522 +0,0 @@ -From 63874f7c2e46f192e43e6214d66236372e36396c Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:41 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE queue settings - -Configure unicast and multicast hardware queues for the PPE -ports to enable packet forwarding between the ports. - -Each PPE port is assigned with a range of queues. The queue ID -selection for a packet is decided by the queue base and queue -offset that is configured based on the internal priority and -the RSS hash value of the packet. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 356 +++++++++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 63 ++++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 21 ++ - 3 files changed, 439 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -128,6 +128,34 @@ struct ppe_scheduler_port_config { - unsigned int drr_node_id; - }; - -+/** -+ * struct ppe_port_schedule_resource - PPE port scheduler resource. -+ * @ucastq_start: Unicast queue start ID. -+ * @ucastq_end: Unicast queue end ID. -+ * @mcastq_start: Multicast queue start ID. -+ * @mcastq_end: Multicast queue end ID. -+ * @flow_id_start: Flow start ID. -+ * @flow_id_end: Flow end ID. -+ * @l0node_start: Scheduler node start ID for queue level. -+ * @l0node_end: Scheduler node end ID for queue level. -+ * @l1node_start: Scheduler node start ID for flow level. -+ * @l1node_end: Scheduler node end ID for flow level. -+ * -+ * PPE scheduler resource allocated among the PPE ports. -+ */ -+struct ppe_port_schedule_resource { -+ unsigned int ucastq_start; -+ unsigned int ucastq_end; -+ unsigned int mcastq_start; -+ unsigned int mcastq_end; -+ unsigned int flow_id_start; -+ unsigned int flow_id_end; -+ unsigned int l0node_start; -+ unsigned int l0node_end; -+ unsigned int l1node_start; -+ unsigned int l1node_end; -+}; -+ - /* Assign the share buffer number 1550 to group 0 by default. */ - static const int ipq9574_ppe_bm_group_config = 1550; - -@@ -676,6 +704,111 @@ static const struct ppe_scheduler_port_c - }, - }; - -+/* The scheduler resource is applied to each PPE port, The resource -+ * includes the unicast & multicast queues, flow nodes and DRR nodes. -+ */ -+static const struct ppe_port_schedule_resource ppe_scheduler_res[] = { -+ { .ucastq_start = 0, -+ .ucastq_end = 63, -+ .mcastq_start = 256, -+ .mcastq_end = 271, -+ .flow_id_start = 0, -+ .flow_id_end = 0, -+ .l0node_start = 0, -+ .l0node_end = 7, -+ .l1node_start = 0, -+ .l1node_end = 0, -+ }, -+ { .ucastq_start = 144, -+ .ucastq_end = 159, -+ .mcastq_start = 272, -+ .mcastq_end = 275, -+ .flow_id_start = 36, -+ .flow_id_end = 39, -+ .l0node_start = 48, -+ .l0node_end = 63, -+ .l1node_start = 8, -+ .l1node_end = 11, -+ }, -+ { .ucastq_start = 160, -+ .ucastq_end = 175, -+ .mcastq_start = 276, -+ .mcastq_end = 279, -+ .flow_id_start = 40, -+ .flow_id_end = 43, -+ .l0node_start = 64, -+ .l0node_end = 79, -+ .l1node_start = 12, -+ .l1node_end = 15, -+ }, -+ { .ucastq_start = 176, -+ .ucastq_end = 191, -+ .mcastq_start = 280, -+ .mcastq_end = 283, -+ .flow_id_start = 44, -+ .flow_id_end = 47, -+ .l0node_start = 80, -+ .l0node_end = 95, -+ .l1node_start = 16, -+ .l1node_end = 19, -+ }, -+ { .ucastq_start = 192, -+ .ucastq_end = 207, -+ .mcastq_start = 284, -+ .mcastq_end = 287, -+ .flow_id_start = 48, -+ .flow_id_end = 51, -+ .l0node_start = 96, -+ .l0node_end = 111, -+ .l1node_start = 20, -+ .l1node_end = 23, -+ }, -+ { .ucastq_start = 208, -+ .ucastq_end = 223, -+ .mcastq_start = 288, -+ .mcastq_end = 291, -+ .flow_id_start = 52, -+ .flow_id_end = 55, -+ .l0node_start = 112, -+ .l0node_end = 127, -+ .l1node_start = 24, -+ .l1node_end = 27, -+ }, -+ { .ucastq_start = 224, -+ .ucastq_end = 239, -+ .mcastq_start = 292, -+ .mcastq_end = 295, -+ .flow_id_start = 56, -+ .flow_id_end = 59, -+ .l0node_start = 128, -+ .l0node_end = 143, -+ .l1node_start = 28, -+ .l1node_end = 31, -+ }, -+ { .ucastq_start = 240, -+ .ucastq_end = 255, -+ .mcastq_start = 296, -+ .mcastq_end = 299, -+ .flow_id_start = 60, -+ .flow_id_end = 63, -+ .l0node_start = 144, -+ .l0node_end = 159, -+ .l1node_start = 32, -+ .l1node_end = 35, -+ }, -+ { .ucastq_start = 64, -+ .ucastq_end = 143, -+ .mcastq_start = 0, -+ .mcastq_end = 0, -+ .flow_id_start = 1, -+ .flow_id_end = 35, -+ .l0node_start = 8, -+ .l0node_end = 47, -+ .l1node_start = 1, -+ .l1node_end = 7, -+ }, -+}; -+ - /* Set the PPE queue level scheduler configuration. */ - static int ppe_scheduler_l0_queue_map_set(struct ppe_device *ppe_dev, - int node_id, int port, -@@ -807,6 +940,149 @@ int ppe_queue_scheduler_set(struct ppe_d - port, scheduler_cfg); - } - -+/** -+ * ppe_queue_ucast_base_set - Set PPE unicast queue base ID and profile ID -+ * @ppe_dev: PPE device -+ * @queue_dst: PPE queue destination configuration -+ * @queue_base: PPE queue base ID -+ * @profile_id: Profile ID -+ * -+ * The PPE unicast queue base ID and profile ID are configured based on the -+ * destination port information that can be service code or CPU code or the -+ * destination port. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev, -+ struct ppe_queue_ucast_dest queue_dst, -+ int queue_base, int profile_id) -+{ -+ int index, profile_size; -+ u32 val, reg; -+ -+ profile_size = queue_dst.src_profile << 8; -+ if (queue_dst.service_code_en) -+ index = PPE_QUEUE_BASE_SERVICE_CODE + profile_size + -+ queue_dst.service_code; -+ else if (queue_dst.cpu_code_en) -+ index = PPE_QUEUE_BASE_CPU_CODE + profile_size + -+ queue_dst.cpu_code; -+ else -+ index = profile_size + queue_dst.dest_port; -+ -+ val = FIELD_PREP(PPE_UCAST_QUEUE_MAP_TBL_PROFILE_ID, profile_id); -+ val |= FIELD_PREP(PPE_UCAST_QUEUE_MAP_TBL_QUEUE_ID, queue_base); -+ reg = PPE_UCAST_QUEUE_MAP_TBL_ADDR + index * PPE_UCAST_QUEUE_MAP_TBL_INC; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ -+/** -+ * ppe_queue_ucast_offset_pri_set - Set PPE unicast queue offset based on priority -+ * @ppe_dev: PPE device -+ * @profile_id: Profile ID -+ * @priority: PPE internal priority to be used to set queue offset -+ * @queue_offset: Queue offset used for calculating the destination queue ID -+ * -+ * The PPE unicast queue offset is configured based on the PPE -+ * internal priority. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_queue_ucast_offset_pri_set(struct ppe_device *ppe_dev, -+ int profile_id, -+ int priority, -+ int queue_offset) -+{ -+ u32 val, reg; -+ int index; -+ -+ index = (profile_id << 4) + priority; -+ val = FIELD_PREP(PPE_UCAST_PRIORITY_MAP_TBL_CLASS, queue_offset); -+ reg = PPE_UCAST_PRIORITY_MAP_TBL_ADDR + index * PPE_UCAST_PRIORITY_MAP_TBL_INC; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ -+/** -+ * ppe_queue_ucast_offset_hash_set - Set PPE unicast queue offset based on hash -+ * @ppe_dev: PPE device -+ * @profile_id: Profile ID -+ * @rss_hash: Packet hash value to be used to set queue offset -+ * @queue_offset: Queue offset used for calculating the destination queue ID -+ * -+ * The PPE unicast queue offset is configured based on the RSS hash value. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev, -+ int profile_id, -+ int rss_hash, -+ int queue_offset) -+{ -+ u32 val, reg; -+ int index; -+ -+ index = (profile_id << 8) + rss_hash; -+ val = FIELD_PREP(PPE_UCAST_HASH_MAP_TBL_HASH, queue_offset); -+ reg = PPE_UCAST_HASH_MAP_TBL_ADDR + index * PPE_UCAST_HASH_MAP_TBL_INC; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ -+/** -+ * ppe_port_resource_get - Get PPE resource per port -+ * @ppe_dev: PPE device -+ * @port: PPE port -+ * @type: Resource type -+ * @res_start: Resource start ID returned -+ * @res_end: Resource end ID returned -+ * -+ * PPE resource is assigned per PPE port, which is acquired for QoS scheduler. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_port_resource_get(struct ppe_device *ppe_dev, int port, -+ enum ppe_resource_type type, -+ int *res_start, int *res_end) -+{ -+ struct ppe_port_schedule_resource res; -+ -+ /* The reserved resource with the maximum port ID of PPE is -+ * also allowed to be acquired. -+ */ -+ if (port > ppe_dev->num_ports) -+ return -EINVAL; -+ -+ res = ppe_scheduler_res[port]; -+ switch (type) { -+ case PPE_RES_UCAST: -+ *res_start = res.ucastq_start; -+ *res_end = res.ucastq_end; -+ break; -+ case PPE_RES_MCAST: -+ *res_start = res.mcastq_start; -+ *res_end = res.mcastq_end; -+ break; -+ case PPE_RES_FLOW_ID: -+ *res_start = res.flow_id_start; -+ *res_end = res.flow_id_end; -+ break; -+ case PPE_RES_L0_NODE: -+ *res_start = res.l0node_start; -+ *res_end = res.l0node_end; -+ break; -+ case PPE_RES_L1_NODE: -+ *res_start = res.l1node_start; -+ *res_end = res.l1node_end; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -1140,6 +1416,80 @@ sch_config_fail: - return ret; - }; - -+/* Configure PPE queue destination of each PPE port. */ -+static int ppe_queue_dest_init(struct ppe_device *ppe_dev) -+{ -+ int ret, port_id, index, q_base, q_offset, res_start, res_end, pri_max; -+ struct ppe_queue_ucast_dest queue_dst; -+ -+ for (port_id = 0; port_id < ppe_dev->num_ports; port_id++) { -+ memset(&queue_dst, 0, sizeof(queue_dst)); -+ -+ ret = ppe_port_resource_get(ppe_dev, port_id, PPE_RES_UCAST, -+ &res_start, &res_end); -+ if (ret) -+ return ret; -+ -+ q_base = res_start; -+ queue_dst.dest_port = port_id; -+ -+ /* Configure queue base ID and profile ID that is same as -+ * physical port ID. -+ */ -+ ret = ppe_queue_ucast_base_set(ppe_dev, queue_dst, -+ q_base, port_id); -+ if (ret) -+ return ret; -+ -+ /* Queue priority range supported by each PPE port */ -+ ret = ppe_port_resource_get(ppe_dev, port_id, PPE_RES_L0_NODE, -+ &res_start, &res_end); -+ if (ret) -+ return ret; -+ -+ pri_max = res_end - res_start; -+ -+ /* Redirect ARP reply packet with the max priority on CPU port, -+ * which keeps the ARP reply directed to CPU (CPU code is 101) -+ * with highest priority queue of EDMA. -+ */ -+ if (port_id == 0) { -+ memset(&queue_dst, 0, sizeof(queue_dst)); -+ -+ queue_dst.cpu_code_en = true; -+ queue_dst.cpu_code = 101; -+ ret = ppe_queue_ucast_base_set(ppe_dev, queue_dst, -+ q_base + pri_max, -+ 0); -+ if (ret) -+ return ret; -+ } -+ -+ /* Initialize the queue offset of internal priority. */ -+ for (index = 0; index < PPE_QUEUE_INTER_PRI_NUM; index++) { -+ q_offset = index > pri_max ? pri_max : index; -+ -+ ret = ppe_queue_ucast_offset_pri_set(ppe_dev, port_id, -+ index, q_offset); -+ if (ret) -+ return ret; -+ } -+ -+ /* Initialize the queue offset of RSS hash as 0 to avoid the -+ * random hardware value that will lead to the unexpected -+ * destination queue generated. -+ */ -+ for (index = 0; index < PPE_QUEUE_HASH_NUM; index++) { -+ ret = ppe_queue_ucast_offset_hash_set(ppe_dev, port_id, -+ index, 0); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1152,5 +1502,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_config_scheduler(ppe_dev); -+ ret = ppe_config_scheduler(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_queue_dest_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -8,6 +8,16 @@ - - #include "ppe.h" - -+/* There are different table index ranges for configuring queue base ID of -+ * the destination port, CPU code and service code. -+ */ -+#define PPE_QUEUE_BASE_DEST_PORT 0 -+#define PPE_QUEUE_BASE_CPU_CODE 1024 -+#define PPE_QUEUE_BASE_SERVICE_CODE 2048 -+ -+#define PPE_QUEUE_INTER_PRI_NUM 16 -+#define PPE_QUEUE_HASH_NUM 256 -+ - /** - * enum ppe_scheduler_frame_mode - PPE scheduler frame mode. - * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG, -@@ -42,8 +52,61 @@ struct ppe_scheduler_cfg { - enum ppe_scheduler_frame_mode frame_mode; - }; - -+/** -+ * enum ppe_resource_type - PPE resource type. -+ * @PPE_RES_UCAST: Unicast queue resource. -+ * @PPE_RES_MCAST: Multicast queue resource. -+ * @PPE_RES_L0_NODE: Level 0 for queue based node resource. -+ * @PPE_RES_L1_NODE: Level 1 for flow based node resource. -+ * @PPE_RES_FLOW_ID: Flow based node resource. -+ */ -+enum ppe_resource_type { -+ PPE_RES_UCAST, -+ PPE_RES_MCAST, -+ PPE_RES_L0_NODE, -+ PPE_RES_L1_NODE, -+ PPE_RES_FLOW_ID, -+}; -+ -+/** -+ * struct ppe_queue_ucast_dest - PPE unicast queue destination. -+ * @src_profile: Source profile. -+ * @service_code_en: Enable service code to map the queue base ID. -+ * @service_code: Service code. -+ * @cpu_code_en: Enable CPU code to map the queue base ID. -+ * @cpu_code: CPU code. -+ * @dest_port: destination port. -+ * -+ * PPE egress queue ID is decided by the service code if enabled, otherwise -+ * by the CPU code if enabled, or by destination port if both service code -+ * and CPU code are disabled. -+ */ -+struct ppe_queue_ucast_dest { -+ int src_profile; -+ bool service_code_en; -+ int service_code; -+ bool cpu_code_en; -+ int cpu_code; -+ int dest_port; -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev); - int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, - int node_id, bool flow_level, int port, - struct ppe_scheduler_cfg scheduler_cfg); -+int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev, -+ struct ppe_queue_ucast_dest queue_dst, -+ int queue_base, -+ int profile_id); -+int ppe_queue_ucast_offset_pri_set(struct ppe_device *ppe_dev, -+ int profile_id, -+ int priority, -+ int queue_offset); -+int ppe_queue_ucast_offset_hash_set(struct ppe_device *ppe_dev, -+ int profile_id, -+ int rss_hash, -+ int queue_offset); -+int ppe_port_resource_get(struct ppe_device *ppe_dev, int port, -+ enum ppe_resource_type type, -+ int *res_start, int *res_end); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -164,6 +164,27 @@ - #define PPE_BM_PORT_FC_SET_PRE_ALLOC(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_BM_PORT_FC_W1_PRE_ALLOC) - -+/* The queue base configurations based on destination port, -+ * service code or CPU code. -+ */ -+#define PPE_UCAST_QUEUE_MAP_TBL_ADDR 0x810000 -+#define PPE_UCAST_QUEUE_MAP_TBL_ENTRIES 3072 -+#define PPE_UCAST_QUEUE_MAP_TBL_INC 0x10 -+#define PPE_UCAST_QUEUE_MAP_TBL_PROFILE_ID GENMASK(3, 0) -+#define PPE_UCAST_QUEUE_MAP_TBL_QUEUE_ID GENMASK(11, 4) -+ -+/* The queue offset configurations based on RSS hash value. */ -+#define PPE_UCAST_HASH_MAP_TBL_ADDR 0x830000 -+#define PPE_UCAST_HASH_MAP_TBL_ENTRIES 4096 -+#define PPE_UCAST_HASH_MAP_TBL_INC 0x10 -+#define PPE_UCAST_HASH_MAP_TBL_HASH GENMASK(7, 0) -+ -+/* The queue offset configurations based on PPE internal priority. */ -+#define PPE_UCAST_PRIORITY_MAP_TBL_ADDR 0x842000 -+#define PPE_UCAST_PRIORITY_MAP_TBL_ENTRIES 256 -+#define PPE_UCAST_PRIORITY_MAP_TBL_INC 0x10 -+#define PPE_UCAST_PRIORITY_MAP_TBL_CLASS GENMASK(3, 0) -+ - /* PPE unicast queue (0-255) configurations. */ - #define PPE_AC_UNICAST_QUEUE_CFG_TBL_ADDR 0x848000 - #define PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES 256 diff --git a/target/linux/qualcommbe/patches-6.12/0330-net-ethernet-qualcomm-Initialize-PPE-service-code-se.patch b/target/linux/qualcommbe/patches-6.12/0330-net-ethernet-qualcomm-Initialize-PPE-service-code-se.patch deleted file mode 100644 index 176b7d6bb4..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0330-net-ethernet-qualcomm-Initialize-PPE-service-code-se.patch +++ /dev/null @@ -1,384 +0,0 @@ -From 4147ce0d95816bded5c5e6cb276b1aa9f2620045 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:42 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE service code settings - -PPE service code is a special code (0-255) that is defined by PPE for -PPE's packet processing stages, as per the network functions required -for the packet. - -For packet being sent out by ARM cores on Ethernet ports, The service -code 1 is used as the default service code. This service code is used -to bypass most of packet processing stages of the PPE before the packet -transmitted out PPE port, since the software network stack has already -processed the packet. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 95 +++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 145 ++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 53 +++++++ - 3 files changed, 292 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -8,6 +8,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -1083,6 +1084,75 @@ int ppe_port_resource_get(struct ppe_dev - return 0; - } - -+/** -+ * ppe_sc_config_set - Set PPE service code configuration -+ * @ppe_dev: PPE device -+ * @sc: Service ID, 0-255 supported by PPE -+ * @cfg: Service code configuration -+ * -+ * PPE service code is used by the PPE during its packet processing stages, -+ * to perform or bypass certain selected packet operations on the packet. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, struct ppe_sc_cfg cfg) -+{ -+ u32 val, reg, servcode_val[2] = {}; -+ unsigned long bitmap_value; -+ int ret; -+ -+ val = FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_PORT_ID_VALID, cfg.dest_port_valid); -+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_PORT_ID, cfg.dest_port); -+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_DIRECTION, cfg.is_src); -+ -+ bitmap_value = bitmap_read(cfg.bitmaps.egress, 0, PPE_SC_BYPASS_EGRESS_SIZE); -+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_DST_BYPASS_BITMAP, bitmap_value); -+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_RX_CNT_EN, -+ test_bit(PPE_SC_BYPASS_COUNTER_RX, cfg.bitmaps.counter)); -+ val |= FIELD_PREP(PPE_IN_L2_SERVICE_TBL_TX_CNT_EN, -+ test_bit(PPE_SC_BYPASS_COUNTER_TX, cfg.bitmaps.counter)); -+ reg = PPE_IN_L2_SERVICE_TBL_ADDR + PPE_IN_L2_SERVICE_TBL_INC * sc; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ -+ bitmap_value = bitmap_read(cfg.bitmaps.ingress, 0, PPE_SC_BYPASS_INGRESS_SIZE); -+ PPE_SERVICE_SET_BYPASS_BITMAP(servcode_val, bitmap_value); -+ PPE_SERVICE_SET_RX_CNT_EN(servcode_val, -+ test_bit(PPE_SC_BYPASS_COUNTER_RX_VLAN, cfg.bitmaps.counter)); -+ reg = PPE_SERVICE_TBL_ADDR + PPE_SERVICE_TBL_INC * sc; -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ servcode_val, ARRAY_SIZE(servcode_val)); -+ if (ret) -+ return ret; -+ -+ reg = PPE_EG_SERVICE_TBL_ADDR + PPE_EG_SERVICE_TBL_INC * sc; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ servcode_val, ARRAY_SIZE(servcode_val)); -+ if (ret) -+ return ret; -+ -+ PPE_EG_SERVICE_SET_NEXT_SERVCODE(servcode_val, cfg.next_service_code); -+ PPE_EG_SERVICE_SET_UPDATE_ACTION(servcode_val, cfg.eip_field_update_bitmap); -+ PPE_EG_SERVICE_SET_HW_SERVICE(servcode_val, cfg.eip_hw_service); -+ PPE_EG_SERVICE_SET_OFFSET_SEL(servcode_val, cfg.eip_offset_sel); -+ PPE_EG_SERVICE_SET_TX_CNT_EN(servcode_val, -+ test_bit(PPE_SC_BYPASS_COUNTER_TX_VLAN, cfg.bitmaps.counter)); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ servcode_val, ARRAY_SIZE(servcode_val)); -+ if (ret) -+ return ret; -+ -+ bitmap_value = bitmap_read(cfg.bitmaps.tunnel, 0, PPE_SC_BYPASS_TUNNEL_SIZE); -+ val = FIELD_PREP(PPE_TL_SERVICE_TBL_BYPASS_BITMAP, bitmap_value); -+ reg = PPE_TL_SERVICE_TBL_ADDR + PPE_TL_SERVICE_TBL_INC * sc; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -1490,6 +1560,25 @@ static int ppe_queue_dest_init(struct pp - return 0; - } - -+/* Initialize the service code 1 used by CPU port. */ -+static int ppe_servcode_init(struct ppe_device *ppe_dev) -+{ -+ struct ppe_sc_cfg sc_cfg = {}; -+ -+ bitmap_zero(sc_cfg.bitmaps.counter, PPE_SC_BYPASS_COUNTER_SIZE); -+ bitmap_zero(sc_cfg.bitmaps.tunnel, PPE_SC_BYPASS_TUNNEL_SIZE); -+ -+ bitmap_fill(sc_cfg.bitmaps.ingress, PPE_SC_BYPASS_INGRESS_SIZE); -+ clear_bit(PPE_SC_BYPASS_INGRESS_FAKE_MAC_HEADER, sc_cfg.bitmaps.ingress); -+ clear_bit(PPE_SC_BYPASS_INGRESS_SERVICE_CODE, sc_cfg.bitmaps.ingress); -+ clear_bit(PPE_SC_BYPASS_INGRESS_FAKE_L2_PROTO, sc_cfg.bitmaps.ingress); -+ -+ bitmap_fill(sc_cfg.bitmaps.egress, PPE_SC_BYPASS_EGRESS_SIZE); -+ clear_bit(PPE_SC_BYPASS_EGRESS_ACL_POST_ROUTING_CHECK, sc_cfg.bitmaps.egress); -+ -+ return ppe_sc_config_set(ppe_dev, PPE_EDMA_SC_BYPASS_ID, sc_cfg); -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1506,5 +1595,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_queue_dest_init(ppe_dev); -+ ret = ppe_queue_dest_init(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_servcode_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -6,6 +6,8 @@ - #ifndef __PPE_CONFIG_H__ - #define __PPE_CONFIG_H__ - -+#include -+ - #include "ppe.h" - - /* There are different table index ranges for configuring queue base ID of -@@ -18,6 +20,9 @@ - #define PPE_QUEUE_INTER_PRI_NUM 16 - #define PPE_QUEUE_HASH_NUM 256 - -+/* The service code is used by EDMA port to transmit packet to PPE. */ -+#define PPE_EDMA_SC_BYPASS_ID 1 -+ - /** - * enum ppe_scheduler_frame_mode - PPE scheduler frame mode. - * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG, -@@ -90,6 +95,144 @@ struct ppe_queue_ucast_dest { - int dest_port; - }; - -+/* Hardware bitmaps for bypassing features of the ingress packet. */ -+enum ppe_sc_ingress_type { -+ PPE_SC_BYPASS_INGRESS_VLAN_TAG_FMT_CHECK = 0, -+ PPE_SC_BYPASS_INGRESS_VLAN_MEMBER_CHECK = 1, -+ PPE_SC_BYPASS_INGRESS_VLAN_TRANSLATE = 2, -+ PPE_SC_BYPASS_INGRESS_MY_MAC_CHECK = 3, -+ PPE_SC_BYPASS_INGRESS_DIP_LOOKUP = 4, -+ PPE_SC_BYPASS_INGRESS_FLOW_LOOKUP = 5, -+ PPE_SC_BYPASS_INGRESS_FLOW_ACTION = 6, -+ PPE_SC_BYPASS_INGRESS_ACL = 7, -+ PPE_SC_BYPASS_INGRESS_FAKE_MAC_HEADER = 8, -+ PPE_SC_BYPASS_INGRESS_SERVICE_CODE = 9, -+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L2 = 10, -+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L3_IPV4 = 11, -+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L3_IPV6 = 12, -+ PPE_SC_BYPASS_INGRESS_WRONG_PKT_FMT_L4 = 13, -+ PPE_SC_BYPASS_INGRESS_FLOW_SERVICE_CODE = 14, -+ PPE_SC_BYPASS_INGRESS_ACL_SERVICE_CODE = 15, -+ PPE_SC_BYPASS_INGRESS_FAKE_L2_PROTO = 16, -+ PPE_SC_BYPASS_INGRESS_PPPOE_TERMINATION = 17, -+ PPE_SC_BYPASS_INGRESS_DEFAULT_VLAN = 18, -+ PPE_SC_BYPASS_INGRESS_DEFAULT_PCP = 19, -+ PPE_SC_BYPASS_INGRESS_VSI_ASSIGN = 20, -+ /* Values 21-23 are not specified by hardware. */ -+ PPE_SC_BYPASS_INGRESS_VLAN_ASSIGN_FAIL = 24, -+ PPE_SC_BYPASS_INGRESS_SOURCE_GUARD = 25, -+ PPE_SC_BYPASS_INGRESS_MRU_MTU_CHECK = 26, -+ PPE_SC_BYPASS_INGRESS_FLOW_SRC_CHECK = 27, -+ PPE_SC_BYPASS_INGRESS_FLOW_QOS = 28, -+ /* This must be last as it determines the size of the BITMAP. */ -+ PPE_SC_BYPASS_INGRESS_SIZE, -+}; -+ -+/* Hardware bitmaps for bypassing features of the egress packet. */ -+enum ppe_sc_egress_type { -+ PPE_SC_BYPASS_EGRESS_VLAN_MEMBER_CHECK = 0, -+ PPE_SC_BYPASS_EGRESS_VLAN_TRANSLATE = 1, -+ PPE_SC_BYPASS_EGRESS_VLAN_TAG_FMT_CTRL = 2, -+ PPE_SC_BYPASS_EGRESS_FDB_LEARN = 3, -+ PPE_SC_BYPASS_EGRESS_FDB_REFRESH = 4, -+ PPE_SC_BYPASS_EGRESS_L2_SOURCE_SECURITY = 5, -+ PPE_SC_BYPASS_EGRESS_MANAGEMENT_FWD = 6, -+ PPE_SC_BYPASS_EGRESS_BRIDGING_FWD = 7, -+ PPE_SC_BYPASS_EGRESS_IN_STP_FLTR = 8, -+ PPE_SC_BYPASS_EGRESS_EG_STP_FLTR = 9, -+ PPE_SC_BYPASS_EGRESS_SOURCE_FLTR = 10, -+ PPE_SC_BYPASS_EGRESS_POLICER = 11, -+ PPE_SC_BYPASS_EGRESS_L2_PKT_EDIT = 12, -+ PPE_SC_BYPASS_EGRESS_L3_PKT_EDIT = 13, -+ PPE_SC_BYPASS_EGRESS_ACL_POST_ROUTING_CHECK = 14, -+ PPE_SC_BYPASS_EGRESS_PORT_ISOLATION = 15, -+ PPE_SC_BYPASS_EGRESS_PRE_ACL_QOS = 16, -+ PPE_SC_BYPASS_EGRESS_POST_ACL_QOS = 17, -+ PPE_SC_BYPASS_EGRESS_DSCP_QOS = 18, -+ PPE_SC_BYPASS_EGRESS_PCP_QOS = 19, -+ PPE_SC_BYPASS_EGRESS_PREHEADER_QOS = 20, -+ PPE_SC_BYPASS_EGRESS_FAKE_MAC_DROP = 21, -+ PPE_SC_BYPASS_EGRESS_TUNL_CONTEXT = 22, -+ PPE_SC_BYPASS_EGRESS_FLOW_POLICER = 23, -+ /* This must be last as it determines the size of the BITMAP. */ -+ PPE_SC_BYPASS_EGRESS_SIZE, -+}; -+ -+/* Hardware bitmaps for bypassing counter of packet. */ -+enum ppe_sc_counter_type { -+ PPE_SC_BYPASS_COUNTER_RX_VLAN = 0, -+ PPE_SC_BYPASS_COUNTER_RX = 1, -+ PPE_SC_BYPASS_COUNTER_TX_VLAN = 2, -+ PPE_SC_BYPASS_COUNTER_TX = 3, -+ /* This must be last as it determines the size of the BITMAP. */ -+ PPE_SC_BYPASS_COUNTER_SIZE, -+}; -+ -+/* Hardware bitmaps for bypassing features of tunnel packet. */ -+enum ppe_sc_tunnel_type { -+ PPE_SC_BYPASS_TUNNEL_SERVICE_CODE = 0, -+ PPE_SC_BYPASS_TUNNEL_TUNNEL_HANDLE = 1, -+ PPE_SC_BYPASS_TUNNEL_L3_IF_CHECK = 2, -+ PPE_SC_BYPASS_TUNNEL_VLAN_CHECK = 3, -+ PPE_SC_BYPASS_TUNNEL_DMAC_CHECK = 4, -+ PPE_SC_BYPASS_TUNNEL_UDP_CSUM_0_CHECK = 5, -+ PPE_SC_BYPASS_TUNNEL_TBL_DE_ACCE_CHECK = 6, -+ PPE_SC_BYPASS_TUNNEL_PPPOE_MC_TERM_CHECK = 7, -+ PPE_SC_BYPASS_TUNNEL_TTL_EXCEED_CHECK = 8, -+ PPE_SC_BYPASS_TUNNEL_MAP_SRC_CHECK = 9, -+ PPE_SC_BYPASS_TUNNEL_MAP_DST_CHECK = 10, -+ PPE_SC_BYPASS_TUNNEL_LPM_DST_LOOKUP = 11, -+ PPE_SC_BYPASS_TUNNEL_LPM_LOOKUP = 12, -+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L2 = 13, -+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L3_IPV4 = 14, -+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L3_IPV6 = 15, -+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_L4 = 16, -+ PPE_SC_BYPASS_TUNNEL_WRONG_PKT_FMT_TUNNEL = 17, -+ /* Values 18-19 are not specified by hardware. */ -+ PPE_SC_BYPASS_TUNNEL_PRE_IPO = 20, -+ /* This must be last as it determines the size of the BITMAP. */ -+ PPE_SC_BYPASS_TUNNEL_SIZE, -+}; -+ -+/** -+ * struct ppe_sc_bypass - PPE service bypass bitmaps -+ * @ingress: Bitmap of features that can be bypassed on the ingress packet. -+ * @egress: Bitmap of features that can be bypassed on the egress packet. -+ * @counter: Bitmap of features that can be bypassed on the counter type. -+ * @tunnel: Bitmap of features that can be bypassed on the tunnel packet. -+ */ -+struct ppe_sc_bypass { -+ DECLARE_BITMAP(ingress, PPE_SC_BYPASS_INGRESS_SIZE); -+ DECLARE_BITMAP(egress, PPE_SC_BYPASS_EGRESS_SIZE); -+ DECLARE_BITMAP(counter, PPE_SC_BYPASS_COUNTER_SIZE); -+ DECLARE_BITMAP(tunnel, PPE_SC_BYPASS_TUNNEL_SIZE); -+}; -+ -+/** -+ * struct ppe_sc_cfg - PPE service code configuration. -+ * @dest_port_valid: Generate destination port or not. -+ * @dest_port: Destination port ID. -+ * @bitmaps: Bitmap of bypass features. -+ * @is_src: Destination port acts as source port, packet sent to CPU. -+ * @next_service_code: New service code generated. -+ * @eip_field_update_bitmap: Fields updated as actions taken for EIP. -+ * @eip_hw_service: Selected hardware functions for EIP. -+ * @eip_offset_sel: Packet offset selection, using packet's layer 4 offset -+ * or using packet's layer 3 offset for EIP. -+ * -+ * Service code is generated during the packet passing through PPE. -+ */ -+struct ppe_sc_cfg { -+ bool dest_port_valid; -+ int dest_port; -+ struct ppe_sc_bypass bitmaps; -+ bool is_src; -+ int next_service_code; -+ int eip_field_update_bitmap; -+ int eip_hw_service; -+ int eip_offset_sel; -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev); - int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, - int node_id, bool flow_level, int port, -@@ -109,4 +252,6 @@ int ppe_queue_ucast_offset_hash_set(stru - int ppe_port_resource_get(struct ppe_device *ppe_dev, int port, - enum ppe_resource_type type, - int *res_start, int *res_end); -+int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, -+ struct ppe_sc_cfg cfg); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -25,10 +25,63 @@ - #define PPE_BM_SCH_CFG_TBL_SECOND_PORT_VALID BIT(6) - #define PPE_BM_SCH_CFG_TBL_SECOND_PORT GENMASK(11, 8) - -+/* PPE service code configuration for the ingress direction functions, -+ * including bypass configuration for relevant PPE switch core functions -+ * such as flow entry lookup bypass. -+ */ -+#define PPE_SERVICE_TBL_ADDR 0x15000 -+#define PPE_SERVICE_TBL_ENTRIES 256 -+#define PPE_SERVICE_TBL_INC 0x10 -+#define PPE_SERVICE_W0_BYPASS_BITMAP GENMASK(31, 0) -+#define PPE_SERVICE_W1_RX_CNT_EN BIT(0) -+ -+#define PPE_SERVICE_SET_BYPASS_BITMAP(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_SERVICE_W0_BYPASS_BITMAP) -+#define PPE_SERVICE_SET_RX_CNT_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_SERVICE_W1_RX_CNT_EN) -+ - /* PPE queue counters enable/disable control. */ - #define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044 - #define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2) - -+/* PPE service code configuration on the egress direction. */ -+#define PPE_EG_SERVICE_TBL_ADDR 0x43000 -+#define PPE_EG_SERVICE_TBL_ENTRIES 256 -+#define PPE_EG_SERVICE_TBL_INC 0x10 -+#define PPE_EG_SERVICE_W0_UPDATE_ACTION GENMASK(31, 0) -+#define PPE_EG_SERVICE_W1_NEXT_SERVCODE GENMASK(7, 0) -+#define PPE_EG_SERVICE_W1_HW_SERVICE GENMASK(13, 8) -+#define PPE_EG_SERVICE_W1_OFFSET_SEL BIT(14) -+#define PPE_EG_SERVICE_W1_TX_CNT_EN BIT(15) -+ -+#define PPE_EG_SERVICE_SET_UPDATE_ACTION(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_EG_SERVICE_W0_UPDATE_ACTION) -+#define PPE_EG_SERVICE_SET_NEXT_SERVCODE(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_NEXT_SERVCODE) -+#define PPE_EG_SERVICE_SET_HW_SERVICE(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_HW_SERVICE) -+#define PPE_EG_SERVICE_SET_OFFSET_SEL(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_OFFSET_SEL) -+#define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_TX_CNT_EN) -+ -+/* PPE service code configuration for destination port and counter. */ -+#define PPE_IN_L2_SERVICE_TBL_ADDR 0x66000 -+#define PPE_IN_L2_SERVICE_TBL_ENTRIES 256 -+#define PPE_IN_L2_SERVICE_TBL_INC 0x10 -+#define PPE_IN_L2_SERVICE_TBL_DST_PORT_ID_VALID BIT(0) -+#define PPE_IN_L2_SERVICE_TBL_DST_PORT_ID GENMASK(4, 1) -+#define PPE_IN_L2_SERVICE_TBL_DST_DIRECTION BIT(5) -+#define PPE_IN_L2_SERVICE_TBL_DST_BYPASS_BITMAP GENMASK(29, 6) -+#define PPE_IN_L2_SERVICE_TBL_RX_CNT_EN BIT(30) -+#define PPE_IN_L2_SERVICE_TBL_TX_CNT_EN BIT(31) -+ -+/* PPE service code configuration for the tunnel packet. */ -+#define PPE_TL_SERVICE_TBL_ADDR 0x306000 -+#define PPE_TL_SERVICE_TBL_ENTRIES 256 -+#define PPE_TL_SERVICE_TBL_INC 4 -+#define PPE_TL_SERVICE_TBL_BYPASS_BITMAP GENMASK(31, 0) -+ - /* Port scheduler global config. */ - #define PPE_PSCH_SCH_DEPTH_CFG_ADDR 0x400000 - #define PPE_PSCH_SCH_DEPTH_CFG_INC 4 diff --git a/target/linux/qualcommbe/patches-6.12/0331-net-ethernet-qualcomm-Initialize-PPE-port-control-se.patch b/target/linux/qualcommbe/patches-6.12/0331-net-ethernet-qualcomm-Initialize-PPE-port-control-se.patch deleted file mode 100644 index f1dcb51a87..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0331-net-ethernet-qualcomm-Initialize-PPE-port-control-se.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 63af46200da794acda25cf8083bde0c1576b0859 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:43 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE port control settings - -1. Enable port specific counters in PPE. -2. Configure the default action as drop when the packet size - is more than the configured MTU of physical port. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 86 ++++++++++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 15 ++++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 47 ++++++++++ - 3 files changed, 147 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -1153,6 +1153,44 @@ int ppe_sc_config_set(struct ppe_device - return regmap_write(ppe_dev->regmap, reg, val); - } - -+/** -+ * ppe_counter_enable_set - Set PPE port counter enabled -+ * @ppe_dev: PPE device -+ * @port: PPE port ID -+ * -+ * Enable PPE counters on the given port for the unicast packet, multicast -+ * packet and VLAN packet received and transmitted by PPE. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port) -+{ -+ u32 reg, mru_mtu_val[3]; -+ int ret; -+ -+ reg = PPE_MRU_MTU_CTRL_TBL_ADDR + PPE_MRU_MTU_CTRL_TBL_INC * port; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+ if (ret) -+ return ret; -+ -+ PPE_MRU_MTU_CTRL_SET_RX_CNT_EN(mru_mtu_val, true); -+ PPE_MRU_MTU_CTRL_SET_TX_CNT_EN(mru_mtu_val, true); -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+ if (ret) -+ return ret; -+ -+ reg = PPE_MC_MTU_CTRL_TBL_ADDR + PPE_MC_MTU_CTRL_TBL_INC * port; -+ ret = regmap_set_bits(ppe_dev->regmap, reg, PPE_MC_MTU_CTRL_TBL_TX_CNT_EN); -+ if (ret) -+ return ret; -+ -+ reg = PPE_PORT_EG_VLAN_TBL_ADDR + PPE_PORT_EG_VLAN_TBL_INC * port; -+ -+ return regmap_set_bits(ppe_dev->regmap, reg, PPE_PORT_EG_VLAN_TBL_TX_COUNTING_EN); -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -1579,6 +1617,48 @@ static int ppe_servcode_init(struct ppe_ - return ppe_sc_config_set(ppe_dev, PPE_EDMA_SC_BYPASS_ID, sc_cfg); - } - -+/* Initialize PPE port configurations. */ -+static int ppe_port_config_init(struct ppe_device *ppe_dev) -+{ -+ u32 reg, val, mru_mtu_val[3]; -+ int i, ret; -+ -+ /* MTU and MRU settings are not required for CPU port 0. */ -+ for (i = 1; i < ppe_dev->num_ports; i++) { -+ /* Enable Ethernet port counter */ -+ ret = ppe_counter_enable_set(ppe_dev, i); -+ if (ret) -+ return ret; -+ -+ reg = PPE_MRU_MTU_CTRL_TBL_ADDR + PPE_MRU_MTU_CTRL_TBL_INC * i; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+ if (ret) -+ return ret; -+ -+ /* Drop the packet when the packet size is more than -+ * the MTU or MRU of the physical interface. -+ */ -+ PPE_MRU_MTU_CTRL_SET_MRU_CMD(mru_mtu_val, PPE_ACTION_DROP); -+ PPE_MRU_MTU_CTRL_SET_MTU_CMD(mru_mtu_val, PPE_ACTION_DROP); -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+ if (ret) -+ return ret; -+ -+ reg = PPE_MC_MTU_CTRL_TBL_ADDR + PPE_MC_MTU_CTRL_TBL_INC * i; -+ val = FIELD_PREP(PPE_MC_MTU_CTRL_TBL_MTU_CMD, PPE_ACTION_DROP); -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_MC_MTU_CTRL_TBL_MTU_CMD, -+ val); -+ if (ret) -+ return ret; -+ } -+ -+ /* Enable CPU port counters. */ -+ return ppe_counter_enable_set(ppe_dev, 0); -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1599,5 +1679,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_servcode_init(ppe_dev); -+ ret = ppe_servcode_init(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_port_config_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -233,6 +233,20 @@ struct ppe_sc_cfg { - int eip_offset_sel; - }; - -+/** -+ * enum ppe_action_type - PPE action of the received packet. -+ * @PPE_ACTION_FORWARD: Packet forwarded per L2/L3 process. -+ * @PPE_ACTION_DROP: Packet dropped by PPE. -+ * @PPE_ACTION_COPY_TO_CPU: Packet copied to CPU port per multicast queue. -+ * @PPE_ACTION_REDIRECT_TO_CPU: Packet redirected to CPU port per unicast queue. -+ */ -+enum ppe_action_type { -+ PPE_ACTION_FORWARD = 0, -+ PPE_ACTION_DROP = 1, -+ PPE_ACTION_COPY_TO_CPU = 2, -+ PPE_ACTION_REDIRECT_TO_CPU = 3, -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev); - int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, - int node_id, bool flow_level, int port, -@@ -254,4 +268,5 @@ int ppe_port_resource_get(struct ppe_dev - int *res_start, int *res_end); - int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, - struct ppe_sc_cfg cfg); -+int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -40,6 +40,18 @@ - #define PPE_SERVICE_SET_RX_CNT_EN(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_SERVICE_W1_RX_CNT_EN) - -+/* PPE port egress VLAN configurations. */ -+#define PPE_PORT_EG_VLAN_TBL_ADDR 0x20020 -+#define PPE_PORT_EG_VLAN_TBL_ENTRIES 8 -+#define PPE_PORT_EG_VLAN_TBL_INC 4 -+#define PPE_PORT_EG_VLAN_TBL_VLAN_TYPE BIT(0) -+#define PPE_PORT_EG_VLAN_TBL_CTAG_MODE GENMASK(2, 1) -+#define PPE_PORT_EG_VLAN_TBL_STAG_MODE GENMASK(4, 3) -+#define PPE_PORT_EG_VLAN_TBL_VSI_TAG_MODE_EN BIT(5) -+#define PPE_PORT_EG_VLAN_TBL_PCP_PROP_CMD BIT(6) -+#define PPE_PORT_EG_VLAN_TBL_DEI_PROP_CMD BIT(7) -+#define PPE_PORT_EG_VLAN_TBL_TX_COUNTING_EN BIT(8) -+ - /* PPE queue counters enable/disable control. */ - #define PPE_EG_BRIDGE_CONFIG_ADDR 0x20044 - #define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN BIT(2) -@@ -65,6 +77,41 @@ - #define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_TX_CNT_EN) - -+/* PPE port control configurations for the traffic to the multicast queues. */ -+#define PPE_MC_MTU_CTRL_TBL_ADDR 0x60a00 -+#define PPE_MC_MTU_CTRL_TBL_ENTRIES 8 -+#define PPE_MC_MTU_CTRL_TBL_INC 4 -+#define PPE_MC_MTU_CTRL_TBL_MTU GENMASK(13, 0) -+#define PPE_MC_MTU_CTRL_TBL_MTU_CMD GENMASK(15, 14) -+#define PPE_MC_MTU_CTRL_TBL_TX_CNT_EN BIT(16) -+ -+/* PPE port control configurations for the traffic to the unicast queues. */ -+#define PPE_MRU_MTU_CTRL_TBL_ADDR 0x65000 -+#define PPE_MRU_MTU_CTRL_TBL_ENTRIES 256 -+#define PPE_MRU_MTU_CTRL_TBL_INC 0x10 -+#define PPE_MRU_MTU_CTRL_W0_MRU GENMASK(13, 0) -+#define PPE_MRU_MTU_CTRL_W0_MRU_CMD GENMASK(15, 14) -+#define PPE_MRU_MTU_CTRL_W0_MTU GENMASK(29, 16) -+#define PPE_MRU_MTU_CTRL_W0_MTU_CMD GENMASK(31, 30) -+#define PPE_MRU_MTU_CTRL_W1_RX_CNT_EN BIT(0) -+#define PPE_MRU_MTU_CTRL_W1_TX_CNT_EN BIT(1) -+#define PPE_MRU_MTU_CTRL_W1_SRC_PROFILE GENMASK(3, 2) -+#define PPE_MRU_MTU_CTRL_W1_INNER_PREC_LOW BIT(31) -+#define PPE_MRU_MTU_CTRL_W2_INNER_PREC_HIGH GENMASK(1, 0) -+ -+#define PPE_MRU_MTU_CTRL_SET_MRU(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MRU) -+#define PPE_MRU_MTU_CTRL_SET_MRU_CMD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MRU_CMD) -+#define PPE_MRU_MTU_CTRL_SET_MTU(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MTU) -+#define PPE_MRU_MTU_CTRL_SET_MTU_CMD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_MRU_MTU_CTRL_W0_MTU_CMD) -+#define PPE_MRU_MTU_CTRL_SET_RX_CNT_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_MRU_MTU_CTRL_W1_RX_CNT_EN) -+#define PPE_MRU_MTU_CTRL_SET_TX_CNT_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_MRU_MTU_CTRL_W1_TX_CNT_EN) -+ - /* PPE service code configuration for destination port and counter. */ - #define PPE_IN_L2_SERVICE_TBL_ADDR 0x66000 - #define PPE_IN_L2_SERVICE_TBL_ENTRIES 256 diff --git a/target/linux/qualcommbe/patches-6.12/0332-net-ethernet-qualcomm-Initialize-PPE-RSS-hash-settin.patch b/target/linux/qualcommbe/patches-6.12/0332-net-ethernet-qualcomm-Initialize-PPE-RSS-hash-settin.patch deleted file mode 100644 index fc0764284d..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0332-net-ethernet-qualcomm-Initialize-PPE-RSS-hash-settin.patch +++ /dev/null @@ -1,344 +0,0 @@ -From 796be78fffeebe77237a6464da7ebe9807d670f0 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:44 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE RSS hash settings - -PPE RSS hash is generated during PPE receive, based on the packet -content (3 tuples or 5 tuples) and as per the configured RSS seed. -The hash is then used to select the queue to transmit the packet -to the ARM CPU. - -This patch initializes the RSS hash settings that are used to -generate the hash for the packet during PPE packet receive. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 194 +++++++++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 39 ++++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 40 ++++ - 3 files changed, 272 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -1191,6 +1191,143 @@ int ppe_counter_enable_set(struct ppe_de - return regmap_set_bits(ppe_dev->regmap, reg, PPE_PORT_EG_VLAN_TBL_TX_COUNTING_EN); - } - -+static int ppe_rss_hash_ipv4_config(struct ppe_device *ppe_dev, int index, -+ struct ppe_rss_hash_cfg cfg) -+{ -+ u32 reg, val; -+ -+ switch (index) { -+ case 0: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_sip_mix[0]); -+ break; -+ case 1: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_dip_mix[0]); -+ break; -+ case 2: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_protocol_mix); -+ break; -+ case 3: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_dport_mix); -+ break; -+ case 4: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_IPV4_VAL, cfg.hash_sport_mix); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ reg = PPE_RSS_HASH_MIX_IPV4_ADDR + index * PPE_RSS_HASH_MIX_IPV4_INC; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ -+static int ppe_rss_hash_ipv6_config(struct ppe_device *ppe_dev, int index, -+ struct ppe_rss_hash_cfg cfg) -+{ -+ u32 reg, val; -+ -+ switch (index) { -+ case 0 ... 3: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_sip_mix[index]); -+ break; -+ case 4 ... 7: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_dip_mix[index - 4]); -+ break; -+ case 8: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_protocol_mix); -+ break; -+ case 9: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_dport_mix); -+ break; -+ case 10: -+ val = FIELD_PREP(PPE_RSS_HASH_MIX_VAL, cfg.hash_sport_mix); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ reg = PPE_RSS_HASH_MIX_ADDR + index * PPE_RSS_HASH_MIX_INC; -+ -+ return regmap_write(ppe_dev->regmap, reg, val); -+} -+ -+/** -+ * ppe_rss_hash_config_set - Configure the PPE hash settings for the packet received. -+ * @ppe_dev: PPE device. -+ * @mode: Configure RSS hash for the packet type IPv4 and IPv6. -+ * @cfg: RSS hash configuration. -+ * -+ * PPE RSS hash settings are configured for the packet type IPv4 and IPv6. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_rss_hash_config_set(struct ppe_device *ppe_dev, int mode, -+ struct ppe_rss_hash_cfg cfg) -+{ -+ u32 val, reg; -+ int i, ret; -+ -+ if (mode & PPE_RSS_HASH_MODE_IPV4) { -+ val = FIELD_PREP(PPE_RSS_HASH_MASK_IPV4_HASH_MASK, cfg.hash_mask); -+ val |= FIELD_PREP(PPE_RSS_HASH_MASK_IPV4_FRAGMENT, cfg.hash_fragment_mode); -+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_MASK_IPV4_ADDR, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(PPE_RSS_HASH_SEED_IPV4_VAL, cfg.hash_seed); -+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_SEED_IPV4_ADDR, val); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < PPE_RSS_HASH_MIX_IPV4_ENTRIES; i++) { -+ ret = ppe_rss_hash_ipv4_config(ppe_dev, i, cfg); -+ if (ret) -+ return ret; -+ } -+ -+ for (i = 0; i < PPE_RSS_HASH_FIN_IPV4_ENTRIES; i++) { -+ val = FIELD_PREP(PPE_RSS_HASH_FIN_IPV4_INNER, cfg.hash_fin_inner[i]); -+ val |= FIELD_PREP(PPE_RSS_HASH_FIN_IPV4_OUTER, cfg.hash_fin_outer[i]); -+ reg = PPE_RSS_HASH_FIN_IPV4_ADDR + i * PPE_RSS_HASH_FIN_IPV4_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ if (mode & PPE_RSS_HASH_MODE_IPV6) { -+ val = FIELD_PREP(PPE_RSS_HASH_MASK_HASH_MASK, cfg.hash_mask); -+ val |= FIELD_PREP(PPE_RSS_HASH_MASK_FRAGMENT, cfg.hash_fragment_mode); -+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_MASK_ADDR, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(PPE_RSS_HASH_SEED_VAL, cfg.hash_seed); -+ ret = regmap_write(ppe_dev->regmap, PPE_RSS_HASH_SEED_ADDR, val); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < PPE_RSS_HASH_MIX_ENTRIES; i++) { -+ ret = ppe_rss_hash_ipv6_config(ppe_dev, i, cfg); -+ if (ret) -+ return ret; -+ } -+ -+ for (i = 0; i < PPE_RSS_HASH_FIN_ENTRIES; i++) { -+ val = FIELD_PREP(PPE_RSS_HASH_FIN_INNER, cfg.hash_fin_inner[i]); -+ val |= FIELD_PREP(PPE_RSS_HASH_FIN_OUTER, cfg.hash_fin_outer[i]); -+ reg = PPE_RSS_HASH_FIN_ADDR + i * PPE_RSS_HASH_FIN_INC; -+ -+ ret = regmap_write(ppe_dev->regmap, reg, val); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -1659,6 +1796,57 @@ static int ppe_port_config_init(struct p - return ppe_counter_enable_set(ppe_dev, 0); - } - -+/* Initialize the PPE RSS configuration for IPv4 and IPv6 packet receive. -+ * RSS settings are to calculate the random RSS hash value generated during -+ * packet receive. This hash is then used to generate the queue offset used -+ * to determine the queue used to transmit the packet. -+ */ -+static int ppe_rss_hash_init(struct ppe_device *ppe_dev) -+{ -+ u16 fins[PPE_RSS_HASH_TUPLES] = { 0x205, 0x264, 0x227, 0x245, 0x201 }; -+ u8 ips[PPE_RSS_HASH_IP_LENGTH] = { 0x13, 0xb, 0x13, 0xb }; -+ struct ppe_rss_hash_cfg hash_cfg; -+ int i, ret; -+ -+ hash_cfg.hash_seed = get_random_u32(); -+ hash_cfg.hash_mask = 0xfff; -+ -+ /* Use 5 tuple as RSS hash key for the first fragment of TCP, UDP -+ * and UDP-Lite packets. -+ */ -+ hash_cfg.hash_fragment_mode = false; -+ -+ /* The final common seed configs used to calculate the RSS has value, -+ * which is available for both IPv4 and IPv6 packet. -+ */ -+ for (i = 0; i < ARRAY_SIZE(fins); i++) { -+ hash_cfg.hash_fin_inner[i] = fins[i] & 0x1f; -+ hash_cfg.hash_fin_outer[i] = fins[i] >> 5; -+ } -+ -+ /* RSS seeds for IP protocol, L4 destination & source port and -+ * destination & source IP used to calculate the RSS hash value. -+ */ -+ hash_cfg.hash_protocol_mix = 0x13; -+ hash_cfg.hash_dport_mix = 0xb; -+ hash_cfg.hash_sport_mix = 0x13; -+ hash_cfg.hash_dip_mix[0] = 0xb; -+ hash_cfg.hash_sip_mix[0] = 0x13; -+ -+ /* Configure RSS seed configs for IPv4 packet. */ -+ ret = ppe_rss_hash_config_set(ppe_dev, PPE_RSS_HASH_MODE_IPV4, hash_cfg); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < ARRAY_SIZE(ips); i++) { -+ hash_cfg.hash_sip_mix[i] = ips[i]; -+ hash_cfg.hash_dip_mix[i] = ips[i]; -+ } -+ -+ /* Configure RSS seed configs for IPv6 packet. */ -+ return ppe_rss_hash_config_set(ppe_dev, PPE_RSS_HASH_MODE_IPV6, hash_cfg); -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1683,5 +1871,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_port_config_init(ppe_dev); -+ ret = ppe_port_config_init(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_rss_hash_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -23,6 +23,12 @@ - /* The service code is used by EDMA port to transmit packet to PPE. */ - #define PPE_EDMA_SC_BYPASS_ID 1 - -+/* The PPE RSS hash configured for IPv4 and IPv6 packet separately. */ -+#define PPE_RSS_HASH_MODE_IPV4 BIT(0) -+#define PPE_RSS_HASH_MODE_IPV6 BIT(1) -+#define PPE_RSS_HASH_IP_LENGTH 4 -+#define PPE_RSS_HASH_TUPLES 5 -+ - /** - * enum ppe_scheduler_frame_mode - PPE scheduler frame mode. - * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG, -@@ -247,6 +253,37 @@ enum ppe_action_type { - PPE_ACTION_REDIRECT_TO_CPU = 3, - }; - -+/** -+ * struct ppe_rss_hash_cfg - PPE RSS hash configuration. -+ * @hash_mask: Mask of the generated hash value. -+ * @hash_fragment_mode: Hash generation mode for the first fragment of TCP, -+ * UDP and UDP-Lite packets, to use either 3 tuple or 5 tuple for RSS hash -+ * key computation. -+ * @hash_seed: Seed to generate RSS hash. -+ * @hash_sip_mix: Source IP selection. -+ * @hash_dip_mix: Destination IP selection. -+ * @hash_protocol_mix: Protocol selection. -+ * @hash_sport_mix: Source L4 port selection. -+ * @hash_dport_mix: Destination L4 port selection. -+ * @hash_fin_inner: RSS hash value first selection. -+ * @hash_fin_outer: RSS hash value second selection. -+ * -+ * PPE RSS hash value is generated for the packet based on the RSS hash -+ * configured. -+ */ -+struct ppe_rss_hash_cfg { -+ u32 hash_mask; -+ bool hash_fragment_mode; -+ u32 hash_seed; -+ u8 hash_sip_mix[PPE_RSS_HASH_IP_LENGTH]; -+ u8 hash_dip_mix[PPE_RSS_HASH_IP_LENGTH]; -+ u8 hash_protocol_mix; -+ u8 hash_sport_mix; -+ u8 hash_dport_mix; -+ u8 hash_fin_inner[PPE_RSS_HASH_TUPLES]; -+ u8 hash_fin_outer[PPE_RSS_HASH_TUPLES]; -+}; -+ - int ppe_hw_config(struct ppe_device *ppe_dev); - int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, - int node_id, bool flow_level, int port, -@@ -269,4 +306,6 @@ int ppe_port_resource_get(struct ppe_dev - int ppe_sc_config_set(struct ppe_device *ppe_dev, int sc, - struct ppe_sc_cfg cfg); - int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port); -+int ppe_rss_hash_config_set(struct ppe_device *ppe_dev, int mode, -+ struct ppe_rss_hash_cfg hash_cfg); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -16,6 +16,46 @@ - #define PPE_BM_SCH_CTRL_SCH_OFFSET GENMASK(14, 8) - #define PPE_BM_SCH_CTRL_SCH_EN BIT(31) - -+/* RSS settings are to calculate the random RSS hash value generated during -+ * packet receive to ARM cores. This hash is then used to generate the queue -+ * offset used to determine the queue used to transmit the packet to ARM cores. -+ */ -+#define PPE_RSS_HASH_MASK_ADDR 0xb4318 -+#define PPE_RSS_HASH_MASK_HASH_MASK GENMASK(20, 0) -+#define PPE_RSS_HASH_MASK_FRAGMENT BIT(28) -+ -+#define PPE_RSS_HASH_SEED_ADDR 0xb431c -+#define PPE_RSS_HASH_SEED_VAL GENMASK(31, 0) -+ -+#define PPE_RSS_HASH_MIX_ADDR 0xb4320 -+#define PPE_RSS_HASH_MIX_ENTRIES 11 -+#define PPE_RSS_HASH_MIX_INC 4 -+#define PPE_RSS_HASH_MIX_VAL GENMASK(4, 0) -+ -+#define PPE_RSS_HASH_FIN_ADDR 0xb4350 -+#define PPE_RSS_HASH_FIN_ENTRIES 5 -+#define PPE_RSS_HASH_FIN_INC 4 -+#define PPE_RSS_HASH_FIN_INNER GENMASK(4, 0) -+#define PPE_RSS_HASH_FIN_OUTER GENMASK(9, 5) -+ -+#define PPE_RSS_HASH_MASK_IPV4_ADDR 0xb4380 -+#define PPE_RSS_HASH_MASK_IPV4_HASH_MASK GENMASK(20, 0) -+#define PPE_RSS_HASH_MASK_IPV4_FRAGMENT BIT(28) -+ -+#define PPE_RSS_HASH_SEED_IPV4_ADDR 0xb4384 -+#define PPE_RSS_HASH_SEED_IPV4_VAL GENMASK(31, 0) -+ -+#define PPE_RSS_HASH_MIX_IPV4_ADDR 0xb4390 -+#define PPE_RSS_HASH_MIX_IPV4_ENTRIES 5 -+#define PPE_RSS_HASH_MIX_IPV4_INC 4 -+#define PPE_RSS_HASH_MIX_IPV4_VAL GENMASK(4, 0) -+ -+#define PPE_RSS_HASH_FIN_IPV4_ADDR 0xb43b0 -+#define PPE_RSS_HASH_FIN_IPV4_ENTRIES 5 -+#define PPE_RSS_HASH_FIN_IPV4_INC 4 -+#define PPE_RSS_HASH_FIN_IPV4_INNER GENMASK(4, 0) -+#define PPE_RSS_HASH_FIN_IPV4_OUTER GENMASK(9, 5) -+ - #define PPE_BM_SCH_CFG_TBL_ADDR 0xc000 - #define PPE_BM_SCH_CFG_TBL_ENTRIES 128 - #define PPE_BM_SCH_CFG_TBL_INC 0x10 diff --git a/target/linux/qualcommbe/patches-6.12/0333-net-ethernet-qualcomm-Initialize-PPE-queue-to-Ethern.patch b/target/linux/qualcommbe/patches-6.12/0333-net-ethernet-qualcomm-Initialize-PPE-queue-to-Ethern.patch deleted file mode 100644 index e05748f0f3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0333-net-ethernet-qualcomm-Initialize-PPE-queue-to-Ethern.patch +++ /dev/null @@ -1,122 +0,0 @@ -From c4a321bc120fabc318df165a7fcdeddfcf052253 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:45 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE queue to Ethernet DMA - ring mapping - -Configure the selected queues to map with an Ethernet DMA ring for the -packet to receive on ARM cores. - -As default initialization, all queues assigned to CPU port 0 are mapped -to the EDMA ring 0. This configuration is later updated during Ethernet -DMA initialization. - -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 47 ++++++++++++++++++- - .../net/ethernet/qualcomm/ppe/ppe_config.h | 6 +++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 5 ++ - 3 files changed, 57 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -1328,6 +1328,28 @@ int ppe_rss_hash_config_set(struct ppe_d - return 0; - } - -+/** -+ * ppe_ring_queue_map_set - Set the PPE queue to Ethernet DMA ring mapping -+ * @ppe_dev: PPE device -+ * @ring_id: Ethernet DMA ring ID -+ * @queue_map: Bit map of queue IDs to given Ethernet DMA ring -+ * -+ * Configure the mapping from a set of PPE queues to a given Ethernet DMA ring. -+ * -+ * Return: 0 on success, negative error code on failure. -+ */ -+int ppe_ring_queue_map_set(struct ppe_device *ppe_dev, int ring_id, u32 *queue_map) -+{ -+ u32 reg, queue_bitmap_val[PPE_RING_TO_QUEUE_BITMAP_WORD_CNT]; -+ -+ memcpy(queue_bitmap_val, queue_map, sizeof(queue_bitmap_val)); -+ reg = PPE_RING_Q_MAP_TBL_ADDR + PPE_RING_Q_MAP_TBL_INC * ring_id; -+ -+ return regmap_bulk_write(ppe_dev->regmap, reg, -+ queue_bitmap_val, -+ ARRAY_SIZE(queue_bitmap_val)); -+} -+ - static int ppe_config_bm_threshold(struct ppe_device *ppe_dev, int bm_port_id, - const struct ppe_bm_port_config port_cfg) - { -@@ -1847,6 +1869,25 @@ static int ppe_rss_hash_init(struct ppe_ - return ppe_rss_hash_config_set(ppe_dev, PPE_RSS_HASH_MODE_IPV6, hash_cfg); - } - -+/* Initialize mapping between PPE queues assigned to CPU port 0 -+ * to Ethernet DMA ring 0. -+ */ -+static int ppe_queues_to_ring_init(struct ppe_device *ppe_dev) -+{ -+ u32 queue_bmap[PPE_RING_TO_QUEUE_BITMAP_WORD_CNT] = {}; -+ int ret, queue_id, queue_max; -+ -+ ret = ppe_port_resource_get(ppe_dev, 0, PPE_RES_UCAST, -+ &queue_id, &queue_max); -+ if (ret) -+ return ret; -+ -+ for (; queue_id <= queue_max; queue_id++) -+ queue_bmap[queue_id / 32] |= BIT_MASK(queue_id % 32); -+ -+ return ppe_ring_queue_map_set(ppe_dev, 0, queue_bmap); -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1875,5 +1916,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_rss_hash_init(ppe_dev); -+ ret = ppe_rss_hash_init(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_queues_to_ring_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -29,6 +29,9 @@ - #define PPE_RSS_HASH_IP_LENGTH 4 - #define PPE_RSS_HASH_TUPLES 5 - -+/* PPE supports 300 queues, each bit presents as one queue. */ -+#define PPE_RING_TO_QUEUE_BITMAP_WORD_CNT 10 -+ - /** - * enum ppe_scheduler_frame_mode - PPE scheduler frame mode. - * @PPE_SCH_WITH_IPG_PREAMBLE_FRAME_CRC: The scheduled frame includes IPG, -@@ -308,4 +311,7 @@ int ppe_sc_config_set(struct ppe_device - int ppe_counter_enable_set(struct ppe_device *ppe_dev, int port); - int ppe_rss_hash_config_set(struct ppe_device *ppe_dev, int mode, - struct ppe_rss_hash_cfg hash_cfg); -+int ppe_ring_queue_map_set(struct ppe_device *ppe_dev, -+ int ring_id, -+ u32 *queue_map); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -207,6 +207,11 @@ - #define PPE_L0_COMP_CFG_TBL_SHAPER_METER_LEN GENMASK(1, 0) - #define PPE_L0_COMP_CFG_TBL_NODE_METER_LEN GENMASK(3, 2) - -+/* PPE queue to Ethernet DMA ring mapping table. */ -+#define PPE_RING_Q_MAP_TBL_ADDR 0x42a000 -+#define PPE_RING_Q_MAP_TBL_ENTRIES 24 -+#define PPE_RING_Q_MAP_TBL_INC 0x40 -+ - /* Table addresses for per-queue dequeue setting. */ - #define PPE_DEQ_OPR_TBL_ADDR 0x430000 - #define PPE_DEQ_OPR_TBL_ENTRIES 300 diff --git a/target/linux/qualcommbe/patches-6.12/0334-net-ethernet-qualcomm-Initialize-PPE-L2-bridge-setti.patch b/target/linux/qualcommbe/patches-6.12/0334-net-ethernet-qualcomm-Initialize-PPE-L2-bridge-setti.patch deleted file mode 100644 index 28a48163a6..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0334-net-ethernet-qualcomm-Initialize-PPE-L2-bridge-setti.patch +++ /dev/null @@ -1,193 +0,0 @@ -From cf7282d1e5712953516fa1cc0ffaae405491b3ca Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Sun, 9 Feb 2025 22:29:46 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Initialize PPE L2 bridge settings - -Initialize the L2 bridge settings for the PPE ports to only enable -L2 frame forwarding between CPU port and PPE Ethernet ports. - -The per-port L2 bridge settings are initialized as follows: -For PPE CPU port, the PPE bridge TX is enabled and FDB learning is -disabled. For PPE physical ports, the default L2 forwarding action -is initialized to forward to CPU port only. - -L2/FDB learning and forwarding will not be enabled for PPE physical -ports yet, since the port's VSI (Virtual Switch Instance) and VSI -membership are not yet configured, which are required for FDB -forwarding. The VSI and FDB forwarding will later be enabled when -switchdev is enabled. - -Signed-off-by: Lei Wei -Signed-off-by: Luo Jie ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 80 ++++++++++++++++++- - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 50 ++++++++++++ - 2 files changed, 129 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -1888,6 +1888,80 @@ static int ppe_queues_to_ring_init(struc - return ppe_ring_queue_map_set(ppe_dev, 0, queue_bmap); - } - -+/* Initialize PPE bridge settings to only enable L2 frame receive and -+ * transmit between CPU port and PPE Ethernet ports. -+ */ -+static int ppe_bridge_init(struct ppe_device *ppe_dev) -+{ -+ u32 reg, mask, port_cfg[4], vsi_cfg[2]; -+ int ret, i; -+ -+ /* Configure the following settings for CPU port0: -+ * a.) Enable Bridge TX -+ * b.) Disable FDB new address learning -+ * c.) Disable station move address learning -+ */ -+ mask = PPE_PORT_BRIDGE_TXMAC_EN; -+ mask |= PPE_PORT_BRIDGE_NEW_LRN_EN; -+ mask |= PPE_PORT_BRIDGE_STA_MOVE_LRN_EN; -+ ret = regmap_update_bits(ppe_dev->regmap, -+ PPE_PORT_BRIDGE_CTRL_ADDR, -+ mask, -+ PPE_PORT_BRIDGE_TXMAC_EN); -+ if (ret) -+ return ret; -+ -+ for (i = 1; i < ppe_dev->num_ports; i++) { -+ /* Enable invalid VSI forwarding for all the physical ports -+ * to CPU port0, in case no VSI is assigned to the physical -+ * port. -+ */ -+ reg = PPE_L2_VP_PORT_TBL_ADDR + PPE_L2_VP_PORT_TBL_INC * i; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ port_cfg, ARRAY_SIZE(port_cfg)); -+ -+ if (ret) -+ return ret; -+ -+ PPE_L2_PORT_SET_INVALID_VSI_FWD_EN(port_cfg, true); -+ PPE_L2_PORT_SET_DST_INFO(port_cfg, 0); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ port_cfg, ARRAY_SIZE(port_cfg)); -+ if (ret) -+ return ret; -+ } -+ -+ for (i = 0; i < PPE_VSI_TBL_ENTRIES; i++) { -+ /* Set the VSI forward membership to include only CPU port0. -+ * FDB learning and forwarding take place only after switchdev -+ * is supported later to create the VSI and join the physical -+ * ports to the VSI port member. -+ */ -+ reg = PPE_VSI_TBL_ADDR + PPE_VSI_TBL_INC * i; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ vsi_cfg, ARRAY_SIZE(vsi_cfg)); -+ if (ret) -+ return ret; -+ -+ PPE_VSI_SET_MEMBER_PORT_BITMAP(vsi_cfg, BIT(0)); -+ PPE_VSI_SET_UUC_BITMAP(vsi_cfg, BIT(0)); -+ PPE_VSI_SET_UMC_BITMAP(vsi_cfg, BIT(0)); -+ PPE_VSI_SET_BC_BITMAP(vsi_cfg, BIT(0)); -+ PPE_VSI_SET_NEW_ADDR_LRN_EN(vsi_cfg, true); -+ PPE_VSI_SET_NEW_ADDR_FWD_CMD(vsi_cfg, PPE_ACTION_FORWARD); -+ PPE_VSI_SET_STATION_MOVE_LRN_EN(vsi_cfg, true); -+ PPE_VSI_SET_STATION_MOVE_FWD_CMD(vsi_cfg, PPE_ACTION_FORWARD); -+ -+ ret = regmap_bulk_write(ppe_dev->regmap, reg, -+ vsi_cfg, ARRAY_SIZE(vsi_cfg)); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ - int ppe_hw_config(struct ppe_device *ppe_dev) - { - int ret; -@@ -1920,5 +1994,9 @@ int ppe_hw_config(struct ppe_device *ppe - if (ret) - return ret; - -- return ppe_queues_to_ring_init(ppe_dev); -+ ret = ppe_queues_to_ring_init(ppe_dev); -+ if (ret) -+ return ret; -+ -+ return ppe_bridge_init(ppe_dev); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -117,6 +117,14 @@ - #define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_TX_CNT_EN) - -+/* PPE port bridge configuration */ -+#define PPE_PORT_BRIDGE_CTRL_ADDR 0x60300 -+#define PPE_PORT_BRIDGE_CTRL_ENTRIES 8 -+#define PPE_PORT_BRIDGE_CTRL_INC 4 -+#define PPE_PORT_BRIDGE_NEW_LRN_EN BIT(0) -+#define PPE_PORT_BRIDGE_STA_MOVE_LRN_EN BIT(3) -+#define PPE_PORT_BRIDGE_TXMAC_EN BIT(16) -+ - /* PPE port control configurations for the traffic to the multicast queues. */ - #define PPE_MC_MTU_CTRL_TBL_ADDR 0x60a00 - #define PPE_MC_MTU_CTRL_TBL_ENTRIES 8 -@@ -125,6 +133,36 @@ - #define PPE_MC_MTU_CTRL_TBL_MTU_CMD GENMASK(15, 14) - #define PPE_MC_MTU_CTRL_TBL_TX_CNT_EN BIT(16) - -+/* PPE VSI configurations */ -+#define PPE_VSI_TBL_ADDR 0x63800 -+#define PPE_VSI_TBL_ENTRIES 64 -+#define PPE_VSI_TBL_INC 0x10 -+#define PPE_VSI_W0_MEMBER_PORT_BITMAP GENMASK(7, 0) -+#define PPE_VSI_W0_UUC_BITMAP GENMASK(15, 8) -+#define PPE_VSI_W0_UMC_BITMAP GENMASK(23, 16) -+#define PPE_VSI_W0_BC_BITMAP GENMASK(31, 24) -+#define PPE_VSI_W1_NEW_ADDR_LRN_EN BIT(0) -+#define PPE_VSI_W1_NEW_ADDR_FWD_CMD GENMASK(2, 1) -+#define PPE_VSI_W1_STATION_MOVE_LRN_EN BIT(3) -+#define PPE_VSI_W1_STATION_MOVE_FWD_CMD GENMASK(5, 4) -+ -+#define PPE_VSI_SET_MEMBER_PORT_BITMAP(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_MEMBER_PORT_BITMAP) -+#define PPE_VSI_SET_UUC_BITMAP(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_UUC_BITMAP) -+#define PPE_VSI_SET_UMC_BITMAP(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_UMC_BITMAP) -+#define PPE_VSI_SET_BC_BITMAP(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_BC_BITMAP) -+#define PPE_VSI_SET_NEW_ADDR_LRN_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_NEW_ADDR_LRN_EN) -+#define PPE_VSI_SET_NEW_ADDR_FWD_CMD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_NEW_ADDR_FWD_CMD) -+#define PPE_VSI_SET_STATION_MOVE_LRN_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_STATION_MOVE_LRN_EN) -+#define PPE_VSI_SET_STATION_MOVE_FWD_CMD(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_STATION_MOVE_FWD_CMD) -+ - /* PPE port control configurations for the traffic to the unicast queues. */ - #define PPE_MRU_MTU_CTRL_TBL_ADDR 0x65000 - #define PPE_MRU_MTU_CTRL_TBL_ENTRIES 256 -@@ -163,6 +201,18 @@ - #define PPE_IN_L2_SERVICE_TBL_RX_CNT_EN BIT(30) - #define PPE_IN_L2_SERVICE_TBL_TX_CNT_EN BIT(31) - -+/* L2 Port configurations */ -+#define PPE_L2_VP_PORT_TBL_ADDR 0x98000 -+#define PPE_L2_VP_PORT_TBL_ENTRIES 256 -+#define PPE_L2_VP_PORT_TBL_INC 0x10 -+#define PPE_L2_VP_PORT_W0_INVALID_VSI_FWD_EN BIT(0) -+#define PPE_L2_VP_PORT_W0_DST_INFO GENMASK(9, 2) -+ -+#define PPE_L2_PORT_SET_INVALID_VSI_FWD_EN(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_INVALID_VSI_FWD_EN) -+#define PPE_L2_PORT_SET_DST_INFO(tbl_cfg, value) \ -+ u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_DST_INFO) -+ - /* PPE service code configuration for the tunnel packet. */ - #define PPE_TL_SERVICE_TBL_ADDR 0x306000 - #define PPE_TL_SERVICE_TBL_ENTRIES 256 diff --git a/target/linux/qualcommbe/patches-6.12/0335-net-ethernet-qualcomm-Add-PPE-debugfs-support-for-PP.patch b/target/linux/qualcommbe/patches-6.12/0335-net-ethernet-qualcomm-Add-PPE-debugfs-support-for-PP.patch deleted file mode 100644 index e748bca604..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0335-net-ethernet-qualcomm-Add-PPE-debugfs-support-for-PP.patch +++ /dev/null @@ -1,950 +0,0 @@ -From fc25088f79cccb934d69e563221068589565926f Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:47 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add PPE debugfs support for PPE - counters - -The PPE hardware counters maintain counters for packets handled by -the various functional blocks of PPE. They help in tracing the packets -passed through PPE and debugging any packet drops. - -The counters displayed by this debugfs file are ones that are common -for all Ethernet ports, and they do not include the counters that are -specific for a MAC port. Hence they cannot be displayed using ethtool. -The per-MAC counters will be supported using "ethtool -S" along with -the netdevice driver. - -The PPE hardware packet counters are made available through -the debugfs entry "/sys/kernel/debug/ppe/packet_counters". - -Signed-off-by: Luo Jie ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/ppe.c | 11 + - drivers/net/ethernet/qualcomm/ppe/ppe.h | 3 + - .../net/ethernet/qualcomm/ppe/ppe_debugfs.c | 692 ++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/ppe_debugfs.h | 16 + - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 102 +++ - 6 files changed, 825 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -4,4 +4,4 @@ - # - - obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o --qcom-ppe-objs := ppe.o ppe_config.o -+qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c -@@ -16,6 +16,7 @@ - - #include "ppe.h" - #include "ppe_config.h" -+#include "ppe_debugfs.h" - - #define PPE_PORT_MAX 8 - #define PPE_CLK_RATE 353000000 -@@ -199,11 +200,20 @@ static int qcom_ppe_probe(struct platfor - if (ret) - return dev_err_probe(dev, ret, "PPE HW config failed\n"); - -+ ppe_debugfs_setup(ppe_dev); - platform_set_drvdata(pdev, ppe_dev); - - return 0; - } - -+static void qcom_ppe_remove(struct platform_device *pdev) -+{ -+ struct ppe_device *ppe_dev; -+ -+ ppe_dev = platform_get_drvdata(pdev); -+ ppe_debugfs_teardown(ppe_dev); -+} -+ - static const struct of_device_id qcom_ppe_of_match[] = { - { .compatible = "qcom,ipq9574-ppe" }, - {} -@@ -216,6 +226,7 @@ static struct platform_driver qcom_ppe_d - .of_match_table = qcom_ppe_of_match, - }, - .probe = qcom_ppe_probe, -+ .remove = qcom_ppe_remove, - }; - module_platform_driver(qcom_ppe_driver); - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h -@@ -11,6 +11,7 @@ - - struct device; - struct regmap; -+struct dentry; - - /** - * struct ppe_device - PPE device private data. -@@ -18,6 +19,7 @@ struct regmap; - * @regmap: PPE register map. - * @clk_rate: PPE clock rate. - * @num_ports: Number of PPE ports. -+ * @debugfs_root: Debugfs root entry. - * @num_icc_paths: Number of interconnect paths. - * @icc_paths: Interconnect path array. - * -@@ -30,6 +32,7 @@ struct ppe_device { - struct regmap *regmap; - unsigned long clk_rate; - unsigned int num_ports; -+ struct dentry *debugfs_root; - unsigned int num_icc_paths; - struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths); - }; ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c -@@ -0,0 +1,692 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE debugfs routines for display of PPE counters useful for debug. */ -+ -+#include -+#include -+#include -+#include -+ -+#include "ppe.h" -+#include "ppe_config.h" -+#include "ppe_debugfs.h" -+#include "ppe_regs.h" -+ -+#define PPE_PKT_CNT_TBL_SIZE 3 -+#define PPE_DROP_PKT_CNT_TBL_SIZE 5 -+ -+#define PPE_W0_PKT_CNT GENMASK(31, 0) -+#define PPE_W2_DROP_PKT_CNT_LOW GENMASK(31, 8) -+#define PPE_W3_DROP_PKT_CNT_HIGH GENMASK(7, 0) -+ -+#define PPE_GET_PKT_CNT(tbl_cnt) \ -+ u32_get_bits(*((u32 *)(tbl_cnt)), PPE_W0_PKT_CNT) -+#define PPE_GET_DROP_PKT_CNT_LOW(tbl_cnt) \ -+ u32_get_bits(*((u32 *)(tbl_cnt) + 0x2), PPE_W2_DROP_PKT_CNT_LOW) -+#define PPE_GET_DROP_PKT_CNT_HIGH(tbl_cnt) \ -+ u32_get_bits(*((u32 *)(tbl_cnt) + 0x3), PPE_W3_DROP_PKT_CNT_HIGH) -+ -+#define PRINT_COUNTER_PREFIX(desc, cnt_type) \ -+ seq_printf(seq, "%-16s %16s", desc, cnt_type) -+ -+#define PRINT_CPU_CODE_COUNTER(cnt, code) \ -+ seq_printf(seq, "%10u(cpucode:%d)", cnt, code) -+ -+#define PRINT_DROP_CODE_COUNTER(cnt, port, code) \ -+ seq_printf(seq, "%10u(port=%d),dropcode:%d", cnt, port, code) -+ -+#define PRINT_SINGLE_COUNTER(tag, cnt, str, index) \ -+do { \ -+ if (!((tag) % 4)) \ -+ seq_printf(seq, "\n%-16s %16s", "", ""); \ -+ seq_printf(seq, "%10u(%s=%04d)", cnt, str, index); \ -+} while (0) -+ -+#define PRINT_TWO_COUNTERS(tag, cnt0, cnt1, str, index) \ -+do { \ -+ if (!((tag) % 4)) \ -+ seq_printf(seq, "\n%-16s %16s", "", ""); \ -+ seq_printf(seq, "%10u/%u(%s=%04d)", cnt0, cnt1, str, index); \ -+} while (0) -+ -+/** -+ * enum ppe_cnt_size_type - PPE counter size type -+ * @PPE_PKT_CNT_SIZE_1WORD: Counter size with single register -+ * @PPE_PKT_CNT_SIZE_3WORD: Counter size with table of 3 words -+ * @PPE_PKT_CNT_SIZE_5WORD: Counter size with table of 5 words -+ * -+ * PPE takes the different register size to record the packet counters. -+ * It uses single register, or register table with 3 words or 5 words. -+ * The counter with table size 5 words also records the drop counter. -+ * There are also some other counter types occupying sizes less than 32 -+ * bits, which is not covered by this enumeration type. -+ */ -+enum ppe_cnt_size_type { -+ PPE_PKT_CNT_SIZE_1WORD, -+ PPE_PKT_CNT_SIZE_3WORD, -+ PPE_PKT_CNT_SIZE_5WORD, -+}; -+ -+static int ppe_pkt_cnt_get(struct ppe_device *ppe_dev, u32 reg, -+ enum ppe_cnt_size_type cnt_type, -+ u32 *cnt, u32 *drop_cnt) -+{ -+ u32 drop_pkt_cnt[PPE_DROP_PKT_CNT_TBL_SIZE]; -+ u32 pkt_cnt[PPE_PKT_CNT_TBL_SIZE]; -+ u32 value; -+ int ret; -+ -+ switch (cnt_type) { -+ case PPE_PKT_CNT_SIZE_1WORD: -+ ret = regmap_read(ppe_dev->regmap, reg, &value); -+ if (ret) -+ return ret; -+ -+ *cnt = value; -+ break; -+ case PPE_PKT_CNT_SIZE_3WORD: -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ pkt_cnt, ARRAY_SIZE(pkt_cnt)); -+ if (ret) -+ return ret; -+ -+ *cnt = PPE_GET_PKT_CNT(pkt_cnt); -+ break; -+ case PPE_PKT_CNT_SIZE_5WORD: -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ drop_pkt_cnt, ARRAY_SIZE(drop_pkt_cnt)); -+ if (ret) -+ return ret; -+ -+ *cnt = PPE_GET_PKT_CNT(drop_pkt_cnt); -+ -+ /* Drop counter with low 24 bits. */ -+ value = PPE_GET_DROP_PKT_CNT_LOW(drop_pkt_cnt); -+ *drop_cnt = FIELD_PREP(GENMASK(23, 0), value); -+ -+ /* Drop counter with high 8 bits. */ -+ value = PPE_GET_DROP_PKT_CNT_HIGH(drop_pkt_cnt); -+ *drop_cnt |= FIELD_PREP(GENMASK(31, 24), value); -+ break; -+ } -+ -+ return 0; -+} -+ -+static void ppe_tbl_pkt_cnt_clear(struct ppe_device *ppe_dev, u32 reg, -+ enum ppe_cnt_size_type cnt_type) -+{ -+ u32 drop_pkt_cnt[PPE_DROP_PKT_CNT_TBL_SIZE] = {}; -+ u32 pkt_cnt[PPE_PKT_CNT_TBL_SIZE] = {}; -+ -+ switch (cnt_type) { -+ case PPE_PKT_CNT_SIZE_1WORD: -+ regmap_write(ppe_dev->regmap, reg, 0); -+ break; -+ case PPE_PKT_CNT_SIZE_3WORD: -+ regmap_bulk_write(ppe_dev->regmap, reg, -+ pkt_cnt, ARRAY_SIZE(pkt_cnt)); -+ break; -+ case PPE_PKT_CNT_SIZE_5WORD: -+ regmap_bulk_write(ppe_dev->regmap, reg, -+ drop_pkt_cnt, ARRAY_SIZE(drop_pkt_cnt)); -+ break; -+ } -+} -+ -+/* The number of packets dropped because of no buffer available, no PPE -+ * buffer assigned to these packets. -+ */ -+static void ppe_port_rx_drop_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("PRX_DROP_CNT", "SILENT_DROP:"); -+ for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD, -+ &drop_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (drop_cnt > 0) { -+ tag++; -+ PRINT_SINGLE_COUNTER(tag, drop_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets dropped because hardware buffers were available -+ * only partially for the packet. -+ */ -+static void ppe_port_rx_bm_drop_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("PRX_BM_DROP_CNT", "OVERFLOW_DROP:"); -+ for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i; -+ -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_SINGLE_COUNTER(tag, pkt_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of currently occupied buffers, that can't be flushed. */ -+static void ppe_port_rx_bm_port_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ int used_cnt, react_cnt; -+ int ret, i, tag = 0; -+ u32 reg, val; -+ -+ PRINT_COUNTER_PREFIX("PRX_BM_PORT_CNT", "USED/REACT:"); -+ for (i = 0; i < PPE_BM_USED_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_BM_USED_CNT_TBL_ADDR + i * PPE_BM_USED_CNT_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ /* The number of PPE buffers used for caching the received -+ * packets before the pause frame sent. -+ */ -+ used_cnt = FIELD_GET(PPE_BM_USED_CNT_VAL, val); -+ -+ reg = PPE_BM_REACT_CNT_TBL_ADDR + i * PPE_BM_REACT_CNT_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ /* The number of PPE buffers used for caching the received -+ * packets after pause frame sent out. -+ */ -+ react_cnt = FIELD_GET(PPE_BM_REACT_CNT_VAL, val); -+ -+ if (used_cnt > 0 || react_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, used_cnt, react_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets processed by the ingress parser module of PPE. */ -+static void ppe_parse_pkt_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, cnt = 0, tunnel_cnt = 0; -+ int i, ret, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("IPR_PKT_CNT", "TPRX/IPRX:"); -+ for (i = 0; i < PPE_IPR_PKT_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_TPR_PKT_CNT_TBL_ADDR + i * PPE_TPR_PKT_CNT_TBL_INC; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD, -+ &tunnel_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ reg = PPE_IPR_PKT_CNT_TBL_ADDR + i * PPE_IPR_PKT_CNT_TBL_INC; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD, -+ &cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (tunnel_cnt > 0 || cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, tunnel_cnt, cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets received or dropped on the ingress direction. */ -+static void ppe_port_rx_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("PORT_RX_CNT", "RX/RX_DROP:"); -+ for (i = 0; i < PPE_PHY_PORT_RX_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PHY_PORT_RX_CNT_TBL_ADDR + PPE_PHY_PORT_RX_CNT_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD, -+ &pkt_cnt, &drop_cnt); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets received or dropped by the port. */ -+static void ppe_vp_rx_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("VPORT_RX_CNT", "RX/RX_DROP:"); -+ for (i = 0; i < PPE_PORT_RX_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PORT_RX_CNT_TBL_ADDR + PPE_PORT_RX_CNT_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD, -+ &pkt_cnt, &drop_cnt); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets received or dropped by layer 2 processing. */ -+static void ppe_pre_l2_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("PRE_L2_CNT", "RX/RX_DROP:"); -+ for (i = 0; i < PPE_PRE_L2_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PRE_L2_CNT_TBL_ADDR + PPE_PRE_L2_CNT_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD, -+ &pkt_cnt, &drop_cnt); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "vsi", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of VLAN packets received by PPE. */ -+static void ppe_vlan_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("VLAN_CNT", "RX:"); -+ for (i = 0; i < PPE_VLAN_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_VLAN_CNT_TBL_ADDR + PPE_VLAN_CNT_TBL_INC * i; -+ -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_SINGLE_COUNTER(tag, pkt_cnt, "vsi", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets handed to CPU by PPE. */ -+static void ppe_cpu_code_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0; -+ int ret, i; -+ -+ PRINT_COUNTER_PREFIX("CPU_CODE_CNT", "CODE:"); -+ for (i = 0; i < PPE_DROP_CPU_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_CPU_CNT_TBL_ADDR + PPE_DROP_CPU_CNT_TBL_INC * i; -+ -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (!pkt_cnt) -+ continue; -+ -+ /* There are 256 CPU codes saved in the first 256 entries -+ * of register table, and 128 drop codes for each PPE port -+ * (0-7), the total entries is 256 + 8 * 128. -+ */ -+ if (i < 256) -+ PRINT_CPU_CODE_COUNTER(pkt_cnt, i); -+ else -+ PRINT_DROP_CODE_COUNTER(pkt_cnt, (i - 256) % 8, -+ (i - 256) / 8); -+ seq_putc(seq, '\n'); -+ PRINT_COUNTER_PREFIX("", ""); -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets forwarded by VLAN on the egress direction. */ -+static void ppe_eg_vsi_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("EG_VSI_CNT", "TX:"); -+ for (i = 0; i < PPE_EG_VSI_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_EG_VSI_COUNTER_TBL_ADDR + PPE_EG_VSI_COUNTER_TBL_INC * i; -+ -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0) { -+ tag++; -+ PRINT_SINGLE_COUNTER(tag, pkt_cnt, "vsi", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets trasmitted or dropped by port. */ -+static void ppe_vp_tx_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("VPORT_TX_CNT", "TX/TX_DROP:"); -+ for (i = 0; i < PPE_VPORT_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_VPORT_TX_COUNTER_TBL_ADDR + PPE_VPORT_TX_COUNTER_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ reg = PPE_VPORT_TX_DROP_CNT_TBL_ADDR + PPE_VPORT_TX_DROP_CNT_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &drop_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0 || drop_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets trasmitted or dropped on the egress direction. */ -+static void ppe_port_tx_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, pkt_cnt = 0, drop_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("PORT_TX_CNT", "TX/TX_DROP:"); -+ for (i = 0; i < PPE_PORT_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_PORT_TX_COUNTER_TBL_ADDR + PPE_PORT_TX_COUNTER_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ reg = PPE_PORT_TX_DROP_CNT_TBL_ADDR + PPE_PORT_TX_DROP_CNT_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &drop_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (pkt_cnt > 0 || drop_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, drop_cnt, "port", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* The number of packets transmitted or pending by the PPE queue. */ -+static void ppe_queue_tx_counter_get(struct ppe_device *ppe_dev, -+ struct seq_file *seq) -+{ -+ u32 reg, val, pkt_cnt = 0, pend_cnt = 0; -+ int ret, i, tag = 0; -+ -+ PRINT_COUNTER_PREFIX("QUEUE_TX_CNT", "TX/PEND:"); -+ for (i = 0; i < PPE_QUEUE_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_QUEUE_TX_COUNTER_TBL_ADDR + PPE_QUEUE_TX_COUNTER_TBL_INC * i; -+ ret = ppe_pkt_cnt_get(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD, -+ &pkt_cnt, NULL); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ if (i < PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES) { -+ reg = PPE_AC_UNICAST_QUEUE_CNT_TBL_ADDR + -+ PPE_AC_UNICAST_QUEUE_CNT_TBL_INC * i; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ pend_cnt = FIELD_GET(PPE_AC_UNICAST_QUEUE_CNT_TBL_PEND_CNT, val); -+ } else { -+ reg = PPE_AC_MULTICAST_QUEUE_CNT_TBL_ADDR + -+ PPE_AC_MULTICAST_QUEUE_CNT_TBL_INC * -+ (i - PPE_AC_UNICAST_QUEUE_CFG_TBL_ENTRIES); -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ seq_printf(seq, "ERROR %d\n", ret); -+ return; -+ } -+ -+ pend_cnt = FIELD_GET(PPE_AC_MULTICAST_QUEUE_CNT_TBL_PEND_CNT, val); -+ } -+ -+ if (pkt_cnt > 0 || pend_cnt > 0) { -+ tag++; -+ PRINT_TWO_COUNTERS(tag, pkt_cnt, pend_cnt, "queue", i); -+ } -+ } -+ -+ seq_putc(seq, '\n'); -+} -+ -+/* Display the various packet counters of PPE. */ -+static int ppe_packet_counter_show(struct seq_file *seq, void *v) -+{ -+ struct ppe_device *ppe_dev = seq->private; -+ -+ ppe_port_rx_drop_counter_get(ppe_dev, seq); -+ ppe_port_rx_bm_drop_counter_get(ppe_dev, seq); -+ ppe_port_rx_bm_port_counter_get(ppe_dev, seq); -+ ppe_parse_pkt_counter_get(ppe_dev, seq); -+ ppe_port_rx_counter_get(ppe_dev, seq); -+ ppe_vp_rx_counter_get(ppe_dev, seq); -+ ppe_pre_l2_counter_get(ppe_dev, seq); -+ ppe_vlan_counter_get(ppe_dev, seq); -+ ppe_cpu_code_counter_get(ppe_dev, seq); -+ ppe_eg_vsi_counter_get(ppe_dev, seq); -+ ppe_vp_tx_counter_get(ppe_dev, seq); -+ ppe_port_tx_counter_get(ppe_dev, seq); -+ ppe_queue_tx_counter_get(ppe_dev, seq); -+ -+ return 0; -+} -+ -+static int ppe_packet_counter_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, ppe_packet_counter_show, inode->i_private); -+} -+ -+static ssize_t ppe_packet_counter_clear(struct file *file, -+ const char __user *buf, -+ size_t count, loff_t *pos) -+{ -+ struct ppe_device *ppe_dev = file_inode(file)->i_private; -+ u32 reg; -+ int i; -+ -+ for (i = 0; i < PPE_DROP_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_CNT_TBL_ADDR + i * PPE_DROP_CNT_TBL_INC; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD); -+ } -+ -+ for (i = 0; i < PPE_DROP_STAT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_STAT_TBL_ADDR + PPE_DROP_STAT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_IPR_PKT_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_IPR_PKT_CNT_TBL_ADDR + i * PPE_IPR_PKT_CNT_TBL_INC; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD); -+ -+ reg = PPE_TPR_PKT_CNT_TBL_ADDR + i * PPE_TPR_PKT_CNT_TBL_INC; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_1WORD); -+ } -+ -+ for (i = 0; i < PPE_VLAN_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_VLAN_CNT_TBL_ADDR + PPE_VLAN_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_PRE_L2_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PRE_L2_CNT_TBL_ADDR + PPE_PRE_L2_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD); -+ } -+ -+ for (i = 0; i < PPE_PORT_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_PORT_TX_DROP_CNT_TBL_ADDR + PPE_PORT_TX_DROP_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ -+ reg = PPE_PORT_TX_COUNTER_TBL_ADDR + PPE_PORT_TX_COUNTER_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_EG_VSI_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_EG_VSI_COUNTER_TBL_ADDR + PPE_EG_VSI_COUNTER_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_VPORT_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_VPORT_TX_COUNTER_TBL_ADDR + PPE_VPORT_TX_COUNTER_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ -+ reg = PPE_VPORT_TX_DROP_CNT_TBL_ADDR + PPE_VPORT_TX_DROP_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_QUEUE_TX_COUNTER_TBL_ENTRIES; i++) { -+ reg = PPE_QUEUE_TX_COUNTER_TBL_ADDR + PPE_QUEUE_TX_COUNTER_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ ppe_tbl_pkt_cnt_clear(ppe_dev, PPE_EPE_DBG_IN_CNT_ADDR, PPE_PKT_CNT_SIZE_1WORD); -+ ppe_tbl_pkt_cnt_clear(ppe_dev, PPE_EPE_DBG_OUT_CNT_ADDR, PPE_PKT_CNT_SIZE_1WORD); -+ -+ for (i = 0; i < PPE_DROP_CPU_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_DROP_CPU_CNT_TBL_ADDR + PPE_DROP_CPU_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_3WORD); -+ } -+ -+ for (i = 0; i < PPE_PORT_RX_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PORT_RX_CNT_TBL_ADDR + PPE_PORT_RX_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD); -+ } -+ -+ for (i = 0; i < PPE_PHY_PORT_RX_CNT_TBL_ENTRIES; i++) { -+ reg = PPE_PHY_PORT_RX_CNT_TBL_ADDR + PPE_PHY_PORT_RX_CNT_TBL_INC * i; -+ ppe_tbl_pkt_cnt_clear(ppe_dev, reg, PPE_PKT_CNT_SIZE_5WORD); -+ } -+ -+ return count; -+} -+ -+static const struct file_operations ppe_debugfs_packet_counter_fops = { -+ .owner = THIS_MODULE, -+ .open = ppe_packet_counter_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+ .write = ppe_packet_counter_clear, -+}; -+ -+void ppe_debugfs_setup(struct ppe_device *ppe_dev) -+{ -+ ppe_dev->debugfs_root = debugfs_create_dir("ppe", NULL); -+ debugfs_create_file("packet_counters", 0444, -+ ppe_dev->debugfs_root, -+ ppe_dev, -+ &ppe_debugfs_packet_counter_fops); -+} -+ -+void ppe_debugfs_teardown(struct ppe_device *ppe_dev) -+{ -+ debugfs_remove_recursive(ppe_dev->debugfs_root); -+ ppe_dev->debugfs_root = NULL; -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.h -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * -+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE debugfs counters setup. */ -+ -+#ifndef __PPE_DEBUGFS_H__ -+#define __PPE_DEBUGFS_H__ -+ -+#include "ppe.h" -+ -+void ppe_debugfs_setup(struct ppe_device *ppe_dev); -+void ppe_debugfs_teardown(struct ppe_device *ppe_dev); -+ -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -16,6 +16,39 @@ - #define PPE_BM_SCH_CTRL_SCH_OFFSET GENMASK(14, 8) - #define PPE_BM_SCH_CTRL_SCH_EN BIT(31) - -+/* PPE drop counters. */ -+#define PPE_DROP_CNT_TBL_ADDR 0xb024 -+#define PPE_DROP_CNT_TBL_ENTRIES 8 -+#define PPE_DROP_CNT_TBL_INC 4 -+ -+/* BM port drop counters. */ -+#define PPE_DROP_STAT_TBL_ADDR 0xe000 -+#define PPE_DROP_STAT_TBL_ENTRIES 30 -+#define PPE_DROP_STAT_TBL_INC 0x10 -+ -+#define PPE_EPE_DBG_IN_CNT_ADDR 0x26054 -+#define PPE_EPE_DBG_OUT_CNT_ADDR 0x26070 -+ -+/* Egress VLAN counters. */ -+#define PPE_EG_VSI_COUNTER_TBL_ADDR 0x41000 -+#define PPE_EG_VSI_COUNTER_TBL_ENTRIES 64 -+#define PPE_EG_VSI_COUNTER_TBL_INC 0x10 -+ -+/* Port TX counters. */ -+#define PPE_PORT_TX_COUNTER_TBL_ADDR 0x45000 -+#define PPE_PORT_TX_COUNTER_TBL_ENTRIES 8 -+#define PPE_PORT_TX_COUNTER_TBL_INC 0x10 -+ -+/* Virtual port TX counters. */ -+#define PPE_VPORT_TX_COUNTER_TBL_ADDR 0x47000 -+#define PPE_VPORT_TX_COUNTER_TBL_ENTRIES 256 -+#define PPE_VPORT_TX_COUNTER_TBL_INC 0x10 -+ -+/* Queue counters. */ -+#define PPE_QUEUE_TX_COUNTER_TBL_ADDR 0x4a000 -+#define PPE_QUEUE_TX_COUNTER_TBL_ENTRIES 300 -+#define PPE_QUEUE_TX_COUNTER_TBL_INC 0x10 -+ - /* RSS settings are to calculate the random RSS hash value generated during - * packet receive to ARM cores. This hash is then used to generate the queue - * offset used to determine the queue used to transmit the packet to ARM cores. -@@ -213,6 +246,51 @@ - #define PPE_L2_PORT_SET_DST_INFO(tbl_cfg, value) \ - u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_DST_INFO) - -+/* Port RX and RX drop counters. */ -+#define PPE_PORT_RX_CNT_TBL_ADDR 0x150000 -+#define PPE_PORT_RX_CNT_TBL_ENTRIES 256 -+#define PPE_PORT_RX_CNT_TBL_INC 0x20 -+ -+/* Physical port RX and RX drop counters. */ -+#define PPE_PHY_PORT_RX_CNT_TBL_ADDR 0x156000 -+#define PPE_PHY_PORT_RX_CNT_TBL_ENTRIES 8 -+#define PPE_PHY_PORT_RX_CNT_TBL_INC 0x20 -+ -+/* Counters for the packet to CPU port. */ -+#define PPE_DROP_CPU_CNT_TBL_ADDR 0x160000 -+#define PPE_DROP_CPU_CNT_TBL_ENTRIES 1280 -+#define PPE_DROP_CPU_CNT_TBL_INC 0x10 -+ -+/* VLAN counters. */ -+#define PPE_VLAN_CNT_TBL_ADDR 0x178000 -+#define PPE_VLAN_CNT_TBL_ENTRIES 64 -+#define PPE_VLAN_CNT_TBL_INC 0x10 -+ -+/* PPE L2 counters. */ -+#define PPE_PRE_L2_CNT_TBL_ADDR 0x17c000 -+#define PPE_PRE_L2_CNT_TBL_ENTRIES 64 -+#define PPE_PRE_L2_CNT_TBL_INC 0x20 -+ -+/* Port TX drop counters. */ -+#define PPE_PORT_TX_DROP_CNT_TBL_ADDR 0x17d000 -+#define PPE_PORT_TX_DROP_CNT_TBL_ENTRIES 8 -+#define PPE_PORT_TX_DROP_CNT_TBL_INC 0x10 -+ -+/* Virtual port TX counters. */ -+#define PPE_VPORT_TX_DROP_CNT_TBL_ADDR 0x17e000 -+#define PPE_VPORT_TX_DROP_CNT_TBL_ENTRIES 256 -+#define PPE_VPORT_TX_DROP_CNT_TBL_INC 0x10 -+ -+/* Counters for the tunnel packet. */ -+#define PPE_TPR_PKT_CNT_TBL_ADDR 0x1d0080 -+#define PPE_TPR_PKT_CNT_TBL_ENTRIES 8 -+#define PPE_TPR_PKT_CNT_TBL_INC 4 -+ -+/* Counters for the all packet received. */ -+#define PPE_IPR_PKT_CNT_TBL_ADDR 0x1e0080 -+#define PPE_IPR_PKT_CNT_TBL_ENTRIES 8 -+#define PPE_IPR_PKT_CNT_TBL_INC 4 -+ - /* PPE service code configuration for the tunnel packet. */ - #define PPE_TL_SERVICE_TBL_ADDR 0x306000 - #define PPE_TL_SERVICE_TBL_ENTRIES 256 -@@ -325,6 +403,18 @@ - #define PPE_BM_PORT_GROUP_ID_INC 0x4 - #define PPE_BM_PORT_GROUP_ID_SHARED_GROUP_ID GENMASK(1, 0) - -+/* Counters for PPE buffers used for packets cached. */ -+#define PPE_BM_USED_CNT_TBL_ADDR 0x6001c0 -+#define PPE_BM_USED_CNT_TBL_ENTRIES 15 -+#define PPE_BM_USED_CNT_TBL_INC 0x4 -+#define PPE_BM_USED_CNT_VAL GENMASK(10, 0) -+ -+/* Counters for PPE buffers used for packets received after pause frame sent. */ -+#define PPE_BM_REACT_CNT_TBL_ADDR 0x600240 -+#define PPE_BM_REACT_CNT_TBL_ENTRIES 15 -+#define PPE_BM_REACT_CNT_TBL_INC 0x4 -+#define PPE_BM_REACT_CNT_VAL GENMASK(8, 0) -+ - #define PPE_BM_SHARED_GROUP_CFG_ADDR 0x600290 - #define PPE_BM_SHARED_GROUP_CFG_ENTRIES 4 - #define PPE_BM_SHARED_GROUP_CFG_INC 0x4 -@@ -449,6 +539,18 @@ - #define PPE_AC_GRP_SET_BUF_LIMIT(tbl_cfg, value) \ - u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_AC_GRP_W1_BUF_LIMIT) - -+/* Counters for packets handled by unicast queues (0-255). */ -+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_ADDR 0x84e000 -+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_ENTRIES 256 -+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_INC 0x10 -+#define PPE_AC_UNICAST_QUEUE_CNT_TBL_PEND_CNT GENMASK(12, 0) -+ -+/* Counters for packets handled by multicast queues (256-299). */ -+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_ADDR 0x852000 -+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_ENTRIES 44 -+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_INC 0x10 -+#define PPE_AC_MULTICAST_QUEUE_CNT_TBL_PEND_CNT GENMASK(12, 0) -+ - /* Table addresses for per-queue enqueue setting. */ - #define PPE_ENQ_OPR_TBL_ADDR 0x85c000 - #define PPE_ENQ_OPR_TBL_ENTRIES 300 diff --git a/target/linux/qualcommbe/patches-6.12/0336-MAINTAINERS-Add-maintainer-for-Qualcomm-PPE-driver.patch b/target/linux/qualcommbe/patches-6.12/0336-MAINTAINERS-Add-maintainer-for-Qualcomm-PPE-driver.patch deleted file mode 100644 index 852bf522eb..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0336-MAINTAINERS-Add-maintainer-for-Qualcomm-PPE-driver.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 28098c348414fa97531449d4e27ba1587e67c2d9 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Sun, 9 Feb 2025 22:29:48 +0800 -Subject: [PATCH] MAINTAINERS: Add maintainer for Qualcomm PPE driver - -Add maintainer entry for PPE (Packet Process Engine) driver -supported for Qualcomm IPQ SoCs. - -Signed-off-by: Luo Jie ---- - MAINTAINERS | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -19146,6 +19146,14 @@ S: Maintained - F: Documentation/devicetree/bindings/mtd/qcom,nandc.yaml - F: drivers/mtd/nand/raw/qcom_nandc.c - -+QUALCOMM PPE DRIVER -+M: Luo Jie -+L: netdev@vger.kernel.org -+S: Supported -+F: Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml -+F: Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst -+F: drivers/net/ethernet/qualcomm/ppe/ -+ - QUALCOMM QSEECOM DRIVER - M: Maximilian Luz - L: linux-arm-msm@vger.kernel.org diff --git a/target/linux/qualcommbe/patches-6.12/0337-net-ethernet-qualcomm-Add-PPE-scheduler-config.patch b/target/linux/qualcommbe/patches-6.12/0337-net-ethernet-qualcomm-Add-PPE-scheduler-config.patch deleted file mode 100644 index d6292f8bf5..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0337-net-ethernet-qualcomm-Add-PPE-scheduler-config.patch +++ /dev/null @@ -1,201 +0,0 @@ -From 93cf3297818ee61607f0a8d1d34e4fb7fcde3cdf Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Tue, 26 Dec 2023 20:18:09 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add PPE scheduler config - -PPE scheduler config determines the priority of scheduling the -packet. The scheduler config is used for supporting the QoS -offload in PPE hardware. - -Change-Id: I4811bd133074757371775a6a69a1cc3cfaa8d0d0 -Signed-off-by: Luo Jie -Alex G: rebase patch on top of PPE driver submission from 20250209. - Add the ppe_queue_priority_set() function and its - dependencies. They will be used in the edma support in - susequent changes. - ppe_queue_priority_set() used to be part of ppe_api.c, and - is hereby moved to ppe_config.c . -Signed-off-by: Alexandru Gagniuc ---- - .../net/ethernet/qualcomm/ppe/ppe_config.c | 141 ++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/ppe_config.h | 5 + - 2 files changed, 146 insertions(+) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c -@@ -864,6 +864,51 @@ static int ppe_scheduler_l0_queue_map_se - val); - } - -+/* Get the first level scheduler configuration. */ -+static int ppe_scheduler_l0_queue_map_get(struct ppe_device *ppe_dev, -+ int node_id, int *port, -+ struct ppe_scheduler_cfg *scheduler_cfg) -+{ -+ u32 val, reg; -+ int ret; -+ -+ reg = PPE_L0_FLOW_MAP_TBL_ADDR + node_id * PPE_L0_FLOW_MAP_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->flow_id = FIELD_GET(PPE_L0_FLOW_MAP_TBL_FLOW_ID, val); -+ scheduler_cfg->pri = FIELD_GET(PPE_L0_FLOW_MAP_TBL_C_PRI, val); -+ scheduler_cfg->drr_node_wt = FIELD_GET(PPE_L0_FLOW_MAP_TBL_C_NODE_WT, val); -+ -+ reg = PPE_L0_C_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg->flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg->pri) * -+ PPE_L0_C_FLOW_CFG_TBL_INC; -+ -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->drr_node_id = FIELD_GET(PPE_L0_C_FLOW_CFG_TBL_NODE_ID, val); -+ scheduler_cfg->unit_is_packet = FIELD_GET(PPE_L0_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT, val); -+ -+ reg = PPE_L0_FLOW_PORT_MAP_TBL_ADDR + node_id * PPE_L0_FLOW_PORT_MAP_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ *port = FIELD_GET(PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM, val); -+ -+ reg = PPE_L0_COMP_CFG_TBL_ADDR + node_id * PPE_L0_COMP_CFG_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->frame_mode = FIELD_GET(PPE_L0_COMP_CFG_TBL_NODE_METER_LEN, val); -+ -+ return 0; -+} -+ - /* Set the PPE flow level scheduler configuration. */ - static int ppe_scheduler_l1_queue_map_set(struct ppe_device *ppe_dev, - int node_id, int port, -@@ -916,6 +961,50 @@ static int ppe_scheduler_l1_queue_map_se - return regmap_update_bits(ppe_dev->regmap, reg, PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, val); - } - -+/* Get the second level scheduler configuration. */ -+static int ppe_scheduler_l1_queue_map_get(struct ppe_device *ppe_dev, -+ int node_id, int *port, -+ struct ppe_scheduler_cfg *scheduler_cfg) -+{ -+ u32 val, reg; -+ int ret; -+ -+ reg = PPE_L1_FLOW_MAP_TBL_ADDR + node_id * PPE_L1_FLOW_MAP_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->flow_id = FIELD_GET(PPE_L1_FLOW_MAP_TBL_FLOW_ID, val); -+ scheduler_cfg->pri = FIELD_GET(PPE_L1_FLOW_MAP_TBL_C_PRI, val); -+ scheduler_cfg->drr_node_wt = FIELD_GET(PPE_L1_FLOW_MAP_TBL_C_NODE_WT, val); -+ -+ reg = PPE_L1_C_FLOW_CFG_TBL_ADDR + -+ (scheduler_cfg->flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg->pri) * -+ PPE_L1_C_FLOW_CFG_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->drr_node_id = FIELD_GET(PPE_L1_C_FLOW_CFG_TBL_NODE_ID, val); -+ scheduler_cfg->unit_is_packet = FIELD_GET(PPE_L1_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT, val); -+ -+ reg = PPE_L1_FLOW_PORT_MAP_TBL_ADDR + node_id * PPE_L1_FLOW_PORT_MAP_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ *port = FIELD_GET(PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM, val); -+ -+ reg = PPE_L1_COMP_CFG_TBL_ADDR + node_id * PPE_L1_COMP_CFG_TBL_INC; -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) -+ return ret; -+ -+ scheduler_cfg->frame_mode = FIELD_GET(PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, val); -+ -+ return 0; -+} -+ - /** - * ppe_queue_scheduler_set - Configure scheduler for PPE hardware queue - * @ppe_dev: PPE device -@@ -942,6 +1031,58 @@ int ppe_queue_scheduler_set(struct ppe_d - } - - /** -+ * ppe_queue_scheduler_get - get QoS scheduler of PPE hardware queue -+ * @ppe_dev: PPE device -+ * @node_id: PPE node ID -+ * @flow_level: Flow level scheduler or queue level scheduler -+ * @port: PPE port ID to get scheduler config -+ * @scheduler_cfg: QoS scheduler configuration -+ * -+ * The hardware QoS function is supported by PPE, the current scheduler -+ * configuration can be acquired based on the queue ID of PPE port. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int ppe_queue_scheduler_get(struct ppe_device *ppe_dev, -+ int node_id, bool flow_level, int *port, -+ struct ppe_scheduler_cfg *scheduler_cfg) -+{ -+ if (flow_level) -+ return ppe_scheduler_l1_queue_map_get(ppe_dev, node_id, -+ port, scheduler_cfg); -+ -+ return ppe_scheduler_l0_queue_map_get(ppe_dev, node_id, -+ port, scheduler_cfg); -+} -+ -+ -+/** -+ * ppe_queue_priority_set - set scheduler priority of PPE hardware queue -+ * @ppe_dev: PPE device -+ * @node_id: PPE hardware node ID, which is either queue ID or flow ID -+ * @priority: Qos scheduler priority -+ * -+ * Configure scheduler priority of PPE hardware queque, the maximum node -+ * ID supported is PPE_QUEUE_ID_NUM added by PPE_FLOW_ID_NUM, queue ID -+ * belongs to level 0, flow ID belongs to level 1 in the packet pipeline. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int ppe_queue_priority_set(struct ppe_device *ppe_dev, -+ int node_id, int priority) -+{ -+ struct ppe_scheduler_cfg sch_cfg; -+ int ret, port, level = 0; -+ -+ ret = ppe_queue_scheduler_get(ppe_dev, node_id, level, &port, &sch_cfg); -+ if (ret) -+ return ret; -+ -+ sch_cfg.pri = priority; -+ return ppe_queue_scheduler_set(ppe_dev, node_id, level, port, sch_cfg); -+} -+ -+/** - * ppe_queue_ucast_base_set - Set PPE unicast queue base ID and profile ID - * @ppe_dev: PPE device - * @queue_dst: PPE queue destination configuration ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h -@@ -291,6 +291,11 @@ int ppe_hw_config(struct ppe_device *ppe - int ppe_queue_scheduler_set(struct ppe_device *ppe_dev, - int node_id, bool flow_level, int port, - struct ppe_scheduler_cfg scheduler_cfg); -+int ppe_queue_scheduler_get(struct ppe_device *ppe_dev, -+ int node_id, bool flow_level, int *port, -+ struct ppe_scheduler_cfg *scheduler_cfg); -+int ppe_queue_priority_set(struct ppe_device *ppe_dev, -+ int queue_id, int priority); - int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev, - struct ppe_queue_ucast_dest queue_dst, - int queue_base, diff --git a/target/linux/qualcommbe/patches-6.12/0338-net-ethernet-qualcomm-Add-phylink-support-for-PPE-MA.patch b/target/linux/qualcommbe/patches-6.12/0338-net-ethernet-qualcomm-Add-phylink-support-for-PPE-MA.patch deleted file mode 100644 index 05b18e820d..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0338-net-ethernet-qualcomm-Add-phylink-support-for-PPE-MA.patch +++ /dev/null @@ -1,1040 +0,0 @@ -From dbb3711ab25ea410ad5286b2f39dccd954cda225 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Thu, 29 Feb 2024 16:59:53 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add phylink support for PPE MAC - ports - -Add MAC initialization and phylink functions for PPE MAC ports. - -Change-Id: I39dcba671732392bcfa2e734473fd083989bfbec -Signed-off-by: Lei Wei ---- - drivers/net/ethernet/qualcomm/Kconfig | 3 + - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/ppe.c | 9 + - drivers/net/ethernet/qualcomm/ppe/ppe.h | 2 + - drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 728 +++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 76 ++ - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 124 ++++ - 7 files changed, 943 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_port.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/ppe_port.h - ---- a/drivers/net/ethernet/qualcomm/Kconfig -+++ b/drivers/net/ethernet/qualcomm/Kconfig -@@ -66,6 +66,9 @@ config QCOM_PPE - depends on HAS_IOMEM && OF - depends on COMMON_CLK - select REGMAP_MMIO -+ select PHYLINK -+ select PCS_QCOM_IPQ_UNIPHY -+ select SFP - help - This driver supports the Qualcomm Technologies, Inc. packet - process engine (PPE) available with IPQ SoC. The PPE includes ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -4,4 +4,4 @@ - # - - obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o --qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o -+qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c -@@ -17,6 +17,7 @@ - #include "ppe.h" - #include "ppe_config.h" - #include "ppe_debugfs.h" -+#include "ppe_port.h" - - #define PPE_PORT_MAX 8 - #define PPE_CLK_RATE 353000000 -@@ -200,6 +201,11 @@ static int qcom_ppe_probe(struct platfor - if (ret) - return dev_err_probe(dev, ret, "PPE HW config failed\n"); - -+ ret = ppe_port_mac_init(ppe_dev); -+ if (ret) -+ return dev_err_probe(dev, ret, -+ "PPE Port MAC initialization failed\n"); -+ - ppe_debugfs_setup(ppe_dev); - platform_set_drvdata(pdev, ppe_dev); - -@@ -212,6 +218,9 @@ static void qcom_ppe_remove(struct platf - - ppe_dev = platform_get_drvdata(pdev); - ppe_debugfs_teardown(ppe_dev); -+ ppe_port_mac_deinit(ppe_dev); -+ -+ platform_set_drvdata(pdev, NULL); - } - - static const struct of_device_id qcom_ppe_of_match[] = { ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h -@@ -20,6 +20,7 @@ struct dentry; - * @clk_rate: PPE clock rate. - * @num_ports: Number of PPE ports. - * @debugfs_root: Debugfs root entry. -+ * @ports: PPE MAC ports. - * @num_icc_paths: Number of interconnect paths. - * @icc_paths: Interconnect path array. - * -@@ -33,6 +34,7 @@ struct ppe_device { - unsigned long clk_rate; - unsigned int num_ports; - struct dentry *debugfs_root; -+ struct ppe_ports *ports; - unsigned int num_icc_paths; - struct icc_bulk_data icc_paths[] __counted_by(num_icc_paths); - }; ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -@@ -0,0 +1,728 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* PPE Port MAC initialization and PPE port MAC functions. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ppe.h" -+#include "ppe_port.h" -+#include "ppe_regs.h" -+ -+/* PPE MAC max frame size which including 4bytes FCS */ -+#define PPE_PORT_MAC_MAX_FRAME_SIZE 0x3000 -+ -+/* PPE BM port start for PPE MAC ports */ -+#define PPE_BM_PORT_MAC_START 7 -+ -+/* PPE port clock and reset name */ -+static const char * const ppe_port_clk_rst_name[] = { -+ [PPE_PORT_CLK_RST_MAC] = "mac", -+ [PPE_PORT_CLK_RST_RX] = "rx", -+ [PPE_PORT_CLK_RST_TX] = "tx", -+}; -+ -+/* PPE port and MAC reset */ -+static int ppe_port_mac_reset(struct ppe_port *ppe_port) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret; -+ -+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]); -+ if (ret) -+ goto error; -+ -+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_RX]); -+ if (ret) -+ goto error; -+ -+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_TX]); -+ if (ret) -+ goto error; -+ -+ /* 150ms delay is required by hardware to reset PPE port and MAC */ -+ msleep(150); -+ -+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]); -+ if (ret) -+ goto error; -+ -+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_RX]); -+ if (ret) -+ goto error; -+ -+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_TX]); -+ if (ret) -+ goto error; -+ -+ return ret; -+ -+error: -+ dev_err(ppe_dev->dev, "%s: port %d reset fail %d\n", -+ __func__, ppe_port->port_id, ret); -+ return ret; -+} -+ -+/* PPE port MAC configuration for phylink */ -+static void ppe_port_mac_config(struct phylink_config *config, -+ unsigned int mode, -+ const struct phylink_link_state *state) -+{ -+ struct ppe_port *ppe_port = container_of(config, struct ppe_port, -+ phylink_config); -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int port = ppe_port->port_id; -+ enum ppe_mac_type mac_type; -+ u32 val, mask; -+ int ret; -+ -+ switch (state->interface) { -+ case PHY_INTERFACE_MODE_2500BASEX: -+ case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10GBASER: -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ mac_type = PPE_MAC_TYPE_XGMAC; -+ break; -+ case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ mac_type = PPE_MAC_TYPE_GMAC; -+ break; -+ default: -+ dev_err(ppe_dev->dev, "%s: Unsupport interface %s\n", -+ __func__, phy_modes(state->interface)); -+ return; -+ } -+ -+ /* Reset Port MAC for GMAC */ -+ if (mac_type == PPE_MAC_TYPE_GMAC) { -+ ret = ppe_port_mac_reset(ppe_port); -+ if (ret) -+ goto err_mac_config; -+ } -+ -+ /* Port mux to select GMAC or XGMAC */ -+ mask = PPE_PORT_SEL_XGMAC(port); -+ val = mac_type == PPE_MAC_TYPE_GMAC ? 0 : mask; -+ ret = regmap_update_bits(ppe_dev->regmap, -+ PPE_PORT_MUX_CTRL_ADDR, -+ mask, val); -+ if (ret) -+ goto err_mac_config; -+ -+ ppe_port->mac_type = mac_type; -+ -+ return; -+ -+err_mac_config: -+ dev_err(ppe_dev->dev, "%s: port %d MAC config fail %d\n", -+ __func__, port, ret); -+} -+ -+/* PPE port GMAC link up configuration */ -+static int ppe_port_gmac_link_up(struct ppe_port *ppe_port, int speed, -+ int duplex, bool tx_pause, bool rx_pause) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 reg, val; -+ -+ /* Set GMAC speed */ -+ switch (speed) { -+ case SPEED_1000: -+ val = GMAC_SPEED_1000; -+ break; -+ case SPEED_100: -+ val = GMAC_SPEED_100; -+ break; -+ case SPEED_10: -+ val = GMAC_SPEED_10; -+ break; -+ default: -+ dev_err(ppe_dev->dev, "%s: Invalid GMAC speed %s\n", -+ __func__, phy_speed_to_str(speed)); -+ return -EINVAL; -+ } -+ -+ reg = PPE_PORT_GMAC_ADDR(port); -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_SPEED_ADDR, -+ GMAC_SPEED_M, val); -+ if (ret) -+ return ret; -+ -+ /* Set duplex, flow control and enable GMAC */ -+ val = GMAC_TRXEN; -+ if (duplex == DUPLEX_FULL) -+ val |= GMAC_DUPLEX_FULL; -+ if (tx_pause) -+ val |= GMAC_TXFCEN; -+ if (rx_pause) -+ val |= GMAC_RXFCEN; -+ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_ENABLE_ADDR, -+ GMAC_ENABLE_ALL, val); -+ -+ return ret; -+} -+ -+/* PPE port XGMAC link up configuration */ -+static int ppe_port_xgmac_link_up(struct ppe_port *ppe_port, -+ phy_interface_t interface, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 reg, val; -+ -+ /* Set XGMAC TX speed and enable TX */ -+ switch (speed) { -+ case SPEED_10000: -+ if (interface == PHY_INTERFACE_MODE_USXGMII) -+ val = XGMAC_SPEED_10000_USXGMII; -+ else -+ val = XGMAC_SPEED_10000; -+ break; -+ case SPEED_5000: -+ val = XGMAC_SPEED_5000; -+ break; -+ case SPEED_2500: -+ if (interface == PHY_INTERFACE_MODE_USXGMII || -+ interface == PHY_INTERFACE_MODE_10G_QXGMII) -+ val = XGMAC_SPEED_2500_USXGMII; -+ else -+ val = XGMAC_SPEED_2500; -+ break; -+ case SPEED_1000: -+ val = XGMAC_SPEED_1000; -+ break; -+ case SPEED_100: -+ val = XGMAC_SPEED_100; -+ break; -+ case SPEED_10: -+ val = XGMAC_SPEED_10; -+ break; -+ default: -+ dev_err(ppe_dev->dev, "%s: Invalid XGMAC speed %s\n", -+ __func__, phy_speed_to_str(speed)); -+ return -EINVAL; -+ } -+ -+ reg = PPE_PORT_XGMAC_ADDR(port); -+ val |= XGMAC_TXEN; -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_TX_CONFIG_ADDR, -+ XGMAC_SPEED_M | XGMAC_TXEN, val); -+ if (ret) -+ return ret; -+ -+ /* Set XGMAC TX flow control */ -+ val = FIELD_PREP(XGMAC_PAUSE_TIME_M, FIELD_MAX(XGMAC_PAUSE_TIME_M)); -+ val |= tx_pause ? XGMAC_TXFCEN : 0; -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_TX_FLOW_CTRL_ADDR, -+ XGMAC_PAUSE_TIME_M | XGMAC_TXFCEN, val); -+ if (ret) -+ return ret; -+ -+ /* Set XGMAC RX flow control */ -+ val = rx_pause ? XGMAC_RXFCEN : 0; -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_RX_FLOW_CTRL_ADDR, -+ XGMAC_RXFCEN, val); -+ if (ret) -+ return ret; -+ -+ /* Enable XGMAC RX*/ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_RX_CONFIG_ADDR, -+ XGMAC_RXEN, XGMAC_RXEN); -+ -+ return ret; -+} -+ -+/* PPE port MAC link up configuration for phylink */ -+static void ppe_port_mac_link_up(struct phylink_config *config, -+ struct phy_device *phy, -+ unsigned int mode, -+ phy_interface_t interface, -+ int speed, int duplex, -+ bool tx_pause, bool rx_pause) -+{ -+ struct ppe_port *ppe_port = container_of(config, struct ppe_port, -+ phylink_config); -+ enum ppe_mac_type mac_type = ppe_port->mac_type; -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 reg, val; -+ -+ if (mac_type == PPE_MAC_TYPE_GMAC) -+ ret = ppe_port_gmac_link_up(ppe_port, -+ speed, duplex, tx_pause, rx_pause); -+ else -+ ret = ppe_port_xgmac_link_up(ppe_port, interface, -+ speed, duplex, tx_pause, rx_pause); -+ if (ret) -+ goto err_port_mac_link_up; -+ -+ /* Set PPE port BM flow control */ -+ reg = PPE_BM_PORT_FC_MODE_ADDR + -+ PPE_BM_PORT_FC_MODE_INC * (port + PPE_BM_PORT_MAC_START); -+ val = tx_pause ? PPE_BM_PORT_FC_MODE_EN : 0; -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_BM_PORT_FC_MODE_EN, val); -+ if (ret) -+ goto err_port_mac_link_up; -+ -+ /* Enable PPE port TX */ -+ reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port; -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_PORT_BRIDGE_TXMAC_EN, -+ PPE_PORT_BRIDGE_TXMAC_EN); -+ if (ret) -+ goto err_port_mac_link_up; -+ -+ return; -+ -+err_port_mac_link_up: -+ dev_err(ppe_dev->dev, "%s: port %d link up fail %d\n", -+ __func__, port, ret); -+} -+ -+/* PPE port MAC link down configuration for phylink */ -+static void ppe_port_mac_link_down(struct phylink_config *config, -+ unsigned int mode, -+ phy_interface_t interface) -+{ -+ struct ppe_port *ppe_port = container_of(config, struct ppe_port, -+ phylink_config); -+ enum ppe_mac_type mac_type = ppe_port->mac_type; -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 reg; -+ -+ /* Disable PPE port TX */ -+ reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port; -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_PORT_BRIDGE_TXMAC_EN, 0); -+ if (ret) -+ goto err_port_mac_link_down; -+ -+ /* Disable PPE MAC */ -+ if (mac_type == PPE_MAC_TYPE_GMAC) { -+ reg = PPE_PORT_GMAC_ADDR(port) + GMAC_ENABLE_ADDR; -+ ret = regmap_update_bits(ppe_dev->regmap, reg, GMAC_TRXEN, 0); -+ if (ret) -+ goto err_port_mac_link_down; -+ } else { -+ reg = PPE_PORT_XGMAC_ADDR(port); -+ ret = regmap_update_bits(ppe_dev->regmap, -+ reg + XGMAC_RX_CONFIG_ADDR, -+ XGMAC_RXEN, 0); -+ if (ret) -+ goto err_port_mac_link_down; -+ -+ ret = regmap_update_bits(ppe_dev->regmap, -+ reg + XGMAC_TX_CONFIG_ADDR, -+ XGMAC_TXEN, 0); -+ if (ret) -+ goto err_port_mac_link_down; -+ } -+ -+ return; -+ -+err_port_mac_link_down: -+ dev_err(ppe_dev->dev, "%s: port %d link down fail %d\n", -+ __func__, port, ret); -+} -+ -+/* PPE port MAC PCS selection for phylink */ -+static -+struct phylink_pcs *ppe_port_mac_select_pcs(struct phylink_config *config, -+ phy_interface_t interface) -+{ -+ struct ppe_port *ppe_port = container_of(config, struct ppe_port, -+ phylink_config); -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 val; -+ -+ /* PPE port5 can connects with PCS0 or PCS1. In PSGMII -+ * mode, it selects PCS0; otherwise, it selects PCS1. -+ */ -+ if (port == 5) { -+ val = interface == PHY_INTERFACE_MODE_PSGMII ? -+ 0 : PPE_PORT5_SEL_PCS1; -+ ret = regmap_update_bits(ppe_dev->regmap, -+ PPE_PORT_MUX_CTRL_ADDR, -+ PPE_PORT5_SEL_PCS1, val); -+ if (ret) { -+ dev_err(ppe_dev->dev, "%s: port5 select PCS fail %d\n", -+ __func__, ret); -+ return NULL; -+ } -+ } -+ -+ return ppe_port->pcs; -+} -+ -+static const struct phylink_mac_ops ppe_phylink_ops = { -+ .mac_config = ppe_port_mac_config, -+ .mac_link_up = ppe_port_mac_link_up, -+ .mac_link_down = ppe_port_mac_link_down, -+ .mac_select_pcs = ppe_port_mac_select_pcs, -+}; -+ -+/** -+ * ppe_port_phylink_setup() - Set phylink instance for the given PPE port -+ * @ppe_port: PPE port -+ * @netdev: Netdevice -+ * -+ * Description: Wrapper function to help setup phylink for the PPE port -+ * specified by @ppe_port and associated with the net device @netdev. -+ * -+ * Return: 0 upon success or a negative error upon failure. -+ */ -+int ppe_port_phylink_setup(struct ppe_port *ppe_port, struct net_device *netdev) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ struct device_node *pcs_node; -+ int ret; -+ -+ /* Create PCS */ -+ pcs_node = of_parse_phandle(ppe_port->np, "pcs-handle", 0); -+ if (!pcs_node) -+ return -ENODEV; -+ -+ ppe_port->pcs = ipq_pcs_get(pcs_node); -+ of_node_put(pcs_node); -+ if (IS_ERR(ppe_port->pcs)) { -+ dev_err(ppe_dev->dev, "%s: port %d failed to create PCS\n", -+ __func__, ppe_port->port_id); -+ return PTR_ERR(ppe_port->pcs); -+ } -+ -+ /* Port phylink capability */ -+ ppe_port->phylink_config.dev = &netdev->dev; -+ ppe_port->phylink_config.type = PHYLINK_NETDEV; -+ ppe_port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | -+ MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 | -+ MAC_2500FD | MAC_5000FD | MAC_10000FD; -+ __set_bit(PHY_INTERFACE_MODE_QSGMII, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_PSGMII, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_SGMII, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_USXGMII, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_10GBASER, -+ ppe_port->phylink_config.supported_interfaces); -+ __set_bit(PHY_INTERFACE_MODE_10G_QXGMII, -+ ppe_port->phylink_config.supported_interfaces); -+ -+ /* Create phylink */ -+ ppe_port->phylink = phylink_create(&ppe_port->phylink_config, -+ of_fwnode_handle(ppe_port->np), -+ ppe_port->interface, -+ &ppe_phylink_ops); -+ if (IS_ERR(ppe_port->phylink)) { -+ dev_err(ppe_dev->dev, "%s: port %d failed to create phylink\n", -+ __func__, ppe_port->port_id); -+ ret = PTR_ERR(ppe_port->phylink); -+ goto err_free_pcs; -+ } -+ -+ /* Connect phylink */ -+ ret = phylink_of_phy_connect(ppe_port->phylink, ppe_port->np, 0); -+ if (ret) { -+ dev_err(ppe_dev->dev, "%s: port %d failed to connect phylink\n", -+ __func__, ppe_port->port_id); -+ goto err_free_phylink; -+ } -+ -+ return 0; -+ -+err_free_phylink: -+ phylink_destroy(ppe_port->phylink); -+ ppe_port->phylink = NULL; -+err_free_pcs: -+ ipq_pcs_put(ppe_port->pcs); -+ ppe_port->pcs = NULL; -+ return ret; -+} -+ -+/** -+ * ppe_port_phylink_destroy() - Destroy phylink instance for the given PPE port -+ * @ppe_port: PPE port -+ * -+ * Description: Wrapper function to help destroy phylink for the PPE port -+ * specified by @ppe_port. -+ */ -+void ppe_port_phylink_destroy(struct ppe_port *ppe_port) -+{ -+ /* Destroy phylink */ -+ if (ppe_port->phylink) { -+ rtnl_lock(); -+ phylink_disconnect_phy(ppe_port->phylink); -+ rtnl_unlock(); -+ phylink_destroy(ppe_port->phylink); -+ ppe_port->phylink = NULL; -+ } -+ -+ /* Destroy PCS */ -+ if (ppe_port->pcs) { -+ ipq_pcs_put(ppe_port->pcs); -+ ppe_port->pcs = NULL; -+ } -+} -+ -+/* PPE port clock initialization */ -+static int ppe_port_clock_init(struct ppe_port *ppe_port) -+{ -+ struct device_node *port_node = ppe_port->np; -+ struct reset_control *rstc; -+ struct clk *clk; -+ int i, j, ret; -+ -+ for (i = 0; i < PPE_PORT_CLK_RST_MAX; i++) { -+ /* Get PPE port resets which will be used to reset PPE -+ * port and MAC. -+ */ -+ rstc = of_reset_control_get_exclusive(port_node, -+ ppe_port_clk_rst_name[i]); -+ if (IS_ERR(rstc)) { -+ ret = PTR_ERR(rstc); -+ goto err_rst; -+ } -+ -+ clk = of_clk_get_by_name(port_node, ppe_port_clk_rst_name[i]); -+ if (IS_ERR(clk)) { -+ ret = PTR_ERR(clk); -+ goto err_clk_get; -+ } -+ -+ ret = clk_prepare_enable(clk); -+ if (ret) -+ goto err_clk_en; -+ -+ ppe_port->clks[i] = clk; -+ ppe_port->rstcs[i] = rstc; -+ } -+ -+ return 0; -+ -+err_clk_en: -+ clk_put(clk); -+err_clk_get: -+ reset_control_put(rstc); -+err_rst: -+ for (j = 0; j < i; j++) { -+ clk_disable_unprepare(ppe_port->clks[j]); -+ clk_put(ppe_port->clks[j]); -+ reset_control_put(ppe_port->rstcs[j]); -+ } -+ -+ return ret; -+} -+ -+/* PPE port clock deinitialization */ -+static void ppe_port_clock_deinit(struct ppe_port *ppe_port) -+{ -+ int i; -+ -+ for (i = 0; i < PPE_PORT_CLK_RST_MAX; i++) { -+ clk_disable_unprepare(ppe_port->clks[i]); -+ clk_put(ppe_port->clks[i]); -+ reset_control_put(ppe_port->rstcs[i]); -+ } -+} -+ -+/* PPE port MAC hardware init configuration */ -+static int ppe_port_mac_hw_init(struct ppe_port *ppe_port) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int ret, port = ppe_port->port_id; -+ u32 reg, val; -+ -+ /* GMAC RX and TX are initialized as disabled */ -+ reg = PPE_PORT_GMAC_ADDR(port); -+ ret = regmap_update_bits(ppe_dev->regmap, -+ reg + GMAC_ENABLE_ADDR, GMAC_TRXEN, 0); -+ if (ret) -+ return ret; -+ -+ /* GMAC max frame size configuration */ -+ val = FIELD_PREP(GMAC_JUMBO_SIZE_M, PPE_PORT_MAC_MAX_FRAME_SIZE); -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_JUMBO_SIZE_ADDR, -+ GMAC_JUMBO_SIZE_M, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(GMAC_MAXFRAME_SIZE_M, PPE_PORT_MAC_MAX_FRAME_SIZE); -+ val |= FIELD_PREP(GMAC_TX_THD_M, 0x1); -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_CTRL_ADDR, -+ GMAC_CTRL_MASK, val); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(GMAC_HIGH_IPG_M, 0xc); -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_DBG_CTRL_ADDR, -+ GMAC_HIGH_IPG_M, val); -+ if (ret) -+ return ret; -+ -+ /* Enable and reset GMAC MIB counters and set as read clear -+ * mode, the GMAC MIB counters will be cleared after reading. -+ */ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_MIB_CTRL_ADDR, -+ GMAC_MIB_CTRL_MASK, GMAC_MIB_CTRL_MASK); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + GMAC_MIB_CTRL_ADDR, -+ GMAC_MIB_RST, 0); -+ if (ret) -+ return ret; -+ -+ /* XGMAC RX and TX disabled and max frame size configuration */ -+ reg = PPE_PORT_XGMAC_ADDR(port); -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_TX_CONFIG_ADDR, -+ XGMAC_TXEN | XGMAC_JD, XGMAC_JD); -+ if (ret) -+ return ret; -+ -+ val = FIELD_PREP(XGMAC_GPSL_M, PPE_PORT_MAC_MAX_FRAME_SIZE); -+ val |= XGMAC_GPSLEN; -+ val |= XGMAC_CST; -+ val |= XGMAC_ACS; -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_RX_CONFIG_ADDR, -+ XGMAC_RX_CONFIG_MASK, val); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_WD_TIMEOUT_ADDR, -+ XGMAC_WD_TIMEOUT_MASK, XGMAC_WD_TIMEOUT_VAL); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_PKT_FILTER_ADDR, -+ XGMAC_PKT_FILTER_MASK, XGMAC_PKT_FILTER_VAL); -+ if (ret) -+ return ret; -+ -+ /* Enable and reset XGMAC MIB counters */ -+ ret = regmap_update_bits(ppe_dev->regmap, reg + XGMAC_MMC_CTRL_ADDR, -+ XGMAC_MCF | XGMAC_CNTRST, XGMAC_CNTRST); -+ -+ return ret; -+} -+ -+/** -+ * ppe_port_mac_init() - Initialization of PPE ports for the PPE device -+ * @ppe_dev: PPE device -+ * -+ * Description: Initialize the PPE MAC ports on the PPE device specified -+ * by @ppe_dev. -+ * -+ * Return: 0 upon success or a negative error upon failure. -+ */ -+int ppe_port_mac_init(struct ppe_device *ppe_dev) -+{ -+ struct device_node *ports_node, *port_node; -+ int port, num, ret, j, i = 0; -+ struct ppe_ports *ppe_ports; -+ phy_interface_t phy_mode; -+ -+ ports_node = of_get_child_by_name(ppe_dev->dev->of_node, -+ "ethernet-ports"); -+ if (!ports_node) { -+ dev_err(ppe_dev->dev, "Failed to get ports node\n"); -+ return -ENODEV; -+ } -+ -+ num = of_get_available_child_count(ports_node); -+ -+ ppe_ports = devm_kzalloc(ppe_dev->dev, -+ struct_size(ppe_ports, port, num), -+ GFP_KERNEL); -+ if (!ppe_ports) { -+ ret = -ENOMEM; -+ goto err_ports_node; -+ } -+ -+ ppe_dev->ports = ppe_ports; -+ ppe_ports->num = num; -+ -+ for_each_available_child_of_node(ports_node, port_node) { -+ ret = of_property_read_u32(port_node, "reg", &port); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Failed to get port id\n"); -+ goto err_port_node; -+ } -+ -+ ret = of_get_phy_mode(port_node, &phy_mode); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Failed to get phy mode\n"); -+ goto err_port_node; -+ } -+ -+ ppe_ports->port[i].ppe_dev = ppe_dev; -+ ppe_ports->port[i].port_id = port; -+ ppe_ports->port[i].np = port_node; -+ ppe_ports->port[i].interface = phy_mode; -+ -+ ret = ppe_port_clock_init(&ppe_ports->port[i]); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Failed to initialize port clocks\n"); -+ goto err_port_clk; -+ } -+ -+ ret = ppe_port_mac_hw_init(&ppe_ports->port[i]); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Failed to initialize MAC hardware\n"); -+ goto err_port_node; -+ } -+ -+ i++; -+ } -+ -+ of_node_put(ports_node); -+ return 0; -+ -+err_port_clk: -+ for (j = 0; j < i; j++) -+ ppe_port_clock_deinit(&ppe_ports->port[j]); -+err_port_node: -+ of_node_put(port_node); -+err_ports_node: -+ of_node_put(ports_node); -+ return ret; -+} -+ -+/** -+ * ppe_port_mac_deinit() - Deinitialization of PPE ports for the PPE device -+ * @ppe_dev: PPE device -+ * -+ * Description: Deinitialize the PPE MAC ports on the PPE device specified -+ * by @ppe_dev. -+ */ -+void ppe_port_mac_deinit(struct ppe_device *ppe_dev) -+{ -+ struct ppe_port *ppe_port; -+ int i; -+ -+ for (i = 0; i < ppe_dev->ports->num; i++) { -+ ppe_port = &ppe_dev->ports->port[i]; -+ ppe_port_clock_deinit(ppe_port); -+ } -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -@@ -0,0 +1,76 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __PPE_PORT_H__ -+#define __PPE_PORT_H__ -+ -+#include -+ -+/** -+ * enum ppe_port_clk_rst_type - PPE port clock and reset ID type -+ * @PPE_PORT_CLK_RST_MAC: The clock and reset ID for port MAC -+ * @PPE_PORT_CLK_RST_RX: The clock and reset ID for port receive path -+ * @PPE_PORT_CLK_RST_TX: The clock and reset for port transmit path -+ * @PPE_PORT_CLK_RST_MAX: The maximum of port clock and reset -+ */ -+enum ppe_port_clk_rst_type { -+ PPE_PORT_CLK_RST_MAC, -+ PPE_PORT_CLK_RST_RX, -+ PPE_PORT_CLK_RST_TX, -+ PPE_PORT_CLK_RST_MAX, -+}; -+ -+/** -+ * enum ppe_mac_type - PPE MAC type -+ * @PPE_MAC_TYPE_GMAC: GMAC type -+ * @PPE_MAC_TYPE_XGMAC: XGMAC type -+ */ -+enum ppe_mac_type { -+ PPE_MAC_TYPE_GMAC, -+ PPE_MAC_TYPE_XGMAC, -+}; -+ -+/** -+ * struct ppe_port - Private data for each PPE port -+ * @phylink: Linux phylink instance -+ * @phylink_config: Linux phylink configurations -+ * @pcs: Linux phylink PCS instance -+ * @np: Port device tree node -+ * @ppe_dev: Back pointer to PPE device private data -+ * @interface: Port interface mode -+ * @mac_type: Port MAC type, GMAC or XGMAC -+ * @port_id: Port ID -+ * @clks: Port clocks -+ * @rstcs: Port resets -+ */ -+struct ppe_port { -+ struct phylink *phylink; -+ struct phylink_config phylink_config; -+ struct phylink_pcs *pcs; -+ struct device_node *np; -+ struct ppe_device *ppe_dev; -+ phy_interface_t interface; -+ enum ppe_mac_type mac_type; -+ int port_id; -+ struct clk *clks[PPE_PORT_CLK_RST_MAX]; -+ struct reset_control *rstcs[PPE_PORT_CLK_RST_MAX]; -+}; -+ -+/** -+ * struct ppe_ports - Array of PPE ports -+ * @num: Number of PPE ports -+ * @port: Each PPE port private data -+ */ -+struct ppe_ports { -+ unsigned int num; -+ struct ppe_port port[] __counted_by(num); -+}; -+ -+int ppe_port_mac_init(struct ppe_device *ppe_dev); -+void ppe_port_mac_deinit(struct ppe_device *ppe_dev); -+int ppe_port_phylink_setup(struct ppe_port *ppe_port, -+ struct net_device *netdev); -+void ppe_port_phylink_destroy(struct ppe_port *ppe_port); -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -9,6 +9,17 @@ - - #include - -+/* PPE port mux select control register */ -+#define PPE_PORT_MUX_CTRL_ADDR 0x10 -+#define PPE_PORT6_SEL_XGMAC BIT(13) -+#define PPE_PORT5_SEL_XGMAC BIT(12) -+#define PPE_PORT4_SEL_XGMAC BIT(11) -+#define PPE_PORT3_SEL_XGMAC BIT(10) -+#define PPE_PORT2_SEL_XGMAC BIT(9) -+#define PPE_PORT1_SEL_XGMAC BIT(8) -+#define PPE_PORT5_SEL_PCS1 BIT(4) -+#define PPE_PORT_SEL_XGMAC(x) (BIT(8) << ((x) - 1)) -+ - /* PPE scheduler configurations for buffer manager block. */ - #define PPE_BM_SCH_CTRL_ADDR 0xb000 - #define PPE_BM_SCH_CTRL_INC 4 -@@ -556,4 +567,117 @@ - #define PPE_ENQ_OPR_TBL_ENTRIES 300 - #define PPE_ENQ_OPR_TBL_INC 0x10 - #define PPE_ENQ_OPR_TBL_ENQ_DISABLE BIT(0) -+ -+/* PPE GMAC and XGMAC register base address */ -+#define PPE_PORT_GMAC_ADDR(x) (0x001000 + ((x) - 1) * 0x200) -+#define PPE_PORT_XGMAC_ADDR(x) (0x500000 + ((x) - 1) * 0x4000) -+ -+/* GMAC enable register */ -+#define GMAC_ENABLE_ADDR 0x0 -+#define GMAC_TXFCEN BIT(6) -+#define GMAC_RXFCEN BIT(5) -+#define GMAC_DUPLEX_FULL BIT(4) -+#define GMAC_TXEN BIT(1) -+#define GMAC_RXEN BIT(0) -+ -+#define GMAC_TRXEN \ -+ (GMAC_TXEN | GMAC_RXEN) -+#define GMAC_ENABLE_ALL \ -+ (GMAC_TXFCEN | GMAC_RXFCEN | GMAC_DUPLEX_FULL | GMAC_TXEN | GMAC_RXEN) -+ -+/* GMAC speed register */ -+#define GMAC_SPEED_ADDR 0x4 -+#define GMAC_SPEED_M GENMASK(1, 0) -+#define GMAC_SPEED_10 0 -+#define GMAC_SPEED_100 1 -+#define GMAC_SPEED_1000 2 -+ -+/* GMAC control register */ -+#define GMAC_CTRL_ADDR 0x18 -+#define GMAC_TX_THD_M GENMASK(27, 24) -+#define GMAC_MAXFRAME_SIZE_M GENMASK(21, 8) -+#define GMAC_CRS_SEL BIT(6) -+ -+#define GMAC_CTRL_MASK \ -+ (GMAC_TX_THD_M | GMAC_MAXFRAME_SIZE_M | GMAC_CRS_SEL) -+ -+/* GMAC debug control register */ -+#define GMAC_DBG_CTRL_ADDR 0x1c -+#define GMAC_HIGH_IPG_M GENMASK(15, 8) -+ -+/* GMAC jumbo size register */ -+#define GMAC_JUMBO_SIZE_ADDR 0x30 -+#define GMAC_JUMBO_SIZE_M GENMASK(13, 0) -+ -+/* GMAC MIB control register */ -+#define GMAC_MIB_CTRL_ADDR 0x34 -+#define GMAC_MIB_RD_CLR BIT(2) -+#define GMAC_MIB_RST BIT(1) -+#define GMAC_MIB_EN BIT(0) -+ -+#define GMAC_MIB_CTRL_MASK \ -+ (GMAC_MIB_RD_CLR | GMAC_MIB_RST | GMAC_MIB_EN) -+ -+/* XGMAC TX configuration register */ -+#define XGMAC_TX_CONFIG_ADDR 0x0 -+#define XGMAC_SPEED_M GENMASK(31, 29) -+#define XGMAC_SPEED_10000_USXGMII FIELD_PREP(XGMAC_SPEED_M, 4) -+#define XGMAC_SPEED_10000 FIELD_PREP(XGMAC_SPEED_M, 0) -+#define XGMAC_SPEED_5000 FIELD_PREP(XGMAC_SPEED_M, 5) -+#define XGMAC_SPEED_2500_USXGMII FIELD_PREP(XGMAC_SPEED_M, 6) -+#define XGMAC_SPEED_2500 FIELD_PREP(XGMAC_SPEED_M, 2) -+#define XGMAC_SPEED_1000 FIELD_PREP(XGMAC_SPEED_M, 3) -+#define XGMAC_SPEED_100 XGMAC_SPEED_1000 -+#define XGMAC_SPEED_10 XGMAC_SPEED_1000 -+#define XGMAC_JD BIT(16) -+#define XGMAC_TXEN BIT(0) -+ -+/* XGMAC RX configuration register */ -+#define XGMAC_RX_CONFIG_ADDR 0x4 -+#define XGMAC_GPSL_M GENMASK(29, 16) -+#define XGMAC_WD BIT(7) -+#define XGMAC_GPSLEN BIT(6) -+#define XGMAC_CST BIT(2) -+#define XGMAC_ACS BIT(1) -+#define XGMAC_RXEN BIT(0) -+ -+#define XGMAC_RX_CONFIG_MASK \ -+ (XGMAC_GPSL_M | XGMAC_WD | XGMAC_GPSLEN | XGMAC_CST | \ -+ XGMAC_ACS | XGMAC_RXEN) -+ -+/* XGMAC packet filter register */ -+#define XGMAC_PKT_FILTER_ADDR 0x8 -+#define XGMAC_RA BIT(31) -+#define XGMAC_PCF_M GENMASK(7, 6) -+#define XGMAC_PR BIT(0) -+ -+#define XGMAC_PKT_FILTER_MASK \ -+ (XGMAC_RA | XGMAC_PCF_M | XGMAC_PR) -+#define XGMAC_PKT_FILTER_VAL \ -+ (XGMAC_RA | XGMAC_PR | FIELD_PREP(XGMAC_PCF_M, 0x2)) -+ -+/* XGMAC watchdog timeout register */ -+#define XGMAC_WD_TIMEOUT_ADDR 0xc -+#define XGMAC_PWE BIT(8) -+#define XGMAC_WTO_M GENMASK(3, 0) -+ -+#define XGMAC_WD_TIMEOUT_MASK \ -+ (XGMAC_PWE | XGMAC_WTO_M) -+#define XGMAC_WD_TIMEOUT_VAL \ -+ (XGMAC_PWE | FIELD_PREP(XGMAC_WTO_M, 0xb)) -+ -+/* XGMAC TX flow control register */ -+#define XGMAC_TX_FLOW_CTRL_ADDR 0x70 -+#define XGMAC_PAUSE_TIME_M GENMASK(31, 16) -+#define XGMAC_TXFCEN BIT(1) -+ -+/* XGMAC RX flow control register */ -+#define XGMAC_RX_FLOW_CTRL_ADDR 0x90 -+#define XGMAC_RXFCEN BIT(0) -+ -+/* XGMAC management counters control register */ -+#define XGMAC_MMC_CTRL_ADDR 0x800 -+#define XGMAC_MCF BIT(3) -+#define XGMAC_CNTRST BIT(0) -+ - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0339-net-ethernet-qualcomm-Add-PPE-port-MAC-MIB-statistic.patch b/target/linux/qualcommbe/patches-6.12/0339-net-ethernet-qualcomm-Add-PPE-port-MAC-MIB-statistic.patch deleted file mode 100644 index 1430692a6f..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0339-net-ethernet-qualcomm-Add-PPE-port-MAC-MIB-statistic.patch +++ /dev/null @@ -1,673 +0,0 @@ -From dbcc0d01241a1353d8e11e764cf7fcd390ae3f1f Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Thu, 29 Feb 2024 20:16:14 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add PPE port MAC MIB statistics - functions - -Add PPE port MAC MIB statistics functions which are used by netdev -ops and ethtool. For GMAC, a polling task is scheduled to read the -MIB counters periodically to avoid 32bit register counter overflow. - -Change-Id: Ic20e240061278f77d703f652e1f7d959db8fac37 -Signed-off-by: Lei Wei ---- - drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 465 +++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 13 + - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 91 ++++ - 3 files changed, 569 insertions(+) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -@@ -23,6 +23,122 @@ - /* PPE BM port start for PPE MAC ports */ - #define PPE_BM_PORT_MAC_START 7 - -+/* Poll interval time to poll GMAC MIBs for overflow protection, -+ * the time should ensure that the 32bit GMAC packet counter -+ * register would not overflow within this time at line rate -+ * speed for 64B packet size. -+ */ -+#define PPE_GMIB_POLL_INTERVAL_MS 120000 -+ -+#define PPE_MAC_MIB_DESC(_s, _o, _n) \ -+ { \ -+ .size = (_s), \ -+ .offset = (_o), \ -+ .name = (_n), \ -+ } -+ -+/* PPE MAC MIB description */ -+struct ppe_mac_mib_info { -+ u32 size; -+ u32 offset; -+ const char *name; -+}; -+ -+/* PPE GMAC MIB statistics type */ -+enum ppe_gmib_stats_type { -+ gmib_rx_broadcast, -+ gmib_rx_pause, -+ gmib_rx_multicast, -+ gmib_rx_fcserr, -+ gmib_rx_alignerr, -+ gmib_rx_runt, -+ gmib_rx_frag, -+ gmib_rx_jumbofcserr, -+ gmib_rx_jumboalignerr, -+ gmib_rx_pkt64, -+ gmib_rx_pkt65to127, -+ gmib_rx_pkt128to255, -+ gmib_rx_pkt256to511, -+ gmib_rx_pkt512to1023, -+ gmib_rx_pkt1024to1518, -+ gmib_rx_pkt1519tomax, -+ gmib_rx_toolong, -+ gmib_rx_bytes_g, -+ gmib_rx_bytes_b, -+ gmib_rx_unicast, -+ gmib_tx_broadcast, -+ gmib_tx_pause, -+ gmib_tx_multicast, -+ gmib_tx_underrun, -+ gmib_tx_pkt64, -+ gmib_tx_pkt65to127, -+ gmib_tx_pkt128to255, -+ gmib_tx_pkt256to511, -+ gmib_tx_pkt512to1023, -+ gmib_tx_pkt1024to1518, -+ gmib_tx_pkt1519tomax, -+ gmib_tx_bytes, -+ gmib_tx_collisions, -+ gmib_tx_abortcol, -+ gmib_tx_multicol, -+ gmib_tx_singlecol, -+ gmib_tx_excdeffer, -+ gmib_tx_deffer, -+ gmib_tx_latecol, -+ gmib_tx_unicast, -+}; -+ -+/* PPE XGMAC MIB statistics type */ -+enum ppe_xgmib_stats_type { -+ xgmib_tx_bytes, -+ xgmib_tx_frames, -+ xgmib_tx_broadcast_g, -+ xgmib_tx_multicast_g, -+ xgmib_tx_pkt64, -+ xgmib_tx_pkt65to127, -+ xgmib_tx_pkt128to255, -+ xgmib_tx_pkt256to511, -+ xgmib_tx_pkt512to1023, -+ xgmib_tx_pkt1024tomax, -+ xgmib_tx_unicast, -+ xgmib_tx_multicast, -+ xgmib_tx_broadcast, -+ xgmib_tx_underflow_err, -+ xgmib_tx_bytes_g, -+ xgmib_tx_frames_g, -+ xgmib_tx_pause, -+ xgmib_tx_vlan_g, -+ xgmib_tx_lpi_usec, -+ xgmib_tx_lpi_tran, -+ xgmib_rx_frames, -+ xgmib_rx_bytes, -+ xgmib_rx_bytes_g, -+ xgmib_rx_broadcast_g, -+ xgmib_rx_multicast_g, -+ xgmib_rx_crc_err, -+ xgmib_rx_runt_err, -+ xgmib_rx_jabber_err, -+ xgmib_rx_undersize_g, -+ xgmib_rx_oversize_g, -+ xgmib_rx_pkt64, -+ xgmib_rx_pkt65to127, -+ xgmib_rx_pkt128to255, -+ xgmib_rx_pkt256to511, -+ xgmib_rx_pkt512to1023, -+ xgmib_rx_pkt1024tomax, -+ xgmib_rx_unicast_g, -+ xgmib_rx_len_err, -+ xgmib_rx_outofrange_err, -+ xgmib_rx_pause, -+ xgmib_rx_fifo_overflow, -+ xgmib_rx_vlan, -+ xgmib_rx_wdog_err, -+ xgmib_rx_lpi_usec, -+ xgmib_rx_lpi_tran, -+ xgmib_rx_drop_frames, -+ xgmib_rx_drop_bytes, -+}; -+ - /* PPE port clock and reset name */ - static const char * const ppe_port_clk_rst_name[] = { - [PPE_PORT_CLK_RST_MAC] = "port_mac", -@@ -30,6 +146,322 @@ static const char * const ppe_port_clk_r - [PPE_PORT_CLK_RST_TX] = "port_tx", - }; - -+/* PPE GMAC MIB statistics description information */ -+static const struct ppe_mac_mib_info gmib_info[] = { -+ PPE_MAC_MIB_DESC(4, GMAC_RXBROAD_ADDR, "rx_broadcast"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPAUSE_ADDR, "rx_pause"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXMULTI_ADDR, "rx_multicast"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXFCSERR_ADDR, "rx_fcserr"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXALIGNERR_ADDR, "rx_alignerr"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXRUNT_ADDR, "rx_runt"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXFRAG_ADDR, "rx_frag"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXJUMBOFCSERR_ADDR, "rx_jumbofcserr"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXJUMBOALIGNERR_ADDR, "rx_jumboalignerr"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT64_ADDR, "rx_pkt64"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT65TO127_ADDR, "rx_pkt65to127"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT128TO255_ADDR, "rx_pkt128to255"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT256TO511_ADDR, "rx_pkt256to511"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT512TO1023_ADDR, "rx_pkt512to1023"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT1024TO1518_ADDR, "rx_pkt1024to1518"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXPKT1519TOX_ADDR, "rx_pkt1519tomax"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXTOOLONG_ADDR, "rx_toolong"), -+ PPE_MAC_MIB_DESC(8, GMAC_RXBYTE_G_ADDR, "rx_bytes_g"), -+ PPE_MAC_MIB_DESC(8, GMAC_RXBYTE_B_ADDR, "rx_bytes_b"), -+ PPE_MAC_MIB_DESC(4, GMAC_RXUNI_ADDR, "rx_unicast"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXBROAD_ADDR, "tx_broadcast"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPAUSE_ADDR, "tx_pause"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXMULTI_ADDR, "tx_multicast"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXUNDERRUN_ADDR, "tx_underrun"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT64_ADDR, "tx_pkt64"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT65TO127_ADDR, "tx_pkt65to127"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT128TO255_ADDR, "tx_pkt128to255"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT256TO511_ADDR, "tx_pkt256to511"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT512TO1023_ADDR, "tx_pkt512to1023"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT1024TO1518_ADDR, "tx_pkt1024to1518"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXPKT1519TOX_ADDR, "tx_pkt1519tomax"), -+ PPE_MAC_MIB_DESC(8, GMAC_TXBYTE_ADDR, "tx_bytes"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXCOLLISIONS_ADDR, "tx_collisions"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXABORTCOL_ADDR, "tx_abortcol"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXMULTICOL_ADDR, "tx_multicol"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXSINGLECOL_ADDR, "tx_singlecol"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXEXCESSIVEDEFER_ADDR, "tx_excdeffer"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXDEFER_ADDR, "tx_deffer"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXLATECOL_ADDR, "tx_latecol"), -+ PPE_MAC_MIB_DESC(4, GMAC_TXUNI_ADDR, "tx_unicast"), -+}; -+ -+/* PPE XGMAC MIB statistics description information */ -+static const struct ppe_mac_mib_info xgmib_info[] = { -+ PPE_MAC_MIB_DESC(8, XGMAC_TXBYTE_GB_ADDR, "tx_bytes"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT_GB_ADDR, "tx_frames"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXBROAD_G_ADDR, "tx_broadcast_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXMULTI_G_ADDR, "tx_multicast_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT64_GB_ADDR, "tx_pkt64"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT65TO127_GB_ADDR, "tx_pkt65to127"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT128TO255_GB_ADDR, "tx_pkt128to255"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT256TO511_GB_ADDR, "tx_pkt256to511"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT512TO1023_GB_ADDR, "tx_pkt512to1023"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT1024TOMAX_GB_ADDR, "tx_pkt1024tomax"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXUNI_GB_ADDR, "tx_unicast"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXMULTI_GB_ADDR, "tx_multicast"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXBROAD_GB_ADDR, "tx_broadcast"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXUNDERFLOW_ERR_ADDR, "tx_underflow_err"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXBYTE_G_ADDR, "tx_bytes_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPKT_G_ADDR, "tx_frames_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXPAUSE_ADDR, "tx_pause"), -+ PPE_MAC_MIB_DESC(8, XGMAC_TXVLAN_G_ADDR, "tx_vlan_g"), -+ PPE_MAC_MIB_DESC(4, XGMAC_TXLPI_USEC_ADDR, "tx_lpi_usec"), -+ PPE_MAC_MIB_DESC(4, XGMAC_TXLPI_TRAN_ADDR, "tx_lpi_tran"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT_GB_ADDR, "rx_frames"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXBYTE_GB_ADDR, "rx_bytes"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXBYTE_G_ADDR, "rx_bytes_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXBROAD_G_ADDR, "rx_broadcast_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXMULTI_G_ADDR, "rx_multicast_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXCRC_ERR_ADDR, "rx_crc_err"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXRUNT_ERR_ADDR, "rx_runt_err"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXJABBER_ERR_ADDR, "rx_jabber_err"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXUNDERSIZE_G_ADDR, "rx_undersize_g"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXOVERSIZE_G_ADDR, "rx_oversize_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT64_GB_ADDR, "rx_pkt64"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT65TO127_GB_ADDR, "rx_pkt65to127"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT128TO255_GB_ADDR, "rx_pkt128to255"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT256TO511_GB_ADDR, "rx_pkt256to511"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT512TO1023_GB_ADDR, "rx_pkt512to1023"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPKT1024TOMAX_GB_ADDR, "rx_pkt1024tomax"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXUNI_G_ADDR, "rx_unicast_g"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXLEN_ERR_ADDR, "rx_len_err"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXOUTOFRANGE_ADDR, "rx_outofrange_err"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXPAUSE_ADDR, "rx_pause"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXFIFOOVERFLOW_ADDR, "rx_fifo_overflow"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXVLAN_GB_ADDR, "rx_vlan"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXWATCHDOG_ERR_ADDR, "rx_wdog_err"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXLPI_USEC_ADDR, "rx_lpi_usec"), -+ PPE_MAC_MIB_DESC(4, XGMAC_RXLPI_TRAN_ADDR, "rx_lpi_tran"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXDISCARD_GB_ADDR, "rx_drop_frames"), -+ PPE_MAC_MIB_DESC(8, XGMAC_RXDISCARDBYTE_GB_ADDR, "rx_drop_bytes"), -+}; -+ -+/* Get GMAC MIBs from registers and accumulate to PPE port GMIB stats array */ -+static void ppe_port_gmib_update(struct ppe_port *ppe_port) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ const struct ppe_mac_mib_info *mib; -+ int port = ppe_port->port_id; -+ u32 reg, val; -+ int i, ret; -+ -+ for (i = 0; i < ARRAY_SIZE(gmib_info); i++) { -+ mib = &gmib_info[i]; -+ reg = PPE_PORT_GMAC_ADDR(port) + mib->offset; -+ -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret); -+ continue; -+ } -+ -+ ppe_port->gmib_stats[i] += val; -+ if (mib->size == 8) { -+ ret = regmap_read(ppe_dev->regmap, reg + 4, &val); -+ if (ret) { -+ dev_warn(ppe_dev->dev, "%s: %d\n", -+ __func__, ret); -+ continue; -+ } -+ -+ ppe_port->gmib_stats[i] += (u64)val << 32; -+ } -+ } -+} -+ -+/* Polling task to read GMIB statistics to avoid GMIB 32bit register overflow */ -+static void ppe_port_gmib_stats_poll(struct work_struct *work) -+{ -+ struct ppe_port *ppe_port = container_of(work, struct ppe_port, -+ gmib_read.work); -+ spin_lock(&ppe_port->gmib_stats_lock); -+ ppe_port_gmib_update(ppe_port); -+ spin_unlock(&ppe_port->gmib_stats_lock); -+ -+ schedule_delayed_work(&ppe_port->gmib_read, -+ msecs_to_jiffies(PPE_GMIB_POLL_INTERVAL_MS)); -+} -+ -+/* Get the XGMAC MIB counter based on the specific MIB stats type */ -+static u64 ppe_port_xgmib_get(struct ppe_port *ppe_port, -+ enum ppe_xgmib_stats_type xgmib_type) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ const struct ppe_mac_mib_info *mib; -+ int port = ppe_port->port_id; -+ u32 reg, val; -+ u64 data = 0; -+ int ret; -+ -+ mib = &xgmib_info[xgmib_type]; -+ reg = PPE_PORT_XGMAC_ADDR(port) + mib->offset; -+ -+ ret = regmap_read(ppe_dev->regmap, reg, &val); -+ if (ret) { -+ dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret); -+ goto data_return; -+ } -+ -+ data = val; -+ if (mib->size == 8) { -+ ret = regmap_read(ppe_dev->regmap, reg + 4, &val); -+ if (ret) { -+ dev_warn(ppe_dev->dev, "%s: %d\n", __func__, ret); -+ goto data_return; -+ } -+ -+ data |= (u64)val << 32; -+ } -+ -+data_return: -+ return data; -+} -+ -+/** -+ * ppe_port_get_sset_count() - Get PPE port statistics string count -+ * @ppe_port: PPE port -+ * @sset: string set ID -+ * -+ * Description: Get the MAC statistics string count for the PPE port -+ * specified by @ppe_port. -+ * -+ * Return: The count of the statistics string. -+ */ -+int ppe_port_get_sset_count(struct ppe_port *ppe_port, int sset) -+{ -+ if (sset != ETH_SS_STATS) -+ return 0; -+ -+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) -+ return ARRAY_SIZE(gmib_info); -+ else -+ return ARRAY_SIZE(xgmib_info); -+} -+ -+/** -+ * ppe_port_get_strings() - Get PPE port statistics strings -+ * @ppe_port: PPE port -+ * @stringset: string set ID -+ * @data: pointer to statistics strings -+ * -+ * Description: Get the MAC statistics stings for the PPE port -+ * specified by @ppe_port. The strings are stored in the buffer -+ * indicated by @data which used in the ethtool ops. -+ */ -+void ppe_port_get_strings(struct ppe_port *ppe_port, u32 stringset, u8 *data) -+{ -+ int i; -+ -+ if (stringset != ETH_SS_STATS) -+ return; -+ -+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) { -+ for (i = 0; i < ARRAY_SIZE(gmib_info); i++) -+ strscpy(data + i * ETH_GSTRING_LEN, gmib_info[i].name, -+ ETH_GSTRING_LEN); -+ } else { -+ for (i = 0; i < ARRAY_SIZE(xgmib_info); i++) -+ strscpy(data + i * ETH_GSTRING_LEN, xgmib_info[i].name, -+ ETH_GSTRING_LEN); -+ } -+} -+ -+/** -+ * ppe_port_get_ethtool_stats() - Get PPE port ethtool statistics -+ * @ppe_port: PPE port -+ * @data: pointer to statistics data -+ * -+ * Description: Get the MAC statistics for the PPE port specified -+ * by @ppe_port. The statistics are stored in the buffer indicated -+ * by @data which used in the ethtool ops. -+ */ -+void ppe_port_get_ethtool_stats(struct ppe_port *ppe_port, u64 *data) -+{ -+ int i; -+ -+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) { -+ spin_lock(&ppe_port->gmib_stats_lock); -+ -+ ppe_port_gmib_update(ppe_port); -+ for (i = 0; i < ARRAY_SIZE(gmib_info); i++) -+ data[i] = ppe_port->gmib_stats[i]; -+ -+ spin_unlock(&ppe_port->gmib_stats_lock); -+ } else { -+ for (i = 0; i < ARRAY_SIZE(xgmib_info); i++) -+ data[i] = ppe_port_xgmib_get(ppe_port, i); -+ } -+} -+ -+/** -+ * ppe_port_get_stats64() - Get PPE port statistics -+ * @ppe_port: PPE port -+ * @s: statistics pointer -+ * -+ * Description: Get the MAC statistics for the PPE port specified -+ * by @ppe_port. -+ */ -+void ppe_port_get_stats64(struct ppe_port *ppe_port, -+ struct rtnl_link_stats64 *s) -+{ -+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) { -+ u64 *src = ppe_port->gmib_stats; -+ -+ spin_lock(&ppe_port->gmib_stats_lock); -+ -+ ppe_port_gmib_update(ppe_port); -+ -+ s->rx_packets = src[gmib_rx_unicast] + -+ src[gmib_rx_broadcast] + src[gmib_rx_multicast]; -+ -+ s->tx_packets = src[gmib_tx_unicast] + -+ src[gmib_tx_broadcast] + src[gmib_tx_multicast]; -+ -+ s->rx_bytes = src[gmib_rx_bytes_g]; -+ s->tx_bytes = src[gmib_tx_bytes]; -+ s->multicast = src[gmib_rx_multicast]; -+ -+ s->rx_crc_errors = src[gmib_rx_fcserr] + src[gmib_rx_frag]; -+ s->rx_frame_errors = src[gmib_rx_alignerr]; -+ s->rx_errors = s->rx_crc_errors + s->rx_frame_errors; -+ s->rx_dropped = src[gmib_rx_toolong] + s->rx_errors; -+ -+ s->tx_fifo_errors = src[gmib_tx_underrun]; -+ s->tx_aborted_errors = src[gmib_tx_abortcol]; -+ s->tx_errors = s->tx_fifo_errors + s->tx_aborted_errors; -+ s->collisions = src[gmib_tx_collisions]; -+ -+ spin_unlock(&ppe_port->gmib_stats_lock); -+ } else { -+ s->multicast = ppe_port_xgmib_get(ppe_port, xgmib_rx_multicast_g); -+ -+ s->rx_packets = s->multicast; -+ s->rx_packets += ppe_port_xgmib_get(ppe_port, xgmib_rx_unicast_g); -+ s->rx_packets += ppe_port_xgmib_get(ppe_port, xgmib_rx_broadcast_g); -+ -+ s->tx_packets = ppe_port_xgmib_get(ppe_port, xgmib_tx_frames); -+ s->rx_bytes = ppe_port_xgmib_get(ppe_port, xgmib_rx_bytes); -+ s->tx_bytes = ppe_port_xgmib_get(ppe_port, xgmib_tx_bytes); -+ -+ s->rx_crc_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_crc_err); -+ s->rx_fifo_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_fifo_overflow); -+ -+ s->rx_length_errors = ppe_port_xgmib_get(ppe_port, xgmib_rx_len_err); -+ s->rx_errors = s->rx_crc_errors + -+ s->rx_fifo_errors + s->rx_length_errors; -+ s->rx_dropped = s->rx_errors; -+ -+ s->tx_fifo_errors = ppe_port_xgmib_get(ppe_port, xgmib_tx_underflow_err); -+ s->tx_errors = s->tx_packets - -+ ppe_port_xgmib_get(ppe_port, xgmib_tx_frames_g); -+ } -+} -+ - /* PPE port and MAC reset */ - static int ppe_port_mac_reset(struct ppe_port *ppe_port) - { -@@ -261,6 +693,9 @@ static void ppe_port_mac_link_up(struct - int ret, port = ppe_port->port_id; - u32 reg, val; - -+ /* Start GMIB statistics polling */ -+ schedule_delayed_work(&ppe_port->gmib_read, 0); -+ - if (mac_type == PPE_MAC_TYPE_GMAC) - ret = ppe_port_gmac_link_up(ppe_port, - speed, duplex, tx_pause, rx_pause); -@@ -306,6 +741,9 @@ static void ppe_port_mac_link_down(struc - int ret, port = ppe_port->port_id; - u32 reg; - -+ /* Stop GMIB statistics polling */ -+ cancel_delayed_work_sync(&ppe_port->gmib_read); -+ - /* Disable PPE port TX */ - reg = PPE_PORT_BRIDGE_CTRL_ADDR + PPE_PORT_BRIDGE_CTRL_INC * port; - ret = regmap_update_bits(ppe_dev->regmap, reg, -@@ -627,6 +1065,27 @@ static int ppe_port_mac_hw_init(struct p - return ret; - } - -+/* PPE port MAC MIB work task initialization */ -+static int ppe_port_mac_mib_work_init(struct ppe_port *ppe_port) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ u64 *gstats; -+ -+ gstats = devm_kzalloc(ppe_dev->dev, -+ sizeof(*gstats) * ARRAY_SIZE(gmib_info), -+ GFP_KERNEL); -+ if (!gstats) -+ return -ENOMEM; -+ -+ ppe_port->gmib_stats = gstats; -+ -+ spin_lock_init(&ppe_port->gmib_stats_lock); -+ INIT_DELAYED_WORK(&ppe_port->gmib_read, -+ ppe_port_gmib_stats_poll); -+ -+ return 0; -+} -+ - /** - * ppe_port_mac_init() - Initialization of PPE ports for the PPE device - * @ppe_dev: PPE device -@@ -693,6 +1152,12 @@ int ppe_port_mac_init(struct ppe_device - goto err_port_node; - } - -+ ret = ppe_port_mac_mib_work_init(&ppe_ports->port[i]); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Failed to initialize MAC MIB work\n"); -+ goto err_port_node; -+ } -+ - i++; - } - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -@@ -8,6 +8,8 @@ - - #include - -+struct rtnl_link_stats64; -+ - /** - * enum ppe_port_clk_rst_type - PPE port clock and reset ID type - * @PPE_PORT_CLK_RST_MAC: The clock and reset ID for port MAC -@@ -44,6 +46,9 @@ enum ppe_mac_type { - * @port_id: Port ID - * @clks: Port clocks - * @rstcs: Port resets -+ * @gmib_read: Delay work task for GMAC MIB statistics polling function -+ * @gmib_stats: GMAC MIB statistics array -+ * @gmib_stats_lock: Lock to protect GMAC MIB statistics - */ - struct ppe_port { - struct phylink *phylink; -@@ -56,6 +61,9 @@ struct ppe_port { - int port_id; - struct clk *clks[PPE_PORT_CLK_RST_MAX]; - struct reset_control *rstcs[PPE_PORT_CLK_RST_MAX]; -+ struct delayed_work gmib_read; -+ u64 *gmib_stats; -+ spinlock_t gmib_stats_lock; /* Protects GMIB stats */ - }; - - /** -@@ -73,4 +81,9 @@ void ppe_port_mac_deinit(struct ppe_devi - int ppe_port_phylink_setup(struct ppe_port *ppe_port, - struct net_device *netdev); - void ppe_port_phylink_destroy(struct ppe_port *ppe_port); -+int ppe_port_get_sset_count(struct ppe_port *ppe_port, int sset); -+void ppe_port_get_strings(struct ppe_port *ppe_port, u32 stringset, u8 *data); -+void ppe_port_get_ethtool_stats(struct ppe_port *ppe_port, u64 *data); -+void ppe_port_get_stats64(struct ppe_port *ppe_port, -+ struct rtnl_link_stats64 *s); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -618,6 +618,48 @@ - #define GMAC_MIB_CTRL_MASK \ - (GMAC_MIB_RD_CLR | GMAC_MIB_RST | GMAC_MIB_EN) - -+/* GMAC MIB counter registers */ -+#define GMAC_RXBROAD_ADDR 0x40 -+#define GMAC_RXPAUSE_ADDR 0x44 -+#define GMAC_RXMULTI_ADDR 0x48 -+#define GMAC_RXFCSERR_ADDR 0x4C -+#define GMAC_RXALIGNERR_ADDR 0x50 -+#define GMAC_RXRUNT_ADDR 0x54 -+#define GMAC_RXFRAG_ADDR 0x58 -+#define GMAC_RXJUMBOFCSERR_ADDR 0x5C -+#define GMAC_RXJUMBOALIGNERR_ADDR 0x60 -+#define GMAC_RXPKT64_ADDR 0x64 -+#define GMAC_RXPKT65TO127_ADDR 0x68 -+#define GMAC_RXPKT128TO255_ADDR 0x6C -+#define GMAC_RXPKT256TO511_ADDR 0x70 -+#define GMAC_RXPKT512TO1023_ADDR 0x74 -+#define GMAC_RXPKT1024TO1518_ADDR 0x78 -+#define GMAC_RXPKT1519TOX_ADDR 0x7C -+#define GMAC_RXTOOLONG_ADDR 0x80 -+#define GMAC_RXBYTE_G_ADDR 0x84 -+#define GMAC_RXBYTE_B_ADDR 0x8C -+#define GMAC_RXUNI_ADDR 0x94 -+#define GMAC_TXBROAD_ADDR 0xA0 -+#define GMAC_TXPAUSE_ADDR 0xA4 -+#define GMAC_TXMULTI_ADDR 0xA8 -+#define GMAC_TXUNDERRUN_ADDR 0xAC -+#define GMAC_TXPKT64_ADDR 0xB0 -+#define GMAC_TXPKT65TO127_ADDR 0xB4 -+#define GMAC_TXPKT128TO255_ADDR 0xB8 -+#define GMAC_TXPKT256TO511_ADDR 0xBC -+#define GMAC_TXPKT512TO1023_ADDR 0xC0 -+#define GMAC_TXPKT1024TO1518_ADDR 0xC4 -+#define GMAC_TXPKT1519TOX_ADDR 0xC8 -+#define GMAC_TXBYTE_ADDR 0xCC -+#define GMAC_TXCOLLISIONS_ADDR 0xD4 -+#define GMAC_TXABORTCOL_ADDR 0xD8 -+#define GMAC_TXMULTICOL_ADDR 0xDC -+#define GMAC_TXSINGLECOL_ADDR 0xE0 -+#define GMAC_TXEXCESSIVEDEFER_ADDR 0xE4 -+#define GMAC_TXDEFER_ADDR 0xE8 -+#define GMAC_TXLATECOL_ADDR 0xEC -+#define GMAC_TXUNI_ADDR 0xF0 -+ - /* XGMAC TX configuration register */ - #define XGMAC_TX_CONFIG_ADDR 0x0 - #define XGMAC_SPEED_M GENMASK(31, 29) -@@ -680,4 +722,53 @@ - #define XGMAC_MCF BIT(3) - #define XGMAC_CNTRST BIT(0) - -+/* XGMAC MIB counter registers */ -+#define XGMAC_TXBYTE_GB_ADDR 0x814 -+#define XGMAC_TXPKT_GB_ADDR 0x81C -+#define XGMAC_TXBROAD_G_ADDR 0x824 -+#define XGMAC_TXMULTI_G_ADDR 0x82C -+#define XGMAC_TXPKT64_GB_ADDR 0x834 -+#define XGMAC_TXPKT65TO127_GB_ADDR 0x83C -+#define XGMAC_TXPKT128TO255_GB_ADDR 0x844 -+#define XGMAC_TXPKT256TO511_GB_ADDR 0x84C -+#define XGMAC_TXPKT512TO1023_GB_ADDR 0x854 -+#define XGMAC_TXPKT1024TOMAX_GB_ADDR 0x85C -+#define XGMAC_TXUNI_GB_ADDR 0x864 -+#define XGMAC_TXMULTI_GB_ADDR 0x86C -+#define XGMAC_TXBROAD_GB_ADDR 0x874 -+#define XGMAC_TXUNDERFLOW_ERR_ADDR 0x87C -+#define XGMAC_TXBYTE_G_ADDR 0x884 -+#define XGMAC_TXPKT_G_ADDR 0x88C -+#define XGMAC_TXPAUSE_ADDR 0x894 -+#define XGMAC_TXVLAN_G_ADDR 0x89C -+#define XGMAC_TXLPI_USEC_ADDR 0x8A4 -+#define XGMAC_TXLPI_TRAN_ADDR 0x8A8 -+#define XGMAC_RXPKT_GB_ADDR 0x900 -+#define XGMAC_RXBYTE_GB_ADDR 0x908 -+#define XGMAC_RXBYTE_G_ADDR 0x910 -+#define XGMAC_RXBROAD_G_ADDR 0x918 -+#define XGMAC_RXMULTI_G_ADDR 0x920 -+#define XGMAC_RXCRC_ERR_ADDR 0x928 -+#define XGMAC_RXRUNT_ERR_ADDR 0x930 -+#define XGMAC_RXJABBER_ERR_ADDR 0x934 -+#define XGMAC_RXUNDERSIZE_G_ADDR 0x938 -+#define XGMAC_RXOVERSIZE_G_ADDR 0x93C -+#define XGMAC_RXPKT64_GB_ADDR 0x940 -+#define XGMAC_RXPKT65TO127_GB_ADDR 0x948 -+#define XGMAC_RXPKT128TO255_GB_ADDR 0x950 -+#define XGMAC_RXPKT256TO511_GB_ADDR 0x958 -+#define XGMAC_RXPKT512TO1023_GB_ADDR 0x960 -+#define XGMAC_RXPKT1024TOMAX_GB_ADDR 0x968 -+#define XGMAC_RXUNI_G_ADDR 0x970 -+#define XGMAC_RXLEN_ERR_ADDR 0x978 -+#define XGMAC_RXOUTOFRANGE_ADDR 0x980 -+#define XGMAC_RXPAUSE_ADDR 0x988 -+#define XGMAC_RXFIFOOVERFLOW_ADDR 0x990 -+#define XGMAC_RXVLAN_GB_ADDR 0x998 -+#define XGMAC_RXWATCHDOG_ERR_ADDR 0x9A0 -+#define XGMAC_RXLPI_USEC_ADDR 0x9A4 -+#define XGMAC_RXLPI_TRAN_ADDR 0x9A8 -+#define XGMAC_RXDISCARD_GB_ADDR 0x9AC -+#define XGMAC_RXDISCARDBYTE_GB_ADDR 0x9B4 -+ - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0340-net-ethernet-qualcomm-Add-PPE-port-MAC-address-and-E.patch b/target/linux/qualcommbe/patches-6.12/0340-net-ethernet-qualcomm-Add-PPE-port-MAC-address-and-E.patch deleted file mode 100644 index 856a1ed4cc..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0340-net-ethernet-qualcomm-Add-PPE-port-MAC-address-and-E.patch +++ /dev/null @@ -1,172 +0,0 @@ -From 55fbbc8ef90df27a16bca1613a793a578b79a384 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Fri, 1 Mar 2024 13:36:26 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add PPE port MAC address and EEE - functions - -Add PPE port MAC address set and EEE set API functions which -will be used by netdev ops and ethtool. - -Change-Id: Id2b3b06ae940b3b6f5227d927316329cdf3caeaa -Signed-off-by: Lei Wei -Alex G: use struct ethtool_keee instead of ethtool_eee -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 75 ++++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 3 + - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 29 ++++++++ - 3 files changed, 107 insertions(+) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -@@ -462,6 +462,81 @@ void ppe_port_get_stats64(struct ppe_por - } - } - -+/** -+ * ppe_port_set_mac_address() - Set PPE port MAC address -+ * @ppe_port: PPE port -+ * @addr: MAC address -+ * -+ * Description: Set MAC address for the given PPE port. -+ * -+ * Return: 0 upon success or a negative error upon failure. -+ */ -+int ppe_port_set_mac_address(struct ppe_port *ppe_port, const u8 *addr) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int port = ppe_port->port_id; -+ u32 reg, val; -+ int ret; -+ -+ if (ppe_port->mac_type == PPE_MAC_TYPE_GMAC) { -+ reg = PPE_PORT_GMAC_ADDR(port); -+ val = (addr[5] << 8) | addr[4]; -+ ret = regmap_write(ppe_dev->regmap, reg + GMAC_GOL_ADDR0_ADDR, val); -+ if (ret) -+ return ret; -+ -+ val = (addr[0] << 24) | (addr[1] << 16) | -+ (addr[2] << 8) | addr[3]; -+ ret = regmap_write(ppe_dev->regmap, reg + GMAC_GOL_ADDR1_ADDR, val); -+ if (ret) -+ return ret; -+ } else { -+ reg = PPE_PORT_XGMAC_ADDR(port); -+ val = (addr[5] << 8) | addr[4] | XGMAC_ADDR_EN; -+ ret = regmap_write(ppe_dev->regmap, reg + XGMAC_ADDR0_H_ADDR, val); -+ if (ret) -+ return ret; -+ -+ val = (addr[3] << 24) | (addr[2] << 16) | -+ (addr[1] << 8) | addr[0]; -+ ret = regmap_write(ppe_dev->regmap, reg + XGMAC_ADDR0_L_ADDR, val); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * ppe_port_set_mac_eee() - Set EEE configuration for PPE port MAC -+ * @ppe_port: PPE port -+ * @eee: EEE settings -+ * -+ * Description: Set port MAC EEE settings for the given PPE port. -+ * -+ * Return: 0 upon success or a negative error upon failure. -+ */ -+int ppe_port_set_mac_eee(struct ppe_port *ppe_port, struct ethtool_keee *eee) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ int port = ppe_port->port_id; -+ u32 val; -+ int ret; -+ -+ ret = regmap_read(ppe_dev->regmap, PPE_LPI_EN_ADDR, &val); -+ if (ret) -+ return ret; -+ -+ if (eee->tx_lpi_enabled) -+ val |= PPE_LPI_PORT_EN(port); -+ else -+ val &= ~PPE_LPI_PORT_EN(port); -+ -+ ret = regmap_write(ppe_dev->regmap, PPE_LPI_EN_ADDR, val); -+ -+ return ret; -+} -+ - /* PPE port and MAC reset */ - static int ppe_port_mac_reset(struct ppe_port *ppe_port) - { ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -@@ -8,6 +8,7 @@ - - #include - -+struct ethtool_keee; - struct rtnl_link_stats64; - - /** -@@ -86,4 +87,6 @@ void ppe_port_get_strings(struct ppe_por - void ppe_port_get_ethtool_stats(struct ppe_port *ppe_port, u64 *data); - void ppe_port_get_stats64(struct ppe_port *ppe_port, - struct rtnl_link_stats64 *s); -+int ppe_port_set_mac_address(struct ppe_port *ppe_port, const u8 *addr); -+int ppe_port_set_mac_eee(struct ppe_port *ppe_port, struct ethtool_keee *eee); - #endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -20,6 +20,16 @@ - #define PPE_PORT5_SEL_PCS1 BIT(4) - #define PPE_PORT_SEL_XGMAC(x) (BIT(8) << ((x) - 1)) - -+/* PPE port LPI enable register */ -+#define PPE_LPI_EN_ADDR 0x400 -+#define PPE_LPI_PORT1_EN BIT(0) -+#define PPE_LPI_PORT2_EN BIT(1) -+#define PPE_LPI_PORT3_EN BIT(2) -+#define PPE_LPI_PORT4_EN BIT(3) -+#define PPE_LPI_PORT5_EN BIT(4) -+#define PPE_LPI_PORT6_EN BIT(5) -+#define PPE_LPI_PORT_EN(x) (BIT(0) << ((x) - 1)) -+ - /* PPE scheduler configurations for buffer manager block. */ - #define PPE_BM_SCH_CTRL_ADDR 0xb000 - #define PPE_BM_SCH_CTRL_INC 4 -@@ -592,6 +602,17 @@ - #define GMAC_SPEED_100 1 - #define GMAC_SPEED_1000 2 - -+/* GMAC MAC address register */ -+#define GMAC_GOL_ADDR0_ADDR 0x8 -+#define GMAC_ADDR_BYTE5 GENMASK(15, 8) -+#define GMAC_ADDR_BYTE4 GENMASK(7, 0) -+ -+#define GMAC_GOL_ADDR1_ADDR 0xC -+#define GMAC_ADDR_BYTE0 GENMASK(31, 24) -+#define GMAC_ADDR_BYTE1 GENMASK(23, 16) -+#define GMAC_ADDR_BYTE2 GENMASK(15, 8) -+#define GMAC_ADDR_BYTE3 GENMASK(7, 0) -+ - /* GMAC control register */ - #define GMAC_CTRL_ADDR 0x18 - #define GMAC_TX_THD_M GENMASK(27, 24) -@@ -717,6 +738,14 @@ - #define XGMAC_RX_FLOW_CTRL_ADDR 0x90 - #define XGMAC_RXFCEN BIT(0) - -+/* XGMAC MAC address register */ -+#define XGMAC_ADDR0_H_ADDR 0x300 -+#define XGMAC_ADDR_EN BIT(31) -+#define XGMAC_ADDRH GENMASK(15, 0) -+ -+#define XGMAC_ADDR0_L_ADDR 0x304 -+#define XGMAC_ADDRL GENMASK(31, 0) -+ - /* XGMAC management counters control register */ - #define XGMAC_MMC_CTRL_ADDR 0x800 - #define XGMAC_MCF BIT(3) diff --git a/target/linux/qualcommbe/patches-6.12/0341-net-ethernet-qualcomm-Add-API-to-configure-PPE-port-.patch b/target/linux/qualcommbe/patches-6.12/0341-net-ethernet-qualcomm-Add-API-to-configure-PPE-port-.patch deleted file mode 100644 index ae81ddb19d..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0341-net-ethernet-qualcomm-Add-API-to-configure-PPE-port-.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 3981aeae5dd43dea94a0ec10f0b2977ebd102560 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Tue, 5 Mar 2024 16:42:56 +0800 -Subject: [PATCH] net: ethernet: qualcomm: Add API to configure PPE port max - frame size - -This function is called when the MTU of an ethernet port is -configured. It limits the size of packet passed through the -ethernet port. - -Change-Id: I2a4dcd04407156d73770d2becbb7cbc0d56b3754 -Signed-off-by: Luo Jie ---- - drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 44 ++++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/ppe_port.h | 1 + - 2 files changed, 45 insertions(+) - ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -@@ -537,6 +537,50 @@ int ppe_port_set_mac_eee(struct ppe_port - return ret; - } - -+/** -+ * ppe_port_set_maxframe() - Set port maximum frame size -+ * @ppe_port: PPE port structure -+ * @maxframe_size: Maximum frame size supported by PPE port -+ * -+ * Description: Set MTU of network interface specified by @ppe_port. -+ * -+ * Return: 0 upon success or a negative error upon failure. -+ */ -+int ppe_port_set_maxframe(struct ppe_port *ppe_port, int maxframe_size) -+{ -+ struct ppe_device *ppe_dev = ppe_port->ppe_dev; -+ u32 reg, val, mru_mtu_val[3]; -+ int port = ppe_port->port_id; -+ int ret; -+ -+ /* The max frame size should be MTU added by ETH_HLEN in PPE. */ -+ maxframe_size += ETH_HLEN; -+ -+ /* MAC takes cover the FCS for the calculation of frame size. */ -+ if (maxframe_size > PPE_PORT_MAC_MAX_FRAME_SIZE - ETH_FCS_LEN) -+ return -EINVAL; -+ -+ reg = PPE_MC_MTU_CTRL_TBL_ADDR + PPE_MC_MTU_CTRL_TBL_INC * port; -+ val = FIELD_PREP(PPE_MC_MTU_CTRL_TBL_MTU, maxframe_size); -+ ret = regmap_update_bits(ppe_dev->regmap, reg, -+ PPE_MC_MTU_CTRL_TBL_MTU, -+ val); -+ if (ret) -+ return ret; -+ -+ reg = PPE_MRU_MTU_CTRL_TBL_ADDR + PPE_MRU_MTU_CTRL_TBL_INC * port; -+ ret = regmap_bulk_read(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+ if (ret) -+ return ret; -+ -+ PPE_MRU_MTU_CTRL_SET_MRU(mru_mtu_val, maxframe_size); -+ PPE_MRU_MTU_CTRL_SET_MTU(mru_mtu_val, maxframe_size); -+ -+ return regmap_bulk_write(ppe_dev->regmap, reg, -+ mru_mtu_val, ARRAY_SIZE(mru_mtu_val)); -+} -+ - /* PPE port and MAC reset */ - static int ppe_port_mac_reset(struct ppe_port *ppe_port) - { ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.h -@@ -89,4 +89,5 @@ void ppe_port_get_stats64(struct ppe_por - struct rtnl_link_stats64 *s); - int ppe_port_set_mac_address(struct ppe_port *ppe_port, const u8 *addr); - int ppe_port_set_mac_eee(struct ppe_port *ppe_port, struct ethtool_keee *eee); -+int ppe_port_set_maxframe(struct ppe_port *ppe_port, int maxframe_size); - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0342-net-ethernet-qualcomm-Add-EDMA-support-for-QCOM-IPQ9.patch b/target/linux/qualcommbe/patches-6.12/0342-net-ethernet-qualcomm-Add-EDMA-support-for-QCOM-IPQ9.patch deleted file mode 100644 index 0160efdacb..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0342-net-ethernet-qualcomm-Add-EDMA-support-for-QCOM-IPQ9.patch +++ /dev/null @@ -1,932 +0,0 @@ -From 00d4f3cb4f5d1e6924151a4551f06b6a82bf0146 Mon Sep 17 00:00:00 2001 -From: Pavithra R -Date: Wed, 28 Feb 2024 11:25:15 +0530 -Subject: [PATCH] net: ethernet: qualcomm: Add EDMA support for QCOM IPQ9574 - chipset. - -Add the infrastructure functions such as Makefile, -EDMA hardware configuration, clock and IRQ initializations. - -Change-Id: I64f65e554e70e9095b0cf3636fec421569ae6895 -Signed-off-by: Pavithra R -Co-developed-by: Suruchi Agarwal -Signed-off-by: Suruchi Agarwal -Alex G: use "ppe_config.h" header instead of "ppe_api.h" - add missing definitions and functions from ppe_api: - - enum ppe_queue_class_type {} - - ppe_edma_queue_offset_config() -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 3 + - drivers/net/ethernet/qualcomm/ppe/edma.c | 480 +++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma.h | 113 +++++ - drivers/net/ethernet/qualcomm/ppe/ppe.c | 10 +- - drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 253 ++++++++++ - 5 files changed, 858 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -5,3 +5,6 @@ - - obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o -+ -+#EDMA -+qcom-ppe-objs += edma.o ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -0,0 +1,480 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ /* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+ /* Qualcomm Ethernet DMA driver setup, HW configuration, clocks and -+ * interrupt initializations. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "ppe_regs.h" -+ -+#define EDMA_IRQ_NAME_SIZE 32 -+ -+/* Global EDMA context. */ -+struct edma_context *edma_ctx; -+ -+/* Priority to multi-queue mapping. */ -+static u8 edma_pri_map[PPE_QUEUE_INTER_PRI_NUM] = { -+ 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7}; -+ -+enum edma_clk_id { -+ EDMA_CLK, -+ EDMA_CFG_CLK, -+ EDMA_CLK_MAX -+}; -+ -+static const char * const clock_name[EDMA_CLK_MAX] = { -+ [EDMA_CLK] = "edma", -+ [EDMA_CFG_CLK] = "edma-cfg", -+}; -+ -+/* Rx Fill ring info for IPQ9574. */ -+static struct edma_ring_info ipq9574_rxfill_ring_info = { -+ .max_rings = 8, -+ .ring_start = 4, -+ .num_rings = 4, -+}; -+ -+/* Rx ring info for IPQ9574. */ -+static struct edma_ring_info ipq9574_rx_ring_info = { -+ .max_rings = 24, -+ .ring_start = 20, -+ .num_rings = 4, -+}; -+ -+/* Tx ring info for IPQ9574. */ -+static struct edma_ring_info ipq9574_tx_ring_info = { -+ .max_rings = 32, -+ .ring_start = 8, -+ .num_rings = 24, -+}; -+ -+/* Tx complete ring info for IPQ9574. */ -+static struct edma_ring_info ipq9574_txcmpl_ring_info = { -+ .max_rings = 32, -+ .ring_start = 8, -+ .num_rings = 24, -+}; -+ -+/* HW info for IPQ9574. */ -+static struct edma_hw_info ipq9574_hw_info = { -+ .rxfill = &ipq9574_rxfill_ring_info, -+ .rx = &ipq9574_rx_ring_info, -+ .tx = &ipq9574_tx_ring_info, -+ .txcmpl = &ipq9574_txcmpl_ring_info, -+ .max_ports = 6, -+ .napi_budget_rx = 128, -+ .napi_budget_tx = 512, -+}; -+ -+static int edma_clock_set_and_enable(struct device *dev, -+ const char *id, unsigned long rate) -+{ -+ struct device_node *edma_np; -+ struct clk *clk = NULL; -+ int ret; -+ -+ edma_np = of_get_child_by_name(dev->of_node, "edma"); -+ -+ clk = devm_get_clk_from_child(dev, edma_np, id); -+ if (IS_ERR(clk)) { -+ dev_err(dev, "clk %s get failed\n", id); -+ of_node_put(edma_np); -+ return PTR_ERR(clk); -+ } -+ -+ ret = clk_set_rate(clk, rate); -+ if (ret) { -+ dev_err(dev, "set %lu rate for %s failed\n", rate, id); -+ of_node_put(edma_np); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(clk); -+ if (ret) { -+ dev_err(dev, "clk %s enable failed\n", id); -+ of_node_put(edma_np); -+ return ret; -+ } -+ -+ of_node_put(edma_np); -+ -+ dev_dbg(dev, "set %lu rate for %s\n", rate, id); -+ -+ return 0; -+} -+ -+static int edma_clock_init(void) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ unsigned long ppe_rate; -+ int ret; -+ -+ ppe_rate = ppe_dev->clk_rate; -+ -+ ret = edma_clock_set_and_enable(dev, clock_name[EDMA_CLK], -+ ppe_rate); -+ if (ret) -+ return ret; -+ -+ ret = edma_clock_set_and_enable(dev, clock_name[EDMA_CFG_CLK], -+ ppe_rate); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+/** -+ * edma_configure_ucast_prio_map_tbl - Configure unicast priority map table. -+ * -+ * Map int_priority values to priority class and initialize -+ * unicast priority map table for default profile_id. -+ */ -+static int edma_configure_ucast_prio_map_tbl(void) -+{ -+ u8 pri_class, int_pri; -+ int ret = 0; -+ -+ /* Set the priority class value for every possible priority. */ -+ for (int_pri = 0; int_pri < PPE_QUEUE_INTER_PRI_NUM; int_pri++) { -+ pri_class = edma_pri_map[int_pri]; -+ -+ /* Priority offset should be less than maximum supported -+ * queue priority. -+ */ -+ if (pri_class > EDMA_PRI_MAX_PER_CORE - 1) { -+ pr_err("Configured incorrect priority offset: %d\n", -+ pri_class); -+ return -EINVAL; -+ } -+ -+ ret = ppe_edma_queue_offset_config(edma_ctx->ppe_dev, -+ PPE_QUEUE_CLASS_PRIORITY, int_pri, pri_class); -+ -+ if (ret) { -+ pr_err("Failed with error: %d to set queue priority class for int_pri: %d for profile_id: %d\n", -+ ret, int_pri, 0); -+ return ret; -+ } -+ -+ pr_debug("profile_id: %d, int_priority: %d, pri_class: %d\n", -+ 0, int_pri, pri_class); -+ } -+ -+ return ret; -+} -+ -+static int edma_irq_init(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct edma_ring_info *rx = hw_info->rx; -+ char edma_irq_name[EDMA_IRQ_NAME_SIZE]; -+ struct device *dev = ppe_dev->dev; -+ struct platform_device *pdev; -+ struct device_node *edma_np; -+ u32 i; -+ -+ pdev = to_platform_device(dev); -+ edma_np = of_get_child_by_name(dev->of_node, "edma"); -+ edma_ctx->intr_info.intr_txcmpl = kzalloc((sizeof(*edma_ctx->intr_info.intr_txcmpl) * -+ txcmpl->num_rings), GFP_KERNEL); -+ if (!edma_ctx->intr_info.intr_txcmpl) { -+ of_node_put(edma_np); -+ return -ENOMEM; -+ } -+ -+ /* Get TXCMPL rings IRQ numbers. */ -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ snprintf(edma_irq_name, sizeof(edma_irq_name), "edma_txcmpl_%d", -+ txcmpl->ring_start + i); -+ edma_ctx->intr_info.intr_txcmpl[i] = of_irq_get_byname(edma_np, edma_irq_name); -+ if (edma_ctx->intr_info.intr_txcmpl[i] < 0) { -+ dev_err(dev, "%s: txcmpl_info.intr[%u] irq get failed\n", -+ edma_np->name, i); -+ of_node_put(edma_np); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ return edma_ctx->intr_info.intr_txcmpl[i]; -+ } -+ -+ dev_dbg(dev, "%s: intr_info.intr_txcmpl[%u] = %u\n", -+ edma_np->name, i, edma_ctx->intr_info.intr_txcmpl[i]); -+ } -+ -+ edma_ctx->intr_info.intr_rx = kzalloc((sizeof(*edma_ctx->intr_info.intr_rx) * -+ rx->num_rings), GFP_KERNEL); -+ if (!edma_ctx->intr_info.intr_rx) { -+ of_node_put(edma_np); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ return -ENOMEM; -+ } -+ -+ /* Get RXDESC rings IRQ numbers. */ -+ for (i = 0; i < rx->num_rings; i++) { -+ snprintf(edma_irq_name, sizeof(edma_irq_name), "edma_rxdesc_%d", -+ rx->ring_start + i); -+ edma_ctx->intr_info.intr_rx[i] = of_irq_get_byname(edma_np, edma_irq_name); -+ if (edma_ctx->intr_info.intr_rx[i] < 0) { -+ dev_err(dev, "%s: rx_queue_map_info.intr[%u] irq get failed\n", -+ edma_np->name, i); -+ of_node_put(edma_np); -+ kfree(edma_ctx->intr_info.intr_rx); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ return edma_ctx->intr_info.intr_rx[i]; -+ } -+ -+ dev_dbg(dev, "%s: intr_info.intr_rx[%u] = %u\n", -+ edma_np->name, i, edma_ctx->intr_info.intr_rx[i]); -+ } -+ -+ /* Get misc IRQ number. */ -+ edma_ctx->intr_info.intr_misc = of_irq_get_byname(edma_np, "edma_misc"); -+ if (edma_ctx->intr_info.intr_misc < 0) { -+ dev_err(dev, "%s: misc_intr irq get failed\n", edma_np->name); -+ of_node_put(edma_np); -+ kfree(edma_ctx->intr_info.intr_rx); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ return edma_ctx->intr_info.intr_misc; -+ } -+ -+ of_node_put(edma_np); -+ -+ dev_dbg(dev, "%s: misc IRQ:%u\n", edma_np->name, -+ edma_ctx->intr_info.intr_misc); -+ -+ return 0; -+} -+ -+static int edma_hw_reset(void) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ struct reset_control *edma_hw_rst; -+ struct device_node *edma_np; -+ const char *reset_string; -+ u32 count, i; -+ int ret; -+ -+ /* Count and parse reset names from DTSI. */ -+ edma_np = of_get_child_by_name(dev->of_node, "edma"); -+ count = of_property_count_strings(edma_np, "reset-names"); -+ if (count < 0) { -+ dev_err(dev, "EDMA reset entry not found\n"); -+ of_node_put(edma_np); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < count; i++) { -+ ret = of_property_read_string_index(edma_np, "reset-names", -+ i, &reset_string); -+ if (ret) { -+ dev_err(dev, "Error reading reset-names"); -+ of_node_put(edma_np); -+ return -EINVAL; -+ } -+ -+ edma_hw_rst = of_reset_control_get_exclusive(edma_np, reset_string); -+ if (IS_ERR(edma_hw_rst)) { -+ of_node_put(edma_np); -+ return PTR_ERR(edma_hw_rst); -+ } -+ -+ /* 100ms delay is required by hardware to reset EDMA. */ -+ reset_control_assert(edma_hw_rst); -+ fsleep(100); -+ -+ reset_control_deassert(edma_hw_rst); -+ fsleep(100); -+ -+ reset_control_put(edma_hw_rst); -+ dev_dbg(dev, "EDMA HW reset, i:%d reset_string:%s\n", i, reset_string); -+ } -+ -+ of_node_put(edma_np); -+ -+ return 0; -+} -+ -+static int edma_hw_configure(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 data, reg; -+ int ret; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_MAS_CTRL_ADDR; -+ ret = regmap_read(regmap, reg, &data); -+ if (ret) -+ return ret; -+ -+ pr_debug("EDMA ver %d hw init\n", data); -+ -+ /* Setup private data structure. */ -+ edma_ctx->intr_info.intr_mask_rx = EDMA_RXDESC_INT_MASK_PKT_INT; -+ edma_ctx->intr_info.intr_mask_txcmpl = EDMA_TX_INT_MASK_PKT_INT; -+ -+ /* Reset EDMA. */ -+ ret = edma_hw_reset(); -+ if (ret) { -+ pr_err("Error in resetting the hardware. ret: %d\n", ret); -+ return ret; -+ } -+ -+ /* Allocate memory for netdevices. */ -+ edma_ctx->netdev_arr = kzalloc((sizeof(**edma_ctx->netdev_arr) * -+ hw_info->max_ports), -+ GFP_KERNEL); -+ if (!edma_ctx->netdev_arr) -+ return -ENOMEM; -+ -+ /* Configure DMA request priority, DMA read burst length, -+ * and AXI write size. -+ */ -+ data = FIELD_PREP(EDMA_DMAR_BURST_LEN_MASK, EDMA_BURST_LEN_ENABLE); -+ data |= FIELD_PREP(EDMA_DMAR_REQ_PRI_MASK, 0); -+ data |= FIELD_PREP(EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK, 31); -+ data |= FIELD_PREP(EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK, 7); -+ data |= FIELD_PREP(EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK, 7); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_DMAR_CTRL_ADDR; -+ ret = regmap_write(regmap, reg, data); -+ if (ret) -+ return ret; -+ -+ /* Configure Tx Timeout Threshold. */ -+ data = EDMA_TX_TIMEOUT_THRESH_VAL; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_TIMEOUT_THRESH_ADDR; -+ ret = regmap_write(regmap, reg, data); -+ if (ret) -+ return ret; -+ -+ /* Set Miscellaneous error mask. */ -+ data = EDMA_MISC_AXI_RD_ERR_MASK | -+ EDMA_MISC_AXI_WR_ERR_MASK | -+ EDMA_MISC_RX_DESC_FIFO_FULL_MASK | -+ EDMA_MISC_RX_ERR_BUF_SIZE_MASK | -+ EDMA_MISC_TX_SRAM_FULL_MASK | -+ EDMA_MISC_TX_CMPL_BUF_FULL_MASK | -+ EDMA_MISC_DATA_LEN_ERR_MASK; -+ data |= EDMA_MISC_TX_TIMEOUT_MASK; -+ edma_ctx->intr_info.intr_mask_misc = data; -+ -+ /* Global EDMA enable and padding enable. */ -+ data = EDMA_PORT_PAD_EN | EDMA_PORT_EDMA_EN; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_PORT_CTRL_ADDR; -+ ret = regmap_write(regmap, reg, data); -+ if (ret) -+ return ret; -+ -+ /* Initialize unicast priority map table. */ -+ ret = (int)edma_configure_ucast_prio_map_tbl(); -+ if (ret) { -+ pr_err("Failed to initialize unicast priority map table: %d\n", -+ ret); -+ kfree(edma_ctx->netdev_arr); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * edma_destroy - EDMA Destroy. -+ * @ppe_dev: PPE device -+ * -+ * Free the memory allocated during setup. -+ */ -+void edma_destroy(struct ppe_device *ppe_dev) -+{ -+ kfree(edma_ctx->intr_info.intr_rx); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ kfree(edma_ctx->netdev_arr); -+} -+ -+/** -+ * edma_setup - EDMA Setup. -+ * @ppe_dev: PPE device -+ * -+ * Configure Ethernet global ctx, clocks, hardware and interrupts. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int edma_setup(struct ppe_device *ppe_dev) -+{ -+ struct device *dev = ppe_dev->dev; -+ int ret; -+ -+ edma_ctx = devm_kzalloc(dev, sizeof(*edma_ctx), GFP_KERNEL); -+ if (!edma_ctx) -+ return -ENOMEM; -+ -+ edma_ctx->hw_info = &ipq9574_hw_info; -+ edma_ctx->ppe_dev = ppe_dev; -+ -+ /* Configure the EDMA common clocks. */ -+ ret = edma_clock_init(); -+ if (ret) { -+ dev_err(dev, "Error in configuring the EDMA clocks\n"); -+ return ret; -+ } -+ -+ dev_dbg(dev, "QCOM EDMA common clocks are configured\n"); -+ -+ ret = edma_hw_configure(); -+ if (ret) { -+ dev_err(dev, "Error in edma configuration\n"); -+ return ret; -+ } -+ -+ ret = edma_irq_init(); -+ if (ret) { -+ dev_err(dev, "Error in irq initialization\n"); -+ return ret; -+ } -+ -+ dev_info(dev, "EDMA configuration successful\n"); -+ -+ return 0; -+} -+ -+/** -+ * ppe_edma_queue_offset_config - Configure queue offset for EDMA interface -+ * @ppe_dev: PPE device -+ * @class: The class to configure queue offset -+ * @index: Class index, internal priority or hash value -+ * @queue_offset: Queue offset value -+ * -+ * PPE EDMA queue offset is configured based on the PPE internal priority or -+ * RSS hash value, the profile ID is fixed to 0 for EDMA interface. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev, -+ enum ppe_queue_class_type class, -+ int index, int queue_offset) -+{ -+ if (class == PPE_QUEUE_CLASS_PRIORITY) -+ return ppe_queue_ucast_offset_pri_set(ppe_dev, 0, -+ index, queue_offset); -+ -+ return ppe_queue_ucast_offset_hash_set(ppe_dev, 0, -+ index, queue_offset); -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -0,0 +1,113 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_MAIN__ -+#define __EDMA_MAIN__ -+ -+#include "ppe_config.h" -+ -+/* One clock cycle = 1/(EDMA clock frequency in Mhz) micro seconds. -+ * -+ * One timer unit is 128 clock cycles. -+ * -+ * So, therefore the microsecond to timer unit calculation is: -+ * Timer unit = time in microseconds / (one clock cycle in microsecond * cycles in 1 timer unit) -+ * = ('x' microsecond * EDMA clock frequency in MHz ('y') / 128). -+ * -+ */ -+#define EDMA_CYCLE_PER_TIMER_UNIT 128 -+#define EDMA_MICROSEC_TO_TIMER_UNIT(x, y) ((x) * (y) / EDMA_CYCLE_PER_TIMER_UNIT) -+#define MHZ 1000000UL -+ -+/* EDMA profile ID. */ -+#define EDMA_CPU_PORT_PROFILE_ID 0 -+ -+/* Number of PPE queue priorities supported per ARM core. */ -+#define EDMA_PRI_MAX_PER_CORE 8 -+ -+/** -+ * enum ppe_queue_class_type - PPE queue class type -+ * @PPE_QUEUE_CLASS_PRIORITY: Queue offset configured from internal priority -+ * @PPE_QUEUE_CLASS_HASH: Queue offset configured from RSS hash. -+ */ -+enum ppe_queue_class_type { -+ PPE_QUEUE_CLASS_PRIORITY, -+ PPE_QUEUE_CLASS_HASH, -+}; -+ -+/** -+ * struct edma_ring_info - EDMA ring data structure. -+ * @max_rings: Maximum number of rings -+ * @ring_start: Ring start ID -+ * @num_rings: Number of rings -+ */ -+struct edma_ring_info { -+ u32 max_rings; -+ u32 ring_start; -+ u32 num_rings; -+}; -+ -+/** -+ * struct edma_hw_info - EDMA hardware data structure. -+ * @rxfill: Rx Fill ring information -+ * @rx: Rx Desc ring information -+ * @tx: Tx Desc ring information -+ * @txcmpl: Tx complete ring information -+ * @max_ports: Maximum number of ports -+ * @napi_budget_rx: Rx NAPI budget -+ * @napi_budget_tx: Tx NAPI budget -+ */ -+struct edma_hw_info { -+ struct edma_ring_info *rxfill; -+ struct edma_ring_info *rx; -+ struct edma_ring_info *tx; -+ struct edma_ring_info *txcmpl; -+ u32 max_ports; -+ u32 napi_budget_rx; -+ u32 napi_budget_tx; -+}; -+ -+/** -+ * struct edma_intr_info - EDMA interrupt data structure. -+ * @intr_mask_rx: RX interrupt mask -+ * @intr_rx: Rx interrupts -+ * @intr_mask_txcmpl: Tx completion interrupt mask -+ * @intr_txcmpl: Tx completion interrupts -+ * @intr_mask_misc: Miscellaneous interrupt mask -+ * @intr_misc: Miscellaneous interrupts -+ */ -+struct edma_intr_info { -+ u32 intr_mask_rx; -+ u32 *intr_rx; -+ u32 intr_mask_txcmpl; -+ u32 *intr_txcmpl; -+ u32 intr_mask_misc; -+ u32 intr_misc; -+}; -+ -+/** -+ * struct edma_context - EDMA context. -+ * @netdev_arr: Net device for each EDMA port -+ * @ppe_dev: PPE device -+ * @hw_info: EDMA Hardware info -+ * @intr_info: EDMA Interrupt info -+ */ -+struct edma_context { -+ struct net_device **netdev_arr; -+ struct ppe_device *ppe_dev; -+ struct edma_hw_info *hw_info; -+ struct edma_intr_info intr_info; -+}; -+ -+/* Global EDMA context. */ -+extern struct edma_context *edma_ctx; -+ -+void edma_destroy(struct ppe_device *ppe_dev); -+int edma_setup(struct ppe_device *ppe_dev); -+int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev, -+ enum ppe_queue_class_type class, -+ int index, int queue_offset); -+ -+ -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c -@@ -14,6 +14,7 @@ - #include - #include - -+#include "edma.h" - #include "ppe.h" - #include "ppe_config.h" - #include "ppe_debugfs.h" -@@ -201,10 +202,16 @@ static int qcom_ppe_probe(struct platfor - if (ret) - return dev_err_probe(dev, ret, "PPE HW config failed\n"); - -- ret = ppe_port_mac_init(ppe_dev); -+ ret = edma_setup(ppe_dev); - if (ret) -+ return dev_err_probe(dev, ret, "EDMA setup failed\n"); -+ -+ ret = ppe_port_mac_init(ppe_dev); -+ if (ret) { -+ edma_destroy(ppe_dev); - return dev_err_probe(dev, ret, - "PPE Port MAC initialization failed\n"); -+ } - - ppe_debugfs_setup(ppe_dev); - platform_set_drvdata(pdev, ppe_dev); -@@ -219,6 +226,7 @@ static void qcom_ppe_remove(struct platf - ppe_dev = platform_get_drvdata(pdev); - ppe_debugfs_teardown(ppe_dev); - ppe_port_mac_deinit(ppe_dev); -+ edma_destroy(ppe_dev); - - platform_set_drvdata(pdev, NULL); - } ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h -@@ -800,4 +800,257 @@ - #define XGMAC_RXDISCARD_GB_ADDR 0x9AC - #define XGMAC_RXDISCARDBYTE_GB_ADDR 0x9B4 - -+#define EDMA_BASE_OFFSET 0xb00000 -+ -+/* EDMA register offsets */ -+#define EDMA_REG_MAS_CTRL_ADDR 0x0 -+#define EDMA_REG_PORT_CTRL_ADDR 0x4 -+#define EDMA_REG_VLAN_CTRL_ADDR 0x8 -+#define EDMA_REG_RXDESC2FILL_MAP_0_ADDR 0x14 -+#define EDMA_REG_RXDESC2FILL_MAP_1_ADDR 0x18 -+#define EDMA_REG_RXDESC2FILL_MAP_2_ADDR 0x1c -+#define EDMA_REG_TXQ_CTRL_ADDR 0x20 -+#define EDMA_REG_TXQ_CTRL_2_ADDR 0x24 -+#define EDMA_REG_TXQ_FC_0_ADDR 0x28 -+#define EDMA_REG_TXQ_FC_1_ADDR 0x30 -+#define EDMA_REG_TXQ_FC_2_ADDR 0x34 -+#define EDMA_REG_TXQ_FC_3_ADDR 0x38 -+#define EDMA_REG_RXQ_CTRL_ADDR 0x3c -+#define EDMA_REG_MISC_ERR_QID_ADDR 0x40 -+#define EDMA_REG_RXQ_FC_THRE_ADDR 0x44 -+#define EDMA_REG_DMAR_CTRL_ADDR 0x48 -+#define EDMA_REG_AXIR_CTRL_ADDR 0x4c -+#define EDMA_REG_AXIW_CTRL_ADDR 0x50 -+#define EDMA_REG_MIN_MSS_ADDR 0x54 -+#define EDMA_REG_LOOPBACK_CTRL_ADDR 0x58 -+#define EDMA_REG_MISC_INT_STAT_ADDR 0x5c -+#define EDMA_REG_MISC_INT_MASK_ADDR 0x60 -+#define EDMA_REG_DBG_CTRL_ADDR 0x64 -+#define EDMA_REG_DBG_DATA_ADDR 0x68 -+#define EDMA_REG_TX_TIMEOUT_THRESH_ADDR 0x6c -+#define EDMA_REG_REQ0_FIFO_THRESH_ADDR 0x80 -+#define EDMA_REG_WB_OS_THRESH_ADDR 0x84 -+#define EDMA_REG_MISC_ERR_QID_REG2_ADDR 0x88 -+#define EDMA_REG_TXDESC2CMPL_MAP_0_ADDR 0x8c -+#define EDMA_REG_TXDESC2CMPL_MAP_1_ADDR 0x90 -+#define EDMA_REG_TXDESC2CMPL_MAP_2_ADDR 0x94 -+#define EDMA_REG_TXDESC2CMPL_MAP_3_ADDR 0x98 -+#define EDMA_REG_TXDESC2CMPL_MAP_4_ADDR 0x9c -+#define EDMA_REG_TXDESC2CMPL_MAP_5_ADDR 0xa0 -+ -+/* Tx descriptor ring configuration register addresses */ -+#define EDMA_REG_TXDESC_BA(n) (0x1000 + (0x1000 * (n))) -+#define EDMA_REG_TXDESC_PROD_IDX(n) (0x1004 + (0x1000 * (n))) -+#define EDMA_REG_TXDESC_CONS_IDX(n) (0x1008 + (0x1000 * (n))) -+#define EDMA_REG_TXDESC_RING_SIZE(n) (0x100c + (0x1000 * (n))) -+#define EDMA_REG_TXDESC_CTRL(n) (0x1010 + (0x1000 * (n))) -+#define EDMA_REG_TXDESC_BA2(n) (0x1014 + (0x1000 * (n))) -+ -+/* RxFill ring configuration register addresses */ -+#define EDMA_REG_RXFILL_BA(n) (0x29000 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_PROD_IDX(n) (0x29004 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_CONS_IDX(n) (0x29008 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_RING_SIZE(n) (0x2900c + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_BUFFER1_SIZE(n) (0x29010 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_FC_THRE(n) (0x29014 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_UGT_THRE(n) (0x29018 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_RING_EN(n) (0x2901c + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_DISABLE(n) (0x29020 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_DISABLE_DONE(n) (0x29024 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_INT_STAT(n) (0x31000 + (0x1000 * (n))) -+#define EDMA_REG_RXFILL_INT_MASK(n) (0x31004 + (0x1000 * (n))) -+ -+/* Rx descriptor ring configuration register addresses */ -+#define EDMA_REG_RXDESC_BA(n) (0x39000 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_PROD_IDX(n) (0x39004 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_CONS_IDX(n) (0x39008 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_RING_SIZE(n) (0x3900c + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_FC_THRE(n) (0x39010 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_UGT_THRE(n) (0x39014 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_CTRL(n) (0x39018 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_BPC(n) (0x3901c + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_DISABLE(n) (0x39020 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_DISABLE_DONE(n) (0x39024 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_PREHEADER_BA(n) (0x39028 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_INT_STAT(n) (0x59000 + (0x1000 * (n))) -+#define EDMA_REG_RXDESC_INT_MASK(n) (0x59004 + (0x1000 * (n))) -+ -+#define EDMA_REG_RX_MOD_TIMER(n) (0x59008 + (0x1000 * (n))) -+#define EDMA_REG_RX_INT_CTRL(n) (0x5900c + (0x1000 * (n))) -+ -+/* Tx completion ring configuration register addresses */ -+#define EDMA_REG_TXCMPL_BA(n) (0x79000 + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_PROD_IDX(n) (0x79004 + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_CONS_IDX(n) (0x79008 + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_RING_SIZE(n) (0x7900c + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_UGT_THRE(n) (0x79010 + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_CTRL(n) (0x79014 + (0x1000 * (n))) -+#define EDMA_REG_TXCMPL_BPC(n) (0x79018 + (0x1000 * (n))) -+ -+#define EDMA_REG_TX_INT_STAT(n) (0x99000 + (0x1000 * (n))) -+#define EDMA_REG_TX_INT_MASK(n) (0x99004 + (0x1000 * (n))) -+#define EDMA_REG_TX_MOD_TIMER(n) (0x99008 + (0x1000 * (n))) -+#define EDMA_REG_TX_INT_CTRL(n) (0x9900c + (0x1000 * (n))) -+ -+/* EDMA_QID2RID_TABLE_MEM register field masks */ -+#define EDMA_RX_RING_ID_QUEUE0_MASK GENMASK(7, 0) -+#define EDMA_RX_RING_ID_QUEUE1_MASK GENMASK(15, 8) -+#define EDMA_RX_RING_ID_QUEUE2_MASK GENMASK(23, 16) -+#define EDMA_RX_RING_ID_QUEUE3_MASK GENMASK(31, 24) -+ -+/* EDMA_REG_PORT_CTRL register bit definitions */ -+#define EDMA_PORT_PAD_EN 0x1 -+#define EDMA_PORT_EDMA_EN 0x2 -+ -+/* EDMA_REG_DMAR_CTRL register field masks */ -+#define EDMA_DMAR_REQ_PRI_MASK GENMASK(2, 0) -+#define EDMA_DMAR_BURST_LEN_MASK BIT(3) -+#define EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK GENMASK(8, 4) -+#define EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK GENMASK(11, 9) -+#define EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK GENMASK(14, 12) -+ -+#define EDMA_BURST_LEN_ENABLE 0 -+ -+/* Tx timeout threshold */ -+#define EDMA_TX_TIMEOUT_THRESH_VAL 0xFFFF -+ -+/* Rx descriptor ring base address mask */ -+#define EDMA_RXDESC_BA_MASK 0xffffffff -+ -+/* Rx Descriptor ring pre-header base address mask */ -+#define EDMA_RXDESC_PREHEADER_BA_MASK 0xffffffff -+ -+/* Tx descriptor prod ring index mask */ -+#define EDMA_TXDESC_PROD_IDX_MASK 0xffff -+ -+/* Tx descriptor consumer ring index mask */ -+#define EDMA_TXDESC_CONS_IDX_MASK 0xffff -+ -+/* Tx descriptor ring size mask */ -+#define EDMA_TXDESC_RING_SIZE_MASK 0xffff -+ -+/* Tx descriptor ring enable */ -+#define EDMA_TXDESC_TX_ENABLE 0x1 -+ -+#define EDMA_TXDESC_CTRL_TXEN_MASK BIT(0) -+#define EDMA_TXDESC_CTRL_FC_GRP_ID_MASK GENMASK(3, 1) -+ -+/* Tx completion ring prod index mask */ -+#define EDMA_TXCMPL_PROD_IDX_MASK 0xffff -+ -+/* Tx completion ring urgent threshold mask */ -+#define EDMA_TXCMPL_LOW_THRE_MASK 0xffff -+#define EDMA_TXCMPL_LOW_THRE_SHIFT 0 -+ -+/* EDMA_REG_TX_MOD_TIMER mask */ -+#define EDMA_TX_MOD_TIMER_INIT_MASK 0xffff -+#define EDMA_TX_MOD_TIMER_INIT_SHIFT 0 -+ -+/* Rx fill ring prod index mask */ -+#define EDMA_RXFILL_PROD_IDX_MASK 0xffff -+ -+/* Rx fill ring consumer index mask */ -+#define EDMA_RXFILL_CONS_IDX_MASK 0xffff -+ -+/* Rx fill ring size mask */ -+#define EDMA_RXFILL_RING_SIZE_MASK 0xffff -+ -+/* Rx fill ring flow control threshold masks */ -+#define EDMA_RXFILL_FC_XON_THRE_MASK 0x7ff -+#define EDMA_RXFILL_FC_XON_THRE_SHIFT 12 -+#define EDMA_RXFILL_FC_XOFF_THRE_MASK 0x7ff -+#define EDMA_RXFILL_FC_XOFF_THRE_SHIFT 0 -+ -+/* Rx fill ring enable bit */ -+#define EDMA_RXFILL_RING_EN 0x1 -+ -+/* Rx desc ring prod index mask */ -+#define EDMA_RXDESC_PROD_IDX_MASK 0xffff -+ -+/* Rx descriptor ring cons index mask */ -+#define EDMA_RXDESC_CONS_IDX_MASK 0xffff -+ -+/* Rx descriptor ring size masks */ -+#define EDMA_RXDESC_RING_SIZE_MASK 0xffff -+#define EDMA_RXDESC_PL_OFFSET_MASK 0x1ff -+#define EDMA_RXDESC_PL_OFFSET_SHIFT 16 -+#define EDMA_RXDESC_PL_DEFAULT_VALUE 0 -+ -+/* Rx descriptor ring flow control threshold masks */ -+#define EDMA_RXDESC_FC_XON_THRE_MASK 0x7ff -+#define EDMA_RXDESC_FC_XON_THRE_SHIFT 12 -+#define EDMA_RXDESC_FC_XOFF_THRE_MASK 0x7ff -+#define EDMA_RXDESC_FC_XOFF_THRE_SHIFT 0 -+ -+/* Rx descriptor ring urgent threshold mask */ -+#define EDMA_RXDESC_LOW_THRE_MASK 0xffff -+#define EDMA_RXDESC_LOW_THRE_SHIFT 0 -+ -+/* Rx descriptor ring enable bit */ -+#define EDMA_RXDESC_RX_EN 0x1 -+ -+/* Tx interrupt status bit */ -+#define EDMA_TX_INT_MASK_PKT_INT 0x1 -+ -+/* Rx interrupt mask */ -+#define EDMA_RXDESC_INT_MASK_PKT_INT 0x1 -+ -+#define EDMA_MASK_INT_DISABLE 0x0 -+#define EDMA_MASK_INT_CLEAR 0x0 -+ -+/* EDMA_REG_RX_MOD_TIMER register field masks */ -+#define EDMA_RX_MOD_TIMER_INIT_MASK 0xffff -+#define EDMA_RX_MOD_TIMER_INIT_SHIFT 0 -+ -+/* EDMA Ring mask */ -+#define EDMA_RING_DMA_MASK 0xffffffff -+ -+/* RXDESC threshold interrupt. */ -+#define EDMA_RXDESC_UGT_INT_STAT 0x2 -+ -+/* RXDESC timer interrupt */ -+#define EDMA_RXDESC_PKT_INT_STAT 0x1 -+ -+/* RXDESC Interrupt status mask */ -+#define EDMA_RXDESC_RING_INT_STATUS_MASK \ -+ (EDMA_RXDESC_UGT_INT_STAT | EDMA_RXDESC_PKT_INT_STAT) -+ -+/* TXCMPL threshold interrupt. */ -+#define EDMA_TXCMPL_UGT_INT_STAT 0x2 -+ -+/* TXCMPL timer interrupt */ -+#define EDMA_TXCMPL_PKT_INT_STAT 0x1 -+ -+/* TXCMPL Interrupt status mask */ -+#define EDMA_TXCMPL_RING_INT_STATUS_MASK \ -+ (EDMA_TXCMPL_UGT_INT_STAT | EDMA_TXCMPL_PKT_INT_STAT) -+ -+#define EDMA_TXCMPL_RETMODE_OPAQUE 0x0 -+ -+#define EDMA_RXDESC_LOW_THRE 0 -+#define EDMA_RX_MOD_TIMER_INIT 1000 -+#define EDMA_RX_NE_INT_EN 0x2 -+ -+#define EDMA_TX_MOD_TIMER 150 -+ -+#define EDMA_TX_INITIAL_PROD_IDX 0x0 -+#define EDMA_TX_NE_INT_EN 0x2 -+ -+/* EDMA misc error mask */ -+#define EDMA_MISC_AXI_RD_ERR_MASK BIT(0) -+#define EDMA_MISC_AXI_WR_ERR_MASK BIT(1) -+#define EDMA_MISC_RX_DESC_FIFO_FULL_MASK BIT(2) -+#define EDMA_MISC_RX_ERR_BUF_SIZE_MASK BIT(3) -+#define EDMA_MISC_TX_SRAM_FULL_MASK BIT(4) -+#define EDMA_MISC_TX_CMPL_BUF_FULL_MASK BIT(5) -+ -+#define EDMA_MISC_DATA_LEN_ERR_MASK BIT(6) -+#define EDMA_MISC_TX_TIMEOUT_MASK BIT(7) -+ -+/* EDMA txdesc2cmpl map */ -+#define EDMA_TXDESC2CMPL_MAP_TXDESC_MASK 0x1F -+ -+/* EDMA rxdesc2fill map */ -+#define EDMA_RXDESC2FILL_MAP_RXDESC_MASK 0x7 -+ - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0343-net-ethernet-qualcomm-Add-netdevice-support-for-QCOM.patch b/target/linux/qualcommbe/patches-6.12/0343-net-ethernet-qualcomm-Add-netdevice-support-for-QCOM.patch deleted file mode 100644 index 55de486ed3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0343-net-ethernet-qualcomm-Add-netdevice-support-for-QCOM.patch +++ /dev/null @@ -1,397 +0,0 @@ -From 5dc80c468c668d855d76b323f09bbadb95cc3147 Mon Sep 17 00:00:00 2001 -From: Suruchi Agarwal -Date: Thu, 21 Mar 2024 16:14:46 -0700 -Subject: [PATCH] net: ethernet: qualcomm: Add netdevice support for QCOM - IPQ9574 chipset. - -Add EDMA ports and netdevice operations for QCOM IPQ9574 chipset. - -Change-Id: I08b2eff52b4ef0d6d428c1c416f5580ef010973f -Co-developed-by: Pavithra R -Signed-off-by: Pavithra R -Signed-off-by: Suruchi Agarwal ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/edma.h | 3 + - drivers/net/ethernet/qualcomm/ppe/edma_port.c | 270 ++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma_port.h | 31 ++ - drivers/net/ethernet/qualcomm/ppe/ppe_port.c | 19 ++ - 5 files changed, 324 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_port.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_port.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o - - #EDMA --qcom-ppe-objs += edma.o -+qcom-ppe-objs += edma.o edma_port.o ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -26,6 +26,9 @@ - /* Number of PPE queue priorities supported per ARM core. */ - #define EDMA_PRI_MAX_PER_CORE 8 - -+/* Interface ID start. */ -+#define EDMA_START_IFNUM 1 -+ - /** - * enum ppe_queue_class_type - PPE queue class type - * @PPE_QUEUE_CLASS_PRIORITY: Queue offset configured from internal priority ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c -@@ -0,0 +1,270 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ /* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* EDMA port initialization, configuration and netdevice ops handling */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_port.h" -+#include "ppe_regs.h" -+ -+/* Number of netdev queues. */ -+#define EDMA_NETDEV_QUEUE_NUM 4 -+ -+static u16 __maybe_unused edma_port_select_queue(__maybe_unused struct net_device *netdev, -+ __maybe_unused struct sk_buff *skb, -+ __maybe_unused struct net_device *sb_dev) -+{ -+ int cpu = get_cpu(); -+ -+ put_cpu(); -+ -+ return cpu; -+} -+ -+static int edma_port_open(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ /* Inform the Linux Networking stack about the hardware capability of -+ * checksum offloading and other features. Each port is -+ * responsible to maintain the feature set it supports. -+ */ -+ netdev->features |= EDMA_NETDEV_FEATURES; -+ netdev->hw_features |= EDMA_NETDEV_FEATURES; -+ netdev->vlan_features |= EDMA_NETDEV_FEATURES; -+ netdev->wanted_features |= EDMA_NETDEV_FEATURES; -+ -+ ppe_port = port_priv->ppe_port; -+ -+ if (ppe_port->phylink) -+ phylink_start(ppe_port->phylink); -+ -+ netif_start_queue(netdev); -+ -+ return 0; -+} -+ -+static int edma_port_close(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ netif_stop_queue(netdev); -+ -+ ppe_port = port_priv->ppe_port; -+ -+ /* Phylink close. */ -+ if (ppe_port->phylink) -+ phylink_stop(ppe_port->phylink); -+ -+ return 0; -+} -+ -+static int edma_port_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *ppe_port; -+ int ret = -EINVAL; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ ppe_port = port_priv->ppe_port; -+ if (ppe_port->phylink) -+ return phylink_mii_ioctl(ppe_port->phylink, ifr, cmd); -+ -+ return ret; -+} -+ -+static int edma_port_change_mtu(struct net_device *netdev, int mtu) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ netdev->mtu = mtu; -+ -+ return ppe_port_set_maxframe(port_priv->ppe_port, mtu); -+} -+ -+static netdev_features_t edma_port_feature_check(__maybe_unused struct sk_buff *skb, -+ __maybe_unused struct net_device *netdev, -+ netdev_features_t features) -+{ -+ return features; -+} -+ -+static void edma_port_get_stats64(struct net_device *netdev, -+ struct rtnl_link_stats64 *stats) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ -+ if (!port_priv) -+ return; -+ -+ ppe_port_get_stats64(port_priv->ppe_port, stats); -+} -+ -+static int edma_port_set_mac_address(struct net_device *netdev, void *macaddr) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct sockaddr *addr = (struct sockaddr *)macaddr; -+ int ret; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ netdev_dbg(netdev, "AddrFamily: %d, %0x:%0x:%0x:%0x:%0x:%0x\n", -+ addr->sa_family, addr->sa_data[0], addr->sa_data[1], -+ addr->sa_data[2], addr->sa_data[3], addr->sa_data[4], -+ addr->sa_data[5]); -+ -+ ret = eth_prepare_mac_addr_change(netdev, addr); -+ if (ret) -+ return ret; -+ -+ if (ppe_port_set_mac_address(port_priv->ppe_port, (u8 *)addr)) { -+ netdev_err(netdev, "set mac address failed for dev: %s\n", netdev->name); -+ return -EINVAL; -+ } -+ -+ eth_commit_mac_addr_change(netdev, addr); -+ -+ return 0; -+} -+ -+static const struct net_device_ops edma_port_netdev_ops = { -+ .ndo_open = edma_port_open, -+ .ndo_stop = edma_port_close, -+ .ndo_get_stats64 = edma_port_get_stats64, -+ .ndo_set_mac_address = edma_port_set_mac_address, -+ .ndo_validate_addr = eth_validate_addr, -+ .ndo_change_mtu = edma_port_change_mtu, -+ .ndo_eth_ioctl = edma_port_ioctl, -+ .ndo_features_check = edma_port_feature_check, -+ .ndo_select_queue = edma_port_select_queue, -+}; -+ -+/** -+ * edma_port_destroy - EDMA port destroy. -+ * @port: PPE port -+ * -+ * Unregister and free the netdevice. -+ */ -+void edma_port_destroy(struct ppe_port *port) -+{ -+ int port_id = port->port_id; -+ struct net_device *netdev = edma_ctx->netdev_arr[port_id - 1]; -+ -+ unregister_netdev(netdev); -+ free_netdev(netdev); -+ ppe_port_phylink_destroy(port); -+ edma_ctx->netdev_arr[port_id - 1] = NULL; -+} -+ -+/** -+ * edma_port_setup - EDMA port Setup. -+ * @port: PPE port -+ * -+ * Initialize and register the netdevice. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int edma_port_setup(struct ppe_port *port) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device_node *np = port->np; -+ struct edma_port_priv *port_priv; -+ int port_id = port->port_id; -+ struct net_device *netdev; -+ u8 mac_addr[ETH_ALEN]; -+ int ret = 0; -+ u8 *maddr; -+ -+ netdev = alloc_etherdev_mqs(sizeof(struct edma_port_priv), -+ EDMA_NETDEV_QUEUE_NUM, EDMA_NETDEV_QUEUE_NUM); -+ if (!netdev) { -+ pr_err("alloc_etherdev() failed\n"); -+ return -ENOMEM; -+ } -+ -+ SET_NETDEV_DEV(netdev, ppe_dev->dev); -+ netdev->dev.of_node = np; -+ -+ /* max_mtu is set to 1500 in ether_setup(). */ -+ netdev->max_mtu = ETH_MAX_MTU; -+ -+ port_priv = netdev_priv(netdev); -+ memset((void *)port_priv, 0, sizeof(struct edma_port_priv)); -+ -+ port_priv->ppe_port = port; -+ port_priv->netdev = netdev; -+ netdev->watchdog_timeo = 5 * HZ; -+ netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; -+ netdev->netdev_ops = &edma_port_netdev_ops; -+ netdev->gso_max_segs = GSO_MAX_SEGS; -+ -+ maddr = mac_addr; -+ if (of_get_mac_address(np, maddr)) -+ maddr = NULL; -+ -+ if (maddr && is_valid_ether_addr(maddr)) { -+ eth_hw_addr_set(netdev, maddr); -+ } else { -+ eth_hw_addr_random(netdev); -+ netdev_info(netdev, "GMAC%d Using random MAC address - %pM\n", -+ port_id, netdev->dev_addr); -+ } -+ -+ netdev_dbg(netdev, "Configuring the port %s(qcom-id:%d)\n", -+ netdev->name, port_id); -+ -+ /* We expect 'port_id' to correspond to ports numbers on SoC. -+ * These begin from '1' and hence we subtract -+ * one when using it as an array index. -+ */ -+ edma_ctx->netdev_arr[port_id - 1] = netdev; -+ -+ /* Setup phylink. */ -+ ret = ppe_port_phylink_setup(port, netdev); -+ if (ret) { -+ netdev_dbg(netdev, "EDMA port phylink setup for netdevice %s\n", -+ netdev->name); -+ goto port_phylink_setup_fail; -+ } -+ -+ /* Register the network interface. */ -+ ret = register_netdev(netdev); -+ if (ret) { -+ netdev_dbg(netdev, "Error registering netdevice %s\n", -+ netdev->name); -+ goto register_netdev_fail; -+ } -+ -+ netdev_dbg(netdev, "Setup EDMA port GMAC%d done\n", port_id); -+ return ret; -+ -+register_netdev_fail: -+ ppe_port_phylink_destroy(port); -+port_phylink_setup_fail: -+ free_netdev(netdev); -+ edma_ctx->netdev_arr[port_id - 1] = NULL; -+ -+ return ret; -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.h -@@ -0,0 +1,31 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_PORTS__ -+#define __EDMA_PORTS__ -+ -+#include "ppe_port.h" -+ -+#define EDMA_NETDEV_FEATURES (NETIF_F_FRAGLIST \ -+ | NETIF_F_SG \ -+ | NETIF_F_RXCSUM \ -+ | NETIF_F_HW_CSUM \ -+ | NETIF_F_TSO \ -+ | NETIF_F_TSO6) -+ -+/** -+ * struct edma_port_priv - EDMA port priv structure. -+ * @ppe_port: Pointer to PPE port -+ * @netdev: Corresponding netdevice -+ * @flags: Feature flags -+ */ -+struct edma_port_priv { -+ struct ppe_port *ppe_port; -+ struct net_device *netdev; -+ unsigned long flags; -+}; -+ -+void edma_port_destroy(struct ppe_port *port); -+int edma_port_setup(struct ppe_port *port); -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_port.c -@@ -13,6 +13,7 @@ - #include - #include - -+#include "edma_port.h" - #include "ppe.h" - #include "ppe_port.h" - #include "ppe_regs.h" -@@ -1277,12 +1278,26 @@ int ppe_port_mac_init(struct ppe_device - goto err_port_node; - } - -+ ret = edma_port_setup(&ppe_ports->port[i]); -+ if (ret) { -+ dev_err(ppe_dev->dev, "QCOM EDMA port setup failed\n"); -+ i--; -+ goto err_port_setup; -+ } -+ - i++; - } - - of_node_put(ports_node); - return 0; - -+err_port_setup: -+ /* Destroy edma ports created till now */ -+ while (i >= 0) { -+ edma_port_destroy(&ppe_ports->port[i]); -+ i--; -+ } -+ - err_port_clk: - for (j = 0; j < i; j++) - ppe_port_clock_deinit(&ppe_ports->port[j]); -@@ -1307,6 +1322,10 @@ void ppe_port_mac_deinit(struct ppe_devi - - for (i = 0; i < ppe_dev->ports->num; i++) { - ppe_port = &ppe_dev->ports->port[i]; -+ -+ /* Destroy all phylinks and edma ports */ -+ edma_port_destroy(ppe_port); -+ - ppe_port_clock_deinit(ppe_port); - } - } diff --git a/target/linux/qualcommbe/patches-6.12/0344-net-ethernet-qualcomm-Add-Rx-Ethernet-DMA-support.patch b/target/linux/qualcommbe/patches-6.12/0344-net-ethernet-qualcomm-Add-Rx-Ethernet-DMA-support.patch deleted file mode 100644 index eb10a00745..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0344-net-ethernet-qualcomm-Add-Rx-Ethernet-DMA-support.patch +++ /dev/null @@ -1,2454 +0,0 @@ -From b5c8c5d3888328321e8be1db50b75dff8f514e51 Mon Sep 17 00:00:00 2001 -From: Suruchi Agarwal -Date: Thu, 21 Mar 2024 16:21:19 -0700 -Subject: [PATCH] net: ethernet: qualcomm: Add Rx Ethernet DMA support - -Add Rx queues, rings, descriptors configurations and -DMA support for the EDMA. - -Change-Id: I612bcd661e74d5bf3ecb33de10fd5298d18ff7e9 -Co-developed-by: Pavithra R -Signed-off-by: Pavithra R -Signed-off-by: Suruchi Agarwal -Alex G: add missing functions that were previously in ppe_api.c: - - ppe_edma_queue_resource_get() - - ppe_edma_ring_to_queues_config() -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/edma.c | 214 +++- - drivers/net/ethernet/qualcomm/ppe/edma.h | 22 +- - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.c | 964 ++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.h | 48 + - drivers/net/ethernet/qualcomm/ppe/edma_port.c | 39 +- - drivers/net/ethernet/qualcomm/ppe/edma_port.h | 31 + - drivers/net/ethernet/qualcomm/ppe/edma_rx.c | 622 +++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma_rx.h | 287 ++++++ - 9 files changed, 2224 insertions(+), 5 deletions(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_rx.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_rx.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o - - #EDMA --qcom-ppe-objs += edma.o edma_port.o -+qcom-ppe-objs += edma.o edma_cfg_rx.o edma_port.o edma_rx.o ---- a/drivers/net/ethernet/qualcomm/ppe/edma.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -18,12 +18,23 @@ - #include - - #include "edma.h" -+#include "edma_cfg_rx.h" - #include "ppe_regs.h" - - #define EDMA_IRQ_NAME_SIZE 32 - - /* Global EDMA context. */ - struct edma_context *edma_ctx; -+static char **edma_rxdesc_irq_name; -+ -+/* Module params. */ -+static int page_mode; -+module_param(page_mode, int, 0); -+MODULE_PARM_DESC(page_mode, "Enable page mode (default:0)"); -+ -+static int rx_buff_size; -+module_param(rx_buff_size, int, 0640); -+MODULE_PARM_DESC(rx_buff_size, "Rx Buffer size for Jumbo MRU value (default:0)"); - - /* Priority to multi-queue mapping. */ - static u8 edma_pri_map[PPE_QUEUE_INTER_PRI_NUM] = { -@@ -178,6 +189,59 @@ static int edma_configure_ucast_prio_map - return ret; - } - -+static int edma_irq_register(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ int ret; -+ u32 i; -+ -+ /* Request IRQ for RXDESC rings. */ -+ edma_rxdesc_irq_name = kzalloc((sizeof(char *) * rx->num_rings), -+ GFP_KERNEL); -+ if (!edma_rxdesc_irq_name) -+ return -ENOMEM; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ edma_rxdesc_irq_name[i] = kzalloc((sizeof(char *) * EDMA_IRQ_NAME_SIZE), -+ GFP_KERNEL); -+ if (!edma_rxdesc_irq_name[i]) { -+ ret = -ENOMEM; -+ goto rxdesc_irq_name_alloc_fail; -+ } -+ -+ snprintf(edma_rxdesc_irq_name[i], 20, "edma_rxdesc_%d", -+ rx->ring_start + i); -+ -+ irq_set_status_flags(edma_ctx->intr_info.intr_rx[i], IRQ_DISABLE_UNLAZY); -+ -+ ret = request_irq(edma_ctx->intr_info.intr_rx[i], -+ edma_rx_handle_irq, IRQF_SHARED, -+ edma_rxdesc_irq_name[i], -+ (void *)&edma_ctx->rx_rings[i]); -+ if (ret) { -+ pr_err("RXDESC ring IRQ:%d request failed\n", -+ edma_ctx->intr_info.intr_rx[i]); -+ goto rx_desc_ring_intr_req_fail; -+ } -+ -+ pr_debug("RXDESC ring: %d IRQ:%d request success: %s\n", -+ rx->ring_start + i, -+ edma_ctx->intr_info.intr_rx[i], -+ edma_rxdesc_irq_name[i]); -+ } -+ -+ return 0; -+ -+rx_desc_ring_intr_req_fail: -+ for (i = 0; i < rx->num_rings; i++) -+ kfree(edma_rxdesc_irq_name[i]); -+rxdesc_irq_name_alloc_fail: -+ kfree(edma_rxdesc_irq_name); -+ -+ return ret; -+} -+ - static int edma_irq_init(void) - { - struct edma_hw_info *hw_info = edma_ctx->hw_info; -@@ -260,6 +324,16 @@ static int edma_irq_init(void) - return 0; - } - -+static int edma_alloc_rings(void) -+{ -+ if (edma_cfg_rx_rings_alloc()) { -+ pr_err("Error in allocating Rx rings\n"); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ - static int edma_hw_reset(void) - { - struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -@@ -343,6 +417,40 @@ static int edma_hw_configure(void) - if (!edma_ctx->netdev_arr) - return -ENOMEM; - -+ edma_ctx->dummy_dev = alloc_netdev_dummy(0); -+ if (!edma_ctx->dummy_dev) { -+ ret = -ENOMEM; -+ pr_err("Failed to allocate dummy device. ret: %d\n", ret); -+ goto dummy_dev_alloc_failed; -+ } -+ -+ /* Set EDMA jumbo MRU if enabled or set page mode. */ -+ if (edma_ctx->rx_buf_size) { -+ edma_ctx->rx_page_mode = false; -+ pr_debug("Rx Jumbo mru is enabled: %d\n", edma_ctx->rx_buf_size); -+ } else { -+ edma_ctx->rx_page_mode = page_mode; -+ } -+ -+ ret = edma_alloc_rings(); -+ if (ret) { -+ pr_err("Error in initializaing the rings. ret: %d\n", ret); -+ goto edma_alloc_rings_failed; -+ } -+ -+ /* Disable interrupts. */ -+ edma_cfg_rx_disable_interrupts(); -+ -+ edma_cfg_rx_rings_disable(); -+ -+ edma_cfg_rx_ring_mappings(); -+ -+ ret = edma_cfg_rx_rings(); -+ if (ret) { -+ pr_err("Error in configuring Rx rings. ret: %d\n", ret); -+ goto edma_cfg_rx_rings_failed; -+ } -+ - /* Configure DMA request priority, DMA read burst length, - * and AXI write size. - */ -@@ -376,6 +484,10 @@ static int edma_hw_configure(void) - data |= EDMA_MISC_TX_TIMEOUT_MASK; - edma_ctx->intr_info.intr_mask_misc = data; - -+ edma_cfg_rx_rings_enable(); -+ edma_cfg_rx_napi_add(); -+ edma_cfg_rx_napi_enable(); -+ - /* Global EDMA enable and padding enable. */ - data = EDMA_PORT_PAD_EN | EDMA_PORT_EDMA_EN; - -@@ -389,11 +501,32 @@ static int edma_hw_configure(void) - if (ret) { - pr_err("Failed to initialize unicast priority map table: %d\n", - ret); -- kfree(edma_ctx->netdev_arr); -- return ret; -+ goto configure_ucast_prio_map_tbl_failed; -+ } -+ -+ /* Initialize RPS hash map table. */ -+ ret = edma_cfg_rx_rps_hash_map(); -+ if (ret) { -+ pr_err("Failed to configure rps hash table: %d\n", -+ ret); -+ goto edma_cfg_rx_rps_hash_map_failed; - } - - return 0; -+ -+edma_cfg_rx_rps_hash_map_failed: -+configure_ucast_prio_map_tbl_failed: -+ edma_cfg_rx_napi_disable(); -+ edma_cfg_rx_napi_delete(); -+ edma_cfg_rx_rings_disable(); -+edma_cfg_rx_rings_failed: -+ edma_cfg_rx_rings_cleanup(); -+edma_alloc_rings_failed: -+ free_netdev(edma_ctx->dummy_dev); -+dummy_dev_alloc_failed: -+ kfree(edma_ctx->netdev_arr); -+ -+ return ret; - } - - /** -@@ -404,8 +537,31 @@ static int edma_hw_configure(void) - */ - void edma_destroy(struct ppe_device *ppe_dev) - { -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ /* Disable interrupts. */ -+ edma_cfg_rx_disable_interrupts(); -+ -+ /* Free IRQ for RXDESC rings. */ -+ for (i = 0; i < rx->num_rings; i++) { -+ synchronize_irq(edma_ctx->intr_info.intr_rx[i]); -+ free_irq(edma_ctx->intr_info.intr_rx[i], -+ (void *)&edma_ctx->rx_rings[i]); -+ kfree(edma_rxdesc_irq_name[i]); -+ } -+ kfree(edma_rxdesc_irq_name); -+ - kfree(edma_ctx->intr_info.intr_rx); - kfree(edma_ctx->intr_info.intr_txcmpl); -+ -+ edma_cfg_rx_napi_disable(); -+ edma_cfg_rx_napi_delete(); -+ edma_cfg_rx_rings_disable(); -+ edma_cfg_rx_rings_cleanup(); -+ -+ free_netdev(edma_ctx->dummy_dev); - kfree(edma_ctx->netdev_arr); - } - -@@ -428,6 +584,7 @@ int edma_setup(struct ppe_device *ppe_de - - edma_ctx->hw_info = &ipq9574_hw_info; - edma_ctx->ppe_dev = ppe_dev; -+ edma_ctx->rx_buf_size = rx_buff_size; - - /* Configure the EDMA common clocks. */ - ret = edma_clock_init(); -@@ -450,6 +607,16 @@ int edma_setup(struct ppe_device *ppe_de - return ret; - } - -+ ret = edma_irq_register(); -+ if (ret) { -+ dev_err(dev, "Error in irq registration\n"); -+ kfree(edma_ctx->intr_info.intr_rx); -+ kfree(edma_ctx->intr_info.intr_txcmpl); -+ return ret; -+ } -+ -+ edma_cfg_rx_enable_interrupts(); -+ - dev_info(dev, "EDMA configuration successful\n"); - - return 0; -@@ -478,3 +645,46 @@ int ppe_edma_queue_offset_config(struct - return ppe_queue_ucast_offset_hash_set(ppe_dev, 0, - index, queue_offset); - } -+ -+/** -+ * ppe_edma_queue_resource_get - Get EDMA queue resource -+ * @ppe_dev: PPE device -+ * @type: Resource type -+ * @res_start: Resource start ID returned -+ * @res_end: Resource end ID returned -+ * -+ * PPE EDMA queue resource includes unicast queue and multicast queue. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int ppe_edma_queue_resource_get(struct ppe_device *ppe_dev, int type, -+ int *res_start, int *res_end) -+{ -+ if (type != PPE_RES_UCAST && type != PPE_RES_MCAST) -+ return -EINVAL; -+ -+ return ppe_port_resource_get(ppe_dev, 0, type, res_start, res_end); -+}; -+ -+/** -+ * ppe_edma_ring_to_queues_config - Map EDMA ring to PPE queues -+ * @ppe_dev: PPE device -+ * @ring_id: EDMA ring ID -+ * @num: Number of queues mapped to EDMA ring -+ * @queues: PPE queue IDs -+ * -+ * PPE queues are configured to map with the special EDMA ring ID. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int ppe_edma_ring_to_queues_config(struct ppe_device *ppe_dev, int ring_id, -+ int num, int queues[] __counted_by(num)) -+{ -+ u32 queue_bmap[PPE_RING_TO_QUEUE_BITMAP_WORD_CNT] = {}; -+ int index; -+ -+ for (index = 0; index < num; index++) -+ queue_bmap[queues[index] / 32] |= BIT_MASK(queues[index] % 32); -+ -+ return ppe_ring_queue_map_set(ppe_dev, ring_id, queue_bmap); -+} ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -6,6 +6,7 @@ - #define __EDMA_MAIN__ - - #include "ppe_config.h" -+#include "edma_rx.h" - - /* One clock cycle = 1/(EDMA clock frequency in Mhz) micro seconds. - * -@@ -29,6 +30,11 @@ - /* Interface ID start. */ - #define EDMA_START_IFNUM 1 - -+#define EDMA_DESC_AVAIL_COUNT(head, tail, _max) ({ \ -+ typeof(_max) (max) = (_max); \ -+ ((((head) - (tail)) + \ -+ (max)) & ((max) - 1)); }) -+ - /** - * enum ppe_queue_class_type - PPE queue class type - * @PPE_QUEUE_CLASS_PRIORITY: Queue offset configured from internal priority -@@ -92,18 +98,28 @@ struct edma_intr_info { - /** - * struct edma_context - EDMA context. - * @netdev_arr: Net device for each EDMA port -+ * @dummy_dev: Dummy netdevice for RX DMA - * @ppe_dev: PPE device - * @hw_info: EDMA Hardware info - * @intr_info: EDMA Interrupt info -+ * @rxfill_rings: Rx fill Rings, SW is producer -+ * @rx_rings: Rx Desc Rings, SW is consumer -+ * @rx_page_mode: Page mode enabled or disabled -+ * @rx_buf_size: Rx buffer size for Jumbo MRU - */ - struct edma_context { - struct net_device **netdev_arr; -+ struct net_device *dummy_dev; - struct ppe_device *ppe_dev; - struct edma_hw_info *hw_info; - struct edma_intr_info intr_info; -+ struct edma_rxfill_ring *rxfill_rings; -+ struct edma_rxdesc_ring *rx_rings; -+ u32 rx_page_mode; -+ u32 rx_buf_size; - }; - --/* Global EDMA context. */ -+/* Global EDMA context */ - extern struct edma_context *edma_ctx; - - void edma_destroy(struct ppe_device *ppe_dev); -@@ -111,6 +127,10 @@ int edma_setup(struct ppe_device *ppe_de - int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev, - enum ppe_queue_class_type class, - int index, int queue_offset); -+int ppe_edma_queue_resource_get(struct ppe_device *ppe_dev, int type, -+ int *res_start, int *res_end); -+int ppe_edma_ring_to_queues_config(struct ppe_device *ppe_dev, int ring_id, -+ int num, int queues[] __counted_by(num)); - - - #endif ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c -@@ -0,0 +1,964 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* Configure rings, Buffers and NAPI for receive path along with -+ * providing APIs to enable, disable, clean and map the Rx rings. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_cfg_rx.h" -+#include "ppe.h" -+#include "ppe_regs.h" -+ -+/* EDMA Queue ID to Ring ID Table. */ -+#define EDMA_QID2RID_TABLE_MEM(q) (0xb9000 + (0x4 * (q))) -+ -+/* Rx ring queue offset. */ -+#define EDMA_QUEUE_OFFSET(q_id) ((q_id) / EDMA_MAX_PRI_PER_CORE) -+ -+/* Rx EDMA maximum queue supported. */ -+#define EDMA_CPU_PORT_QUEUE_MAX(queue_start) \ -+ ((queue_start) + (EDMA_MAX_PRI_PER_CORE * num_possible_cpus()) - 1) -+ -+/* EDMA Queue ID to Ring ID configuration. */ -+#define EDMA_QID2RID_NUM_PER_REG 4 -+ -+int rx_queues[] = {0, 8, 16, 24}; -+ -+static u32 edma_rx_ring_queue_map[][EDMA_MAX_CORE] = {{ 0, 8, 16, 24 }, -+ { 1, 9, 17, 25 }, -+ { 2, 10, 18, 26 }, -+ { 3, 11, 19, 27 }, -+ { 4, 12, 20, 28 }, -+ { 5, 13, 21, 29 }, -+ { 6, 14, 22, 30 }, -+ { 7, 15, 23, 31 }}; -+ -+static int edma_cfg_rx_desc_rings_reset_queue_mapping(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, ret; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ ret = ppe_edma_ring_to_queues_config(edma_ctx->ppe_dev, rxdesc_ring->ring_id, -+ ARRAY_SIZE(rx_queues), rx_queues); -+ if (ret) { -+ pr_err("Error in unmapping rxdesc ring %d to PPE queue mapping to disable its backpressure configuration\n", -+ i); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int edma_cfg_rx_desc_ring_reset_queue_priority(u32 rxdesc_ring_idx) -+{ -+ u32 i, queue_id, ret; -+ -+ for (i = 0; i < EDMA_MAX_PRI_PER_CORE; i++) { -+ queue_id = edma_rx_ring_queue_map[i][rxdesc_ring_idx]; -+ -+ ret = ppe_queue_priority_set(edma_ctx->ppe_dev, queue_id, i); -+ if (ret) { -+ pr_err("Error in resetting %u queue's priority\n", -+ queue_id); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int edma_cfg_rx_desc_ring_reset_queue_config(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, ret; -+ -+ if (unlikely(rx->num_rings > num_possible_cpus())) { -+ pr_err("Invalid count of rxdesc rings: %d\n", -+ rx->num_rings); -+ return -EINVAL; -+ } -+ -+ /* Unmap Rxdesc ring to PPE queue mapping */ -+ ret = edma_cfg_rx_desc_rings_reset_queue_mapping(); -+ if (ret) { -+ pr_err("Error in resetting Rx desc ring backpressure config\n"); -+ return ret; -+ } -+ -+ /* Reset the priority for PPE queues mapped to Rx rings */ -+ for (i = 0; i < rx->num_rings; i++) { -+ ret = edma_cfg_rx_desc_ring_reset_queue_priority(i); -+ if (ret) { -+ pr_err("Error in resetting ring:%d queue's priority\n", -+ i + rx->ring_start); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int edma_cfg_rx_desc_ring_to_queue_mapping(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ int ret; -+ -+ /* Rxdesc ring to PPE queue mapping */ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ ret = ppe_edma_ring_to_queues_config(edma_ctx->ppe_dev, -+ rxdesc_ring->ring_id, -+ ARRAY_SIZE(rx_queues), rx_queues); -+ if (ret) { -+ pr_err("Error in configuring Rx ring to PPE queue mapping, ret: %d, id: %d\n", -+ ret, rxdesc_ring->ring_id); -+ if (!edma_cfg_rx_desc_rings_reset_queue_mapping()) -+ pr_err("Error in resetting Rx desc ringbackpressure configurations\n"); -+ -+ return ret; -+ } -+ -+ pr_debug("Rx desc ring %d to PPE queue mapping for backpressure:\n", -+ rxdesc_ring->ring_id); -+ } -+ -+ return 0; -+} -+ -+static void edma_cfg_rx_desc_ring_configure(struct edma_rxdesc_ring *rxdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 data, reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_BA(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, (u32)(rxdesc_ring->pdma & EDMA_RXDESC_BA_MASK)); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_PREHEADER_BA(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, (u32)(rxdesc_ring->sdma & EDMA_RXDESC_PREHEADER_BA_MASK)); -+ -+ data = rxdesc_ring->count & EDMA_RXDESC_RING_SIZE_MASK; -+ data |= (EDMA_RXDESC_PL_DEFAULT_VALUE & EDMA_RXDESC_PL_OFFSET_MASK) -+ << EDMA_RXDESC_PL_OFFSET_SHIFT; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_RING_SIZE(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, data); -+ -+ /* Configure the Mitigation timer */ -+ data = EDMA_MICROSEC_TO_TIMER_UNIT(EDMA_RX_MITIGATION_TIMER_DEF, -+ ppe_dev->clk_rate / MHZ); -+ data = ((data & EDMA_RX_MOD_TIMER_INIT_MASK) -+ << EDMA_RX_MOD_TIMER_INIT_SHIFT); -+ pr_debug("EDMA Rx mitigation timer value: %d\n", data); -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RX_MOD_TIMER(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, data); -+ -+ /* Configure the Mitigation packet count */ -+ data = (EDMA_RX_MITIGATION_PKT_CNT_DEF & EDMA_RXDESC_LOW_THRE_MASK) -+ << EDMA_RXDESC_LOW_THRE_SHIFT; -+ pr_debug("EDMA Rx mitigation packet count value: %d\n", data); -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_UGT_THRE(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, data); -+ -+ /* Enable ring. Set ret mode to 'opaque'. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RX_INT_CTRL(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, EDMA_RX_NE_INT_EN); -+} -+ -+static void edma_cfg_rx_qid_to_rx_desc_ring_mapping(void) -+{ -+ u32 desc_index, ring_index, reg_index, data, q_id; -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 mcast_start, mcast_end, reg; -+ int ret; -+ -+ desc_index = (rx->ring_start & EDMA_RX_RING_ID_MASK); -+ -+ /* Here map all the queues to ring. */ -+ for (q_id = EDMA_RX_QUEUE_START; -+ q_id <= EDMA_CPU_PORT_QUEUE_MAX(EDMA_RX_QUEUE_START); -+ q_id += EDMA_QID2RID_NUM_PER_REG) { -+ reg_index = q_id / EDMA_QID2RID_NUM_PER_REG; -+ ring_index = desc_index + EDMA_QUEUE_OFFSET(q_id); -+ -+ data = FIELD_PREP(EDMA_RX_RING_ID_QUEUE0_MASK, ring_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE1_MASK, ring_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE2_MASK, ring_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE3_MASK, ring_index); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_QID2RID_TABLE_MEM(reg_index); -+ regmap_write(regmap, reg, data); -+ pr_debug("Configure QID2RID: %d reg:0x%x to 0x%x, desc_index: %d, reg_index: %d\n", -+ q_id, EDMA_QID2RID_TABLE_MEM(reg_index), data, desc_index, reg_index); -+ } -+ -+ ret = ppe_edma_queue_resource_get(edma_ctx->ppe_dev, PPE_RES_MCAST, -+ &mcast_start, &mcast_end); -+ if (ret < 0) { -+ pr_err("Error in extracting multicast queue values\n"); -+ return; -+ } -+ -+ /* Map multicast queues to the first Rx ring. */ -+ desc_index = (rx->ring_start & EDMA_RX_RING_ID_MASK); -+ for (q_id = mcast_start; q_id <= mcast_end; -+ q_id += EDMA_QID2RID_NUM_PER_REG) { -+ reg_index = q_id / EDMA_QID2RID_NUM_PER_REG; -+ -+ data = FIELD_PREP(EDMA_RX_RING_ID_QUEUE0_MASK, desc_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE1_MASK, desc_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE2_MASK, desc_index); -+ data |= FIELD_PREP(EDMA_RX_RING_ID_QUEUE3_MASK, desc_index); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_QID2RID_TABLE_MEM(reg_index); -+ regmap_write(regmap, reg, data); -+ -+ pr_debug("Configure QID2RID: %d reg:0x%x to 0x%x\n", -+ q_id, EDMA_QID2RID_TABLE_MEM(reg_index), data); -+ } -+} -+ -+static void edma_cfg_rx_rings_to_rx_fill_mapping(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, data, reg; -+ -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_0_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_1_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_2_ADDR, 0); -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring = &edma_ctx->rx_rings[i]; -+ u32 data, reg, ring_id; -+ -+ ring_id = rxdesc_ring->ring_id; -+ if (ring_id >= 0 && ring_id <= 9) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_0_ADDR; -+ else if (ring_id >= 10 && ring_id <= 19) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_1_ADDR; -+ else -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_2_ADDR; -+ -+ pr_debug("Configure RXDESC:%u to use RXFILL:%u\n", -+ ring_id, -+ rxdesc_ring->rxfill->ring_id); -+ -+ /* Set the Rx fill ring number in the mapping register. */ -+ regmap_read(regmap, reg, &data); -+ data |= (rxdesc_ring->rxfill->ring_id & -+ EDMA_RXDESC2FILL_MAP_RXDESC_MASK) << -+ ((ring_id % 10) * 3); -+ regmap_write(regmap, reg, data); -+ } -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_0_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_RXDESC2FILL_MAP_0_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_1_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_RXDESC2FILL_MAP_1_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC2FILL_MAP_2_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_RXDESC2FILL_MAP_2_ADDR: 0x%x\n", data); -+} -+ -+/** -+ * edma_cfg_rx_rings_enable - Enable Rx and Rxfill rings -+ * -+ * Enable Rx and Rxfill rings. -+ */ -+void edma_cfg_rx_rings_enable(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, reg; -+ -+ /* Enable Rx rings */ -+ for (i = rx->ring_start; i < rx->ring_start + rx->num_rings; i++) { -+ u32 data; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_CTRL(i); -+ regmap_read(regmap, reg, &data); -+ data |= EDMA_RXDESC_RX_EN; -+ regmap_write(regmap, reg, data); -+ } -+ -+ for (i = rxfill->ring_start; i < rxfill->ring_start + rxfill->num_rings; i++) { -+ u32 data; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_RING_EN(i); -+ regmap_read(regmap, reg, &data); -+ data |= EDMA_RXFILL_RING_EN; -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+/** -+ * edma_cfg_rx_rings_disable - Disable Rx and Rxfill rings -+ * -+ * Disable Rx and Rxfill rings. -+ */ -+void edma_cfg_rx_rings_disable(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, reg; -+ -+ /* Disable Rx rings */ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring = NULL; -+ u32 data; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_CTRL(rxdesc_ring->ring_id); -+ regmap_read(regmap, reg, &data); -+ data &= ~EDMA_RXDESC_RX_EN; -+ regmap_write(regmap, reg, data); -+ } -+ -+ /* Disable RxFill Rings */ -+ for (i = 0; i < rxfill->num_rings; i++) { -+ struct edma_rxfill_ring *rxfill_ring = NULL; -+ u32 data; -+ -+ rxfill_ring = &edma_ctx->rxfill_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_RING_EN(rxfill_ring->ring_id); -+ regmap_read(regmap, reg, &data); -+ data &= ~EDMA_RXFILL_RING_EN; -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+/** -+ * edma_cfg_rx_mappings - Setup RX ring mapping -+ * -+ * Setup queue ID to Rx desc ring mapping. -+ */ -+void edma_cfg_rx_ring_mappings(void) -+{ -+ edma_cfg_rx_qid_to_rx_desc_ring_mapping(); -+ edma_cfg_rx_rings_to_rx_fill_mapping(); -+} -+ -+static void edma_cfg_rx_fill_ring_cleanup(struct edma_rxfill_ring *rxfill_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct device *dev = ppe_dev->dev; -+ u16 cons_idx, curr_idx; -+ u32 data, reg; -+ -+ /* Get RxFill ring producer index */ -+ curr_idx = rxfill_ring->prod_idx & EDMA_RXFILL_PROD_IDX_MASK; -+ -+ /* Get RxFill ring consumer index */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_CONS_IDX(rxfill_ring->ring_id); -+ regmap_read(regmap, reg, &data); -+ cons_idx = data & EDMA_RXFILL_CONS_IDX_MASK; -+ -+ while (curr_idx != cons_idx) { -+ struct edma_rxfill_desc *rxfill_desc; -+ struct sk_buff *skb; -+ -+ /* Get RxFill descriptor */ -+ rxfill_desc = EDMA_RXFILL_DESC(rxfill_ring, cons_idx); -+ -+ cons_idx = (cons_idx + 1) & EDMA_RX_RING_SIZE_MASK; -+ -+ /* Get skb from opaque */ -+ skb = (struct sk_buff *)EDMA_RXFILL_OPAQUE_GET(rxfill_desc); -+ if (unlikely(!skb)) { -+ pr_err("Empty skb reference at index:%d\n", -+ cons_idx); -+ continue; -+ } -+ -+ dev_kfree_skb_any(skb); -+ } -+ -+ /* Free RxFill ring descriptors */ -+ dma_free_coherent(dev, (sizeof(struct edma_rxfill_desc) -+ * rxfill_ring->count), -+ rxfill_ring->desc, rxfill_ring->dma); -+ rxfill_ring->desc = NULL; -+ rxfill_ring->dma = (dma_addr_t)0; -+} -+ -+static int edma_cfg_rx_fill_ring_dma_alloc(struct edma_rxfill_ring *rxfill_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ -+ /* Allocate RxFill ring descriptors */ -+ rxfill_ring->desc = dma_alloc_coherent(dev, (sizeof(struct edma_rxfill_desc) -+ * rxfill_ring->count), -+ &rxfill_ring->dma, -+ GFP_KERNEL | __GFP_ZERO); -+ if (unlikely(!rxfill_ring->desc)) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static int edma_cfg_rx_desc_ring_dma_alloc(struct edma_rxdesc_ring *rxdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ -+ rxdesc_ring->pdesc = dma_alloc_coherent(dev, (sizeof(struct edma_rxdesc_pri) -+ * rxdesc_ring->count), -+ &rxdesc_ring->pdma, GFP_KERNEL | __GFP_ZERO); -+ if (unlikely(!rxdesc_ring->pdesc)) -+ return -ENOMEM; -+ -+ rxdesc_ring->sdesc = dma_alloc_coherent(dev, (sizeof(struct edma_rxdesc_sec) -+ * rxdesc_ring->count), -+ &rxdesc_ring->sdma, GFP_KERNEL | __GFP_ZERO); -+ if (unlikely(!rxdesc_ring->sdesc)) { -+ dma_free_coherent(dev, (sizeof(struct edma_rxdesc_pri) -+ * rxdesc_ring->count), -+ rxdesc_ring->pdesc, -+ rxdesc_ring->pdma); -+ rxdesc_ring->pdesc = NULL; -+ rxdesc_ring->pdma = (dma_addr_t)0; -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void edma_cfg_rx_desc_ring_cleanup(struct edma_rxdesc_ring *rxdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct device *dev = ppe_dev->dev; -+ u32 prod_idx, cons_idx, reg; -+ -+ /* Get Rxdesc consumer & producer indices */ -+ cons_idx = rxdesc_ring->cons_idx & EDMA_RXDESC_CONS_IDX_MASK; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_PROD_IDX(rxdesc_ring->ring_id); -+ regmap_read(regmap, reg, &prod_idx); -+ prod_idx = prod_idx & EDMA_RXDESC_PROD_IDX_MASK; -+ -+ /* Free any buffers assigned to any descriptors */ -+ while (cons_idx != prod_idx) { -+ struct edma_rxdesc_pri *rxdesc_pri = -+ EDMA_RXDESC_PRI_DESC(rxdesc_ring, cons_idx); -+ struct sk_buff *skb; -+ -+ /* Update consumer index */ -+ cons_idx = (cons_idx + 1) & EDMA_RX_RING_SIZE_MASK; -+ -+ /* Get opaque from Rxdesc */ -+ skb = (struct sk_buff *)EDMA_RXDESC_OPAQUE_GET(rxdesc_pri); -+ if (unlikely(!skb)) { -+ pr_warn("Empty skb reference at index:%d\n", -+ cons_idx); -+ continue; -+ } -+ -+ dev_kfree_skb_any(skb); -+ } -+ -+ /* Update the consumer index */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_CONS_IDX(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, cons_idx); -+ -+ /* Free Rxdesc ring descriptor */ -+ dma_free_coherent(dev, (sizeof(struct edma_rxdesc_pri) -+ * rxdesc_ring->count), rxdesc_ring->pdesc, -+ rxdesc_ring->pdma); -+ rxdesc_ring->pdesc = NULL; -+ rxdesc_ring->pdma = (dma_addr_t)0; -+ -+ /* Free any buffers assigned to any secondary ring descriptors */ -+ dma_free_coherent(dev, (sizeof(struct edma_rxdesc_sec) -+ * rxdesc_ring->count), rxdesc_ring->sdesc, -+ rxdesc_ring->sdma); -+ rxdesc_ring->sdesc = NULL; -+ rxdesc_ring->sdma = (dma_addr_t)0; -+} -+ -+static int edma_cfg_rx_rings_setup(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 ring_idx, alloc_size, buf_len; -+ -+ /* Set buffer allocation size */ -+ if (edma_ctx->rx_buf_size) { -+ alloc_size = edma_ctx->rx_buf_size + -+ EDMA_RX_SKB_HEADROOM + NET_IP_ALIGN; -+ buf_len = alloc_size - EDMA_RX_SKB_HEADROOM - NET_IP_ALIGN; -+ } else if (edma_ctx->rx_page_mode) { -+ alloc_size = EDMA_RX_PAGE_MODE_SKB_SIZE + -+ EDMA_RX_SKB_HEADROOM + NET_IP_ALIGN; -+ buf_len = PAGE_SIZE; -+ } else { -+ alloc_size = EDMA_RX_BUFFER_SIZE; -+ buf_len = alloc_size - EDMA_RX_SKB_HEADROOM - NET_IP_ALIGN; -+ } -+ -+ pr_debug("EDMA ctx:%p rx_ring alloc_size=%d, buf_len=%d\n", -+ edma_ctx, alloc_size, buf_len); -+ -+ /* Allocate Rx fill ring descriptors */ -+ for (ring_idx = 0; ring_idx < rxfill->num_rings; ring_idx++) { -+ u32 ret; -+ struct edma_rxfill_ring *rxfill_ring = NULL; -+ -+ rxfill_ring = &edma_ctx->rxfill_rings[ring_idx]; -+ rxfill_ring->count = EDMA_RX_RING_SIZE; -+ rxfill_ring->ring_id = rxfill->ring_start + ring_idx; -+ rxfill_ring->alloc_size = alloc_size; -+ rxfill_ring->buf_len = buf_len; -+ rxfill_ring->page_mode = edma_ctx->rx_page_mode; -+ -+ ret = edma_cfg_rx_fill_ring_dma_alloc(rxfill_ring); -+ if (ret) { -+ pr_err("Error in setting up %d rxfill ring. ret: %d", -+ rxfill_ring->ring_id, ret); -+ while (--ring_idx >= 0) -+ edma_cfg_rx_fill_ring_cleanup(&edma_ctx->rxfill_rings[ring_idx]); -+ -+ return -ENOMEM; -+ } -+ } -+ -+ /* Allocate RxDesc ring descriptors */ -+ for (ring_idx = 0; ring_idx < rx->num_rings; ring_idx++) { -+ u32 index, queue_id = EDMA_RX_QUEUE_START; -+ struct edma_rxdesc_ring *rxdesc_ring = NULL; -+ u32 ret; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[ring_idx]; -+ rxdesc_ring->count = EDMA_RX_RING_SIZE; -+ rxdesc_ring->ring_id = rx->ring_start + ring_idx; -+ -+ if (queue_id > EDMA_CPU_PORT_QUEUE_MAX(EDMA_RX_QUEUE_START)) { -+ pr_err("Invalid queue_id: %d\n", queue_id); -+ while (--ring_idx >= 0) -+ edma_cfg_rx_desc_ring_cleanup(&edma_ctx->rx_rings[ring_idx]); -+ -+ goto rxdesc_mem_alloc_fail; -+ } -+ -+ /* Create a mapping between RX Desc ring and Rx fill ring. -+ * Number of fill rings are lesser than the descriptor rings -+ * Share the fill rings across descriptor rings. -+ */ -+ index = rxfill->ring_start + -+ (ring_idx % rxfill->num_rings); -+ rxdesc_ring->rxfill = &edma_ctx->rxfill_rings[index -+ - rxfill->ring_start]; -+ -+ ret = edma_cfg_rx_desc_ring_dma_alloc(rxdesc_ring); -+ if (ret) { -+ pr_err("Error in setting up %d rxdesc ring. ret: %d", -+ rxdesc_ring->ring_id, ret); -+ while (--ring_idx >= 0) -+ edma_cfg_rx_desc_ring_cleanup(&edma_ctx->rx_rings[ring_idx]); -+ -+ goto rxdesc_mem_alloc_fail; -+ } -+ } -+ -+ pr_debug("Rx descriptor count for Rx desc and Rx fill rings : %d\n", -+ EDMA_RX_RING_SIZE); -+ -+ return 0; -+ -+rxdesc_mem_alloc_fail: -+ for (ring_idx = 0; ring_idx < rxfill->num_rings; ring_idx++) -+ edma_cfg_rx_fill_ring_cleanup(&edma_ctx->rxfill_rings[ring_idx]); -+ -+ return -ENOMEM; -+} -+ -+/** -+ * edma_cfg_rx_buff_size_setup - Configure EDMA Rx jumbo buffer -+ * -+ * Configure EDMA Rx jumbo buffer -+ */ -+void edma_cfg_rx_buff_size_setup(void) -+{ -+ if (edma_ctx->rx_buf_size) { -+ edma_ctx->rx_page_mode = false; -+ pr_debug("Rx Jumbo mru is enabled: %d\n", edma_ctx->rx_buf_size); -+ } -+} -+ -+/** -+ * edma_cfg_rx_rings_alloc - Allocate EDMA Rx rings -+ * -+ * Allocate EDMA Rx rings. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+int edma_cfg_rx_rings_alloc(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct edma_ring_info *rx = hw_info->rx; -+ int ret; -+ -+ edma_ctx->rxfill_rings = kzalloc((sizeof(*edma_ctx->rxfill_rings) * -+ rxfill->num_rings), -+ GFP_KERNEL); -+ if (!edma_ctx->rxfill_rings) -+ return -ENOMEM; -+ -+ edma_ctx->rx_rings = kzalloc((sizeof(*edma_ctx->rx_rings) * -+ rx->num_rings), -+ GFP_KERNEL); -+ if (!edma_ctx->rx_rings) -+ goto rxdesc_ring_alloc_fail; -+ -+ pr_debug("RxDesc:%u rx (%u-%u) RxFill:%u (%u-%u)\n", -+ rx->num_rings, rx->ring_start, -+ (rx->ring_start + rx->num_rings - 1), -+ rxfill->num_rings, rxfill->ring_start, -+ (rxfill->ring_start + rxfill->num_rings - 1)); -+ -+ if (edma_cfg_rx_rings_setup()) { -+ pr_err("Error in setting up Rx rings\n"); -+ goto rx_rings_setup_fail; -+ } -+ -+ /* Reset Rx descriptor ring mapped queue's configurations */ -+ ret = edma_cfg_rx_desc_ring_reset_queue_config(); -+ if (ret) { -+ pr_err("Error in resetting the Rx descriptor rings configurations\n"); -+ edma_cfg_rx_rings_cleanup(); -+ return ret; -+ } -+ -+ return 0; -+ -+rx_rings_setup_fail: -+ kfree(edma_ctx->rx_rings); -+ edma_ctx->rx_rings = NULL; -+rxdesc_ring_alloc_fail: -+ kfree(edma_ctx->rxfill_rings); -+ edma_ctx->rxfill_rings = NULL; -+ -+ return -ENOMEM; -+} -+ -+/** -+ * edma_cfg_rx_rings_cleanup - Cleanup EDMA Rx rings -+ * -+ * Cleanup EDMA Rx rings -+ */ -+void edma_cfg_rx_rings_cleanup(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ /* Free RxFill ring descriptors */ -+ for (i = 0; i < rxfill->num_rings; i++) -+ edma_cfg_rx_fill_ring_cleanup(&edma_ctx->rxfill_rings[i]); -+ -+ /* Free Rx completion ring descriptors */ -+ for (i = 0; i < rx->num_rings; i++) -+ edma_cfg_rx_desc_ring_cleanup(&edma_ctx->rx_rings[i]); -+ -+ kfree(edma_ctx->rxfill_rings); -+ kfree(edma_ctx->rx_rings); -+ edma_ctx->rxfill_rings = NULL; -+ edma_ctx->rx_rings = NULL; -+} -+ -+static void edma_cfg_rx_fill_ring_configure(struct edma_rxfill_ring *rxfill_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 ring_sz, reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_BA(rxfill_ring->ring_id); -+ regmap_write(regmap, reg, (u32)(rxfill_ring->dma & EDMA_RING_DMA_MASK)); -+ -+ ring_sz = rxfill_ring->count & EDMA_RXFILL_RING_SIZE_MASK; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_RING_SIZE(rxfill_ring->ring_id); -+ regmap_write(regmap, reg, ring_sz); -+ -+ edma_rx_alloc_buffer(rxfill_ring, rxfill_ring->count - 1); -+} -+ -+static void edma_cfg_rx_desc_ring_flow_control(u32 threshold_xoff, u32 threshold_xon) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 data, i, reg; -+ -+ data = (threshold_xoff & EDMA_RXDESC_FC_XOFF_THRE_MASK) << EDMA_RXDESC_FC_XOFF_THRE_SHIFT; -+ data |= ((threshold_xon & EDMA_RXDESC_FC_XON_THRE_MASK) << EDMA_RXDESC_FC_XON_THRE_SHIFT); -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_FC_THRE(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+static void edma_cfg_rx_fill_ring_flow_control(int threshold_xoff, int threshold_xon) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 data, i, reg; -+ -+ data = (threshold_xoff & EDMA_RXFILL_FC_XOFF_THRE_MASK) << EDMA_RXFILL_FC_XOFF_THRE_SHIFT; -+ data |= ((threshold_xon & EDMA_RXFILL_FC_XON_THRE_MASK) << EDMA_RXFILL_FC_XON_THRE_SHIFT); -+ -+ for (i = 0; i < rxfill->num_rings; i++) { -+ struct edma_rxfill_ring *rxfill_ring; -+ -+ rxfill_ring = &edma_ctx->rxfill_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_FC_THRE(rxfill_ring->ring_id); -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+/** -+ * edma_cfg_rx_rings - Configure EDMA Rx rings. -+ * -+ * Configure EDMA Rx rings. -+ */ -+int edma_cfg_rx_rings(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ for (i = 0; i < rxfill->num_rings; i++) -+ edma_cfg_rx_fill_ring_configure(&edma_ctx->rxfill_rings[i]); -+ -+ for (i = 0; i < rx->num_rings; i++) -+ edma_cfg_rx_desc_ring_configure(&edma_ctx->rx_rings[i]); -+ -+ /* Configure Rx flow control configurations */ -+ edma_cfg_rx_desc_ring_flow_control(EDMA_RX_FC_XOFF_DEF, EDMA_RX_FC_XON_DEF); -+ edma_cfg_rx_fill_ring_flow_control(EDMA_RX_FC_XOFF_DEF, EDMA_RX_FC_XON_DEF); -+ -+ return edma_cfg_rx_desc_ring_to_queue_mapping(); -+} -+ -+/** -+ * edma_cfg_rx_disable_interrupts - EDMA disable RX interrupts -+ * -+ * Disable RX interrupt masks -+ */ -+void edma_cfg_rx_disable_interrupts(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, reg; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring = -+ &edma_ctx->rx_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_INT_MASK(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, EDMA_MASK_INT_CLEAR); -+ } -+} -+ -+/** -+ * edma_cfg_rx_enable_interrupts - EDMA enable RX interrupts -+ * -+ * Enable RX interrupt masks -+ */ -+void edma_cfg_rx_enable_interrupts(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i, reg; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring = -+ &edma_ctx->rx_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_INT_MASK(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_rx); -+ } -+} -+ -+/** -+ * edma_cfg_rx_napi_disable - Disable NAPI for Rx -+ * -+ * Disable NAPI for Rx -+ */ -+void edma_cfg_rx_napi_disable(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ if (!rxdesc_ring->napi_added) -+ continue; -+ -+ napi_disable(&rxdesc_ring->napi); -+ } -+} -+ -+/** -+ * edma_cfg_rx_napi_enable - Enable NAPI for Rx -+ * -+ * Enable NAPI for Rx -+ */ -+void edma_cfg_rx_napi_enable(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ if (!rxdesc_ring->napi_added) -+ continue; -+ -+ napi_enable(&rxdesc_ring->napi); -+ } -+} -+ -+/** -+ * edma_cfg_rx_napi_delete - Delete Rx NAPI -+ * -+ * Delete RX NAPI -+ */ -+void edma_cfg_rx_napi_delete(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ if (!rxdesc_ring->napi_added) -+ continue; -+ -+ netif_napi_del(&rxdesc_ring->napi); -+ rxdesc_ring->napi_added = false; -+ } -+} -+ -+/* Add Rx NAPI */ -+/** -+ * edma_cfg_rx_napi_add - Add Rx NAPI -+ * @netdev: Netdevice -+ * -+ * Add RX NAPI -+ */ -+void edma_cfg_rx_napi_add(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rx = hw_info->rx; -+ u32 i; -+ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring = &edma_ctx->rx_rings[i]; -+ -+ netif_napi_add_weight(edma_ctx->dummy_dev, &rxdesc_ring->napi, -+ edma_rx_napi_poll, hw_info->napi_budget_rx); -+ rxdesc_ring->napi_added = true; -+ } -+ -+ netdev_dbg(edma_ctx->dummy_dev, "Rx NAPI budget: %d\n", hw_info->napi_budget_rx); -+} -+ -+/** -+ * edma_cfg_rx_rps_hash_map - Configure rx rps hash map. -+ * -+ * Initialize and configure RPS hash map for queues -+ */ -+int edma_cfg_rx_rps_hash_map(void) -+{ -+ cpumask_t edma_rps_cpumask = {{EDMA_RX_DEFAULT_BITMAP}}; -+ int map_len = 0, idx = 0, ret = 0; -+ u32 q_off = EDMA_RX_QUEUE_START; -+ u32 q_map[EDMA_MAX_CORE] = {0}; -+ u32 hash, cpu; -+ -+ /* Map all possible hash values to queues used by the EDMA Rx -+ * rings based on a bitmask, which represents the cores to be mapped. -+ * These queues are expected to be mapped to different Rx rings -+ * which are assigned to different cores using IRQ affinity configuration. -+ */ -+ for_each_cpu(cpu, &edma_rps_cpumask) { -+ q_map[map_len] = q_off + (cpu * EDMA_MAX_PRI_PER_CORE); -+ map_len++; -+ } -+ -+ for (hash = 0; hash < PPE_QUEUE_HASH_NUM; hash++) { -+ ret = ppe_edma_queue_offset_config(edma_ctx->ppe_dev, -+ PPE_QUEUE_CLASS_HASH, hash, q_map[idx]); -+ if (ret) -+ return ret; -+ -+ pr_debug("profile_id: %u, hash: %u, q_off: %u\n", -+ EDMA_CPU_PORT_PROFILE_ID, hash, q_map[idx]); -+ idx = (idx + 1) % map_len; -+ } -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h -@@ -0,0 +1,48 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_CFG_RX__ -+#define __EDMA_CFG_RX__ -+ -+/* SKB payload size used in page mode */ -+#define EDMA_RX_PAGE_MODE_SKB_SIZE 256 -+ -+/* Rx flow control X-OFF default value */ -+#define EDMA_RX_FC_XOFF_DEF 32 -+ -+/* Rx flow control X-ON default value */ -+#define EDMA_RX_FC_XON_DEF 64 -+ -+/* Rx AC flow control original threshold */ -+#define EDMA_RX_AC_FC_THRE_ORIG 0x190 -+ -+/* Rx AC flow control default threshold */ -+#define EDMA_RX_AC_FC_THRES_DEF 0x104 -+/* Rx mitigation timer's default value in microseconds */ -+#define EDMA_RX_MITIGATION_TIMER_DEF 25 -+ -+/* Rx mitigation packet count's default value */ -+#define EDMA_RX_MITIGATION_PKT_CNT_DEF 16 -+ -+/* Default bitmap of cores for RPS to ARM cores */ -+#define EDMA_RX_DEFAULT_BITMAP ((1 << EDMA_MAX_CORE) - 1) -+ -+int edma_cfg_rx_rings(void); -+int edma_cfg_rx_rings_alloc(void); -+void edma_cfg_rx_ring_mappings(void); -+void edma_cfg_rx_rings_cleanup(void); -+void edma_cfg_rx_disable_interrupts(void); -+void edma_cfg_rx_enable_interrupts(void); -+void edma_cfg_rx_napi_disable(void); -+void edma_cfg_rx_napi_enable(void); -+void edma_cfg_rx_napi_delete(void); -+void edma_cfg_rx_napi_add(void); -+void edma_cfg_rx_mapping(void); -+void edma_cfg_rx_rings_enable(void); -+void edma_cfg_rx_rings_disable(void); -+void edma_cfg_rx_buff_size_setup(void); -+int edma_cfg_rx_rps_hash_map(void); -+int edma_cfg_rx_rps(struct ctl_table *table, int write, -+ void *buffer, size_t *lenp, loff_t *ppos); -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c -@@ -12,12 +12,39 @@ - #include - - #include "edma.h" -+#include "edma_cfg_rx.h" - #include "edma_port.h" - #include "ppe_regs.h" - - /* Number of netdev queues. */ - #define EDMA_NETDEV_QUEUE_NUM 4 - -+static int edma_port_stats_alloc(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ /* Allocate per-cpu stats memory. */ -+ port_priv->pcpu_stats.rx_stats = -+ netdev_alloc_pcpu_stats(struct edma_port_rx_stats); -+ if (!port_priv->pcpu_stats.rx_stats) { -+ netdev_err(netdev, "Per-cpu EDMA Rx stats alloc failed for %s\n", -+ netdev->name); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void edma_port_stats_free(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ -+ free_percpu(port_priv->pcpu_stats.rx_stats); -+} -+ - static u16 __maybe_unused edma_port_select_queue(__maybe_unused struct net_device *netdev, - __maybe_unused struct sk_buff *skb, - __maybe_unused struct net_device *sb_dev) -@@ -172,6 +199,7 @@ void edma_port_destroy(struct ppe_port * - int port_id = port->port_id; - struct net_device *netdev = edma_ctx->netdev_arr[port_id - 1]; - -+ edma_port_stats_free(netdev); - unregister_netdev(netdev); - free_netdev(netdev); - ppe_port_phylink_destroy(port); -@@ -232,6 +260,13 @@ int edma_port_setup(struct ppe_port *por - port_id, netdev->dev_addr); - } - -+ /* Allocate memory for EDMA port statistics. */ -+ ret = edma_port_stats_alloc(netdev); -+ if (ret) { -+ netdev_dbg(netdev, "EDMA port stats alloc failed\n"); -+ goto stats_alloc_fail; -+ } -+ - netdev_dbg(netdev, "Configuring the port %s(qcom-id:%d)\n", - netdev->name, port_id); - -@@ -263,8 +298,10 @@ int edma_port_setup(struct ppe_port *por - register_netdev_fail: - ppe_port_phylink_destroy(port); - port_phylink_setup_fail: -- free_netdev(netdev); - edma_ctx->netdev_arr[port_id - 1] = NULL; -+ edma_port_stats_free(netdev); -+stats_alloc_fail: -+ free_netdev(netdev); - - return ret; - } ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.h -@@ -15,14 +15,45 @@ - | NETIF_F_TSO6) - - /** -+ * struct edma_port_rx_stats - EDMA RX per CPU stats for the port. -+ * @rx_pkts: Number of Rx packets -+ * @rx_bytes: Number of Rx bytes -+ * @rx_drops: Number of Rx drops -+ * @rx_nr_frag_pkts: Number of Rx nr_frags packets -+ * @rx_fraglist_pkts: Number of Rx fraglist packets -+ * @rx_nr_frag_headroom_err: nr_frags headroom error packets -+ * @syncp: Synchronization pointer -+ */ -+struct edma_port_rx_stats { -+ u64 rx_pkts; -+ u64 rx_bytes; -+ u64 rx_drops; -+ u64 rx_nr_frag_pkts; -+ u64 rx_fraglist_pkts; -+ u64 rx_nr_frag_headroom_err; -+ struct u64_stats_sync syncp; -+}; -+ -+/** -+ * struct edma_port_pcpu_stats - EDMA per cpu stats data structure for the port. -+ * @rx_stats: Per CPU Rx statistics -+ */ -+struct edma_port_pcpu_stats { -+ struct edma_port_rx_stats __percpu *rx_stats; -+}; -+ -+/** - * struct edma_port_priv - EDMA port priv structure. - * @ppe_port: Pointer to PPE port - * @netdev: Corresponding netdevice -+ * @pcpu_stats: Per CPU netdev statistics -+ * @txr_map: Tx ring per-core mapping - * @flags: Feature flags - */ - struct edma_port_priv { - struct ppe_port *ppe_port; - struct net_device *netdev; -+ struct edma_port_pcpu_stats pcpu_stats; - unsigned long flags; - }; - ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_rx.c -@@ -0,0 +1,622 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* Provides APIs to alloc Rx Buffers, reap the buffers, receive and -+ * process linear and Scatter Gather packets. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_cfg_rx.h" -+#include "edma_port.h" -+#include "ppe.h" -+#include "ppe_regs.h" -+ -+static int edma_rx_alloc_buffer_list(struct edma_rxfill_ring *rxfill_ring, int alloc_count) -+{ -+ struct edma_rxfill_stats *rxfill_stats = &rxfill_ring->rxfill_stats; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ u32 rx_alloc_size = rxfill_ring->alloc_size; -+ struct regmap *regmap = ppe_dev->regmap; -+ bool page_mode = rxfill_ring->page_mode; -+ struct edma_rxfill_desc *rxfill_desc; -+ u32 buf_len = rxfill_ring->buf_len; -+ struct device *dev = ppe_dev->dev; -+ u16 prod_idx, start_idx; -+ u16 num_alloc = 0; -+ u32 reg; -+ -+ prod_idx = rxfill_ring->prod_idx; -+ start_idx = prod_idx; -+ -+ while (likely(alloc_count--)) { -+ dma_addr_t buff_addr; -+ struct sk_buff *skb; -+ struct page *pg; -+ -+ rxfill_desc = EDMA_RXFILL_DESC(rxfill_ring, prod_idx); -+ -+ skb = dev_alloc_skb(rx_alloc_size); -+ if (unlikely(!skb)) { -+ u64_stats_update_begin(&rxfill_stats->syncp); -+ ++rxfill_stats->alloc_failed; -+ u64_stats_update_end(&rxfill_stats->syncp); -+ break; -+ } -+ -+ skb_reserve(skb, EDMA_RX_SKB_HEADROOM + NET_IP_ALIGN); -+ -+ if (likely(!page_mode)) { -+ buff_addr = dma_map_single(dev, skb->data, rx_alloc_size, DMA_FROM_DEVICE); -+ if (dma_mapping_error(dev, buff_addr)) { -+ dev_dbg(dev, "edma_context:%p Unable to dma for non page mode", -+ edma_ctx); -+ dev_kfree_skb_any(skb); -+ break; -+ } -+ } else { -+ pg = alloc_page(GFP_ATOMIC); -+ if (unlikely(!pg)) { -+ u64_stats_update_begin(&rxfill_stats->syncp); -+ ++rxfill_stats->page_alloc_failed; -+ u64_stats_update_end(&rxfill_stats->syncp); -+ dev_kfree_skb_any(skb); -+ dev_dbg(dev, "edma_context:%p Unable to allocate page", -+ edma_ctx); -+ break; -+ } -+ -+ buff_addr = dma_map_page(dev, pg, 0, PAGE_SIZE, DMA_FROM_DEVICE); -+ if (dma_mapping_error(dev, buff_addr)) { -+ dev_dbg(dev, "edma_context:%p Mapping error for page mode", -+ edma_ctx); -+ __free_page(pg); -+ dev_kfree_skb_any(skb); -+ break; -+ } -+ -+ skb_fill_page_desc(skb, 0, pg, 0, PAGE_SIZE); -+ } -+ -+ EDMA_RXFILL_BUFFER_ADDR_SET(rxfill_desc, buff_addr); -+ -+ EDMA_RXFILL_OPAQUE_LO_SET(rxfill_desc, skb); -+#ifdef __LP64__ -+ EDMA_RXFILL_OPAQUE_HI_SET(rxfill_desc, skb); -+#endif -+ EDMA_RXFILL_PACKET_LEN_SET(rxfill_desc, -+ (u32)(buf_len) & EDMA_RXFILL_BUF_SIZE_MASK); -+ prod_idx = (prod_idx + 1) & EDMA_RX_RING_SIZE_MASK; -+ num_alloc++; -+ } -+ -+ if (likely(num_alloc)) { -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXFILL_PROD_IDX(rxfill_ring->ring_id); -+ regmap_write(regmap, reg, prod_idx); -+ rxfill_ring->prod_idx = prod_idx; -+ } -+ -+ return num_alloc; -+} -+ -+/** -+ * edma_rx_alloc_buffer - EDMA Rx alloc buffer. -+ * @rxfill_ring: EDMA Rxfill ring -+ * @alloc_count: Number of rings to alloc -+ * -+ * Alloc Rx buffers for RxFill ring. -+ * -+ * Return the number of rings allocated. -+ */ -+int edma_rx_alloc_buffer(struct edma_rxfill_ring *rxfill_ring, int alloc_count) -+{ -+ return edma_rx_alloc_buffer_list(rxfill_ring, alloc_count); -+} -+ -+/* Mark ip_summed appropriately in the skb as per the L3/L4 checksum -+ * status in descriptor. -+ */ -+static void edma_rx_checksum_verify(struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ u8 pid = EDMA_RXDESC_PID_GET(rxdesc_pri); -+ -+ skb_checksum_none_assert(skb); -+ -+ if (likely(EDMA_RX_PID_IS_IPV4(pid))) { -+ if (likely(EDMA_RXDESC_L3CSUM_STATUS_GET(rxdesc_pri)) && -+ likely(EDMA_RXDESC_L4CSUM_STATUS_GET(rxdesc_pri))) -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ } else if (likely(EDMA_RX_PID_IS_IPV6(pid))) { -+ if (likely(EDMA_RXDESC_L4CSUM_STATUS_GET(rxdesc_pri))) -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ } -+} -+ -+static void edma_rx_process_last_segment(struct edma_rxdesc_ring *rxdesc_ring, -+ struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ bool page_mode = rxdesc_ring->rxfill->page_mode; -+ struct edma_port_pcpu_stats *pcpu_stats; -+ struct edma_port_rx_stats *rx_stats; -+ struct edma_port_priv *port_dev; -+ struct sk_buff *skb_head; -+ struct net_device *dev; -+ u32 pkt_length; -+ -+ /* Get packet length. */ -+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri); -+ -+ skb_head = rxdesc_ring->head; -+ dev = skb_head->dev; -+ -+ /* Check Rx checksum offload status. */ -+ if (likely(dev->features & NETIF_F_RXCSUM)) -+ edma_rx_checksum_verify(rxdesc_pri, skb_head); -+ -+ /* Get stats for the netdevice. */ -+ port_dev = netdev_priv(dev); -+ pcpu_stats = &port_dev->pcpu_stats; -+ rx_stats = this_cpu_ptr(pcpu_stats->rx_stats); -+ -+ if (unlikely(page_mode)) { -+ if (unlikely(!pskb_may_pull(skb_head, ETH_HLEN))) { -+ /* Discard the SKB that we have been building, -+ * in addition to the SKB linked to current descriptor. -+ */ -+ dev_kfree_skb_any(skb_head); -+ rxdesc_ring->head = NULL; -+ rxdesc_ring->last = NULL; -+ rxdesc_ring->pdesc_head = NULL; -+ -+ u64_stats_update_begin(&rx_stats->syncp); -+ rx_stats->rx_nr_frag_headroom_err++; -+ u64_stats_update_end(&rx_stats->syncp); -+ -+ return; -+ } -+ } -+ -+ if (unlikely(!pskb_pull(skb_head, EDMA_RXDESC_DATA_OFFSET_GET(rxdesc_ring->pdesc_head)))) { -+ dev_kfree_skb_any(skb_head); -+ rxdesc_ring->head = NULL; -+ rxdesc_ring->last = NULL; -+ rxdesc_ring->pdesc_head = NULL; -+ -+ u64_stats_update_begin(&rx_stats->syncp); -+ rx_stats->rx_nr_frag_headroom_err++; -+ u64_stats_update_end(&rx_stats->syncp); -+ -+ return; -+ } -+ -+ u64_stats_update_begin(&rx_stats->syncp); -+ rx_stats->rx_pkts++; -+ rx_stats->rx_bytes += skb_head->len; -+ rx_stats->rx_nr_frag_pkts += (u64)page_mode; -+ rx_stats->rx_fraglist_pkts += (u64)(!page_mode); -+ u64_stats_update_end(&rx_stats->syncp); -+ -+ pr_debug("edma_context:%p skb:%p Jumbo pkt_length:%u\n", -+ edma_ctx, skb_head, skb_head->len); -+ -+ skb_head->protocol = eth_type_trans(skb_head, dev); -+ -+ /* Send packet up the stack. */ -+ if (dev->features & NETIF_F_GRO) -+ napi_gro_receive(&rxdesc_ring->napi, skb_head); -+ else -+ netif_receive_skb(skb_head); -+ -+ rxdesc_ring->head = NULL; -+ rxdesc_ring->last = NULL; -+ rxdesc_ring->pdesc_head = NULL; -+} -+ -+static void edma_rx_handle_frag_list(struct edma_rxdesc_ring *rxdesc_ring, -+ struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ u32 pkt_length; -+ -+ /* Get packet length. */ -+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri); -+ pr_debug("edma_context:%p skb:%p fragment pkt_length:%u\n", -+ edma_ctx, skb, pkt_length); -+ -+ if (!(rxdesc_ring->head)) { -+ skb_put(skb, pkt_length); -+ rxdesc_ring->head = skb; -+ rxdesc_ring->last = NULL; -+ rxdesc_ring->pdesc_head = rxdesc_pri; -+ -+ return; -+ } -+ -+ /* Append it to the fraglist of head if this is second frame -+ * If not second frame append to tail. -+ */ -+ skb_put(skb, pkt_length); -+ if (!skb_has_frag_list(rxdesc_ring->head)) -+ skb_shinfo(rxdesc_ring->head)->frag_list = skb; -+ else -+ rxdesc_ring->last->next = skb; -+ -+ rxdesc_ring->last = skb; -+ rxdesc_ring->last->next = NULL; -+ rxdesc_ring->head->len += pkt_length; -+ rxdesc_ring->head->data_len += pkt_length; -+ rxdesc_ring->head->truesize += skb->truesize; -+ -+ /* If there are more segments for this packet, -+ * then we have nothing to do. Otherwise process -+ * last segment and send packet to stack. -+ */ -+ if (EDMA_RXDESC_MORE_BIT_GET(rxdesc_pri)) -+ return; -+ -+ edma_rx_process_last_segment(rxdesc_ring, rxdesc_pri, skb); -+} -+ -+static void edma_rx_handle_nr_frags(struct edma_rxdesc_ring *rxdesc_ring, -+ struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ skb_frag_t *frag = NULL; -+ u32 pkt_length; -+ -+ /* Get packet length. */ -+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri); -+ pr_debug("edma_context:%p skb:%p fragment pkt_length:%u\n", -+ edma_ctx, skb, pkt_length); -+ -+ if (!(rxdesc_ring->head)) { -+ skb->len = pkt_length; -+ skb->data_len = pkt_length; -+ skb->truesize = SKB_TRUESIZE(PAGE_SIZE); -+ rxdesc_ring->head = skb; -+ rxdesc_ring->last = NULL; -+ rxdesc_ring->pdesc_head = rxdesc_pri; -+ -+ return; -+ } -+ -+ frag = &skb_shinfo(skb)->frags[0]; -+ -+ /* Append current frag at correct index as nr_frag of parent. */ -+ skb_add_rx_frag(rxdesc_ring->head, skb_shinfo(rxdesc_ring->head)->nr_frags, -+ skb_frag_page(frag), 0, pkt_length, PAGE_SIZE); -+ skb_shinfo(skb)->nr_frags = 0; -+ -+ /* Free the SKB after we have appended its frag page to the head skb. */ -+ dev_kfree_skb_any(skb); -+ -+ /* If there are more segments for this packet, -+ * then we have nothing to do. Otherwise process -+ * last segment and send packet to stack. -+ */ -+ if (EDMA_RXDESC_MORE_BIT_GET(rxdesc_pri)) -+ return; -+ -+ edma_rx_process_last_segment(rxdesc_ring, rxdesc_pri, skb); -+} -+ -+static bool edma_rx_handle_linear_packets(struct edma_rxdesc_ring *rxdesc_ring, -+ struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ bool page_mode = rxdesc_ring->rxfill->page_mode; -+ struct edma_port_pcpu_stats *pcpu_stats; -+ struct edma_port_rx_stats *rx_stats; -+ struct edma_port_priv *port_dev; -+ skb_frag_t *frag = NULL; -+ u32 pkt_length; -+ -+ /* Get stats for the netdevice. */ -+ port_dev = netdev_priv(skb->dev); -+ pcpu_stats = &port_dev->pcpu_stats; -+ rx_stats = this_cpu_ptr(pcpu_stats->rx_stats); -+ -+ /* Get packet length. */ -+ pkt_length = EDMA_RXDESC_PACKET_LEN_GET(rxdesc_pri); -+ -+ if (likely(!page_mode)) { -+ skb_put(skb, pkt_length); -+ goto send_to_stack; -+ } -+ -+ /* Handle linear packet in page mode. */ -+ frag = &skb_shinfo(skb)->frags[0]; -+ skb_add_rx_frag(skb, 0, skb_frag_page(frag), 0, pkt_length, PAGE_SIZE); -+ -+ /* Pull ethernet header into SKB data area for header processing. */ -+ if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) { -+ u64_stats_update_begin(&rx_stats->syncp); -+ rx_stats->rx_nr_frag_headroom_err++; -+ u64_stats_update_end(&rx_stats->syncp); -+ dev_kfree_skb_any(skb); -+ -+ return false; -+ } -+ -+send_to_stack: -+ -+ __skb_pull(skb, EDMA_RXDESC_DATA_OFFSET_GET(rxdesc_pri)); -+ -+ /* Check Rx checksum offload status. */ -+ if (likely(skb->dev->features & NETIF_F_RXCSUM)) -+ edma_rx_checksum_verify(rxdesc_pri, skb); -+ -+ u64_stats_update_begin(&rx_stats->syncp); -+ rx_stats->rx_pkts++; -+ rx_stats->rx_bytes += pkt_length; -+ rx_stats->rx_nr_frag_pkts += (u64)page_mode; -+ u64_stats_update_end(&rx_stats->syncp); -+ -+ skb->protocol = eth_type_trans(skb, skb->dev); -+ if (skb->dev->features & NETIF_F_GRO) -+ napi_gro_receive(&rxdesc_ring->napi, skb); -+ else -+ netif_receive_skb(skb); -+ -+ netdev_dbg(skb->dev, "edma_context:%p, skb:%p pkt_length:%u\n", -+ edma_ctx, skb, skb->len); -+ -+ return true; -+} -+ -+static struct net_device *edma_rx_get_src_dev(struct edma_rxdesc_stats *rxdesc_stats, -+ struct edma_rxdesc_pri *rxdesc_pri, -+ struct sk_buff *skb) -+{ -+ u32 src_info = EDMA_RXDESC_SRC_INFO_GET(rxdesc_pri); -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct net_device *ndev = NULL; -+ u8 src_port_num; -+ -+ /* Check src_info. */ -+ if (likely((src_info & EDMA_RXDESC_SRCINFO_TYPE_MASK) -+ == EDMA_RXDESC_SRCINFO_TYPE_PORTID)) { -+ src_port_num = src_info & EDMA_RXDESC_PORTNUM_BITS; -+ } else { -+ if (net_ratelimit()) { -+ pr_warn("Invalid src info_type:0x%x. Drop skb:%p\n", -+ (src_info & EDMA_RXDESC_SRCINFO_TYPE_MASK), skb); -+ } -+ -+ u64_stats_update_begin(&rxdesc_stats->syncp); -+ ++rxdesc_stats->src_port_inval_type; -+ u64_stats_update_end(&rxdesc_stats->syncp); -+ -+ return NULL; -+ } -+ -+ /* Packet with PP source. */ -+ if (likely(src_port_num <= hw_info->max_ports)) { -+ if (unlikely(src_port_num < EDMA_START_IFNUM)) { -+ if (net_ratelimit()) -+ pr_warn("Port number error :%d. Drop skb:%p\n", -+ src_port_num, skb); -+ -+ u64_stats_update_begin(&rxdesc_stats->syncp); -+ ++rxdesc_stats->src_port_inval; -+ u64_stats_update_end(&rxdesc_stats->syncp); -+ -+ return NULL; -+ } -+ -+ /* Get netdev for this port using the source port -+ * number as index into the netdev array. We need to -+ * subtract one since the indices start form '0' and -+ * port numbers start from '1'. -+ */ -+ ndev = edma_ctx->netdev_arr[src_port_num - 1]; -+ } -+ -+ if (likely(ndev)) -+ return ndev; -+ -+ if (net_ratelimit()) -+ pr_warn("Netdev Null src_info_type:0x%x src port num:%d Drop skb:%p\n", -+ (src_info & EDMA_RXDESC_SRCINFO_TYPE_MASK), -+ src_port_num, skb); -+ -+ u64_stats_update_begin(&rxdesc_stats->syncp); -+ ++rxdesc_stats->src_port_inval_netdev; -+ u64_stats_update_end(&rxdesc_stats->syncp); -+ -+ return NULL; -+} -+ -+static int edma_rx_reap(struct edma_rxdesc_ring *rxdesc_ring, int budget) -+{ -+ struct edma_rxdesc_stats *rxdesc_stats = &rxdesc_ring->rxdesc_stats; -+ u32 alloc_size = rxdesc_ring->rxfill->alloc_size; -+ bool page_mode = rxdesc_ring->rxfill->page_mode; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct edma_rxdesc_pri *next_rxdesc_pri; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct device *dev = ppe_dev->dev; -+ u32 prod_idx, cons_idx, end_idx; -+ u32 work_to_do, work_done = 0; -+ struct sk_buff *next_skb; -+ u32 work_leftover, reg; -+ -+ /* Get Rx ring producer and consumer indices. */ -+ cons_idx = rxdesc_ring->cons_idx; -+ -+ if (likely(rxdesc_ring->work_leftover > EDMA_RX_MAX_PROCESS)) { -+ work_to_do = rxdesc_ring->work_leftover; -+ } else { -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_PROD_IDX(rxdesc_ring->ring_id); -+ regmap_read(regmap, reg, &prod_idx); -+ prod_idx = prod_idx & EDMA_RXDESC_PROD_IDX_MASK; -+ work_to_do = EDMA_DESC_AVAIL_COUNT(prod_idx, -+ cons_idx, EDMA_RX_RING_SIZE); -+ rxdesc_ring->work_leftover = work_to_do; -+ } -+ -+ if (work_to_do > budget) -+ work_to_do = budget; -+ -+ rxdesc_ring->work_leftover -= work_to_do; -+ end_idx = (cons_idx + work_to_do) & EDMA_RX_RING_SIZE_MASK; -+ next_rxdesc_pri = EDMA_RXDESC_PRI_DESC(rxdesc_ring, cons_idx); -+ -+ /* Get opaque from RXDESC. */ -+ next_skb = (struct sk_buff *)EDMA_RXDESC_OPAQUE_GET(next_rxdesc_pri); -+ -+ work_leftover = work_to_do & (EDMA_RX_MAX_PROCESS - 1); -+ while (likely(work_to_do--)) { -+ struct edma_rxdesc_pri *rxdesc_pri; -+ struct net_device *ndev; -+ struct sk_buff *skb; -+ dma_addr_t dma_addr; -+ -+ skb = next_skb; -+ rxdesc_pri = next_rxdesc_pri; -+ dma_addr = EDMA_RXDESC_BUFFER_ADDR_GET(rxdesc_pri); -+ -+ if (!page_mode) -+ dma_unmap_single(dev, dma_addr, alloc_size, -+ DMA_TO_DEVICE); -+ else -+ dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_TO_DEVICE); -+ -+ /* Update consumer index. */ -+ cons_idx = (cons_idx + 1) & EDMA_RX_RING_SIZE_MASK; -+ -+ /* Get the next Rx descriptor. */ -+ next_rxdesc_pri = EDMA_RXDESC_PRI_DESC(rxdesc_ring, cons_idx); -+ -+ /* Handle linear packets or initial segments first. */ -+ if (likely(!(rxdesc_ring->head))) { -+ ndev = edma_rx_get_src_dev(rxdesc_stats, rxdesc_pri, skb); -+ if (unlikely(!ndev)) { -+ dev_kfree_skb_any(skb); -+ goto next_rx_desc; -+ } -+ -+ /* Update skb fields for head skb. */ -+ skb->dev = ndev; -+ skb->skb_iif = ndev->ifindex; -+ -+ /* Handle linear packets. */ -+ if (likely(!EDMA_RXDESC_MORE_BIT_GET(rxdesc_pri))) { -+ next_skb = -+ (struct sk_buff *)EDMA_RXDESC_OPAQUE_GET(next_rxdesc_pri); -+ -+ if (unlikely(! -+ edma_rx_handle_linear_packets(rxdesc_ring, -+ rxdesc_pri, skb))) -+ dev_kfree_skb_any(skb); -+ -+ goto next_rx_desc; -+ } -+ } -+ -+ next_skb = (struct sk_buff *)EDMA_RXDESC_OPAQUE_GET(next_rxdesc_pri); -+ -+ /* Handle scatter frame processing for first/middle/last segments. */ -+ page_mode ? edma_rx_handle_nr_frags(rxdesc_ring, rxdesc_pri, skb) : -+ edma_rx_handle_frag_list(rxdesc_ring, rxdesc_pri, skb); -+ -+next_rx_desc: -+ /* Update work done. */ -+ work_done++; -+ -+ /* Check if we can refill EDMA_RX_MAX_PROCESS worth buffers, -+ * if yes, refill and update index before continuing. -+ */ -+ if (unlikely(!(work_done & (EDMA_RX_MAX_PROCESS - 1)))) { -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_CONS_IDX(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, cons_idx); -+ rxdesc_ring->cons_idx = cons_idx; -+ edma_rx_alloc_buffer_list(rxdesc_ring->rxfill, EDMA_RX_MAX_PROCESS); -+ } -+ } -+ -+ /* Check if we need to refill and update -+ * index for any buffers before exit. -+ */ -+ if (unlikely(work_leftover)) { -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_CONS_IDX(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, cons_idx); -+ rxdesc_ring->cons_idx = cons_idx; -+ edma_rx_alloc_buffer_list(rxdesc_ring->rxfill, work_leftover); -+ } -+ -+ return work_done; -+} -+ -+/** -+ * edma_rx_napi_poll - EDMA Rx napi poll. -+ * @napi: NAPI structure -+ * @budget: Rx NAPI budget -+ * -+ * EDMA RX NAPI handler to handle the NAPI poll. -+ * -+ * Return the number of packets processed. -+ */ -+int edma_rx_napi_poll(struct napi_struct *napi, int budget) -+{ -+ struct edma_rxdesc_ring *rxdesc_ring = (struct edma_rxdesc_ring *)napi; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ int work_done = 0; -+ u32 status, reg; -+ -+ do { -+ work_done += edma_rx_reap(rxdesc_ring, budget - work_done); -+ if (likely(work_done >= budget)) -+ return work_done; -+ -+ /* Check if there are more packets to process. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_INT_STAT(rxdesc_ring->ring_id); -+ regmap_read(regmap, reg, &status); -+ status = status & EDMA_RXDESC_RING_INT_STATUS_MASK; -+ } while (likely(status)); -+ -+ napi_complete(napi); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_INT_MASK(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_rx); -+ -+ return work_done; -+} -+ -+/** -+ * edma_rx_handle_irq - EDMA Rx handle irq. -+ * @irq: Interrupt to handle -+ * @ctx: Context -+ * -+ * Process RX IRQ and schedule NAPI. -+ * -+ * Return IRQ_HANDLED(1) on success. -+ */ -+irqreturn_t edma_rx_handle_irq(int irq, void *ctx) -+{ -+ struct edma_rxdesc_ring *rxdesc_ring = (struct edma_rxdesc_ring *)ctx; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 reg; -+ -+ if (likely(napi_schedule_prep(&rxdesc_ring->napi))) { -+ /* Disable RxDesc interrupt. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_INT_MASK(rxdesc_ring->ring_id); -+ regmap_write(regmap, reg, EDMA_MASK_INT_DISABLE); -+ __napi_schedule(&rxdesc_ring->napi); -+ } -+ -+ return IRQ_HANDLED; -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_rx.h -@@ -0,0 +1,287 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_RX__ -+#define __EDMA_RX__ -+ -+#include -+ -+#define EDMA_RXFILL_RING_PER_CORE_MAX 1 -+#define EDMA_RXDESC_RING_PER_CORE_MAX 1 -+ -+/* Max Rx processing without replenishing RxFill ring. */ -+#define EDMA_RX_MAX_PROCESS 32 -+ -+#define EDMA_RX_SKB_HEADROOM 128 -+#define EDMA_RX_QUEUE_START 0 -+#define EDMA_RX_BUFFER_SIZE 1984 -+#define EDMA_MAX_CORE 4 -+ -+#define EDMA_GET_DESC(R, i, type) (&(((type *)((R)->desc))[(i)])) -+#define EDMA_GET_PDESC(R, i, type) (&(((type *)((R)->pdesc))[(i)])) -+#define EDMA_GET_SDESC(R, i, type) (&(((type *)((R)->sdesc))[(i)])) -+#define EDMA_RXFILL_DESC(R, i) EDMA_GET_DESC(R, i, \ -+ struct edma_rxfill_desc) -+#define EDMA_RXDESC_PRI_DESC(R, i) EDMA_GET_PDESC(R, i, \ -+ struct edma_rxdesc_pri) -+#define EDMA_RXDESC_SEC_DESC(R, i) EDMA_GET_SDESC(R, i, \ -+ struct edma_rxdesc_sec) -+ -+#define EDMA_RX_RING_SIZE 2048 -+ -+#define EDMA_RX_RING_SIZE_MASK (EDMA_RX_RING_SIZE - 1) -+#define EDMA_RX_RING_ID_MASK 0x1F -+ -+#define EDMA_MAX_PRI_PER_CORE 8 -+#define EDMA_RX_PID_IPV4_MAX 0x3 -+#define EDMA_RX_PID_IPV6 0x4 -+#define EDMA_RX_PID_IS_IPV4(pid) (!((pid) & (~EDMA_RX_PID_IPV4_MAX))) -+#define EDMA_RX_PID_IS_IPV6(pid) (!(!((pid) & EDMA_RX_PID_IPV6))) -+ -+#define EDMA_RXDESC_BUFFER_ADDR_GET(desc) \ -+ ((u32)(le32_to_cpu((__force __le32)((desc)->word0)))) -+#define EDMA_RXDESC_OPAQUE_GET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ ((uintptr_t)((u64)((desc)->word2) | \ -+ ((u64)((desc)->word3) << 0x20))); }) -+ -+#define EDMA_RXDESC_SRCINFO_TYPE_PORTID 0x2000 -+#define EDMA_RXDESC_SRCINFO_TYPE_MASK 0xF000 -+#define EDMA_RXDESC_L3CSUM_STATUS_MASK BIT(13) -+#define EDMA_RXDESC_L4CSUM_STATUS_MASK BIT(12) -+#define EDMA_RXDESC_PORTNUM_BITS 0x0FFF -+ -+#define EDMA_RXDESC_PACKET_LEN_MASK 0x3FFFF -+#define EDMA_RXDESC_PACKET_LEN_GET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ ((le32_to_cpu((__force __le32)((desc)->word5))) & \ -+ EDMA_RXDESC_PACKET_LEN_MASK); }) -+ -+#define EDMA_RXDESC_MORE_BIT_MASK 0x40000000 -+#define EDMA_RXDESC_MORE_BIT_GET(desc) ((le32_to_cpu((__force __le32)((desc)->word1))) & \ -+ EDMA_RXDESC_MORE_BIT_MASK) -+#define EDMA_RXDESC_SRC_DST_INFO_GET(desc) \ -+ ((u32)((le32_to_cpu((__force __le32)((desc)->word4))))) -+ -+#define EDMA_RXDESC_L3_OFFSET_MASK GENMASK(23, 16) -+#define EDMA_RXDESC_L3_OFFSET_GET(desc) FIELD_GET(EDMA_RXDESC_L3_OFFSET_MASK, \ -+ le32_to_cpu((__force __le32)((desc)->word7))) -+ -+#define EDMA_RXDESC_PID_MASK GENMASK(15, 12) -+#define EDMA_RXDESC_PID_GET(desc) FIELD_GET(EDMA_RXDESC_PID_MASK, \ -+ le32_to_cpu((__force __le32)((desc)->word7))) -+ -+#define EDMA_RXDESC_DST_INFO_MASK GENMASK(31, 16) -+#define EDMA_RXDESC_DST_INFO_GET(desc) FIELD_GET(EDMA_RXDESC_DST_INFO_MASK, \ -+ le32_to_cpu((__force __le32)((desc)->word4))) -+ -+#define EDMA_RXDESC_SRC_INFO_MASK GENMASK(15, 0) -+#define EDMA_RXDESC_SRC_INFO_GET(desc) FIELD_GET(EDMA_RXDESC_SRC_INFO_MASK, \ -+ le32_to_cpu((__force __le32)((desc)->word4))) -+ -+#define EDMA_RXDESC_PORT_ID_MASK GENMASK(11, 0) -+#define EDMA_RXDESC_PORT_ID_GET(x) FIELD_GET(EDMA_RXDESC_PORT_ID_MASK, x) -+ -+#define EDMA_RXDESC_SRC_PORT_ID_GET(desc) (EDMA_RXDESC_PORT_ID_GET \ -+ (EDMA_RXDESC_SRC_INFO_GET(desc))) -+#define EDMA_RXDESC_DST_PORT_ID_GET(desc) (EDMA_RXDESC_PORT_ID_GET \ -+ (EDMA_RXDESC_DST_INFO_GET(desc))) -+ -+#define EDMA_RXDESC_DST_PORT (0x2 << EDMA_RXDESC_PID_SHIFT) -+ -+#define EDMA_RXDESC_L3CSUM_STATUS_GET(desc) FIELD_GET(EDMA_RXDESC_L3CSUM_STATUS_MASK, \ -+ le32_to_cpu((__force __le32)(desc)->word6)) -+#define EDMA_RXDESC_L4CSUM_STATUS_GET(desc) FIELD_GET(EDMA_RXDESC_L4CSUM_STATUS_MASK, \ -+ le32_to_cpu((__force __le32)(desc)->word6)) -+ -+#define EDMA_RXDESC_DATA_OFFSET_MASK GENMASK(11, 0) -+#define EDMA_RXDESC_DATA_OFFSET_GET(desc) FIELD_GET(EDMA_RXDESC_DATA_OFFSET_MASK, \ -+ le32_to_cpu((__force __le32)(desc)->word6)) -+ -+#define EDMA_RXFILL_BUF_SIZE_MASK 0xFFFF -+#define EDMA_RXFILL_BUF_SIZE_SHIFT 16 -+ -+/* Opaque values are not accessed by the EDMA HW, -+ * so endianness conversion is not needed. -+ */ -+ -+#define EDMA_RXFILL_OPAQUE_LO_SET(desc, ptr) (((desc)->word2) = \ -+ (u32)(uintptr_t)(ptr)) -+#ifdef __LP64__ -+#define EDMA_RXFILL_OPAQUE_HI_SET(desc, ptr) (((desc)->word3) = \ -+ (u32)((u64)(ptr) >> 0x20)) -+#endif -+ -+#define EDMA_RXFILL_OPAQUE_GET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ ((uintptr_t)((u64)((desc)->word2) | \ -+ ((u64)((desc)->word3) << 0x20))); }) -+ -+#define EDMA_RXFILL_PACKET_LEN_SET(desc, len) { \ -+ (((desc)->word1) = (u32)((((u32)len) << EDMA_RXFILL_BUF_SIZE_SHIFT) & \ -+ 0xFFFF0000)); \ -+} -+ -+#define EDMA_RXFILL_BUFFER_ADDR_SET(desc, addr) (((desc)->word0) = (u32)(addr)) -+ -+/* Opaque values are set in word2 and word3, they are not accessed by the EDMA HW, -+ * so endianness conversion is not needed. -+ */ -+#define EDMA_RXFILL_ENDIAN_SET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ cpu_to_le32s(&((desc)->word0)); \ -+ cpu_to_le32s(&((desc)->word1)); \ -+}) -+ -+/* RX DESC size shift to obtain index from descriptor pointer. */ -+#define EDMA_RXDESC_SIZE_SHIFT 5 -+ -+/** -+ * struct edma_rxdesc_stats - RX descriptor ring stats. -+ * @src_port_inval: Invalid source port number -+ * @src_port_inval_type: Source type is not PORT ID -+ * @src_port_inval_netdev: Invalid net device for the source port -+ * @syncp: Synchronization pointer -+ */ -+struct edma_rxdesc_stats { -+ u64 src_port_inval; -+ u64 src_port_inval_type; -+ u64 src_port_inval_netdev; -+ struct u64_stats_sync syncp; -+}; -+ -+/** -+ * struct edma_rxfill_stats - Rx fill descriptor ring stats. -+ * @alloc_failed: Buffer allocation failure count -+ * @page_alloc_failed: Page allocation failure count for page mode -+ * @syncp: Synchronization pointer -+ */ -+struct edma_rxfill_stats { -+ u64 alloc_failed; -+ u64 page_alloc_failed; -+ struct u64_stats_sync syncp; -+}; -+ -+/** -+ * struct edma_rxdesc_pri - Rx descriptor. -+ * @word0: Buffer address -+ * @word1: More bit, priority bit, service code -+ * @word2: Opaque low bits -+ * @word3: Opaque high bits -+ * @word4: Destination and source information -+ * @word5: WiFi QoS, data length -+ * @word6: Hash value, check sum status -+ * @word7: DSCP, packet offsets -+ */ -+struct edma_rxdesc_pri { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+ u32 word4; -+ u32 word5; -+ u32 word6; -+ u32 word7; -+}; -+ -+ /** -+ * struct edma_rxdesc_sec - Rx secondary descriptor. -+ * @word0: Timestamp -+ * @word1: Secondary checksum status -+ * @word2: QoS tag -+ * @word3: Flow index details -+ * @word4: Secondary packet offsets -+ * @word5: Multicast bit, checksum -+ * @word6: SVLAN, CVLAN -+ * @word7: Secondary SVLAN, CVLAN -+ */ -+struct edma_rxdesc_sec { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+ u32 word4; -+ u32 word5; -+ u32 word6; -+ u32 word7; -+}; -+ -+/** -+ * struct edma_rxfill_desc - RxFill descriptor. -+ * @word0: Buffer address -+ * @word1: Buffer size -+ * @word2: Opaque low bits -+ * @word3: Opaque high bits -+ */ -+struct edma_rxfill_desc { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+}; -+ -+/** -+ * struct edma_rxfill_ring - RxFill ring -+ * @ring_id: RxFill ring number -+ * @count: Number of descriptors in the ring -+ * @prod_idx: Ring producer index -+ * @alloc_size: Buffer size to allocate -+ * @desc: Descriptor ring virtual address -+ * @dma: Descriptor ring physical address -+ * @buf_len: Buffer length for rxfill descriptor -+ * @page_mode: Page mode for Rx processing -+ * @rx_fill_stats: Rx fill ring statistics -+ */ -+struct edma_rxfill_ring { -+ u32 ring_id; -+ u32 count; -+ u32 prod_idx; -+ u32 alloc_size; -+ struct edma_rxfill_desc *desc; -+ dma_addr_t dma; -+ u32 buf_len; -+ bool page_mode; -+ struct edma_rxfill_stats rxfill_stats; -+}; -+ -+/** -+ * struct edma_rxdesc_ring - RxDesc ring -+ * @napi: Pointer to napi -+ * @ring_id: Rxdesc ring number -+ * @count: Number of descriptors in the ring -+ * @work_leftover: Leftover descriptors to be processed -+ * @cons_idx: Ring consumer index -+ * @pdesc: Primary descriptor ring virtual address -+ * @pdesc_head: Primary descriptor head in case of scatter-gather frame -+ * @sdesc: Secondary descriptor ring virtual address -+ * @rxdesc_stats: Rx descriptor ring statistics -+ * @rxfill: RxFill ring used -+ * @napi_added: Flag to indicate NAPI add status -+ * @pdma: Primary descriptor ring physical address -+ * @sdma: Secondary descriptor ring physical address -+ * @head: Head of the skb list in case of scatter-gather frame -+ * @last: Last skb of the skb list in case of scatter-gather frame -+ */ -+struct edma_rxdesc_ring { -+ struct napi_struct napi; -+ u32 ring_id; -+ u32 count; -+ u32 work_leftover; -+ u32 cons_idx; -+ struct edma_rxdesc_pri *pdesc; -+ struct edma_rxdesc_pri *pdesc_head; -+ struct edma_rxdesc_sec *sdesc; -+ struct edma_rxdesc_stats rxdesc_stats; -+ struct edma_rxfill_ring *rxfill; -+ bool napi_added; -+ dma_addr_t pdma; -+ dma_addr_t sdma; -+ struct sk_buff *head; -+ struct sk_buff *last; -+}; -+ -+irqreturn_t edma_rx_handle_irq(int irq, void *ctx); -+int edma_rx_alloc_buffer(struct edma_rxfill_ring *rxfill_ring, int alloc_count); -+int edma_rx_napi_poll(struct napi_struct *napi, int budget); -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0345-net-ethernet-qualcomm-Add-Tx-Ethernet-DMA-support.patch b/target/linux/qualcommbe/patches-6.12/0345-net-ethernet-qualcomm-Add-Tx-Ethernet-DMA-support.patch deleted file mode 100644 index 39d300de80..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0345-net-ethernet-qualcomm-Add-Tx-Ethernet-DMA-support.patch +++ /dev/null @@ -1,2363 +0,0 @@ -From 339d3a5365f150a78ed405684e379fee3acdbe90 Mon Sep 17 00:00:00 2001 -From: Suruchi Agarwal -Date: Thu, 21 Mar 2024 16:26:29 -0700 -Subject: [PATCH] net: ethernet: qualcomm: Add Tx Ethernet DMA support - -Add Tx queues, rings, descriptors configurations and -DMA support for the EDMA. - -Change-Id: Idfb0e1fe5ac494d614097d6c97dd15d63bbce8e6 -Co-developed-by: Pavithra R -Signed-off-by: Pavithra R -Signed-off-by: Suruchi Agarwal ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/edma.c | 97 ++- - drivers/net/ethernet/qualcomm/ppe/edma.h | 7 + - .../net/ethernet/qualcomm/ppe/edma_cfg_tx.c | 648 ++++++++++++++ - .../net/ethernet/qualcomm/ppe/edma_cfg_tx.h | 28 + - drivers/net/ethernet/qualcomm/ppe/edma_port.c | 136 +++ - drivers/net/ethernet/qualcomm/ppe/edma_port.h | 35 + - drivers/net/ethernet/qualcomm/ppe/edma_tx.c | 808 ++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma_tx.h | 302 +++++++ - 9 files changed, 2055 insertions(+), 8 deletions(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.h - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_tx.c - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_tx.h - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o - - #EDMA --qcom-ppe-objs += edma.o edma_cfg_rx.o edma_port.o edma_rx.o -+qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_port.o edma_rx.o edma_tx.o ---- a/drivers/net/ethernet/qualcomm/ppe/edma.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -18,6 +18,7 @@ - #include - - #include "edma.h" -+#include "edma_cfg_tx.h" - #include "edma_cfg_rx.h" - #include "ppe_regs.h" - -@@ -25,6 +26,7 @@ - - /* Global EDMA context. */ - struct edma_context *edma_ctx; -+static char **edma_txcmpl_irq_name; - static char **edma_rxdesc_irq_name; - - /* Module params. */ -@@ -192,22 +194,59 @@ static int edma_configure_ucast_prio_map - static int edma_irq_register(void) - { - struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; - struct edma_ring_info *rx = hw_info->rx; - int ret; - u32 i; - -+ /* Request IRQ for TXCMPL rings. */ -+ edma_txcmpl_irq_name = kzalloc((sizeof(char *) * txcmpl->num_rings), GFP_KERNEL); -+ if (!edma_txcmpl_irq_name) -+ return -ENOMEM; -+ -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ edma_txcmpl_irq_name[i] = kzalloc((sizeof(char *) * EDMA_IRQ_NAME_SIZE), -+ GFP_KERNEL); -+ if (!edma_txcmpl_irq_name[i]) { -+ ret = -ENOMEM; -+ goto txcmpl_ring_irq_name_alloc_fail; -+ } -+ -+ snprintf(edma_txcmpl_irq_name[i], EDMA_IRQ_NAME_SIZE, "edma_txcmpl_%d", -+ txcmpl->ring_start + i); -+ -+ irq_set_status_flags(edma_ctx->intr_info.intr_txcmpl[i], IRQ_DISABLE_UNLAZY); -+ -+ ret = request_irq(edma_ctx->intr_info.intr_txcmpl[i], -+ edma_tx_handle_irq, IRQF_SHARED, -+ edma_txcmpl_irq_name[i], -+ (void *)&edma_ctx->txcmpl_rings[i]); -+ if (ret) { -+ pr_err("TXCMPL ring IRQ:%d request %d failed\n", -+ edma_ctx->intr_info.intr_txcmpl[i], i); -+ goto txcmpl_ring_intr_req_fail; -+ } -+ -+ pr_debug("TXCMPL ring: %d IRQ:%d request success: %s\n", -+ txcmpl->ring_start + i, -+ edma_ctx->intr_info.intr_txcmpl[i], -+ edma_txcmpl_irq_name[i]); -+ } -+ - /* Request IRQ for RXDESC rings. */ - edma_rxdesc_irq_name = kzalloc((sizeof(char *) * rx->num_rings), - GFP_KERNEL); -- if (!edma_rxdesc_irq_name) -- return -ENOMEM; -+ if (!edma_rxdesc_irq_name) { -+ ret = -ENOMEM; -+ goto rxdesc_irq_name_alloc_fail; -+ } - - for (i = 0; i < rx->num_rings; i++) { - edma_rxdesc_irq_name[i] = kzalloc((sizeof(char *) * EDMA_IRQ_NAME_SIZE), - GFP_KERNEL); - if (!edma_rxdesc_irq_name[i]) { - ret = -ENOMEM; -- goto rxdesc_irq_name_alloc_fail; -+ goto rxdesc_ring_irq_name_alloc_fail; - } - - snprintf(edma_rxdesc_irq_name[i], 20, "edma_rxdesc_%d", -@@ -236,8 +275,19 @@ static int edma_irq_register(void) - rx_desc_ring_intr_req_fail: - for (i = 0; i < rx->num_rings; i++) - kfree(edma_rxdesc_irq_name[i]); --rxdesc_irq_name_alloc_fail: -+rxdesc_ring_irq_name_alloc_fail: - kfree(edma_rxdesc_irq_name); -+rxdesc_irq_name_alloc_fail: -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ synchronize_irq(edma_ctx->intr_info.intr_txcmpl[i]); -+ free_irq(edma_ctx->intr_info.intr_txcmpl[i], -+ (void *)&edma_ctx->txcmpl_rings[i]); -+ } -+txcmpl_ring_intr_req_fail: -+ for (i = 0; i < txcmpl->num_rings; i++) -+ kfree(edma_txcmpl_irq_name[i]); -+txcmpl_ring_irq_name_alloc_fail: -+ kfree(edma_txcmpl_irq_name); - - return ret; - } -@@ -326,12 +376,22 @@ static int edma_irq_init(void) - - static int edma_alloc_rings(void) - { -+ if (edma_cfg_tx_rings_alloc()) { -+ pr_err("Error in allocating Tx rings\n"); -+ return -ENOMEM; -+ } -+ - if (edma_cfg_rx_rings_alloc()) { - pr_err("Error in allocating Rx rings\n"); -- return -ENOMEM; -+ goto rx_rings_alloc_fail; - } - - return 0; -+ -+rx_rings_alloc_fail: -+ edma_cfg_tx_rings_cleanup(); -+ -+ return -ENOMEM; - } - - static int edma_hw_reset(void) -@@ -389,7 +449,7 @@ static int edma_hw_configure(void) - struct edma_hw_info *hw_info = edma_ctx->hw_info; - struct ppe_device *ppe_dev = edma_ctx->ppe_dev; - struct regmap *regmap = ppe_dev->regmap; -- u32 data, reg; -+ u32 data, reg, i; - int ret; - - reg = EDMA_BASE_OFFSET + EDMA_REG_MAS_CTRL_ADDR; -@@ -439,11 +499,17 @@ static int edma_hw_configure(void) - } - - /* Disable interrupts. */ -+ for (i = 1; i <= hw_info->max_ports; i++) -+ edma_cfg_tx_disable_interrupts(i); -+ - edma_cfg_rx_disable_interrupts(); - - edma_cfg_rx_rings_disable(); - - edma_cfg_rx_ring_mappings(); -+ edma_cfg_tx_ring_mappings(); -+ -+ edma_cfg_tx_rings(); - - ret = edma_cfg_rx_rings(); - if (ret) { -@@ -520,6 +586,7 @@ configure_ucast_prio_map_tbl_failed: - edma_cfg_rx_napi_delete(); - edma_cfg_rx_rings_disable(); - edma_cfg_rx_rings_failed: -+ edma_cfg_tx_rings_cleanup(); - edma_cfg_rx_rings_cleanup(); - edma_alloc_rings_failed: - free_netdev(edma_ctx->dummy_dev); -@@ -538,13 +605,27 @@ dummy_dev_alloc_failed: - void edma_destroy(struct ppe_device *ppe_dev) - { - struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; - struct edma_ring_info *rx = hw_info->rx; - u32 i; - - /* Disable interrupts. */ -+ for (i = 1; i <= hw_info->max_ports; i++) -+ edma_cfg_tx_disable_interrupts(i); -+ - edma_cfg_rx_disable_interrupts(); - -- /* Free IRQ for RXDESC rings. */ -+ /* Free IRQ for TXCMPL rings. */ -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ synchronize_irq(edma_ctx->intr_info.intr_txcmpl[i]); -+ -+ free_irq(edma_ctx->intr_info.intr_txcmpl[i], -+ (void *)&edma_ctx->txcmpl_rings[i]); -+ kfree(edma_txcmpl_irq_name[i]); -+ } -+ kfree(edma_txcmpl_irq_name); -+ -+ /* Free IRQ for RXDESC rings */ - for (i = 0; i < rx->num_rings; i++) { - synchronize_irq(edma_ctx->intr_info.intr_rx[i]); - free_irq(edma_ctx->intr_info.intr_rx[i], -@@ -560,6 +641,7 @@ void edma_destroy(struct ppe_device *ppe - edma_cfg_rx_napi_delete(); - edma_cfg_rx_rings_disable(); - edma_cfg_rx_rings_cleanup(); -+ edma_cfg_tx_rings_cleanup(); - - free_netdev(edma_ctx->dummy_dev); - kfree(edma_ctx->netdev_arr); -@@ -585,6 +667,7 @@ int edma_setup(struct ppe_device *ppe_de - edma_ctx->hw_info = &ipq9574_hw_info; - edma_ctx->ppe_dev = ppe_dev; - edma_ctx->rx_buf_size = rx_buff_size; -+ edma_ctx->tx_requeue_stop = false; - - /* Configure the EDMA common clocks. */ - ret = edma_clock_init(); ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -7,6 +7,7 @@ - - #include "ppe_config.h" - #include "edma_rx.h" -+#include "edma_tx.h" - - /* One clock cycle = 1/(EDMA clock frequency in Mhz) micro seconds. - * -@@ -104,8 +105,11 @@ struct edma_intr_info { - * @intr_info: EDMA Interrupt info - * @rxfill_rings: Rx fill Rings, SW is producer - * @rx_rings: Rx Desc Rings, SW is consumer -+ * @tx_rings: Tx Descriptor Ring, SW is producer -+ * @txcmpl_rings: Tx complete Ring, SW is consumer - * @rx_page_mode: Page mode enabled or disabled - * @rx_buf_size: Rx buffer size for Jumbo MRU -+ * @tx_requeue_stop: Tx requeue stop enabled or disabled - */ - struct edma_context { - struct net_device **netdev_arr; -@@ -115,8 +119,11 @@ struct edma_context { - struct edma_intr_info intr_info; - struct edma_rxfill_ring *rxfill_rings; - struct edma_rxdesc_ring *rx_rings; -+ struct edma_txdesc_ring *tx_rings; -+ struct edma_txcmpl_ring *txcmpl_rings; - u32 rx_page_mode; - u32 rx_buf_size; -+ bool tx_requeue_stop; - }; - - /* Global EDMA context */ ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.c -@@ -0,0 +1,648 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* Configure rings, Buffers and NAPI for transmit path along with -+ * providing APIs to enable, disable, clean and map the Tx rings. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_cfg_tx.h" -+#include "edma_port.h" -+#include "ppe.h" -+#include "ppe_regs.h" -+ -+static void edma_cfg_txcmpl_ring_cleanup(struct edma_txcmpl_ring *txcmpl_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ -+ /* Free any buffers assigned to any descriptors. */ -+ edma_tx_complete(EDMA_TX_RING_SIZE - 1, txcmpl_ring); -+ -+ /* Free TxCmpl ring descriptors. */ -+ dma_free_coherent(dev, sizeof(struct edma_txcmpl_desc) -+ * txcmpl_ring->count, txcmpl_ring->desc, -+ txcmpl_ring->dma); -+ txcmpl_ring->desc = NULL; -+ txcmpl_ring->dma = (dma_addr_t)0; -+} -+ -+static int edma_cfg_txcmpl_ring_setup(struct edma_txcmpl_ring *txcmpl_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ -+ /* Allocate RxFill ring descriptors. */ -+ txcmpl_ring->desc = dma_alloc_coherent(dev, sizeof(struct edma_txcmpl_desc) -+ * txcmpl_ring->count, -+ &txcmpl_ring->dma, -+ GFP_KERNEL | __GFP_ZERO); -+ -+ if (unlikely(!txcmpl_ring->desc)) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static void edma_cfg_tx_desc_ring_cleanup(struct edma_txdesc_ring *txdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txdesc_pri *txdesc = NULL; -+ struct device *dev = ppe_dev->dev; -+ u32 prod_idx, cons_idx, data, reg; -+ struct sk_buff *skb = NULL; -+ -+ /* Free any buffers assigned to any descriptors. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_PROD_IDX(txdesc_ring->id); -+ regmap_read(regmap, reg, &data); -+ prod_idx = data & EDMA_TXDESC_PROD_IDX_MASK; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_CONS_IDX(txdesc_ring->id); -+ regmap_read(regmap, reg, &data); -+ cons_idx = data & EDMA_TXDESC_CONS_IDX_MASK; -+ -+ /* Walk active list, obtain skb from descriptor and free it. */ -+ while (cons_idx != prod_idx) { -+ txdesc = EDMA_TXDESC_PRI_DESC(txdesc_ring, cons_idx); -+ skb = (struct sk_buff *)EDMA_TXDESC_OPAQUE_GET(txdesc); -+ dev_kfree_skb_any(skb); -+ -+ cons_idx = ((cons_idx + 1) & EDMA_TX_RING_SIZE_MASK); -+ } -+ -+ /* Free Tx ring descriptors. */ -+ dma_free_coherent(dev, (sizeof(struct edma_txdesc_pri) -+ * txdesc_ring->count), -+ txdesc_ring->pdesc, -+ txdesc_ring->pdma); -+ txdesc_ring->pdesc = NULL; -+ txdesc_ring->pdma = (dma_addr_t)0; -+ -+ /* Free any buffers assigned to any secondary descriptors. */ -+ dma_free_coherent(dev, (sizeof(struct edma_txdesc_sec) -+ * txdesc_ring->count), -+ txdesc_ring->sdesc, -+ txdesc_ring->sdma); -+ txdesc_ring->sdesc = NULL; -+ txdesc_ring->sdma = (dma_addr_t)0; -+} -+ -+static int edma_cfg_tx_desc_ring_setup(struct edma_txdesc_ring *txdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ -+ /* Allocate RxFill ring descriptors. */ -+ txdesc_ring->pdesc = dma_alloc_coherent(dev, sizeof(struct edma_txdesc_pri) -+ * txdesc_ring->count, -+ &txdesc_ring->pdma, -+ GFP_KERNEL | __GFP_ZERO); -+ -+ if (unlikely(!txdesc_ring->pdesc)) -+ return -ENOMEM; -+ -+ txdesc_ring->sdesc = dma_alloc_coherent(dev, sizeof(struct edma_txdesc_sec) -+ * txdesc_ring->count, -+ &txdesc_ring->sdma, -+ GFP_KERNEL | __GFP_ZERO); -+ -+ if (unlikely(!txdesc_ring->sdesc)) { -+ dma_free_coherent(dev, (sizeof(struct edma_txdesc_pri) -+ * txdesc_ring->count), -+ txdesc_ring->pdesc, -+ txdesc_ring->pdma); -+ txdesc_ring->pdesc = NULL; -+ txdesc_ring->pdma = (dma_addr_t)0; -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void edma_cfg_tx_desc_ring_configure(struct edma_txdesc_ring *txdesc_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 data, reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_BA(txdesc_ring->id); -+ regmap_write(regmap, reg, (u32)(txdesc_ring->pdma & EDMA_RING_DMA_MASK)); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_BA2(txdesc_ring->id); -+ regmap_write(regmap, reg, (u32)(txdesc_ring->sdma & EDMA_RING_DMA_MASK)); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_RING_SIZE(txdesc_ring->id); -+ regmap_write(regmap, reg, (u32)(txdesc_ring->count & EDMA_TXDESC_RING_SIZE_MASK)); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_PROD_IDX(txdesc_ring->id); -+ regmap_write(regmap, reg, (u32)EDMA_TX_INITIAL_PROD_IDX); -+ -+ data = FIELD_PREP(EDMA_TXDESC_CTRL_FC_GRP_ID_MASK, txdesc_ring->fc_grp_id); -+ -+ /* Configure group ID for flow control for this Tx ring. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_CTRL(txdesc_ring->id); -+ regmap_write(regmap, reg, data); -+} -+ -+static void edma_cfg_txcmpl_ring_configure(struct edma_txcmpl_ring *txcmpl_ring) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 data, reg; -+ -+ /* Configure TxCmpl ring base address. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_BA(txcmpl_ring->id); -+ regmap_write(regmap, reg, (u32)(txcmpl_ring->dma & EDMA_RING_DMA_MASK)); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_RING_SIZE(txcmpl_ring->id); -+ regmap_write(regmap, reg, (u32)(txcmpl_ring->count & EDMA_TXDESC_RING_SIZE_MASK)); -+ -+ /* Set TxCmpl ret mode to opaque. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_CTRL(txcmpl_ring->id); -+ regmap_write(regmap, reg, EDMA_TXCMPL_RETMODE_OPAQUE); -+ -+ /* Configure the Mitigation timer. */ -+ data = EDMA_MICROSEC_TO_TIMER_UNIT(EDMA_TX_MITIGATION_TIMER_DEF, -+ ppe_dev->clk_rate / MHZ); -+ data = ((data & EDMA_TX_MOD_TIMER_INIT_MASK) -+ << EDMA_TX_MOD_TIMER_INIT_SHIFT); -+ pr_debug("EDMA Tx mitigation timer value: %d\n", data); -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_MOD_TIMER(txcmpl_ring->id); -+ regmap_write(regmap, reg, data); -+ -+ /* Configure the Mitigation packet count. */ -+ data = (EDMA_TX_MITIGATION_PKT_CNT_DEF & EDMA_TXCMPL_LOW_THRE_MASK) -+ << EDMA_TXCMPL_LOW_THRE_SHIFT; -+ pr_debug("EDMA Tx mitigation packet count value: %d\n", data); -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_UGT_THRE(txcmpl_ring->id); -+ regmap_write(regmap, reg, data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_CTRL(txcmpl_ring->id); -+ regmap_write(regmap, reg, EDMA_TX_NE_INT_EN); -+} -+ -+/** -+ * edma_cfg_tx_fill_per_port_tx_map - Fill Tx ring mapping. -+ * @netdev: Netdevice. -+ * @port_id: Port ID. -+ * -+ * Fill per-port Tx ring mapping in net device private area. -+ */ -+void edma_cfg_tx_fill_per_port_tx_map(struct net_device *netdev, u32 port_id) -+{ -+ u32 i; -+ -+ /* Ring to core mapping is done in order starting from 0 for port 1. */ -+ for_each_possible_cpu(i) { -+ struct edma_port_priv *port_dev = (struct edma_port_priv *)netdev_priv(netdev); -+ struct edma_txdesc_ring *txdesc_ring; -+ u32 txdesc_ring_id; -+ -+ txdesc_ring_id = ((port_id - 1) * num_possible_cpus()) + i; -+ txdesc_ring = &edma_ctx->tx_rings[txdesc_ring_id]; -+ port_dev->txr_map[i] = txdesc_ring; -+ } -+} -+ -+/** -+ * edma_cfg_tx_rings_enable - Enable Tx rings. -+ * -+ * Enable Tx rings. -+ */ -+void edma_cfg_tx_rings_enable(u32 port_id) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txdesc_ring *txdesc_ring; -+ u32 i, ring_idx, reg; -+ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txdesc_ring = &edma_ctx->tx_rings[ring_idx]; -+ u32 data; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_CTRL(txdesc_ring->id); -+ regmap_read(regmap, reg, &data); -+ data |= FIELD_PREP(EDMA_TXDESC_CTRL_TXEN_MASK, EDMA_TXDESC_TX_ENABLE); -+ -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+/** -+ * edma_cfg_tx_rings_disable - Disable Tx rings. -+ * -+ * Disable Tx rings. -+ */ -+void edma_cfg_tx_rings_disable(u32 port_id) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txdesc_ring *txdesc_ring; -+ u32 i, ring_idx, reg; -+ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txdesc_ring = &edma_ctx->tx_rings[ring_idx]; -+ u32 data; -+ -+ txdesc_ring = &edma_ctx->tx_rings[i]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_CTRL(txdesc_ring->id); -+ regmap_read(regmap, reg, &data); -+ data &= ~EDMA_TXDESC_TX_ENABLE; -+ regmap_write(regmap, reg, data); -+ } -+} -+ -+/** -+ * edma_cfg_tx_ring_mappings - Map Tx to Tx complete rings. -+ * -+ * Map Tx to Tx complete rings. -+ */ -+void edma_cfg_tx_ring_mappings(void) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_ring_info *tx = hw_info->tx; -+ u32 desc_index, i, data, reg; -+ -+ /* Clear the TXDESC2CMPL_MAP_xx reg before setting up -+ * the mapping. This register holds TXDESC to TXFILL ring -+ * mapping. -+ */ -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_0_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_1_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_2_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_3_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_4_ADDR, 0); -+ regmap_write(regmap, EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_5_ADDR, 0); -+ desc_index = txcmpl->ring_start; -+ -+ /* 6 registers to hold the completion mapping for total 32 -+ * TX desc rings (0-5, 6-11, 12-17, 18-23, 24-29 and rest). -+ * In each entry 5 bits hold the mapping for a particular TX desc ring. -+ */ -+ for (i = tx->ring_start; i < tx->ring_start + tx->num_rings; i++) { -+ u32 reg, data; -+ -+ if (i >= 0 && i <= 5) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_0_ADDR; -+ else if (i >= 6 && i <= 11) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_1_ADDR; -+ else if (i >= 12 && i <= 17) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_2_ADDR; -+ else if (i >= 18 && i <= 23) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_3_ADDR; -+ else if (i >= 24 && i <= 29) -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_4_ADDR; -+ else -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_5_ADDR; -+ -+ pr_debug("Configure Tx desc:%u to use TxCmpl:%u\n", i, desc_index); -+ -+ /* Set the Tx complete descriptor ring number in the mapping register. -+ * E.g. If (txcmpl ring)desc_index = 31, (txdesc ring)i = 28. -+ * reg = EDMA_REG_TXDESC2CMPL_MAP_4_ADDR -+ * data |= (desc_index & 0x1F) << ((i % 6) * 5); -+ * data |= (0x1F << 20); - -+ * This sets 11111 at 20th bit of register EDMA_REG_TXDESC2CMPL_MAP_4_ADDR. -+ */ -+ regmap_read(regmap, reg, &data); -+ data |= (desc_index & EDMA_TXDESC2CMPL_MAP_TXDESC_MASK) << ((i % 6) * 5); -+ regmap_write(regmap, reg, data); -+ -+ desc_index++; -+ if (desc_index == txcmpl->ring_start + txcmpl->num_rings) -+ desc_index = txcmpl->ring_start; -+ } -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_0_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_0_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_1_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_1_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_2_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_2_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_3_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_3_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_4_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_4_ADDR: 0x%x\n", data); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC2CMPL_MAP_5_ADDR; -+ regmap_read(regmap, reg, &data); -+ pr_debug("EDMA_REG_TXDESC2CMPL_MAP_5_ADDR: 0x%x\n", data); -+} -+ -+static int edma_cfg_tx_rings_setup(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct edma_ring_info *tx = hw_info->tx; -+ u32 i, j = 0; -+ -+ /* Set Txdesc flow control group id, same as port number. */ -+ for (i = 0; i < hw_info->max_ports; i++) { -+ for_each_possible_cpu(j) { -+ struct edma_txdesc_ring *txdesc_ring = NULL; -+ u32 txdesc_idx = (i * num_possible_cpus()) + j; -+ -+ txdesc_ring = &edma_ctx->tx_rings[txdesc_idx]; -+ txdesc_ring->fc_grp_id = i + 1; -+ } -+ } -+ -+ /* Allocate TxDesc ring descriptors. */ -+ for (i = 0; i < tx->num_rings; i++) { -+ struct edma_txdesc_ring *txdesc_ring = NULL; -+ int ret; -+ -+ txdesc_ring = &edma_ctx->tx_rings[i]; -+ txdesc_ring->count = EDMA_TX_RING_SIZE; -+ txdesc_ring->id = tx->ring_start + i; -+ -+ ret = edma_cfg_tx_desc_ring_setup(txdesc_ring); -+ if (ret) { -+ pr_err("Error in setting up %d txdesc ring. ret: %d", -+ txdesc_ring->id, ret); -+ while (i-- >= 0) -+ edma_cfg_tx_desc_ring_cleanup(&edma_ctx->tx_rings[i]); -+ -+ return -ENOMEM; -+ } -+ } -+ -+ /* Allocate TxCmpl ring descriptors. */ -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ struct edma_txcmpl_ring *txcmpl_ring = NULL; -+ int ret; -+ -+ txcmpl_ring = &edma_ctx->txcmpl_rings[i]; -+ txcmpl_ring->count = EDMA_TX_RING_SIZE; -+ txcmpl_ring->id = txcmpl->ring_start + i; -+ -+ ret = edma_cfg_txcmpl_ring_setup(txcmpl_ring); -+ if (ret != 0) { -+ pr_err("Error in setting up %d TxCmpl ring. ret: %d", -+ txcmpl_ring->id, ret); -+ while (i-- >= 0) -+ edma_cfg_txcmpl_ring_cleanup(&edma_ctx->txcmpl_rings[i]); -+ -+ goto txcmpl_mem_alloc_fail; -+ } -+ } -+ -+ pr_debug("Tx descriptor count for Tx desc and Tx complete rings: %d\n", -+ EDMA_TX_RING_SIZE); -+ -+ return 0; -+ -+txcmpl_mem_alloc_fail: -+ for (i = 0; i < tx->num_rings; i++) -+ edma_cfg_tx_desc_ring_cleanup(&edma_ctx->tx_rings[i]); -+ -+ return -ENOMEM; -+} -+ -+/** -+ * edma_cfg_tx_rings_alloc - Allocate EDMA Tx rings. -+ * -+ * Allocate EDMA Tx rings. -+ */ -+int edma_cfg_tx_rings_alloc(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct edma_ring_info *tx = hw_info->tx; -+ -+ edma_ctx->tx_rings = kzalloc((sizeof(*edma_ctx->tx_rings) * tx->num_rings), -+ GFP_KERNEL); -+ if (!edma_ctx->tx_rings) -+ return -ENOMEM; -+ -+ edma_ctx->txcmpl_rings = kzalloc((sizeof(*edma_ctx->txcmpl_rings) * txcmpl->num_rings), -+ GFP_KERNEL); -+ if (!edma_ctx->txcmpl_rings) -+ goto txcmpl_ring_alloc_fail; -+ -+ pr_debug("Num rings - TxDesc:%u (%u-%u) TxCmpl:%u (%u-%u)\n", -+ tx->num_rings, tx->ring_start, -+ (tx->ring_start + tx->num_rings - 1), -+ txcmpl->num_rings, txcmpl->ring_start, -+ (txcmpl->ring_start + txcmpl->num_rings - 1)); -+ -+ if (edma_cfg_tx_rings_setup()) { -+ pr_err("Error in setting up tx rings\n"); -+ goto tx_rings_setup_fail; -+ } -+ -+ return 0; -+ -+tx_rings_setup_fail: -+ kfree(edma_ctx->txcmpl_rings); -+ edma_ctx->txcmpl_rings = NULL; -+ -+txcmpl_ring_alloc_fail: -+ kfree(edma_ctx->tx_rings); -+ edma_ctx->tx_rings = NULL; -+ -+ return -ENOMEM; -+} -+ -+/** -+ * edma_cfg_tx_rings_cleanup - Cleanup EDMA Tx rings. -+ * -+ * Cleanup EDMA Tx rings. -+ */ -+void edma_cfg_tx_rings_cleanup(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct edma_ring_info *tx = hw_info->tx; -+ u32 i; -+ -+ /* Free any buffers assigned to any descriptors. */ -+ for (i = 0; i < tx->num_rings; i++) -+ edma_cfg_tx_desc_ring_cleanup(&edma_ctx->tx_rings[i]); -+ -+ /* Free Tx completion descriptors. */ -+ for (i = 0; i < txcmpl->num_rings; i++) -+ edma_cfg_txcmpl_ring_cleanup(&edma_ctx->txcmpl_rings[i]); -+ -+ kfree(edma_ctx->tx_rings); -+ kfree(edma_ctx->txcmpl_rings); -+ edma_ctx->tx_rings = NULL; -+ edma_ctx->txcmpl_rings = NULL; -+} -+ -+/** -+ * edma_cfg_tx_rings - Configure EDMA Tx rings. -+ * -+ * Configure EDMA Tx rings. -+ */ -+void edma_cfg_tx_rings(void) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct edma_ring_info *tx = hw_info->tx; -+ u32 i; -+ -+ /* Configure Tx desc ring. */ -+ for (i = 0; i < tx->num_rings; i++) -+ edma_cfg_tx_desc_ring_configure(&edma_ctx->tx_rings[i]); -+ -+ /* Configure TxCmpl ring. */ -+ for (i = 0; i < txcmpl->num_rings; i++) -+ edma_cfg_txcmpl_ring_configure(&edma_ctx->txcmpl_rings[i]); -+} -+ -+/** -+ * edma_cfg_tx_disable_interrupts - EDMA disable TX interrupts. -+ * -+ * Disable TX interrupt masks. -+ */ -+void edma_cfg_tx_disable_interrupts(u32 port_id) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx, reg; -+ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_MASK(txcmpl_ring->id); -+ regmap_write(regmap, reg, EDMA_MASK_INT_CLEAR); -+ } -+} -+ -+/** -+ * edma_cfg_tx_enable_interrupts - EDMA enable TX interrupts. -+ * -+ * Enable TX interrupt masks. -+ */ -+void edma_cfg_tx_enable_interrupts(u32 port_id) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx, reg; -+ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_MASK(txcmpl_ring->id); -+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_txcmpl); -+ } -+} -+ -+/** -+ * edma_cfg_tx_napi_enable - EDMA Tx NAPI. -+ * @port_id: Port ID. -+ * -+ * Enable Tx NAPI. -+ */ -+void edma_cfg_tx_napi_enable(u32 port_id) -+{ -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx; -+ -+ /* Enabling Tx napi for a interface with each queue. */ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ if (!txcmpl_ring->napi_added) -+ continue; -+ -+ napi_enable(&txcmpl_ring->napi); -+ } -+} -+ -+/** -+ * edma_cfg_tx_napi_disable - Disable Tx NAPI. -+ * @port_id: Port ID. -+ * -+ * Disable Tx NAPI. -+ */ -+void edma_cfg_tx_napi_disable(u32 port_id) -+{ -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx; -+ -+ /* Disabling Tx napi for a interface with each queue. */ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ if (!txcmpl_ring->napi_added) -+ continue; -+ -+ napi_disable(&txcmpl_ring->napi); -+ } -+} -+ -+/** -+ * edma_cfg_tx_napi_delete - Delete Tx NAPI. -+ * @port_id: Port ID. -+ * -+ * Delete Tx NAPI. -+ */ -+void edma_cfg_tx_napi_delete(u32 port_id) -+{ -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx; -+ -+ /* Disabling Tx napi for a interface with each queue. */ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ if (!txcmpl_ring->napi_added) -+ continue; -+ -+ netif_napi_del(&txcmpl_ring->napi); -+ txcmpl_ring->napi_added = false; -+ } -+} -+ -+/** -+ * edma_cfg_tx_napi_add - TX NAPI add. -+ * @netdev: Netdevice. -+ * @port_id: Port ID. -+ * -+ * TX NAPI add. -+ */ -+void edma_cfg_tx_napi_add(struct net_device *netdev, u32 port_id) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_txcmpl_ring *txcmpl_ring; -+ u32 i, ring_idx; -+ -+ /* Adding tx napi for a interface with each queue. */ -+ for_each_possible_cpu(i) { -+ ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -+ txcmpl_ring = &edma_ctx->txcmpl_rings[ring_idx]; -+ netif_napi_add_weight(netdev, &txcmpl_ring->napi, -+ edma_tx_napi_poll, hw_info->napi_budget_tx); -+ txcmpl_ring->napi_added = true; -+ netdev_dbg(netdev, "Napi added for txcmpl ring: %u\n", txcmpl_ring->id); -+ } -+ -+ netdev_dbg(netdev, "Tx NAPI budget: %d\n", hw_info->napi_budget_tx); -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.h -@@ -0,0 +1,28 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_CFG_TX__ -+#define __EDMA_CFG_TX__ -+ -+/* Tx mitigation timer's default value. */ -+#define EDMA_TX_MITIGATION_TIMER_DEF 250 -+ -+/* Tx mitigation packet count default value. */ -+#define EDMA_TX_MITIGATION_PKT_CNT_DEF 16 -+ -+void edma_cfg_tx_rings(void); -+int edma_cfg_tx_rings_alloc(void); -+void edma_cfg_tx_rings_cleanup(void); -+void edma_cfg_tx_disable_interrupts(u32 port_id); -+void edma_cfg_tx_enable_interrupts(u32 port_id); -+void edma_cfg_tx_napi_enable(u32 port_id); -+void edma_cfg_tx_napi_disable(u32 port_id); -+void edma_cfg_tx_napi_delete(u32 port_id); -+void edma_cfg_tx_napi_add(struct net_device *netdevice, u32 macid); -+void edma_cfg_tx_ring_mappings(void); -+void edma_cfg_txcmpl_mapping_fill(void); -+void edma_cfg_tx_rings_enable(u32 port_id); -+void edma_cfg_tx_rings_disable(u32 port_id); -+void edma_cfg_tx_fill_per_port_tx_map(struct net_device *netdev, u32 macid); -+#endif ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c -@@ -13,6 +13,7 @@ - - #include "edma.h" - #include "edma_cfg_rx.h" -+#include "edma_cfg_tx.h" - #include "edma_port.h" - #include "ppe_regs.h" - -@@ -35,6 +36,15 @@ static int edma_port_stats_alloc(struct - return -ENOMEM; - } - -+ port_priv->pcpu_stats.tx_stats = -+ netdev_alloc_pcpu_stats(struct edma_port_tx_stats); -+ if (!port_priv->pcpu_stats.tx_stats) { -+ netdev_err(netdev, "Per-cpu EDMA Tx stats alloc failed for %s\n", -+ netdev->name); -+ free_percpu(port_priv->pcpu_stats.rx_stats); -+ return -ENOMEM; -+ } -+ - return 0; - } - -@@ -43,6 +53,28 @@ static void edma_port_stats_free(struct - struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); - - free_percpu(port_priv->pcpu_stats.rx_stats); -+ free_percpu(port_priv->pcpu_stats.tx_stats); -+} -+ -+static void edma_port_configure(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ int port_id = port->port_id; -+ -+ edma_cfg_tx_fill_per_port_tx_map(netdev, port_id); -+ edma_cfg_tx_rings_enable(port_id); -+ edma_cfg_tx_napi_add(netdev, port_id); -+} -+ -+static void edma_port_deconfigure(struct net_device *netdev) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ int port_id = port->port_id; -+ -+ edma_cfg_tx_napi_delete(port_id); -+ edma_cfg_tx_rings_disable(port_id); - } - - static u16 __maybe_unused edma_port_select_queue(__maybe_unused struct net_device *netdev, -@@ -60,6 +92,7 @@ static int edma_port_open(struct net_dev - { - struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); - struct ppe_port *ppe_port; -+ int port_id; - - if (!port_priv) - return -EINVAL; -@@ -74,10 +107,14 @@ static int edma_port_open(struct net_dev - netdev->wanted_features |= EDMA_NETDEV_FEATURES; - - ppe_port = port_priv->ppe_port; -+ port_id = ppe_port->port_id; - - if (ppe_port->phylink) - phylink_start(ppe_port->phylink); - -+ edma_cfg_tx_napi_enable(port_id); -+ edma_cfg_tx_enable_interrupts(port_id); -+ - netif_start_queue(netdev); - - return 0; -@@ -87,13 +124,21 @@ static int edma_port_close(struct net_de - { - struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); - struct ppe_port *ppe_port; -+ int port_id; - - if (!port_priv) - return -EINVAL; - - netif_stop_queue(netdev); - -+ /* 20ms delay would provide a plenty of margin to take care of in-flight packets. */ -+ msleep(20); -+ - ppe_port = port_priv->ppe_port; -+ port_id = ppe_port->port_id; -+ -+ edma_cfg_tx_disable_interrupts(port_id); -+ edma_cfg_tx_napi_disable(port_id); - - /* Phylink close. */ - if (ppe_port->phylink) -@@ -137,6 +182,92 @@ static netdev_features_t edma_port_featu - return features; - } - -+static netdev_tx_t edma_port_xmit(struct sk_buff *skb, -+ struct net_device *dev) -+{ -+ struct edma_port_priv *port_priv = NULL; -+ struct edma_port_pcpu_stats *pcpu_stats; -+ struct edma_txdesc_ring *txdesc_ring; -+ struct edma_port_tx_stats *stats; -+ enum edma_tx_gso_status result; -+ struct sk_buff *segs = NULL; -+ u8 cpu_id; -+ u32 skbq; -+ int ret; -+ -+ if (!skb || !dev) -+ return NETDEV_TX_OK; -+ -+ port_priv = netdev_priv(dev); -+ -+ /* Select a TX ring. */ -+ skbq = (skb_get_queue_mapping(skb) & (num_possible_cpus() - 1)); -+ -+ txdesc_ring = (struct edma_txdesc_ring *)port_priv->txr_map[skbq]; -+ -+ pcpu_stats = &port_priv->pcpu_stats; -+ stats = this_cpu_ptr(pcpu_stats->tx_stats); -+ -+ /* HW does not support TSO for packets with more than or equal to -+ * 32 segments. Perform SW GSO for such packets. -+ */ -+ result = edma_tx_gso_segment(skb, dev, &segs); -+ if (likely(result == EDMA_TX_GSO_NOT_NEEDED)) { -+ /* Transmit the packet. */ -+ ret = edma_tx_ring_xmit(dev, skb, txdesc_ring, stats); -+ -+ if (unlikely(ret == EDMA_TX_FAIL_NO_DESC)) { -+ if (likely(!edma_ctx->tx_requeue_stop)) { -+ cpu_id = smp_processor_id(); -+ netdev_dbg(dev, "Stopping tx queue due to lack oftx descriptors\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->tx_queue_stopped[cpu_id]; -+ u64_stats_update_end(&stats->syncp); -+ netif_tx_stop_queue(netdev_get_tx_queue(dev, skbq)); -+ return NETDEV_TX_BUSY; -+ } -+ } -+ -+ if (unlikely(ret != EDMA_TX_OK)) { -+ dev_kfree_skb_any(skb); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->tx_drops; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ return NETDEV_TX_OK; -+ } else if (unlikely(result == EDMA_TX_GSO_FAIL)) { -+ netdev_dbg(dev, "%p: SW GSO failed for segment size: %d\n", -+ skb, skb_shinfo(skb)->gso_segs); -+ dev_kfree_skb_any(skb); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->tx_gso_drop_pkts; -+ u64_stats_update_end(&stats->syncp); -+ return NETDEV_TX_OK; -+ } -+ -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->tx_gso_pkts; -+ u64_stats_update_end(&stats->syncp); -+ -+ dev_kfree_skb_any(skb); -+ while (segs) { -+ skb = segs; -+ segs = segs->next; -+ -+ /* Transmit the packet. */ -+ ret = edma_tx_ring_xmit(dev, skb, txdesc_ring, stats); -+ if (unlikely(ret != EDMA_TX_OK)) { -+ dev_kfree_skb_any(skb); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->tx_drops; -+ u64_stats_update_end(&stats->syncp); -+ } -+ } -+ -+ return NETDEV_TX_OK; -+} -+ - static void edma_port_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *stats) - { -@@ -179,6 +310,7 @@ static int edma_port_set_mac_address(str - static const struct net_device_ops edma_port_netdev_ops = { - .ndo_open = edma_port_open, - .ndo_stop = edma_port_close, -+ .ndo_start_xmit = edma_port_xmit, - .ndo_get_stats64 = edma_port_get_stats64, - .ndo_set_mac_address = edma_port_set_mac_address, - .ndo_validate_addr = eth_validate_addr, -@@ -199,6 +331,7 @@ void edma_port_destroy(struct ppe_port * - int port_id = port->port_id; - struct net_device *netdev = edma_ctx->netdev_arr[port_id - 1]; - -+ edma_port_deconfigure(netdev); - edma_port_stats_free(netdev); - unregister_netdev(netdev); - free_netdev(netdev); -@@ -276,6 +409,8 @@ int edma_port_setup(struct ppe_port *por - */ - edma_ctx->netdev_arr[port_id - 1] = netdev; - -+ edma_port_configure(netdev); -+ - /* Setup phylink. */ - ret = ppe_port_phylink_setup(port, netdev); - if (ret) { -@@ -298,6 +433,7 @@ int edma_port_setup(struct ppe_port *por - register_netdev_fail: - ppe_port_phylink_destroy(port); - port_phylink_setup_fail: -+ edma_port_deconfigure(netdev); - edma_ctx->netdev_arr[port_id - 1] = NULL; - edma_port_stats_free(netdev); - stats_alloc_fail: ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.h -@@ -7,6 +7,8 @@ - - #include "ppe_port.h" - -+#define EDMA_PORT_MAX_CORE 4 -+ - #define EDMA_NETDEV_FEATURES (NETIF_F_FRAGLIST \ - | NETIF_F_SG \ - | NETIF_F_RXCSUM \ -@@ -35,11 +37,43 @@ struct edma_port_rx_stats { - }; - - /** -+ * struct edma_port_tx_stats - EDMA TX port per CPU stats for the port. -+ * @tx_pkts: Number of Tx packets -+ * @tx_bytes: Number of Tx bytes -+ * @tx_drops: Number of Tx drops -+ * @tx_nr_frag_pkts: Number of Tx nr_frag packets -+ * @tx_fraglist_pkts: Number of Tx fraglist packets -+ * @tx_fraglist_with_nr_frags_pkts: Number of Tx packets with fraglist and nr_frags -+ * @tx_tso_pkts: Number of Tx TSO packets -+ * @tx_tso_drop_pkts: Number of Tx TSO drop packets -+ * @tx_gso_pkts: Number of Tx GSO packets -+ * @tx_gso_drop_pkts: Number of Tx GSO drop packets -+ * @tx_queue_stopped: Number of Tx queue stopped packets -+ * @syncp: Synchronization pointer -+ */ -+struct edma_port_tx_stats { -+ u64 tx_pkts; -+ u64 tx_bytes; -+ u64 tx_drops; -+ u64 tx_nr_frag_pkts; -+ u64 tx_fraglist_pkts; -+ u64 tx_fraglist_with_nr_frags_pkts; -+ u64 tx_tso_pkts; -+ u64 tx_tso_drop_pkts; -+ u64 tx_gso_pkts; -+ u64 tx_gso_drop_pkts; -+ u64 tx_queue_stopped[EDMA_PORT_MAX_CORE]; -+ struct u64_stats_sync syncp; -+}; -+ -+/** - * struct edma_port_pcpu_stats - EDMA per cpu stats data structure for the port. - * @rx_stats: Per CPU Rx statistics -+ * @tx_stats: Per CPU Tx statistics - */ - struct edma_port_pcpu_stats { - struct edma_port_rx_stats __percpu *rx_stats; -+ struct edma_port_tx_stats __percpu *tx_stats; - }; - - /** -@@ -54,6 +88,7 @@ struct edma_port_priv { - struct ppe_port *ppe_port; - struct net_device *netdev; - struct edma_port_pcpu_stats pcpu_stats; -+ struct edma_txdesc_ring *txr_map[EDMA_PORT_MAX_CORE]; - unsigned long flags; - }; - ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_tx.c -@@ -0,0 +1,808 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* Provide APIs to alloc Tx Buffers, fill the Tx descriptors and transmit -+ * Scatter Gather and linear packets, Tx complete to free the skb after transmit. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_cfg_tx.h" -+#include "edma_port.h" -+#include "ppe.h" -+#include "ppe_regs.h" -+ -+static u32 edma_tx_num_descs_for_sg(struct sk_buff *skb) -+{ -+ u32 nr_frags_first = 0, num_tx_desc_needed = 0; -+ -+ /* Check if we have enough Tx descriptors for SG. */ -+ if (unlikely(skb_shinfo(skb)->nr_frags)) { -+ nr_frags_first = skb_shinfo(skb)->nr_frags; -+ WARN_ON_ONCE(nr_frags_first > MAX_SKB_FRAGS); -+ num_tx_desc_needed += nr_frags_first; -+ } -+ -+ /* Walk through fraglist skbs making a note of nr_frags -+ * One Tx desc for fraglist skb. Fraglist skb may have -+ * further nr_frags. -+ */ -+ if (unlikely(skb_has_frag_list(skb))) { -+ struct sk_buff *iter_skb; -+ -+ skb_walk_frags(skb, iter_skb) { -+ u32 nr_frags = skb_shinfo(iter_skb)->nr_frags; -+ -+ WARN_ON_ONCE(nr_frags > MAX_SKB_FRAGS); -+ num_tx_desc_needed += (1 + nr_frags); -+ } -+ } -+ -+ return (num_tx_desc_needed + 1); -+} -+ -+/** -+ * edma_tx_gso_segment - Tx GSO. -+ * @skb: Socket Buffer. -+ * @netdev: Netdevice. -+ * @segs: SKB segments from GSO. -+ * -+ * Format skbs into GSOs. -+ * -+ * Return 1 on success, error code on failure. -+ */ -+enum edma_tx_gso_status edma_tx_gso_segment(struct sk_buff *skb, -+ struct net_device *netdev, struct sk_buff **segs) -+{ -+ u32 num_tx_desc_needed; -+ -+ /* Check is skb is non-linear to proceed. */ -+ if (likely(!skb_is_nonlinear(skb))) -+ return EDMA_TX_GSO_NOT_NEEDED; -+ -+ /* Check if TSO is enabled. If so, return as skb doesn't -+ * need to be segmented by linux. -+ */ -+ if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { -+ num_tx_desc_needed = edma_tx_num_descs_for_sg(skb); -+ if (likely(num_tx_desc_needed <= EDMA_TX_TSO_SEG_MAX)) -+ return EDMA_TX_GSO_NOT_NEEDED; -+ } -+ -+ /* GSO segmentation of the skb into multiple segments. */ -+ *segs = skb_gso_segment(skb, netdev->features -+ & ~(NETIF_F_TSO | NETIF_F_TSO6)); -+ -+ /* Check for error in GSO segmentation. */ -+ if (IS_ERR_OR_NULL(*segs)) { -+ netdev_info(netdev, "Tx gso fail\n"); -+ return EDMA_TX_GSO_FAIL; -+ } -+ -+ return EDMA_TX_GSO_SUCCEED; -+} -+ -+/** -+ * edma_tx_complete - Reap Tx completion descriptors. -+ * @work_to_do: Work to do. -+ * @txcmpl_ring: Tx Completion ring. -+ * -+ * Reap Tx completion descriptors of the transmitted -+ * packets and free the corresponding SKBs. -+ * -+ * Return the number descriptors for which Tx complete is done. -+ */ -+u32 edma_tx_complete(u32 work_to_do, struct edma_txcmpl_ring *txcmpl_ring) -+{ -+ struct edma_txcmpl_stats *txcmpl_stats = &txcmpl_ring->txcmpl_stats; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 cons_idx, end_idx, data, cpu_id; -+ struct device *dev = ppe_dev->dev; -+ u32 avail, count, txcmpl_errors; -+ struct edma_txcmpl_desc *txcmpl; -+ u32 prod_idx = 0, more_bit = 0; -+ struct netdev_queue *nq; -+ struct sk_buff *skb; -+ u32 reg; -+ -+ cons_idx = txcmpl_ring->cons_idx; -+ -+ if (likely(txcmpl_ring->avail_pkt >= work_to_do)) { -+ avail = work_to_do; -+ } else { -+ /* Get TXCMPL ring producer index. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_PROD_IDX(txcmpl_ring->id); -+ regmap_read(regmap, reg, &data); -+ prod_idx = data & EDMA_TXCMPL_PROD_IDX_MASK; -+ -+ avail = EDMA_DESC_AVAIL_COUNT(prod_idx, cons_idx, EDMA_TX_RING_SIZE); -+ txcmpl_ring->avail_pkt = avail; -+ -+ if (unlikely(!avail)) { -+ dev_dbg(dev, "No available descriptors are pending for %d txcmpl ring\n", -+ txcmpl_ring->id); -+ u64_stats_update_begin(&txcmpl_stats->syncp); -+ ++txcmpl_stats->no_pending_desc; -+ u64_stats_update_end(&txcmpl_stats->syncp); -+ return 0; -+ } -+ -+ avail = min(avail, work_to_do); -+ } -+ -+ count = avail; -+ -+ end_idx = (cons_idx + avail) & EDMA_TX_RING_SIZE_MASK; -+ txcmpl = EDMA_TXCMPL_DESC(txcmpl_ring, cons_idx); -+ -+ /* Instead of freeing the skb, it might be better to save and use -+ * for Rxfill. -+ */ -+ while (likely(avail--)) { -+ /* The last descriptor holds the SKB pointer for scattered frames. -+ * So skip the descriptors with more bit set. -+ */ -+ more_bit = EDMA_TXCMPL_MORE_BIT_GET(txcmpl); -+ if (unlikely(more_bit)) { -+ u64_stats_update_begin(&txcmpl_stats->syncp); -+ ++txcmpl_stats->desc_with_more_bit; -+ u64_stats_update_end(&txcmpl_stats->syncp); -+ cons_idx = ((cons_idx + 1) & EDMA_TX_RING_SIZE_MASK); -+ txcmpl = EDMA_TXCMPL_DESC(txcmpl_ring, cons_idx); -+ continue; -+ } -+ -+ /* Find and free the skb for Tx completion. */ -+ skb = (struct sk_buff *)EDMA_TXCMPL_OPAQUE_GET(txcmpl); -+ if (unlikely(!skb)) { -+ if (net_ratelimit()) -+ dev_warn(dev, "Invalid cons_idx:%u prod_idx:%u word2:%x word3:%x\n", -+ cons_idx, prod_idx, txcmpl->word2, txcmpl->word3); -+ -+ u64_stats_update_begin(&txcmpl_stats->syncp); -+ ++txcmpl_stats->invalid_buffer; -+ u64_stats_update_end(&txcmpl_stats->syncp); -+ } else { -+ dev_dbg(dev, "TXCMPL: skb:%p, skb->len %d, skb->data_len %d, cons_idx:%d prod_idx:%d word2:0x%x word3:0x%x\n", -+ skb, skb->len, skb->data_len, cons_idx, prod_idx, -+ txcmpl->word2, txcmpl->word3); -+ -+ txcmpl_errors = EDMA_TXCOMP_RING_ERROR_GET(txcmpl->word3); -+ if (unlikely(txcmpl_errors)) { -+ if (net_ratelimit()) -+ dev_err(dev, "Error 0x%0x observed in tx complete %d ring\n", -+ txcmpl_errors, txcmpl_ring->id); -+ -+ u64_stats_update_begin(&txcmpl_stats->syncp); -+ ++txcmpl_stats->errors; -+ u64_stats_update_end(&txcmpl_stats->syncp); -+ } -+ -+ /* Retrieve pool id for unmapping. -+ * 0 for linear skb and (pool id - 1) represents nr_frag index. -+ */ -+ if (!EDMA_TXCOMP_POOL_ID_GET(txcmpl)) { -+ dma_unmap_single(dev, virt_to_phys(skb->data), -+ skb->len, DMA_TO_DEVICE); -+ } else { -+ u8 frag_index = (EDMA_TXCOMP_POOL_ID_GET(txcmpl) - 1); -+ skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_index]; -+ -+ dma_unmap_page(dev, virt_to_phys(frag), -+ PAGE_SIZE, DMA_TO_DEVICE); -+ } -+ -+ dev_kfree_skb(skb); -+ } -+ -+ cons_idx = ((cons_idx + 1) & EDMA_TX_RING_SIZE_MASK); -+ txcmpl = EDMA_TXCMPL_DESC(txcmpl_ring, cons_idx); -+ } -+ -+ txcmpl_ring->cons_idx = cons_idx; -+ txcmpl_ring->avail_pkt -= count; -+ -+ dev_dbg(dev, "TXCMPL:%u count:%u prod_idx:%u cons_idx:%u\n", -+ txcmpl_ring->id, count, prod_idx, cons_idx); -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_CONS_IDX(txcmpl_ring->id); -+ regmap_write(regmap, reg, cons_idx); -+ -+ /* If tx_requeue_stop disabled (tx_requeue_stop = 0) -+ * Fetch the tx queue of interface and check if it is stopped. -+ * if queue is stopped and interface is up, wake up this queue. -+ */ -+ if (unlikely(!edma_ctx->tx_requeue_stop)) { -+ cpu_id = smp_processor_id(); -+ nq = netdev_get_tx_queue(txcmpl_ring->napi.dev, cpu_id); -+ if (unlikely(netif_tx_queue_stopped(nq)) && -+ netif_carrier_ok(txcmpl_ring->napi.dev)) { -+ dev_dbg(dev, "Waking queue number %d, for interface %s\n", -+ cpu_id, txcmpl_ring->napi.dev->name); -+ __netif_tx_lock(nq, cpu_id); -+ netif_tx_wake_queue(nq); -+ __netif_tx_unlock(nq); -+ } -+ } -+ -+ return count; -+} -+ -+/** -+ * edma_tx_napi_poll - EDMA TX NAPI handler. -+ * @napi: NAPI structure. -+ * @budget: Tx NAPI Budget. -+ * -+ * EDMA TX NAPI handler. -+ */ -+int edma_tx_napi_poll(struct napi_struct *napi, int budget) -+{ -+ struct edma_txcmpl_ring *txcmpl_ring = (struct edma_txcmpl_ring *)napi; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 txcmpl_intr_status; -+ int work_done = 0; -+ u32 data, reg; -+ -+ do { -+ work_done += edma_tx_complete(budget - work_done, txcmpl_ring); -+ if (work_done >= budget) -+ return work_done; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_STAT(txcmpl_ring->id); -+ regmap_read(regmap, reg, &data); -+ txcmpl_intr_status = data & EDMA_TXCMPL_RING_INT_STATUS_MASK; -+ } while (txcmpl_intr_status); -+ -+ /* No more packets to process. Finish NAPI processing. */ -+ napi_complete(napi); -+ -+ /* Set TXCMPL ring interrupt mask. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_MASK(txcmpl_ring->id); -+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_txcmpl); -+ -+ return work_done; -+} -+ -+/** -+ * edma_tx_handle_irq - Tx IRQ Handler. -+ * @irq: Interrupt request. -+ * @ctx: Context. -+ * -+ * Process TX IRQ and schedule NAPI. -+ * -+ * Return IRQ handler code. -+ */ -+irqreturn_t edma_tx_handle_irq(int irq, void *ctx) -+{ -+ struct edma_txcmpl_ring *txcmpl_ring = (struct edma_txcmpl_ring *)ctx; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 reg; -+ -+ pr_debug("irq: irq=%d txcmpl_ring_id=%u\n", irq, txcmpl_ring->id); -+ if (likely(napi_schedule_prep(&txcmpl_ring->napi))) { -+ /* Disable TxCmpl intr. */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TX_INT_MASK(txcmpl_ring->id); -+ regmap_write(regmap, reg, EDMA_MASK_INT_DISABLE); -+ __napi_schedule(&txcmpl_ring->napi); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void edma_tx_dma_unmap_frags(struct sk_buff *skb, u32 nr_frags) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ u32 buf_len = 0; -+ u8 i = 0; -+ -+ for (i = 0; i < skb_shinfo(skb)->nr_frags - nr_frags; i++) { -+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; -+ -+ /* DMA mapping was not done for zero size segments. */ -+ buf_len = skb_frag_size(frag); -+ if (unlikely(buf_len == 0)) -+ continue; -+ -+ dma_unmap_page(dev, virt_to_phys(frag), PAGE_SIZE, -+ DMA_TO_DEVICE); -+ } -+} -+ -+static u32 edma_tx_skb_nr_frags(struct edma_txdesc_ring *txdesc_ring, -+ struct edma_txdesc_pri **txdesc, struct sk_buff *skb, -+ u32 *hw_next_to_use, u32 *invalid_frag) -+{ -+ u32 nr_frags = 0, buf_len = 0, num_descs = 0, start_idx = 0, end_idx = 0; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ u32 start_hw_next_to_use = *hw_next_to_use; -+ struct edma_txdesc_pri *txd = *txdesc; -+ struct device *dev = ppe_dev->dev; -+ u8 i = 0; -+ -+ /* Hold onto the index mapped to *txdesc. -+ * This will be the index previous to that of current *hw_next_to_use. -+ */ -+ start_idx = (((*hw_next_to_use) + EDMA_TX_RING_SIZE_MASK) -+ & EDMA_TX_RING_SIZE_MASK); -+ -+ /* Handle if the skb has nr_frags. */ -+ nr_frags = skb_shinfo(skb)->nr_frags; -+ num_descs = nr_frags; -+ i = 0; -+ -+ while (nr_frags--) { -+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; -+ dma_addr_t buff_addr; -+ -+ buf_len = skb_frag_size(frag); -+ -+ /* Zero size segment can lead EDMA HW to hang so, we don't want to -+ * process them. Zero size segment can happen during TSO operation -+ * if there is nothing but header in the primary segment. -+ */ -+ if (unlikely(buf_len == 0)) { -+ num_descs--; -+ i++; -+ continue; -+ } -+ -+ /* Setting the MORE bit on the previous Tx descriptor. -+ * Note: We will flush this descriptor as well later. -+ */ -+ EDMA_TXDESC_MORE_BIT_SET(txd, 1); -+ EDMA_TXDESC_ENDIAN_SET(txd); -+ -+ txd = EDMA_TXDESC_PRI_DESC(txdesc_ring, *hw_next_to_use); -+ memset(txd, 0, sizeof(struct edma_txdesc_pri)); -+ buff_addr = skb_frag_dma_map(dev, frag, 0, buf_len, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, buff_addr)) { -+ dev_dbg(dev, "Unable to dma first descriptor for nr_frags tx\n"); -+ *hw_next_to_use = start_hw_next_to_use; -+ *invalid_frag = nr_frags; -+ return 0; -+ } -+ -+ EDMA_TXDESC_BUFFER_ADDR_SET(txd, buff_addr); -+ EDMA_TXDESC_DATA_LEN_SET(txd, buf_len); -+ EDMA_TXDESC_POOL_ID_SET(txd, (i + 1)); -+ -+ *hw_next_to_use = ((*hw_next_to_use + 1) & EDMA_TX_RING_SIZE_MASK); -+ i++; -+ } -+ -+ EDMA_TXDESC_ENDIAN_SET(txd); -+ -+ /* This will be the index previous to that of current *hw_next_to_use. */ -+ end_idx = (((*hw_next_to_use) + EDMA_TX_RING_SIZE_MASK) & EDMA_TX_RING_SIZE_MASK); -+ -+ *txdesc = txd; -+ -+ return num_descs; -+} -+ -+static void edma_tx_fill_pp_desc(struct edma_port_priv *port_priv, -+ struct edma_txdesc_pri *txd, struct sk_buff *skb, -+ struct edma_port_tx_stats *stats) -+{ -+ struct ppe_port *port = port_priv->ppe_port; -+ int port_id = port->port_id; -+ -+ /* Offload L3/L4 checksum computation. */ -+ if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { -+ EDMA_TXDESC_ADV_OFFLOAD_SET(txd); -+ EDMA_TXDESC_IP_CSUM_SET(txd); -+ EDMA_TXDESC_L4_CSUM_SET(txd); -+ } -+ -+ /* Check if the packet needs TSO -+ * This will be mostly true for SG packets. -+ */ -+ if (unlikely(skb_is_gso(skb))) { -+ if ((skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) || -+ (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)) { -+ u32 mss = skb_shinfo(skb)->gso_size; -+ -+ /* If MSS<256, HW will do TSO using MSS=256, -+ * if MSS>10K, HW will do TSO using MSS=10K, -+ * else HW will report error 0x200000 in Tx Cmpl. -+ */ -+ if (mss < EDMA_TX_TSO_MSS_MIN) -+ mss = EDMA_TX_TSO_MSS_MIN; -+ else if (mss > EDMA_TX_TSO_MSS_MAX) -+ mss = EDMA_TX_TSO_MSS_MAX; -+ -+ EDMA_TXDESC_TSO_ENABLE_SET(txd, 1); -+ EDMA_TXDESC_MSS_SET(txd, mss); -+ -+ /* Update tso stats. */ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_tso_pkts++; -+ u64_stats_update_end(&stats->syncp); -+ } -+ } -+ -+ /* Set destination information in the descriptor. */ -+ EDMA_TXDESC_SERVICE_CODE_SET(txd, PPE_EDMA_SC_BYPASS_ID); -+ EDMA_DST_INFO_SET(txd, port_id); -+} -+ -+static struct edma_txdesc_pri *edma_tx_skb_first_desc(struct edma_port_priv *port_priv, -+ struct edma_txdesc_ring *txdesc_ring, -+ struct sk_buff *skb, u32 *hw_next_to_use, -+ struct edma_port_tx_stats *stats) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct edma_txdesc_pri *txd = NULL; -+ struct device *dev = ppe_dev->dev; -+ dma_addr_t buff_addr; -+ u32 buf_len = 0; -+ -+ /* Get the packet length. */ -+ buf_len = skb_headlen(skb); -+ txd = EDMA_TXDESC_PRI_DESC(txdesc_ring, *hw_next_to_use); -+ memset(txd, 0, sizeof(struct edma_txdesc_pri)); -+ -+ /* Set the data pointer as the buffer address in the descriptor. */ -+ buff_addr = dma_map_single(dev, skb->data, buf_len, DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, buff_addr)) { -+ dev_dbg(dev, "Unable to dma first descriptor for tx\n"); -+ return NULL; -+ } -+ -+ EDMA_TXDESC_BUFFER_ADDR_SET(txd, buff_addr); -+ EDMA_TXDESC_POOL_ID_SET(txd, 0); -+ edma_tx_fill_pp_desc(port_priv, txd, skb, stats); -+ -+ /* Set packet length in the descriptor. */ -+ EDMA_TXDESC_DATA_LEN_SET(txd, buf_len); -+ *hw_next_to_use = (*hw_next_to_use + 1) & EDMA_TX_RING_SIZE_MASK; -+ -+ return txd; -+} -+ -+static void edma_tx_handle_dma_err(struct sk_buff *skb, u32 num_sg_frag_list) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct device *dev = ppe_dev->dev; -+ struct sk_buff *iter_skb = NULL; -+ u32 cnt_sg_frag_list = 0; -+ -+ /* Walk through all fraglist skbs. */ -+ skb_walk_frags(skb, iter_skb) { -+ if (skb_headlen(iter_skb)) { -+ dma_unmap_single(dev, virt_to_phys(iter_skb->data), -+ skb_headlen(iter_skb), DMA_TO_DEVICE); -+ cnt_sg_frag_list += 1; -+ } -+ -+ if (cnt_sg_frag_list == num_sg_frag_list) -+ return; -+ -+ /* skb fraglist skb had nr_frags, unmap that memory. */ -+ u32 nr_frags = skb_shinfo(iter_skb)->nr_frags; -+ -+ if (nr_frags == 0) -+ continue; -+ -+ for (int i = 0; i < nr_frags; i++) { -+ skb_frag_t *frag = &skb_shinfo(iter_skb)->frags[i]; -+ -+ /* DMA mapping was not done for zero size segments. */ -+ if (unlikely(skb_frag_size(frag) == 0)) -+ continue; -+ -+ dma_unmap_page(dev, virt_to_phys(frag), -+ PAGE_SIZE, DMA_TO_DEVICE); -+ cnt_sg_frag_list += 1; -+ if (cnt_sg_frag_list == num_sg_frag_list) -+ return; -+ } -+ } -+} -+ -+static u32 edma_tx_skb_sg_fill_desc(struct edma_txdesc_ring *txdesc_ring, -+ struct edma_txdesc_pri **txdesc, -+ struct sk_buff *skb, u32 *hw_next_to_use, -+ struct edma_port_tx_stats *stats) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ u32 start_hw_next_to_use = 0, invalid_frag = 0; -+ struct edma_txdesc_pri *txd = *txdesc; -+ struct device *dev = ppe_dev->dev; -+ struct sk_buff *iter_skb = NULL; -+ u32 buf_len = 0, num_descs = 0; -+ u32 num_sg_frag_list = 0; -+ -+ /* Head skb processed already. */ -+ num_descs++; -+ -+ if (unlikely(skb_has_frag_list(skb))) { -+ struct edma_txdesc_pri *start_desc = NULL; -+ u32 start_idx = 0, end_idx = 0; -+ -+ /* Hold onto the index mapped to txd. -+ * This will be the index previous to that of current *hw_next_to_use. -+ */ -+ start_idx = (((*hw_next_to_use) + EDMA_TX_RING_SIZE_MASK) -+ & EDMA_TX_RING_SIZE_MASK); -+ start_desc = txd; -+ start_hw_next_to_use = *hw_next_to_use; -+ -+ /* Walk through all fraglist skbs. */ -+ skb_walk_frags(skb, iter_skb) { -+ dma_addr_t buff_addr; -+ u32 num_nr_frag = 0; -+ -+ /* This case could happen during the packet decapsulation. -+ * All header content might be removed. -+ */ -+ buf_len = skb_headlen(iter_skb); -+ if (unlikely(buf_len == 0)) -+ goto skip_primary; -+ -+ /* We make sure to flush this descriptor later. */ -+ EDMA_TXDESC_MORE_BIT_SET(txd, 1); -+ EDMA_TXDESC_ENDIAN_SET(txd); -+ -+ txd = EDMA_TXDESC_PRI_DESC(txdesc_ring, *hw_next_to_use); -+ memset(txd, 0, sizeof(struct edma_txdesc_pri)); -+ buff_addr = dma_map_single(dev, iter_skb->data, -+ buf_len, DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, buff_addr)) { -+ dev_dbg(dev, "Unable to dma for fraglist\n"); -+ goto dma_err; -+ } -+ -+ EDMA_TXDESC_BUFFER_ADDR_SET(txd, buff_addr); -+ EDMA_TXDESC_DATA_LEN_SET(txd, buf_len); -+ EDMA_TXDESC_POOL_ID_SET(txd, 0); -+ -+ *hw_next_to_use = (*hw_next_to_use + 1) & EDMA_TX_RING_SIZE_MASK; -+ num_descs += 1; -+ num_sg_frag_list += 1; -+ -+ /* skb fraglist skb can have nr_frags. */ -+skip_primary: -+ if (unlikely(skb_shinfo(iter_skb)->nr_frags)) { -+ num_nr_frag = edma_tx_skb_nr_frags(txdesc_ring, &txd, -+ iter_skb, hw_next_to_use, -+ &invalid_frag); -+ if (unlikely(!num_nr_frag)) { -+ dev_dbg(dev, "No descriptor available for ring %d\n", -+ txdesc_ring->id); -+ edma_tx_dma_unmap_frags(iter_skb, invalid_frag); -+ goto dma_err; -+ } -+ -+ num_descs += num_nr_frag; -+ num_sg_frag_list += num_nr_frag; -+ -+ /* Update fraglist with nr_frag stats. */ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_fraglist_with_nr_frags_pkts++; -+ u64_stats_update_end(&stats->syncp); -+ } -+ } -+ -+ EDMA_TXDESC_ENDIAN_SET(txd); -+ -+ /* This will be the index previous to -+ * that of current *hw_next_to_use. -+ */ -+ end_idx = (((*hw_next_to_use) + EDMA_TX_RING_SIZE_MASK) & -+ EDMA_TX_RING_SIZE_MASK); -+ -+ /* Update frag_list stats. */ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_fraglist_pkts++; -+ u64_stats_update_end(&stats->syncp); -+ } else { -+ /* Process skb with nr_frags. */ -+ num_descs += edma_tx_skb_nr_frags(txdesc_ring, &txd, skb, -+ hw_next_to_use, &invalid_frag); -+ if (unlikely(!num_descs)) { -+ dev_dbg(dev, "No descriptor available for ring %d\n", txdesc_ring->id); -+ edma_tx_dma_unmap_frags(skb, invalid_frag); -+ *txdesc = NULL; -+ return num_descs; -+ } -+ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_nr_frag_pkts++; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ dev_dbg(dev, "skb:%p num_descs_filled: %u, nr_frags %u, frag_list fragments %u\n", -+ skb, num_descs, skb_shinfo(skb)->nr_frags, num_sg_frag_list); -+ -+ *txdesc = txd; -+ -+ return num_descs; -+ -+dma_err: -+ if (!num_sg_frag_list) -+ goto reset_state; -+ -+ edma_tx_handle_dma_err(skb, num_sg_frag_list); -+ -+reset_state: -+ *hw_next_to_use = start_hw_next_to_use; -+ *txdesc = NULL; -+ -+ return 0; -+} -+ -+static u32 edma_tx_avail_desc(struct edma_txdesc_ring *txdesc_ring, -+ u32 hw_next_to_use) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ u32 data = 0, avail = 0, hw_next_to_clean = 0; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_CONS_IDX(txdesc_ring->id); -+ regmap_read(regmap, reg, &data); -+ hw_next_to_clean = data & EDMA_TXDESC_CONS_IDX_MASK; -+ -+ avail = EDMA_DESC_AVAIL_COUNT(hw_next_to_clean - 1, -+ hw_next_to_use, EDMA_TX_RING_SIZE); -+ -+ return avail; -+} -+ -+/** -+ * edma_tx_ring_xmit - Transmit a packet. -+ * @netdev: Netdevice. -+ * @skb: Socket Buffer. -+ * @txdesc_ring: Tx Descriptor ring. -+ * @stats: EDMA Tx Statistics. -+ * -+ * Check for available descriptors, fill the descriptors -+ * and transmit both linear and non linear packets. -+ * -+ * Return 0 on success, negative error code on failure. -+ */ -+enum edma_tx_status edma_tx_ring_xmit(struct net_device *netdev, -+ struct sk_buff *skb, struct edma_txdesc_ring *txdesc_ring, -+ struct edma_port_tx_stats *stats) -+{ -+ struct edma_txdesc_stats *txdesc_stats = &txdesc_ring->txdesc_stats; -+ struct edma_port_priv *port_priv = netdev_priv(netdev); -+ u32 num_tx_desc_needed = 0, num_desc_filled = 0; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct ppe_port *port = port_priv->ppe_port; -+ struct regmap *regmap = ppe_dev->regmap; -+ struct edma_txdesc_pri *txdesc = NULL; -+ struct device *dev = ppe_dev->dev; -+ int port_id = port->port_id; -+ u32 hw_next_to_use = 0; -+ u32 reg; -+ -+ hw_next_to_use = txdesc_ring->prod_idx; -+ -+ if (unlikely(!(txdesc_ring->avail_desc))) { -+ txdesc_ring->avail_desc = edma_tx_avail_desc(txdesc_ring, -+ hw_next_to_use); -+ if (unlikely(!txdesc_ring->avail_desc)) { -+ netdev_dbg(netdev, "No available descriptors are present at %d ring\n", -+ txdesc_ring->id); -+ -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->no_desc_avail; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ return EDMA_TX_FAIL_NO_DESC; -+ } -+ } -+ -+ /* Process head skb for linear skb. -+ * Process head skb + nr_frags + fraglist for non linear skb. -+ */ -+ if (likely(!skb_is_nonlinear(skb))) { -+ txdesc = edma_tx_skb_first_desc(port_priv, txdesc_ring, skb, -+ &hw_next_to_use, stats); -+ if (unlikely(!txdesc)) { -+ netdev_dbg(netdev, "No descriptor available for ring %d\n", -+ txdesc_ring->id); -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->no_desc_avail; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ return EDMA_TX_FAIL_NO_DESC; -+ } -+ -+ EDMA_TXDESC_ENDIAN_SET(txdesc); -+ num_desc_filled++; -+ } else { -+ num_tx_desc_needed = edma_tx_num_descs_for_sg(skb); -+ -+ /* HW does not support TSO for packets with more than 32 segments. -+ * HW hangs up if it sees more than 32 segments. Kernel Perform GSO -+ * for such packets with netdev gso_max_segs set to 32. -+ */ -+ if (unlikely(num_tx_desc_needed > EDMA_TX_TSO_SEG_MAX)) { -+ netdev_dbg(netdev, "Number of segments %u more than %u for %d ring\n", -+ num_tx_desc_needed, EDMA_TX_TSO_SEG_MAX, txdesc_ring->id); -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->tso_max_seg_exceed; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_tso_drop_pkts++; -+ u64_stats_update_end(&stats->syncp); -+ -+ return EDMA_TX_FAIL; -+ } -+ -+ if (unlikely(num_tx_desc_needed > txdesc_ring->avail_desc)) { -+ txdesc_ring->avail_desc = edma_tx_avail_desc(txdesc_ring, -+ hw_next_to_use); -+ if (num_tx_desc_needed > txdesc_ring->avail_desc) { -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->no_desc_avail; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ netdev_dbg(netdev, "Not enough available descriptors are present at %d ring for SG packet. Needed %d, currently available %d\n", -+ txdesc_ring->id, num_tx_desc_needed, -+ txdesc_ring->avail_desc); -+ return EDMA_TX_FAIL_NO_DESC; -+ } -+ } -+ -+ txdesc = edma_tx_skb_first_desc(port_priv, txdesc_ring, skb, -+ &hw_next_to_use, stats); -+ if (unlikely(!txdesc)) { -+ netdev_dbg(netdev, "No non-linear descriptor available for ring %d\n", -+ txdesc_ring->id); -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->no_desc_avail; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ return EDMA_TX_FAIL_NO_DESC; -+ } -+ -+ num_desc_filled = edma_tx_skb_sg_fill_desc(txdesc_ring, -+ &txdesc, skb, &hw_next_to_use, stats); -+ if (unlikely(!txdesc)) { -+ netdev_dbg(netdev, "No descriptor available for ring %d\n", -+ txdesc_ring->id); -+ dma_unmap_single(dev, virt_to_phys(skb->data), -+ skb->len, DMA_TO_DEVICE); -+ u64_stats_update_begin(&txdesc_stats->syncp); -+ ++txdesc_stats->no_desc_avail; -+ u64_stats_update_end(&txdesc_stats->syncp); -+ return EDMA_TX_FAIL_NO_DESC; -+ } -+ } -+ -+ /* Set the skb pointer to the descriptor's opaque field/s -+ * on the last descriptor of the packet/SG packet. -+ */ -+ EDMA_TXDESC_OPAQUE_SET(txdesc, skb); -+ -+ /* Update producer index. */ -+ txdesc_ring->prod_idx = hw_next_to_use & EDMA_TXDESC_PROD_IDX_MASK; -+ txdesc_ring->avail_desc -= num_desc_filled; -+ -+ netdev_dbg(netdev, "%s: skb:%p tx_ring:%u proto:0x%x skb->len:%d\n port:%u prod_idx:%u ip_summed:0x%x\n", -+ netdev->name, skb, txdesc_ring->id, ntohs(skb->protocol), -+ skb->len, port_id, hw_next_to_use, skb->ip_summed); -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_TXDESC_PROD_IDX(txdesc_ring->id); -+ regmap_write(regmap, reg, txdesc_ring->prod_idx); -+ -+ u64_stats_update_begin(&stats->syncp); -+ stats->tx_pkts++; -+ stats->tx_bytes += skb->len; -+ u64_stats_update_end(&stats->syncp); -+ -+ return EDMA_TX_OK; -+} ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_tx.h -@@ -0,0 +1,302 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef __EDMA_TX__ -+#define __EDMA_TX__ -+ -+#include "edma_port.h" -+ -+#define EDMA_GET_DESC(R, i, type) (&(((type *)((R)->desc))[(i)])) -+#define EDMA_GET_PDESC(R, i, type) (&(((type *)((R)->pdesc))[(i)])) -+#define EDMA_GET_SDESC(R, i, type) (&(((type *)((R)->sdesc))[(i)])) -+#define EDMA_TXCMPL_DESC(R, i) EDMA_GET_DESC(R, i, \ -+ struct edma_txcmpl_desc) -+#define EDMA_TXDESC_PRI_DESC(R, i) EDMA_GET_PDESC(R, i, \ -+ struct edma_txdesc_pri) -+#define EDMA_TXDESC_SEC_DESC(R, i) EDMA_GET_SDESC(R, i, \ -+ struct edma_txdesc_sec) -+ -+#define EDMA_DESC_AVAIL_COUNT(head, tail, _max) ({ \ -+ typeof(_max) (max) = (_max); \ -+ ((((head) - (tail)) + \ -+ (max)) & ((max) - 1)); }) -+ -+#define EDMA_TX_RING_SIZE 2048 -+#define EDMA_TX_RING_SIZE_MASK (EDMA_TX_RING_SIZE - 1) -+ -+/* Max segment processing capacity of HW for TSO. */ -+#define EDMA_TX_TSO_SEG_MAX 32 -+ -+/* HW defined low and high MSS size. */ -+#define EDMA_TX_TSO_MSS_MIN 256 -+#define EDMA_TX_TSO_MSS_MAX 10240 -+ -+#define EDMA_DST_PORT_TYPE 2 -+#define EDMA_DST_PORT_TYPE_SHIFT 28 -+#define EDMA_DST_PORT_TYPE_MASK (0xf << EDMA_DST_PORT_TYPE_SHIFT) -+#define EDMA_DST_PORT_ID_SHIFT 16 -+#define EDMA_DST_PORT_ID_MASK (0xfff << EDMA_DST_PORT_ID_SHIFT) -+ -+#define EDMA_DST_PORT_TYPE_SET(x) (((x) << EDMA_DST_PORT_TYPE_SHIFT) & \ -+ EDMA_DST_PORT_TYPE_MASK) -+#define EDMA_DST_PORT_ID_SET(x) (((x) << EDMA_DST_PORT_ID_SHIFT) & \ -+ EDMA_DST_PORT_ID_MASK) -+#define EDMA_DST_INFO_SET(desc, x) ((desc)->word4 |= \ -+ (EDMA_DST_PORT_TYPE_SET(EDMA_DST_PORT_TYPE) | EDMA_DST_PORT_ID_SET(x))) -+ -+#define EDMA_TXDESC_TSO_ENABLE_MASK BIT(24) -+#define EDMA_TXDESC_TSO_ENABLE_SET(desc, x) ((desc)->word5 |= \ -+ FIELD_PREP(EDMA_TXDESC_TSO_ENABLE_MASK, x)) -+#define EDMA_TXDESC_MSS_MASK GENMASK(31, 16) -+#define EDMA_TXDESC_MSS_SET(desc, x) ((desc)->word6 |= \ -+ FIELD_PREP(EDMA_TXDESC_MSS_MASK, x)) -+#define EDMA_TXDESC_MORE_BIT_MASK BIT(30) -+#define EDMA_TXDESC_MORE_BIT_SET(desc, x) ((desc)->word1 |= \ -+ FIELD_PREP(EDMA_TXDESC_MORE_BIT_MASK, x)) -+ -+#define EDMA_TXDESC_ADV_OFFSET_BIT BIT(31) -+#define EDMA_TXDESC_ADV_OFFLOAD_SET(desc) ((desc)->word5 |= \ -+ FIELD_PREP(EDMA_TXDESC_ADV_OFFSET_BIT, 1)) -+#define EDMA_TXDESC_IP_CSUM_BIT BIT(25) -+#define EDMA_TXDESC_IP_CSUM_SET(desc) ((desc)->word5 |= \ -+ FIELD_PREP(EDMA_TXDESC_IP_CSUM_BIT, 1)) -+ -+#define EDMA_TXDESC_L4_CSUM_SET_MASK GENMASK(27, 26) -+#define EDMA_TXDESC_L4_CSUM_SET(desc) ((desc)->word5 |= \ -+ (FIELD_PREP(EDMA_TXDESC_L4_CSUM_SET_MASK, 1))) -+ -+#define EDMA_TXDESC_POOL_ID_SET_MASK GENMASK(24, 18) -+#define EDMA_TXDESC_POOL_ID_SET(desc, x) ((desc)->word5 |= \ -+ (FIELD_PREP(EDMA_TXDESC_POOL_ID_SET_MASK, x))) -+ -+#define EDMA_TXDESC_DATA_LEN_SET(desc, x) ((desc)->word5 |= ((x) & 0x1ffff)) -+#define EDMA_TXDESC_SERVICE_CODE_MASK GENMASK(24, 16) -+#define EDMA_TXDESC_SERVICE_CODE_SET(desc, x) ((desc)->word1 |= \ -+ (FIELD_PREP(EDMA_TXDESC_SERVICE_CODE_MASK, x))) -+#define EDMA_TXDESC_BUFFER_ADDR_SET(desc, addr) (((desc)->word0) = (addr)) -+ -+#ifdef __LP64__ -+#define EDMA_TXDESC_OPAQUE_GET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ (((u64)(desc)->word3 << 32) | (desc)->word2); }) -+ -+#define EDMA_TXCMPL_OPAQUE_GET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ (((u64)(desc)->word1 << 32) | \ -+ (desc)->word0); }) -+ -+#define EDMA_TXDESC_OPAQUE_LO_SET(desc, ptr) ((desc)->word2 = \ -+ (u32)(uintptr_t)(ptr)) -+ -+#define EDMA_TXDESC_OPAQUE_HI_SET(desc, ptr) ((desc)->word3 = \ -+ (u32)((u64)(ptr) >> 32)) -+ -+#define EDMA_TXDESC_OPAQUE_SET(_desc, _ptr) do { \ -+ typeof(_desc) (desc) = (_desc); \ -+ typeof(_ptr) (ptr) = (_ptr); \ -+ EDMA_TXDESC_OPAQUE_LO_SET(desc, ptr); \ -+ EDMA_TXDESC_OPAQUE_HI_SET(desc, ptr); \ -+} while (0) -+#else -+#define EDMA_TXCMPL_OPAQUE_GET(desc) ((desc)->word0) -+#define EDMA_TXDESC_OPAQUE_GET(desc) ((desc)->word2) -+#define EDMA_TXDESC_OPAQUE_LO_SET(desc, ptr) ((desc)->word2 = (u32)(uintptr_t)ptr) -+ -+#define EDMA_TXDESC_OPAQUE_SET(desc, ptr) \ -+ EDMA_TXDESC_OPAQUE_LO_SET(desc, ptr) -+#endif -+#define EDMA_TXCMPL_MORE_BIT_MASK BIT(30) -+ -+#define EDMA_TXCMPL_MORE_BIT_GET(desc) ((le32_to_cpu((__force __le32)((desc)->word2))) & \ -+ EDMA_TXCMPL_MORE_BIT_MASK) -+ -+#define EDMA_TXCOMP_RING_ERROR_MASK GENMASK(22, 0) -+ -+#define EDMA_TXCOMP_RING_ERROR_GET(x) ((le32_to_cpu((__force __le32)x)) & \ -+ EDMA_TXCOMP_RING_ERROR_MASK) -+ -+#define EDMA_TXCOMP_POOL_ID_MASK GENMASK(5, 0) -+ -+#define EDMA_TXCOMP_POOL_ID_GET(desc) ((le32_to_cpu((__force __le32)((desc)->word2))) & \ -+ EDMA_TXCOMP_POOL_ID_MASK) -+ -+/* Opaque values are set in word2 and word3, -+ * they are not accessed by the EDMA HW, -+ * so endianness conversion is not needed. -+ */ -+#define EDMA_TXDESC_ENDIAN_SET(_desc) ({ \ -+ typeof(_desc) (desc) = (_desc); \ -+ cpu_to_le32s(&((desc)->word0)); \ -+ cpu_to_le32s(&((desc)->word1)); \ -+ cpu_to_le32s(&((desc)->word4)); \ -+ cpu_to_le32s(&((desc)->word5)); \ -+ cpu_to_le32s(&((desc)->word6)); \ -+ cpu_to_le32s(&((desc)->word7)); \ -+}) -+ -+/* EDMA Tx GSO status */ -+enum edma_tx_status { -+ EDMA_TX_OK = 0, /* Tx success. */ -+ EDMA_TX_FAIL_NO_DESC = 1, /* Not enough descriptors. */ -+ EDMA_TX_FAIL = 2, /* Tx failure. */ -+}; -+ -+/* EDMA TX GSO status */ -+enum edma_tx_gso_status { -+ EDMA_TX_GSO_NOT_NEEDED = 0, -+ /* Packet has segment count less than TX_TSO_SEG_MAX. */ -+ EDMA_TX_GSO_SUCCEED = 1, -+ /* GSO Succeed. */ -+ EDMA_TX_GSO_FAIL = 2, -+ /* GSO failed, drop the packet. */ -+}; -+ -+/** -+ * struct edma_txcmpl_stats - EDMA TX complete ring statistics. -+ * @invalid_buffer: Invalid buffer address received. -+ * @errors: Other Tx complete descriptor errors indicated by the hardware. -+ * @desc_with_more_bit: Packet's segment transmit count. -+ * @no_pending_desc: No descriptor is pending for processing. -+ * @syncp: Synchronization pointer. -+ */ -+struct edma_txcmpl_stats { -+ u64 invalid_buffer; -+ u64 errors; -+ u64 desc_with_more_bit; -+ u64 no_pending_desc; -+ struct u64_stats_sync syncp; -+}; -+ -+/** -+ * struct edma_txdesc_stats - EDMA Tx descriptor ring statistics. -+ * @no_desc_avail: No descriptor available to transmit. -+ * @tso_max_seg_exceed: Packets extending EDMA_TX_TSO_SEG_MAX segments. -+ * @syncp: Synchronization pointer. -+ */ -+struct edma_txdesc_stats { -+ u64 no_desc_avail; -+ u64 tso_max_seg_exceed; -+ struct u64_stats_sync syncp; -+}; -+ -+/** -+ * struct edma_txdesc_pri - EDMA primary TX descriptor. -+ * @word0: Low 32-bit of buffer address. -+ * @word1: Buffer recycling, PTP tag flag, PRI valid flag. -+ * @word2: Low 32-bit of opaque value. -+ * @word3: High 32-bit of opaque value. -+ * @word4: Source/Destination port info. -+ * @word5: VLAN offload, csum mode, ip_csum_en, tso_en, data len. -+ * @word6: MSS/hash_value/PTP tag, data offset. -+ * @word7: L4/L3 offset, PROT type, L2 type, CVLAN/SVLAN tag, service code. -+ */ -+struct edma_txdesc_pri { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+ u32 word4; -+ u32 word5; -+ u32 word6; -+ u32 word7; -+}; -+ -+/** -+ * struct edma_txdesc_sec - EDMA secondary TX descriptor. -+ * @word0: Reserved. -+ * @word1: Custom csum offset, payload offset, TTL/NAT action. -+ * @word2: NAPT translated port, DSCP value, TTL value. -+ * @word3: Flow index value and valid flag. -+ * @word4: Reserved. -+ * @word5: Reserved. -+ * @word6: CVLAN/SVLAN command. -+ * @word7: CVLAN/SVLAN tag value. -+ */ -+struct edma_txdesc_sec { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+ u32 word4; -+ u32 word5; -+ u32 word6; -+ u32 word7; -+}; -+ -+/** -+ * struct edma_txcmpl_desc - EDMA TX complete descriptor. -+ * @word0: Low 32-bit opaque value. -+ * @word1: High 32-bit opaque value. -+ * @word2: More fragment, transmit ring id, pool id. -+ * @word3: Error indications. -+ */ -+struct edma_txcmpl_desc { -+ u32 word0; -+ u32 word1; -+ u32 word2; -+ u32 word3; -+}; -+ -+/** -+ * struct edma_txdesc_ring - EDMA TX descriptor ring -+ * @prod_idx: Producer index -+ * @id: Tx ring number -+ * @avail_desc: Number of available descriptor to process -+ * @pdesc: Primary descriptor ring virtual address -+ * @pdma: Primary descriptor ring physical address -+ * @sdesc: Secondary descriptor ring virtual address -+ * @tx_desc_stats: Tx descriptor ring statistics -+ * @sdma: Secondary descriptor ring physical address -+ * @count: Number of descriptors -+ * @fc_grp_id: Flow control group ID -+ */ -+struct edma_txdesc_ring { -+ u32 prod_idx; -+ u32 id; -+ u32 avail_desc; -+ struct edma_txdesc_pri *pdesc; -+ dma_addr_t pdma; -+ struct edma_txdesc_sec *sdesc; -+ struct edma_txdesc_stats txdesc_stats; -+ dma_addr_t sdma; -+ u32 count; -+ u8 fc_grp_id; -+}; -+ -+/** -+ * struct edma_txcmpl_ring - EDMA TX complete ring -+ * @napi: NAPI -+ * @cons_idx: Consumer index -+ * @avail_pkt: Number of available packets to process -+ * @desc: Descriptor ring virtual address -+ * @id: Txcmpl ring number -+ * @tx_cmpl_stats: Tx complete ring statistics -+ * @dma: Descriptor ring physical address -+ * @count: Number of descriptors in the ring -+ * @napi_added: Flag to indicate NAPI add status -+ */ -+struct edma_txcmpl_ring { -+ struct napi_struct napi; -+ u32 cons_idx; -+ u32 avail_pkt; -+ struct edma_txcmpl_desc *desc; -+ u32 id; -+ struct edma_txcmpl_stats txcmpl_stats; -+ dma_addr_t dma; -+ u32 count; -+ bool napi_added; -+}; -+ -+enum edma_tx_status edma_tx_ring_xmit(struct net_device *netdev, -+ struct sk_buff *skb, -+ struct edma_txdesc_ring *txdesc_ring, -+ struct edma_port_tx_stats *stats); -+u32 edma_tx_complete(u32 work_to_do, -+ struct edma_txcmpl_ring *txcmpl_ring); -+irqreturn_t edma_tx_handle_irq(int irq, void *ctx); -+int edma_tx_napi_poll(struct napi_struct *napi, int budget); -+enum edma_tx_gso_status edma_tx_gso_segment(struct sk_buff *skb, -+ struct net_device *netdev, struct sk_buff **segs); -+ -+#endif diff --git a/target/linux/qualcommbe/patches-6.12/0346-net-ethernet-qualcomm-Add-miscellaneous-error-interr.patch b/target/linux/qualcommbe/patches-6.12/0346-net-ethernet-qualcomm-Add-miscellaneous-error-interr.patch deleted file mode 100644 index 0bdfb0c897..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0346-net-ethernet-qualcomm-Add-miscellaneous-error-interr.patch +++ /dev/null @@ -1,730 +0,0 @@ -From 8a924457c0b71acee96c8f78ef386e2a354a2aca Mon Sep 17 00:00:00 2001 -From: Suruchi Agarwal -Date: Thu, 21 Mar 2024 16:31:04 -0700 -Subject: [PATCH] net: ethernet: qualcomm: Add miscellaneous error interrupts - and counters - -Miscellaneous error interrupts, EDMA Tx/Rx and error counters are supported -using debugfs framework. - -Change-Id: I7da8b978a7e93947b03a45269a81b401f35da31c -Co-developed-by: Pavithra R -Signed-off-by: Pavithra R -Signed-off-by: Suruchi Agarwal ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/edma.c | 162 ++++++++ - drivers/net/ethernet/qualcomm/ppe/edma.h | 30 ++ - .../net/ethernet/qualcomm/ppe/edma_debugfs.c | 370 ++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/ppe_debugfs.c | 17 + - 5 files changed, 580 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_debugfs.c - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o - - #EDMA --qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_port.o edma_rx.o edma_tx.o -+qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_debugfs.o edma_port.o edma_rx.o edma_tx.o ---- a/drivers/net/ethernet/qualcomm/ppe/edma.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -152,6 +152,42 @@ static int edma_clock_init(void) - } - - /** -+ * edma_err_stats_alloc - Allocate stats memory -+ * -+ * Allocate memory for per-CPU error stats. -+ */ -+int edma_err_stats_alloc(void) -+{ -+ u32 i; -+ -+ edma_ctx->err_stats = alloc_percpu(*edma_ctx->err_stats); -+ if (!edma_ctx->err_stats) -+ return -ENOMEM; -+ -+ for_each_possible_cpu(i) { -+ struct edma_err_stats *stats; -+ -+ stats = per_cpu_ptr(edma_ctx->err_stats, i); -+ u64_stats_init(&stats->syncp); -+ } -+ -+ return 0; -+} -+ -+/** -+ * edma_err_stats_free - Free stats memory -+ * -+ * Free memory of per-CPU error stats. -+ */ -+void edma_err_stats_free(void) -+{ -+ if (edma_ctx->err_stats) { -+ free_percpu(edma_ctx->err_stats); -+ edma_ctx->err_stats = NULL; -+ } -+} -+ -+/** - * edma_configure_ucast_prio_map_tbl - Configure unicast priority map table. - * - * Map int_priority values to priority class and initialize -@@ -191,11 +227,113 @@ static int edma_configure_ucast_prio_map - return ret; - } - -+static void edma_disable_misc_interrupt(void) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_MISC_INT_MASK_ADDR; -+ regmap_write(regmap, reg, EDMA_MASK_INT_CLEAR); -+} -+ -+static void edma_enable_misc_interrupt(void) -+{ -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 reg; -+ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_MISC_INT_MASK_ADDR; -+ regmap_write(regmap, reg, edma_ctx->intr_info.intr_mask_misc); -+} -+ -+static irqreturn_t edma_misc_handle_irq(int irq, -+ __maybe_unused void *ctx) -+{ -+ struct edma_err_stats *stats = this_cpu_ptr(edma_ctx->err_stats); -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; -+ struct regmap *regmap = ppe_dev->regmap; -+ u32 misc_intr_status, data, reg; -+ -+ /* Read Misc intr status */ -+ reg = EDMA_BASE_OFFSET + EDMA_REG_MISC_INT_STAT_ADDR; -+ regmap_read(regmap, reg, &data); -+ misc_intr_status = data & edma_ctx->intr_info.intr_mask_misc; -+ -+ pr_debug("Received misc irq %d, status: %d\n", irq, misc_intr_status); -+ -+ if (FIELD_GET(EDMA_MISC_AXI_RD_ERR_MASK, misc_intr_status)) { -+ pr_err("MISC AXI read error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_axi_read_err; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_AXI_WR_ERR_MASK, misc_intr_status)) { -+ pr_err("MISC AXI write error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_axi_write_err; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_RX_DESC_FIFO_FULL_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC Rx descriptor fifo full error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_rxdesc_fifo_full; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_RX_ERR_BUF_SIZE_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC Rx buffer size error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_rx_buf_size_err; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_TX_SRAM_FULL_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC Tx SRAM full error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_tx_sram_full; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_TX_CMPL_BUF_FULL_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC Tx complete buffer full error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_txcmpl_buf_full; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_DATA_LEN_ERR_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC data length error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_tx_data_len_err; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ if (FIELD_GET(EDMA_MISC_TX_TIMEOUT_MASK, misc_intr_status)) { -+ if (net_ratelimit()) -+ pr_err("MISC Tx timeout error received\n"); -+ u64_stats_update_begin(&stats->syncp); -+ ++stats->edma_tx_timeout; -+ u64_stats_update_end(&stats->syncp); -+ } -+ -+ return IRQ_HANDLED; -+} -+ - static int edma_irq_register(void) - { - struct edma_hw_info *hw_info = edma_ctx->hw_info; - struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct ppe_device *ppe_dev = edma_ctx->ppe_dev; - struct edma_ring_info *rx = hw_info->rx; -+ struct device *dev = ppe_dev->dev; - int ret; - u32 i; - -@@ -270,8 +408,25 @@ static int edma_irq_register(void) - edma_rxdesc_irq_name[i]); - } - -+ /* Request Misc IRQ */ -+ ret = request_irq(edma_ctx->intr_info.intr_misc, edma_misc_handle_irq, -+ IRQF_SHARED, "edma_misc", -+ (void *)dev); -+ if (ret) { -+ pr_err("MISC IRQ:%d request failed\n", -+ edma_ctx->intr_info.intr_misc); -+ goto misc_intr_req_fail; -+ } -+ - return 0; - -+misc_intr_req_fail: -+ /* Free IRQ for RXDESC rings */ -+ for (i = 0; i < rx->num_rings; i++) { -+ synchronize_irq(edma_ctx->intr_info.intr_rx[i]); -+ free_irq(edma_ctx->intr_info.intr_rx[i], -+ (void *)&edma_ctx->rx_rings[i]); -+ } - rx_desc_ring_intr_req_fail: - for (i = 0; i < rx->num_rings; i++) - kfree(edma_rxdesc_irq_name[i]); -@@ -503,6 +658,7 @@ static int edma_hw_configure(void) - edma_cfg_tx_disable_interrupts(i); - - edma_cfg_rx_disable_interrupts(); -+ edma_disable_misc_interrupt(); - - edma_cfg_rx_rings_disable(); - -@@ -614,6 +770,7 @@ void edma_destroy(struct ppe_device *ppe - edma_cfg_tx_disable_interrupts(i); - - edma_cfg_rx_disable_interrupts(); -+ edma_disable_misc_interrupt(); - - /* Free IRQ for TXCMPL rings. */ - for (i = 0; i < txcmpl->num_rings; i++) { -@@ -634,6 +791,10 @@ void edma_destroy(struct ppe_device *ppe - } - kfree(edma_rxdesc_irq_name); - -+ /* Free Misc IRQ */ -+ synchronize_irq(edma_ctx->intr_info.intr_misc); -+ free_irq(edma_ctx->intr_info.intr_misc, (void *)(ppe_dev->dev)); -+ - kfree(edma_ctx->intr_info.intr_rx); - kfree(edma_ctx->intr_info.intr_txcmpl); - -@@ -699,6 +860,7 @@ int edma_setup(struct ppe_device *ppe_de - } - - edma_cfg_rx_enable_interrupts(); -+ edma_enable_misc_interrupt(); - - dev_info(dev, "EDMA configuration successful\n"); - ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -47,6 +47,30 @@ enum ppe_queue_class_type { - }; - - /** -+ * struct edma_err_stats - EDMA error stats -+ * @edma_axi_read_err: AXI read error -+ * @edma_axi_write_err: AXI write error -+ * @edma_rxdesc_fifo_full: Rx desc FIFO full error -+ * @edma_rx_buf_size_err: Rx buffer size too small error -+ * @edma_tx_sram_full: Tx packet SRAM buffer full error -+ * @edma_tx_data_len_err: Tx data length error -+ * @edma_tx_timeout: Tx timeout error -+ * @edma_txcmpl_buf_full: Tx completion buffer full error -+ * @syncp: Synchronization pointer -+ */ -+struct edma_err_stats { -+ u64 edma_axi_read_err; -+ u64 edma_axi_write_err; -+ u64 edma_rxdesc_fifo_full; -+ u64 edma_rx_buf_size_err; -+ u64 edma_tx_sram_full; -+ u64 edma_tx_data_len_err; -+ u64 edma_tx_timeout; -+ u64 edma_txcmpl_buf_full; -+ struct u64_stats_sync syncp; -+}; -+ -+/** - * struct edma_ring_info - EDMA ring data structure. - * @max_rings: Maximum number of rings - * @ring_start: Ring start ID -@@ -107,6 +131,7 @@ struct edma_intr_info { - * @rx_rings: Rx Desc Rings, SW is consumer - * @tx_rings: Tx Descriptor Ring, SW is producer - * @txcmpl_rings: Tx complete Ring, SW is consumer -+ * @err_stats: Per CPU error statistics - * @rx_page_mode: Page mode enabled or disabled - * @rx_buf_size: Rx buffer size for Jumbo MRU - * @tx_requeue_stop: Tx requeue stop enabled or disabled -@@ -121,6 +146,7 @@ struct edma_context { - struct edma_rxdesc_ring *rx_rings; - struct edma_txdesc_ring *tx_rings; - struct edma_txcmpl_ring *txcmpl_rings; -+ struct edma_err_stats __percpu *err_stats; - u32 rx_page_mode; - u32 rx_buf_size; - bool tx_requeue_stop; -@@ -129,8 +155,12 @@ struct edma_context { - /* Global EDMA context */ - extern struct edma_context *edma_ctx; - -+int edma_err_stats_alloc(void); -+void edma_err_stats_free(void); - void edma_destroy(struct ppe_device *ppe_dev); - int edma_setup(struct ppe_device *ppe_dev); -+void edma_debugfs_teardown(void); -+int edma_debugfs_setup(struct ppe_device *ppe_dev); - int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev, - enum ppe_queue_class_type class, - int index, int queue_offset); ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_debugfs.c -@@ -0,0 +1,370 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* EDMA debugfs routines for display of Tx/Rx counters. */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+ -+#define EDMA_STATS_BANNER_MAX_LEN 80 -+#define EDMA_RX_RING_STATS_NODE_NAME "EDMA_RX" -+#define EDMA_TX_RING_STATS_NODE_NAME "EDMA_TX" -+#define EDMA_ERR_STATS_NODE_NAME "EDMA_ERR" -+ -+static struct dentry *edma_dentry; -+static struct dentry *stats_dentry; -+ -+static void edma_debugfs_print_banner(struct seq_file *m, char *node) -+{ -+ u32 banner_char_len, i; -+ -+ for (i = 0; i < EDMA_STATS_BANNER_MAX_LEN; i++) -+ seq_puts(m, "_"); -+ banner_char_len = (EDMA_STATS_BANNER_MAX_LEN - (strlen(node) + 2)) / 2; -+ seq_puts(m, "\n\n"); -+ -+ for (i = 0; i < banner_char_len; i++) -+ seq_puts(m, "<"); -+ seq_printf(m, " %s ", node); -+ -+ for (i = 0; i < banner_char_len; i++) -+ seq_puts(m, ">"); -+ seq_puts(m, "\n"); -+ -+ for (i = 0; i < EDMA_STATS_BANNER_MAX_LEN; i++) -+ seq_puts(m, "_"); -+ seq_puts(m, "\n\n"); -+} -+ -+static int edma_debugfs_rx_rings_stats_show(struct seq_file *m, -+ void __maybe_unused *p) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *rxfill = hw_info->rxfill; -+ struct edma_rxfill_stats *rxfill_stats; -+ struct edma_rxdesc_stats *rxdesc_stats; -+ struct edma_ring_info *rx = hw_info->rx; -+ unsigned int start; -+ u32 i; -+ -+ rxfill_stats = kcalloc(rxfill->num_rings, sizeof(*rxfill_stats), GFP_KERNEL); -+ if (!rxfill_stats) -+ return -ENOMEM; -+ -+ rxdesc_stats = kcalloc(rx->num_rings, sizeof(*rxdesc_stats), GFP_KERNEL); -+ if (!rxdesc_stats) { -+ kfree(rxfill_stats); -+ return -ENOMEM; -+ } -+ -+ /* Get stats for Rx fill rings. */ -+ for (i = 0; i < rxfill->num_rings; i++) { -+ struct edma_rxfill_ring *rxfill_ring; -+ struct edma_rxfill_stats *stats; -+ -+ rxfill_ring = &edma_ctx->rxfill_rings[i]; -+ stats = &rxfill_ring->rxfill_stats; -+ do { -+ start = u64_stats_fetch_begin(&stats->syncp); -+ rxfill_stats[i].alloc_failed = stats->alloc_failed; -+ rxfill_stats[i].page_alloc_failed = stats->page_alloc_failed; -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); -+ } -+ -+ /* Get stats for Rx Desc rings. */ -+ for (i = 0; i < rx->num_rings; i++) { -+ struct edma_rxdesc_ring *rxdesc_ring; -+ struct edma_rxdesc_stats *stats; -+ -+ rxdesc_ring = &edma_ctx->rx_rings[i]; -+ stats = &rxdesc_ring->rxdesc_stats; -+ do { -+ start = u64_stats_fetch_begin(&stats->syncp); -+ rxdesc_stats[i].src_port_inval = stats->src_port_inval; -+ rxdesc_stats[i].src_port_inval_type = stats->src_port_inval_type; -+ rxdesc_stats[i].src_port_inval_netdev = stats->src_port_inval_netdev; -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); -+ } -+ -+ edma_debugfs_print_banner(m, EDMA_RX_RING_STATS_NODE_NAME); -+ -+ seq_puts(m, "\n#EDMA RX descriptor rings stats:\n\n"); -+ for (i = 0; i < rx->num_rings; i++) { -+ seq_printf(m, "\t\tEDMA RX descriptor %d ring stats:\n", i + rx->ring_start); -+ seq_printf(m, "\t\t rxdesc[%d]:src_port_inval = %llu\n", -+ i + rx->ring_start, rxdesc_stats[i].src_port_inval); -+ seq_printf(m, "\t\t rxdesc[%d]:src_port_inval_type = %llu\n", -+ i + rx->ring_start, rxdesc_stats[i].src_port_inval_type); -+ seq_printf(m, "\t\t rxdesc[%d]:src_port_inval_netdev = %llu\n", -+ i + rx->ring_start, -+ rxdesc_stats[i].src_port_inval_netdev); -+ seq_puts(m, "\n"); -+ } -+ -+ seq_puts(m, "\n#EDMA RX fill rings stats:\n\n"); -+ for (i = 0; i < rxfill->num_rings; i++) { -+ seq_printf(m, "\t\tEDMA RX fill %d ring stats:\n", i + rxfill->ring_start); -+ seq_printf(m, "\t\t rxfill[%d]:alloc_failed = %llu\n", -+ i + rxfill->ring_start, rxfill_stats[i].alloc_failed); -+ seq_printf(m, "\t\t rxfill[%d]:page_alloc_failed = %llu\n", -+ i + rxfill->ring_start, rxfill_stats[i].page_alloc_failed); -+ seq_puts(m, "\n"); -+ } -+ -+ kfree(rxfill_stats); -+ kfree(rxdesc_stats); -+ return 0; -+} -+ -+static int edma_debugfs_tx_rings_stats_show(struct seq_file *m, -+ void __maybe_unused *p) -+{ -+ struct edma_hw_info *hw_info = edma_ctx->hw_info; -+ struct edma_ring_info *txcmpl = hw_info->txcmpl; -+ struct edma_ring_info *tx = hw_info->tx; -+ struct edma_txcmpl_stats *txcmpl_stats; -+ struct edma_txdesc_stats *txdesc_stats; -+ unsigned int start; -+ u32 i; -+ -+ txcmpl_stats = kcalloc(txcmpl->num_rings, sizeof(*txcmpl_stats), GFP_KERNEL); -+ if (!txcmpl_stats) -+ return -ENOMEM; -+ -+ txdesc_stats = kcalloc(tx->num_rings, sizeof(*txdesc_stats), GFP_KERNEL); -+ if (!txdesc_stats) { -+ kfree(txcmpl_stats); -+ return -ENOMEM; -+ } -+ -+ /* Get stats for Tx desc rings. */ -+ for (i = 0; i < tx->num_rings; i++) { -+ struct edma_txdesc_ring *txdesc_ring; -+ struct edma_txdesc_stats *stats; -+ -+ txdesc_ring = &edma_ctx->tx_rings[i]; -+ stats = &txdesc_ring->txdesc_stats; -+ do { -+ start = u64_stats_fetch_begin(&stats->syncp); -+ txdesc_stats[i].no_desc_avail = stats->no_desc_avail; -+ txdesc_stats[i].tso_max_seg_exceed = stats->tso_max_seg_exceed; -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); -+ } -+ -+ /* Get stats for Tx Complete rings. */ -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ struct edma_txcmpl_ring *txcmpl_ring; -+ struct edma_txcmpl_stats *stats; -+ -+ txcmpl_ring = &edma_ctx->txcmpl_rings[i]; -+ stats = &txcmpl_ring->txcmpl_stats; -+ do { -+ start = u64_stats_fetch_begin(&stats->syncp); -+ txcmpl_stats[i].invalid_buffer = stats->invalid_buffer; -+ txcmpl_stats[i].errors = stats->errors; -+ txcmpl_stats[i].desc_with_more_bit = stats->desc_with_more_bit; -+ txcmpl_stats[i].no_pending_desc = stats->no_pending_desc; -+ } while (u64_stats_fetch_retry(&stats->syncp, start)); -+ } -+ -+ edma_debugfs_print_banner(m, EDMA_TX_RING_STATS_NODE_NAME); -+ -+ seq_puts(m, "\n#EDMA TX complete rings stats:\n\n"); -+ for (i = 0; i < txcmpl->num_rings; i++) { -+ seq_printf(m, "\t\tEDMA TX complete %d ring stats:\n", i + txcmpl->ring_start); -+ seq_printf(m, "\t\t txcmpl[%d]:invalid_buffer = %llu\n", -+ i + txcmpl->ring_start, txcmpl_stats[i].invalid_buffer); -+ seq_printf(m, "\t\t txcmpl[%d]:errors = %llu\n", -+ i + txcmpl->ring_start, txcmpl_stats[i].errors); -+ seq_printf(m, "\t\t txcmpl[%d]:desc_with_more_bit = %llu\n", -+ i + txcmpl->ring_start, txcmpl_stats[i].desc_with_more_bit); -+ seq_printf(m, "\t\t txcmpl[%d]:no_pending_desc = %llu\n", -+ i + txcmpl->ring_start, txcmpl_stats[i].no_pending_desc); -+ seq_puts(m, "\n"); -+ } -+ -+ seq_puts(m, "\n#EDMA TX descriptor rings stats:\n\n"); -+ for (i = 0; i < tx->num_rings; i++) { -+ seq_printf(m, "\t\tEDMA TX descriptor %d ring stats:\n", i + tx->ring_start); -+ seq_printf(m, "\t\t txdesc[%d]:no_desc_avail = %llu\n", -+ i + tx->ring_start, txdesc_stats[i].no_desc_avail); -+ seq_printf(m, "\t\t txdesc[%d]:tso_max_seg_exceed = %llu\n", -+ i + tx->ring_start, txdesc_stats[i].tso_max_seg_exceed); -+ seq_puts(m, "\n"); -+ } -+ -+ kfree(txcmpl_stats); -+ kfree(txdesc_stats); -+ return 0; -+} -+ -+static int edma_debugfs_err_stats_show(struct seq_file *m, -+ void __maybe_unused *p) -+{ -+ struct edma_err_stats *err_stats, *pcpu_err_stats; -+ unsigned int start; -+ u32 cpu; -+ -+ err_stats = kzalloc(sizeof(*err_stats), GFP_KERNEL); -+ if (!err_stats) -+ return -ENOMEM; -+ -+ /* Get percpu EDMA miscellaneous stats. */ -+ for_each_possible_cpu(cpu) { -+ pcpu_err_stats = per_cpu_ptr(edma_ctx->err_stats, cpu); -+ do { -+ start = u64_stats_fetch_begin(&pcpu_err_stats->syncp); -+ err_stats->edma_axi_read_err += -+ pcpu_err_stats->edma_axi_read_err; -+ err_stats->edma_axi_write_err += -+ pcpu_err_stats->edma_axi_write_err; -+ err_stats->edma_rxdesc_fifo_full += -+ pcpu_err_stats->edma_rxdesc_fifo_full; -+ err_stats->edma_rx_buf_size_err += -+ pcpu_err_stats->edma_rx_buf_size_err; -+ err_stats->edma_tx_sram_full += -+ pcpu_err_stats->edma_tx_sram_full; -+ err_stats->edma_tx_data_len_err += -+ pcpu_err_stats->edma_tx_data_len_err; -+ err_stats->edma_tx_timeout += -+ pcpu_err_stats->edma_tx_timeout; -+ err_stats->edma_txcmpl_buf_full += -+ pcpu_err_stats->edma_txcmpl_buf_full; -+ } while (u64_stats_fetch_retry(&pcpu_err_stats->syncp, start)); -+ } -+ -+ edma_debugfs_print_banner(m, EDMA_ERR_STATS_NODE_NAME); -+ -+ seq_puts(m, "\n#EDMA error stats:\n\n"); -+ seq_printf(m, "\t\t axi read error = %llu\n", -+ err_stats->edma_axi_read_err); -+ seq_printf(m, "\t\t axi write error = %llu\n", -+ err_stats->edma_axi_write_err); -+ seq_printf(m, "\t\t Rx descriptor fifo full = %llu\n", -+ err_stats->edma_rxdesc_fifo_full); -+ seq_printf(m, "\t\t Rx buffer size error = %llu\n", -+ err_stats->edma_rx_buf_size_err); -+ seq_printf(m, "\t\t Tx SRAM full = %llu\n", -+ err_stats->edma_tx_sram_full); -+ seq_printf(m, "\t\t Tx data length error = %llu\n", -+ err_stats->edma_tx_data_len_err); -+ seq_printf(m, "\t\t Tx timeout = %llu\n", -+ err_stats->edma_tx_timeout); -+ seq_printf(m, "\t\t Tx completion buffer full = %llu\n", -+ err_stats->edma_txcmpl_buf_full); -+ -+ kfree(err_stats); -+ return 0; -+} -+ -+static int edma_debugs_rx_rings_stats_open(struct inode *inode, -+ struct file *file) -+{ -+ return single_open(file, edma_debugfs_rx_rings_stats_show, -+ inode->i_private); -+} -+ -+static const struct file_operations edma_debugfs_rx_rings_file_ops = { -+ .open = edma_debugs_rx_rings_stats_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release -+}; -+ -+static int edma_debugs_tx_rings_stats_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, edma_debugfs_tx_rings_stats_show, inode->i_private); -+} -+ -+static const struct file_operations edma_debugfs_tx_rings_file_ops = { -+ .open = edma_debugs_tx_rings_stats_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release -+}; -+ -+static int edma_debugs_err_stats_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, edma_debugfs_err_stats_show, inode->i_private); -+} -+ -+static const struct file_operations edma_debugfs_misc_file_ops = { -+ .open = edma_debugs_err_stats_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = seq_release -+}; -+ -+/** -+ * edma_debugfs_teardown - EDMA debugfs teardown. -+ * -+ * EDMA debugfs teardown and free stats memory. -+ */ -+void edma_debugfs_teardown(void) -+{ -+ /* Free EDMA miscellaneous stats memory */ -+ edma_err_stats_free(); -+ -+ debugfs_remove_recursive(edma_dentry); -+ edma_dentry = NULL; -+ stats_dentry = NULL; -+} -+ -+/** -+ * edma_debugfs_setup - EDMA debugfs setup. -+ * @ppe_dev: PPE Device -+ * -+ * EDMA debugfs setup. -+ */ -+int edma_debugfs_setup(struct ppe_device *ppe_dev) -+{ -+ edma_dentry = debugfs_create_dir("edma", ppe_dev->debugfs_root); -+ if (!edma_dentry) { -+ pr_err("Unable to create debugfs edma directory in debugfs\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ stats_dentry = debugfs_create_dir("stats", edma_dentry); -+ if (!stats_dentry) { -+ pr_err("Unable to create debugfs stats directory in debugfs\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ if (!debugfs_create_file("rx_ring_stats", 0444, stats_dentry, -+ NULL, &edma_debugfs_rx_rings_file_ops)) { -+ pr_err("Unable to create Rx rings statistics file entry in debugfs\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ if (!debugfs_create_file("tx_ring_stats", 0444, stats_dentry, -+ NULL, &edma_debugfs_tx_rings_file_ops)) { -+ pr_err("Unable to create Tx rings statistics file entry in debugfs\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ /* Allocate memory for EDMA miscellaneous stats */ -+ if (edma_err_stats_alloc() < 0) { -+ pr_err("Unable to allocate miscellaneous percpu stats\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ if (!debugfs_create_file("err_stats", 0444, stats_dentry, -+ NULL, &edma_debugfs_misc_file_ops)) { -+ pr_err("Unable to create EDMA miscellaneous statistics file entry in debugfs\n"); -+ goto debugfs_dir_failed; -+ } -+ -+ return 0; -+ -+debugfs_dir_failed: -+ debugfs_remove_recursive(edma_dentry); -+ edma_dentry = NULL; -+ stats_dentry = NULL; -+ return -ENOMEM; -+} ---- a/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c -+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_debugfs.c -@@ -7,9 +7,11 @@ - - #include - #include -+#include - #include - #include - -+#include "edma.h" - #include "ppe.h" - #include "ppe_config.h" - #include "ppe_debugfs.h" -@@ -678,15 +680,30 @@ static const struct file_operations ppe_ - - void ppe_debugfs_setup(struct ppe_device *ppe_dev) - { -+ int ret; -+ - ppe_dev->debugfs_root = debugfs_create_dir("ppe", NULL); - debugfs_create_file("packet_counters", 0444, - ppe_dev->debugfs_root, - ppe_dev, - &ppe_debugfs_packet_counter_fops); -+ -+ if (!ppe_dev->debugfs_root) { -+ dev_err(ppe_dev->dev, "Error in PPE debugfs setup\n"); -+ return; -+ } -+ -+ ret = edma_debugfs_setup(ppe_dev); -+ if (ret) { -+ dev_err(ppe_dev->dev, "Error in EDMA debugfs setup API. ret: %d\n", ret); -+ debugfs_remove_recursive(ppe_dev->debugfs_root); -+ ppe_dev->debugfs_root = NULL; -+ } - } - - void ppe_debugfs_teardown(struct ppe_device *ppe_dev) - { -+ edma_debugfs_teardown(); - debugfs_remove_recursive(ppe_dev->debugfs_root); - ppe_dev->debugfs_root = NULL; - } diff --git a/target/linux/qualcommbe/patches-6.12/0347-net-ethernet-qualcomm-Add-ethtool-support-for-EDMA.patch b/target/linux/qualcommbe/patches-6.12/0347-net-ethernet-qualcomm-Add-ethtool-support-for-EDMA.patch deleted file mode 100644 index 4e0103db57..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0347-net-ethernet-qualcomm-Add-ethtool-support-for-EDMA.patch +++ /dev/null @@ -1,344 +0,0 @@ -From bd61a680fb657eb65272225f18c93fe338c700da Mon Sep 17 00:00:00 2001 -From: Pavithra R -Date: Thu, 30 May 2024 20:46:36 +0530 -Subject: [PATCH] net: ethernet: qualcomm: Add ethtool support for EDMA - -ethtool ops can be used for EDMA netdevice configuration and statistics. - -Change-Id: I57fc19415dacbe51fed000520336463938220609 -Signed-off-by: Pavithra R -Alex G: use struct ethtool_keee instead of ethtool_eee -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/ppe/Makefile | 2 +- - drivers/net/ethernet/qualcomm/ppe/edma.h | 1 + - .../net/ethernet/qualcomm/ppe/edma_ethtool.c | 294 ++++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma_port.c | 1 + - 4 files changed, 297 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/ethernet/qualcomm/ppe/edma_ethtool.c - ---- a/drivers/net/ethernet/qualcomm/ppe/Makefile -+++ b/drivers/net/ethernet/qualcomm/ppe/Makefile -@@ -7,4 +7,4 @@ obj-$(CONFIG_QCOM_PPE) += qcom-ppe.o - qcom-ppe-objs := ppe.o ppe_config.o ppe_debugfs.o ppe_port.o - - #EDMA --qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_debugfs.o edma_port.o edma_rx.o edma_tx.o -+qcom-ppe-objs += edma.o edma_cfg_rx.o edma_cfg_tx.o edma_debugfs.o edma_port.o edma_rx.o edma_tx.o edma_ethtool.o ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -161,6 +161,7 @@ void edma_destroy(struct ppe_device *ppe - int edma_setup(struct ppe_device *ppe_dev); - void edma_debugfs_teardown(void); - int edma_debugfs_setup(struct ppe_device *ppe_dev); -+void edma_set_ethtool_ops(struct net_device *netdev); - int ppe_edma_queue_offset_config(struct ppe_device *ppe_dev, - enum ppe_queue_class_type class, - int index, int queue_offset); ---- /dev/null -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_ethtool.c -@@ -0,0 +1,294 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+/* ethtool support for EDMA */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "edma.h" -+#include "edma_port.h" -+ -+struct edma_ethtool_stats { -+ u8 stat_string[ETH_GSTRING_LEN]; -+ u32 stat_offset; -+}; -+ -+/** -+ * struct edma_gmac_stats - Per-GMAC statistics. -+ * @rx_packets: Number of RX packets -+ * @rx_bytes: Number of RX bytes -+ * @rx_dropped: Number of RX dropped packets -+ * @rx_fraglist_packets: Number of RX fraglist packets -+ * @rx_nr_frag_packets: Number of RX nr fragment packets -+ * @rx_nr_frag_headroom_err: Number of RX nr fragment packets with headroom error -+ * @tx_packets: Number of TX packets -+ * @tx_bytes: Number of TX bytes -+ * @tx_dropped: Number of TX dropped packets -+ * @tx_nr_frag_packets: Number of TX nr fragment packets -+ * @tx_fraglist_packets: Number of TX fraglist packets -+ * @tx_fraglist_with_nr_frags_packets: Number of TX fraglist packets with nr fragments -+ * @tx_tso_packets: Number of TX TCP segmentation offload packets -+ * @tx_tso_drop_packets: Number of TX TCP segmentation dropped packets -+ * @tx_gso_packets: Number of TX SW GSO packets -+ * @tx_gso_drop_packets: Number of TX SW GSO dropped packets -+ * @tx_queue_stopped: Number of times Queue got stopped -+ */ -+struct edma_gmac_stats { -+ u64 rx_packets; -+ u64 rx_bytes; -+ u64 rx_dropped; -+ u64 rx_fraglist_packets; -+ u64 rx_nr_frag_packets; -+ u64 rx_nr_frag_headroom_err; -+ u64 tx_packets; -+ u64 tx_bytes; -+ u64 tx_dropped; -+ u64 tx_nr_frag_packets; -+ u64 tx_fraglist_packets; -+ u64 tx_fraglist_with_nr_frags_packets; -+ u64 tx_tso_packets; -+ u64 tx_tso_drop_packets; -+ u64 tx_gso_packets; -+ u64 tx_gso_drop_packets; -+ u64 tx_queue_stopped[EDMA_MAX_CORE]; -+}; -+ -+#define EDMA_STAT(m) offsetof(struct edma_gmac_stats, m) -+ -+static const struct edma_ethtool_stats edma_gstrings_stats[] = { -+ {"rx_bytes", EDMA_STAT(rx_bytes)}, -+ {"rx_packets", EDMA_STAT(rx_packets)}, -+ {"rx_dropped", EDMA_STAT(rx_dropped)}, -+ {"rx_fraglist_packets", EDMA_STAT(rx_fraglist_packets)}, -+ {"rx_nr_frag_packets", EDMA_STAT(rx_nr_frag_packets)}, -+ {"rx_nr_frag_headroom_err", EDMA_STAT(rx_nr_frag_headroom_err)}, -+ {"tx_bytes", EDMA_STAT(tx_bytes)}, -+ {"tx_packets", EDMA_STAT(tx_packets)}, -+ {"tx_dropped", EDMA_STAT(tx_dropped)}, -+ {"tx_nr_frag_packets", EDMA_STAT(tx_nr_frag_packets)}, -+ {"tx_fraglist_packets", EDMA_STAT(tx_fraglist_packets)}, -+ {"tx_fraglist_nr_frags_packets", EDMA_STAT(tx_fraglist_with_nr_frags_packets)}, -+ {"tx_tso_packets", EDMA_STAT(tx_tso_packets)}, -+ {"tx_tso_drop_packets", EDMA_STAT(tx_tso_drop_packets)}, -+ {"tx_gso_packets", EDMA_STAT(tx_gso_packets)}, -+ {"tx_gso_drop_packets", EDMA_STAT(tx_gso_drop_packets)}, -+ {"tx_queue_stopped_cpu0", EDMA_STAT(tx_queue_stopped[0])}, -+ {"tx_queue_stopped_cpu1", EDMA_STAT(tx_queue_stopped[1])}, -+ {"tx_queue_stopped_cpu2", EDMA_STAT(tx_queue_stopped[2])}, -+ {"tx_queue_stopped_cpu3", EDMA_STAT(tx_queue_stopped[3])}, -+}; -+ -+#define EDMA_STATS_LEN ARRAY_SIZE(edma_gstrings_stats) -+ -+static void edma_port_get_stats(struct net_device *netdev, -+ struct edma_gmac_stats *stats) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct edma_port_rx_stats *pcpu_rx_stats; -+ struct edma_port_tx_stats *pcpu_tx_stats; -+ int i; -+ -+ memset(stats, 0, sizeof(struct edma_port_pcpu_stats)); -+ -+ for_each_possible_cpu(i) { -+ struct edma_port_rx_stats rxp; -+ struct edma_port_tx_stats txp; -+ unsigned int start; -+ -+ pcpu_rx_stats = per_cpu_ptr(port_priv->pcpu_stats.rx_stats, i); -+ -+ do { -+ start = u64_stats_fetch_begin(&pcpu_rx_stats->syncp); -+ memcpy(&rxp, pcpu_rx_stats, sizeof(*pcpu_rx_stats)); -+ } while (u64_stats_fetch_retry(&pcpu_rx_stats->syncp, start)); -+ -+ stats->rx_packets += rxp.rx_pkts; -+ stats->rx_bytes += rxp.rx_bytes; -+ stats->rx_dropped += rxp.rx_drops; -+ stats->rx_nr_frag_packets += rxp.rx_nr_frag_pkts; -+ stats->rx_fraglist_packets += rxp.rx_fraglist_pkts; -+ stats->rx_nr_frag_headroom_err += rxp.rx_nr_frag_headroom_err; -+ -+ pcpu_tx_stats = per_cpu_ptr(port_priv->pcpu_stats.tx_stats, i); -+ -+ do { -+ start = u64_stats_fetch_begin(&pcpu_tx_stats->syncp); -+ memcpy(&txp, pcpu_tx_stats, sizeof(*pcpu_tx_stats)); -+ } while (u64_stats_fetch_retry(&pcpu_tx_stats->syncp, start)); -+ -+ stats->tx_packets += txp.tx_pkts; -+ stats->tx_bytes += txp.tx_bytes; -+ stats->tx_dropped += txp.tx_drops; -+ stats->tx_nr_frag_packets += txp.tx_nr_frag_pkts; -+ stats->tx_fraglist_packets += txp.tx_fraglist_pkts; -+ stats->tx_fraglist_with_nr_frags_packets += txp.tx_fraglist_with_nr_frags_pkts; -+ stats->tx_tso_packets += txp.tx_tso_pkts; -+ stats->tx_tso_drop_packets += txp.tx_tso_drop_pkts; -+ stats->tx_gso_packets += txp.tx_gso_pkts; -+ stats->tx_gso_drop_packets += txp.tx_gso_drop_pkts; -+ stats->tx_queue_stopped[i] += txp.tx_queue_stopped[i]; -+ } -+} -+ -+static void edma_get_ethtool_stats(struct net_device *netdev, -+ __maybe_unused struct ethtool_stats *stats, -+ u64 *data) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct edma_gmac_stats edma_stats; -+ u64 *mib_data; -+ int i; -+ u8 *p; -+ -+ if (!port_priv) -+ return; -+ -+ /* Get the DMA Driver statistics from the data plane if available. */ -+ memset(&edma_stats, 0, sizeof(struct edma_gmac_stats)); -+ edma_port_get_stats(netdev, &edma_stats); -+ -+ /* Populate data plane statistics. */ -+ for (i = 0; i < EDMA_STATS_LEN; i++) { -+ p = ((u8 *)(&edma_stats) + edma_gstrings_stats[i].stat_offset); -+ data[i] = *(u64 *)p; -+ } -+ -+ /* Get the GMAC MIB statistics along with the DMA driver statistics. */ -+ mib_data = &data[EDMA_STATS_LEN]; -+ ppe_port_get_ethtool_stats(port_priv->ppe_port, mib_data); -+} -+ -+static int edma_get_strset_count(struct net_device *netdev, int sset) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ int sset_count = 0; -+ -+ if (!port_priv || sset != ETH_SS_STATS) -+ return 0; -+ -+ sset_count = ppe_port_get_sset_count(port_priv->ppe_port, sset); -+ -+ return (EDMA_STATS_LEN + sset_count); -+} -+ -+static void edma_get_strings(struct net_device *netdev, u32 stringset, -+ u8 *data) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ int i; -+ -+ if (!port_priv || stringset != ETH_SS_STATS) -+ return; -+ -+ for (i = 0; i < EDMA_STATS_LEN; i++) { -+ memcpy(data, edma_gstrings_stats[i].stat_string, -+ strlen(edma_gstrings_stats[i].stat_string)); -+ data += ETH_GSTRING_LEN; -+ } -+ -+ ppe_port_get_strings(port_priv->ppe_port, stringset, data); -+} -+ -+static int edma_get_link_ksettings(struct net_device *netdev, -+ struct ethtool_link_ksettings *cmd) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ return phylink_ethtool_ksettings_get(port->phylink, cmd); -+} -+ -+static int edma_set_link_ksettings(struct net_device *netdev, -+ const struct ethtool_link_ksettings *cmd) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ return phylink_ethtool_ksettings_set(port->phylink, cmd); -+} -+ -+static void edma_get_pauseparam(struct net_device *netdev, -+ struct ethtool_pauseparam *pause) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ -+ if (!port_priv) -+ return; -+ -+ phylink_ethtool_get_pauseparam(port->phylink, pause); -+} -+ -+static int edma_set_pauseparam(struct net_device *netdev, -+ struct ethtool_pauseparam *pause) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ return phylink_ethtool_set_pauseparam(port->phylink, pause); -+} -+ -+static int edma_get_eee(struct net_device *netdev, struct ethtool_keee *eee) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ return phylink_ethtool_get_eee(port->phylink, eee); -+} -+ -+static int edma_set_eee(struct net_device *netdev, struct ethtool_keee *eee) -+{ -+ struct edma_port_priv *port_priv = (struct edma_port_priv *)netdev_priv(netdev); -+ struct ppe_port *port = port_priv->ppe_port; -+ int ret; -+ -+ if (!port_priv) -+ return -EINVAL; -+ -+ ret = ppe_port_set_mac_eee(port_priv->ppe_port, eee); -+ if (ret) -+ return ret; -+ -+ return phylink_ethtool_set_eee(port->phylink, eee); -+} -+ -+static const struct ethtool_ops edma_ethtool_ops = { -+ .get_strings = &edma_get_strings, -+ .get_sset_count = &edma_get_strset_count, -+ .get_ethtool_stats = &edma_get_ethtool_stats, -+ .get_link = ðtool_op_get_link, -+ .get_link_ksettings = edma_get_link_ksettings, -+ .set_link_ksettings = edma_set_link_ksettings, -+ .get_pauseparam = &edma_get_pauseparam, -+ .set_pauseparam = &edma_set_pauseparam, -+ .get_eee = &edma_get_eee, -+ .set_eee = &edma_set_eee, -+}; -+ -+/** -+ * edma_set_ethtool_ops - Set ethtool operations -+ * @netdev: Netdevice -+ * -+ * Set ethtool operations. -+ */ -+void edma_set_ethtool_ops(struct net_device *netdev) -+{ -+ netdev->ethtool_ops = &edma_ethtool_ops; -+} ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c -@@ -380,6 +380,7 @@ int edma_port_setup(struct ppe_port *por - netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; - netdev->netdev_ops = &edma_port_netdev_ops; - netdev->gso_max_segs = GSO_MAX_SEGS; -+ edma_set_ethtool_ops(netdev); - - maddr = mac_addr; - if (of_get_mac_address(np, maddr)) diff --git a/target/linux/qualcommbe/patches-6.12/0348-net-ethernet-qualcomm-Add-module-parameters-for-driv.patch b/target/linux/qualcommbe/patches-6.12/0348-net-ethernet-qualcomm-Add-module-parameters-for-driv.patch deleted file mode 100644 index 65eb3c6c20..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0348-net-ethernet-qualcomm-Add-module-parameters-for-driv.patch +++ /dev/null @@ -1,286 +0,0 @@ -From 2ecec7e47e269e05cdd393c34aae51d4866070c6 Mon Sep 17 00:00:00 2001 -From: Pavithra R -Date: Tue, 11 Jun 2024 00:00:46 +0530 -Subject: [PATCH] net: ethernet: qualcomm: Add module parameters for driver - tunings - -Add module params and corresponding functionality for Tx/Rx -mitigation timer/packet count, napi budget and tx requeue stop. - -Change-Id: I1717559c931bba4f355ee06ab89f289818400ca2 -Signed-off-by: Pavithra R ---- - drivers/net/ethernet/qualcomm/ppe/edma.c | 35 +++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.c | 29 +++++++++++++-- - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.h | 21 +++++++++++ - .../net/ethernet/qualcomm/ppe/edma_cfg_tx.c | 29 +++++++++++++-- - .../net/ethernet/qualcomm/ppe/edma_cfg_tx.h | 16 +++++++++ - drivers/net/ethernet/qualcomm/ppe/edma_rx.h | 4 +++ - drivers/net/ethernet/qualcomm/ppe/edma_tx.h | 4 +++ - 7 files changed, 134 insertions(+), 4 deletions(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/edma.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -38,6 +38,38 @@ static int rx_buff_size; - module_param(rx_buff_size, int, 0640); - MODULE_PARM_DESC(rx_buff_size, "Rx Buffer size for Jumbo MRU value (default:0)"); - -+int edma_rx_napi_budget = EDMA_RX_NAPI_WORK_DEF; -+module_param(edma_rx_napi_budget, int, 0444); -+MODULE_PARM_DESC(edma_rx_napi_budget, "Rx NAPI budget (default:128, min:16, max:512)"); -+ -+int edma_tx_napi_budget = EDMA_TX_NAPI_WORK_DEF; -+module_param(edma_tx_napi_budget, int, 0444); -+MODULE_PARM_DESC(edma_tx_napi_budget, "Tx NAPI budget (default:512 for ipq95xx, min:16, max:512)"); -+ -+int edma_rx_mitigation_pkt_cnt = EDMA_RX_MITIGATION_PKT_CNT_DEF; -+module_param(edma_rx_mitigation_pkt_cnt, int, 0444); -+MODULE_PARM_DESC(edma_rx_mitigation_pkt_cnt, -+ "Rx mitigation packet count value (default:16, min:0, max: 256)"); -+ -+s32 edma_rx_mitigation_timer = EDMA_RX_MITIGATION_TIMER_DEF; -+module_param(edma_rx_mitigation_timer, int, 0444); -+MODULE_PARM_DESC(edma_dp_rx_mitigation_timer, -+ "Rx mitigation timer value in microseconds (default:25, min:0, max: 1000)"); -+ -+int edma_tx_mitigation_timer = EDMA_TX_MITIGATION_TIMER_DEF; -+module_param(edma_tx_mitigation_timer, int, 0444); -+MODULE_PARM_DESC(edma_tx_mitigation_timer, -+ "Tx mitigation timer value in microseconds (default:250, min:0, max: 1000)"); -+ -+int edma_tx_mitigation_pkt_cnt = EDMA_TX_MITIGATION_PKT_CNT_DEF; -+module_param(edma_tx_mitigation_pkt_cnt, int, 0444); -+MODULE_PARM_DESC(edma_tx_mitigation_pkt_cnt, -+ "Tx mitigation packet count value (default:16, min:0, max: 256)"); -+ -+static int tx_requeue_stop; -+module_param(tx_requeue_stop, int, 0640); -+MODULE_PARM_DESC(tx_requeue_stop, "Disable Tx requeue function (default:0)"); -+ - /* Priority to multi-queue mapping. */ - static u8 edma_pri_map[PPE_QUEUE_INTER_PRI_NUM] = { - 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7}; -@@ -828,7 +860,10 @@ int edma_setup(struct ppe_device *ppe_de - edma_ctx->hw_info = &ipq9574_hw_info; - edma_ctx->ppe_dev = ppe_dev; - edma_ctx->rx_buf_size = rx_buff_size; -+ - edma_ctx->tx_requeue_stop = false; -+ if (tx_requeue_stop != 0) -+ edma_ctx->tx_requeue_stop = true; - - /* Configure the EDMA common clocks. */ - ret = edma_clock_init(); ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c -@@ -166,6 +166,24 @@ static void edma_cfg_rx_desc_ring_config - reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_RING_SIZE(rxdesc_ring->ring_id); - regmap_write(regmap, reg, data); - -+ /* Validate mitigation timer value */ -+ if (edma_rx_mitigation_timer < EDMA_RX_MITIGATION_TIMER_MIN || -+ edma_rx_mitigation_timer > EDMA_RX_MITIGATION_TIMER_MAX) { -+ pr_err("Invalid Rx mitigation timer configured:%d for ring:%d. Using the default timer value:%d\n", -+ edma_rx_mitigation_timer, rxdesc_ring->ring_id, -+ EDMA_RX_MITIGATION_TIMER_DEF); -+ edma_rx_mitigation_timer = EDMA_RX_MITIGATION_TIMER_DEF; -+ } -+ -+ /* Validate mitigation packet count value */ -+ if (edma_rx_mitigation_pkt_cnt < EDMA_RX_MITIGATION_PKT_CNT_MIN || -+ edma_rx_mitigation_pkt_cnt > EDMA_RX_MITIGATION_PKT_CNT_MAX) { -+ pr_err("Invalid Rx mitigation packet count configured:%d for ring:%d. Using the default packet counter value:%d\n", -+ edma_rx_mitigation_timer, rxdesc_ring->ring_id, -+ EDMA_RX_MITIGATION_PKT_CNT_DEF); -+ edma_rx_mitigation_pkt_cnt = EDMA_RX_MITIGATION_PKT_CNT_DEF; -+ } -+ - /* Configure the Mitigation timer */ - data = EDMA_MICROSEC_TO_TIMER_UNIT(EDMA_RX_MITIGATION_TIMER_DEF, - ppe_dev->clk_rate / MHZ); -@@ -176,7 +194,7 @@ static void edma_cfg_rx_desc_ring_config - regmap_write(regmap, reg, data); - - /* Configure the Mitigation packet count */ -- data = (EDMA_RX_MITIGATION_PKT_CNT_DEF & EDMA_RXDESC_LOW_THRE_MASK) -+ data = (edma_rx_mitigation_pkt_cnt & EDMA_RXDESC_LOW_THRE_MASK) - << EDMA_RXDESC_LOW_THRE_SHIFT; - pr_debug("EDMA Rx mitigation packet count value: %d\n", data); - reg = EDMA_BASE_OFFSET + EDMA_REG_RXDESC_UGT_THRE(rxdesc_ring->ring_id); -@@ -915,6 +933,13 @@ void edma_cfg_rx_napi_add(void) - struct edma_ring_info *rx = hw_info->rx; - u32 i; - -+ if (edma_rx_napi_budget < EDMA_RX_NAPI_WORK_MIN || -+ edma_rx_napi_budget > EDMA_RX_NAPI_WORK_MAX) { -+ pr_err("Incorrect Rx NAPI budget: %d, setting to default: %d", -+ edma_rx_napi_budget, hw_info->napi_budget_rx); -+ edma_rx_napi_budget = hw_info->napi_budget_rx; -+ } -+ - for (i = 0; i < rx->num_rings; i++) { - struct edma_rxdesc_ring *rxdesc_ring = &edma_ctx->rx_rings[i]; - -@@ -923,7 +948,7 @@ void edma_cfg_rx_napi_add(void) - rxdesc_ring->napi_added = true; - } - -- netdev_dbg(edma_ctx->dummy_dev, "Rx NAPI budget: %d\n", hw_info->napi_budget_rx); -+ netdev_dbg(edma_ctx->dummy_dev, "Rx NAPI budget: %d\n", edma_rx_napi_budget); - } - - /** ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h -@@ -5,6 +5,15 @@ - #ifndef __EDMA_CFG_RX__ - #define __EDMA_CFG_RX__ - -+/* Rx default NAPI budget */ -+#define EDMA_RX_NAPI_WORK_DEF 128 -+ -+/* RX minimum NAPI budget */ -+#define EDMA_RX_NAPI_WORK_MIN 16 -+ -+/* Rx maximum NAPI budget */ -+#define EDMA_RX_NAPI_WORK_MAX 512 -+ - /* SKB payload size used in page mode */ - #define EDMA_RX_PAGE_MODE_SKB_SIZE 256 - -@@ -22,9 +31,21 @@ - /* Rx mitigation timer's default value in microseconds */ - #define EDMA_RX_MITIGATION_TIMER_DEF 25 - -+/* Rx mitigation timer's minimum value in microseconds */ -+#define EDMA_RX_MITIGATION_TIMER_MIN 0 -+ -+/* Rx mitigation timer's maximum value in microseconds */ -+#define EDMA_RX_MITIGATION_TIMER_MAX 1000 -+ - /* Rx mitigation packet count's default value */ - #define EDMA_RX_MITIGATION_PKT_CNT_DEF 16 - -+/* Rx mitigation packet count's minimum value */ -+#define EDMA_RX_MITIGATION_PKT_CNT_MIN 0 -+ -+/* Rx mitigation packet count's maximum value */ -+#define EDMA_RX_MITIGATION_PKT_CNT_MAX 256 -+ - /* Default bitmap of cores for RPS to ARM cores */ - #define EDMA_RX_DEFAULT_BITMAP ((1 << EDMA_MAX_CORE) - 1) - ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.c -@@ -170,6 +170,24 @@ static void edma_cfg_txcmpl_ring_configu - reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_CTRL(txcmpl_ring->id); - regmap_write(regmap, reg, EDMA_TXCMPL_RETMODE_OPAQUE); - -+ /* Validate mitigation timer value */ -+ if (edma_tx_mitigation_timer < EDMA_TX_MITIGATION_TIMER_MIN || -+ edma_tx_mitigation_timer > EDMA_TX_MITIGATION_TIMER_MAX) { -+ pr_err("Invalid Tx mitigation timer configured:%d for ring:%d. Using the default timer value:%d\n", -+ edma_tx_mitigation_timer, txcmpl_ring->id, -+ EDMA_TX_MITIGATION_TIMER_DEF); -+ edma_tx_mitigation_timer = EDMA_TX_MITIGATION_TIMER_DEF; -+ } -+ -+ /* Validate mitigation packet count value */ -+ if (edma_tx_mitigation_pkt_cnt < EDMA_TX_MITIGATION_PKT_CNT_MIN || -+ edma_tx_mitigation_pkt_cnt > EDMA_TX_MITIGATION_PKT_CNT_MAX) { -+ pr_err("Invalid Tx mitigation packet count configured:%d for ring:%d. Using the default packet counter value:%d\n", -+ edma_tx_mitigation_timer, txcmpl_ring->id, -+ EDMA_TX_MITIGATION_PKT_CNT_DEF); -+ edma_tx_mitigation_pkt_cnt = EDMA_TX_MITIGATION_PKT_CNT_DEF; -+ } -+ - /* Configure the Mitigation timer. */ - data = EDMA_MICROSEC_TO_TIMER_UNIT(EDMA_TX_MITIGATION_TIMER_DEF, - ppe_dev->clk_rate / MHZ); -@@ -180,7 +198,7 @@ static void edma_cfg_txcmpl_ring_configu - regmap_write(regmap, reg, data); - - /* Configure the Mitigation packet count. */ -- data = (EDMA_TX_MITIGATION_PKT_CNT_DEF & EDMA_TXCMPL_LOW_THRE_MASK) -+ data = (edma_tx_mitigation_pkt_cnt & EDMA_TXCMPL_LOW_THRE_MASK) - << EDMA_TXCMPL_LOW_THRE_SHIFT; - pr_debug("EDMA Tx mitigation packet count value: %d\n", data); - reg = EDMA_BASE_OFFSET + EDMA_REG_TXCMPL_UGT_THRE(txcmpl_ring->id); -@@ -634,6 +652,13 @@ void edma_cfg_tx_napi_add(struct net_dev - struct edma_txcmpl_ring *txcmpl_ring; - u32 i, ring_idx; - -+ if (edma_tx_napi_budget < EDMA_TX_NAPI_WORK_MIN || -+ edma_tx_napi_budget > EDMA_TX_NAPI_WORK_MAX) { -+ pr_err("Incorrect Tx NAPI budget: %d, setting to default: %d", -+ edma_tx_napi_budget, hw_info->napi_budget_tx); -+ edma_tx_napi_budget = hw_info->napi_budget_tx; -+ } -+ - /* Adding tx napi for a interface with each queue. */ - for_each_possible_cpu(i) { - ring_idx = ((port_id - 1) * num_possible_cpus()) + i; -@@ -644,5 +669,5 @@ void edma_cfg_tx_napi_add(struct net_dev - netdev_dbg(netdev, "Napi added for txcmpl ring: %u\n", txcmpl_ring->id); - } - -- netdev_dbg(netdev, "Tx NAPI budget: %d\n", hw_info->napi_budget_tx); -+ netdev_dbg(netdev, "Tx NAPI budget: %d\n", edma_tx_napi_budget); - } ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_tx.h -@@ -5,12 +5,28 @@ - #ifndef __EDMA_CFG_TX__ - #define __EDMA_CFG_TX__ - -+#define EDMA_TX_NAPI_WORK_DEF 512 -+#define EDMA_TX_NAPI_WORK_MIN 16 -+#define EDMA_TX_NAPI_WORK_MAX 512 -+ - /* Tx mitigation timer's default value. */ - #define EDMA_TX_MITIGATION_TIMER_DEF 250 - -+/* Tx mitigation timer's minimum value in microseconds */ -+#define EDMA_TX_MITIGATION_TIMER_MIN 0 -+ -+/* Tx mitigation timer's maximum value in microseconds */ -+#define EDMA_TX_MITIGATION_TIMER_MAX 1000 -+ - /* Tx mitigation packet count default value. */ - #define EDMA_TX_MITIGATION_PKT_CNT_DEF 16 - -+/* Tx mitigation packet count's minimum value */ -+#define EDMA_TX_MITIGATION_PKT_CNT_MIN 0 -+ -+/* Tx mitigation packet count's maximum value */ -+#define EDMA_TX_MITIGATION_PKT_CNT_MAX 256 -+ - void edma_cfg_tx_rings(void); - int edma_cfg_tx_rings_alloc(void); - void edma_cfg_tx_rings_cleanup(void); ---- a/drivers/net/ethernet/qualcomm/ppe/edma_rx.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_rx.h -@@ -281,6 +281,10 @@ struct edma_rxdesc_ring { - struct sk_buff *last; - }; - -+extern int edma_rx_napi_budget; -+extern int edma_rx_mitigation_timer; -+extern int edma_rx_mitigation_pkt_cnt; -+ - irqreturn_t edma_rx_handle_irq(int irq, void *ctx); - int edma_rx_alloc_buffer(struct edma_rxfill_ring *rxfill_ring, int alloc_count); - int edma_rx_napi_poll(struct napi_struct *napi, int budget); ---- a/drivers/net/ethernet/qualcomm/ppe/edma_tx.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_tx.h -@@ -288,6 +288,10 @@ struct edma_txcmpl_ring { - bool napi_added; - }; - -+extern int edma_tx_napi_budget; -+extern int edma_tx_mitigation_timer; -+extern int edma_tx_mitigation_pkt_cnt; -+ - enum edma_tx_status edma_tx_ring_xmit(struct net_device *netdev, - struct sk_buff *skb, - struct edma_txdesc_ring *txdesc_ring, diff --git a/target/linux/qualcommbe/patches-6.12/0349-net-ethernet-qualcomm-Add-sysctl-for-RPS-bitmap.patch b/target/linux/qualcommbe/patches-6.12/0349-net-ethernet-qualcomm-Add-sysctl-for-RPS-bitmap.patch deleted file mode 100644 index c6970015d7..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0349-net-ethernet-qualcomm-Add-sysctl-for-RPS-bitmap.patch +++ /dev/null @@ -1,145 +0,0 @@ -From dcac735a715c13a817d65ae371564cf2793330b2 Mon Sep 17 00:00:00 2001 -From: Pavithra R -Date: Tue, 11 Jun 2024 01:43:22 +0530 -Subject: [PATCH] net: ethernet: qualcomm: Add sysctl for RPS bitmap - -Add sysctl to configure RPS bitmap for EDMA receive. -This bitmap is used to configure the set of ARM cores -used to receive packets from EDMA. - -Change-Id: Ie0e7d5971db93ea1494608a9e79c4abb13ce69b6 -Signed-off-by: Pavithra R -Alex G: Use **const** ctl_table argument for .proc_handler -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/ppe/edma.c | 23 ++++++++++++++++ - drivers/net/ethernet/qualcomm/ppe/edma.h | 2 ++ - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.c | 27 +++++++++++++++++++ - .../net/ethernet/qualcomm/ppe/edma_cfg_rx.h | 6 ++++- - 4 files changed, 57 insertions(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/edma.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.c -@@ -797,6 +797,11 @@ void edma_destroy(struct ppe_device *ppe - struct edma_ring_info *rx = hw_info->rx; - u32 i; - -+ if (edma_ctx->rx_rps_ctl_table_hdr) { -+ unregister_sysctl_table(edma_ctx->rx_rps_ctl_table_hdr); -+ edma_ctx->rx_rps_ctl_table_hdr = NULL; -+ } -+ - /* Disable interrupts. */ - for (i = 1; i <= hw_info->max_ports; i++) - edma_cfg_tx_disable_interrupts(i); -@@ -840,6 +845,17 @@ void edma_destroy(struct ppe_device *ppe - kfree(edma_ctx->netdev_arr); - } - -+/* EDMA Rx RPS core sysctl table */ -+static struct ctl_table edma_rx_rps_core_table[] = { -+ { -+ .procname = "rps_bitmap_cores", -+ .data = &edma_cfg_rx_rps_bitmap_cores, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = edma_cfg_rx_rps_bitmap -+ }, -+}; -+ - /** - * edma_setup - EDMA Setup. - * @ppe_dev: PPE device -@@ -865,6 +881,13 @@ int edma_setup(struct ppe_device *ppe_de - if (tx_requeue_stop != 0) - edma_ctx->tx_requeue_stop = true; - -+ edma_ctx->rx_rps_ctl_table_hdr = register_sysctl("net/edma", -+ edma_rx_rps_core_table); -+ if (!edma_ctx->rx_rps_ctl_table_hdr) { -+ pr_err("Rx rps sysctl table configuration failed\n"); -+ return -EINVAL; -+ } -+ - /* Configure the EDMA common clocks. */ - ret = edma_clock_init(); - if (ret) { ---- a/drivers/net/ethernet/qualcomm/ppe/edma.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma.h -@@ -132,6 +132,7 @@ struct edma_intr_info { - * @tx_rings: Tx Descriptor Ring, SW is producer - * @txcmpl_rings: Tx complete Ring, SW is consumer - * @err_stats: Per CPU error statistics -+ * @rx_rps_ctl_table_hdr: Rx RPS sysctl table - * @rx_page_mode: Page mode enabled or disabled - * @rx_buf_size: Rx buffer size for Jumbo MRU - * @tx_requeue_stop: Tx requeue stop enabled or disabled -@@ -147,6 +148,7 @@ struct edma_context { - struct edma_txdesc_ring *tx_rings; - struct edma_txcmpl_ring *txcmpl_rings; - struct edma_err_stats __percpu *err_stats; -+ struct ctl_table_header *rx_rps_ctl_table_hdr; - u32 rx_page_mode; - u32 rx_buf_size; - bool tx_requeue_stop; ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.c -@@ -43,6 +43,8 @@ static u32 edma_rx_ring_queue_map[][EDMA - { 6, 14, 22, 30 }, - { 7, 15, 23, 31 }}; - -+u32 edma_cfg_rx_rps_bitmap_cores = EDMA_RX_DEFAULT_BITMAP; -+ - static int edma_cfg_rx_desc_rings_reset_queue_mapping(void) - { - struct edma_hw_info *hw_info = edma_ctx->hw_info; -@@ -987,3 +989,28 @@ int edma_cfg_rx_rps_hash_map(void) - - return 0; - } -+ -+/* Configure RPS hash mapping based on bitmap */ -+int edma_cfg_rx_rps_bitmap(const struct ctl_table *table, int write, -+ void *buffer, size_t *lenp, loff_t *ppos) -+{ -+ int ret; -+ -+ ret = proc_dointvec(table, write, buffer, lenp, ppos); -+ -+ if (!write) -+ return ret; -+ -+ if (!edma_cfg_rx_rps_bitmap_cores || -+ edma_cfg_rx_rps_bitmap_cores > EDMA_RX_DEFAULT_BITMAP) { -+ pr_warn("Incorrect CPU bitmap: %x. Setting it to default value: %d", -+ edma_cfg_rx_rps_bitmap_cores, EDMA_RX_DEFAULT_BITMAP); -+ edma_cfg_rx_rps_bitmap_cores = EDMA_RX_DEFAULT_BITMAP; -+ } -+ -+ ret = edma_cfg_rx_rps_hash_map(); -+ -+ pr_info("EDMA RPS bitmap value: %d\n", edma_cfg_rx_rps_bitmap_cores); -+ -+ return ret; -+} ---- a/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_cfg_rx.h -@@ -49,6 +49,8 @@ - /* Default bitmap of cores for RPS to ARM cores */ - #define EDMA_RX_DEFAULT_BITMAP ((1 << EDMA_MAX_CORE) - 1) - -+extern u32 edma_cfg_rx_rps_bitmap_cores; -+ - int edma_cfg_rx_rings(void); - int edma_cfg_rx_rings_alloc(void); - void edma_cfg_rx_ring_mappings(void); -@@ -64,6 +66,8 @@ void edma_cfg_rx_rings_enable(void); - void edma_cfg_rx_rings_disable(void); - void edma_cfg_rx_buff_size_setup(void); - int edma_cfg_rx_rps_hash_map(void); --int edma_cfg_rx_rps(struct ctl_table *table, int write, -+int edma_cfg_rx_rps(const struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos); -+int edma_cfg_rx_rps_bitmap(const struct ctl_table *table, int write, -+ void *buffer, size_t *lenp, loff_t *ppos); - #endif diff --git a/target/linux/qualcommbe/patches-6.12/0350-net-ethernet-qualcomm-Add-support-for-label-property.patch b/target/linux/qualcommbe/patches-6.12/0350-net-ethernet-qualcomm-Add-support-for-label-property.patch deleted file mode 100644 index 79af169c8e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0350-net-ethernet-qualcomm-Add-support-for-label-property.patch +++ /dev/null @@ -1,48 +0,0 @@ -From a809433c9b6a418dd886f12a5dcb3376f73bf2a7 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 4 Dec 2024 01:37:05 +0100 -Subject: [PATCH] net: ethernet: qualcomm: Add support for label property for - EDMA port - -Add support for label property for EDMA port. This is useful to define -custom name in DTS for specific ethernet port instead of assigning a -dynamic name at runtime. - -This also improve the log output by using modern APIs. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/qualcomm/ppe/edma_port.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - ---- a/drivers/net/ethernet/qualcomm/ppe/edma_port.c -+++ b/drivers/net/ethernet/qualcomm/ppe/edma_port.c -@@ -355,13 +355,25 @@ int edma_port_setup(struct ppe_port *por - int port_id = port->port_id; - struct net_device *netdev; - u8 mac_addr[ETH_ALEN]; -+ const char *name; -+ int assign_type; - int ret = 0; - u8 *maddr; - -- netdev = alloc_etherdev_mqs(sizeof(struct edma_port_priv), -- EDMA_NETDEV_QUEUE_NUM, EDMA_NETDEV_QUEUE_NUM); -+ name = of_get_property(np, "label", NULL); -+ if (name) { -+ assign_type = NET_NAME_PREDICTABLE; -+ } else { -+ name = "eth%d"; -+ assign_type = NET_NAME_ENUM; -+ } -+ -+ netdev = alloc_netdev_mqs(sizeof(struct edma_port_priv), -+ name, assign_type, -+ ether_setup, -+ EDMA_NETDEV_QUEUE_NUM, EDMA_NETDEV_QUEUE_NUM); - if (!netdev) { -- pr_err("alloc_etherdev() failed\n"); -+ dev_err(ppe_dev->dev, "alloc_netdev_mqs() failed\n"); - return -ENOMEM; - } - diff --git a/target/linux/qualcommbe/patches-6.12/0351-net-ethernet-qualcomm-ppe-Fix-unmet-dependency-with-.patch b/target/linux/qualcommbe/patches-6.12/0351-net-ethernet-qualcomm-ppe-Fix-unmet-dependency-with-.patch deleted file mode 100644 index a0d15cf2a0..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0351-net-ethernet-qualcomm-ppe-Fix-unmet-dependency-with-.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 9c4ad75f17788a64c1e37d0b9e19ca157e01c80a Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 9 Dec 2024 18:19:06 +0100 -Subject: [PATCH] net: ethernet: qualcomm: ppe: Fix unmet dependency with - QCOM_PPE - -Fix unmet dependency with QCOM_PPE on selecting SFP. - -WARNING: unmet direct dependencies detected for SFP - Depends on [m]: NETDEVICES [=y] && PHYLIB [=y] && I2C [=y] && PHYLINK [=y] && (HWMON [=m] || HWMON [=m]=n [=n]) - Selected by [y]: - - QCOM_PPE [=y] && NETDEVICES [=y] && ETHERNET [=y] && NET_VENDOR_QUALCOMM [=y] && HAS_IOMEM [=y] && OF [=y] && COMMON_CLK [=y] - -This permit correct compilation of the modules with SFP enabled. - -Signed-off-by: Christian Marangi ---- - drivers/net/ethernet/qualcomm/Kconfig | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/Kconfig -+++ b/drivers/net/ethernet/qualcomm/Kconfig -@@ -68,7 +68,6 @@ config QCOM_PPE - select REGMAP_MMIO - select PHYLINK - select PCS_QCOM_IPQ_UNIPHY -- select SFP - help - This driver supports the Qualcomm Technologies, Inc. packet - process engine (PPE) available with IPQ SoC. The PPE includes diff --git a/target/linux/qualcommbe/patches-6.12/0352-net-ethernet-qualcomm-ppe-select-correct-PCS-depende.patch b/target/linux/qualcommbe/patches-6.12/0352-net-ethernet-qualcomm-ppe-select-correct-PCS-depende.patch deleted file mode 100644 index 3893c5cd8d..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0352-net-ethernet-qualcomm-ppe-select-correct-PCS-depende.patch +++ /dev/null @@ -1,24 +0,0 @@ -From ac41b401d274a4004027fa4000d801cd28c51f4c Mon Sep 17 00:00:00 2001 -From: Alexandru Gagniuc -Date: Tue, 13 May 2025 13:41:37 -0500 -Subject: [PATCH] net: ethernet: qualcomm: ppe: select correct PCS dependency - -The config symbol for the PCS driver has changed to PCS_QCOM_IPQ9574, -since the original submission. Update Kconfig accordingly. - -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/ethernet/qualcomm/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/ethernet/qualcomm/Kconfig -+++ b/drivers/net/ethernet/qualcomm/Kconfig -@@ -67,7 +67,7 @@ config QCOM_PPE - depends on COMMON_CLK - select REGMAP_MMIO - select PHYLINK -- select PCS_QCOM_IPQ_UNIPHY -+ select PCS_QCOM_IPQ9574 - help - This driver supports the Qualcomm Technologies, Inc. packet - process engine (PPE) available with IPQ SoC. The PPE includes diff --git a/target/linux/qualcommbe/patches-6.12/0353-arm64-dts-qcom-Add-IPQ9574-PPE-base-device-node.patch b/target/linux/qualcommbe/patches-6.12/0353-arm64-dts-qcom-Add-IPQ9574-PPE-base-device-node.patch deleted file mode 100644 index 640a2a9f02..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0353-arm64-dts-qcom-Add-IPQ9574-PPE-base-device-node.patch +++ /dev/null @@ -1,72 +0,0 @@ -From bbf706ecfd4295d73c8217d5220573dd51d7a081 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Fri, 1 Mar 2024 14:46:45 +0800 -Subject: [PATCH] arm64: dts: qcom: Add IPQ9574 PPE base device node - -PPE is the packet process engine on the Qualcomm IPQ platform, -which is connected with the external switch or PHY device via -the UNIPHY (PCS). - -Change-Id: I254bd48c218aa4eab54f697a2ad149f5a93b682c -Signed-off-by: Luo Jie -Alex G: Add "qcom_ppe" label to PPE node -Signed-off-by: Alexandru Gagniuc ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 39 +++++++++++++++++++++++++++ - 1 file changed, 39 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - - / { -@@ -1271,6 +1272,44 @@ - #interconnect-cells = <1>; - }; - -+ qcom_ppe: ethernet@3a000000 { -+ compatible = "qcom,ipq9574-ppe"; -+ reg = <0x3a000000 0xbef800>; -+ ranges; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ clocks = <&nsscc NSS_CC_PPE_SWITCH_CLK>, -+ <&nsscc NSS_CC_PPE_SWITCH_CFG_CLK>, -+ <&nsscc NSS_CC_PPE_SWITCH_IPE_CLK>, -+ <&nsscc NSS_CC_PPE_SWITCH_BTQ_CLK>; -+ clock-names = "ppe", -+ "ppe_cfg", -+ "ppe_ipe", -+ "ppe_btq"; -+ resets = <&nsscc PPE_FULL_RESET>; -+ interconnects = <&nsscc MASTER_NSSNOC_PPE -+ &nsscc SLAVE_NSSNOC_PPE>, -+ <&nsscc MASTER_NSSNOC_PPE_CFG -+ &nsscc SLAVE_NSSNOC_PPE_CFG>, -+ <&gcc MASTER_NSSNOC_QOSGEN_REF -+ &gcc SLAVE_NSSNOC_QOSGEN_REF>, -+ <&gcc MASTER_NSSNOC_TIMEOUT_REF -+ &gcc SLAVE_NSSNOC_TIMEOUT_REF>, -+ <&gcc MASTER_MEM_NOC_NSSNOC -+ &gcc SLAVE_MEM_NOC_NSSNOC>, -+ <&gcc MASTER_NSSNOC_MEMNOC -+ &gcc SLAVE_NSSNOC_MEMNOC>, -+ <&gcc MASTER_NSSNOC_MEM_NOC_1 -+ &gcc SLAVE_NSSNOC_MEM_NOC_1>; -+ interconnect-names = "ppe", -+ "ppe_cfg", -+ "qos_gen", -+ "timeout_ref", -+ "nssnoc_memnoc", -+ "memnoc_nssnoc", -+ "memnoc_nssnoc_1"; -+ }; -+ - pcs0: ethernet-pcs@7a00000 { - compatible = "qcom,ipq9574-pcs"; - reg = <0x7a00000 0x10000>; diff --git a/target/linux/qualcommbe/patches-6.12/0354-arm64-dts-qcom-Add-EDMA-node-for-IPQ9574.patch b/target/linux/qualcommbe/patches-6.12/0354-arm64-dts-qcom-Add-EDMA-node-for-IPQ9574.patch deleted file mode 100644 index f93ed0c37e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0354-arm64-dts-qcom-Add-EDMA-node-for-IPQ9574.patch +++ /dev/null @@ -1,91 +0,0 @@ -From bd50babc7db2a35d98236a0386173dccd6c6374b Mon Sep 17 00:00:00 2001 -From: Pavithra R -Date: Wed, 6 Mar 2024 22:29:41 +0530 -Subject: [PATCH] arm64: dts: qcom: Add EDMA node for IPQ9574 - -Add EDMA (Ethernet DMA) device tree node for IPQ9574 to -enable ethernet support. - -Change-Id: I87d7c50f2485c8670948dce305000337f6499f8b -Signed-off-by: Pavithra R ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 68 +++++++++++++++++++++++++++ - 1 file changed, 68 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -1308,6 +1308,74 @@ - "nssnoc_memnoc", - "memnoc_nssnoc", - "memnoc_nssnoc_1"; -+ -+ edma { -+ compatible = "qcom,ipq9574-edma"; -+ clocks = <&nsscc NSS_CC_PPE_EDMA_CLK>, -+ <&nsscc NSS_CC_PPE_EDMA_CFG_CLK>; -+ clock-names = "edma", -+ "edma-cfg"; -+ resets = <&nsscc EDMA_HW_RESET>; -+ reset-names = "edma_rst"; -+ interrupts = , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ , -+ ; -+ interrupt-names = "edma_txcmpl_8", -+ "edma_txcmpl_9", -+ "edma_txcmpl_10", -+ "edma_txcmpl_11", -+ "edma_txcmpl_12", -+ "edma_txcmpl_13", -+ "edma_txcmpl_14", -+ "edma_txcmpl_15", -+ "edma_txcmpl_16", -+ "edma_txcmpl_17", -+ "edma_txcmpl_18", -+ "edma_txcmpl_19", -+ "edma_txcmpl_20", -+ "edma_txcmpl_21", -+ "edma_txcmpl_22", -+ "edma_txcmpl_23", -+ "edma_txcmpl_24", -+ "edma_txcmpl_25", -+ "edma_txcmpl_26", -+ "edma_txcmpl_27", -+ "edma_txcmpl_28", -+ "edma_txcmpl_29", -+ "edma_txcmpl_30", -+ "edma_txcmpl_31", -+ "edma_rxdesc_20", -+ "edma_rxdesc_21", -+ "edma_rxdesc_22", -+ "edma_rxdesc_23", -+ "edma_misc"; -+ }; - }; - - pcs0: ethernet-pcs@7a00000 { diff --git a/target/linux/qualcommbe/patches-6.12/0355-arm64-dts-qcom-Add-IPQ9574-RDP433-port-node.patch b/target/linux/qualcommbe/patches-6.12/0355-arm64-dts-qcom-Add-IPQ9574-RDP433-port-node.patch deleted file mode 100644 index 83f0e24117..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0355-arm64-dts-qcom-Add-IPQ9574-RDP433-port-node.patch +++ /dev/null @@ -1,197 +0,0 @@ -From 001b663ecc5f838dac143623badae0e472749d8a Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Tue, 14 May 2024 10:53:27 +0800 -Subject: [PATCH] arm64: dts: qcom: Add IPQ9574 RDP433 port node - -There are 6 PPE MAC ports available on RDP433. The port1-port4 are -connected with QCA8075 QUAD PHYs through UNIPHY0 PCS channel0-channel3. -The port5 is connected with Aquantia PHY through UNIPHY1 PCS channel0 -and the port6 is connected with Aquantia PHY through UNIPHY2 PCS -channel0. - -Change-Id: Ic16efdef2fe2cff7b1e80245619c0f82afb24cb9 -Signed-off-by: Lei Wei ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 167 ++++++++++++++++++++ - 1 file changed, 167 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -@@ -55,6 +55,46 @@ - status = "okay"; - }; - -+&mdio { -+ reset-gpios = <&tlmm 60 GPIO_ACTIVE_LOW>; -+ clock-frequency = <6250000>; -+ status = "okay"; -+ -+ ethernet-phy-package@0 { -+ compatible = "qcom,qca8075-package"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x10>; -+ qcom,package-mode = "qsgmii"; -+ -+ phy0: ethernet-phy@10 { -+ reg = <0x10>; -+ }; -+ -+ phy1: ethernet-phy@11 { -+ reg = <0x11>; -+ }; -+ -+ phy2: ethernet-phy@12 { -+ reg = <0x12>; -+ }; -+ -+ phy3: ethernet-phy@13 { -+ reg = <0x13>; -+ }; -+ }; -+ -+ phy4: ethernet-phy@8 { -+ compatible ="ethernet-phy-ieee802.3-c45"; -+ reg = <8>; -+ }; -+ -+ phy5: ethernet-phy@0 { -+ compatible ="ethernet-phy-ieee802.3-c45"; -+ reg = <0>; -+ }; -+}; -+ - &tlmm { - - pcie1_default: pcie1-default-state { -@@ -161,3 +201,130 @@ - }; - }; - }; -+ -+&qcom_ppe { -+ ethernet-ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@1 { -+ reg = <1>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy0>; -+ pcs-handle = <&pcs0_ch0>; -+ clocks = <&nsscc NSS_CC_PORT1_MAC_CLK>, -+ <&nsscc NSS_CC_PORT1_RX_CLK>, -+ <&nsscc NSS_CC_PORT1_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT1_MAC_ARES>, -+ <&nsscc PORT1_RX_ARES>, -+ <&nsscc PORT1_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy1>; -+ pcs-handle = <&pcs0_ch1>; -+ clocks = <&nsscc NSS_CC_PORT2_MAC_CLK>, -+ <&nsscc NSS_CC_PORT2_RX_CLK>, -+ <&nsscc NSS_CC_PORT2_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT2_MAC_ARES>, -+ <&nsscc PORT2_RX_ARES>, -+ <&nsscc PORT2_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy2>; -+ pcs-handle = <&pcs0_ch2>; -+ clocks = <&nsscc NSS_CC_PORT3_MAC_CLK>, -+ <&nsscc NSS_CC_PORT3_RX_CLK>, -+ <&nsscc NSS_CC_PORT3_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT3_MAC_ARES>, -+ <&nsscc PORT3_RX_ARES>, -+ <&nsscc PORT3_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ phy-mode = "qsgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy3>; -+ pcs-handle = <&pcs0_ch3>; -+ clocks = <&nsscc NSS_CC_PORT4_MAC_CLK>, -+ <&nsscc NSS_CC_PORT4_RX_CLK>, -+ <&nsscc NSS_CC_PORT4_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT4_MAC_ARES>, -+ <&nsscc PORT4_RX_ARES>, -+ <&nsscc PORT4_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@5 { -+ reg = <5>; -+ phy-mode = "usxgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy4>; -+ pcs-handle = <&pcs1_ch0>; -+ clocks = <&nsscc NSS_CC_PORT5_MAC_CLK>, -+ <&nsscc NSS_CC_PORT5_RX_CLK>, -+ <&nsscc NSS_CC_PORT5_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT5_MAC_ARES>, -+ <&nsscc PORT5_RX_ARES>, -+ <&nsscc PORT5_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ phy-mode = "usxgmii"; -+ managed = "in-band-status"; -+ phy-handle = <&phy5>; -+ pcs-handle = <&pcs2_ch0>; -+ clocks = <&nsscc NSS_CC_PORT6_MAC_CLK>, -+ <&nsscc NSS_CC_PORT6_RX_CLK>, -+ <&nsscc NSS_CC_PORT6_TX_CLK>; -+ clock-names = "mac", -+ "rx", -+ "tx"; -+ resets = <&nsscc PORT6_MAC_ARES>, -+ <&nsscc PORT6_RX_ARES>, -+ <&nsscc PORT6_TX_ARES>; -+ reset-names = "mac", -+ "rx", -+ "tx"; -+ }; -+ }; -+}; diff --git a/target/linux/qualcommbe/patches-6.12/0356-arm64-dts-qcom-add-AQR-NVMEM-node-for-IPQ9574-RDP433.patch b/target/linux/qualcommbe/patches-6.12/0356-arm64-dts-qcom-add-AQR-NVMEM-node-for-IPQ9574-RDP433.patch deleted file mode 100644 index e508bad9a6..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0356-arm64-dts-qcom-add-AQR-NVMEM-node-for-IPQ9574-RDP433.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 30b751f5984e295f0b5e7a2308b6103fae3322d2 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 9 Dec 2024 18:10:43 +0100 -Subject: [PATCH] arm64: dts: qcom: add AQR NVMEM node for IPQ9574 RDP433 board - -Add Aquantia NVMEM node for IPQ9574 RDP433 board to load the firmware -for the Aquantia PHY. - -Signed-off-by: Christian Marangi ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -@@ -87,11 +87,17 @@ - phy4: ethernet-phy@8 { - compatible ="ethernet-phy-ieee802.3-c45"; - reg = <8>; -+ -+ nvmem-cells = <&aqr_fw>; -+ nvmem-cell-names = "firmware"; - }; - - phy5: ethernet-phy@0 { - compatible ="ethernet-phy-ieee802.3-c45"; - reg = <0>; -+ -+ nvmem-cells = <&aqr_fw>; -+ nvmem-cell-names = "firmware"; - }; - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0357-arm64-dts-qcom-Add-label-to-EDMA-port-for-IPQ9574-RD.patch b/target/linux/qualcommbe/patches-6.12/0357-arm64-dts-qcom-Add-label-to-EDMA-port-for-IPQ9574-RD.patch deleted file mode 100644 index 950c9faf3c..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0357-arm64-dts-qcom-Add-label-to-EDMA-port-for-IPQ9574-RD.patch +++ /dev/null @@ -1,62 +0,0 @@ -From b297d12d434191845cf8ae359466dcd8312ed21d Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Wed, 4 Dec 2024 01:49:09 +0100 -Subject: [PATCH] arm64: dts: qcom: Add label to EDMA port for IPQ9574 RDP433 - -Add label to EDMA port for IPQ9574 RDP433 board. - -Signed-off-by: Christian Marangi ---- - arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -+++ b/arch/arm64/boot/dts/qcom/ipq9574-rdp433.dts -@@ -217,6 +217,7 @@ - reg = <1>; - phy-mode = "qsgmii"; - managed = "in-band-status"; -+ label = "lan1"; - phy-handle = <&phy0>; - pcs-handle = <&pcs0_ch0>; - clocks = <&nsscc NSS_CC_PORT1_MAC_CLK>, -@@ -237,6 +238,7 @@ - reg = <2>; - phy-mode = "qsgmii"; - managed = "in-band-status"; -+ label = "lan2"; - phy-handle = <&phy1>; - pcs-handle = <&pcs0_ch1>; - clocks = <&nsscc NSS_CC_PORT2_MAC_CLK>, -@@ -257,6 +259,7 @@ - reg = <3>; - phy-mode = "qsgmii"; - managed = "in-band-status"; -+ label = "lan3"; - phy-handle = <&phy2>; - pcs-handle = <&pcs0_ch2>; - clocks = <&nsscc NSS_CC_PORT3_MAC_CLK>, -@@ -277,6 +280,7 @@ - reg = <4>; - phy-mode = "qsgmii"; - managed = "in-band-status"; -+ label = "lan4"; - phy-handle = <&phy3>; - pcs-handle = <&pcs0_ch3>; - clocks = <&nsscc NSS_CC_PORT4_MAC_CLK>, -@@ -297,6 +301,7 @@ - reg = <5>; - phy-mode = "usxgmii"; - managed = "in-band-status"; -+ label = "lan5"; - phy-handle = <&phy4>; - pcs-handle = <&pcs1_ch0>; - clocks = <&nsscc NSS_CC_PORT5_MAC_CLK>, -@@ -317,6 +322,7 @@ - reg = <6>; - phy-mode = "usxgmii"; - managed = "in-band-status"; -+ label = "wan"; - phy-handle = <&phy5>; - pcs-handle = <&pcs2_ch0>; - clocks = <&nsscc NSS_CC_PORT6_MAC_CLK>, diff --git a/target/linux/qualcommbe/patches-6.12/0358-clk-qcom-nsscc-Attach-required-NSSNOC-clock-to-PM-do.patch b/target/linux/qualcommbe/patches-6.12/0358-clk-qcom-nsscc-Attach-required-NSSNOC-clock-to-PM-do.patch deleted file mode 100644 index 372572a24e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0358-clk-qcom-nsscc-Attach-required-NSSNOC-clock-to-PM-do.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 6417cb20e854194a845d4ab092b92fd753c0e405 Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 30 Jan 2025 16:11:14 +0100 -Subject: [PATCH] clk: qcom: nsscc: Attach required NSSNOC clock to PM domain - -There is currently a problem with ICC clock disabling the NSSNOC clock -as there isn't any user for them on calling sync_state. -This cause the kernel to stall if NSS is enabled and reboot with the watchdog. - -This is caused by the fact that the NSSNOC clock nsscc, snoc and snoc_1 -are actually required to make the NSS work and make the system continue -booting. - -To attach these clock, setup pm-clk in nsscc and setup the correct -resume/suspend OPs. - -With this change, the clock gets correctly attached and are not disabled -when ICC call the sync_state. - -Suggested-by: Dmitry Baryshkov -Signed-off-by: Christian Marangi -Alex G: Retrieve clocks by name rather than index. -Signed-off-by: Alexandru Gagniuc ---- - drivers/clk/qcom/nsscc-ipq9574.c | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - ---- a/drivers/clk/qcom/nsscc-ipq9574.c -+++ b/drivers/clk/qcom/nsscc-ipq9574.c -@@ -3060,6 +3060,7 @@ MODULE_DEVICE_TABLE(of, nss_cc_ipq9574_m - - static int nss_cc_ipq9574_probe(struct platform_device *pdev) - { -+ struct device *dev = &pdev->dev; - struct regmap *regmap; - int ret; - -@@ -3075,6 +3076,18 @@ static int nss_cc_ipq9574_probe(struct p - if (ret) - return dev_err_probe(&pdev->dev, ret, "Fail to add bus clock\n"); - -+ ret = pm_clk_add(&pdev->dev, "nssnoc"); -+ if (ret) -+ return dev_err_probe(dev, ret,"failed to acquire nssnoc clock\n"); -+ -+ ret = pm_clk_add(&pdev->dev, "snoc"); -+ if (ret) -+ return dev_err_probe(dev, ret,"failed to acquire snoc clock\n"); -+ -+ ret = pm_clk_add(&pdev->dev, "snoc_1"); -+ if (ret) -+ return dev_err_probe(dev, ret,"failed to acquire snoc_1 clock\n"); -+ - ret = pm_runtime_resume_and_get(&pdev->dev); - if (ret) - return dev_err_probe(&pdev->dev, ret, "Fail to resume\n"); -@@ -3089,8 +3102,16 @@ static int nss_cc_ipq9574_probe(struct p - clk_alpha_pll_configure(&ubi32_pll_main, regmap, &ubi32_pll_config); - - ret = qcom_cc_really_probe(&pdev->dev, &nss_cc_ipq9574_desc, regmap); -+ if (ret) -+ goto err_put_pm; -+ - pm_runtime_put(&pdev->dev); - -+ return 0; -+ -+err_put_pm: -+ pm_runtime_put_sync(dev); -+ - return ret; - } - diff --git a/target/linux/qualcommbe/patches-6.12/0359-arm64-dts-qcom-ipq9574-add-NSSNOC-clock-to-nss-node.patch b/target/linux/qualcommbe/patches-6.12/0359-arm64-dts-qcom-ipq9574-add-NSSNOC-clock-to-nss-node.patch deleted file mode 100644 index c32f077a01..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0359-arm64-dts-qcom-ipq9574-add-NSSNOC-clock-to-nss-node.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 372bbae100ffe14908bfd8448143c6cdbea17e8d Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Thu, 30 Jan 2025 16:23:03 +0100 -Subject: [PATCH] arm64: dts: qcom: ipq9574: add NSSNOC clock to nss node - -Add NSSNOC clock to nss node to attach the clock with PM clock and fix -the boot stall after ICC sync_state. - -Signed-off-by: Christian Marangi -Alex G: Do not remove GCC_NSSCC_CLK ("bus") clock - Add clock-names for the new clocks -Signed-off-by: Alexandru Gagniuc ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -1255,7 +1255,10 @@ - <&pcs1 1>, - <&pcs2 0>, - <&pcs2 1>, -- <&gcc GCC_NSSCC_CLK>; -+ <&gcc GCC_NSSCC_CLK>, -+ <&gcc GCC_NSSNOC_NSSCC_CLK>, -+ <&gcc GCC_NSSNOC_SNOC_CLK>, -+ <&gcc GCC_NSSNOC_SNOC_1_CLK>; - clock-names = "xo", - "nss_1200", - "ppe_353", -@@ -1266,7 +1269,10 @@ - "uniphy1_tx", - "uniphy2_rx", - "uniphy2_tx", -- "bus"; -+ "bus", -+ "nssnoc", -+ "snoc", -+ "snoc_1"; - #clock-cells = <1>; - #reset-cells = <1>; - #interconnect-cells = <1>; diff --git a/target/linux/qualcommbe/patches-6.12/0360-clk-qcom-nsscc-ipq9574-fix-port5-clock-config.patch b/target/linux/qualcommbe/patches-6.12/0360-clk-qcom-nsscc-ipq9574-fix-port5-clock-config.patch deleted file mode 100644 index 725079c810..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0360-clk-qcom-nsscc-ipq9574-fix-port5-clock-config.patch +++ /dev/null @@ -1,46 +0,0 @@ -From fa691ff57c72a8f0bfeff1a9e86ae2d78765b0da Mon Sep 17 00:00:00 2001 -From: Mantas Pucka -Date: Mon, 31 Mar 2025 15:39:59 +0300 -Subject: [PATCH] clk: qcom: nsscc-ipq9574: fix port5 clock config - -Currently there is no configuration to derive 25/125MHz port5 clock -from uniphy1 running at 125MHz. This is needed for SGMII mode when -port5 is using uniphy1. - -Fix this by adding option such clock config option. - -Signed-off-by: Mantas Pucka ---- - drivers/clk/qcom/nsscc-ipq9574.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/clk/qcom/nsscc-ipq9574.c -+++ b/drivers/clk/qcom/nsscc-ipq9574.c -@@ -383,11 +383,13 @@ static const struct freq_multi_tbl ftbl_ - - static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_25[] = { - C(P_UNIPHY1_NSS_RX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY1_NSS_RX_CLK, 5, 0, 0), - C(P_UNIPHY0_NSS_RX_CLK, 5, 0, 0), - }; - - static const struct freq_conf ftbl_nss_cc_port5_rx_clk_src_125[] = { - C(P_UNIPHY1_NSS_RX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY1_NSS_RX_CLK, 1, 0, 0), - C(P_UNIPHY0_NSS_RX_CLK, 1, 0, 0), - }; - -@@ -408,11 +410,13 @@ static const struct freq_multi_tbl ftbl_ - - static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_25[] = { - C(P_UNIPHY1_NSS_TX_CLK, 12.5, 0, 0), -+ C(P_UNIPHY1_NSS_TX_CLK, 5, 0, 0), - C(P_UNIPHY0_NSS_TX_CLK, 5, 0, 0), - }; - - static const struct freq_conf ftbl_nss_cc_port5_tx_clk_src_125[] = { - C(P_UNIPHY1_NSS_TX_CLK, 2.5, 0, 0), -+ C(P_UNIPHY1_NSS_TX_CLK, 1, 0, 0), - C(P_UNIPHY0_NSS_TX_CLK, 1, 0, 0), - }; - diff --git a/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch b/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch deleted file mode 100644 index 5bdf3e9299..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 432c2a2da1e0f4a8e2c0fea191361832a7f90f36 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Wed, 6 Mar 2024 17:40:52 +0800 -Subject: [PATCH] net: pcs: Add 10GBASER interface mode support to IPQ UNIPHY - PCS driver - -10GBASER mode is used when PCS connects with a 10G SFP module. - -Change-Id: Ifc3c3bb23811807a9b34e88771aab2c830c2327c -Signed-off-by: Lei Wei -Alex G: Use regmap to read/write registers - Remove xpcs_reset deassert logic (to be implemented later) -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 47 ++++++++++++++++++++++++++++++ - 1 file changed, 47 insertions(+) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -55,6 +55,9 @@ - FIELD_PREP(GENMASK(9, 2), \ - FIELD_GET(XPCS_INDIRECT_ADDR_L, reg))) - -+#define XPCS_KR_STS 0x30020 -+#define XPCS_KR_LINK_STS BIT(12) -+ - #define XPCS_DIG_CTRL 0x38000 - #define XPCS_USXG_ADPT_RESET BIT(10) - #define XPCS_USXG_EN BIT(9) -@@ -196,6 +199,28 @@ static void ipq_pcs_get_state_usxgmii(st - state->duplex = DUPLEX_FULL; - } - -+static void ipq_pcs_get_state_10gbaser(struct ipq_pcs *qpcs, -+ struct phylink_link_state *state) -+{ -+ unsigned int val; -+ int ret; -+ -+ ret = regmap_read(qpcs->regmap, XPCS_KR_STS, &val); -+ if (ret) { -+ state->link = 0; -+ return; -+ } -+ -+ state->link = !!(val & XPCS_KR_LINK_STS); -+ -+ if (!state->link) -+ return; -+ -+ state->speed = SPEED_10000; -+ state->duplex = DUPLEX_FULL; -+ state->pause |= MLO_PAUSE_TXRX_MASK; -+} -+ - static int ipq_pcs_config_mode(struct ipq_pcs *qpcs, - phy_interface_t interface) - { -@@ -212,6 +237,7 @@ static int ipq_pcs_config_mode(struct ip - val = PCS_MODE_QSGMII; - break; - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10GBASER: - val = PCS_MODE_XPCS; - rate = 312500000; - break; -@@ -311,6 +337,15 @@ static int ipq_pcs_config_usxgmii(struct - return regmap_set_bits(qpcs->regmap, XPCS_MII_CTRL, XPCS_MII_AN_EN); - } - -+static int ipq_pcs_config_10gbaser(struct ipq_pcs *qpcs) -+{ -+ /* Configure 10GBASER mode if required */ -+ if (qpcs->interface == PHY_INTERFACE_MODE_10GBASER) -+ return 0; -+ -+ return ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_10GBASER); -+} -+ - static int ipq_pcs_link_up_config_sgmii(struct ipq_pcs *qpcs, - int index, - unsigned int neg_mode, -@@ -399,6 +434,7 @@ static int ipq_pcs_validate(struct phyli - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_10GBASER: - return 0; - case PHY_INTERFACE_MODE_USXGMII: - /* USXGMII only supports full duplex mode */ -@@ -418,6 +454,8 @@ static unsigned int ipq_pcs_inband_caps( - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_USXGMII: - return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ case PHY_INTERFACE_MODE_10GBASER: -+ return LINK_INBAND_DISABLE; - default: - return 0; - } -@@ -472,6 +510,9 @@ static void ipq_pcs_get_state(struct phy - case PHY_INTERFACE_MODE_USXGMII: - ipq_pcs_get_state_usxgmii(qpcs, state); - break; -+ case PHY_INTERFACE_MODE_10GBASER: -+ ipq_pcs_get_state_10gbaser(qpcs, state); -+ break; - default: - break; - } -@@ -500,6 +541,8 @@ static int ipq_pcs_config(struct phylink - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); - case PHY_INTERFACE_MODE_USXGMII: - return ipq_pcs_config_usxgmii(qpcs); -+ case PHY_INTERFACE_MODE_10GBASER: -+ return ipq_pcs_config_10gbaser(qpcs); - default: - return -EOPNOTSUPP; - }; -@@ -524,6 +567,9 @@ static void ipq_pcs_link_up(struct phyli - case PHY_INTERFACE_MODE_USXGMII: - ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); - break; -+ case PHY_INTERFACE_MODE_10GBASER: -+ /* Nothing to do here */ -+ return; - default: - return; - } -@@ -603,6 +649,7 @@ static unsigned long ipq_pcs_clk_rate_ge - { - switch (qpcs->interface) { - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10GBASER: - return 312500000; - default: - return 125000000; diff --git a/target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch b/target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch deleted file mode 100644 index fbdebec13a..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 0d3a93e3a5544daec59d8f10ac5ccab39849536e Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Tue, 2 Apr 2024 18:28:42 +0800 -Subject: [PATCH] net: pcs: Add 2500BASEX interface mode support to IPQ UNIPHY - PCS driver - -2500BASEX mode is used when PCS connects with QCA8386 switch in a fixed -2500M link. It is also used when PCS connectes with QCA8081 PHY which -works at 2500M link speed. In addition, it can be also used when PCS -connects with a 2.5G SFP module. - -Change-Id: I3fe61113c1b3685debc20659736a9488216a029d -Signed-off-by: Lei Wei -Alex G: use regmap to read/write registers - 's/ipq_unipcs/ipq_pcs/' in function names as suggested by Luo Jie -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 67 ++++++++++++++++++++++++++++++ - 1 file changed, 67 insertions(+) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -26,6 +26,7 @@ - #define PCS_MODE_SEL_MASK GENMASK(12, 8) - #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) - #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) -+#define PCS_MODE_2500BASEX FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) - #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) - - #define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) -@@ -155,6 +156,29 @@ static void ipq_pcs_get_state_sgmii(stru - state->duplex = DUPLEX_HALF; - } - -+static void ipq_pcs_get_state_2500basex(struct ipq_pcs *qpcs, -+ struct phylink_link_state *state) -+{ -+ unsigned int val; -+ int ret; -+ -+ ret = regmap_read(qpcs->regmap, PCS_MII_STS(0), &val); -+ if (ret) { -+ state->link = 0; -+ return; -+ } -+ -+ -+ state->link = !!(val & PCS_MII_LINK_STS); -+ -+ if (!state->link) -+ return; -+ -+ state->speed = SPEED_2500; -+ state->duplex = DUPLEX_FULL; -+ state->pause |= MLO_PAUSE_TXRX_MASK; -+} -+ - static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, - struct phylink_link_state *state) - { -@@ -236,6 +260,10 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_QSGMII: - val = PCS_MODE_QSGMII; - break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ val = PCS_MODE_2500BASEX; -+ rate = 312500000; -+ break; - case PHY_INTERFACE_MODE_USXGMII: - case PHY_INTERFACE_MODE_10GBASER: - val = PCS_MODE_XPCS; -@@ -314,6 +342,15 @@ static int ipq_pcs_config_sgmii(struct i - PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); - } - -+static int ipq_pcs_config_2500basex(struct ipq_pcs *qpcs) -+{ -+ /* Configure PCS for 2500BASEX mode if required */ -+ if (qpcs->interface == PHY_INTERFACE_MODE_2500BASEX) -+ return 0; -+ -+ return ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_2500BASEX); -+} -+ - static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs) - { - int ret; -@@ -388,6 +425,22 @@ static int ipq_pcs_link_up_config_sgmii( - PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); - } - -+static int ipq_pcs_link_up_config_2500basex(struct ipq_pcs *qpcs, int speed) -+{ -+ int ret; -+ -+ /* 2500BASEX does not support autoneg and does not need to -+ * configure PCS speed. Only reset PCS adapter here. -+ */ -+ ret = regmap_clear_bits(qpcs->regmap, -+ PCS_MII_CTRL(0), PCS_MII_ADPT_RESET); -+ if (ret) -+ return ret; -+ -+ return regmap_set_bits(qpcs->regmap, -+ PCS_MII_CTRL(0), PCS_MII_ADPT_RESET); -+} -+ - static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, int speed) - { - unsigned int val; -@@ -436,6 +489,10 @@ static int ipq_pcs_validate(struct phyli - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_10GBASER: - return 0; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ /* In-band autoneg is not supported for 2500BASEX */ -+ phylink_clear(supported, Autoneg); -+ return 0; - case PHY_INTERFACE_MODE_USXGMII: - /* USXGMII only supports full duplex mode */ - phylink_clear(supported, 100baseT_Half); -@@ -454,6 +511,7 @@ static unsigned int ipq_pcs_inband_caps( - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_USXGMII: - return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; -+ case PHY_INTERFACE_MODE_2500BASEX: - case PHY_INTERFACE_MODE_10GBASER: - return LINK_INBAND_DISABLE; - default: -@@ -507,6 +565,9 @@ static void ipq_pcs_get_state(struct phy - case PHY_INTERFACE_MODE_QSGMII: - ipq_pcs_get_state_sgmii(qpcs, index, state); - break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ ipq_pcs_get_state_2500basex(qpcs, state); -+ break; - case PHY_INTERFACE_MODE_USXGMII: - ipq_pcs_get_state_usxgmii(qpcs, state); - break; -@@ -539,6 +600,8 @@ static int ipq_pcs_config(struct phylink - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); -+ case PHY_INTERFACE_MODE_2500BASEX: -+ return ipq_pcs_config_2500basex(qpcs); - case PHY_INTERFACE_MODE_USXGMII: - return ipq_pcs_config_usxgmii(qpcs); - case PHY_INTERFACE_MODE_10GBASER: -@@ -564,6 +627,9 @@ static void ipq_pcs_link_up(struct phyli - ret = ipq_pcs_link_up_config_sgmii(qpcs, index, - neg_mode, speed); - break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ ret = ipq_pcs_link_up_config_2500basex(qpcs, speed); -+ break; - case PHY_INTERFACE_MODE_USXGMII: - ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); - break; -@@ -648,6 +714,7 @@ static int ipq_pcs_create_miis(struct ip - static unsigned long ipq_pcs_clk_rate_get(struct ipq_pcs *qpcs) - { - switch (qpcs->interface) { -+ case PHY_INTERFACE_MODE_2500BASEX: - case PHY_INTERFACE_MODE_USXGMII: - case PHY_INTERFACE_MODE_10GBASER: - return 312500000; diff --git a/target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch b/target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch deleted file mode 100644 index 37aa60d8ff..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch +++ /dev/null @@ -1,104 +0,0 @@ -From d82953614a4f09dd7479e1d3904351ff85d1d088 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Tue, 9 Apr 2024 01:07:22 +0800 -Subject: [PATCH] net: pcs: Add 1000BASEX interface mode support to IPQ UNIPHY - PCS driver - -1000BASEX is used when PCS connects with a 1G SFP module. - -Change-Id: Ied7298de3c1ecba74e6457a07fdd6b3ceab79728 -Signed-off-by: Lei Wei -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 21 ++++++++++++++++++--- - 1 file changed, 18 insertions(+), 3 deletions(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -28,6 +28,9 @@ - #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) - #define PCS_MODE_2500BASEX FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) - #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) -+#define PCS_MODE_SGMII_MODE_MASK GENMASK(6, 4) -+#define PCS_MODE_SGMII_MODE_1000BASEX FIELD_PREP(PCS_MODE_SGMII_MODE_MASK, \ -+ 0x0) - - #define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) - #define PCS_MII_ADPT_RESET BIT(11) -@@ -249,10 +252,11 @@ static int ipq_pcs_config_mode(struct ip - phy_interface_t interface) - { - unsigned long rate = 125000000; -- unsigned int val; -+ unsigned int val, mask; - int ret; - - /* Configure PCS interface mode */ -+ mask = PCS_MODE_SEL_MASK; - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - val = PCS_MODE_SGMII; -@@ -260,6 +264,10 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_QSGMII: - val = PCS_MODE_QSGMII; - break; -+ case PHY_INTERFACE_MODE_1000BASEX: -+ mask |= PCS_MODE_SGMII_MODE_MASK; -+ val = PCS_MODE_SGMII | PCS_MODE_SGMII_MODE_1000BASEX; -+ break; - case PHY_INTERFACE_MODE_2500BASEX: - val = PCS_MODE_2500BASEX; - rate = 312500000; -@@ -273,8 +281,7 @@ static int ipq_pcs_config_mode(struct ip - return -EOPNOTSUPP; - } - -- ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL, -- PCS_MODE_SEL_MASK, val); -+ ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL, mask, val); - if (ret) - return ret; - -@@ -487,6 +494,7 @@ static int ipq_pcs_validate(struct phyli - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_10GBASER: - return 0; - case PHY_INTERFACE_MODE_2500BASEX: -@@ -509,6 +517,7 @@ static unsigned int ipq_pcs_inband_caps( - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_USXGMII: - return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; - case PHY_INTERFACE_MODE_2500BASEX: -@@ -563,6 +572,10 @@ static void ipq_pcs_get_state(struct phy - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: -+ /* SGMII and 1000BASEX in-band autoneg word format are decoded -+ * by PCS hardware and both placed to the same status register. -+ */ - ipq_pcs_get_state_sgmii(qpcs, index, state); - break; - case PHY_INTERFACE_MODE_2500BASEX: -@@ -599,6 +612,7 @@ static int ipq_pcs_config(struct phylink - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); - case PHY_INTERFACE_MODE_2500BASEX: - return ipq_pcs_config_2500basex(qpcs); -@@ -624,6 +638,7 @@ static void ipq_pcs_link_up(struct phyli - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_1000BASEX: - ret = ipq_pcs_link_up_config_sgmii(qpcs, index, - neg_mode, speed); - break; diff --git a/target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch b/target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch deleted file mode 100644 index 2563ac8396..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch +++ /dev/null @@ -1,267 +0,0 @@ -From fc26c6f6c69149ce87c88d6878ae929b2a138063 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Mon, 15 Apr 2024 11:06:02 +0800 -Subject: [PATCH] net: pcs: Add 10G_QXGMII interface mode support to IPQ UNIPHY - PCS driver - -10G_QXGMII is used when PCS connectes with QCA8084 four ports -2.5G PHYs. - -Change-Id: If3dc92a07ac3e51f7c9473fb05fa0668617916fb -Signed-off-by: Lei Wei -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 109 +++++++++++++++++++++++------ - 1 file changed, 87 insertions(+), 22 deletions(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -48,6 +48,9 @@ - #define PCS_MII_STS_SPEED_100 1 - #define PCS_MII_STS_SPEED_1000 2 - -+#define PCS_QP_USXG_OPTION 0x584 -+#define PCS_QP_USXG_GMII_SRC_XPCS BIT(0) -+ - #define PCS_PLL_RESET 0x780 - #define PCS_ANA_SW_RESET BIT(6) - -@@ -63,10 +66,23 @@ - #define XPCS_KR_LINK_STS BIT(12) - - #define XPCS_DIG_CTRL 0x38000 -+#define XPCS_SOFT_RESET BIT(15) - #define XPCS_USXG_ADPT_RESET BIT(10) - #define XPCS_USXG_EN BIT(9) - -+#define XPCS_KR_CTRL 0x38007 -+#define XPCS_USXG_MODE_MASK GENMASK(12, 10) -+#define XPCS_10G_QXGMII_MODE FIELD_PREP(XPCS_USXG_MODE_MASK, 0x5) -+ -+#define XPCS_DIG_STS 0x3800a -+#define XPCS_DIG_STS_AM_COUNT GENMASK(14, 0) -+ -+/* DIG control for MII1 - MII3 */ -+#define XPCS_MII1_DIG_CTRL(x) (0x1a8000 + 0x10000 * ((x) - 1)) -+#define XPCS_MII1_USXG_ADPT_RESET BIT(5) -+ - #define XPCS_MII_CTRL 0x1f0000 -+#define XPCS_MII1_CTRL(x) (0x1a0000 + 0x10000 * ((x) - 1)) - #define XPCS_MII_AN_EN BIT(12) - #define XPCS_DUPLEX_FULL BIT(8) - #define XPCS_SPEED_MASK (BIT(13) | BIT(6) | BIT(5)) -@@ -78,9 +94,11 @@ - #define XPCS_SPEED_10 0 - - #define XPCS_MII_AN_CTRL 0x1f8001 -+#define XPCS_MII1_AN_CTRL(x) (0x1a8001 + 0x10000 * ((x) - 1)) - #define XPCS_MII_AN_8BIT BIT(8) - - #define XPCS_MII_AN_INTR_STS 0x1f8002 -+#define XPCS_MII1_AN_INTR_STS(x) (0x1a8002 + 0x10000 * ((x) - 1)) - #define XPCS_USXG_AN_LINK_STS BIT(14) - #define XPCS_USXG_AN_SPEED_MASK GENMASK(12, 10) - #define XPCS_USXG_AN_SPEED_10 0 -@@ -90,6 +108,10 @@ - #define XPCS_USXG_AN_SPEED_5000 5 - #define XPCS_USXG_AN_SPEED_10000 3 - -+#define XPCS_XAUI_MODE_CTRL 0x1f8004 -+#define XPCS_MII1_XAUI_MODE_CTRL(x) (0x1a8004 + 0x10000 * ((x) - 1)) -+#define XPCS_TX_IPG_CHECK_DIS BIT(0) -+ - /* Per PCS MII private data */ - struct ipq_pcs_mii { - struct ipq_pcs *qpcs; -@@ -182,13 +204,14 @@ static void ipq_pcs_get_state_2500basex( - state->pause |= MLO_PAUSE_TXRX_MASK; - } - --static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, -+static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, int index, - struct phylink_link_state *state) - { -- unsigned int val; -+ unsigned int reg, val; - int ret; - -- ret = regmap_read(qpcs->regmap, XPCS_MII_AN_INTR_STS, &val); -+ reg = (index == 0) ? XPCS_MII_AN_INTR_STS : XPCS_MII1_AN_INTR_STS(index); -+ ret = regmap_read(qpcs->regmap, reg, &val); - if (ret) { - state->link = 0; - return; -@@ -273,6 +296,7 @@ static int ipq_pcs_config_mode(struct ip - rate = 312500000; - break; - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10G_QXGMII: - case PHY_INTERFACE_MODE_10GBASER: - val = PCS_MODE_XPCS; - rate = 312500000; -@@ -285,6 +309,13 @@ static int ipq_pcs_config_mode(struct ip - if (ret) - return ret; - -+ if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ ret = regmap_set_bits(qpcs->regmap, PCS_QP_USXG_OPTION, -+ PCS_QP_USXG_GMII_SRC_XPCS); -+ if (ret) -+ return ret; -+ } -+ - /* PCS PLL reset */ - ret = regmap_clear_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); - if (ret) -@@ -358,27 +389,51 @@ static int ipq_pcs_config_2500basex(stru - return ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_2500BASEX); - } - --static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs) -+static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs, -+ int index, -+ phy_interface_t interface) - { -+ unsigned int reg; - int ret; - - /* Configure the XPCS for USXGMII mode if required */ -- if (qpcs->interface == PHY_INTERFACE_MODE_USXGMII) -- return 0; -- -- ret = ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_USXGMII); -- if (ret) -- return ret; -+ if (qpcs->interface != interface) { -+ ret = ipq_pcs_config_mode(qpcs, interface); -+ if (ret) -+ return ret; - -- ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_USXG_EN); -- if (ret) -- return ret; -+ if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ ret = regmap_update_bits(qpcs->regmap, XPCS_KR_CTRL, -+ XPCS_USXG_MODE_MASK, XPCS_10G_QXGMII_MODE); -+ if (ret) -+ return ret; -+ -+ /* Set Alignment Marker Interval value as 0x6018 */ -+ ret = regmap_update_bits(qpcs->regmap, XPCS_DIG_STS, -+ XPCS_DIG_STS_AM_COUNT, 0x6018); -+ if (ret) -+ return ret; -+ -+ ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_SOFT_RESET); -+ if (ret) -+ return ret; -+ } -+ -+ /* Disable Tx IPG check for 10G_QXGMII */ -+ if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ reg = (index == 0) ? XPCS_XAUI_MODE_CTRL : XPCS_MII1_XAUI_MODE_CTRL(index); -+ ret = regmap_set_bits(qpcs->regmap, reg, XPCS_TX_IPG_CHECK_DIS); -+ if (ret) -+ return ret; -+ } - -- ret = regmap_set_bits(qpcs->regmap, XPCS_MII_AN_CTRL, XPCS_MII_AN_8BIT); -+ reg = (index == 0) ? XPCS_MII_AN_CTRL : XPCS_MII1_AN_CTRL(index); -+ ret = regmap_set_bits(qpcs->regmap, reg, XPCS_MII_AN_8BIT); - if (ret) - return ret; - -- return regmap_set_bits(qpcs->regmap, XPCS_MII_CTRL, XPCS_MII_AN_EN); -+ reg = (index == 0) ? XPCS_MII_CTRL : XPCS_MII1_CTRL(index); -+ return regmap_set_bits(qpcs->regmap, reg, XPCS_MII_AN_EN); - } - - static int ipq_pcs_config_10gbaser(struct ipq_pcs *qpcs) -@@ -448,9 +503,10 @@ static int ipq_pcs_link_up_config_2500ba - PCS_MII_CTRL(0), PCS_MII_ADPT_RESET); - } - --static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, int speed) -+static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, -+ int index, int speed) - { -- unsigned int val; -+ unsigned int reg, val; - int ret; - - switch (speed) { -@@ -478,14 +534,17 @@ static int ipq_pcs_link_up_config_usxgmi - } - - /* Configure XPCS speed */ -- ret = regmap_update_bits(qpcs->regmap, XPCS_MII_CTRL, -+ reg = (index == 0) ? XPCS_MII_CTRL : XPCS_MII1_CTRL(index); -+ ret = regmap_update_bits(qpcs->regmap, reg, - XPCS_SPEED_MASK, val | XPCS_DUPLEX_FULL); - if (ret) - return ret; - - /* XPCS adapter reset */ -- return regmap_set_bits(qpcs->regmap, -- XPCS_DIG_CTRL, XPCS_USXG_ADPT_RESET); -+ reg = (index == 0) ? XPCS_DIG_CTRL : XPCS_MII1_DIG_CTRL(index); -+ val = (index == 0) ? XPCS_USXG_ADPT_RESET : XPCS_MII1_USXG_ADPT_RESET; -+ return regmap_set_bits(qpcs->regmap, reg, val); -+ - } - - static int ipq_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, -@@ -502,6 +561,7 @@ static int ipq_pcs_validate(struct phyli - phylink_clear(supported, Autoneg); - return 0; - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10G_QXGMII: - /* USXGMII only supports full duplex mode */ - phylink_clear(supported, 100baseT_Half); - phylink_clear(supported, 10baseT_Half); -@@ -519,6 +579,7 @@ static unsigned int ipq_pcs_inband_caps( - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10G_QXGMII: - return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; - case PHY_INTERFACE_MODE_2500BASEX: - case PHY_INTERFACE_MODE_10GBASER: -@@ -582,7 +643,8 @@ static void ipq_pcs_get_state(struct phy - ipq_pcs_get_state_2500basex(qpcs, state); - break; - case PHY_INTERFACE_MODE_USXGMII: -- ipq_pcs_get_state_usxgmii(qpcs, state); -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ ipq_pcs_get_state_usxgmii(qpcs, index, state); - break; - case PHY_INTERFACE_MODE_10GBASER: - ipq_pcs_get_state_10gbaser(qpcs, state); -@@ -617,7 +679,8 @@ static int ipq_pcs_config(struct phylink - case PHY_INTERFACE_MODE_2500BASEX: - return ipq_pcs_config_2500basex(qpcs); - case PHY_INTERFACE_MODE_USXGMII: -- return ipq_pcs_config_usxgmii(qpcs); -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ return ipq_pcs_config_usxgmii(qpcs, index, interface); - case PHY_INTERFACE_MODE_10GBASER: - return ipq_pcs_config_10gbaser(qpcs); - default: -@@ -646,7 +709,8 @@ static void ipq_pcs_link_up(struct phyli - ret = ipq_pcs_link_up_config_2500basex(qpcs, speed); - break; - case PHY_INTERFACE_MODE_USXGMII: -- ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ ret = ipq_pcs_link_up_config_usxgmii(qpcs, index, speed); - break; - case PHY_INTERFACE_MODE_10GBASER: - /* Nothing to do here */ -@@ -731,6 +795,7 @@ static unsigned long ipq_pcs_clk_rate_ge - switch (qpcs->interface) { - case PHY_INTERFACE_MODE_2500BASEX: - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10G_QXGMII: - case PHY_INTERFACE_MODE_10GBASER: - return 312500000; - default: diff --git a/target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch b/target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch deleted file mode 100644 index 6ec8f2634e..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 87da3bbd25eb0a17e2c698120528e76c26b326d0 Mon Sep 17 00:00:00 2001 -From: Mantas Pucka -Date: Mon, 2 Jun 2025 17:18:13 +0300 -Subject: [PATCH] net: pcs: ipq-uniphy: control MISC2 register for 2.5G support - -When 2500base-x mode is enabled MISC2 regsister needs to have different -value than for other 1G modes. - -Signed-off-by: Mantas Pucka ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -22,6 +22,11 @@ - #define PCS_CALIBRATION 0x1e0 - #define PCS_CALIBRATION_DONE BIT(7) - -+#define PCS_MISC2 0x218 -+#define PCS_MISC2_MODE_MASK GENMASK(6, 5) -+#define PCS_MISC2_MODE_SGMII FIELD_PREP(PCS_MISC2_MODE_MASK, 0x1) -+#define PCS_MISC2_MODE_SGMII_PLUS FIELD_PREP(PCS_MISC2_MODE_MASK, 0x2) -+ - #define PCS_MODE_CTRL 0x46c - #define PCS_MODE_SEL_MASK GENMASK(12, 8) - #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) -@@ -275,7 +280,7 @@ static int ipq_pcs_config_mode(struct ip - phy_interface_t interface) - { - unsigned long rate = 125000000; -- unsigned int val, mask; -+ unsigned int val, mask, misc2 = 0; - int ret; - - /* Configure PCS interface mode */ -@@ -283,6 +288,7 @@ static int ipq_pcs_config_mode(struct ip - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - val = PCS_MODE_SGMII; -+ misc2 = PCS_MISC2_MODE_SGMII; - break; - case PHY_INTERFACE_MODE_QSGMII: - val = PCS_MODE_QSGMII; -@@ -290,9 +296,11 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_1000BASEX: - mask |= PCS_MODE_SGMII_MODE_MASK; - val = PCS_MODE_SGMII | PCS_MODE_SGMII_MODE_1000BASEX; -+ misc2 = PCS_MISC2_MODE_SGMII; - break; - case PHY_INTERFACE_MODE_2500BASEX: - val = PCS_MODE_2500BASEX; -+ misc2 = PCS_MISC2_MODE_SGMII_PLUS; - rate = 312500000; - break; - case PHY_INTERFACE_MODE_USXGMII: -@@ -315,6 +323,13 @@ static int ipq_pcs_config_mode(struct ip - if (ret) - return ret; - } -+ -+ if (misc2) { -+ ret = regmap_update_bits(qpcs->regmap, PCS_MISC2, -+ PCS_MISC2_MODE_MASK, misc2); -+ if (ret) -+ return ret; -+ } - - /* PCS PLL reset */ - ret = regmap_clear_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); diff --git a/target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch b/target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch deleted file mode 100644 index b02782e7b3..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch +++ /dev/null @@ -1,24 +0,0 @@ -From bedf56b46ae53c4abb21eebb3e1d5a7483926dda Mon Sep 17 00:00:00 2001 -From: Mantas Pucka -Date: Mon, 2 Jun 2025 17:20:58 +0300 -Subject: [PATCH] net: pcs: ipq-uniphy: fix USXGMII link-up failure - -USXGMII link-up may fail due to too short delay after PLL reset. -Increase the delay to fix this. - -Signed-off-by: Mantas Pucka ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -336,7 +336,7 @@ static int ipq_pcs_config_mode(struct ip - if (ret) - return ret; - -- fsleep(1000); -+ fsleep(20000); - ret = regmap_set_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); - if (ret) - return ret; diff --git a/target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch b/target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch deleted file mode 100644 index 63a523ae1c..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch +++ /dev/null @@ -1,282 +0,0 @@ -From b4e07a8a3ec3dc5f676238987556e2aff0b14028 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Mon, 29 Jan 2024 11:39:36 +0800 -Subject: [PATCH] net: pcs: qcom-ipq9574: Update IPQ9574 PCS driver - -Keep the PCS driver synced with the latest version posted to the kernel -community and add the XPCS reset support. - -Signed-off-by: Luo Jie -Signed-off-by: Alexandru Gagniuc ---- - .../bindings/net/pcs/qcom,ipq9574-pcs.yaml | 7 ++ - drivers/net/pcs/pcs-qcom-ipq9574.c | 68 +++++++++++++++---- - 2 files changed, 63 insertions(+), 12 deletions(-) - ---- a/Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml -+++ b/Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml -@@ -98,6 +98,10 @@ properties: - - const: sys - - const: ahb - -+ resets: -+ maxItems: 1 -+ description: XPCS reset -+ - '#clock-cells': - const: 1 - description: See include/dt-bindings/net/qcom,ipq9574-pcs.h for constants -@@ -137,6 +141,7 @@ required: - - '#size-cells' - - clocks - - clock-names -+ - resets - - '#clock-cells' - - additionalProperties: false -@@ -144,6 +149,7 @@ additionalProperties: false - examples: - - | - #include -+ #include - - ethernet-pcs@7a00000 { - compatible = "qcom,ipq9574-pcs"; -@@ -154,6 +160,7 @@ examples: - <&gcc GCC_UNIPHY0_AHB_CLK>; - clock-names = "sys", - "ahb"; -+ resets = <&gcc GCC_UNIPHY0_XPCS_RESET>; - #clock-cells = <1>; - - pcs-mii@0 { ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #include - -@@ -31,9 +32,12 @@ - #define PCS_MODE_SEL_MASK GENMASK(12, 8) - #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) - #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) -+#define PCS_MODE_PSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x2) - #define PCS_MODE_2500BASEX FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) - #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) - #define PCS_MODE_SGMII_MODE_MASK GENMASK(6, 4) -+#define PCS_MODE_SGMII_MODE_MAC FIELD_PREP(PCS_MODE_SGMII_MODE_MASK, \ -+ 0x2) - #define PCS_MODE_SGMII_MODE_1000BASEX FIELD_PREP(PCS_MODE_SGMII_MODE_MASK, \ - 0x0) - -@@ -52,6 +56,8 @@ - #define PCS_MII_STS_SPEED_10 0 - #define PCS_MII_STS_SPEED_100 1 - #define PCS_MII_STS_SPEED_1000 2 -+#define PCS_MII_STS_PAUSE_TX_EN BIT(1) -+#define PCS_MII_STS_PAUSE_RX_EN BIT(0) - - #define PCS_QP_USXG_OPTION 0x584 - #define PCS_QP_USXG_GMII_SRC_XPCS BIT(0) -@@ -142,6 +148,7 @@ struct ipq_pcs { - struct clk_hw tx_hw; - - struct ipq_pcs_mii *qpcs_mii[PCS_MAX_MII_NRS]; -+ struct reset_control *xpcs_rstc; - }; - - #define phylink_pcs_to_qpcs_mii(_pcs) \ -@@ -184,6 +191,11 @@ static void ipq_pcs_get_state_sgmii(stru - state->duplex = DUPLEX_FULL; - else - state->duplex = DUPLEX_HALF; -+ -+ if (val & PCS_MII_STS_PAUSE_TX_EN) -+ state->pause |= MLO_PAUSE_TX; -+ if (val & PCS_MII_STS_PAUSE_RX_EN) -+ state->pause |= MLO_PAUSE_RX; - } - - static void ipq_pcs_get_state_2500basex(struct ipq_pcs *qpcs, -@@ -198,7 +210,6 @@ static void ipq_pcs_get_state_2500basex( - return; - } - -- - state->link = !!(val & PCS_MII_LINK_STS); - - if (!state->link) -@@ -281,17 +292,27 @@ static int ipq_pcs_config_mode(struct ip - { - unsigned long rate = 125000000; - unsigned int val, mask, misc2 = 0; -+ bool xpcs_mode = false; - int ret; - -+ /* Assert XPCS reset */ -+ reset_control_assert(qpcs->xpcs_rstc); -+ - /* Configure PCS interface mode */ - mask = PCS_MODE_SEL_MASK; - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: -- val = PCS_MODE_SGMII; -+ mask |= PCS_MODE_SGMII_MODE_MASK; -+ val = PCS_MODE_SGMII | PCS_MODE_SGMII_MODE_MAC; - misc2 = PCS_MISC2_MODE_SGMII; - break; - case PHY_INTERFACE_MODE_QSGMII: -- val = PCS_MODE_QSGMII; -+ mask |= PCS_MODE_SGMII_MODE_MASK; -+ val = PCS_MODE_QSGMII | PCS_MODE_SGMII_MODE_MAC; -+ break; -+ case PHY_INTERFACE_MODE_PSGMII: -+ mask |= PCS_MODE_SGMII_MODE_MASK; -+ val = PCS_MODE_PSGMII | PCS_MODE_SGMII_MODE_MAC; - break; - case PHY_INTERFACE_MODE_1000BASEX: - mask |= PCS_MODE_SGMII_MODE_MASK; -@@ -308,6 +329,7 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_10GBASER: - val = PCS_MODE_XPCS; - rate = 312500000; -+ xpcs_mode = true; - break; - default: - return -EOPNOTSUPP; -@@ -367,6 +389,10 @@ static int ipq_pcs_config_mode(struct ip - return ret; - } - -+ /* Deassert XPCS */ -+ if (xpcs_mode) -+ reset_control_deassert(qpcs->xpcs_rstc); -+ - return 0; - } - -@@ -384,15 +410,13 @@ static int ipq_pcs_config_sgmii(struct i - return ret; - } - -- /* Nothing to do here as in-band autoneg mode is enabled -- * by default for each PCS MII port. -- */ -+ /* Set AN mode or force mode */ - if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) -- return 0; -- -- /* Set force speed mode */ -- return regmap_set_bits(qpcs->regmap, -- PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); -+ return regmap_clear_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); -+ else -+ return regmap_set_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); - } - - static int ipq_pcs_config_2500basex(struct ipq_pcs *qpcs) -@@ -417,6 +441,10 @@ static int ipq_pcs_config_usxgmii(struct - if (ret) - return ret; - -+ ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_USXG_EN); -+ if (ret) -+ return ret; -+ - if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { - ret = regmap_update_bits(qpcs->regmap, XPCS_KR_CTRL, - XPCS_USXG_MODE_MASK, XPCS_10G_QXGMII_MODE); -@@ -432,6 +460,7 @@ static int ipq_pcs_config_usxgmii(struct - ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_SOFT_RESET); - if (ret) - return ret; -+ } - } - - /* Disable Tx IPG check for 10G_QXGMII */ -@@ -559,7 +588,6 @@ static int ipq_pcs_link_up_config_usxgmi - reg = (index == 0) ? XPCS_DIG_CTRL : XPCS_MII1_DIG_CTRL(index); - val = (index == 0) ? XPCS_USXG_ADPT_RESET : XPCS_MII1_USXG_ADPT_RESET; - return regmap_set_bits(qpcs->regmap, reg, val); -- - } - - static int ipq_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, -@@ -568,6 +596,7 @@ static int ipq_pcs_validate(struct phyli - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_10GBASER: - return 0; -@@ -592,6 +621,7 @@ static unsigned int ipq_pcs_inband_caps( - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_USXGMII: - case PHY_INTERFACE_MODE_10G_QXGMII: -@@ -648,6 +678,7 @@ static void ipq_pcs_get_state(struct phy - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - /* SGMII and 1000BASEX in-band autoneg word format are decoded - * by PCS hardware and both placed to the same status register. -@@ -689,6 +720,7 @@ static int ipq_pcs_config(struct phylink - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); - case PHY_INTERFACE_MODE_2500BASEX: -@@ -703,6 +735,11 @@ static int ipq_pcs_config(struct phylink - }; - } - -+static void ipq_pcs_an_restart(struct phylink_pcs *pcs) -+{ -+ /* Currently not used */ -+} -+ - static void ipq_pcs_link_up(struct phylink_pcs *pcs, - unsigned int neg_mode, - phy_interface_t interface, -@@ -716,6 +753,7 @@ static void ipq_pcs_link_up(struct phyli - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_1000BASEX: - ret = ipq_pcs_link_up_config_sgmii(qpcs, index, - neg_mode, speed); -@@ -746,6 +784,7 @@ static const struct phylink_pcs_ops ipq_ - .pcs_disable = ipq_pcs_disable, - .pcs_get_state = ipq_pcs_get_state, - .pcs_config = ipq_pcs_config, -+ .pcs_an_restart = ipq_pcs_an_restart, - .pcs_link_up = ipq_pcs_link_up, - }; - -@@ -990,6 +1029,11 @@ static int ipq9574_pcs_probe(struct plat - return dev_err_probe(dev, PTR_ERR(clk), - "Failed to enable AHB clock\n"); - -+ qpcs->xpcs_rstc = devm_reset_control_get_optional(dev, NULL); -+ if (IS_ERR_OR_NULL(qpcs->xpcs_rstc)) -+ return dev_err_probe(dev, PTR_ERR(qpcs->xpcs_rstc), -+ "Failed to get XPCS reset\n"); -+ - ret = ipq_pcs_clk_register(qpcs); - if (ret) - return ret; diff --git a/target/linux/qualcommbe/patches-6.12/0370-net-phy-Add-phy_package_remove_once-helper.patch b/target/linux/qualcommbe/patches-6.12/0370-net-phy-Add-phy_package_remove_once-helper.patch deleted file mode 100644 index ec81286431..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0370-net-phy-Add-phy_package_remove_once-helper.patch +++ /dev/null @@ -1,36 +0,0 @@ -From d11eba3e178a9d42a579c656b2c9b643f4ce3e1e Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 23 Sep 2024 18:46:34 +0800 -Subject: [PATCH] net: phy: Add phy_package_remove_once helper - -QCA8084 PHY package needs to do the PHY package clean up, -add phy_package_remove_once helper to support. - -Change-Id: I3cd73bc7be1b1d531435ef72f48db0682548decf -Signed-off-by: Luo Jie ---- - include/linux/phy.h | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -376,6 +376,7 @@ struct phy_package_shared { - /* used as bit number in atomic bitops */ - #define PHY_SHARED_F_INIT_DONE 0 - #define PHY_SHARED_F_PROBE_DONE 1 -+#define PHY_SHARED_F_REMOVE_DONE 2 - - /** - * struct mii_bus - Represents an MDIO bus -@@ -2290,6 +2291,11 @@ static inline bool phy_package_probe_onc - return __phy_package_set_once(phydev, PHY_SHARED_F_PROBE_DONE); - } - -+static inline bool phy_package_remove_once(struct phy_device *phydev) -+{ -+ return __phy_package_set_once(phydev, PHY_SHARED_F_REMOVE_DONE); -+} -+ - extern const struct bus_type mdio_bus_type; - - struct mdio_board_info { diff --git a/target/linux/qualcommbe/patches-6.12/0371-net-phy-qca808x-Add-QCA8084-SerDes-probe-and-remove-.patch b/target/linux/qualcommbe/patches-6.12/0371-net-phy-qca808x-Add-QCA8084-SerDes-probe-and-remove-.patch deleted file mode 100644 index a0c84bddeb..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0371-net-phy-qca808x-Add-QCA8084-SerDes-probe-and-remove-.patch +++ /dev/null @@ -1,437 +0,0 @@ -From c12b79af730116936504afe97234f9afb6ac8fc0 Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 23 Sep 2024 20:28:24 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 SerDes probe and remove - functions - -QCA8084 PHY package integrates the XPCS and PCS, which is used -to support 10G-QXGMII. XPCS includes 4 channels to connect with -Quad PHY, and PCS controls the interface mode configured. - -XPCS and PCS are probed and removed by PHY package. - -Change-Id: Ided0a5cd4c996dc2a2a0d0598e930fab060caaf8 -Signed-off-by: Luo Jie -Alex G: Use phy_package_get_*() accessors -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/Makefile | 2 +- - drivers/net/phy/qcom/qca8084_serdes.c | 249 ++++++++++++++++++++++++++ - drivers/net/phy/qcom/qca8084_serdes.h | 18 ++ - drivers/net/phy/qcom/qca808x.c | 53 ++++++ - 4 files changed, 321 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/phy/qcom/qca8084_serdes.c - create mode 100644 drivers/net/phy/qcom/qca8084_serdes.h - ---- a/drivers/net/phy/qcom/Makefile -+++ b/drivers/net/phy/qcom/Makefile -@@ -2,5 +2,5 @@ - obj-$(CONFIG_QCOM_NET_PHYLIB) += qcom-phy-lib.o - obj-$(CONFIG_AT803X_PHY) += at803x.o - obj-$(CONFIG_QCA83XX_PHY) += qca83xx.o --obj-$(CONFIG_QCA808X_PHY) += qca808x.o -+obj-$(CONFIG_QCA808X_PHY) += qca808x.o qca8084_serdes.o - obj-$(CONFIG_QCA807X_PHY) += qca807x.o ---- /dev/null -+++ b/drivers/net/phy/qcom/qca8084_serdes.c -@@ -0,0 +1,249 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "qca8084_serdes.h" -+ -+/* XPCS includes 4 channels, each channel has the different MMD ID for -+ * configuring auto-negotiation complete interrupt, mii-4bit, auto- -+ * negotiation capabilities and TX configuration for the connected PHY. -+ * -+ * MMD31 is for channel 0; -+ * MMD26 is for channel 1; -+ * MMD27 is for channel 2; -+ * MMD28 is for channel 3; -+ */ -+#define QCA8084_CHANNEL_MAX 4 -+ -+enum pcs_clk_id { -+ PCS_CLK, -+ PCS_RX_ROOT_CLK, -+ PCS_TX_ROOT_CLK, -+ PCS_CLK_MAX -+}; -+ -+enum xpcs_clk_id { -+ XPCS_XGMII_RX_CLK, -+ XPCS_XGMII_TX_CLK, -+ XPCS_RX_CLK, -+ XPCS_TX_CLK, -+ XPCS_PORT_RX_CLK, -+ XPCS_PORT_TX_CLK, -+ XPCS_RX_SRC_CLK, -+ XPCS_TX_SRC_CLK, -+ XPCS_CLK_MAX -+}; -+ -+struct qca8084_xpcs_channel_priv { -+ int ch_id; -+ struct reset_control *rstcs; -+ struct clk *clks[XPCS_CLK_MAX]; -+}; -+ -+struct qca8084_pcs_data { -+ struct reset_control *rstc; -+ struct clk *clks[PCS_CLK_MAX]; -+}; -+ -+struct qca8084_xpcs_data { -+ struct reset_control *rstc; -+ struct qca8084_xpcs_channel_priv xpcs_ch[QCA8084_CHANNEL_MAX]; -+}; -+ -+static const char *const xpcs_clock_names[XPCS_CLK_MAX] = { -+ [XPCS_XGMII_RX_CLK] = "xgmii_rx", -+ [XPCS_XGMII_TX_CLK] = "xgmii_tx", -+ [XPCS_RX_CLK] = "xpcs_rx", -+ [XPCS_TX_CLK] = "xpcs_tx", -+ [XPCS_PORT_RX_CLK] = "port_rx", -+ [XPCS_PORT_TX_CLK] = "port_tx", -+ [XPCS_RX_SRC_CLK] = "rx_src", -+ [XPCS_TX_SRC_CLK] = "tx_src", -+}; -+ -+static const char *const pcs_clock_names[PCS_CLK_MAX] = { -+ [PCS_CLK] = "pcs", -+ [PCS_RX_ROOT_CLK] = "pcs_rx_root", -+ [PCS_TX_ROOT_CLK] = "pcs_tx_root", -+}; -+ -+struct mdio_device *qca8084_package_pcs_probe(struct device_node *pcs_np) -+{ -+ struct qca8084_pcs_data *pcs_data; -+ struct mdio_device *mdiodev; -+ struct reset_control *rstc; -+ struct device *dev; -+ struct clk *clk; -+ int i; -+ -+ mdiodev = fwnode_mdio_find_device(of_fwnode_handle(pcs_np)); -+ if (!mdiodev) -+ return ERR_PTR(-EPROBE_DEFER); -+ -+ dev = &mdiodev->dev; -+ pcs_data = devm_kzalloc(dev, sizeof(*pcs_data), GFP_KERNEL); -+ if (!pcs_data) { -+ dev_err(dev, "Allocate PCS data failed\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ rstc = devm_reset_control_get_exclusive(dev, NULL); -+ if (IS_ERR(rstc)) { -+ dev_err(dev, "Get PCS reset failed\n"); -+ return ERR_CAST(rstc); -+ } -+ -+ pcs_data->rstc = rstc; -+ -+ for (i = 0; i < ARRAY_SIZE(pcs_clock_names); i++) { -+ clk = devm_clk_get(dev, pcs_clock_names[i]); -+ if (IS_ERR(clk)) { -+ dev_err(dev, "Failed to get the PCS clock ID %s\n", -+ pcs_clock_names[i]); -+ return ERR_CAST(clk); -+ } -+ pcs_data->clks[i] = clk; -+ } -+ -+ mdiodev_set_drvdata(mdiodev, pcs_data); -+ -+ return mdiodev; -+} -+ -+struct mdio_device *qca8084_package_xpcs_probe(struct device_node *xpcs_np) -+{ -+ struct qca8084_xpcs_data *xpcs_data; -+ struct mdio_device *mdiodev; -+ struct reset_control *rstc; -+ struct device_node *child; -+ struct device *dev; -+ struct clk *clk; -+ int i, j, node; -+ -+ mdiodev = fwnode_mdio_find_device(of_fwnode_handle(xpcs_np)); -+ if (!mdiodev) -+ return ERR_PTR(-EPROBE_DEFER); -+ -+ dev = &mdiodev->dev; -+ -+ xpcs_data = devm_kzalloc(dev, sizeof(*xpcs_data), GFP_KERNEL); -+ if (!xpcs_data) { -+ dev_err(dev, "Allocate XPCS data failed\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ rstc = devm_reset_control_get_exclusive(dev, NULL); -+ if (IS_ERR(rstc)) { -+ dev_err(dev, "Get XPCS reset failed\n"); -+ return ERR_CAST(rstc); -+ } -+ -+ xpcs_data->rstc = rstc; -+ -+ /* Sanity check the number of channel sub nodes */ -+ node = of_get_available_child_count(xpcs_np); -+ if (node != QCA8084_CHANNEL_MAX) -+ return ERR_PTR(-EINVAL); -+ -+ node = 0; -+ for_each_available_child_of_node(xpcs_np, child) { -+ struct qca8084_xpcs_channel_priv *ch_data; -+ u32 channel; -+ -+ /* The subnode name must be 'channel'. */ -+ if (!(of_node_name_eq(child, "channel"))) -+ continue; -+ -+ if (of_property_read_u32(child, "reg", &channel)) { -+ dev_err(dev, "%s: Failed to get reg\n", -+ child->full_name); -+ -+ mdiodev = ERR_PTR(-EINVAL); -+ goto put_ch_clk_rst; -+ } -+ -+ if (channel >= QCA8084_CHANNEL_MAX) { -+ dev_err(dev, "%s: Invalid reg %d\n", -+ child->full_name, channel); -+ -+ mdiodev = ERR_PTR(-EINVAL); -+ goto put_ch_clk_rst; -+ } -+ -+ ch_data = &xpcs_data->xpcs_ch[node]; -+ ch_data->ch_id = channel; -+ -+ ch_data->rstcs = of_reset_control_array_get_exclusive(child); -+ if (IS_ERR(ch_data->rstcs)) { -+ dev_err(dev, "%s: Failed to get reset\n", -+ child->full_name); -+ -+ mdiodev = ERR_CAST(ch_data->rstcs); -+ goto put_ch_clk_rst; -+ } -+ -+ for (j = 0; j < ARRAY_SIZE(xpcs_clock_names); j++) { -+ clk = of_clk_get_by_name(child, xpcs_clock_names[j]); -+ if (IS_ERR(clk)) { -+ dev_err(dev, "Failed to get the clock ID %s\n", -+ xpcs_clock_names[j]); -+ mdiodev = ERR_CAST(clk); -+ goto put_ch_child; -+ } -+ ch_data->clks[j] = clk; -+ } -+ -+ node++; -+ } -+ -+ mdiodev_set_drvdata(mdiodev, xpcs_data); -+ -+ return mdiodev; -+ -+put_ch_child: -+ node++; -+ -+put_ch_clk_rst: -+ for (i = 0; i < node; i++) { -+ j--; -+ while (j >= 0) { -+ clk_put(xpcs_data->xpcs_ch[i].clks[j]); -+ j--; -+ } -+ -+ j = ARRAY_SIZE(xpcs_clock_names); -+ } -+ -+ for (i = 0; i < node; i++) -+ reset_control_put(xpcs_data->xpcs_ch[i].rstcs); -+ -+ of_node_put(child); -+ -+ return mdiodev; -+} -+ -+void qca8084_package_xpcs_and_pcs_remove(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev) -+{ -+ struct qca8084_xpcs_data *xpcs_data = mdiodev_get_drvdata(xpcs_mdiodev); -+ int i, j; -+ -+ for (i = 0; i < ARRAY_SIZE(xpcs_data->xpcs_ch); i++) { -+ reset_control_put(xpcs_data->xpcs_ch[i].rstcs); -+ -+ for (j = 0; j < ARRAY_SIZE(xpcs_data->xpcs_ch[i].clks); j++) -+ clk_put(xpcs_data->xpcs_ch[i].clks[j]); -+ } -+ -+ mdio_device_put(xpcs_mdiodev); -+ mdio_device_put(pcs_mdiodev); -+} ---- /dev/null -+++ b/drivers/net/phy/qcom/qca8084_serdes.h -@@ -0,0 +1,18 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Driver for QCA8084 SerDes -+ * -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ */ -+ -+#ifndef _QCA8084_SERDES_H_ -+#define _QCA8084_SERDES_H_ -+ -+#include -+#include -+ -+struct mdio_device *qca8084_package_pcs_probe(struct device_node *pcs_np); -+struct mdio_device *qca8084_package_xpcs_probe(struct device_node *xpcs_np); -+void qca8084_package_xpcs_and_pcs_remove(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev); -+#endif /* _QCA8084_SERDES_H_ */ ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -8,6 +8,7 @@ - #include - - #include "../phylib.h" -+#include "qca8084_serdes.h" - #include "qcom.h" - - /* ADC threshold */ -@@ -172,11 +173,13 @@ enum { - - struct qca808x_priv { - int led_polarity_mode; -+ int channel_id; - }; - - struct qca808x_shared_priv { - int package_mode; - struct clk *clk[PACKAGE_CLK_MAX]; -+ struct mdio_device *mdiodev[2]; /* PCS and XPCS mdio device */ - }; - - static const char *const qca8084_package_clk_name[PACKAGE_CLK_MAX] = { -@@ -354,6 +357,8 @@ static int qca808x_probe(struct phy_devi - { - struct device *dev = &phydev->mdio.dev; - struct qca808x_priv *priv; -+ u32 ch_id = 0; -+ int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) -@@ -362,6 +367,14 @@ static int qca808x_probe(struct phy_devi - /* Init LED polarity mode to -1 */ - priv->led_polarity_mode = -1; - -+ /* DT property qcom,xpcs-channel" is optional and only available for -+ * 10G-QXGMII mode. -+ */ -+ ret = of_property_read_u32(dev->of_node, "qcom,xpcs-channel", &ch_id); -+ if (ret && ret != -EINVAL) -+ return ret; -+ -+ priv->channel_id = ch_id; - phydev->priv = priv; - - return 0; -@@ -1012,6 +1025,7 @@ static int qca8084_phy_package_probe_onc - struct device_node *np = phy_package_get_node(phydev); - struct qca808x_shared_priv *shared_priv; - struct reset_control *rstc; -+ struct device_node *child; - int i, ret, clear, set; - struct clk *clk; - -@@ -1072,6 +1086,26 @@ static int qca8084_phy_package_probe_onc - if (ret && ret != -EINVAL) - return ret; - -+ for_each_available_child_of_node(np, child) { -+ struct mdio_device *mdiodev; -+ -+ if (of_node_name_eq(child, "pcs-phy")) { -+ mdiodev = qca8084_package_pcs_probe(child); -+ if (IS_ERR(mdiodev)) -+ return PTR_ERR(mdiodev); -+ -+ shared_priv->mdiodev[0] = mdiodev; -+ } -+ -+ if (of_node_name_eq(child, "xpcs-phy")) { -+ mdiodev = qca8084_package_xpcs_probe(child); -+ if (IS_ERR(mdiodev)) -+ return PTR_ERR(mdiodev); -+ -+ shared_priv->mdiodev[1] = mdiodev; -+ } -+ } -+ - rstc = of_reset_control_get_exclusive(np, NULL); - if (IS_ERR(rstc)) - return dev_err_probe(&phydev->mdio.dev, PTR_ERR(rstc), -@@ -1081,6 +1115,14 @@ static int qca8084_phy_package_probe_onc - return reset_control_deassert(rstc); - } - -+static void qca8084_phy_package_remove_once(struct phy_device *phydev) -+{ -+ struct qca808x_shared_priv *shared_priv = phy_package_get_priv(phydev);; -+ -+ qca8084_package_xpcs_and_pcs_remove(shared_priv->mdiodev[1], -+ shared_priv->mdiodev[0]); -+} -+ - static int qca8084_probe(struct phy_device *phydev) - { - struct qca808x_shared_priv *shared_priv; -@@ -1099,6 +1141,10 @@ static int qca8084_probe(struct phy_devi - return ret; - } - -+ ret = qca808x_probe(phydev); -+ if (ret) -+ return ret; -+ - /* Enable clock of PHY device, so that the PHY register - * can be accessed to get PHY features. - */ -@@ -1116,6 +1162,12 @@ static int qca8084_probe(struct phy_devi - return reset_control_deassert(rstc); - } - -+static void qca8084_remove(struct phy_device *phydev) -+{ -+ if (phy_package_remove_once(phydev)) -+ qca8084_phy_package_remove_once(phydev); -+} -+ - static struct phy_driver qca808x_driver[] = { - { - /* Qualcomm QCA8081 */ -@@ -1167,6 +1219,7 @@ static struct phy_driver qca808x_driver[ - .config_init = qca8084_config_init, - .link_change_notify = qca8084_link_change_notify, - .probe = qca8084_probe, -+ .remove = qca8084_remove, - }, }; - - module_phy_driver(qca808x_driver); diff --git a/target/linux/qualcommbe/patches-6.12/0372-net-phy-qca808x-Add-QCA8084-SerDes-init-function.patch b/target/linux/qualcommbe/patches-6.12/0372-net-phy-qca808x-Add-QCA8084-SerDes-init-function.patch deleted file mode 100644 index 688d7ac474..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0372-net-phy-qca808x-Add-QCA8084-SerDes-init-function.patch +++ /dev/null @@ -1,446 +0,0 @@ -From d137b725f8f4a7d49a809dcd73c5b836495ec44d Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 23 Sep 2024 20:59:40 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 SerDes init function - -When QCA8084 works on 10G-QXGMII, the XPCS and PCS need to be -configured in the PHY package init function. - -Change-Id: Iac48c44f0e80adf055fa9c2095e99a04ba24c4bb -Signed-off-by: Luo Jie ---- - drivers/net/phy/qcom/qca8084_serdes.c | 374 ++++++++++++++++++++++++++ - drivers/net/phy/qcom/qca8084_serdes.h | 2 + - drivers/net/phy/qcom/qca808x.c | 11 + - 3 files changed, 387 insertions(+) - ---- a/drivers/net/phy/qcom/qca8084_serdes.c -+++ b/drivers/net/phy/qcom/qca8084_serdes.c -@@ -24,6 +24,92 @@ - */ - #define QCA8084_CHANNEL_MAX 4 - -+/* MII registers */ -+#define PLL_POWER_ON_AND_RESET 0x0 -+#define PCS_ANA_SW_RESET BIT(6) -+ -+#define PLL_CONTROL 6 -+#define PLL_CONTROL_CMLDIV2_IBSEL_MASK GENMASK(5, 4) -+ -+/* MMD_PMAPMD registers */ -+#define CDR_CONTRL 0x20 -+#define SSC_FIX_MODE BIT(3) -+ -+#define CALIBRATION4 0x78 -+#define CALIBRATION_DONE BIT(7) -+ -+#define MODE_CONTROL 0x11b -+#define MODE_CONTROL_SEL_MASK GENMASK(12, 8) -+#define MODE_CONTROL_XPCS 0x10 -+#define MODE_CONTROL_SGMII_PLUS 0x8 -+#define MODE_CONTROL_SGMII 0x4 -+#define MODE_CONTROL_SGMII_SEL_MASK GENMASK(6, 4) -+#define MODE_CONTROL_SGMII_PHY 1 -+#define MODE_CONTROL_SGMII_MAC 2 -+ -+#define QP_USXG_OPTION1 0x180 -+#define QP_USXG_OPTION1_DATAPASS BIT(0) -+#define QP_USXG_OPTION1_DATAPASS_SGMII 0 -+#define QP_USXG_OPTION1_DATAPASS_USXGMII 1 -+ -+#define BYPASS_TUNNING_IPG 0x189 -+#define BYPASS_TUNNING_IPG_MASK GENMASK(11, 0) -+ -+/* MDIO_MMD_PCS register */ -+#define PCS_CONTROL2 0x7 -+#define PCS_TYPE_MASK GENMASK(3, 0) -+#define PCS_TYPE_BASER 0 -+ -+#define PCS_EEE_CONTROL 0x14 -+#define EEE_CAPABILITY BIT(6) -+ -+#define PCS_STATUS1 0x20 -+#define PCS_BASER_UP BIT(12) -+ -+#define DIG_CTRL1 0x8000 -+#define DIG_CTRL1_USXGMII_EN BIT(9) -+#define DIG_CTRL1_XPCS_RESET BIT(15) -+#define FIFO_RESET_CH0 BIT(10) -+#define FIFO_RESET_CH1_CH2_CH3 BIT(5) -+ -+#define EEE_MODE_CONTROL 0x8006 -+#define EEE_LCT_RES GENMASK(11, 8) -+#define EEE_SIGN BIT(6) -+#define EEE_LRX_EN BIT(1) -+#define EEE_LTX_EN BIT(0) -+ -+#define PCS_TPC 0x8007 -+#define PCS_QXGMII_MODE_MASK GENMASK(12, 10) -+#define PCS_QXGMII_EN 0x5 -+ -+#define EEE_RX_TIMER 0x8009 -+#define EEE_RX_TIMER_100US_RES GENMASK(7, 0) -+#define EEE_RX_TIMER_RWR_RES GENMASK(12, 8) -+ -+#define AM_LINK_TIMER 0x800a -+#define AM_LINK_TIMER_VAL 0x6018 -+ -+#define EEE_MODE_CONTROL1 0x800b -+#define TRANS_LPI_MODE BIT(0) -+#define TRANS_RX_LPI_MODE BIT(8) -+ -+/* QXGMII channel MMD register */ -+#define MII_CONTROL 0x0 -+#define AUTO_NEGOTIATION_EN BIT(12) -+#define AUTO_NEGOTIATION_RESTART BIT(9) -+#define PCS_SPEED_2500 BIT(5) -+#define PCS_SPEED_1000 BIT(6) -+#define PCS_SPEED_100 BIT(13) -+#define PCS_SPEED_10 0 -+ -+#define DIG_CONTROL2 0x8001 -+#define MII_BIT_CONTROL BIT(8) -+#define TX_CONFIG BIT(3) -+#define AUTO_NEGOTIATION_CMPLT_INTR BIT(0) -+ -+#define XAUI_CONTROL 0x8004 -+#define TX_IPG_CHECK_DISABLE BIT(0) -+ - enum pcs_clk_id { - PCS_CLK, - PCS_RX_ROOT_CLK, -@@ -76,6 +162,8 @@ static const char *const pcs_clock_names - [PCS_TX_ROOT_CLK] = "pcs_tx_root", - }; - -+static const int qca8084_xpcs_ch_mmd[QCA8084_CHANNEL_MAX] = { 31, 26, 27, 28 }; -+ - struct mdio_device *qca8084_package_pcs_probe(struct device_node *pcs_np) - { - struct qca8084_pcs_data *pcs_data; -@@ -247,3 +335,289 @@ void qca8084_package_xpcs_and_pcs_remove - mdio_device_put(xpcs_mdiodev); - mdio_device_put(pcs_mdiodev); - } -+ -+static int qca8084_pcs_set_interface_mode(struct mdio_device *mdio_dev, -+ phy_interface_t ifmode) -+{ -+ int ret, hw_ifmode, data; -+ -+ switch (ifmode) { -+ case PHY_INTERFACE_MODE_SGMII: -+ hw_ifmode = MODE_CONTROL_SGMII; -+ data = QP_USXG_OPTION1_DATAPASS_SGMII; -+ break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ hw_ifmode = MODE_CONTROL_SGMII_PLUS; -+ data = QP_USXG_OPTION1_DATAPASS_SGMII; -+ break; -+ case PHY_INTERFACE_MODE_10G_QXGMII: -+ hw_ifmode = MODE_CONTROL_XPCS; -+ data = QP_USXG_OPTION1_DATAPASS_USXGMII; -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ /* For PLL stable under high temperature */ -+ ret = mdiodev_modify(mdio_dev, PLL_CONTROL, -+ PLL_CONTROL_CMLDIV2_IBSEL_MASK, -+ FIELD_PREP(PLL_CONTROL_CMLDIV2_IBSEL_MASK, 3)); -+ if (ret) -+ return ret; -+ -+ /* Configure the interface mode of PCS */ -+ ret = mdiodev_c45_modify(mdio_dev, MDIO_MMD_PMAPMD, MODE_CONTROL, -+ MODE_CONTROL_SEL_MASK, -+ FIELD_PREP(MODE_CONTROL_SEL_MASK, hw_ifmode)); -+ if (ret) -+ return ret; -+ -+ /* Data pass selects SGMII or USXGMII */ -+ return mdiodev_c45_modify(mdio_dev, MDIO_MMD_PMAPMD, QP_USXG_OPTION1, -+ QP_USXG_OPTION1_DATAPASS, -+ FIELD_PREP(QP_USXG_OPTION1_DATAPASS, data)); -+} -+ -+static int qca8084_do_calibration(struct mdio_device *mdio_dev) -+{ -+ int ret; -+ -+ ret = mdiodev_modify(mdio_dev, PLL_POWER_ON_AND_RESET, -+ PCS_ANA_SW_RESET, 0); -+ if (ret) -+ return ret; -+ -+ usleep_range(10000, 11000); -+ ret = mdiodev_modify(mdio_dev, PLL_POWER_ON_AND_RESET, -+ PCS_ANA_SW_RESET, PCS_ANA_SW_RESET); -+ if (ret) -+ return ret; -+ -+ /* Wait calibration done */ -+ return read_poll_timeout(mdiodev_c45_read, ret, -+ (ret & CALIBRATION_DONE), -+ 100, 100000, true, mdio_dev, -+ MDIO_MMD_PMAPMD, CALIBRATION4); -+} -+ -+ -+static int qca8084_xpcs_set_mode(struct mdio_device *xpcs_mdiodev) -+{ -+ int ret, val, i; -+ -+ /* Configure BaseR mode */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, PCS_CONTROL2, -+ PCS_TYPE_MASK, -+ FIELD_PREP(PCS_TYPE_MASK, PCS_TYPE_BASER)); -+ if (ret) -+ return ret; -+ -+ /* Wait BaseR link up */ -+ ret = read_poll_timeout(mdiodev_c45_read, val, -+ (val & PCS_BASER_UP), 1000, 100000, true, -+ xpcs_mdiodev, -+ MDIO_MMD_PCS, PCS_STATUS1); -+ if (ret) { -+ dev_err(&xpcs_mdiodev->dev, "BaseR link failed!\n"); -+ return ret; -+ } -+ -+ /* Enable USXGMII mode */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, DIG_CTRL1, -+ DIG_CTRL1_USXGMII_EN, -+ DIG_CTRL1_USXGMII_EN); -+ if (ret) -+ return ret; -+ -+ /* Configure QXGMII mode */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, PCS_TPC, -+ PCS_QXGMII_MODE_MASK, -+ FIELD_PREP(PCS_QXGMII_MODE_MASK, -+ PCS_QXGMII_EN)); -+ if (ret) -+ return ret; -+ -+ /* Configure AM interval */ -+ ret = mdiodev_c45_write(xpcs_mdiodev, MDIO_MMD_PCS, AM_LINK_TIMER, -+ AM_LINK_TIMER_VAL); -+ if (ret) -+ return ret; -+ -+ /* Reset XPCS */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, DIG_CTRL1, -+ DIG_CTRL1_XPCS_RESET, -+ DIG_CTRL1_XPCS_RESET); -+ if (ret) -+ return ret; -+ -+ /* Wait XPCS reset done */ -+ ret = read_poll_timeout(mdiodev_c45_read, val, -+ !(val & DIG_CTRL1_XPCS_RESET), -+ 1000, 100000, true, xpcs_mdiodev, -+ MDIO_MMD_PCS, DIG_CTRL1); -+ if (ret) { -+ dev_err(&xpcs_mdiodev->dev, "XPCS reset failed!\n"); -+ return ret; -+ } -+ -+ /* Enable auto-negotiation complete interrupt, using mii-4bit -+ * and TX configureation of PHY side on all XPCS channels. -+ */ -+ for (i = 0; i < QCA8084_CHANNEL_MAX; i++) { -+ ret = mdiodev_c45_modify(xpcs_mdiodev, qca8084_xpcs_ch_mmd[i], -+ DIG_CONTROL2, -+ (MII_BIT_CONTROL | TX_CONFIG | -+ AUTO_NEGOTIATION_CMPLT_INTR), -+ (TX_CONFIG | AUTO_NEGOTIATION_CMPLT_INTR)); -+ if (ret) -+ return ret; -+ -+ /* Enable auto-negotiation capability */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, qca8084_xpcs_ch_mmd[i], -+ MII_CONTROL, -+ AUTO_NEGOTIATION_EN, -+ AUTO_NEGOTIATION_EN); -+ if (ret) -+ return ret; -+ -+ /* Disable TX IPG check */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, qca8084_xpcs_ch_mmd[i], -+ XAUI_CONTROL, -+ TX_IPG_CHECK_DISABLE, -+ TX_IPG_CHECK_DISABLE); -+ if (ret) -+ return ret; -+ } -+ -+ /* Check EEE capability supported or not */ -+ ret = mdiodev_c45_read(xpcs_mdiodev, MDIO_MMD_PCS, PCS_EEE_CONTROL); -+ if (ret < 0) -+ return ret; -+ -+ if (ret & EEE_CAPABILITY) { -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, -+ EEE_MODE_CONTROL, -+ EEE_LCT_RES | EEE_SIGN, -+ FIELD_PREP(EEE_LCT_RES, 1) | EEE_SIGN); -+ if (ret) -+ return ret; -+ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, -+ EEE_RX_TIMER, -+ EEE_RX_TIMER_100US_RES | EEE_RX_TIMER_RWR_RES, -+ FIELD_PREP(EEE_RX_TIMER_100US_RES, 0xc8) | -+ FIELD_PREP(EEE_RX_TIMER_RWR_RES, 0x1c)); -+ if (ret) -+ return ret; -+ -+ /* Enable EEE LPI */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, -+ EEE_MODE_CONTROL1, -+ TRANS_LPI_MODE | TRANS_RX_LPI_MODE, -+ TRANS_LPI_MODE | TRANS_RX_LPI_MODE); -+ if (ret) -+ return ret; -+ -+ /* Enable TX/RX LPI pattern */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, -+ EEE_MODE_CONTROL, -+ EEE_LRX_EN | EEE_LTX_EN, -+ EEE_LRX_EN | EEE_LTX_EN); -+ } -+ -+ return ret; -+} -+ -+static int qca8084_pcs_set_mode(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev) -+{ -+ struct qca8084_xpcs_data *xpcs_data = mdiodev_get_drvdata(xpcs_mdiodev); -+ struct qca8084_pcs_data *pcs_data = mdiodev_get_drvdata(pcs_mdiodev); -+ struct qca8084_xpcs_channel_priv xpcs_ch; -+ int ret, channel; -+ -+ /* Enable clock and de-assert for PCS. */ -+ ret = clk_prepare_enable(pcs_data->clks[PCS_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = reset_control_deassert(pcs_data->rstc); -+ if (ret) -+ return ret; -+ -+ /* IPG tunning selection for RX, TX and XGMII of all channels. */ -+ ret = mdiodev_c45_modify(pcs_mdiodev, MDIO_MMD_PMAPMD, -+ BYPASS_TUNNING_IPG, -+ BYPASS_TUNNING_IPG_MASK, 0); -+ if (ret) -+ return ret; -+ -+ reset_control_assert(xpcs_data->rstc); -+ -+ ret = qca8084_pcs_set_interface_mode(pcs_mdiodev, -+ PHY_INTERFACE_MODE_10G_QXGMII); -+ if (ret) -+ return ret; -+ -+ /* Reset of 4 channels */ -+ for (channel = 0; channel < QCA8084_CHANNEL_MAX; channel++) { -+ xpcs_ch = xpcs_data->xpcs_ch[channel]; -+ ret = reset_control_reset(xpcs_ch.rstcs); -+ if (ret) -+ return ret; -+ } -+ -+ ret = qca8084_do_calibration(pcs_mdiodev); -+ if (ret) { -+ dev_err(&pcs_mdiodev->dev, "PCS calibration timeout!\n"); -+ return ret; -+ } -+ -+ /* Enable PCS SSC to fix mode */ -+ ret = mdiodev_c45_modify(pcs_mdiodev, MDIO_MMD_PMAPMD, -+ CDR_CONTRL, SSC_FIX_MODE, SSC_FIX_MODE); -+ if (ret) -+ return ret; -+ -+ return reset_control_deassert(xpcs_data->rstc); -+} -+ -+static int qca8084_xpcs_clock_parent_set(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev) -+{ -+ struct qca8084_xpcs_data *xpcs_data = mdiodev_get_drvdata(xpcs_mdiodev); -+ struct qca8084_pcs_data *pcs_data = mdiodev_get_drvdata(pcs_mdiodev); -+ struct qca8084_xpcs_channel_priv xpcs_ch; -+ int ret, channel; -+ -+ for (channel = 0; channel < QCA8084_CHANNEL_MAX; channel++) { -+ xpcs_ch = xpcs_data->xpcs_ch[channel]; -+ ret = clk_set_parent(xpcs_ch.clks[XPCS_RX_SRC_CLK], -+ pcs_data->clks[PCS_RX_ROOT_CLK]); -+ if (ret) -+ return ret; -+ -+ ret = clk_set_parent(xpcs_ch.clks[XPCS_TX_SRC_CLK], -+ pcs_data->clks[PCS_TX_ROOT_CLK]); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+int qca8084_qxgmii_set_mode(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev) -+{ -+ int ret; -+ -+ ret = qca8084_xpcs_clock_parent_set(xpcs_mdiodev, pcs_mdiodev); -+ if (ret) -+ return ret; -+ -+ ret = qca8084_pcs_set_mode(xpcs_mdiodev, pcs_mdiodev); -+ if (ret) -+ return ret; -+ -+ return qca8084_xpcs_set_mode(xpcs_mdiodev); -+} ---- a/drivers/net/phy/qcom/qca8084_serdes.h -+++ b/drivers/net/phy/qcom/qca8084_serdes.h -@@ -15,4 +15,6 @@ struct mdio_device *qca8084_package_pcs_ - struct mdio_device *qca8084_package_xpcs_probe(struct device_node *xpcs_np); - void qca8084_package_xpcs_and_pcs_remove(struct mdio_device *xpcs_mdiodev, - struct mdio_device *pcs_mdiodev); -+int qca8084_qxgmii_set_mode(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev); - #endif /* _QCA8084_SERDES_H_ */ ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -926,6 +926,14 @@ static int qca8084_phy_package_config_in - - usleep_range(10000, 11000); - -+ /* Configure PCS working on 10G-QXGMII mode */ -+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ ret = qca8084_qxgmii_set_mode(shared_priv->mdiodev[1], -+ shared_priv->mdiodev[0]); -+ if (ret) -+ return ret; -+ } -+ - /* Initialize the PHY package clock and reset, which is the - * necessary config sequence after GPIO reset on the PHY package. - */ -@@ -1164,6 +1172,9 @@ static int qca8084_probe(struct phy_devi - - static void qca8084_remove(struct phy_device *phydev) - { -+ if (phydev->interface != PHY_INTERFACE_MODE_10G_QXGMII) -+ return; -+ - if (phy_package_remove_once(phydev)) - qca8084_phy_package_remove_once(phydev); - } diff --git a/target/linux/qualcommbe/patches-6.12/0373-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch b/target/linux/qualcommbe/patches-6.12/0373-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch deleted file mode 100644 index 1244837fd5..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0373-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch +++ /dev/null @@ -1,251 +0,0 @@ -From 2f5b7e167d847a5b5b74a91f991d48635453c55f Mon Sep 17 00:00:00 2001 -From: Luo Jie -Date: Mon, 23 Sep 2024 21:24:56 +0800 -Subject: [PATCH] net: phy: qca808x: Add QCA8084 SerDes speed config - -When the link of PHY is changed, the XPCS channel needs to be -configured to adapt the current link status. - -Change-Id: I50d8973691dff133fc6bec1e9a1043bb646811fc -Signed-off-by: Luo Jie -Alex G: Use phy_package_get_*() accessors -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/phy/qcom/qca8084_serdes.c | 159 ++++++++++++++++++++++++++ - drivers/net/phy/qcom/qca8084_serdes.h | 3 + - drivers/net/phy/qcom/qca808x.c | 15 ++- - 3 files changed, 175 insertions(+), 2 deletions(-) - ---- a/drivers/net/phy/qcom/qca8084_serdes.c -+++ b/drivers/net/phy/qcom/qca8084_serdes.c -@@ -4,6 +4,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -55,6 +56,13 @@ - #define BYPASS_TUNNING_IPG 0x189 - #define BYPASS_TUNNING_IPG_MASK GENMASK(11, 0) - -+#define QP_USXG_RESET 0x18c -+#define QP_USXG_SGMII_FUNC_RESET BIT(4) -+#define QP_USXG_P3_FUNC_RESET BIT(3) -+#define QP_USXG_P2_FUNC_RESET BIT(2) -+#define QP_USXG_P1_FUNC_RESET BIT(1) -+#define QP_USXG_P0_FUNC_RESET BIT(0) -+ - /* MDIO_MMD_PCS register */ - #define PCS_CONTROL2 0x7 - #define PCS_TYPE_MASK GENMASK(3, 0) -@@ -107,6 +115,9 @@ - #define TX_CONFIG BIT(3) - #define AUTO_NEGOTIATION_CMPLT_INTR BIT(0) - -+#define PCS_ERR_SEL 0x8002 -+#define PCS_AN_COMPLETE BIT(0) -+ - #define XAUI_CONTROL 0x8004 - #define TX_IPG_CHECK_DISABLE BIT(0) - -@@ -621,3 +632,151 @@ int qca8084_qxgmii_set_mode(struct mdio_ - - return qca8084_xpcs_set_mode(xpcs_mdiodev); - } -+ -+static int qca8084_pcs_ipg_tune_reset(struct mdio_device *mdio_dev, -+ int reset_function) -+{ -+ int ret; -+ -+ ret = mdiodev_c45_modify(mdio_dev, MDIO_MMD_PMAPMD, QP_USXG_RESET, -+ reset_function, 0); -+ if (ret) -+ return ret; -+ -+ usleep_range(1000, 1100); -+ -+ return mdiodev_c45_modify(mdio_dev, MDIO_MMD_PMAPMD, QP_USXG_RESET, -+ reset_function, reset_function); -+} -+ -+static int qca8084_xpcs_an_restart(struct mdio_device *xpcs_mdiodev, -+ int channel) -+{ -+ int ret, mmd; -+ -+ mmd = qca8084_xpcs_ch_mmd[channel]; -+ -+ /* Restart auto-negotiation */ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, mmd, MII_CONTROL, -+ AUTO_NEGOTIATION_RESTART, -+ AUTO_NEGOTIATION_RESTART); -+ if (ret) -+ return ret; -+ -+ usleep_range(1000, 1100); -+ -+ /* Clear pcs auto-negotiation complete interrupt */ -+ return mdiodev_c45_modify(xpcs_mdiodev, mmd, PCS_ERR_SEL, -+ PCS_AN_COMPLETE, 0); -+} -+ -+void qca8084_qxgmii_set_speed(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev, -+ int channel, int speed) -+{ -+ struct qca8084_xpcs_data *xpcs_data = mdiodev_get_drvdata(xpcs_mdiodev); -+ struct qca8084_xpcs_channel_priv *xpcs_ch; -+ int mmd, i, ret, xpcs_rate; -+ unsigned long rate; -+ -+ for (i = 0; i < QCA8084_CHANNEL_MAX; i++) { -+ xpcs_ch = &(xpcs_data->xpcs_ch[channel]); -+ if (channel == xpcs_ch->ch_id) -+ break; -+ } -+ -+ if (i == QCA8084_CHANNEL_MAX) { -+ dev_err(&xpcs_mdiodev->dev, "Invalid channel %d\n", channel); -+ return; -+ } -+ -+ mmd = qca8084_xpcs_ch_mmd[channel]; -+ -+ ret = qca8084_xpcs_an_restart(xpcs_mdiodev, channel); -+ if (ret) -+ return; -+ -+ switch (speed) { -+ case SPEED_2500: -+ rate = 312500000; -+ xpcs_rate = PCS_SPEED_2500; -+ break; -+ case SPEED_1000: -+ rate = 125000000; -+ xpcs_rate = PCS_SPEED_1000; -+ break; -+ case SPEED_100: -+ rate = 25000000; -+ xpcs_rate = PCS_SPEED_100; -+ break; -+ case SPEED_10: -+ default: -+ rate = 2500000; -+ xpcs_rate = PCS_SPEED_10; -+ break; -+ } -+ -+ clk_set_rate(xpcs_ch->clks[XPCS_RX_CLK], rate); -+ clk_set_rate(xpcs_ch->clks[XPCS_TX_CLK], rate); -+ -+ /* XGMII takes the different clock rate 78.125Mhz from XPCS clock -+ * when linked at 2500M. -+ */ -+ if (speed == SPEED_2500) -+ rate = 78125000; -+ -+ clk_set_rate(xpcs_ch->clks[XPCS_XGMII_RX_CLK], rate); -+ clk_set_rate(xpcs_ch->clks[XPCS_XGMII_TX_CLK], rate); -+ -+ ret = mdiodev_c45_modify(xpcs_mdiodev, mmd, MII_CONTROL, -+ PCS_SPEED_2500 | PCS_SPEED_1000 | -+ PCS_SPEED_100 | PCS_SPEED_10, -+ xpcs_rate); -+ if (ret) -+ return; -+ -+ /* Disable clocks if link down with unknown speed. The channel clocks -+ * are disabled by default, __clk_is_enabled() is used to avoid -+ * disabling the clocks that is already in the disabled status. -+ */ -+ if (speed == SPEED_UNKNOWN) { -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_RX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_RX_CLK]); -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_TX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_TX_CLK]); -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_PORT_RX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_PORT_RX_CLK]); -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_PORT_TX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_PORT_TX_CLK]); -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_XGMII_RX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_XGMII_RX_CLK]); -+ if (__clk_is_enabled(xpcs_ch->clks[XPCS_XGMII_TX_CLK])) -+ clk_disable_unprepare(xpcs_ch->clks[XPCS_XGMII_TX_CLK]); -+ } else { -+ clk_prepare_enable(xpcs_ch->clks[XPCS_RX_CLK]); -+ clk_prepare_enable(xpcs_ch->clks[XPCS_TX_CLK]); -+ clk_prepare_enable(xpcs_ch->clks[XPCS_PORT_RX_CLK]); -+ clk_prepare_enable(xpcs_ch->clks[XPCS_PORT_TX_CLK]); -+ clk_prepare_enable(xpcs_ch->clks[XPCS_XGMII_RX_CLK]); -+ clk_prepare_enable(xpcs_ch->clks[XPCS_XGMII_TX_CLK]); -+ } -+ -+ msleep(100); -+ -+ ret = reset_control_reset(xpcs_ch->rstcs); -+ if (ret) -+ return; -+ -+ /* Reset IPG tune of PCS device. */ -+ ret = qca8084_pcs_ipg_tune_reset(pcs_mdiodev, BIT(channel)); -+ if (ret) -+ return; -+ -+ if (channel == 0) -+ mdiodev_c45_modify(xpcs_mdiodev, MDIO_MMD_PCS, DIG_CTRL1, -+ FIFO_RESET_CH0, FIFO_RESET_CH0); -+ else -+ mdiodev_c45_modify(xpcs_mdiodev, mmd, DIG_CTRL1, -+ FIFO_RESET_CH1_CH2_CH3, -+ FIFO_RESET_CH1_CH2_CH3); -+} ---- a/drivers/net/phy/qcom/qca8084_serdes.h -+++ b/drivers/net/phy/qcom/qca8084_serdes.h -@@ -17,4 +17,7 @@ void qca8084_package_xpcs_and_pcs_remove - struct mdio_device *pcs_mdiodev); - int qca8084_qxgmii_set_mode(struct mdio_device *xpcs_mdiodev, - struct mdio_device *pcs_mdiodev); -+void qca8084_qxgmii_set_speed(struct mdio_device *xpcs_mdiodev, -+ struct mdio_device *pcs_mdiodev, -+ int channel, int speed); - #endif /* _QCA8084_SERDES_H_ */ ---- a/drivers/net/phy/qcom/qca808x.c -+++ b/drivers/net/phy/qcom/qca808x.c -@@ -976,6 +976,7 @@ static int qca8084_config_init(struct ph - - static void qca8084_link_change_notify(struct phy_device *phydev) - { -+ struct qca808x_shared_priv *shared_priv; - int ret; - - /* Assert the FIFO between PHY and MAC. */ -@@ -1007,14 +1008,24 @@ static void qca8084_link_change_notify(s - } - } - -- /* Enable IPG level 10 to 11 tuning for link speed 1000M in the -+ /* Enable IPG level 10 to 11 tuning for link speed 1000M and -+ * configure the related XPCS channel with the phydev in the - * 10G_QXGMII mode. - */ -- if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) -+ if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ shared_priv = phy_package_get_priv(phydev); -+ struct qca808x_priv *priv = phydev->priv; -+ - phy_modify_mmd(phydev, MDIO_MMD_AN, QCA8084_MMD7_IPG_OP, - QCA8084_IPG_10_TO_11_EN, - phydev->speed == SPEED_1000 ? - QCA8084_IPG_10_TO_11_EN : 0); -+ -+ qca8084_qxgmii_set_speed(shared_priv->mdiodev[1], -+ shared_priv->mdiodev[0], -+ priv->channel_id, -+ phydev->speed); -+ } - } - - /* QCA8084 is a four-port PHY, which integrates the clock controller, diff --git a/target/linux/qualcommbe/patches-6.12/0374-dt-bindings-pwm-add-IPQ6018-binding.patch b/target/linux/qualcommbe/patches-6.12/0374-dt-bindings-pwm-add-IPQ6018-binding.patch deleted file mode 100644 index 07a64a0f61..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0374-dt-bindings-pwm-add-IPQ6018-binding.patch +++ /dev/null @@ -1,181 +0,0 @@ -From patchwork Fri Nov 28 10:29:13 2025 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: George Moussalem via B4 Relay - -X-Patchwork-Id: 2169931 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@legolas.ozlabs.org -Authentication-Results: legolas.ozlabs.org; - dkim=pass (2048-bit key; - unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 - header.s=k20201202 header.b=qU845OFh; - dkim-atps=neutral -Authentication-Results: legolas.ozlabs.org; - spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org - (client-ip=213.196.21.55; helo=ams.mirrors.kernel.org; - envelope-from=linux-pwm+bounces-7721-incoming=patchwork.ozlabs.org@vger.kernel.org; - receiver=patchwork.ozlabs.org) -Received: from ams.mirrors.kernel.org (ams.mirrors.kernel.org [213.196.21.55]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange X25519 server-signature ECDSA (secp384r1)) - (No client certificate requested) - by legolas.ozlabs.org (Postfix) with ESMTPS id 4dHqMJ5gXFz1yDj - for ; Fri, 28 Nov 2025 21:30:52 +1100 (AEDT) -Received: from smtp.subspace.kernel.org (relay.kernel.org [52.25.139.140]) - (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by ams.mirrors.kernel.org (Postfix) with ESMTPS id 0783B352ED3 - for ; Fri, 28 Nov 2025 10:29:38 +0000 (UTC) -Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) - by smtp.subspace.kernel.org (Postfix) with ESMTP id 5B94630C370; - Fri, 28 Nov 2025 10:29:23 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b="qU845OFh" -X-Original-To: linux-pwm@vger.kernel.org -Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org - [10.30.226.201]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by smtp.subspace.kernel.org (Postfix) with ESMTPS id 27F7930B525; - Fri, 28 Nov 2025 10:29:22 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - arc=none smtp.client-ip=10.30.226.201 -ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; - t=1764325763; cv=none; - b=EZdjLPtvTBCzr24d6uks1u6xas9FiqaXRtClecDuZQfT8aKQnU9LDJSaswvWaMHcpRkbBujRZFntPyNohlI+P0vj+Zlmof30QOr4Cw61jr3wGlfQNPsH0ib1AuyADzOHFj1W0c+mfqIs2onOC15OGkIc+DWrCsNXePSM/0/0XQM= -ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; - s=arc-20240116; t=1764325763; c=relaxed/simple; - bh=fNS3C2NaCK+go2nQNBlkD9EyrNNHIb0CZcl2LNOQBmE=; - h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: - In-Reply-To:To:Cc; - b=iRh98acHGzMCOeqCHb4A30mpdpFjHp96ccf65E1oF0kaAGzHdhWM7H56NI22q+0GXrY7o91H7F+x1Dz1spr6OZc6bMG4DuV8oap/vEdtyjApt+7zNFUl0PcrMSLSe2YVFaWgVvk7/IenJxJhEqcPWhsFZR+HGM4iuhv2lP3w32c= -ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b=qU845OFh; arc=none smtp.client-ip=10.30.226.201 -Received: by smtp.kernel.org (Postfix) with ESMTPS id BDCD9C113D0; - Fri, 28 Nov 2025 10:29:22 +0000 (UTC) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; - s=k20201202; t=1764325762; - bh=fNS3C2NaCK+go2nQNBlkD9EyrNNHIb0CZcl2LNOQBmE=; - h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; - b=qU845OFhU3cciT1imeWuTMro85tXusIJt99AroBlTX9t+aY8oZwFPjd4KhPNki2mi - gK5GyKlndlusCuuiAqnaaQahXFM6I16gAWHOaCMORh1VJ0Vdli6WOo66C/KlZBrRPN - 4x/+oieXIooU174yYf8PhFevu9NVbs1arlck6sgsyyW7HB0WwedreqFH2qfmTO4NyF - zDymUL0G9Og8hd89PsEyZkkDLVroKnvjU7POud+8el6a6PvDYUOmCTM/rsu2gJX64s - k9Nm5ZJmRWfQvaku8McARECvY/QLX3P+pweAuDyazDxpGgTTxPqMbyywNEBjfVYu+o - ksKwowwfTPqHg== -Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org - (localhost.localdomain [127.0.0.1]) - by smtp.lore.kernel.org (Postfix) with ESMTP id A0784D116EA; - Fri, 28 Nov 2025 10:29:22 +0000 (UTC) -From: George Moussalem via B4 Relay - -Date: Fri, 28 Nov 2025 14:29:13 +0400 -Subject: [PATCH v19 1/6] dt-bindings: pwm: add IPQ6018 binding -Precedence: bulk -X-Mailing-List: linux-pwm@vger.kernel.org -List-Id: -List-Subscribe: -List-Unsubscribe: -MIME-Version: 1.0 -Message-Id: <20251128-ipq-pwm-v19-1-13bc704cc6a5@outlook.com> -References: <20251128-ipq-pwm-v19-0-13bc704cc6a5@outlook.com> -In-Reply-To: <20251128-ipq-pwm-v19-0-13bc704cc6a5@outlook.com> -To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , - Rob Herring , Krzysztof Kozlowski , - Conor Dooley , Baruch Siach , - Bjorn Andersson , - Konrad Dybcio -Cc: linux-arm-msm@vger.kernel.org, linux-pwm@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, - George Moussalem , - Devi Priya , - Baruch Siach , - Bjorn Andersson , - Krzysztof Kozlowski -X-Mailer: b4 0.14.2 -X-Developer-Signature: v=1; a=ed25519-sha256; t=1764325760; l=2042; - i=george.moussalem@outlook.com; s=20250321; h=from:subject:message-id; - bh=8ayVJ9z0kZoRdShrug1dJ1pjUonk4k9SO1yJzG93fMg=; - b=o0lsJw1oX/jEPu9xLh+Ovt+AbJGXh3X8na0H8Ko0Vcl7PFsYQQEOP9HhJAp8Y5XyBFBcroa6x - AHFNonYE7aVArYgsi5KqkDnui4xwpKQpD5RwWJ3JFA96K5IALoApziu -X-Developer-Key: i=george.moussalem@outlook.com; a=ed25519; - pk=/PuRTSI9iYiHwcc6Nrde8qF4ZDhJBlUgpHdhsIjnqIk= -X-Endpoint-Received: by B4 Relay for george.moussalem@outlook.com/20250321 - with auth_id=364 -X-Original-From: George Moussalem -Reply-To: george.moussalem@outlook.com - -From: Devi Priya - -DT binding for the PWM block in Qualcomm IPQ6018 SoC. - -Reviewed-by: Bjorn Andersson -Reviewed-by: Krzysztof Kozlowski -Co-developed-by: Baruch Siach -Signed-off-by: Baruch Siach -Signed-off-by: Devi Priya -Signed-off-by: George Moussalem ---- - .../devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml | 51 ++++++++++++++++++++++ - 1 file changed, 51 insertions(+) - ---- /dev/null -+++ b/Documentation/devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml -@@ -0,0 +1,51 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/pwm/qcom,ipq6018-pwm.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Qualcomm IPQ6018 PWM controller -+ -+maintainers: -+ - George Moussalem -+ -+properties: -+ compatible: -+ oneOf: -+ - items: -+ - enum: -+ - qcom,ipq5018-pwm -+ - qcom,ipq5332-pwm -+ - qcom,ipq9574-pwm -+ - const: qcom,ipq6018-pwm -+ - const: qcom,ipq6018-pwm -+ -+ reg: -+ maxItems: 1 -+ -+ clocks: -+ maxItems: 1 -+ -+ "#pwm-cells": -+ const: 3 -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - "#pwm-cells" -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ -+ pwm: pwm@1941010 { -+ compatible = "qcom,ipq6018-pwm"; -+ reg = <0x01941010 0x20>; -+ clocks = <&gcc GCC_ADSS_PWM_CLK>; -+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>; -+ assigned-clock-rates = <100000000>; -+ #pwm-cells = <3>; -+ }; diff --git a/target/linux/qualcommbe/patches-6.12/0375-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch b/target/linux/qualcommbe/patches-6.12/0375-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch deleted file mode 100644 index 670b360e98..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0375-pwm-driver-for-qualcomm-ipq6018-pwm-block.patch +++ /dev/null @@ -1,403 +0,0 @@ -From patchwork Wed Feb 4 11:25:08 2026 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: George Moussalem via B4 Relay - -X-Patchwork-Id: 2192910 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@legolas.ozlabs.org -Authentication-Results: legolas.ozlabs.org; - dkim=pass (2048-bit key; - unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 - header.s=k20201202 header.b=WGUCMoYx; - dkim-atps=neutral -Authentication-Results: legolas.ozlabs.org; - spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org - (client-ip=172.105.105.114; helo=tor.lore.kernel.org; - envelope-from=linux-pwm+bounces-8087-incoming=patchwork.ozlabs.org@vger.kernel.org; - receiver=patchwork.ozlabs.org) -Received: from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange x25519) - (No client certificate requested) - by legolas.ozlabs.org (Postfix) with ESMTPS id 4f5dMp0fDDz1xqf - for ; Wed, 04 Feb 2026 22:26:14 +1100 (AEDT) -Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org - [100.90.174.1]) - by tor.lore.kernel.org (Postfix) with ESMTP id EBABA301D322 - for ; Wed, 4 Feb 2026 11:25:18 +0000 (UTC) -Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) - by smtp.subspace.kernel.org (Postfix) with ESMTP id 498E93ECBC6; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b="WGUCMoYx" -X-Original-To: linux-pwm@vger.kernel.org -Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org - [10.30.226.201]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1653D3E9F8E; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - arc=none smtp.client-ip=10.30.226.201 -ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; - t=1770204314; cv=none; - b=G3d0Ri0xw7F/u2rUoaF2eprL1ihrTvDSfCszkp2ciK2Y+UB3YSBt1K9D5nrbQw3bG1mHFZSO34nH/NZUQUoP97w8cJNILcVALgdGNfpM1vdDsKcRjomVZOvJi5sTvm2qnS4gIzL5DhybGv6UMOPcMrPM4TyZjpnvnJyWo9twGXE= -ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; - s=arc-20240116; t=1770204314; c=relaxed/simple; - bh=DlyTmDysGY1XB33v65FxlGZh2bVxvGJcWBwNBttMHy4=; - h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: - In-Reply-To:To:Cc; - b=oscy1mdUqAhot2KYVVHi6uWkqWGm1fzDdZJUn82fx79nITsOMMaDBwep6Ra0KSpsxVMrI0KvqGJf5Aa68+YmcJpXOGKERtXl98pFEsTsnHR8ofyWZ5r2lR8Xiojdk3aCWuj3pkgi61p9TwpvAsXI4eZU0JoqNv2Ty8HO6hF2+cI= -ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b=WGUCMoYx; arc=none smtp.client-ip=10.30.226.201 -Received: by smtp.kernel.org (Postfix) with ESMTPS id C1097C2BCAF; - Wed, 4 Feb 2026 11:25:13 +0000 (UTC) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; - s=k20201202; t=1770204313; - bh=DlyTmDysGY1XB33v65FxlGZh2bVxvGJcWBwNBttMHy4=; - h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; - b=WGUCMoYxqwybcHrn+vGBd5QHaN5JxKMe0VHNxaeZmtbFd0vYZ3BwJ8m5hAjyRZ0eD - 2JIVvL9CxJeb48YIWZL8Hp49Ofp7FboBk7Q31N1+sBMQOC74MJNfvnFS9aMDNmTwJc - /vWoridD8Vn4Nj7bwQyhMAkreL54siL8bGUwW32yihFKR1AztlfhSE8roX72luaGMc - ALHuZzPPpCZFC4ZQ55PvaDHDAdBAplA3bVN0hcawiL/9jlpNiFoFsNHNOSmYgbkxIH - KW9GymmfG5d9cinrJZ2EThR1WDiIs41hnH1ijcK7vMMG3L6LoXzyIrjZo973bSp+oB - H5T79DAQ5KXZA== -Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org - (localhost.localdomain [127.0.0.1]) - by smtp.lore.kernel.org (Postfix) with ESMTP id AABE3E95389; - Wed, 4 Feb 2026 11:25:13 +0000 (UTC) -From: George Moussalem via B4 Relay - -Date: Wed, 04 Feb 2026 15:25:08 +0400 -Subject: [PATCH v20 2/6] pwm: driver for qualcomm ipq6018 pwm block -Precedence: bulk -X-Mailing-List: linux-pwm@vger.kernel.org -List-Id: -List-Subscribe: -List-Unsubscribe: -MIME-Version: 1.0 -Message-Id: <20260204-ipq-pwm-v20-2-91733011a3d1@outlook.com> -References: <20260204-ipq-pwm-v20-0-91733011a3d1@outlook.com> -In-Reply-To: <20260204-ipq-pwm-v20-0-91733011a3d1@outlook.com> -To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , - Rob Herring , Krzysztof Kozlowski , - Conor Dooley , Baruch Siach , - Bjorn Andersson , - Konrad Dybcio -Cc: linux-arm-msm@vger.kernel.org, linux-pwm@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, - George Moussalem , - Devi Priya , - Baruch Siach -X-Mailer: b4 0.14.2 -X-Developer-Signature: v=1; a=ed25519-sha256; t=1770204310; l=9677; - i=george.moussalem@outlook.com; s=20250321; h=from:subject:message-id; - bh=lqVC0W9FHdaTi1eT81frsdr/MvrSo0xMFV72k7YrO7I=; - b=mcjrEkuzodOMpsOdLZkQ609EXbJZFxJ8sU8yRwppwYWMDGETj4y5NtRIMVLi7GxOiU0zqcWls - CZHLZJaNDRaCaTzN1DMBfmpBhwkY/Hu+GKk+Nh9uBfpU2UxvCU4SSmG -X-Developer-Key: i=george.moussalem@outlook.com; a=ed25519; - pk=/PuRTSI9iYiHwcc6Nrde8qF4ZDhJBlUgpHdhsIjnqIk= -X-Endpoint-Received: by B4 Relay for george.moussalem@outlook.com/20250321 - with auth_id=364 -X-Original-From: George Moussalem -Reply-To: george.moussalem@outlook.com - -From: Devi Priya - -Driver for the PWM block in Qualcomm IPQ6018 line of SoCs. Based on -driver from downstream Codeaurora kernel tree. Removed support for older -(V1) variants because I have no access to that hardware. - -Tested on IPQ5018 and IPQ6010 based hardware. - -Co-developed-by: Baruch Siach -Signed-off-by: Baruch Siach -Signed-off-by: Devi Priya -Reviewed-by: Bjorn Andersson -Signed-off-by: George Moussalem ---- ---- - drivers/pwm/Kconfig | 12 +++ - drivers/pwm/Makefile | 1 + - drivers/pwm/pwm-ipq.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 252 insertions(+) - ---- a/drivers/pwm/Kconfig -+++ b/drivers/pwm/Kconfig -@@ -319,6 +319,18 @@ config PWM_INTEL_LGM - To compile this driver as a module, choose M here: the module - will be called pwm-intel-lgm. - -+config PWM_IPQ -+ tristate "IPQ PWM support" -+ depends on ARCH_QCOM || COMPILE_TEST -+ depends on HAVE_CLK && HAS_IOMEM -+ help -+ Generic PWM framework driver for IPQ PWM block which supports -+ 4 pwm channels. Each of the these channels can be configured -+ independent of each other. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called pwm-ipq. -+ - config PWM_IQS620A - tristate "Azoteq IQS620A PWM support" - depends on MFD_IQS62X || COMPILE_TEST ---- a/drivers/pwm/Makefile -+++ b/drivers/pwm/Makefile -@@ -27,6 +27,7 @@ obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o - obj-$(CONFIG_PWM_IMX27) += pwm-imx27.o - obj-$(CONFIG_PWM_IMX_TPM) += pwm-imx-tpm.o - obj-$(CONFIG_PWM_INTEL_LGM) += pwm-intel-lgm.o -+obj-$(CONFIG_PWM_IPQ) += pwm-ipq.o - obj-$(CONFIG_PWM_IQS620A) += pwm-iqs620a.o - obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o - obj-$(CONFIG_PWM_KEEMBAY) += pwm-keembay.o ---- /dev/null -+++ b/drivers/pwm/pwm-ipq.c -@@ -0,0 +1,239 @@ -+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 -+/* -+ * Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved. -+ * -+ * Hardware notes / Limitations: -+ * - The PWM controller has no publicly available datasheet. -+ * - Each of the four channels is programmed via two 32-bit registers -+ * (REG0 and REG1 at 8-byte stride). -+ * - Period and duty-cycle reconfiguration is fully atomic: new divider, -+ * pre-divider, and high-duration values are latched by setting the -+ * UPDATE bit (bit 30 in REG1). The hardware applies the new settings -+ * at the beginning of the next period without disabling the output, -+ * so the currently running period is always completed. -+ * - On disable (clearing the ENABLE bit 31 in REG1), the hardware -+ * finishes the current period before stopping the output. The pin -+ * is then driven to the inactive (low) level. -+ * - Upon disabling, the hardware resets the pre-divider (PRE_DIV) and divider -+ * fields (PWM_DIV) in REG0 and REG1 to 0x0000 and 0x0001 respectively. -+ * - Only normal polarity is supported. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* The frequency range supported is 1 Hz to clock rate */ -+#define IPQ_PWM_MAX_PERIOD_NS ((u64)NSEC_PER_SEC) -+ -+/* -+ * Two 32-bit registers for each PWM: REG0, and REG1. -+ * Base offset for PWM #i is at 8 * #i. -+ */ -+#define IPQ_PWM_REG0 0 -+#define IPQ_PWM_REG0_PWM_DIV GENMASK(15, 0) -+#define IPQ_PWM_REG0_HI_DURATION GENMASK(31, 16) -+ -+#define IPQ_PWM_REG1 4 -+#define IPQ_PWM_REG1_PRE_DIV GENMASK(15, 0) -+ -+/* -+ * The max value specified for each field is based on the number of bits -+ * in the pwm control register for that field (16-bit) -+ */ -+#define IPQ_PWM_MAX_DIV FIELD_MAX(IPQ_PWM_REG0_PWM_DIV) -+ -+/* -+ * Enable bit is set to enable output toggling in pwm device. -+ * Update bit is set to trigger the change and is unset automatically -+ * to reflect the changed divider and high duration values in register. -+ */ -+#define IPQ_PWM_REG1_UPDATE BIT(30) -+#define IPQ_PWM_REG1_ENABLE BIT(31) -+ -+struct ipq_pwm_chip { -+ void __iomem *mem; -+ unsigned long clk_rate; -+}; -+ -+static struct ipq_pwm_chip *ipq_pwm_from_chip(struct pwm_chip *chip) -+{ -+ return pwmchip_get_drvdata(chip); -+} -+ -+static unsigned int ipq_pwm_reg_read(struct pwm_device *pwm, unsigned int reg) -+{ -+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip); -+ unsigned int off = 8 * pwm->hwpwm + reg; -+ -+ return readl(ipq_chip->mem + off); -+} -+ -+static void ipq_pwm_reg_write(struct pwm_device *pwm, unsigned int reg, -+ unsigned int val) -+{ -+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip); -+ unsigned int off = 8 * pwm->hwpwm + reg; -+ -+ writel(val, ipq_chip->mem + off); -+} -+ -+static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, -+ const struct pwm_state *state) -+{ -+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip); -+ unsigned int pre_div, pwm_div; -+ u64 period_ns, duty_ns; -+ unsigned long val = 0; -+ unsigned long hi_dur; -+ -+ if (state->polarity != PWM_POLARITY_NORMAL) -+ return -EINVAL; -+ -+ if (!ipq_chip->clk_rate) -+ return -EINVAL; -+ -+ if (state->period < DIV64_U64_ROUND_UP(NSEC_PER_SEC, -+ ipq_chip->clk_rate)) -+ return -ERANGE; -+ -+ period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS); -+ duty_ns = min(state->duty_cycle, period_ns); -+ -+ pwm_div = IPQ_PWM_MAX_DIV - 1; -+ pre_div = mul_u64_u64_div_u64(period_ns, ipq_chip->clk_rate, -+ (u64)NSEC_PER_SEC * (pwm_div + 1)); -+ pre_div = (pre_div > 0) ? pre_div - 1 : 0; -+ -+ if (pre_div > IPQ_PWM_MAX_DIV) -+ pre_div = IPQ_PWM_MAX_DIV; -+ -+ /* -+ * high duration = pwm duty * (pwm div + 1) -+ * pwm duty = duty_ns / period_ns -+ */ -+ hi_dur = mul_u64_u64_div_u64(duty_ns, ipq_chip->clk_rate, -+ (u64)(pre_div + 1) * NSEC_PER_SEC); -+ -+ val = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) | -+ FIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div); -+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG0, val); -+ -+ val = FIELD_PREP(IPQ_PWM_REG1_PRE_DIV, pre_div); -+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val); -+ -+ /* PWM enable toggle needs a separate write to REG1 */ -+ val |= IPQ_PWM_REG1_UPDATE; -+ if (state->enabled) -+ val |= IPQ_PWM_REG1_ENABLE; -+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val); -+ -+ return 0; -+} -+ -+static int ipq_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, -+ struct pwm_state *state) -+{ -+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip); -+ unsigned int pre_div, pwm_div, hi_dur; -+ u64 effective_div, hi_div; -+ u32 reg0, reg1; -+ -+ reg1 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG1); -+ state->enabled = reg1 & IPQ_PWM_REG1_ENABLE; -+ -+ if (!state->enabled) -+ return 0; -+ -+ reg0 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG0); -+ -+ state->polarity = PWM_POLARITY_NORMAL; -+ -+ pwm_div = FIELD_GET(IPQ_PWM_REG0_PWM_DIV, reg0); -+ hi_dur = FIELD_GET(IPQ_PWM_REG0_HI_DURATION, reg0); -+ pre_div = FIELD_GET(IPQ_PWM_REG1_PRE_DIV, reg1); -+ -+ effective_div = (u64)(pre_div + 1) * (pwm_div + 1); -+ state->period = DIV64_U64_ROUND_UP(effective_div * NSEC_PER_SEC, -+ ipq_chip->clk_rate); -+ -+ hi_div = hi_dur * (pre_div + 1); -+ state->duty_cycle = DIV64_U64_ROUND_UP(hi_div * NSEC_PER_SEC, -+ ipq_chip->clk_rate); -+ -+ /* -+ * ensure a valid config is passed back to PWM core in case duty_cycle -+ * is > period (>100%) -+ */ -+ state->duty_cycle = min(state->duty_cycle, state->period); -+ -+ return 0; -+} -+ -+static const struct pwm_ops ipq_pwm_ops = { -+ .apply = ipq_pwm_apply, -+ .get_state = ipq_pwm_get_state, -+}; -+ -+static int ipq_pwm_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ipq_pwm_chip *pwm; -+ struct pwm_chip *chip; -+ struct clk *clk; -+ int ret; -+ -+ chip = devm_pwmchip_alloc(dev, 4, sizeof(*pwm)); -+ if (IS_ERR(chip)) -+ return PTR_ERR(chip); -+ pwm = ipq_pwm_from_chip(chip); -+ -+ pwm->mem = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(pwm->mem)) -+ return dev_err_probe(dev, PTR_ERR(pwm->mem), -+ "Failed to acquire resource\n"); -+ -+ clk = devm_clk_get_enabled(dev, NULL); -+ if (IS_ERR(clk)) -+ return dev_err_probe(dev, PTR_ERR(clk), -+ "Failed to get clock\n"); -+ -+ ret = devm_clk_rate_exclusive_get(dev, clk); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to lock clock rate\n"); -+ -+ pwm->clk_rate = clk_get_rate(clk); -+ -+ chip->ops = &ipq_pwm_ops; -+ -+ ret = devm_pwmchip_add(dev, chip); -+ if (ret < 0) -+ return dev_err_probe(dev, ret, "Failed to add pwm chip\n"); -+ -+ return 0; -+} -+ -+static const struct of_device_id pwm_ipq_dt_match[] = { -+ { .compatible = "qcom,ipq6018-pwm", }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, pwm_ipq_dt_match); -+ -+static struct platform_driver ipq_pwm_driver = { -+ .driver = { -+ .name = "ipq-pwm", -+ .of_match_table = pwm_ipq_dt_match, -+ }, -+ .probe = ipq_pwm_probe, -+}; -+ -+module_platform_driver(ipq_pwm_driver); -+ -+MODULE_LICENSE("GPL"); diff --git a/target/linux/qualcommbe/patches-6.12/0376-arm64-dts-qcom-ipq9574-add-pwm-node.patch b/target/linux/qualcommbe/patches-6.12/0376-arm64-dts-qcom-ipq9574-add-pwm-node.patch deleted file mode 100644 index 011433c6dd..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0376-arm64-dts-qcom-ipq9574-add-pwm-node.patch +++ /dev/null @@ -1,144 +0,0 @@ -From patchwork Wed Feb 4 11:25:12 2026 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: George Moussalem via B4 Relay - -X-Patchwork-Id: 2192912 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@legolas.ozlabs.org -Authentication-Results: legolas.ozlabs.org; - dkim=pass (2048-bit key; - unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 - header.s=k20201202 header.b=eBdXYFei; - dkim-atps=neutral -Authentication-Results: legolas.ozlabs.org; - spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org - (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org; - envelope-from=linux-pwm+bounces-8091-incoming=patchwork.ozlabs.org@vger.kernel.org; - receiver=patchwork.ozlabs.org) -Received: from tor.lore.kernel.org (tor.lore.kernel.org - [IPv6:2600:3c04:e001:36c::12fc:5321]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange x25519) - (No client certificate requested) - by legolas.ozlabs.org (Postfix) with ESMTPS id 4f5dN51jvwz1xqf - for ; Wed, 04 Feb 2026 22:26:29 +1100 (AEDT) -Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org - [100.90.174.1]) - by tor.lore.kernel.org (Postfix) with ESMTP id E6ED73028364 - for ; Wed, 4 Feb 2026 11:25:22 +0000 (UTC) -Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) - by smtp.subspace.kernel.org (Postfix) with ESMTP id 7787F3ECBDF; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b="eBdXYFei" -X-Original-To: linux-pwm@vger.kernel.org -Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org - [10.30.226.201]) - (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) - (No client certificate requested) - by smtp.subspace.kernel.org (Postfix) with ESMTPS id 488673ECBC5; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -Authentication-Results: smtp.subspace.kernel.org; - arc=none smtp.client-ip=10.30.226.201 -ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; - t=1770204314; cv=none; - b=uwndTXZwjatScjw/qfG0MiKqSIzmIqMgv7TVXWmxKetvRuaAg31sb9ZhW77UPjPX/lMOditmtVgqxnruPV2O6MZjPnZYpu9HApUfhtwTIOzw3WjizZC/AgH49PFHOWCDPWcP9WGPKoDjEz3vupzf1ki1h0rXV4pbjkJtO2Dgfg8= -ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; - s=arc-20240116; t=1770204314; c=relaxed/simple; - bh=vE8UXlKfInB73S8Crc3gaHWqLQg+oOyoCtzeWharQS0=; - h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: - In-Reply-To:To:Cc; - b=nr0qlzwFsS+ce2fu7iqjeCzNSpG8h2LgSxcLUcVXPjNCM2Ync4ajZxf9s+2yE/jV1FuPogUTSu/Npx6P4esNTjiZnUNQQGO/vqBBzhAUOsRZh5kDpfIZD4XNW94nSCFEnymaMZDVMojvZSF25aKaWLbrWAehNVPyQMhyGyXG2kg= -ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; - dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org - header.b=eBdXYFei; arc=none smtp.client-ip=10.30.226.201 -Received: by smtp.kernel.org (Postfix) with ESMTPS id 1FBA8C16AAE; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; - s=k20201202; t=1770204314; - bh=vE8UXlKfInB73S8Crc3gaHWqLQg+oOyoCtzeWharQS0=; - h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; - b=eBdXYFeiLIl+QGeTfz6IIUeYBuEEDl+b419qodE2EVomGdqaNo6884pycBeWBvZMh - haX7oelDQSKnWGiF9sQjVUxz4Bay2BEZVQ1GmcghWtGQg7w+d4/fdfvByLW08F//at - iN1OoKPRpYgIVaVKk7kEOMlXr20t38YcZLXpVfFG+fIWwnxTLMzJ8Gau5rLyluyr8P - eM9GvY4qwgMgvdyujRQepS7Oi+ovHftu/43TRRxbdoIE8N8kI7jYvsCdHJ61HDu2ls - NNNef1ZfWkcdGaVDLNWZmQ6VTGMTNKrX1uWcdOfsGts6/lMd7pc+dMVMn4md9rJWnb - Ul0Go0aD9V1TQ== -Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org - (localhost.localdomain [127.0.0.1]) - by smtp.lore.kernel.org (Postfix) with ESMTP id 0DE25E95389; - Wed, 4 Feb 2026 11:25:14 +0000 (UTC) -From: George Moussalem via B4 Relay - -Date: Wed, 04 Feb 2026 15:25:12 +0400 -Subject: [PATCH v20 6/6] arm64: dts: qcom: ipq9574: add pwm node -Precedence: bulk -X-Mailing-List: linux-pwm@vger.kernel.org -List-Id: -List-Subscribe: -List-Unsubscribe: -MIME-Version: 1.0 -Message-Id: <20260204-ipq-pwm-v20-6-91733011a3d1@outlook.com> -References: <20260204-ipq-pwm-v20-0-91733011a3d1@outlook.com> -In-Reply-To: <20260204-ipq-pwm-v20-0-91733011a3d1@outlook.com> -To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , - Rob Herring , Krzysztof Kozlowski , - Conor Dooley , Baruch Siach , - Bjorn Andersson , - Konrad Dybcio -Cc: linux-arm-msm@vger.kernel.org, linux-pwm@vger.kernel.org, - devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, - George Moussalem , - Dmitry Baryshkov -X-Mailer: b4 0.14.2 -X-Developer-Signature: v=1; a=ed25519-sha256; t=1770204310; l=1234; - i=george.moussalem@outlook.com; s=20250321; h=from:subject:message-id; - bh=1ixhFwq2rEjXYJIhs5+j+ngAUcQh5KQa6+Qdzh8kp4o=; - b=ky+nnCBbPuFce/HNZnz6s4ubdKccwoR4mGT7VVjp1Q+YR30lXS7xluR+rnmLy73TfU2J3/6kO - 144Si65ChORDD0KZk1dvy+masC3Igfhy8O3qYSqMdoqSlttNJsS5eZR -X-Developer-Key: i=george.moussalem@outlook.com; a=ed25519; - pk=/PuRTSI9iYiHwcc6Nrde8qF4ZDhJBlUgpHdhsIjnqIk= -X-Endpoint-Received: by B4 Relay for george.moussalem@outlook.com/20250321 - with auth_id=364 -X-Original-From: George Moussalem -Reply-To: george.moussalem@outlook.com - -From: George Moussalem - -Describe the PWM block on IPQ9574. - -Although PWM is in the TCSR area, make pwm its own node as simple-mfd -has been removed from the bindings and as such hardware components -should have its own node. - -Reviewed-by: Dmitry Baryshkov -Signed-off-by: George Moussalem -Reviewed-by: Konrad Dybcio ---- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi -+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi -@@ -469,6 +469,16 @@ - reg = <0x01937000 0x21000>; - }; - -+ pwm: pwm@1941010 { -+ compatible = "qcom,ipq9574-pwm", "qcom,ipq6018-pwm"; -+ reg = <0x01941010 0x20>; -+ clocks = <&gcc GCC_ADSS_PWM_CLK>; -+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>; -+ assigned-clock-rates = <100000000>; -+ #pwm-cells = <3>; -+ status = "disabled"; -+ }; -+ - sdhc_1: mmc@7804000 { - compatible = "qcom,ipq9574-sdhci", "qcom,sdhci-msm-v5"; - reg = <0x07804000 0x1000>, From 03aa344b2c52dd265668f817835179c93cc8cf98 Mon Sep 17 00:00:00 2001 From: Igor Kravchenko Date: Sun, 21 Jun 2026 11:29:25 +0300 Subject: [PATCH 122/228] qualcommbe: fold kernel fixes Move the QCA8084 XPCS channel lookup fix into the SerDes speed config patch, so qca8084_qxgmii_set_speed() walks the channel table with the loop index from the start. Move the PPE port reset loop fix into the PPE driver update patch, so ppe_port_mac_reset() asserts and deasserts each reset control instead of reusing the MAC reset for every iteration. Signed-off-by: Igor Kravchenko Link: https://github.com/openwrt/openwrt/pull/23900 Signed-off-by: Robert Marko --- ...-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch | 11 ++++++----- .../0342-net-qualcomm-Update-IPQ9574-PPE-driver.patch | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/target/linux/qualcommbe/patches-6.18/0312-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch b/target/linux/qualcommbe/patches-6.18/0312-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch index 9d83ce9883..09822dac36 100644 --- a/target/linux/qualcommbe/patches-6.18/0312-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch +++ b/target/linux/qualcommbe/patches-6.18/0312-net-phy-qca808x-Add-QCA8084-SerDes-speed-config.patch @@ -13,8 +13,8 @@ Signed-off-by: Alexandru Gagniuc --- drivers/net/phy/qcom/qca8084_serdes.c | 159 ++++++++++++++++++++++++++ drivers/net/phy/qcom/qca8084_serdes.h | 3 + - drivers/net/phy/qcom/qca808x.c | 15 ++- - 3 files changed, 175 insertions(+), 2 deletions(-) + drivers/net/phy/qcom/qca808x.c | 16 ++- + 3 files changed, 176 insertions(+), 2 deletions(-) --- a/drivers/net/phy/qcom/qca8084_serdes.c +++ b/drivers/net/phy/qcom/qca8084_serdes.c @@ -102,7 +102,7 @@ Signed-off-by: Alexandru Gagniuc + unsigned long rate; + + for (i = 0; i < QCA8084_CHANNEL_MAX; i++) { -+ xpcs_ch = &(xpcs_data->xpcs_ch[channel]); ++ xpcs_ch = &xpcs_data->xpcs_ch[i]; + if (channel == xpcs_ch->ch_id) + break; + } @@ -222,7 +222,7 @@ Signed-off-by: Alexandru Gagniuc int ret; /* Assert the FIFO between PHY and MAC. */ -@@ -1028,14 +1029,24 @@ static void qca8084_link_change_notify(s +@@ -1028,14 +1029,25 @@ static void qca8084_link_change_notify(s } } @@ -233,8 +233,9 @@ Signed-off-by: Alexandru Gagniuc */ - if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) + if (phydev->interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ shared_priv = phy_package_get_priv(phydev); + struct qca808x_priv *priv = phydev->priv; ++ ++ shared_priv = phy_package_get_priv(phydev); + phy_modify_mmd(phydev, MDIO_MMD_AN, QCA8084_MMD7_IPG_OP, QCA8084_IPG_10_TO_11_EN, diff --git a/target/linux/qualcommbe/patches-6.18/0342-net-qualcomm-Update-IPQ9574-PPE-driver.patch b/target/linux/qualcommbe/patches-6.18/0342-net-qualcomm-Update-IPQ9574-PPE-driver.patch index 24d89dcc47..72f91a80be 100644 --- a/target/linux/qualcommbe/patches-6.18/0342-net-qualcomm-Update-IPQ9574-PPE-driver.patch +++ b/target/linux/qualcommbe/patches-6.18/0342-net-qualcomm-Update-IPQ9574-PPE-driver.patch @@ -2288,7 +2288,7 @@ Signed-off-by: Alexandru Gagniuc - if (ret) - goto error; + for (i = PPE_PORT_CLK_RST_MAC; i < PPE_PORT_CLK_RST_MAX; i++) { -+ ret = reset_control_assert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]); ++ ret = reset_control_assert(ppe_port->rstcs[i]); + if (ret) + return ret; + } @@ -2300,7 +2300,7 @@ Signed-off-by: Alexandru Gagniuc - return ret; + for (i = PPE_PORT_CLK_RST_MAC; i < PPE_PORT_CLK_RST_MAX; i++) { -+ ret = reset_control_deassert(ppe_port->rstcs[PPE_PORT_CLK_RST_MAC]); ++ ret = reset_control_deassert(ppe_port->rstcs[i]); + if (ret) + return ret; + } From 0eb407c000276d500f792b64d6a01d659ff5c17b Mon Sep 17 00:00:00 2001 From: Shine <4c.fce2@proton.me> Date: Mon, 22 Jun 2026 15:35:33 +0200 Subject: [PATCH 123/228] package: arm-trusted-firmware-tools: add proper patch header A patch was added without proper header. Add a header that explains what the patch does and its prerequisites. Fixes: e42e9c8133fbd0dce7abfe1ec696383745448078 Signed-off-by: Shine <4c.fce2@proton.me> Link: https://github.com/openwrt/openwrt/pull/23917 Signed-off-by: Robert Marko --- .../patches/003-fiptool_musl_fix.patch | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch b/package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch index f421e91ef0..ec94c90d9e 100644 --- a/package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch +++ b/package/boot/arm-trusted-firmware-tools/patches/003-fiptool_musl_fix.patch @@ -1,6 +1,31 @@ +From 6f51da2bb799a8b77da0167eeea45d5d5125f39c Mon Sep 17 00:00:00 2001 +From: Shine <4c.fce2@proton.me> +Date: Mon, 22 Jun 2026 14:45:39 +0200 +Subject: fix fiptool build on musl host + +Due to POSIX style ioctl(int,int,...) declaration, building fiptool under +MUSL generates a compiler warning (BLKGETSIZE64 == 0x80081272, ie. integer +overflow). This causes a build failure when compiling with -Werror and +-pedantic GCC switches enabled. + +Selectively cast the parameter to (int) when hinted to be running on a +MUSL based build host. + +Requires a __MUSL__ macro to be defined. MUSL does not provide such a +predefined macro, so this has to be passed explicitly to GCC, e.g. with +-D__MUSL__ during build. + +For OpenWrt, this is done in the arm-trusted-firmware-tools Makefile, +see commit e42e9c8133fbd0dce7abfe1ec696383745448078 + +Signed-off-by: Shine <4c.fce2@proton.me> +--- + tools/fiptool/fiptool.c | 4 ++++ + 1 file changed, 4 insertions(+) + --- a/tools/fiptool/fiptool.c +++ b/tools/fiptool/fiptool.c -@@ -318,7 +318,11 @@ +@@ -318,7 +318,11 @@ static int parse_fip(const char *filename, fip_toc_header_t *toc_header_out) #ifdef BLKGETSIZE64 if ((st.st_mode & S_IFBLK) != 0) From d4a23ac098472db460309595f59de98c98af8062 Mon Sep 17 00:00:00 2001 From: Timo Jutila Date: Mon, 15 Jun 2026 10:46:14 +0300 Subject: [PATCH 124/228] qualcommax: ipq807x: Fix w_disable for Deco X80-5G Change w_disable GPIO to 55. 35 is used in the u-boot as "ONOFF_MODULE 5G", 55 can be found in the stock dts as w_disable Signed-off-by: Timo Jutila Link: https://github.com/openwrt/openwrt/pull/23800 Signed-off-by: Robert Marko --- target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts b/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts index 09f8be6e15..8a6f474424 100644 --- a/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts +++ b/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts @@ -33,8 +33,8 @@ to suit the TP-Link Deco X80-5G target */ w_disable { gpio-export,name = "w_disable"; - gpio-export,output = <1>; - gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>; /* wwan disable output */ + gpio-export,output = <0>; + gpios = <&tlmm 55 GPIO_ACTIVE_LOW>; /* wwan disable output */ }; modem-reset { From db1b70dc9850c8a3badf9994a50f6ea38563a82d Mon Sep 17 00:00:00 2001 From: Timo Jutila Date: Sun, 14 Jun 2026 14:12:05 +0300 Subject: [PATCH 125/228] qualcommax: ipq807x: Add PCIe support for TP-Link Deco X80-5G Make 5G modem available over PCIe. Modify dts to enable PCIe. Adapted based on ipq8072-linkhub-hh500v.dts Add MHI modules to default X80-5g image Signed-off-by: Timo Jutila Link: https://github.com/openwrt/openwrt/pull/23801 Signed-off-by: Robert Marko --- .../qualcommax/dts/ipq8074-deco-x80-5g.dts | 56 +++++++++++++++++-- target/linux/qualcommax/image/ipq807x.mk | 3 +- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts b/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts index 8a6f474424..2f14b554cc 100644 --- a/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts +++ b/target/linux/qualcommax/dts/ipq8074-deco-x80-5g.dts @@ -48,6 +48,12 @@ to suit the TP-Link Deco X80-5G target */ gpio-export,output = <0>; gpios = <&tlmm 56 GPIO_ACTIVE_HIGH>; /* select external sma antennas for wwan output */ }; + + modem-power { /* sdx_pon_gpio for pcie */ + gpio-export,name = "modem_power"; + gpio-export,output = <1>; + gpios = <&tlmm 30 GPIO_ACTIVE_HIGH>; + }; }; gpio_keys { @@ -315,11 +321,27 @@ to suit the TP-Link Deco X80-5G target */ bias-disable; }; - modem_pins: modem-state { - pins = "gpio29", "gpio55"; - function = "gpio"; - drive-strength = <2>; - bias-disable; + modem_pins: modem-pins { + modem_power_on { + bias-pull-up; + drive-strength = <8>; + output-high; + pins = "gpio30"; + function = "gpio"; + }; + + modem_reset { + drive-strength = <8>; + output-high; + pins = "gpio29"; + }; + + w_disable { + pins = "gpio55"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; }; led_pins: led-state { @@ -344,6 +366,13 @@ to suit the TP-Link Deco X80-5G target */ bias-pull-up; }; }; + + pcie0_default_state: pcie0_wake_gpio { + bias-pull-up; + drive-strength = <8>; + function = "pcie0_wake"; + pins = "gpio59"; + }; }; &blsp1_uart5 { @@ -456,3 +485,20 @@ to suit the TP-Link Deco X80-5G target */ status = "okay"; qcom,ath11k-calibration-variant = "tplink_deco-x80-5g"; }; + +&pcie_qmp0 { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + pinctrl-0 = <&pcie0_default_state>; + pinctrl-names = "default"; + perst-gpio = <&tlmm 58 GPIO_ACTIVE_LOW>; + + pcie@0 { + modem@0,0 { + reg = <0x00 0x00 0x00 0x00 0x00>; + }; + }; +}; diff --git a/target/linux/qualcommax/image/ipq807x.mk b/target/linux/qualcommax/image/ipq807x.mk index d1f42dd617..2bd3dab634 100644 --- a/target/linux/qualcommax/image/ipq807x.mk +++ b/target/linux/qualcommax/image/ipq807x.mk @@ -472,7 +472,8 @@ define Device/tplink_deco-x80-5g DEVICE_DTS_CONFIG := config@hk01.c5 SOC := ipq8074 DEVICE_PACKAGES := kmod-hwmon-gpiofan ipq-wifi-tplink_deco-x80-5g \ - kmod-usb-serial-option kmod-usb-net-qmi-wwan + kmod-usb-serial-option kmod-usb-net-qmi-wwan kmod-mhi-pci-generic \ + kmod-mhi-wwan-ctrl kmod-mhi-wwan-mbim endef TARGET_DEVICES += tplink_deco-x80-5g From d21b7bfbff92820fe277e78a4ec778cd1c26efd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Daleck=C3=BD?= Date: Fri, 5 Jun 2026 16:02:09 +0200 Subject: [PATCH 126/228] mvebu: fix Turris MOX update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turris MOX still upgrades from a legacy SD card image rather than using the default sysupgrade path for cortexa53 devices. Route image validation, upgrade handling and config backup through the legacy_sdcard helpers so sysupgrade writes the correct image format and preserves settings. Signed-off-by: Štěpán Dalecký Link: https://github.com/openwrt/openwrt/pull/23666 Signed-off-by: Hauke Mehrtens --- .../linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh index 8b8149c96b..e62e72ba55 100755 --- a/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh +++ b/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh @@ -43,6 +43,7 @@ methode_update_active_bootscript() { platform_check_image() { case "$(board_name)" in + cznic,turris-mox|\ glinet,gl-mv1000|\ globalscale,espressobin|\ globalscale,espressobin-emmc|\ @@ -59,6 +60,7 @@ platform_check_image() { platform_do_upgrade() { case "$(board_name)" in + cznic,turris-mox|\ glinet,gl-mv1000|\ globalscale,espressobin|\ globalscale,espressobin-emmc|\ @@ -117,6 +119,7 @@ platform_do_upgrade() { } platform_copy_config() { case "$(board_name)" in + cznic,turris-mox|\ glinet,gl-mv1000|\ globalscale,espressobin|\ globalscale,espressobin-emmc|\ From 4bea1cf4d80ddaf920cb658e579e8ae577b7c358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Daleck=C3=BD?= Date: Fri, 5 Jun 2026 17:47:03 +0200 Subject: [PATCH 127/228] mvebu: add kmod-btmrvl to Turris MOX packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turris MOX needs the btmrvl module for its onboard Marvell Bluetooth controller. Include kmod-btmrvl in DEVICE_PACKAGES so default images ship with the required driver. Signed-off-by: Štěpán Dalecký Link: https://github.com/openwrt/openwrt/pull/23666 Signed-off-by: Hauke Mehrtens --- target/linux/mvebu/image/cortexa53.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/mvebu/image/cortexa53.mk b/target/linux/mvebu/image/cortexa53.mk index 54823002fd..3074c81270 100644 --- a/target/linux/mvebu/image/cortexa53.mk +++ b/target/linux/mvebu/image/cortexa53.mk @@ -6,7 +6,7 @@ define Device/cznic_turris-mox kmod-rtc-ds1307 kmod-i2c-pxa kmod-dsa kmod-dsa-mv88e6xxx kmod-sfp \ kmod-phy-marvell kmod-phy-marvell-10g kmod-ath10k ath10k-board-qca988x \ ath10k-firmware-qca988x kmod-mt7915e kmod-mt7915-firmware mwlwifi-firmware-88w8997 \ - wpad-basic-mbedtls kmod-mwifiex-sdio + wpad-basic-mbedtls kmod-mwifiex-sdio kmod-btmrvl SOC := armada-3720 BOOT_SCRIPT := turris-mox endef From 302d8be2bce25563b66a6261b40c1ef709686049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0t=C4=9Bp=C3=A1n=20Daleck=C3=BD?= Date: Fri, 5 Jun 2026 19:04:30 +0200 Subject: [PATCH 128/228] mvebu: set MOX firmware fallback via cmdline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Newer kernels support applying sysctl keys from the kernel command line. Set sysctl.kernel.firmware_config.force_sysfs_fallback=0 in MOX bootargs to disable firmware sysfs fallback without a board-specific init script. Signed-off-by: Štěpán Dalecký Link: https://github.com/openwrt/openwrt/pull/23666 Signed-off-by: Hauke Mehrtens --- target/linux/mvebu/image/turris-mox.bootscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/mvebu/image/turris-mox.bootscript b/target/linux/mvebu/image/turris-mox.bootscript index 29d16964af..6a4d4cd60f 100644 --- a/target/linux/mvebu/image/turris-mox.bootscript +++ b/target/linux/mvebu/image/turris-mox.bootscript @@ -40,7 +40,7 @@ if part uuid ${devtype} ${devnum}:${distro_bootpart} bootuuid; then fi fi if test "$filesize" != "0"; then - setenv bootargs "earlyprintk console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000 rootfstype=${rootfstype} root=${rootdev} rootflags=${rootflags} rootwait ${contract} rw cfg80211.freg=${regdomain} ${quirks}" + setenv bootargs "earlyprintk console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000 rootfstype=${rootfstype} root=${rootdev} rootflags=${rootflags} rootwait ${contract} rw cfg80211.freg=${regdomain} sysctl.kernel.firmware_config.force_sysfs_fallback=0 ${quirks}" booti ${kernel_addr_r} - ${fdt_addr_r} echo "Booting Image failed" else From 9c48477cf70aae3ba92d0ab5c66e3859210bb941 Mon Sep 17 00:00:00 2001 From: Chad Monroe Date: Mon, 15 Jun 2026 14:21:02 -0700 Subject: [PATCH 129/228] hostapd: fix misplaced radar-detected ubus notification Fixes: 94037ab6b031 ("hostapd: update to 2022-07-29") Signed-off-by: Chad Monroe Link: https://github.com/openwrt/openwrt/pull/23815 Signed-off-by: Hauke Mehrtens --- .../network/services/hostapd/patches/600-ubus_support.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch index 290f2e8e4a..1c7f013c37 100644 --- a/package/network/services/hostapd/patches/600-ubus_support.patch +++ b/package/network/services/hostapd/patches/600-ubus_support.patch @@ -81,15 +81,15 @@ probe/assoc/auth requests via object subscribe. --- a/src/ap/dfs.c +++ b/src/ap/dfs.c -@@ -1295,6 +1295,8 @@ int hostapd_dfs_pre_cac_expired(struct h +@@ -1543,6 +1543,8 @@ int hostapd_dfs_radar_detected(struct ho "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", freq, ht_enabled, chan_offset, chan_width, cf1, cf2); + hostapd_ubus_notify_radar_detected(iface, freq, chan_width, cf1, cf2); + + iface->radar_detected = true; + /* Proceed only if DFS is not offloaded to the driver */ - if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) - return 0; --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -333,6 +333,10 @@ int hostapd_notif_assoc(struct hostapd_d From 733dc15644ba22e17ead7cd0c5a168e49440a46c Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Wed, 24 Jun 2026 01:53:14 +0200 Subject: [PATCH 130/228] odhcp6c: update to Git HEAD (2026-06-20) 07d324ee7222 odhcp6c: fix handling of RFC6603 Prefix Exclude Option Signed-off-by: Hauke Mehrtens --- package/network/ipv6/odhcp6c/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/ipv6/odhcp6c/Makefile b/package/network/ipv6/odhcp6c/Makefile index 238672b1e1..99fa036860 100644 --- a/package/network/ipv6/odhcp6c/Makefile +++ b/package/network/ipv6/odhcp6c/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/odhcp6c.git -PKG_SOURCE_DATE:=2026-06-04 -PKG_SOURCE_VERSION:=daf4ec3054e753c99fdcc3ac5464926548b38351 -PKG_MIRROR_HASH:=a6239fde325f4815d186bde99e30f95877e58b03fa4fab25013a769127ce3369 +PKG_SOURCE_DATE:=2026-06-20 +PKG_SOURCE_VERSION:=07d324ee7222c0e15b9975281f18236fdccc11bd +PKG_MIRROR_HASH:=f26733017c82f5397bae026c56df8e1225dfaa8cdbea3cf7b3f9192cfa9ba719 PKG_MAINTAINER:=Álvaro Fernández Rojas PKG_LICENSE:=GPL-2.0 From 4ffea5638878f3bddebef99c21373c0158ba7caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 17 Jun 2026 10:42:00 +0200 Subject: [PATCH 131/228] tools: util-linux: update to 2.42.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Release notes: https://www.kernel.org/pub/linux/utils/util-linux/v2.42/v2.42.2-ReleaseNotes Signed-off-by: Thomas Weißschuh Link: https://github.com/openwrt/openwrt/pull/23844 Signed-off-by: Hauke Mehrtens --- tools/util-linux/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/util-linux/Makefile b/tools/util-linux/Makefile index 07d712295b..6554eff183 100644 --- a/tools/util-linux/Makefile +++ b/tools/util-linux/Makefile @@ -7,11 +7,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=util-linux -PKG_VERSION:=2.42.1 +PKG_VERSION:=2.42.2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/linux/utils/$(PKG_NAME)/v2.42 -PKG_HASH:=82e9158eb12a9b0b569d84e1687fed9dd18fe89ccd8ef5ac3427218a7c0d7f7f +PKG_HASH:=03a05d3adf9602ef128f2da05b84b3205ce60c351e5737c0370f74000679ce8a PKG_CPE_ID:=cpe:/a:kernel:util-linux include $(INCLUDE_DIR)/host-build.mk From 11865bffc8cc680e3729b7bf5280ce90a695acdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 17 Jun 2026 10:42:27 +0200 Subject: [PATCH 132/228] util-linux: update to 2.42.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Release notes: https://www.kernel.org/pub/linux/utils/util-linux/v2.42/v2.42.2-ReleaseNotes Signed-off-by: Thomas Weißschuh Link: https://github.com/openwrt/openwrt/pull/23844 Signed-off-by: Hauke Mehrtens --- package/utils/util-linux/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/utils/util-linux/Makefile b/package/utils/util-linux/Makefile index aee0235f21..b7adcd195a 100644 --- a/package/utils/util-linux/Makefile +++ b/package/utils/util-linux/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=util-linux -PKG_VERSION:=2.42.1 +PKG_VERSION:=2.42.2 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/linux/utils/$(PKG_NAME)/v2.42 -PKG_HASH:=82e9158eb12a9b0b569d84e1687fed9dd18fe89ccd8ef5ac3427218a7c0d7f7f +PKG_HASH:=03a05d3adf9602ef128f2da05b84b3205ce60c351e5737c0370f74000679ce8a PKG_CPE_ID:=cpe:/a:kernel:util-linux PKG_INSTALL:=1 From c32059b383ee9e0817b561158f3a54eeb974f995 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 17 Jun 2026 10:40:30 +0200 Subject: [PATCH 133/228] netifd: update to Git HEAD (2026-06-16) abfaaac65929 netifd: fix const-discard warnings in attr/devtype parsing 52c7db3a2beb bridge: remove kernel member on teardown regardless of device claim state 741fd3c162df bridge: attempt delbr unconditionally on bridge destroy 2909720f8cf1 system-linux: detach device from stale bridge before adding it 67f06ef1600a interface: detach hotplug members on reassignment bb7f0a456dce interface-ip: skip offlink handling on point-to-point links c1f9d4df847a system-linux: guard PSE port priority for older kernel headers b087b0773366 build: prefer libnl-tiny and fix LIBNL detection on reconfigure b0063715d7ea device: add broadcast_flood bridge port setting 973354a1a6f0 interface: add carrier_loss_delay option d155e4cefbd9 interface: add restart support Signed-off-by: Felix Fietkau --- package/network/config/netifd/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile index 8ef6d3cdb7..748678894c 100644 --- a/package/network/config/netifd/Makefile +++ b/package/network/config/netifd/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2026-04-23 -PKG_SOURCE_VERSION:=e45b890fa532bb89380b78008c2cc70bfad2c4c7 -PKG_MIRROR_HASH:=bf318b9905ca2a63a8bb834d356bef3eec031acc843ba0137495708090894f75 +PKG_SOURCE_DATE:=2026-06-16 +PKG_SOURCE_VERSION:=d155e4cefbd964b7c022618c1d74b549de25e8a8 +PKG_MIRROR_HASH:=a9b9cf01e800ac072a353a6c7f7c7854b5b9139b336645b50cc21c5b8ef38390 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 From d9c765286d9c77feca9be0eb9988df6c6acab96a Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 17 Mar 2026 11:37:00 +0100 Subject: [PATCH 134/228] wifi-scripts: fix HE Operation IE parsing in iwinfo scan cell.he was only populated when the 6 GHz Operation Information sub-element was parsed, making HE invisible to scan results on 2.4/5 GHz bands. Fix this by setting cell.he unconditionally when HE Operation IE (Extension Element 36) is seen. Gate 6 GHz channel width parsing on cell.band rather than the HE Operation Parameters bit field, which proved unreliable on MediaTek firmware. Fix flag byte offsets in the 6 GHz path: VHT Oper Info Present (BIT 14) and Co-Hosted BSS (BIT 15) are in byte 1 of he_oper_params which maps to ext[2], not ext[1]. For non-6GHz bands, derive channel width from the already-parsed VHT/HT Operation IEs instead of leaving cell.he empty. Signed-off-by: John Crispin --- .../files-ucode/usr/share/ucode/iwinfo.uc | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc index c56026f104..2cea4c5430 100644 --- a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc +++ b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc @@ -533,22 +533,27 @@ function scan_extension(ext, cell) { switch(ord(ext, 0)) { case 36: - let offset = 7; + cell.he = {}; - if (!(ord(ext, 3) & 0x2)) - break; + if (cell.band == '6') { + let offset = 7; - if (ord(ext, 2) & 0x40) - offset += 3; + if (ord(ext, 2) & 0x40) + offset += 3; - if (ord(ext, 2) & 0x80) - offset += 1; + if (ord(ext, 2) & 0x80) + offset += 1; - cell.he = { - chan_width: eht_chan_width[ord(ext, offset + 1) & 0x3], - center_chan_1: ord(ext, offset + 2), - center_chan_2: ord(ext, offset + 3), - }; + cell.he.chan_width = eht_chan_width[ord(ext, offset + 1) & 0x3]; + cell.he.center_chan_1 = ord(ext, offset + 2); + cell.he.center_chan_2 = ord(ext, offset + 3); + } else if (cell.vht) { + cell.he.chan_width = cell.vht.chan_width; + cell.he.center_chan_1 = cell.vht.center_chan_1; + cell.he.center_chan_2 = cell.vht.center_chan_2; + } else if (cell.ht) { + cell.he.chan_width = cell.ht.chan_width; + } break; case 106: From 7f2effc94d75545db503eae72a046c3adf374ca3 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 24 Mar 2026 12:07:46 +0100 Subject: [PATCH 135/228] wifi-scripts: expose connected_time in iwinfo assoclist Signed-off-by: John Crispin --- .../config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc | 1 + 1 file changed, 1 insertion(+) diff --git a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc index 2cea4c5430..7519bdda94 100644 --- a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc +++ b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/iwinfo.uc @@ -370,6 +370,7 @@ export function assoclist(dev) { flags: assoc_flags(station.sta_info.tx_bitrate ?? {}), }, expected_throughput: format_expected_throughput(station.sta_info.expected_throughput ?? 0), + connected_time: station.sta_info.connected_time ?? 0, }; ret[sta.mac] = sta; } From 87f5376eb7fd60173e0a0b7f0f48334d5a255677 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 23 Jan 2026 08:42:20 +0100 Subject: [PATCH 136/228] busybox: enable timeout utility by default Small cost, but can be of use for non-interactive scripts. Signed-off-by: John Crispin Signed-off-by: Felix Fietkau --- package/utils/busybox/Config-defaults.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/utils/busybox/Config-defaults.in b/package/utils/busybox/Config-defaults.in index 213a7ab73e..71175bddfc 100644 --- a/package/utils/busybox/Config-defaults.in +++ b/package/utils/busybox/Config-defaults.in @@ -867,7 +867,7 @@ config BUSYBOX_DEFAULT_FEATURE_TEST_64 default y config BUSYBOX_DEFAULT_TIMEOUT bool - default n + default y config BUSYBOX_DEFAULT_TOUCH bool default y From c92ded2f6e7a31f807a653b9fc5cda930ca4b945 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 15 Jun 2026 10:50:16 +0200 Subject: [PATCH 137/228] wifi-scripts: fix EAP STA support in supplicant config generation The supplicant config generator read eap_type and auth from UCI for internal logic but never wrote the corresponding eap= and phase2= directives to the wpa_supplicant config. Fix by: - Generating eap= and phase2= from eap_type/auth for PEAP/TTLS/FAST/TLS - Adding eap and phase2 to the network_append_vars output list Signed-off-by: John Crispin Signed-off-by: Felix Fietkau --- .../files-ucode/usr/share/ucode/wifi/supplicant.uc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc index 7104357f39..7f0effadd8 100644 --- a/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc +++ b/package/network/config/wifi-scripts/files-ucode/usr/share/ucode/wifi/supplicant.uc @@ -155,11 +155,16 @@ function setup_sta(data, config) { if (config.ca_cert_usesystem && fs.stat('/etc/ssl/certs/ca-certificates.crt')) config.ca_cert = '/etc/ssl/certs/ca-certificates.crt'; + const eap_method_map = { fast: 'FAST', peap: 'PEAP', ttls: 'TTLS', tls: 'TLS' }; + if (eap_method_map[config.eap_type]) + config.eap = eap_method_map[config.eap_type]; + switch(config.eap_type) { case 'fast': case 'peap': case 'ttls': set_default(config, 'auth', 'MSCHAPV2'); + config.phase2 = `"auth=${config.auth}"`; if (config.auth == 'EAP-TLS') { if (config.ca_cert2_usesystem && fs.stat('/etc/ssl/certs/ca-certificates.crt')) config.ca_cert2 = '/etc/ssl/certs/ca-certificates.crt'; @@ -205,7 +210,7 @@ function setup_sta(data, config) { 'disable_ht', 'disable_ht40', 'disable_vht', 'vht', 'max_oper_chwidth', 'ht40', 'beacon_int', 'ieee80211w', 'rates', 'mesh_basic_rates', 'mcast_rate', 'altsubject_match', 'domain_match', 'domain_suffix_match', - 'bssid_blacklist', 'bssid_whitelist', 'erp', + 'bssid_blacklist', 'bssid_whitelist', 'erp', 'eap', 'phase2', 'dpp_connector', 'dpp_csign', 'dpp_netaccesskey', ]); } From b8175a021b6029f2b1aaf3d766cd645c5c47a8ff Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 17 Jun 2026 10:44:57 +0200 Subject: [PATCH 138/228] netifd: dhcp: add restart command for clean lease re-acquire Add a proto_dhcp_restart() handler that re-acquires the DHCP lease via a single ubus call, releasing the previous lease and triggering a fresh DHCPDISCOVER without bouncing the interface. The re-acquire is implemented by sending SIGHUP to udhcpc, which releases the current lease (if any) and immediately transitions the state machine to INIT_SELECTING so the next main-loop iteration sends a fresh DHCPDISCOVER. A single signal thus expresses 'release this lease and get a new one' without exiting the client, so upstream watchdogs (e.g. a DNS-health monitor) can request a clean re-lease without tearing down the interface. Signed-off-by: John Crispin Signed-off-by: Felix Fietkau --- .../netifd/files/lib/netifd/proto/dhcp.sh | 10 ++++ .../patches/700-udhcpc-sighup-restart.patch | 48 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 package/utils/busybox/patches/700-udhcpc-sighup-restart.patch diff --git a/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh b/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh index 2214fc0b8d..5d8e0dda5e 100755 --- a/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh +++ b/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh @@ -10,6 +10,7 @@ init_proto "$@" proto_dhcp_init_config() { renew_handler=1 + restart_handler=1 proto_config_add_string 'ipaddr:ipaddr' proto_config_add_string 'hostname:hostname' @@ -115,6 +116,15 @@ proto_dhcp_renew() { [ -n "$sigusr1" ] && proto_kill_command "$interface" $sigusr1 } +proto_dhcp_restart() { + local interface="$1" + # SIGHUP asks a patched udhcpc to release the current lease and + # immediately re-enter INIT_SELECTING so a fresh DHCPDISCOVER goes + # out. Requires the matching busybox udhcpc patch. + local sighup="$(kill -l SIGHUP)" + [ -n "$sighup" ] && proto_kill_command "$interface" $sighup +} + proto_dhcp_teardown() { local interface="$1" proto_kill_command "$interface" diff --git a/package/utils/busybox/patches/700-udhcpc-sighup-restart.patch b/package/utils/busybox/patches/700-udhcpc-sighup-restart.patch new file mode 100644 index 0000000000..b58d54b616 --- /dev/null +++ b/package/utils/busybox/patches/700-udhcpc-sighup-restart.patch @@ -0,0 +1,48 @@ +From: John Crispin +Date: Wed, 15 Apr 2026 16:15:38 +0200 +Subject: [PATCH] udhcpc: treat SIGHUP as release + rediscover + +Add a SIGHUP handler to udhcpc that releases the current lease (if any) +and immediately transitions the state machine to INIT_SELECTING so the +next main-loop iteration sends a fresh DHCPDISCOVER. This lets a single +signal express 'release this lease and get a new one' without exiting +the client, so upstream watchdogs (e.g. a DNS-health monitor) can +request a clean re-lease without tearing down the interface. + +Signed-off-by: John Crispin +--- +--- a/networking/udhcp/dhcpc.c ++++ b/networking/udhcp/dhcpc.c +@@ -1606,6 +1606,22 @@ int udhcpc_main(int argc UNUSED_PARAM, c + /* ^^^ switches to LISTEN_NONE */ + timeout = INT_MAX; + continue; ++ case SIGHUP: ++ bb_info_msg("received SIGHUP, restarting DHCP session"); ++ /* release the current lease if we have one */ ++ if (client_data.state != INIT_SELECTING ++ && client_data.state != RELEASED) ++ perform_release(server_id, requested_ip); ++ /* drop any cached offer, kick the state machine into ++ * INIT_SELECTING so the next iteration sends a fresh ++ * DHCPDISCOVER */ ++ change_listen_mode(LISTEN_NONE); ++ server_id = 0; ++ requested_ip = 0; ++ packet_num = 0; ++ client_data.state = INIT_SELECTING; ++ timeout = 0; ++ continue; + case SIGTERM: + bb_info_msg("received %s", "SIGTERM"); + goto ret0; +--- a/networking/udhcp/signalpipe.c ++++ b/networking/udhcp/signalpipe.c +@@ -58,6 +58,7 @@ void FAST_FUNC udhcp_sp_setup(void) + bb_signals(0 + + (1 << SIGUSR1) + + (1 << SIGUSR2) ++ + (1 << SIGHUP) + + (1 << SIGTERM) + , signal_handler); + } From 3b6050fe423675c8d6b25d1c5435d21b52d23d8b Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 17 Mar 2026 12:25:24 +0100 Subject: [PATCH 139/228] wifi-scripts: make scan output fields conditional Only print VHT/HE/EHT center frequency and channel width fields when they are actually populated. This avoids displaying undefined values for non-6GHz HE results where channel info is derived from VHT/HT Operation IEs. Also fix center_chan_2 format specifier from %s to %d. Signed-off-by: John Crispin --- .../wifi-scripts/files-ucode/usr/bin/iwinfo | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/package/network/config/wifi-scripts/files-ucode/usr/bin/iwinfo b/package/network/config/wifi-scripts/files-ucode/usr/bin/iwinfo index d36268b06e..8bda0bd15f 100755 --- a/package/network/config/wifi-scripts/files-ucode/usr/bin/iwinfo +++ b/package/network/config/wifi-scripts/files-ucode/usr/bin/iwinfo @@ -95,23 +95,32 @@ function print_scan(cells) { if (cell.vht) { printf('\t VHT Operation:\n'); - printf('\t\tCenter Frequency 1: %d\n', cell.vht.center_chan_1); - printf('\t\tCenter Frequency 2: %s\n', cell.vht.center_chan_2); - printf('\t\tChannel Width: %s\n', cell.vht.chan_width); + if (cell.vht.center_chan_1) + printf('\t\tCenter Frequency 1: %d\n', cell.vht.center_chan_1); + if (cell.vht.center_chan_2) + printf('\t\tCenter Frequency 2: %d\n', cell.vht.center_chan_2); + if (cell.vht.chan_width) + printf('\t\tChannel Width: %s\n', cell.vht.chan_width); } if (cell.he) { printf('\t HE Operation:\n'); - printf('\t\tCenter Frequency 1: %d\n', cell.he.center_chan_1); - printf('\t\tCenter Frequency 2: %s\n', cell.he.center_chan_2); - printf('\t\tChannel Width: %s\n', cell.he.chan_width); + if (cell.he.center_chan_1) + printf('\t\tCenter Frequency 1: %d\n', cell.he.center_chan_1); + if (cell.he.center_chan_2) + printf('\t\tCenter Frequency 2: %d\n', cell.he.center_chan_2); + if (cell.he.chan_width) + printf('\t\tChannel Width: %s\n', cell.he.chan_width); } if (cell.eht) { printf('\t EHT Operation:\n'); - printf('\t\tCenter Frequency 1: %d\n', cell.eht.center_chan_1); - printf('\t\tCenter Frequency 2: %s\n', cell.eht.center_chan_2); - printf('\t\tChannel Width: %s\n', cell.eht.chan_width); + if (cell.eht.center_chan_1) + printf('\t\tCenter Frequency 1: %d\n', cell.eht.center_chan_1); + if (cell.eht.center_chan_2) + printf('\t\tCenter Frequency 2: %d\n', cell.eht.center_chan_2); + if (cell.eht.chan_width) + printf('\t\tChannel Width: %s\n', cell.eht.chan_width); } printf('\n'); From 2010cfde392e6038121c87dd52767ea6d4c75fd3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 17 Jun 2026 12:01:52 +0200 Subject: [PATCH 140/228] procd: update to Git HEAD (2026-06-17) 9ff6e43bb75f service: notify instance exit details via ubus 4f42296dc4f0 jail: mount rootfs overlay with userxattr in user namespace 60fdbf00e924 jail: chown rootfs overlay dir to mapped root in user namespace Signed-off-by: Felix Fietkau --- package/system/procd/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/system/procd/Makefile b/package/system/procd/Makefile index de7d5f77e0..1603c89131 100644 --- a/package/system/procd/Makefile +++ b/package/system/procd/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/procd.git -PKG_MIRROR_HASH:=f57f124eb1f6a0a7100cc9327bc4842d3667f611d789fc4b3e8ea4a18f73955f -PKG_SOURCE_DATE:=2026-05-22 -PKG_SOURCE_VERSION:=74bfbee8adb8162ee3f1427905af06836f332a37 +PKG_MIRROR_HASH:=bd9e510b303b58f1edb1bfc4629e523f9a96c80a5b66cf5c972f9245bfec5596 +PKG_SOURCE_DATE:=2026-06-17 +PKG_SOURCE_VERSION:=60fdbf00e924fff0a510c4ec31c520d35e69bfe1 CMAKE_INSTALL:=1 PKG_LICENSE:=GPL-2.0 From c9945c203accce9dad4799ae4fddecefc49ea814 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 12 Mar 2026 14:50:05 +0100 Subject: [PATCH 141/228] lldpd: resolve bridge VLAN sub-interfaces to member ports When bridge VLAN filtering is active, network_get_physdev resolves UCI interface names to the VLAN sub-interface (e.g. br-lanv0) rather than the bridge master. LLDP frames use reserved multicast (01:80:c2:00:00:0e) which bridges trap to member ports, so lldpd must listen on the physical ports to receive them. Detect when the resolved device is a sub-interface of a bridge and expand it to the list of bridge member ports instead. Signed-off-by: John Crispin --- .../network/services/lldpd/files/lldpd.init | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/package/network/services/lldpd/files/lldpd.init b/package/network/services/lldpd/files/lldpd.init index e9891389c2..50063a01bc 100644 --- a/package/network/services/lldpd/files/lldpd.init +++ b/package/network/services/lldpd/files/lldpd.init @@ -123,6 +123,23 @@ get_config_restart_hash() { export -n "$var=$_hash" } +resolve_bridge_member_ports() { + local _lower _bridge _port _ports="" + + _lower=$(ls "/sys/class/net/$1/" 2>/dev/null | grep "^lower_" | head -1) + [ -n "$_lower" ] || return 1 + + _bridge="${_lower#lower_}" + [ -d "/sys/class/net/$_bridge/bridge" ] || return 1 + + for _port in $(ls "/sys/class/net/$_bridge/" 2>/dev/null | grep "^lower_"); do + append _ports "${_port#lower_}" "," + done + + [ -n "$_ports" ] || return 1 + echo "$_ports" +} + get_interface_csv() { local _ifaces config_get _ifaces "$2" "$3" @@ -134,7 +151,15 @@ get_interface_csv() { local _l2device="" if network_get_physdev _l2device "$_iface" || [ -e "/sys/class/net/$_iface" ]; then - append _ifnames "${_l2device:-$_iface}" "," + local _resolved="${_l2device:-$_iface}" + local _ports + # LLDP uses reserved multicast (01:80:c2:00:00:0e) that bridges + # trap rather than forward; trapped frames arrive on the member + # ports, not on bridge VLAN sub-interfaces, so resolve down to + # the individual bridge member ports + _ports=$(resolve_bridge_member_ports "$_resolved") + [ -n "$_ports" ] && _resolved="$_ports" + append _ifnames "$_resolved" "," else # Glob case (interface is e.g. '!eth1' or 'eth*' or '*') append _ifnames "$_iface" "," From d2f17ddd395ef4717555e5bd2eddb2e787d94f31 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 16 Apr 2026 14:26:11 +0200 Subject: [PATCH 142/228] netifd: expose udhcpc timeout/retry/tryagain UCI options in dhcp.sh proto/dhcp.sh hardcoded `-t 0` (infinite retries) with no way for UCI / operator to tune per-retry interval (udhcpc -T), retry count (udhcpc -t) or failure retry-loop wait (udhcpc -A). Add three new proto config ints (timeout, retry, tryagain) and thread them into the udhcpc command line. Unset options preserve existing behaviour: retry defaults to 0, timeout and tryagain are omitted so udhcpc uses its own RFC defaults. Signed-off-by: John Crispin Signed-off-by: Felix Fietkau --- .../config/netifd/files/lib/netifd/proto/dhcp.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh b/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh index 5d8e0dda5e..5765efffaa 100755 --- a/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh +++ b/package/network/config/netifd/files/lib/netifd/proto/dhcp.sh @@ -28,6 +28,9 @@ proto_dhcp_init_config() { proto_config_add_string mtu6rd proto_config_add_string customroutes proto_config_add_boolean classlessroute + proto_config_add_int timeout + proto_config_add_int retry + proto_config_add_int tryagain } proto_dhcp_add_sendopts() { @@ -55,8 +58,8 @@ proto_dhcp_setup() { local config="$1" local iface="$2" - local ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute - json_get_vars ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute + local ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute timeout retry tryagain + json_get_vars ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute timeout retry tryagain local opt dhcpopts for opt in $reqopts; do @@ -102,7 +105,9 @@ proto_dhcp_setup() { proto_run_command "$config" udhcpc \ -p /var/run/udhcpc-$iface.pid \ -s /lib/netifd/dhcp.script \ - -f -t 0 -i "$iface" \ + -f -t "${retry:-0}" -i "$iface" \ + ${timeout:+-T "$timeout"} \ + ${tryagain:+-A "$tryagain"} \ ${ipaddr:+-r ${ipaddr/\/*/}} \ ${hostname:+-x "hostname:$hostname"} \ ${emptyvendorid:+-V ""} \ From 8c613a9a224c0d2c096fc635980834b9954db035 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 19 Jun 2026 16:32:19 +0200 Subject: [PATCH 143/228] base-files: derive DHCP DUID from device MAC address The DUID-UUID was generated from a random UUID, which is regenerated on every fresh flash and therefore does not survive reconfiguration events such as reflashing without keeping the configuration. RFC8415/RFC6355 prefer a DUID that remains stable across such events. Add a ucode helper that picks the first LAN port (falling back to WAN) from /etc/board.json, resolves its MAC address and derives a stable UUID from it, falling back to a random UUID only when that fails. Signed-off-by: Felix Fietkau --- package/base-files/Makefile | 3 +- .../etc/uci-defaults/14_network-generate-duid | 6 +- .../files/usr/libexec/duid-generate | 120 ++++++++++++++++++ 3 files changed, 126 insertions(+), 3 deletions(-) create mode 100755 package/base-files/files/usr/libexec/duid-generate diff --git a/package/base-files/Makefile b/package/base-files/Makefile index 2f84179cb3..d19f6fc712 100644 --- a/package/base-files/Makefile +++ b/package/base-files/Makefile @@ -43,7 +43,8 @@ define Package/base-files +netifd +libc +jsonfilter +SIGNED_PACKAGES:usign +SIGNED_PACKAGES:openwrt-keyring \ +NAND_SUPPORT:ubi-utils +fstools +fwtool \ +SELINUX:procd-selinux +!SELINUX:procd +USE_SECCOMP:procd-seccomp \ - +SELINUX:busybox-selinux +!SELINUX:busybox + +SELINUX:busybox-selinux +!SELINUX:busybox \ + +ucode +ucode-mod-fs +ucode-mod-digest TITLE:=Base filesystem for OpenWrt URL:=https://openwrt.org/ VERSION:=$(PKG_RELEASE)~$(lastword $(subst -, ,$(REVISION))) diff --git a/package/base-files/files/etc/uci-defaults/14_network-generate-duid b/package/base-files/files/etc/uci-defaults/14_network-generate-duid index c793dba695..7742897617 100644 --- a/package/base-files/files/etc/uci-defaults/14_network-generate-duid +++ b/package/base-files/files/etc/uci-defaults/14_network-generate-duid @@ -1,8 +1,10 @@ [ "$(uci -q get network.globals.dhcp_default_duid || echo "auto")" != "auto" ] && exit 0 +duid="$(/usr/libexec/duid-generate)" +[ -n "$duid" ] || exit 1 + uci -q batch <<-EOF >/dev/null - # DUID-UUID - RFC6355 - set network.globals.dhcp_default_duid="$(printf '%s%s' '0004' $(cat /proc/sys/kernel/random/uuid | sed -e 's/-//g'))" + set network.globals.dhcp_default_duid="$duid" commit network EOF diff --git a/package/base-files/files/usr/libexec/duid-generate b/package/base-files/files/usr/libexec/duid-generate new file mode 100755 index 0000000000..2318239feb --- /dev/null +++ b/package/base-files/files/usr/libexec/duid-generate @@ -0,0 +1,120 @@ +#!/usr/bin/env ucode +'use strict'; + +import { readfile } from 'fs'; +import * as digest from 'digest'; + +// Fixed salt prefixed to the MAC address before hashing. It only separates this +// particular use of the MAC from any other; the value itself carries no meaning. +const DUID_SALT = 'openwrt-dhcp-duid:'; +const DUID_TYPE_UUID = '0004'; + +function mac_normalise(mac) { + if (type(mac) != 'string') + return null; + + mac = lc(trim(mac)); + + if (!match(mac, /^[0-9a-f]{2}(:[0-9a-f]{2}){5}$/)) + return null; + + if (mac == '00:00:00:00:00:00') + return null; + + return mac; +} + +function sysfs_mac(dev) { + if (!dev) + return null; + + return mac_normalise(readfile('/sys/class/net/' + dev + '/address')); +} + +function role_mac(board, role) { + if (type(role) != 'object') + return null; + + let dev; + if (type(role.ports) == 'array' && length(role.ports) > 0) + dev = role.ports[0]; + else + dev = role.device; + + // Prefer the live hardware address of the physical port. + let mac = sysfs_mac(dev); + if (mac) + return mac; + + // Fall back to MAC addresses recorded in board.json. + mac = mac_normalise(board?.network_device?.[dev]?.macaddr); + if (mac) + return mac; + + return mac_normalise(role.macaddr); +} + +function board_mac(board) { + let net = board?.network; + if (type(net) != 'object') + return null; + + for (let prefix in ['lan', 'wan']) { + let mac = role_mac(board, net[prefix]); + if (mac) + return mac; + + for (let name in keys(net)) { + if (substr(name, 0, length(prefix)) != prefix) + continue; + + mac = role_mac(board, net[name]); + if (mac) + return mac; + } + } + + return null; +} + +function uuid_set_bits(u, version) { + let b6 = (hex(substr(u, 12, 2)) & 0x0f) | (version << 4); + let b8 = (hex(substr(u, 16, 2)) & 0x3f) | 0x80; + + return substr(u, 0, 12) + sprintf('%02x', b6) + + substr(u, 14, 2) + sprintf('%02x', b8) + + substr(u, 18, 14); +} + +function uuid_from_mac(mac) { + let hash = digest.sha1(DUID_SALT + mac); + if (type(hash) != 'string' || length(hash) < 32) + return null; + + return uuid_set_bits(substr(hash, 0, 32), 5); +} + +function uuid_random() { + let uuid = readfile('/proc/sys/kernel/random/uuid'); + if (!uuid) + return null; + + return join('', split(trim(uuid), '-')); +} + +let board; +try { + board = json(readfile('/etc/board.json')); +} catch (e) { + board = null; +} + +let mac = board_mac(board); +let uuid = mac ? uuid_from_mac(mac) : null; + +uuid ??= uuid_random(); + +if (!uuid) + exit(1); + +print(DUID_TYPE_UUID + uuid + '\n'); From a0c5a58123fd0cee1bbe9ee5a2ac9c33e22ecdf0 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 24 Jun 2026 11:22:26 +0200 Subject: [PATCH 144/228] mt76: update to Git HEAD (2026-06-23) 012e52ae3805 wifi: mt76: use hrtimer_setup() in mt76x02u beacon init d2b01fbc329b mt76: pass LED define via ccflags-y 9a46d8d21d2a wifi: mt76: add PS buffering support for HW-managed TIM drivers 9e613fb007f5 wifi: mt76: mt7915: handle MCU PS sync events b0af99f238f7 wifi: mt76: mt7996: handle UNI PS sync events 34064bd58bb3 wifi: mt76: mt7925: clean up DMA on probe failure 4ab8f2122dcb wifi: mt76: disable rx napi before queue cleanup 381582f2a5de wifi: mt76: mt7996: avoid memset overwriting tx_info->control.flags d463ed9490ab wifi: mt76: mt7921: fix resource leak in probe error path dd1459c0c708 wifi: mt76: mt7921/mt7925: fix NULL dereference in CSA beacon 6ae6f2b58cf5 wifi: mt76: route TDLS-peer frames as 3-addr non-DS in HW encap 0753cf183d8c wifi: mt76: mt7925: don't disable AP BSS when removing TDLS peer fe0555feb30a wifi: mt76: use kfree_rcu for offchannel link in mt76_put_vif_phy_link 97fc0e785d0e wifi: mt76: mt7921: fix uninitialized variable warning 49a0aa659f7b wifi: mt76: drop redundant device reference a4f3781dea07 wifi: mt76x0u: drop redundant device reference 52071e885528 wifi: mt76x2u: drop redundant device reference 0aca66c123f8 wifi: mt76: mt792xu: drop redundant device reference 5c94494f1b8d dma.h: add missing variable initialization 756b1c67eb3b wifi: mt76: mt7925: add Netgear A8500 USB device ID 58331e62df80 wifi: mt76: mt7996: Fix NULL pointer dereference in mt7996_init_tx_queues() bd493e29f7e0 wifi: mt76: mt7925: fix stale pointer comparisons in change_vif_links 3c575281716f wifi: mt76: mt7925: add 320MHz bandwidth to bss_rlm_tlv b1f7e240c717 wifi: mt76: mt7925: handle 320MHz bandwidth in RXV and TXS 06277d860b3d wifi: mt76: mt7925: populate EHT 320MHz MCS map in sta_rec 70bfd49d255a wifi: mt76: mt7925: advertise EHT 320MHz capabilities for 6GHz band fda04bb435fa wifi: mt76: mt7925: add MT7927 chip ID helpers 6e5802e93dfb wifi: mt76: mt7925: add MT7927 firmware paths 8175695dcd5e wifi: mt76: mt7925: use irq_map for chip-specific interrupt handling f698c7f22569 wifi: mt76: mt7925: disable ASPM and runtime PM for MT7927 1f91523cb928 wifi: mt76: connac: replace is_mt7925() with is_connac3() 9342a017992d wifi: mt76: mt7925: use link-specific removal for non-MLD STA 3969bb117161 wifi: mt76: connac: tolerate inactive BSS deactivation d045c72b294c wifi: mt76: mt792x: add MT7927 WFSYS reset support b81028de36e8 wifi: mt76: mt792x: factor out common DMA queue allocation 903f8b3bfa02 wifi: mt76: mt7925: switch DMA init to common mt792x queue helpers 79e061f30b0c wifi: mt76: mt792x: add MT7927-specific PCIe DMA support 3e55b6595da9 wifi: mt76: mt7925: sync MT7927 BSS band assignment b8e20dc9c221 wifi: mt76: mt7925: add MBMC event handling 049633e34b79 wifi: mt76: mt792x: enable CNM ops for MT7927 8a7d31ac92b0 wifi: mt76: mt7925: add MT7927 PCIe support 62956aec1615 wifi: mt76: mt7925: add MT7927 USB support 4ed651794a7f wifi: mt76: mt7925: keep TX BA state in the primary WCID 6cdcb480f32b wifi: mt76: mt7925: pass WCID explicitly to mt7925_mcu_sta_ba() f142a55342a4 wifi: mt76: mt7925: program BA state on active links 3e54e1c80079 wifi: mt76: mt792x: skip MLD header rewrite for 802.3 encap TX e588dc4843ab wifi: mt76: mt7925: validate skb length in testmode query 2802466a9440 wifi: mt76: mt7915: validate skb length in txpower SKU query d8fc8629f2bc wifi: mt76: mt7996: Fix possible token leak in mt7996_tx_prepare_skb() 652740d6f12e wifi: mt76: mt7996: Fix possible NULL pointer dereference in mt7996_mac_write_txwi_80211() f5f14a017454 Revert "wifi: mt76: disable rx napi before queue cleanup" 1e7ac9bf7764 Revert "wifi: mt76: mt7996: avoid memset overwriting tx_info->control.flags" 934f64710479 wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add() 1ba5cc4b4023 wifi: mt76: mt7925: drop redundant chandef.chan NULL check in MT7927 path 02934c3d0726 wifi: mt76: mt7996: remove redundant pdev->bus check in probe 2ab649809db7 wifi: mt76: add wcid publish check in mt76_sta_add 7825972b0a3c wifi: mt76: transform aspm_conf for pci_disable_link_state c0e41eb57d96 wifi: mt76: mt7996: reduce phy work in set_coverage e640565e0701 wifi: mt76: mt7996: limit work in set_bitrate_mask 761478b9b1a3 wifi: mt76: connac: use a helper to cache txpower_cur 1e05654e6aec wifi: mt76: connac: factor out rate power limit calculation 994443de60ba wifi: mt76: mt792x: report txpower for the requested vif link 600dbf123399 wifi: mt76: mt792x: add common USB transport reset helpers 91f19ba39348 wifi: mt76: mt7921u: escalate broken USB transport to device reset 03644ac19f9a wifi: mt76: fix argument to ieee80211_is_first_frag() cd931f9e5fa6 wifi: mt76: mt7996: disable UNI_BSS_INFO_PROTECT_INFO for mt7996 fc890d5b3603 wifi: mt76: mt7921: refactor regulatory domain handling to regd.[ch] 1ec0abf5d9aa wifi: mt76: mt7921: refactor CLC support check flow cd3d2a68c90c wifi: mt76: mt7921: refactor regulatory notifier flow 06d1ccbecd50 wifi: mt76: mt7921: add auto regdomain switch support 4fb4a076256f wifi: mt76: mt7921: disable auto regd changes after user set 748311faa56c wifi: mt76: mt7915: fix potential tx_retries underflow ee2bb3337274 wifi: mt76: mt7921: fix potential tx_retries underflow e791fb66e47c wifi: mt76: mt7925: fix potential tx_retries underflow 9f60dd01e62c wifi: mt76: mt7996: fix potential tx_retries underflow a3bf7dac3e58 wifi: mt76: mt7921: assert sniffer on chanctx change 72d8dc857443 wifi: mt76: Drop unneeded mt76_register_debugfs_fops() return checks f8b59ca3be7b wifi: mt76: don't pin undrainable PS stations in the tx scheduler 2dd6e4c8892f firmware: update MT7981 firmware to version 20260515 Signed-off-by: Felix Fietkau --- package/kernel/mt76/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index c2e3a199fc..b7a1bc2402 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2026-03-21 -PKG_SOURCE_VERSION:=018f60316d4dd6b4e741874eda40e2dfaa29df3b -PKG_MIRROR_HASH:=54a8125453a6fe04c89cf5335bdf0ea16c409361e1e5a79fb339d67cee26df0e +PKG_SOURCE_DATE:=2026-06-23 +PKG_SOURCE_VERSION:=2dd6e4c8892f59b7943ee163afd6ced881bfb31b +PKG_MIRROR_HASH:=9cd490cc08ccbcdd1476edfefd689d01ba5ef43a4a0cc7e23f13ac3a1e1522c5 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 From e40458a2ffb2b54fa6eaaec54c315e5b402e7558 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 24 Jun 2026 12:33:11 +0200 Subject: [PATCH 145/228] mt76: remove obsolete patches Already included in the last update Fixes: a0c5a58123fd ("mt76: update to Git HEAD (2026-06-23)" Signed-off-by: Felix Fietkau --- ...rtimer_setup-in-mt76x02u-beacon-init.patch | 33 ------------------- .../003-pass-LED-define-via-ccflags-y.patch | 26 --------------- 2 files changed, 59 deletions(-) delete mode 100644 package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch delete mode 100644 package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch diff --git a/package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch b/package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch deleted file mode 100644 index 705104cc4b..0000000000 --- a/package/kernel/mt76/patches/002-use-hrtimer_setup-in-mt76x02u-beacon-init.patch +++ /dev/null @@ -1,33 +0,0 @@ -From a95e567eb0e06d460dee234f9c845fbfb215ab11 Mon Sep 17 00:00:00 2001 -From: Mieczyslaw Nalewaj -Date: Thu, 29 Jan 2026 16:36:25 +0100 -Subject: [PATCH] wifi: mt76: use hrtimer_setup() in mt76x02u beacon init - -Replace the two-step hrtimer initialization pattern with a single -consolidated call to hrtimer_setup(). -The legacy approach of calling hrtimer_init() followed by manual -assignment to timer.function is deprecated. The new hrtimer_setup() -helper atomically initializes the timer and assigns the callback -function in one operation, eliminating the race-prone intermediate -state where the timer is initialized but lacks a handler. - -Signed-off-by: Mieczyslaw Nalewaj ---- - mt76x02_usb_core.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/mt76x02_usb_core.c b/mt76x02_usb_core.c -index c94c2f661..3a28a8cc1 100644 ---- a/mt76x02_usb_core.c -+++ b/mt76x02_usb_core.c -@@ -264,8 +264,8 @@ void mt76x02u_init_beacon_config(struct mt76x02_dev *dev) - }; - dev->beacon_ops = &beacon_ops; - -- hrtimer_init(&dev->pre_tbtt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); -- dev->pre_tbtt_timer.function = mt76x02u_pre_tbtt_interrupt; -+ hrtimer_setup(&dev->pre_tbtt_timer, mt76x02u_pre_tbtt_interrupt, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); - INIT_WORK(&dev->pre_tbtt_work, mt76x02u_pre_tbtt_work); - - mt76x02_init_beacon_config(dev); diff --git a/package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch b/package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch deleted file mode 100644 index 243d4efee8..0000000000 --- a/package/kernel/mt76/patches/003-pass-LED-define-via-ccflags-y.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Mieczyslaw Nalewaj -Date: Thu, 2 Apr 2026 19:01:10 +0200 -Subject: Subject: [PATCH] mt76: pass LED define via ccflags-y - -Replace the deprecated EXTRA_CFLAGS with ccflags-y so that -the -DCONFIG_MT76_LEDS define is applied correctly by the kernel -build system. EXTRA_CFLAGS is no longer honored by recent -kbuilds[1]; ccflags-y is the supported variable and works -on kernels 6.12 and 6.18. - -1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.18.20&id=f77bf01425b11947eeb3b5b54685212c302741b8 - -Signed-off-by: Mieczyslaw Nalewaj ---- - Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/Makefile -+++ b/Makefile -@@ -1,5 +1,5 @@ - # SPDX-License-Identifier: BSD-3-Clause-Clear --EXTRA_CFLAGS += -Werror -DCONFIG_MT76_LEDS -+ccflags-y += -Werror -DCONFIG_MT76_LEDS - obj-m := mt76.o - obj-$(CONFIG_MT76_USB) += mt76-usb.o - obj-$(CONFIG_MT76_SDIO) += mt76-sdio.o From a623f81e4c9642c127151b17001c7c2694878ba1 Mon Sep 17 00:00:00 2001 From: Qingfang Deng Date: Wed, 24 Jun 2026 09:32:56 +0800 Subject: [PATCH 146/228] kernel: move flowtable fix to backport-6.18 The patch is accepted upstream, so move it to backport-6.18 and update its headers. Signed-off-by: Qingfang Deng Link: https://github.com/openwrt/openwrt/pull/23930 Signed-off-by: Robert Marko --- ...ilter-flowtable-fix-offloaded-ct-timeout-never-b.patch} | 7 ++++--- ...filter-nft_flow_offload-handle-netdevice-events-f.patch | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) rename target/linux/generic/{pending-6.18/704-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch => backport-6.18/704-v7.2-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch} (92%) diff --git a/target/linux/generic/pending-6.18/704-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch b/target/linux/generic/backport-6.18/704-v7.2-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch similarity index 92% rename from target/linux/generic/pending-6.18/704-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch rename to target/linux/generic/backport-6.18/704-v7.2-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch index 852a0d43d4..22cd634071 100644 --- a/target/linux/generic/pending-6.18/704-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch +++ b/target/linux/generic/backport-6.18/704-v7.2-netfilter-flowtable-fix-offloaded-ct-timeout-never-b.patch @@ -1,7 +1,7 @@ +From 53b3e60edb674b442b2b3bbdba484667b0f47a5d Mon Sep 17 00:00:00 2001 From: Adrian Bente Date: Thu, 28 May 2026 10:08:51 +0300 -Subject: [PATCH v2 net] netfilter: flowtable: fix offloaded ct timeout never being extended -Message-ID: <20260528070851.3913-1-adibente@gmail.com> +Subject: [PATCH] netfilter: flowtable: fix offloaded ct timeout never being extended OpenWrt has recently migrated many platforms to kernel 6.18. On the MediaTek platform, which supports hardware network offloading, WiFi @@ -29,10 +29,11 @@ snapshot and compare against that same absolute snapshot in the cmpxchg, so the timeout extension actually takes effect while the datapath remains authoritative if it updates ct->timeout concurrently. -Suggested-by: Florian Westphal Fixes: 03428ca5cee9 ("netfilter: conntrack: rework offload nf_conn timeout extension logic") Cc: stable@vger.kernel.org +Suggested-by: Florian Westphal Signed-off-by: Adrian Bente +Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_flow_table_core.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/target/linux/generic/pending-6.18/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/pending-6.18/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch index d37fbd7c22..246e1a4c6a 100644 --- a/target/linux/generic/pending-6.18/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +++ b/target/linux/generic/pending-6.18/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch @@ -10,7 +10,7 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c -@@ -805,6 +805,23 @@ static struct pernet_operations nf_flow_ +@@ -810,6 +810,23 @@ static struct pernet_operations nf_flow_ .exit_batch = nf_flow_table_pernet_exit, }; @@ -34,7 +34,7 @@ Signed-off-by: Pablo Neira Ayuso static int __init nf_flow_table_module_init(void) { int ret; -@@ -821,6 +838,10 @@ static int __init nf_flow_table_module_i +@@ -826,6 +843,10 @@ static int __init nf_flow_table_module_i if (ret) goto out_bpf; @@ -45,7 +45,7 @@ Signed-off-by: Pablo Neira Ayuso return 0; out_bpf: -@@ -832,6 +853,7 @@ out_offload: +@@ -837,6 +858,7 @@ out_offload: static void __exit nf_flow_table_module_exit(void) { From 9635f44eade368f6be619eb8099f9f7f3cb2859d Mon Sep 17 00:00:00 2001 From: Mieczyslaw Nalewaj Date: Sun, 7 Jun 2026 19:35:10 +0200 Subject: [PATCH 147/228] kernel: split nf-nathelper-extra into individual packages Split kmod-nf-nathelper-extra into separate helper packages and keep the original package as a compatibility meta-package. This allows selecting only the required protocol helpers instead of installing all helper modules and dependencies. Signed-off-by: Mieczyslaw Nalewaj Link: https://github.com/openwrt/openwrt/pull/23690 Signed-off-by: Robert Marko --- include/netfilter.mk | 22 --- package/kernel/linux/modules/netfilter.mk | 186 ++++++++++++++++++++-- 2 files changed, 175 insertions(+), 33 deletions(-) diff --git a/include/netfilter.mk b/include/netfilter.mk index 2159540318..c38fb7931a 100644 --- a/include/netfilter.mk +++ b/include/netfilter.mk @@ -201,27 +201,6 @@ $(eval $(call nf_add,NF_NATHELPER,CONFIG_NF_CONNTRACK_FTP, $(P_XT)nf_conntrack_f $(eval $(call nf_add,NF_NATHELPER,CONFIG_NF_NAT_FTP, $(P_XT)nf_nat_ftp)) -# nathelper-extra - -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_BROADCAST, $(P_XT)nf_conntrack_broadcast)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_NETBIOS_NS, $(P_XT)nf_conntrack_netbios_ns)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_SANE, $(P_XT)nf_conntrack_sane)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_AMANDA, $(P_XT)nf_conntrack_amanda)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_AMANDA, $(P_XT)nf_nat_amanda)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_H323, $(P_XT)nf_conntrack_h323)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_H323, $(P_V4)nf_nat_h323)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_PPTP, $(P_XT)nf_conntrack_pptp)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_PPTP, $(P_V4)nf_nat_pptp)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_SIP, $(P_XT)nf_conntrack_sip)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_SIP, $(P_XT)nf_nat_sip)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_SNMP, $(P_XT)nf_conntrack_snmp)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_SNMP_BASIC, $(P_V4)nf_nat_snmp_basic)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_TFTP, $(P_XT)nf_conntrack_tftp)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_TFTP, $(P_XT)nf_nat_tftp)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_CONNTRACK_IRC, $(P_XT)nf_conntrack_irc)) -$(eval $(call nf_add,NF_NATHELPER_EXTRA,CONFIG_NF_NAT_IRC, $(P_XT)nf_nat_irc)) - - # nflog $(eval $(call nf_add,IPT_NFLOG,CONFIG_NETFILTER_XT_TARGET_NFLOG, $(P_XT)xt_NFLOG)) @@ -375,7 +354,6 @@ IPT_BUILTIN += $(IPT_NAT-y) IPT_BUILTIN += $(IPT_NAT6-y) IPT_BUILTIN += $(IPT_NAT_EXTRA-y) IPT_BUILTIN += $(NF_NATHELPER-y) -IPT_BUILTIN += $(NF_NATHELPER_EXTRA-y) IPT_BUILTIN += $(IPT_TPROXY-y) IPT_BUILTIN += $(NFNETLINK-y) IPT_BUILTIN += $(NFNETLINK_LOG-y) diff --git a/package/kernel/linux/modules/netfilter.mk b/package/kernel/linux/modules/netfilter.mk index ffacd80a73..6ef1522115 100644 --- a/package/kernel/linux/modules/netfilter.mk +++ b/package/kernel/linux/modules/netfilter.mk @@ -512,7 +512,7 @@ define KernelPackage/nf-ipvs-sip SUBMENU:=$(NF_MENU) TITLE:=Virtual Server SIP protocol support KCONFIG:=CONFIG_IP_VS_PE_SIP - DEPENDS:=kmod-nf-ipvs +kmod-nf-nathelper-extra + DEPENDS:=kmod-nf-ipvs +kmod-nf-nathelper-sip FILES:=$(LINUX_DIR)/net/netfilter/ipvs/ip_vs_pe_sip.ko endef @@ -621,30 +621,194 @@ $(eval $(call KernelPackage,nf-nathelper)) define KernelPackage/nf-nathelper-extra SUBMENU:=$(NF_MENU) TITLE:=Extra Conntrack and NAT helpers - KCONFIG:=$(KCONFIG_NF_NATHELPER_EXTRA) - FILES:=$(foreach mod,$(NF_NATHELPER_EXTRA-m),$(LINUX_DIR)/net/$(mod).ko) - AUTOLOAD:=$(call AutoProbe,$(notdir $(NF_NATHELPER_EXTRA-m))) - DEPENDS:=+kmod-nf-nat +kmod-lib-textsearch +kmod-asn1-decoder + DEPENDS:= \ + +kmod-nf-nathelper-amanda \ + +kmod-nf-nathelper-broadcast \ + +kmod-nf-nathelper-h323 \ + +kmod-nf-nathelper-irc \ + +kmod-nf-nathelper-netbios \ + +kmod-nf-nathelper-pptp \ + +kmod-nf-nathelper-sane \ + +kmod-nf-nathelper-sip \ + +kmod-nf-nathelper-snmp \ + +kmod-nf-nathelper-tftp endef define KernelPackage/nf-nathelper-extra/description - Extra Netfilter (IPv4) Conntrack and NAT helpers - Includes: + Compatibility package providing all extra Netfilter + conntrack and NAT helpers. + This package depends on all individual helper packages: - amanda + - broadcast - h323 - irc - - mms + - netbios - pptp - - proto_gre + - sane - sip - - snmp_basic + - snmp - tftp - - broadcast + Select individual helper packages instead if only a + subset is required. endef $(eval $(call KernelPackage,nf-nathelper-extra)) +define KernelPackage/nf-nathelper-amanda + SUBMENU:=$(NF_MENU) + TITLE:=Amanda conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_AMANDA \ + CONFIG_NF_NAT_AMANDA + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_amanda.ko \ + $(LINUX_DIR)/net/$(P_XT)nf_nat_amanda.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_amanda nf_nat_amanda) + DEPENDS:=+kmod-nf-nat +kmod-lib-textsearch +endef + +$(eval $(call KernelPackage,nf-nathelper-amanda)) + + +define KernelPackage/nf-nathelper-broadcast + SUBMENU:=$(NF_MENU) + TITLE:=Broadcast conntrack helper + KCONFIG:=CONFIG_NF_CONNTRACK_BROADCAST + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_broadcast.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_broadcast) + DEPENDS:=+kmod-nf-conntrack +endef + +$(eval $(call KernelPackage,nf-nathelper-broadcast)) + + +define KernelPackage/nf-nathelper-h323 + SUBMENU:=$(NF_MENU) + TITLE:=H.323 conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_H323 \ + CONFIG_NF_NAT_H323 + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_h323.ko \ + $(LINUX_DIR)/net/$(P_V4)nf_nat_h323.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_h323 nf_nat_h323) + DEPENDS:=+kmod-nf-nat +endef + +$(eval $(call KernelPackage,nf-nathelper-h323)) + + +define KernelPackage/nf-nathelper-irc + SUBMENU:=$(NF_MENU) + TITLE:=IRC conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_IRC \ + CONFIG_NF_NAT_IRC + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_irc.ko \ + $(LINUX_DIR)/net/$(P_XT)nf_nat_irc.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_irc nf_nat_irc) + DEPENDS:=+kmod-nf-nat +endef + +$(eval $(call KernelPackage,nf-nathelper-irc)) + + +define KernelPackage/nf-nathelper-netbios + SUBMENU:=$(NF_MENU) + TITLE:=NetBIOS NS conntrack helper + KCONFIG:=CONFIG_NF_CONNTRACK_NETBIOS_NS + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_netbios_ns.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_netbios_ns) + DEPENDS:=+kmod-nf-conntrack +kmod-nf-nathelper-broadcast +endef + +$(eval $(call KernelPackage,nf-nathelper-netbios)) + + +define KernelPackage/nf-nathelper-pptp + SUBMENU:=$(NF_MENU) + TITLE:=PPTP conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_PPTP \ + CONFIG_NF_NAT_PPTP + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_pptp.ko \ + $(LINUX_DIR)/net/$(P_V4)nf_nat_pptp.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_pptp nf_nat_pptp) + DEPENDS:=+kmod-nf-nat +endef + +$(eval $(call KernelPackage,nf-nathelper-pptp)) + + +define KernelPackage/nf-nathelper-sane + SUBMENU:=$(NF_MENU) + TITLE:=SANE conntrack helper + KCONFIG:=CONFIG_NF_CONNTRACK_SANE + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_sane.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_sane) + DEPENDS:=+kmod-nf-conntrack +endef + +$(eval $(call KernelPackage,nf-nathelper-sane)) + + +define KernelPackage/nf-nathelper-sip + SUBMENU:=$(NF_MENU) + TITLE:=SIP conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_SIP \ + CONFIG_NF_NAT_SIP + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_sip.ko \ + $(LINUX_DIR)/net/$(P_XT)nf_nat_sip.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_sip nf_nat_sip) + DEPENDS:=+kmod-nf-nat +endef + +$(eval $(call KernelPackage,nf-nathelper-sip)) + + +define KernelPackage/nf-nathelper-snmp + SUBMENU:=$(NF_MENU) + TITLE:=SNMP conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_SNMP \ + CONFIG_NF_NAT_SNMP_BASIC + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_snmp.ko \ + $(LINUX_DIR)/net/$(P_V4)nf_nat_snmp_basic.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_snmp nf_nat_snmp_basic) + DEPENDS:= \ + +kmod-asn1-decoder \ + +kmod-nf-nat \ + +kmod-nf-nathelper-broadcast +endef + +$(eval $(call KernelPackage,nf-nathelper-snmp)) + + +define KernelPackage/nf-nathelper-tftp + SUBMENU:=$(NF_MENU) + TITLE:=TFTP conntrack and NAT helper + KCONFIG:= \ + CONFIG_NF_CONNTRACK_TFTP \ + CONFIG_NF_NAT_TFTP + FILES:= \ + $(LINUX_DIR)/net/$(P_XT)nf_conntrack_tftp.ko \ + $(LINUX_DIR)/net/$(P_XT)nf_nat_tftp.ko + AUTOLOAD:=$(call AutoProbe,nf_conntrack_tftp nf_nat_tftp) + DEPENDS:=+kmod-nf-nat +endef + +$(eval $(call KernelPackage,nf-nathelper-tftp)) + + define KernelPackage/ipt-nflog TITLE:=Module for user-space packet logging KCONFIG:=$(KCONFIG_IPT_NFLOG) From 1c8c05ca98ee9f7b67d8160a8cb059be3b2714a1 Mon Sep 17 00:00:00 2001 From: Robert Senderek Date: Mon, 9 Feb 2026 13:07:06 +0100 Subject: [PATCH 148/228] mvebu: add support for Zyxel NAS326 ----- Hardware: CPU: ARMADA 380 1x1332Mhz RAM: 512MB DDR3 FLASH: 256MB MX30LF2G18AC 2x SATA III 2x USB3.0 1x USB2.0 i2c to control various states. RTC with battery 1Gbit LAN (WoL capable) 9x LED RESET button at back Power button at front (gpio-poweroff) Copy button at front ----- Doesn't work FAN control buzzer ----- UART connections Connect UART to port J3 115200 +----+----+----+----+----+ |3.3V| TX | RX | | GND| +----+----+----+ +----+ Depend of UART adapter board can fail to boot when adapter is attached. (all leds are dimmed) . In that case disconnect UART for an < second and after that all leds should be white. Stop u-boot by ctrl-c within 3s window. (bootdelay 7s or more helps) setenv bootdelay 7 saveenv ----- Instalation via UART Boot initramfs-kernel.bin setenv ethact egiga0 setenv serverip 192.168.1.11 setenv ipaddr 192.168.1.12 tftpboot 0x02000000 *initramfs-kernel.bin bootm 0x02000000 - Device is DHCP client by default ( as the other supported NAS) do backup into safe space /dev/mtd3 Kernel-1 /dev/mtd4 RootFS-1 use sysupgrade in console or via luci ----- MAC addresses mac stored in u-boot-env ethaddr label mac = eth0 mac = 5c:6a:80:xx:xx:xx ----- Setting up u-boot dual boot u-boot contain two banks contain two OEM copies To boot OpenWrt from bank1 setenv next_bootfrom 1 saveenv To boot OEM from bank2 setenv next_bootfrom 2 saveenv ----- Configuration via i2c install i2c-tools Enable WoL i2cset -y 0x0 0xa 0xa 0x0006 w Disable WoL i2cset -y 0x0 0xa 0xa 0x0306 w Enable auto power on i2cset -y 0x0 0x0a 0x0a 0x0107 w Disable auto power on i2cset -y 0x0 0x0a 0x0a 0x0007 w Signed-off-by: Robert Senderek Link: https://github.com/openwrt/openwrt/pull/23228 Signed-off-by: Robert Marko --- .../uboot-tools/uboot-envtools/files/mvebu | 3 + .../base-files/etc/board.d/02_network | 7 +- .../base-files/lib/upgrade/platform.sh | 12 + .../dts/marvell/armada-380-zyxel-nas326.dts | 383 ++++++++++++++++++ target/linux/mvebu/image/cortexa9.mk | 14 + 5 files changed, 418 insertions(+), 1 deletion(-) create mode 100644 target/linux/mvebu/files/arch/arm/boot/dts/marvell/armada-380-zyxel-nas326.dts diff --git a/package/boot/uboot-tools/uboot-envtools/files/mvebu b/package/boot/uboot-tools/uboot-envtools/files/mvebu index 7346611acb..018177ab6e 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/mvebu +++ b/package/boot/uboot-tools/uboot-envtools/files/mvebu @@ -78,6 +78,9 @@ methode,edpu) synology,ds213j) ubootenv_add_mtd "u-boot-env" "0x0" "0x10000" "0x10000" ;; +zyxel,nas326) + ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x80000" "0x80000" + ;; esac config_load ubootenv diff --git a/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network b/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network index cd0f4c99c4..9833143d75 100644 --- a/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network +++ b/target/linux/mvebu/cortexa9/base-files/etc/board.d/02_network @@ -15,7 +15,8 @@ mvebu_setup_interfaces() ctera,c200-v2|\ synology,ds213j|\ wd,cloud-ex2-ultra|\ - wd,cloud-mirror-gen2) + wd,cloud-mirror-gen2|\ + zyxel,nas326) ucidef_set_interface_lan "eth0" "dhcp" ;; cznic,turris-omnia) @@ -104,6 +105,10 @@ mvebu_setup_macs() label_mac=$(macaddr_canonicalize $(strings /dev/mtd7|grep -E '([0-9A-F]{2}[:])')) lan_mac=$label_mac ;; + zyxel,nas326) + label_mac=$(mtd_get_mac_ascii u-boot-env ethaddr) + lan_mac=$label_mac + ;; esac [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac diff --git a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh index 10078eec9a..8198bea7b7 100755 --- a/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh +++ b/target/linux/mvebu/cortexa9/base-files/lib/upgrade/platform.sh @@ -8,6 +8,14 @@ RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' REQUIRE_IMAGE_METADATA=1 +nas326_initial_setup() +{ + # initialize UBI if it's running on initramfs + [ "$(rootfs_type)" = "tmpfs" ] || return 0 + + ubirmvol /dev/ubi0 -N ubi_rootfs1 +} + platform_check_image() { case "$(board_name)" in cznic,turris-omnia|\ @@ -37,6 +45,10 @@ platform_do_upgrade() { wd,cloud-mirror-gen2) nand_do_upgrade "$1" ;; + zyxel,nas326) + nas326_initial_setup + nand_do_upgrade "$1" + ;; ctera,c200-v2) part=$(find_mtd_part "active_bank") diff --git a/target/linux/mvebu/files/arch/arm/boot/dts/marvell/armada-380-zyxel-nas326.dts b/target/linux/mvebu/files/arch/arm/boot/dts/marvell/armada-380-zyxel-nas326.dts new file mode 100644 index 0000000000..ca88040a13 --- /dev/null +++ b/target/linux/mvebu/files/arch/arm/boot/dts/marvell/armada-380-zyxel-nas326.dts @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include +#include +#include +#include "armada-380.dtsi" + +/ { + model = "Zyxel NAS326"; + compatible = "zyxel,nas326", "marvell,armada380"; + + aliases { + led-boot = &status_white; + led-failsafe = &status_red; + led-running = &status_white; + led-upgrade = &status_white; + label-mac-device = ð0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + append-rootblock = "nullparameter="; /* override the bootloader args */ + }; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x20000000>; /* 512MB */ + }; + + soc { + ranges = ; + + internal-regs { + timer@c200 { + status = "okay"; + }; + + pcie { + status = "okay"; + + pcie@1,0 { + status = "okay"; + }; + + pcie@2,0 { + status = "okay"; + }; + }; + }; + }; + + usb2_phy: usb2_phy { + compatible = "usb-nop-xceiv"; + vcc-supply = <&usb2_power>; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&button_pins>; + + power { + label = "Power Button"; + linux,code = ; + gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; + }; + + copy { + label = "Copy Button"; + linux,code = ; + gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "Reset Button"; + linux,code = ; + gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + + sata1white { + color = ; + function = LED_FUNCTION_DISK_ACTIVITY; + function-enumerator = <1>; + gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "ata1"; + }; + + sata1red { + color = ; + function = LED_FUNCTION_DISK_ERR; + function-enumerator = <1>; + gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>; + }; + + sata2white { + color = ; + function = LED_FUNCTION_DISK_ACTIVITY; + function-enumerator = <2>; + gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "ata2"; + }; + + sata2red { + color = ; + function = LED_FUNCTION_DISK_ERR; + function-enumerator = <2>; + gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + }; + + usb { + color = ; + function = LED_FUNCTION_USB; + gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "usb-host"; + }; + + status_white: status_white { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>; + }; + + status_red: status_red { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + }; + + copy_white { + color = ; + function = "copy"; + gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>; + }; + + copy_red { + color = ; + function = "copy"; + gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + }; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + usb2_power: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "USB2 Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>; + }; + + reg_sata0: regulator@2 { + compatible = "regulator-fixed"; + regulator-name = "pwr_en_sata0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + regulator-boot-on; + gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>; + }; + + reg_5v_sata0: v5-sata0 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_sata0>; + }; + + reg_12v_sata0: v12-sata0 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + vin-supply = <®_sata0>; + }; + + reg_sata1: regulator@3 { + regulator-name = "pwr_en_sata1"; + compatible = "regulator-fixed"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + regulator-boot-on; + gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>; + }; + + reg_5v_sata1: v5-sata1 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_sata1>; + }; + + reg_12v_sata1: v12-sata1 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata1"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + vin-supply = <®_sata1>; + }; + }; + + gpio-poweroff { + compatible = "gpio-poweroff"; + pinctrl-0 = <&pwr_off>; + pinctrl-names = "default"; + gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>; + }; +}; + +&ahci0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + sata-port@0 { + reg = <0>; + target-supply = <®_sata0>; + #thermal-sensor-cells = <0>; + }; + + sata-port@1 { + reg = <1>; + target-supply = <®_sata1>; + #thermal-sensor-cells = <1>; + }; +}; + +&bm { + status = "okay"; +}; + +&bm_bppi { + status = "okay"; +}; + +ð0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&ge0_rgmii_pins>; + phy = <&phy0>; + phy-mode = "rgmii-id"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <100000>; +}; + +&mdio { + phy0: ethernet-phy@1 { + marvell,reg-init = <0x01 0x16 0x00 0x03 0x01 0x10 0x00 0x1817 0x01 0x11 0x00 0x442a 0x01 0x16 0x00 0x00 0x01 0x00 0x00 0x1140 0x01 0x04 0x00 0x1e1 0x01 0x10 0x00 0x3860 0x01 0x00 0x00 0x9140>; + reg = <1>; + }; +}; + +&nand_controller { + status = "okay"; + + nand: nand@0 { + reg = <0>; + label = "pxa3xx_nand-0"; + nand-rb = <0>; + marvell,nand-keep-config; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x200000>; + read-only; + }; + + partition@200000 { + label = "u-boot-env"; + reg = <0x200000 0x200000>; + }; + + partition@400000 { + label = "Config"; + reg = <0x400000 0xa00000>; + read-only; + }; + + partition@e00000 { + label = "kernel"; + reg = <0xe00000 0xf00000>;/* 15 MB */ + }; + + partition@1d00000 { + label = "ubi"; + reg = <0x1d00000 0x6a00000>;/* 106 MB */ + }; + + partition@8700000 { + label = "Kernel-2"; + reg = <0x8700000 0xf00000>; + read-only; + }; + + partition@9600000 { + label = "RootFS-2"; + reg = <0x9600000 0x6a00000>; + read-only; + }; + }; + }; +}; + +&pinctrl { + button_pins: button_pins { + marvell,pins = "mpp39", "mpp46", "mpp49"; + marvell,function = "gpio"; + }; + + led_pins: led_pins { + marvell,pins = "mpp21", "mpp26", "mpp37", + "mpp48", "mpp50", "mpp52", + "mpp53", "mpp54", "mpp55"; + marvell,function = "gpio"; + }; + + pwr_off: pwr_off { + marvell,pins = "mpp20"; + marvell,function = "gpio"; + }; +}; + +&sdhci { + broken-cd; + wp-inverted; + bus-width = <8>; + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb3_0 { + status = "okay"; +}; + +&usb3_1 { + status = "okay"; +}; diff --git a/target/linux/mvebu/image/cortexa9.mk b/target/linux/mvebu/image/cortexa9.mk index b564e5dc4a..e01a5a8254 100644 --- a/target/linux/mvebu/image/cortexa9.mk +++ b/target/linux/mvebu/image/cortexa9.mk @@ -497,3 +497,17 @@ define Device/wd_cloud-mirror-gen2 IMAGE/uImage-factory.bin := append-kernel endef TARGET_DEVICES += wd_cloud-mirror-gen2 + +define Device/zyxel_nas326 + $(Device/NAND-128K) + DEVICE_VENDOR := Zyxel + DEVICE_MODEL := NAS326 + DEVICE_PACKAGES += mkf2fs e2fsprogs \ + partx-utils kmod-hwmon-drivetemp -ppp -kmod-nft-offload -dnsmasq \ + -odhcpd-ipv6only + DEVICE_DTS := armada-380-zyxel-nas326 + FILESYSTEMS := squashfs ubifs + KERNEL := kernel-bin | append-dtb + KERNEL_INITRAMFS := kernel-bin | append-dtb | uImage none +endef +TARGET_DEVICES += zyxel_nas326 From a7a715e11af8b00a49adcec83d945e67abe89dc6 Mon Sep 17 00:00:00 2001 From: YAJIMA Hideyuki Date: Sun, 21 Jun 2026 00:49:38 +0900 Subject: [PATCH 149/228] ramips: add support for ASUS RT-AC85U This patch adds support for the ASUS RT-AC85U wireless router. It is a dual-band gigabit router based on the MediaTek MT7621AT SoC. MAC Address Layout: - LAN/WAN/2.4G/5G MAC addresses are derived from the factory partition at offset 0xe000. Hardware Specifications: - SoC: MediaTek MT7621AT (880 MHz, 2C/4T) - RAM: 128 MB DDR3 - Flash: 128 MB Winbond W29N01HV NAND - WI1: MediaTek MT7615E (2.4 GHz, 4x4) - WI2: MediaTek MT7615E (5 GHz, 4x4) - Switch: MediaTek MT7530 (Embedded Gigabit Switch) - Ports: 1x WAN, 4x LAN (10/100/1000 Mbps), 1x USB 3.0 - LEDs: Power, LAN, WAN, 2.4G, 5G, USB, WPS - Buttons: WPS, Reset Installation / Flashing guide: 1. Power off the device. 2. Hold Reset button and power on to enter ASUS Restoration mode (slow flash LED). 3. Set your computer's static IP to 192.168.1.x (e.g., 192.168.1.10). 4. Upload the OpenWrt initramfs image via ASUS Restoration tool to 192.168.1.1. 5. Wait for the device to boot into the temporary OpenWrt environment. 6. Access LuCI (192.168.1.1) and flash sysupgrade image to make it permanent. Signed-off-by: YAJIMA Hideyuki Link: https://github.com/openwrt/openwrt/pull/23747 Signed-off-by: Robert Marko --- .../linux/ramips/dts/mt7621_asus_rt-ac85u.dts | 233 ++++++++++++++++++ target/linux/ramips/image/mt7621.mk | 10 + .../mt7621/base-files/lib/upgrade/platform.sh | 1 + 3 files changed, 244 insertions(+) create mode 100644 target/linux/ramips/dts/mt7621_asus_rt-ac85u.dts diff --git a/target/linux/ramips/dts/mt7621_asus_rt-ac85u.dts b/target/linux/ramips/dts/mt7621_asus_rt-ac85u.dts new file mode 100644 index 0000000000..92bca2e14b --- /dev/null +++ b/target/linux/ramips/dts/mt7621_asus_rt-ac85u.dts @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7621.dtsi" + +#include +#include +#include + +/ { + compatible = "asus,rt-ac85u", "mediatek,mt7621-soc"; + model = "ASUS RT-AC85U"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + label-mac-device = &gmac0; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; + }; + + wifi2g { + color = ; + function = LED_FUNCTION_WLAN_2GHZ; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + wifi5g { + color = ; + function = LED_FUNCTION_WLAN_5GHZ; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + + wan { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + }; + + lan { + color = ; + function = LED_FUNCTION_LAN; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + }; + + usb { + color = ; + function = LED_FUNCTION_USB; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + }; + + wps { + color = ; + function = LED_FUNCTION_WPS; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&nand { + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0xe0000>; + read-only; + }; + + partition@e0000 { + label = "u-boot-env"; + reg = <0xe0000 0x100000>; + read-only; + }; + + partition@1e0000 { + label = "factory"; + reg = <0x1e0000 0x100000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x4da8>; + }; + + eeprom_factory_8000: eeprom@8000 { + reg = <0x8000 0x4da8>; + }; + + macaddr_factory_e000: macaddr@e000 { + reg = <0xe000 0x6>; + }; + }; + }; + + partition@2e0000 { + label = "factory2"; + reg = <0x2e0000 0x100000>; + read-only; + }; + + partition@3e0000 { + label = "kernel"; + reg = <0x3e0000 0x400000>; + }; + + partition@7e0000 { + label = "ubi"; + reg = <0x7e0000 0x2e00000>; + }; + + partition@35e0000 { + label = "firmware2"; + reg = <0x35e0000 0x3200000>; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&pcie0 { + wifi0: wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + ieee80211-freq-limit = <2400000 2500000>; + }; +}; + +&pcie1 { + wifi1: wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_factory_8000>; + nvmem-cell-names = "eeprom"; + ieee80211-freq-limit = <5000000 6000000>; + }; +}; + + +&gmac0 { + nvmem-cells = <&macaddr_factory_e000>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + status = "okay"; + label = "wan"; + phy-handle = <ðphy4>; + + nvmem-cells = <&macaddr_factory_e000>; + nvmem-cell-names = "mac-address"; +}; + +ðphy4 { + /delete-property/ interrupts; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "disabled"; + }; + }; +}; + +&state_default { + gpio { + groups = "uart2", "uart3", "i2c"; + function = "gpio"; + }; +}; + +&xhci { + status = "okay"; +}; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index a80bede347..96653683de 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -458,6 +458,16 @@ define Device/asus_rt-ac85p endef TARGET_DEVICES += asus_rt-ac85p +define Device/asus_rt-ac85u + $(Device/nand) + DEVICE_VENDOR := ASUS + DEVICE_MODEL := RT-AC85U + DEVICE_DTS := mt7621_asus_rt-ac85u + IMAGE_SIZE := 51200k + DEVICE_PACKAGES := kmod-usb3 kmod-mt7615-firmware uboot-envtools +endef +TARGET_DEVICES += asus_rt-ac85u + define Device/asus_rt-n56u-b1 $(Device/dsa-migration) $(Device/uimage-lzma-loader) diff --git a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh index 52617bc426..4e1aab2763 100644 --- a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh +++ b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh @@ -73,6 +73,7 @@ platform_do_upgrade() { arcadyan,we420223-99|\ asus,rt-ac65p|\ asus,rt-ac85p|\ + asus,rt-ac85u|\ asus,rt-ax53u|\ asus,rt-ax54|\ asus,4g-ax56|\ From f08cd5ce5d66d76fa6e282d6e3f29bab9cdf8023 Mon Sep 17 00:00:00 2001 From: Shine <4c.fce2@proton.me> Date: Fri, 12 Jun 2026 16:27:28 +0200 Subject: [PATCH 150/228] scripts: dhcpv6: harmonize IAID between IA_NA and IA_PD requests For DHCPv6 address requests (IA_NA), odhcp6c currently uses the first eight digits of the i/f name's MD5 hash as IAID. In case of DHCPv6-PD, however, odhcp6c expects the IAID to be specified explicitly for the IA_PD(s) requested, otherwise it will start counting the IAID from "1" up for each "-P" argument. As OpenWrt only requests a single IA_PD per interface, make sure to pass the identical IAID for IA_PD as is used for IA_NA, unless a custom IAID was explicitly specified in the i/f configuration. This prevents regressions with ISPs that expect an IA_PD request to come from the same IAID+DUID combination as the IA_NA request. In addition, add some validation of the "reqprefix" value, in order to catch most cases that would otherwise result in netifd or odhcp6c malfunction. Signed-off-by: Shine <4c.fce2@proton.me> Link: https://github.com/openwrt/openwrt/pull/23758 Signed-off-by: Robert Marko --- package/network/ipv6/odhcp6c/files/dhcpv6.sh | 23 ++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/package/network/ipv6/odhcp6c/files/dhcpv6.sh b/package/network/ipv6/odhcp6c/files/dhcpv6.sh index 6e257e11cb..71777bc4e1 100755 --- a/package/network/ipv6/odhcp6c/files/dhcpv6.sh +++ b/package/network/ipv6/odhcp6c/files/dhcpv6.sh @@ -1,6 +1,7 @@ #!/bin/sh . /lib/functions.sh +. /lib/functions/network.sh . ../netifd-proto.sh . /lib/config/uci.sh init_proto "$@" @@ -9,7 +10,7 @@ proto_dhcpv6_init_config() { renew_handler=1 proto_config_add_string 'reqaddress:or("try","force","none")' - proto_config_add_string 'reqprefix:or("auto","no",range(0, 64))' + proto_config_add_string reqprefix proto_config_add_string clientid proto_config_add_string 'reqopts:list(uinteger)' proto_config_add_string 'defaultreqopts:bool' @@ -85,7 +86,25 @@ proto_dhcpv6_setup() { [ -n "$reqaddress" ] && append opts "-N$reqaddress" [ -z "$reqprefix" -o "$reqprefix" = "auto" ] && reqprefix=0 - [ "$reqprefix" != "no" ] && append opts "-P$reqprefix" + [ "$reqprefix" != "no" ] && { + # append interface IAID if none specified + local iaid=$(echo -n $reqprefix | sed -nr 's/^.*:([0-9A-Fa-f]{1,8})$/\1/p') + [ -z "$iaid" ] && { + network_generate_iface_iaid iaid "$iface" + reqprefix="$reqprefix:$iaid" + } + # validate prefix/length hint + local hint=${reqprefix%:$iaid} + [ "${hint#/}" -le "128" ] 2>/dev/null && { + reqprefix=${reqprefix#/} + } || { + validate_data cidr6 "$hint" 2>/dev/null || { + reqprefix="0:$iaid" + logger -p warn -t dhcpv6 "$iface: ignoring invalid prefix hint" + } + } + append opts "-P$reqprefix" + } [ -n "$clientid" ] && { clientid="$(hexdump_2hex "$clientid")" From a1ab701efa9c3fabfd6dda233bc71a99c3fad371 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 24 Jun 2026 15:51:36 +0200 Subject: [PATCH 151/228] mediatek: openwrt-one: make the front button usable as WPS button It's the most common use for such a button, and the behavior can be changed in user space if needed Signed-off-by: Felix Fietkau --- target/linux/mediatek/dts/mt7981b-openwrt-one.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/mediatek/dts/mt7981b-openwrt-one.dts b/target/linux/mediatek/dts/mt7981b-openwrt-one.dts index d0b94af5cb..a3c532a141 100644 --- a/target/linux/mediatek/dts/mt7981b-openwrt-one.dts +++ b/target/linux/mediatek/dts/mt7981b-openwrt-one.dts @@ -50,7 +50,7 @@ user { label = "user"; - linux,code = ; + linux,code = ; gpios = <&pio 0 GPIO_ACTIVE_LOW>; }; From 7edb29d241dbd4acd0a716a3735dedd5ac3b36e2 Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sun, 7 Jun 2026 13:04:39 +0300 Subject: [PATCH 152/228] kernel: add support for FudanMicro FM25G01B and FM25G02B spi-nand This commit adds support for FudanMicro FM25G01B and FM25G02B SPI NAND chips. This is required to: 1. Fix bootloop on new revision of Keenetic KN-1812 and Netcraze NC-1812 (with FudanMicro FM25G02B SPI NAND) 2. Add Nokia XG-040G-MD support (device has either SkyHigh or FudanMicro SPI NAND). Fixes: https://github.com/openwrt/openwrt/issues/23855 Signed-off-by: Mikhail Zhilkin Link: https://github.com/openwrt/openwrt/pull/23864 Signed-off-by: Hauke Mehrtens --- ...nand-fmsh-add-support-for-FM25G0102B.patch | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 target/linux/generic/pending-6.18/401-mtd-spinand-fmsh-add-support-for-FM25G0102B.patch diff --git a/target/linux/generic/pending-6.18/401-mtd-spinand-fmsh-add-support-for-FM25G0102B.patch b/target/linux/generic/pending-6.18/401-mtd-spinand-fmsh-add-support-for-FM25G0102B.patch new file mode 100644 index 0000000000..e3a5a10e5b --- /dev/null +++ b/target/linux/generic/pending-6.18/401-mtd-spinand-fmsh-add-support-for-FM25G0102B.patch @@ -0,0 +1,152 @@ +From: Ziyang Huang +To: miquel.raynal@bootlin.com +Subject: [PATCH v3] mtd: spinand: fmsh: add support for FM25G{01,02}B +Date: Sun, 31 May 2026 21:05:17 +0800 + +Add support for FudanMicro FM25G01B SPI NAND and FudanMicro FM25G02B SPI +NAND. + +FM25G01B datasheet: https://www.fmsh.com/nvm/FM25G01B_ds_eng.pdf +FM25G02B datasheet: https://www.fmsh.com/nvm/FM25G02B_ds_eng.pdf + +Signed-off-by: Ziyang Huang +Link: https://lore.kernel.org/all/SEYPR01MB58821E380C5DD8F7B3FFDA23C9142@SEYPR01MB5882.apcprd01.prod.exchangelabs.com/ +[Fix chip names in the commit message, mask macro in the switch operator] +Signed-off-by: Mikhail Zhilkin +--- +Changes since v2: + More verbose commit message. + Use only one section in fm25g01b_ooblayout_free(). + +Changes since v1: + Fix copy-paste issue. (Correct FM25G01B size.) + + drivers/mtd/nand/spi/fmsh.c | 96 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 96 insertions(+) + +--- a/drivers/mtd/nand/spi/fmsh.c ++++ b/drivers/mtd/nand/spi/fmsh.c +@@ -9,6 +9,16 @@ + #include + #include + ++#define FM25G01B_STATUS_ECC_MASK (7 << 4) ++ #define FM25G01B_STATUS_ECC_NO_BITFLIPS (0 << 4) ++ #define FM25G01B_STATUS_ECC_1_3_BITFLIPS (1 << 4) ++ #define FM25G01B_STATUS_ECC_4_BITFLIPS (2 << 4) ++ #define FM25G01B_STATUS_ECC_5_BITFLIPS (3 << 4) ++ #define FM25G01B_STATUS_ECC_6_BITFLIPS (4 << 4) ++ #define FM25G01B_STATUS_ECC_7_BITFLIPS (5 << 4) ++ #define FM25G01B_STATUS_ECC_8_BITFLIPS (6 << 4) ++ #define FM25G01B_STATUS_ECC_UNCOR_ERROR (7 << 4) ++ + #define FM25S01BI3_STATUS_ECC_MASK (7 << 4) + #define FM25S01BI3_STATUS_ECC_NO_BITFLIPS (0 << 4) + #define FM25S01BI3_STATUS_ECC_1_3_BITFLIPS (1 << 4) +@@ -34,6 +44,67 @@ static SPINAND_OP_VARIANTS(update_cache_ + SPINAND_PROG_LOAD_1S_1S_4S_OP(false, 0, NULL, 0), + SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0)); + ++ ++static int fm25g01b_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ region->offset = 64; ++ region->length = 64; ++ ++ return 0; ++} ++ ++static int fm25g01b_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ /* reserve 2 bytes for the BBM */ ++ region->offset = 2; ++ region->length = 62; ++ ++ return 0; ++} ++ ++static int fm25g01b_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & FM25G01B_STATUS_ECC_MASK) { ++ case FM25G01B_STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case FM25G01B_STATUS_ECC_1_3_BITFLIPS: ++ return 3; ++ ++ case FM25G01B_STATUS_ECC_4_BITFLIPS: ++ return 4; ++ ++ case FM25G01B_STATUS_ECC_5_BITFLIPS: ++ return 5; ++ ++ case FM25G01B_STATUS_ECC_6_BITFLIPS: ++ return 6; ++ ++ case FM25G01B_STATUS_ECC_7_BITFLIPS: ++ return 7; ++ ++ case FM25G01B_STATUS_ECC_8_BITFLIPS: ++ return 8; ++ ++ case FM25G01B_STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ + static int fm25s01a_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) + { +@@ -102,6 +173,11 @@ static int fm25s01bi3_ooblayout_free(str + return 0; + } + ++static const struct mtd_ooblayout_ops fm25g01b_ooblayout = { ++ .ecc = fm25g01b_ooblayout_ecc, ++ .free = fm25g01b_ooblayout_free, ++}; ++ + static const struct mtd_ooblayout_ops fm25s01a_ooblayout = { + .ecc = fm25s01a_ooblayout_ecc, + .free = fm25s01a_ooblayout_free, +@@ -113,6 +189,26 @@ static const struct mtd_ooblayout_ops fm + }; + + static const struct spinand_info fmsh_spinand_table[] = { ++ SPINAND_INFO("FM25G01B", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xd1), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 21, 1, 1, 1), ++ NAND_ECCREQ(8, 528), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&fm25g01b_ooblayout, ++ fm25g01b_ecc_get_status)), ++ SPINAND_INFO("FM25G02B", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xd2), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 41, 1, 1, 1), ++ NAND_ECCREQ(8, 528), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&fm25g01b_ooblayout, ++ fm25g01b_ecc_get_status)), + SPINAND_INFO("FM25S01A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), From 219798083ce774d00f600c9d0293e73a9889c18b Mon Sep 17 00:00:00 2001 From: Jack Sun Date: Thu, 25 Jun 2026 19:31:35 +0800 Subject: [PATCH 153/228] tools/cmake: update to 4.3.4 Release notes:https://cmake.org/cmake/help/latest/release/4.3.html No need refresh patches. Signed-off-by: Jack Sun Link: https://github.com/openwrt/openwrt/pull/23938 Signed-off-by: Hauke Mehrtens --- tools/cmake/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/cmake/Makefile b/tools/cmake/Makefile index 09ee956891..45f7df13d2 100644 --- a/tools/cmake/Makefile +++ b/tools/cmake/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=cmake -PKG_VERSION:=4.3.3 +PKG_VERSION:=4.3.4 PKG_VERSION_MAJOR:=$(word 1,$(subst ., ,$(PKG_VERSION))).$(word 2,$(subst ., ,$(PKG_VERSION))) PKG_RELEASE:=1 PKG_CPE_ID:=cpe:/a:kitware:cmake @@ -15,7 +15,7 @@ PKG_CPE_ID:=cpe:/a:kitware:cmake PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/Kitware/CMake/releases/download/v$(PKG_VERSION)/ \ https://cmake.org/files/v$(PKG_VERSION_MAJOR)/ -PKG_HASH:=cba4bb7a44edf2877bb6f059932896383babe435b3a8c3b5df48b4aa41c9bb85 +PKG_HASH:=fdeff897b9eb49d764539f2b1edc6eb7e1440df325678a97c1978499e931adda HOST_BUILD_PARALLEL:=1 HOST_CONFIGURE_PARALLEL:=1 From 219daaa24038e0e56e49177df586d4a296bce6a6 Mon Sep 17 00:00:00 2001 From: xiao bo Date: Thu, 25 Jun 2026 19:20:49 +0800 Subject: [PATCH 154/228] rockchip: backport upstream fix R76S SD suspend power loss This patch is a full backport of Linux upstream commit a9c1acebfe0484343a443d082e039ca77186ed22 for rk3576-nanopi-r76s.dts device tree, resolving SD card power dropout in runtime suspend. When runtime suspend is active, the SD power domain is shut down, wiping power control registers and cutting card power. I/O recovery relies on mmc_blk_mq_rw_recovery(), which results in poor performance and unstable card detection. Implement GPIO-controlled vcc3v3_sd regulator and attach vmmc-supply to sdmmc node to maintain SD power during suspend. Also add cd-gpios to guarantee working hotplug when system enters idle/suspend state. Modifications in DTS: - vcc3v3_sd fixed regulator + sdmmc_pwren pinctrl - vmmc-supply & vqmmc-supply for sdmmc bus power retention - cd-gpios for SD card presence detection Signed-off-by: xiao bo Link: https://github.com/openwrt/openwrt/pull/23924 Signed-off-by: Hauke Mehrtens --- ...ip-Fix-SD-card-support-for-RK3576-Na.patch | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 target/linux/rockchip/patches-6.18/053-v6.19-arm64-dts-rockchip-Fix-SD-card-support-for-RK3576-Na.patch diff --git a/target/linux/rockchip/patches-6.18/053-v6.19-arm64-dts-rockchip-Fix-SD-card-support-for-RK3576-Na.patch b/target/linux/rockchip/patches-6.18/053-v6.19-arm64-dts-rockchip-Fix-SD-card-support-for-RK3576-Na.patch new file mode 100644 index 0000000000..0d4a4a56d3 --- /dev/null +++ b/target/linux/rockchip/patches-6.18/053-v6.19-arm64-dts-rockchip-Fix-SD-card-support-for-RK3576-Na.patch @@ -0,0 +1,77 @@ +From 3256c25e6c833e11e2a574b69f4ba30e86049846 Mon Sep 17 00:00:00 2001 +From: Shawn Lin +Date: Fri, 16 Jan 2026 08:55:32 +0800 +Subject: [PATCH] arm64: dts: rockchip: Fix SD card support for RK3576 Nanopi + R76s + +[ Upstream commit a9c1acebfe0484343a443d082e039ca77186ed22 ] + +When runtime suspend is enabled, the associated power domain is powered +off, which resets the registers, including the power control bit. As a result, +the card loses power during runtime suspend. The card should still be able +to process I/O with the help of mmc_blk_mq_rw_recovery(), which is suboptimal. +To address this issue, we must use vmmc-supply with a GPIO based method to +maintain power to the card and store valid tuning phases. Also, add cd-gpios +method to make hot-plug work correctly during idle periods. + +Fixes: 7fee88882704 ("arm64: dts: rockchip: Add devicetree for the FriendlyElec NanoPi R76S") +Cc: stable@vger.kernel.org +Signed-off-by: Shawn Lin +Tested-by: Marco Schirrmeister +Link: https://patch.msgid.link/1768524932-163929-6-git-send-email-shawn.lin@rock-chips.com +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + .../boot/dts/rockchip/rk3576-nanopi-r76s.dts | 23 ++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3576-nanopi-r76s.dts +@@ -192,6 +192,18 @@ + regulator-name = "vcc_3v3_s0"; + vin-supply = <&vcc_3v3_s3>; + }; ++ ++ vcc3v3_sd: regulator-vcc-3v3-sd { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_pwren>; ++ regulator-name = "vcc3v3_sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_3v3_s0>; ++ }; + }; + + &combphy0_ps { +@@ -726,6 +738,12 @@ + }; + }; + ++ sdmmc { ++ sdmmc_pwren: sdmmc-pwren { ++ rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ + usb { + usb_otg0_pwren_h: usb-otg0-pwren-h { + rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; +@@ -751,11 +769,14 @@ + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; ++ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; + disable-wp; + no-mmc; + no-sdio; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>; + sd-uhs-sdr104; +- vmmc-supply = <&vcc_3v3_s3>; ++ vmmc-supply = <&vcc3v3_sd>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; + }; From e79df8aa0386a4b93f597a088ddb92273212dff6 Mon Sep 17 00:00:00 2001 From: Fil Dunsky Date: Wed, 3 Jun 2026 21:18:20 +0300 Subject: [PATCH 155/228] mediatek: add WD-R3000N-G2A as ALT device for Bazis AX3000WM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Bazis AX3000WM is an OEM variant of the Shenzhen Jia Yan Technology WD-R3000N-G2A (per EAEU certificate N RU Д-CN.РА04.В.23104/26). Hardware is identical. Added for the owners of this device so they can find it in firmware-selector. Signed-off-by: Fil Dunsky Link: https://github.com/openwrt/openwrt/pull/23653 Signed-off-by: Hauke Mehrtens --- target/linux/mediatek/image/filogic.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index eb660ddc14..7d2eefbf7a 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -813,6 +813,8 @@ TARGET_DEVICES += bananapi_bpi-r4-lite define Device/bazis_ax3000wm DEVICE_VENDOR := Bazis DEVICE_MODEL := AX3000WM + DEVICE_ALT0_VENDOR := Shenzhen Jia Yan Technology + DEVICE_ALT0_MODEL := WD-R3000N-G2A DEVICE_DTS := mt7981b-bazis-ax3000wm DEVICE_DTS_DIR := ../dts UBINIZE_OPTS := -E 5 From 85e15f34ace3077d960682564119597dd82afea1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 24 Jun 2026 17:20:54 +0200 Subject: [PATCH 156/228] airoha: backport additional fixes for ethernet driver Backport fixes for airoha_eth driver from net tree recently merged upstream. Refresh all affected patch. Signed-off-by: Lorenzo Bianconi [ refresh patch, improve commit title/description ] Link: https://github.com/openwrt/openwrt/pull/23934 Signed-off-by: Christian Marangi --- ...egister-index-for-Tx-fwd-counter-con.patch | 37 ++++++++ ...ebugfs-new-tuple-display-for-IPv4-RO.patch | 44 ++++++++++ ...a-fix-foe_check_time-allocation-size.patch | 34 ++++++++ ...on-standard-return-value-in-airoha_p.patch | 31 +++++++ ...kb-priority-underflow-in-airoha_dev_.patch | 52 ++++++++++++ ...X-scheduler-queue-mask-loop-upper-bo.patch | 50 +++++++++++ ...ha-Fix-typos-in-comments-and-Kconfig.patch | 68 +++++++++++++++ ...ff-by-one-in-airoha_tc_remove_htb_qu.patch | 34 ++++++++ ...etif_set_real_num_tx_queues-for-spar.patch | 84 +++++++++++++++++++ ...7-airoha-ethernet-drop-xsi-mac-reset.patch | 4 +- ...10-10-net-airoha-add-phylink-support.patch | 12 +-- ...-airoha-Implement-HW-GRO-TCP-support.patch | 4 +- ...-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch | 21 +++-- ...-net-airoha-Rework-MTU-configuration.patch | 4 +- 14 files changed, 456 insertions(+), 23 deletions(-) create mode 100644 target/linux/airoha/patches-6.18/170-v7.2-net-airoha-Fix-register-index-for-Tx-fwd-counter-con.patch create mode 100644 target/linux/airoha/patches-6.18/171-v7.2-net-airoha-Fix-debugfs-new-tuple-display-for-IPv4-RO.patch create mode 100644 target/linux/airoha/patches-6.18/172-v7.2-net-airoha-fix-foe_check_time-allocation-size.patch create mode 100644 target/linux/airoha/patches-6.18/173-v7.2-net-airoha-Fix-non-standard-return-value-in-airoha_p.patch create mode 100644 target/linux/airoha/patches-6.18/174-v7.2-net-airoha-Fix-skb-priority-underflow-in-airoha_dev_.patch create mode 100644 target/linux/airoha/patches-6.18/175-v7.2-net-airoha-Fix-TX-scheduler-queue-mask-loop-upper-bo.patch create mode 100644 target/linux/airoha/patches-6.18/176-v7.2-net-airoha-Fix-typos-in-comments-and-Kconfig.patch create mode 100644 target/linux/airoha/patches-6.18/177-v7.2-net-airoha-Fix-off-by-one-in-airoha_tc_remove_htb_qu.patch create mode 100644 target/linux/airoha/patches-6.18/178-v7.2-net-airoha-fix-netif_set_real_num_tx_queues-for-spar.patch diff --git a/target/linux/airoha/patches-6.18/170-v7.2-net-airoha-Fix-register-index-for-Tx-fwd-counter-con.patch b/target/linux/airoha/patches-6.18/170-v7.2-net-airoha-Fix-register-index-for-Tx-fwd-counter-con.patch new file mode 100644 index 0000000000..3059178661 --- /dev/null +++ b/target/linux/airoha/patches-6.18/170-v7.2-net-airoha-Fix-register-index-for-Tx-fwd-counter-con.patch @@ -0,0 +1,37 @@ +From 1402ecccf5630a0b7fa4749d7d2e72abc3f3d73d Mon Sep 17 00:00:00 2001 +Message-ID: <1402ecccf5630a0b7fa4749d7d2e72abc3f3d73d.1782312403.git.lorenzo@kernel.org> +From: "Wayen.Yan" +Date: Fri, 12 Jun 2026 07:09:13 +0800 +Subject: [PATCH 1/2] net: airoha: Fix register index for Tx-fwd counter + configuration + +In airoha_qdma_init_qos_stats(), the Tx-fwd counter configuration +register uses the same index (i << 1) as the Tx-cpu counter, which +overwrites the Tx-cpu configuration. The Tx-fwd counter value register +correctly uses (i << 1) + 1, so the configuration register should use +the same index. + +Fix the REG_CNTR_CFG index from (i << 1) to ((i << 1) + 1) so that +the Tx-fwd counter is properly configured instead of clobbering the +Tx-cpu counter config. + +Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support") +Signed-off-by: Wayen.Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/6a2b40e7.4dd82583.3a5c46.e566@mx.google.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1331,7 +1331,7 @@ static void airoha_qdma_init_qos_stats(s + FIELD_PREP(CNTR_CHAN_MASK, i)); + /* Tx-fwd transferred count */ + airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0); +- airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1), ++ airoha_qdma_wr(qdma, REG_CNTR_CFG((i << 1) + 1), + CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK | + CNTR_ALL_DSCP_RING_EN_MASK | + FIELD_PREP(CNTR_SRC_MASK, 1) | diff --git a/target/linux/airoha/patches-6.18/171-v7.2-net-airoha-Fix-debugfs-new-tuple-display-for-IPv4-RO.patch b/target/linux/airoha/patches-6.18/171-v7.2-net-airoha-Fix-debugfs-new-tuple-display-for-IPv4-RO.patch new file mode 100644 index 0000000000..3a487a44c4 --- /dev/null +++ b/target/linux/airoha/patches-6.18/171-v7.2-net-airoha-Fix-debugfs-new-tuple-display-for-IPv4-RO.patch @@ -0,0 +1,44 @@ +From 1c3a77471afbb3981af28f7f7c8b2487558e4b00 Mon Sep 17 00:00:00 2001 +Message-ID: <1c3a77471afbb3981af28f7f7c8b2487558e4b00.1782312403.git.lorenzo@kernel.org> +In-Reply-To: <1402ecccf5630a0b7fa4749d7d2e72abc3f3d73d.1782312403.git.lorenzo@kernel.org> +References: <1402ecccf5630a0b7fa4749d7d2e72abc3f3d73d.1782312403.git.lorenzo@kernel.org> +From: "Wayen.Yan" +Date: Fri, 12 Jun 2026 07:09:56 +0800 +Subject: [PATCH 2/2] net: airoha: Fix debugfs new-tuple display for IPv4 ROUTE + entries +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In airoha_ppe_debugfs_foe_show(), the second switch statement falls +through from PPE_PKT_TYPE_IPV4_HNAPT/DSLITE to PPE_PKT_TYPE_IPV4_ROUTE, +accessing hwe->ipv4.new_tuple for all three types. However, IPv4 ROUTE +(3-tuple) entries do not contain a valid new_tuple — this field is only +meaningful for NATted flows (HNAPT/DSLITE). For ROUTE entries, the +memory at the new_tuple offset holds routing information, not NAT data, +so displaying "new=" produces garbage output. + +Display new_tuple only for HNAPT and DSLITE, and let IPV4_ROUTE fall +through to the default case. + +Fixes: 3fe15c640f38 ("net: airoha: Introduce PPE debugfs support") +Link: https://lore.kernel.org/6a2b40ea.4dd82583.3a5c46.e5a2@mx.google.com +Signed-off-by: Wayen.Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/6a2be54b.ef98c1b2.3c3224.2ed8@mx.google.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe_debugfs.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c +@@ -121,8 +121,6 @@ static int airoha_ppe_debugfs_foe_show(s + case PPE_PKT_TYPE_IPV4_DSLITE: + src_port = &hwe->ipv4.new_tuple.src_port; + dest_port = &hwe->ipv4.new_tuple.dest_port; +- fallthrough; +- case PPE_PKT_TYPE_IPV4_ROUTE: + src_addr = &hwe->ipv4.new_tuple.src_ip; + dest_addr = &hwe->ipv4.new_tuple.dest_ip; + seq_puts(m, " new="); diff --git a/target/linux/airoha/patches-6.18/172-v7.2-net-airoha-fix-foe_check_time-allocation-size.patch b/target/linux/airoha/patches-6.18/172-v7.2-net-airoha-fix-foe_check_time-allocation-size.patch new file mode 100644 index 0000000000..9851f30434 --- /dev/null +++ b/target/linux/airoha/patches-6.18/172-v7.2-net-airoha-fix-foe_check_time-allocation-size.patch @@ -0,0 +1,34 @@ +From 5c121ee635680c93d7074becf14cfbaac140f80d Mon Sep 17 00:00:00 2001 +Message-ID: <5c121ee635680c93d7074becf14cfbaac140f80d.1782312136.git.lorenzo@kernel.org> +From: Wayen Yan +Date: Tue, 16 Jun 2026 19:52:36 +0800 +Subject: [PATCH] net: airoha: fix foe_check_time allocation size + +foe_check_time is declared as u16 pointer but was allocated with +only ppe_num_entries bytes instead of ppe_num_entries * sizeof(u16). + +When airoha_ppe_foe_verify_entry() is called with hash >= ppe_num_entries/2, +it writes beyond the allocated buffer, causing heap buffer overflow and +potential kernel crash. + +Fixes: 6d5b601d52a2 ("net: airoha: ppe: Dynamically allocate foe_check_time array in airoha_ppe struct") +Signed-off-by: Wayen Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/178161119471.2163752.14373384830691569758@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1601,7 +1601,8 @@ int airoha_ppe_init(struct airoha_eth *e + return -ENOMEM; + } + +- ppe->foe_check_time = devm_kzalloc(eth->dev, ppe_num_entries, ++ ppe->foe_check_time = devm_kzalloc(eth->dev, ++ ppe_num_entries * sizeof(*ppe->foe_check_time), + GFP_KERNEL); + if (!ppe->foe_check_time) + return -ENOMEM; diff --git a/target/linux/airoha/patches-6.18/173-v7.2-net-airoha-Fix-non-standard-return-value-in-airoha_p.patch b/target/linux/airoha/patches-6.18/173-v7.2-net-airoha-Fix-non-standard-return-value-in-airoha_p.patch new file mode 100644 index 0000000000..e48937d2b4 --- /dev/null +++ b/target/linux/airoha/patches-6.18/173-v7.2-net-airoha-Fix-non-standard-return-value-in-airoha_p.patch @@ -0,0 +1,31 @@ +From 05173fa30add3787e7ab2e735c4ee00431994259 Mon Sep 17 00:00:00 2001 +Message-ID: <05173fa30add3787e7ab2e735c4ee00431994259.1782312341.git.lorenzo@kernel.org> +From: "Wayen.Yan" +Date: Sat, 13 Jun 2026 08:22:31 +0800 +Subject: [PATCH] net: airoha: Fix non-standard return value in + airoha_ppe_get_wdma_info() + +airoha_ppe_get_wdma_info() returns -1 when the last path in the +forwarding path stack is not of type DEV_PATH_MTK_WDMA. This is not +a standard kernel error code. Replace it with -EINVAL since the +input path type is invalid from the caller's perspective. + +Signed-off-by: Wayen.Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/6a2ca3d9.ad59c0a6.147df9.2a62@mx.google.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -277,7 +277,7 @@ static int airoha_ppe_get_wdma_info(stru + + path = &stack.path[stack.num_paths - 1]; + if (path->type != DEV_PATH_MTK_WDMA) +- return -1; ++ return -EINVAL; + + info->idx = path->mtk_wdma.wdma_idx; + info->bss = path->mtk_wdma.bss; diff --git a/target/linux/airoha/patches-6.18/174-v7.2-net-airoha-Fix-skb-priority-underflow-in-airoha_dev_.patch b/target/linux/airoha/patches-6.18/174-v7.2-net-airoha-Fix-skb-priority-underflow-in-airoha_dev_.patch new file mode 100644 index 0000000000..4ec30e3850 --- /dev/null +++ b/target/linux/airoha/patches-6.18/174-v7.2-net-airoha-Fix-skb-priority-underflow-in-airoha_dev_.patch @@ -0,0 +1,52 @@ +From 86e51aa24686cc95bb35613059e8b94b9b81e3f0 Mon Sep 17 00:00:00 2001 +Message-ID: <86e51aa24686cc95bb35613059e8b94b9b81e3f0.1782312099.git.lorenzo@kernel.org> +From: Wayen Yan +Date: Sat, 20 Jun 2026 16:17:44 +0800 +Subject: [PATCH] net: airoha: Fix skb->priority underflow in + airoha_dev_select_queue() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In airoha_dev_select_queue(), the expression: + + queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; + +implicitly converts to unsigned arithmetic: when skb->priority is 0 +(the default for unclassified traffic), (0u - 1u) wraps to UINT_MAX, +and UINT_MAX % 8 = 7, routing default best-effort packets to the +highest-priority QoS queue. This causes QoS inversion where the +majority of traffic on a PON gateway starves actual high-priority +flows (VoIP, gaming, etc.). + +The "- 1" offset was a leftover from the ETS offload implementation +that has since been removed. The correct mapping is a direct modulo: + + queue = skb->priority % AIROHA_NUM_QOS_QUEUES; + +This maps priority 0 → queue 0 (lowest), priority 7 → queue 7 +(highest), with higher priorities wrapping around. This is the +standard Linux sk_prio → HW queue mapping used by other drivers. + +Fixes: 2b288b81560b ("net: airoha: Introduce ndo_select_queue callback") +Link: https://lore.kernel.org/netdev/178185573207.2378135.3729126358670287878@gmail.com/ +Acked-by: Lorenzo Bianconi +Reviewed-by: Joe Damato +Signed-off-by: Wayen Yan +Link: https://patch.msgid.link/178194366700.2485734.5368768965976693502@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2110,7 +2110,7 @@ static u16 airoha_dev_select_queue(struc + */ + channel = netdev_uses_dsa(netdev) ? skb_get_queue_mapping(skb) : port->id; + channel = channel % AIROHA_NUM_QOS_CHANNELS; +- queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */ ++ queue = skb->priority % AIROHA_NUM_QOS_QUEUES; + queue = channel * AIROHA_NUM_QOS_QUEUES + queue; + + return queue < netdev->num_tx_queues ? queue : 0; diff --git a/target/linux/airoha/patches-6.18/175-v7.2-net-airoha-Fix-TX-scheduler-queue-mask-loop-upper-bo.patch b/target/linux/airoha/patches-6.18/175-v7.2-net-airoha-Fix-TX-scheduler-queue-mask-loop-upper-bo.patch new file mode 100644 index 0000000000..fcf47bcfe3 --- /dev/null +++ b/target/linux/airoha/patches-6.18/175-v7.2-net-airoha-Fix-TX-scheduler-queue-mask-loop-upper-bo.patch @@ -0,0 +1,50 @@ +From 245043dfc2101e7dc6268bf123b75305a91e4e00 Mon Sep 17 00:00:00 2001 +Message-ID: <245043dfc2101e7dc6268bf123b75305a91e4e00.1782312080.git.lorenzo@kernel.org> +From: Wayen Yan +Date: Fri, 19 Jun 2026 21:12:06 +0800 +Subject: [PATCH] net: airoha: Fix TX scheduler queue mask loop upper bound +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In airoha_qdma_set_chan_tx_sched(), the loop clearing queue mask was +using AIROHA_NUM_TX_RING (32) instead of AIROHA_NUM_QOS_QUEUES (8). + +Each channel has 8 queues, and TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i) +computes BIT(i + (channel * 8)). With i ranging 0..31, this causes: +- channel 0: clears bit 0..31 (all 4 channels) instead of 0..7 +- channel 1: clears bit 8..31 (channels 1-3) instead of 8..15 +- channel 2: clears bit 16..31 (channels 2-3) instead of 16..23 +- channel 3: clears bit 24..31 (channel 3 only) - correct by accident + +While BIT(32+) on arm64 produces 64-bit values truncated to 0 in u32 +mask parameter, the loop still incorrectly clears queues within the +same channel beyond queue 7. + +Even though this is functionally harmless (the register resets to 0 +and is only ever cleared, never set — so clearing extra bits is a +no-op), the loop bound is semantically wrong and should be fixed for +correctness and clarity. + +Fix by using AIROHA_NUM_QOS_QUEUES (8) as the loop upper bound. + +Fixes: ef1ca9271313 ("net: airoha: Add sched HTB offload support") +Acked-by: Lorenzo Bianconi +Signed-off-by: Wayen Yan +Link: https://patch.msgid.link/178187479434.2400840.1312143943526335838@gmail.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2395,7 +2395,7 @@ static int airoha_qdma_set_chan_tx_sched + struct airoha_gdm_dev *dev = netdev_priv(netdev); + int i; + +- for (i = 0; i < AIROHA_NUM_TX_RING; i++) ++ for (i = 0; i < AIROHA_NUM_QOS_QUEUES; i++) + airoha_qdma_clear(dev->qdma, REG_QUEUE_CLOSE_CFG(channel), + TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i)); + diff --git a/target/linux/airoha/patches-6.18/176-v7.2-net-airoha-Fix-typos-in-comments-and-Kconfig.patch b/target/linux/airoha/patches-6.18/176-v7.2-net-airoha-Fix-typos-in-comments-and-Kconfig.patch new file mode 100644 index 0000000000..3b10867ea2 --- /dev/null +++ b/target/linux/airoha/patches-6.18/176-v7.2-net-airoha-Fix-typos-in-comments-and-Kconfig.patch @@ -0,0 +1,68 @@ +From a061dfb063fa03ed09cf21145ffff247cf94721a Mon Sep 17 00:00:00 2001 +Message-ID: +In-Reply-To: <05173fa30add3787e7ab2e735c4ee00431994259.1782312317.git.lorenzo@kernel.org> +References: <05173fa30add3787e7ab2e735c4ee00431994259.1782312317.git.lorenzo@kernel.org> +From: "Wayen.Yan" +Date: Sat, 13 Jun 2026 08:41:16 +0800 +Subject: [PATCH 2/2] net: airoha: Fix typos in comments and Kconfig + +Fix several typos found during code review: +- Kconfig: "Aiorha" -> "Airoha" in NET_AIROHA_FLOW_STATS help text +- Comment: "CMD1" -> "CDM1" (Central DMA, not Command) +- Comments: "GMD1/2/3/4" -> "GDM1/2/3/4" (Gigabit DMA, not GMD) + +These are pure comment and documentation fixes with no functional impact. + +Signed-off-by: Wayen.Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/6a2ca74a.c5b1db4e.21a698.01e7@mx.google.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/Kconfig | 2 +- + drivers/net/ethernet/airoha/airoha_eth.c | 10 +++++----- + 2 files changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/airoha/Kconfig ++++ b/drivers/net/ethernet/airoha/Kconfig +@@ -29,6 +29,6 @@ config NET_AIROHA_FLOW_STATS + bool "Airoha flow stats" + depends on NET_AIROHA && NET_AIROHA_NPU + help +- Enable Aiorha flowtable statistic counters. ++ Enable Airoha flowtable statistic counters. + + endif #NET_VENDOR_AIROHA +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -344,18 +344,18 @@ static void airoha_fe_pse_ports_init(str + FIELD_PREP(PSE_ALLRSV_MASK, all_rsv)); + } + +- /* CMD1 */ ++ /* CDM1 */ + for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM1]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM1, q, + PSE_QUEUE_RSV_PAGES); +- /* GMD1 */ ++ /* GDM1 */ + for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM1]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM1, q, + PSE_QUEUE_RSV_PAGES); +- /* GMD2 */ ++ /* GDM2 */ + for (q = 6; q < pse_port_num_queues[FE_PSE_PORT_GDM2]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM2, q, 0); +- /* GMD3 */ ++ /* GDM3 */ + for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM3]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM3, q, + PSE_QUEUE_RSV_PAGES); +@@ -390,7 +390,7 @@ static void airoha_fe_pse_ports_init(str + q, 0); + } + } +- /* GMD4 */ ++ /* GDM4 */ + for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM4]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM4, q, + PSE_QUEUE_RSV_PAGES); diff --git a/target/linux/airoha/patches-6.18/177-v7.2-net-airoha-Fix-off-by-one-in-airoha_tc_remove_htb_qu.patch b/target/linux/airoha/patches-6.18/177-v7.2-net-airoha-Fix-off-by-one-in-airoha_tc_remove_htb_qu.patch new file mode 100644 index 0000000000..821fd6a930 --- /dev/null +++ b/target/linux/airoha/patches-6.18/177-v7.2-net-airoha-Fix-off-by-one-in-airoha_tc_remove_htb_qu.patch @@ -0,0 +1,34 @@ +From bfcce49c4aaab9339ef7b9a7fa4d8ac5a19cc820 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Lorenzo Bianconi +Date: Fri, 19 Jun 2026 13:37:13 +0200 +Subject: [PATCH 1/2] net: airoha: Fix off-by-one in + airoha_tc_remove_htb_queue() + +airoha_tc_htb_alloc_leaf_queue() computes the HTB QoS channel index +as opt->classid % AIROHA_NUM_QOS_CHANNELS and stores it in qos_sq_bmap. +However, airoha_tc_remove_htb_queue() clears the HTB configuration +using queue + 1 as the channel index, causing an off-by-one error. +Use queue directly as the QoS channel index to match the allocation +logic. + +Fixes: ef1ca9271313b ("net: airoha: Add sched HTB offload support") +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260619-airoha-qos-fixes-v2-1-5c43485038f9@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -3006,7 +3006,7 @@ static void airoha_tc_remove_htb_queue(s + struct airoha_qdma *qdma = dev->qdma; + + netif_set_real_num_tx_queues(netdev, netdev->real_num_tx_queues - 1); +- airoha_qdma_set_tx_rate_limit(netdev, queue + 1, 0, 0); ++ airoha_qdma_set_tx_rate_limit(netdev, queue, 0, 0); + + clear_bit(queue, qdma->qos_channel_map); + clear_bit(queue, dev->qos_sq_bmap); diff --git a/target/linux/airoha/patches-6.18/178-v7.2-net-airoha-fix-netif_set_real_num_tx_queues-for-spar.patch b/target/linux/airoha/patches-6.18/178-v7.2-net-airoha-fix-netif_set_real_num_tx_queues-for-spar.patch new file mode 100644 index 0000000000..532a5851a3 --- /dev/null +++ b/target/linux/airoha/patches-6.18/178-v7.2-net-airoha-fix-netif_set_real_num_tx_queues-for-spar.patch @@ -0,0 +1,84 @@ +From 788663dd28e424639318842ba5ae290672528609 Mon Sep 17 00:00:00 2001 +Message-ID: <788663dd28e424639318842ba5ae290672528609.1782366471.git.lorenzo@kernel.org> +In-Reply-To: +References: +From: Lorenzo Bianconi +Date: Fri, 19 Jun 2026 13:37:14 +0200 +Subject: [PATCH 2/2] net: airoha: fix netif_set_real_num_tx_queues for sparse + QoS channels + +airoha_tc_htb_alloc_leaf_queue() assigns queue IDs based on the channel +index (opt->qid = AIROHA_NUM_TX_RING + channel), but updates +real_num_tx_queues with a simple increment (num_tx_queues + 1). When QoS +channels are allocated sparsely (e.g., channels 0 and 3 without 1 and +2), the returned qid can exceed real_num_tx_queues, causing out-of-bounds +accesses in the networking stack. +For example, allocating channel 0 then channel 3 results in +real_num_tx_queues = 34 but qid = 35, which is out of range [0, 34). +Fix this by computing real_num_tx_queues based on the highest active +channel index rather than using a simple counter, in both the allocation +and deletion paths. + +Fixes: ef1ca9271313b ("net: airoha: Add sched HTB offload support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260619-airoha-qos-fixes-v2-2-5c43485038f9@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 25 +++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2789,7 +2789,7 @@ static int airoha_tc_htb_alloc_leaf_queu + struct tc_htb_qopt_offload *opt) + { + u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; +- int err, num_tx_queues = netdev->real_num_tx_queues; ++ int err, num_tx_queues = AIROHA_NUM_TX_RING + channel + 1; + struct airoha_gdm_dev *dev = netdev_priv(netdev); + struct airoha_qdma *qdma = dev->qdma; + +@@ -2806,13 +2806,15 @@ static int airoha_tc_htb_alloc_leaf_queu + if (err) + goto error; + +- err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1); +- if (err) { +- airoha_qdma_set_tx_rate_limit(netdev, channel, 0, +- opt->quantum); +- NL_SET_ERR_MSG_MOD(opt->extack, +- "failed setting real_num_tx_queues"); +- goto error; ++ if (num_tx_queues > netdev->real_num_tx_queues) { ++ err = netif_set_real_num_tx_queues(netdev, num_tx_queues); ++ if (err) { ++ airoha_qdma_set_tx_rate_limit(netdev, channel, 0, ++ opt->quantum); ++ NL_SET_ERR_MSG_MOD(opt->extack, ++ "failed setting real_num_tx_queues"); ++ goto error; ++ } + } + + set_bit(channel, dev->qos_sq_bmap); +@@ -3003,13 +3005,18 @@ static int airoha_dev_setup_tc_block(str + static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) + { + struct airoha_gdm_dev *dev = netdev_priv(netdev); ++ int num_tx_queues = AIROHA_NUM_TX_RING; + struct airoha_qdma *qdma = dev->qdma; + +- netif_set_real_num_tx_queues(netdev, netdev->real_num_tx_queues - 1); + airoha_qdma_set_tx_rate_limit(netdev, queue, 0, 0); + + clear_bit(queue, qdma->qos_channel_map); + clear_bit(queue, dev->qos_sq_bmap); ++ ++ if (!bitmap_empty(dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)) ++ num_tx_queues += find_last_bit(dev->qos_sq_bmap, ++ AIROHA_NUM_QOS_CHANNELS) + 1; ++ netif_set_real_num_tx_queues(netdev, num_tx_queues); + } + + static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev, diff --git a/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch b/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch index d6560370d2..2af0f1f9ab 100644 --- a/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch +++ b/target/linux/airoha/patches-6.18/310-07-airoha-ethernet-drop-xsi-mac-reset.patch @@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c -@@ -3511,7 +3511,6 @@ static void airoha_remove(struct platfor +@@ -3518,7 +3518,6 @@ static void airoha_remove(struct platfor } static const char * const en7581_xsi_rsts_names[] = { @@ -23,7 +23,7 @@ Signed-off-by: Christian Marangi "hsi0-mac", "hsi1-mac", "hsi-mac", -@@ -3598,7 +3597,6 @@ static int airoha_en7581_get_dev_from_sp +@@ -3605,7 +3604,6 @@ static int airoha_en7581_get_dev_from_sp } static const char * const an7583_xsi_rsts_names[] = { diff --git a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch index de636badfb..6d6c08b9b2 100644 --- a/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch +++ b/target/linux/airoha/patches-6.18/310-10-net-airoha-add-phylink-support.patch @@ -110,7 +110,7 @@ Signed-off-by: Christian Marangi static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev, int channel, enum tx_sched_mode mode, const u16 *weights, u8 n_weights) -@@ -3119,7 +3149,8 @@ static const struct ethtool_ops airoha_e +@@ -3126,7 +3156,8 @@ static const struct ethtool_ops airoha_e .get_drvinfo = airoha_ethtool_get_drvinfo, .get_eth_mac_stats = airoha_ethtool_get_mac_stats, .get_rmon_stats = airoha_ethtool_get_rmon_stats, @@ -120,7 +120,7 @@ Signed-off-by: Christian Marangi .get_link = ethtool_op_get_link, }; -@@ -3175,6 +3206,159 @@ bool airoha_is_valid_gdm_dev(struct airo +@@ -3182,6 +3213,159 @@ bool airoha_is_valid_gdm_dev(struct airo return false; } @@ -280,7 +280,7 @@ Signed-off-by: Christian Marangi static int airoha_alloc_gdm_device(struct airoha_eth *eth, struct airoha_gdm_port *port, int nbq, struct device_node *np) -@@ -3238,7 +3422,7 @@ static int airoha_alloc_gdm_device(struc +@@ -3245,7 +3429,7 @@ static int airoha_alloc_gdm_device(struc dev->nbq = nbq; port->devs[index] = dev; @@ -289,7 +289,7 @@ Signed-off-by: Christian Marangi } static int airoha_alloc_gdm_port(struct airoha_eth *eth, -@@ -3273,7 +3457,7 @@ static int airoha_alloc_gdm_port(struct +@@ -3280,7 +3464,7 @@ static int airoha_alloc_gdm_port(struct return -ENOMEM; port->id = id; @@ -298,7 +298,7 @@ Signed-off-by: Christian Marangi eth->ports[p] = port; err = airoha_metadata_dst_alloc(port); -@@ -3464,6 +3648,8 @@ error_napi_stop: +@@ -3471,6 +3655,8 @@ error_napi_stop: netdev = netdev_from_priv(dev); if (netdev->reg_state == NETREG_REGISTERED) unregister_netdev(netdev); @@ -307,7 +307,7 @@ Signed-off-by: Christian Marangi of_node_put(netdev->dev.of_node); } airoha_metadata_dst_free(port); -@@ -3500,6 +3686,7 @@ static void airoha_remove(struct platfor +@@ -3507,6 +3693,7 @@ static void airoha_remove(struct platfor netdev = netdev_from_priv(dev); unregister_netdev(netdev); diff --git a/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch b/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch index 16513e3c25..a07062d7fd 100644 --- a/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch +++ b/target/linux/airoha/patches-6.18/916-02-net-airoha-Implement-HW-GRO-TCP-support.patch @@ -535,7 +535,7 @@ Signed-off-by: Lorenzo Bianconi static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, struct net_device *netdev) { -@@ -3139,6 +3449,8 @@ static const struct net_device_ops airoh +@@ -3146,6 +3456,8 @@ static const struct net_device_ops airoh .ndo_stop = airoha_dev_stop, .ndo_change_mtu = airoha_dev_change_mtu, .ndo_select_queue = airoha_dev_select_queue, @@ -544,7 +544,7 @@ Signed-off-by: Lorenzo Bianconi .ndo_start_xmit = airoha_dev_xmit, .ndo_get_stats64 = airoha_dev_get_stats64, .ndo_set_mac_address = airoha_dev_set_macaddr, -@@ -3380,11 +3692,9 @@ static int airoha_alloc_gdm_device(struc +@@ -3387,11 +3699,9 @@ static int airoha_alloc_gdm_device(struc netdev->ethtool_ops = &airoha_ethtool_ops; netdev->max_mtu = AIROHA_MAX_MTU; netdev->watchdog_timeo = 5 * HZ; diff --git a/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch b/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch index 77b37d5483..757d54db70 100644 --- a/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch +++ b/target/linux/airoha/patches-6.18/920-12-net-airoha-defer-GDM3-GDM4-WAN-mode-and-GDM2-loopbac.patch @@ -333,7 +333,7 @@ Signed-off-by: Lorenzo Bianconi int i; + qdma = airoha_qdma_deref(dev); - for (i = 0; i < AIROHA_NUM_TX_RING; i++) + for (i = 0; i < AIROHA_NUM_QOS_QUEUES; i++) - airoha_qdma_clear(dev->qdma, REG_QUEUE_CLOSE_CFG(channel), + airoha_qdma_clear(qdma, REG_QUEUE_CLOSE_CFG(channel), TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i)); @@ -407,7 +407,7 @@ Signed-off-by: Lorenzo Bianconi if (err) @@ -3138,11 +3234,12 @@ static int airoha_tc_htb_alloc_leaf_queu u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; - int err, num_tx_queues = netdev->real_num_tx_queues; + int err, num_tx_queues = AIROHA_NUM_TX_RING + channel + 1; struct airoha_gdm_dev *dev = netdev_priv(netdev); - struct airoha_qdma *qdma = dev->qdma; + struct airoha_qdma *qdma; @@ -419,7 +419,7 @@ Signed-off-by: Lorenzo Bianconi if (test_and_set_bit(channel, qdma->qos_channel_map)) { NL_SET_ERR_MSG_MOD(opt->extack, "qdma qos channel already in use"); -@@ -3176,7 +3273,7 @@ static int airoha_qdma_set_rx_meter(stru +@@ -3178,7 +3275,7 @@ static int airoha_qdma_set_rx_meter(stru u32 rate, u32 bucket_size, enum trtcm_unit_type unit_type) { @@ -428,21 +428,20 @@ Signed-off-by: Lorenzo Bianconi int i; for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { -@@ -3350,11 +3447,12 @@ static int airoha_dev_setup_tc_block(str - static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue) +@@ -3353,10 +3450,11 @@ static void airoha_tc_remove_htb_queue(s { struct airoha_gdm_dev *dev = netdev_priv(netdev); + int num_tx_queues = AIROHA_NUM_TX_RING; - struct airoha_qdma *qdma = dev->qdma; + struct airoha_qdma *qdma; - netif_set_real_num_tx_queues(netdev, netdev->real_num_tx_queues - 1); - airoha_qdma_set_tx_rate_limit(netdev, queue + 1, 0, 0); + airoha_qdma_set_tx_rate_limit(netdev, queue, 0, 0); + qdma = airoha_qdma_deref(dev); clear_bit(queue, qdma->qos_channel_map); clear_bit(queue, dev->qos_sq_bmap); - } -@@ -3375,6 +3473,95 @@ static int airoha_tc_htb_delete_leaf_que + +@@ -3382,6 +3480,95 @@ static int airoha_tc_htb_delete_leaf_que return 0; } @@ -538,7 +537,7 @@ Signed-off-by: Lorenzo Bianconi static int airoha_tc_htb_destroy(struct net_device *netdev) { struct airoha_gdm_dev *dev = netdev_priv(netdev); -@@ -3383,6 +3570,8 @@ static int airoha_tc_htb_destroy(struct +@@ -3390,6 +3577,8 @@ static int airoha_tc_htb_destroy(struct for_each_set_bit(q, dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS) airoha_tc_remove_htb_queue(netdev, q); @@ -547,7 +546,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -3402,24 +3591,33 @@ static int airoha_tc_get_htb_get_leaf_qu +@@ -3409,24 +3598,33 @@ static int airoha_tc_get_htb_get_leaf_qu return 0; } diff --git a/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch b/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch index 2e854b6f49..1769b58372 100644 --- a/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch +++ b/target/linux/airoha/patches-6.18/920-13-net-airoha-Rework-MTU-configuration.patch @@ -143,7 +143,7 @@ Signed-off-by: Lorenzo Bianconi return 0; } -@@ -3490,6 +3465,7 @@ static void airoha_disable_qos_for_gdm34 +@@ -3497,6 +3472,7 @@ static void airoha_disable_qos_for_gdm34 dev->flags &= ~AIROHA_PRIV_F_WAN; airoha_dev_set_qdma(dev); @@ -151,7 +151,7 @@ Signed-off-by: Lorenzo Bianconi airoha_set_macaddr(dev, netdev->dev_addr); if (netif_running(netdev)) -@@ -3538,6 +3514,7 @@ static int airoha_enable_qos_for_gdm34(s +@@ -3545,6 +3521,7 @@ static int airoha_enable_qos_for_gdm34(s if (err) goto error_disable_loopback; From fe5edcf9850d60a33a5510a42256f988a159ec75 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sat, 20 Jun 2026 07:37:46 +0000 Subject: [PATCH 157/228] realtek: pcs: add SerDes page definitions To reduce having magic values all over the place in the whole driver, add definitions for the SerDes register pages. They are equal among all variants and can be clearly named, as already done in the debugfs output of the realtek-otto-serdes-mdio driver. This should ease comparison, code understanding and very likely is a step forward towards upstream-readyness. Also define two macros to cover the special cases for RTL931x's digital SerDes via 0x40/0x80 page offset. Link: https://github.com/openwrt/openwrt/pull/23915 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index d1bfdbf4f6..b188ee4c1c 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -116,6 +116,56 @@ #define RTPCS_931X_SDS_MAIN_AMP_MASK GENMASK(9, 5) #define RTPCS_931X_SDS_POST_AMP_MASK GENMASK(14, 10) +/* + * A SerDes has a register space separated into several pages. Each page + * serves a different purpose and is the home of common settings. E.g., + * there are dedicated pages for each operating speed of a SerDes. + */ +enum rtpcs_page { + PAGE_SDS = 0x00, + PAGE_SDS_EXT = 0x01, + PAGE_FIB = 0x02, + PAGE_FIB_EXT = 0x03, + PAGE_TGR_STD_0 = 0x04, + PAGE_TGR_STD_1 = 0x05, + PAGE_TGR_PRO_0 = 0x06, + PAGE_TGR_PRO_1 = 0x07, + PAGE_TGX_STD_0 = 0x08, + PAGE_TGX_STD_1 = 0x09, + PAGE_TGX_PRO_0 = 0x0a, + PAGE_TGX_PRO_1 = 0x0b, + PAGE_WDIG = 0x1f, + PAGE_ANA_MISC = 0x20, + PAGE_ANA_COM = 0x21, + PAGE_ANA_SPD = 0x22, + PAGE_ANA_SPD_EXT = 0x23, + PAGE_ANA_1G2 = 0x24, + PAGE_ANA_1G2_EXT = 0x25, + PAGE_ANA_2G5 = 0x26, + PAGE_ANA_2G5_EXT = 0x27, + PAGE_ANA_3G1 = 0x28, + PAGE_ANA_3G1_EXT = 0x29, + PAGE_ANA_5G0 = 0x2a, + PAGE_ANA_5G0_EXT = 0x2b, + PAGE_ANA_6G2 = 0x2c, + PAGE_ANA_6G2_EXT = 0x2d, + PAGE_ANA_10G = 0x2e, + PAGE_ANA_10G_EXT = 0x2f, + PAGE_GPON_SP = 0x30, + PAGE_GPON_SP_EXT = 0x31, + PAGE_EPON_SP = 0x32, + PAGE_EPON_SP_EXT = 0x33, + PAGE_ANA_6G0 = 0x34, + PAGE_ANA_6G0_EXT = 0x35, +}; + +/* + * RTL931X only: the digital SDS 1/2 register pages mirror an analog page at a + * fixed +0x40 / +0x80 region offset. See rtpcs_931x_sds_op_xsg_write(). + */ +#define DIGI_1(page) ((page) + 0x40) +#define DIGI_2(page) ((page) + 0x80) + enum rtpcs_sds_type { RTPCS_SDS_TYPE_UNKNOWN, RTPCS_SDS_TYPE_5G, From 4a31f8e54430fe6de762cd105b4a33a0dece562b Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sat, 20 Jun 2026 07:52:34 +0000 Subject: [PATCH 158/228] realtek: pcs: replace hardcoded page values with named fields Replace all hardcoded page values in various calls and definitions with the previously added defines. This should help readability, giving those various values a name and making it easier to compare and track within the context of what is being set. Link: https://github.com/openwrt/openwrt/pull/23915 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 1196 +++++++++-------- 1 file changed, 618 insertions(+), 578 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index b188ee4c1c..68bcd26667 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -226,13 +226,14 @@ struct rtpcs_ctrl; struct rtpcs_serdes; struct rtpcs_sds_ops { - int (*read)(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, int bitlow); - int (*write)(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, int bitlow, - u16 value); + int (*read)(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow); + int (*write)(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value); /* optional */ - int (*xsg_write)(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, int bitlow, - u16 value); + int (*xsg_write)(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value); int (*set_autoneg)(struct rtpcs_serdes *sds, unsigned int neg_mode, const unsigned long *advertising); @@ -265,7 +266,7 @@ struct rtpcs_sds_ops { }; struct rtpcs_sds_reg_field { - u8 page; + enum rtpcs_page page; u8 reg; u8 msb; u8 lsb; @@ -337,7 +338,7 @@ struct rtpcs_config { }; struct rtpcs_sds_config { - u8 page; + enum rtpcs_page page; u8 reg; u16 data; }; @@ -348,7 +349,7 @@ struct rtpcs_sds_tx_config { u8 post_amp; }; -static int rtpcs_sds_to_mmd(int sds_page, int sds_regnum) +static int rtpcs_sds_to_mmd(enum rtpcs_page sds_page, int sds_regnum) { return (sds_page << 8) + sds_regnum; } @@ -360,8 +361,8 @@ static int rtpcs_sds_to_mmd(int sds_page, int sds_regnum) * implementing the SerDes read/write ops. */ -static int __rtpcs_sds_read_raw(struct rtpcs_ctrl *ctrl, int sds_id, int page, int regnum, - int bithigh, int bitlow) +static int __rtpcs_sds_read_raw(struct rtpcs_ctrl *ctrl, int sds_id, enum rtpcs_page page, + int regnum, int bithigh, int bitlow) { int mmd_regnum = rtpcs_sds_to_mmd(page, regnum); u16 mask; @@ -378,8 +379,8 @@ static int __rtpcs_sds_read_raw(struct rtpcs_ctrl *ctrl, int sds_id, int page, i return (val & mask) >> bitlow; } -static int __rtpcs_sds_write_raw(struct rtpcs_ctrl *ctrl, int sds_id, int page, int regnum, - int bithigh, int bitlow, u16 value) +static int __rtpcs_sds_write_raw(struct rtpcs_ctrl *ctrl, int sds_id, enum rtpcs_page page, + int regnum, int bithigh, int bitlow, u16 value) { int mmd_regnum = rtpcs_sds_to_mmd(page, regnum); u16 mask, set; @@ -397,38 +398,38 @@ static int __rtpcs_sds_write_raw(struct rtpcs_ctrl *ctrl, int sds_id, int page, /* Generic implementations, if no special behavior is needed */ -static int rtpcs_generic_sds_op_read(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow) +static int rtpcs_generic_sds_op_read(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow) { return __rtpcs_sds_read_raw(sds->ctrl, sds->id, page, regnum, bithigh, bitlow); } -static int rtpcs_generic_sds_op_write(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow, u16 value) +static int rtpcs_generic_sds_op_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value) { return __rtpcs_sds_write_raw(sds->ctrl, sds->id, page, regnum, bithigh, bitlow, value); } /* Convenience helpers */ -static int rtpcs_sds_read_bits(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow) +static int rtpcs_sds_read_bits(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow) { return sds->ops->read(sds, page, regnum, bithigh, bitlow); } -static int rtpcs_sds_write_bits(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow, u16 value) +static int rtpcs_sds_write_bits(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value) { return sds->ops->write(sds, page, regnum, bithigh, bitlow, value); } -static int rtpcs_sds_read(struct rtpcs_serdes *sds, int page, int regnum) +static int rtpcs_sds_read(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum) { return sds->ops->read(sds, page, regnum, 15, 0); } -static int rtpcs_sds_write(struct rtpcs_serdes *sds, int page, int regnum, u16 value) +static int rtpcs_sds_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, u16 value) { return sds->ops->write(sds, page, regnum, 15, 0, value); } @@ -445,8 +446,8 @@ static int rtpcs_sds_write_field(struct rtpcs_serdes *sds, const struct rtpcs_sd return sds->ops->write(sds, field->page, field->reg, field->msb, field->lsb, value); } -static int rtpcs_sds_xsg_write_bits(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow, u16 value) +static int rtpcs_sds_xsg_write_bits(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value) { if (!sds->ops->xsg_write) return -ENOTSUPP; @@ -454,7 +455,8 @@ static int rtpcs_sds_xsg_write_bits(struct rtpcs_serdes *sds, int page, int regn return sds->ops->xsg_write(sds, page, regnum, bithigh, bitlow, value); } -static int rtpcs_sds_xsg_write(struct rtpcs_serdes *sds, int page, int regnum, u16 value) +static int rtpcs_sds_xsg_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + u16 value) { if (!sds->ops->xsg_write) return -ENOTSUPP; @@ -739,47 +741,47 @@ static void rtpcs_838x_sds_patch_qsgmii(struct rtpcs_serdes *sds) { bool is_even = (rtpcs_sds_get_even(sds) == sds); - rtpcs_sds_write(sds, 0x1, 0x3, 0xf46d); - rtpcs_sds_write(sds, 0x1, 0x2, 0x85fa); - rtpcs_sds_write(sds, 0x1, 0x6, 0x20d8); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x3, 0xf46d); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x2, 0x85fa); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x6, 0x20d8); - rtpcs_sds_write(sds, 0x1, 10, is_even ? 0x58c7 : 0x80c7); - rtpcs_sds_write(sds, 0x1, 17, is_even ? 0xb7c9 : 0x4208); - rtpcs_sds_write(sds, 0x1, 18, is_even ? 0xab8e : 0xc208); - rtpcs_sds_write(sds, 0x1, 11, 0x482); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 10, is_even ? 0x58c7 : 0x80c7); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 17, is_even ? 0xb7c9 : 0x4208); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 18, is_even ? 0xab8e : 0xc208); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 11, 0x482); if (is_even) - rtpcs_sds_write(sds, 0x1, 19, 0x24ab); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 19, 0x24ab); - rtpcs_sds_write(sds, 0x2, 25, 0x303); - rtpcs_sds_write(sds, 0x1, 14, 0xfcc2); + rtpcs_sds_write(sds, PAGE_FIB, 25, 0x303); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 14, 0xfcc2); } static void rtpcs_838x_sds_patch_fiber(struct rtpcs_serdes *sds) { bool is_even = rtpcs_sds_get_even(sds) == sds; - rtpcs_sds_write(sds, 1, 2, 0x85fa); - rtpcs_sds_write(sds, 1, 3, 0x00); - rtpcs_sds_write(sds, 1, 4, 0xdccc); - rtpcs_sds_write(sds, 1, 5, 0x00); - rtpcs_sds_write(sds, 1, 6, is_even ? 0x20d8 : 0x3600); - rtpcs_sds_write(sds, 1, 7, 0x03); - rtpcs_sds_write(sds, 1, 8, 0x79aa); - rtpcs_sds_write(sds, 1, 9, 0x8c64); - rtpcs_sds_write(sds, 1, 10, 0xc3); - rtpcs_sds_write(sds, 1, 11, 0x1482); - rtpcs_sds_write(sds, 1, 17, 0xb7c9); - rtpcs_sds_write(sds, 1, 18, 0xab8e); - rtpcs_sds_write(sds, 2, 24, 0x14aa); - rtpcs_sds_write(sds, 2, 25, 0x303); - rtpcs_sds_write(sds, 1, 14, 0xf002); - rtpcs_sds_write(sds, 2, 27, 0x4bf); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 2, 0x85fa); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 3, 0x00); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 4, 0xdccc); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 5, 0x00); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 6, is_even ? 0x20d8 : 0x3600); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 7, 0x03); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 8, 0x79aa); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 9, 0x8c64); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 10, 0xc3); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 11, 0x1482); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 17, 0xb7c9); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 18, 0xab8e); + rtpcs_sds_write(sds, PAGE_FIB, 24, 0x14aa); + rtpcs_sds_write(sds, PAGE_FIB, 25, 0x303); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 14, 0xf002); + rtpcs_sds_write(sds, PAGE_FIB, 27, 0x4bf); } static void rtpcs_838x_sds_reset(struct rtpcs_serdes *sds) { - rtpcs_sds_write_bits(sds, 0, 3, 6, 6, 0x1); /* REG3 SOFT_RST */ - rtpcs_sds_write_bits(sds, 0, 3, 6, 6, 0x0); /* REG3 SOFT_RST */ + rtpcs_sds_write_bits(sds, PAGE_SDS, 3, 6, 6, 0x1); /* REG3 SOFT_RST */ + rtpcs_sds_write_bits(sds, PAGE_SDS, 3, 6, 6, 0x0); /* REG3 SOFT_RST */ } static void rtpcs_838x_sds_fill_caps(struct rtpcs_serdes *sds) @@ -823,12 +825,12 @@ static int rtpcs_838x_sds_deactivate(struct rtpcs_serdes *sds) return ret; /* EN_RX | EN_TX */ - ret = rtpcs_sds_write_bits(sds, 0, 0, 1, 0, 0x0); + ret = rtpcs_sds_write_bits(sds, PAGE_SDS, 0, 1, 0, 0x0); if (ret) return ret; /* CFG_FIB_PDOWN / BMCR_PDOWN */ - return rtpcs_sds_write_bits(sds, 2, MII_BMCR, 11, 11, 0x1); + return rtpcs_sds_write_bits(sds, PAGE_FIB, MII_BMCR, 11, 11, 0x1); } static int rtpcs_838x_sds_activate(struct rtpcs_serdes *sds) @@ -838,12 +840,12 @@ static int rtpcs_838x_sds_activate(struct rtpcs_serdes *sds) rtpcs_838x_sds_reset(sds); /* CFG_FIB_PDOWN / BMCR_PDOWN */ - ret = rtpcs_sds_write_bits(sds, 2, MII_BMCR, 11, 11, 0x0); + ret = rtpcs_sds_write_bits(sds, PAGE_FIB, MII_BMCR, 11, 11, 0x0); if (ret) return ret; /* EN_RX | EN_TX */ - ret = rtpcs_sds_write_bits(sds, 0, 0, 1, 0, 0x3); + ret = rtpcs_sds_write_bits(sds, PAGE_SDS, 0, 1, 0, 0x3); if (ret) return ret; @@ -890,15 +892,15 @@ static int rtpcs_838x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd struct rtpcs_ctrl *ctrl = sds->ctrl; u8 sds_id = sds->id; - rtpcs_sds_write(sds, 0, 1, 0xf00); + rtpcs_sds_write(sds, PAGE_SDS, 1, 0xf00); usleep_range(1000, 2000); - rtpcs_sds_write(sds, 0, 2, 0x7060); + rtpcs_sds_write(sds, PAGE_SDS, 2, 0x7060); usleep_range(1000, 2000); if (sds_id >= 4) { - rtpcs_sds_write(sds, 2, 30, 0x71e); + rtpcs_sds_write(sds, PAGE_FIB, 30, 0x71e); usleep_range(1000, 2000); - rtpcs_sds_write(sds, 0, 4, 0x74d); + rtpcs_sds_write(sds, PAGE_SDS, 4, 0x74d); usleep_range(1000, 2000); } @@ -923,11 +925,11 @@ static int rtpcs_838x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd /* CKREFBUF_S0S1 */ regmap_write_bits(ctrl->map, RTPCS_838X_PLL_CML_CTRL, 0xf, 0xf); - rtpcs_sds_write_bits(sds, 0x1, 0x3, 1, 1, 0x1); /* REG_CML_SEL */ + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x3, 1, 1, 0x1); /* REG_CML_SEL */ } - rtpcs_sds_write(sds, 0x1, 0x9, 0x8e64); - rtpcs_sds_write(sds, 0x1, 0x9, 0x8c64); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x9, 0x8e64); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x9, 0x8c64); return 0; } @@ -1005,33 +1007,33 @@ static void rtpcs_839x_sds_reset(struct rtpcs_serdes *sds) return; if (sds->type == RTPCS_SDS_TYPE_10G) { - rtpcs_sds_write_bits(odd_sds, 0x2f, 0x1d, 3, 0, 0x5); + rtpcs_sds_write_bits(odd_sds, PAGE_ANA_10G_EXT, 0x1d, 3, 0, 0x5); msleep(500); - rtpcs_sds_write_bits(odd_sds, 0x2f, 0x1d, 3, 0, 0xf); - rtpcs_sds_write_bits(odd_sds, 0x2f, 0x1d, 3, 0, 0x0); + rtpcs_sds_write_bits(odd_sds, PAGE_ANA_10G_EXT, 0x1d, 3, 0, 0xf); + rtpcs_sds_write_bits(odd_sds, PAGE_ANA_10G_EXT, 0x1d, 3, 0, 0x0); - rtpcs_sds_write_bits(even_sds, 0x2e, 0x10, 3, 3, 0x0); - rtpcs_sds_write_bits(even_sds, 0x2f, 0x0, 15, 15, 0x1); + rtpcs_sds_write_bits(even_sds, PAGE_ANA_10G, 0x10, 3, 3, 0x0); + rtpcs_sds_write_bits(even_sds, PAGE_ANA_10G_EXT, 0x0, 15, 15, 0x1); msleep(100); - rtpcs_sds_write_bits(even_sds, 0x2f, 0x0, 15, 15, 0x0); + rtpcs_sds_write_bits(even_sds, PAGE_ANA_10G_EXT, 0x0, 15, 15, 0x0); } else { - rtpcs_sds_write(odd_sds, 0x25, 0x1, 0x0050); - rtpcs_sds_write(odd_sds, 0x25, 0x1, 0x00f0); - rtpcs_sds_write(odd_sds, 0x25, 0x1, 0x0000); + rtpcs_sds_write(odd_sds, PAGE_ANA_1G2_EXT, 0x1, 0x0050); + rtpcs_sds_write(odd_sds, PAGE_ANA_1G2_EXT, 0x1, 0x00f0); + rtpcs_sds_write(odd_sds, PAGE_ANA_1G2_EXT, 0x1, 0x0000); - rtpcs_sds_write_bits(sds, 0x24, 0x14, 0, 0, 0x0); - rtpcs_sds_write_bits(sds, 0x24, 0x14, 9, 9, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_1G2, 0x14, 0, 0, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_1G2, 0x14, 9, 9, 0x1); msleep(100); - rtpcs_sds_write_bits(sds, 0x24, 0x14, 9, 9, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_1G2, 0x14, 9, 9, 0x0); } - rtpcs_sds_write(even_sds, 0x0, 0x3, 0x7146); + rtpcs_sds_write(even_sds, PAGE_SDS, 0x3, 0x7146); msleep(100); - rtpcs_sds_write(even_sds, 0x0, 0x3, 0x7106); + rtpcs_sds_write(even_sds, PAGE_SDS, 0x3, 0x7106); - rtpcs_sds_write(odd_sds, 0x0, 0x3, 0x7146); + rtpcs_sds_write(odd_sds, PAGE_SDS, 0x3, 0x7146); msleep(100); - rtpcs_sds_write(odd_sds, 0x0, 0x3, 0x7106); + rtpcs_sds_write(odd_sds, PAGE_SDS, 0x3, 0x7106); } static void rtpcs_839x_sds_fill_caps(struct rtpcs_serdes *sds) @@ -1080,105 +1082,105 @@ static int rtpcs_839x_sds_probe(struct rtpcs_serdes *sds) return 0; /* Part 1: register setup */ - rtpcs_sds_write(sds, 0x2e, 0x0, 0x5800); - rtpcs_sds_write(sds, 0x2e, 0x1, 0x4000); - rtpcs_sds_write(sds, 0x2e, 0x2, is_even ? 0x5400 : 0x5000); - rtpcs_sds_write(sds, 0x2e, 0x3, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x4, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x5, 0x4000); - rtpcs_sds_write(sds, 0x2e, 0x6, 0x4000); - rtpcs_sds_write(sds, 0x2e, 0x7, 0xffff); - rtpcs_sds_write(sds, 0x2e, 0x8, 0xffff); - rtpcs_sds_write(sds, 0x2e, 0x9, 0x806f); - rtpcs_sds_write(sds, 0x2e, 0xa, 0x0004); - rtpcs_sds_write(sds, 0x2e, 0xb, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0xc, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0xd, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0xe, 0x0a00); - rtpcs_sds_write(sds, 0x2e, 0xf, 0x2000); - rtpcs_sds_write(sds, 0x2e, 0x10, 0xf00e); - rtpcs_sds_write(sds, 0x2e, 0x11, is_even ? 0xf04a : 0xfdab); - rtpcs_sds_write(sds, 0x2e, 0x12, is_even ? 0x97b3 : 0x96ea); - rtpcs_sds_write(sds, 0x2e, 0x13, 0x5318); - rtpcs_sds_write(sds, 0x2e, 0x14, 0x0f03); - rtpcs_sds_write(sds, 0x2e, 0x15, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x16, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x17, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x18, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x19, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x1a, 0xffff); - rtpcs_sds_write(sds, 0x2e, 0x1b, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x1c, 0x1203); - rtpcs_sds_write(sds, 0x2e, 0x1d, 0x0000); - rtpcs_sds_write(sds, 0x2e, 0x1e, 0xa052); - rtpcs_sds_write(sds, 0x2e, 0x1f, 0x9a00); - rtpcs_sds_write(sds, 0x2f, 0x0, 0x00f5); - rtpcs_sds_write(sds, 0x2f, 0x1, 0xf000); - rtpcs_sds_write(sds, 0x2f, 0x2, is_even ? 0x41ff : 0x4079); - rtpcs_sds_write(sds, 0x2f, 0x3, 0x0000); - rtpcs_sds_write(sds, 0x2f, 0x4, is_even ? 0x39ff : 0x93fa); - rtpcs_sds_write(sds, 0x2f, 0x5, 0x3340); - rtpcs_sds_write(sds, 0x2f, 0x6, is_even ? 0x40aa : 0x4280); - rtpcs_sds_write(sds, 0x2f, 0x7, 0x0000); - rtpcs_sds_write(sds, 0x2f, 0x8, 0x801f); - rtpcs_sds_write(sds, 0x2f, 0x9, 0x0000); - rtpcs_sds_write(sds, 0x2f, 0xa, 0x619c); - rtpcs_sds_write(sds, 0x2f, 0xb, 0xffed); - rtpcs_sds_write(sds, 0x2f, 0xc, 0x29ff); - rtpcs_sds_write(sds, 0x2f, 0xd, 0x29ff); - rtpcs_sds_write(sds, 0x2f, 0xe, is_even ? 0x4e10 : 0x4c50); - rtpcs_sds_write(sds, 0x2f, 0xf, is_even ? 0x4e10 : 0x4c50); - rtpcs_sds_write(sds, 0x2f, 0x10, 0x0000); - rtpcs_sds_write(sds, 0x2f, 0x11, 0x0000); - rtpcs_sds_write(sds, 0x0, 0xc, 0x08ec); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x0, 0x5800); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1, 0x4000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x2, is_even ? 0x5400 : 0x5000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x3, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x4, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x5, 0x4000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x6, 0x4000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x7, 0xffff); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x8, 0xffff); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x9, 0x806f); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xa, 0x0004); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xb, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xc, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xd, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xe, 0x0a00); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0xf, 0x2000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x10, 0xf00e); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x11, is_even ? 0xf04a : 0xfdab); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x12, is_even ? 0x97b3 : 0x96ea); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x13, 0x5318); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x14, 0x0f03); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x15, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x16, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x17, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x18, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x19, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1a, 0xffff); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1b, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1c, 0x1203); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1d, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1e, 0xa052); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1f, 0x9a00); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x0, 0x00f5); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x1, 0xf000); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x2, is_even ? 0x41ff : 0x4079); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x3, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x4, is_even ? 0x39ff : 0x93fa); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x5, 0x3340); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x6, is_even ? 0x40aa : 0x4280); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x7, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x8, 0x801f); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x9, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xa, 0x619c); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xb, 0xffed); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xc, 0x29ff); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xd, 0x29ff); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xe, is_even ? 0x4e10 : 0x4c50); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0xf, is_even ? 0x4e10 : 0x4c50); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x10, 0x0000); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x11, 0x0000); + rtpcs_sds_write(sds, PAGE_SDS, 0xc, 0x08ec); if (!is_even) - rtpcs_sds_write(sds, 0x2f, 0x1f, 0x003f); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x1f, 0x003f); /* Part 2: register bit patching (contains some "reset flips") */ - rtpcs_sds_write_bits(sds, 0x0, 0x7, 14, 14, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0x9, 15, 0, 0x417f); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 9, 9, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 12, 10, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 5, 3, 0x0005); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 8, 6, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 2, 0, 0x0002); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 15, 0, 0xc440); + rtpcs_sds_write_bits(sds, PAGE_SDS, 0x7, 14, 14, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x9, 15, 0, 0x417f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 9, 9, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 12, 10, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 5, 3, 0x0005); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 8, 6, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 2, 0, 0x0002); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 15, 0, 0xc440); if (is_even) - rtpcs_sds_write_bits(sds, 0x2f, 0x6, 3, 3, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x5, 15, 0, 0x8000); - rtpcs_sds_write_bits(sds, 0x2e, 0x6, 15, 0, 0x8000); - rtpcs_sds_write_bits(sds, 0x2e, 0xa, 15, 0, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 15, 0, 0x0002); - rtpcs_sds_write_bits(sds, 0x2e, 0x1f, 15, 0, 0xbe00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x6, 3, 3, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x5, 15, 0, 0x8000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x6, 15, 0, 0x8000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xa, 15, 0, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 15, 0, 0x0002); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1f, 15, 0, 0xbe00); if (is_even) { - rtpcs_sds_write_bits(sds, 0x2f, 0xe, 10, 10, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0xf, 10, 10, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0xe, 14, 14, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0xf, 14, 14, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xe, 10, 10, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xf, 10, 10, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xe, 14, 14, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xf, 14, 14, 0x0000); } - rtpcs_sds_write_bits(sds, 0x2e, 0x10, 5, 5, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0x9, 8, 8, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x3, 15, 12, 0x000f); - rtpcs_sds_write_bits(sds, 0x2e, 0x1f, 13, 12, 0x0003); - rtpcs_sds_write_bits(sds, 0x2e, 0x1f, 11, 9, 0x0007); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 15, 15, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 14, 14, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 13, 13, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 12, 12, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 11, 9, 0x0002); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 8, 6, 0x0002); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 5, 3, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 2, 0, 0x0000); - rtpcs_sds_write_bits(sds, 0x2f, 0xc, 9, 9, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0xd, 9, 9, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0x8, 5, 5, 0x0001); - rtpcs_sds_write_bits(sds, 0x2f, 0x8, 6, 6, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 15, 15, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x10, 15, 12, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 4, 4, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 9, 9, 0x0000); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 3, 0, 0x0008); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 8, 5, 0x0008); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x10, 5, 5, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x9, 8, 8, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x3, 15, 12, 0x000f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1f, 13, 12, 0x0003); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1f, 11, 9, 0x0007); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 15, 15, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 14, 14, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 13, 13, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 12, 12, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 11, 9, 0x0002); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 8, 6, 0x0002); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 5, 3, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 2, 0, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xc, 9, 9, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0xd, 9, 9, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x8, 5, 5, 0x0001); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x8, 6, 6, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 15, 15, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x10, 15, 12, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 4, 4, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 9, 9, 0x0000); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 3, 0, 0x0008); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 8, 5, 0x0008); return 0; } @@ -1245,7 +1247,7 @@ static int rtpcs_93xx_sds_set_autoneg(struct rtpcs_serdes *sds, unsigned int neg case RTPCS_SDS_MODE_XSGMII: /* XSG N-way state */ en_val = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ? 0x0 : 0x1; - return rtpcs_sds_xsg_write_bits(sds, 0x0, 0x2, 9, 8, en_val); + return rtpcs_sds_xsg_write_bits(sds, PAGE_SDS, 0x2, 9, 8, en_val); case RTPCS_SDS_MODE_USXGMII_10GSXGMII ... RTPCS_SDS_MODE_USXGMII_2_5GSXGMII: /* @@ -1254,7 +1256,7 @@ static int rtpcs_93xx_sds_set_autoneg(struct rtpcs_serdes *sds, unsigned int neg * We do not support forced USXGMII link yet, always activate USXGMII-AN * for now. */ - return rtpcs_sds_write_bits(sds, 0x7, 0x11, 3, 0, 0xf); + return rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_1, 0x11, 3, 0, 0xf); default: return rtpcs_generic_sds_set_autoneg(sds, neg_mode, advertising); @@ -1265,39 +1267,39 @@ static void rtpcs_93xx_sds_usxgmii_config(struct rtpcs_serdes *sds, u32 opcode, u32 all_am_markers, u32 an_table, u32 sync_bit) { /* this comes from USXGMII patch sequences of the SDK */ - rtpcs_sds_write(sds, 0x06, 0x00, 0x0000); - rtpcs_sds_write(sds, 0x06, 0x0D, 0x0F00); - rtpcs_sds_write(sds, 0x06, 0x1D, 0x0600); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x00, 0x0000); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x0D, 0x0F00); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x1D, 0x0600); - rtpcs_sds_write(sds, 0x07, 0x06, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH0 */ - rtpcs_sds_write(sds, 0x07, 0x08, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH1 */ - rtpcs_sds_write(sds, 0x07, 0x0a, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH2 */ - rtpcs_sds_write(sds, 0x07, 0x0c, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH3 */ + rtpcs_sds_write(sds, PAGE_TGR_PRO_1, 0x06, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH0 */ + rtpcs_sds_write(sds, PAGE_TGR_PRO_1, 0x08, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH1 */ + rtpcs_sds_write(sds, PAGE_TGR_PRO_1, 0x0a, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH2 */ + rtpcs_sds_write(sds, PAGE_TGR_PRO_1, 0x0c, 0x1401); /* CFG_QHSG_TXCFG_MAC_CH3 */ /* * Controls the USXGMII AN mode. Two states are currently known: * - 0x03: generic/standard-compliant mode * - 0xaa: Realtek-proprietary mode (e.g. RTL8224) */ - rtpcs_sds_write_bits(sds, 0x7, 0x10, 7, 0, opcode); /* CFG_QHSG_AN_OPC */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_1, 0x10, 7, 0, opcode); /* CFG_QHSG_AN_OPC */ - rtpcs_sds_write_bits(sds, 0x6, 0x12, 15, 0, am_period); - rtpcs_sds_write_bits(sds, 0x6, 0x13, 7, 0, all_am_markers); /* CFG_AM0_M0 */ - rtpcs_sds_write_bits(sds, 0x6, 0x13, 15, 8, all_am_markers); /* CFG_AM0_M1 */ - rtpcs_sds_write_bits(sds, 0x6, 0x14, 7, 0, all_am_markers); /* CFG_AM0_M2 */ - rtpcs_sds_write_bits(sds, 0x6, 0x14, 15, 8, all_am_markers); /* CFG_AM1_M0 */ - rtpcs_sds_write_bits(sds, 0x6, 0x15, 7, 0, all_am_markers); /* CFG_AM1_M1 */ - rtpcs_sds_write_bits(sds, 0x6, 0x15, 15, 8, all_am_markers); /* CFG_AM1_M2 */ - rtpcs_sds_write_bits(sds, 0x6, 0x16, 7, 0, all_am_markers); /* CFG_AM2_M0 */ - rtpcs_sds_write_bits(sds, 0x6, 0x16, 15, 8, all_am_markers); /* CFG_AM2_M1 */ - rtpcs_sds_write_bits(sds, 0x6, 0x17, 7, 0, all_am_markers); /* CFG_AM2_M2 */ - rtpcs_sds_write_bits(sds, 0x6, 0x17, 15, 8, all_am_markers); /* CFG_AM3_M0 */ - rtpcs_sds_write_bits(sds, 0x6, 0x18, 7, 0, all_am_markers); /* CFG_AM3_M1 */ - rtpcs_sds_write_bits(sds, 0x6, 0x18, 15, 8, all_am_markers); /* CFG_AM3_M2 */ - rtpcs_sds_write_bits(sds, 0x6, 0xe, 10, 10, an_table); - rtpcs_sds_write_bits(sds, 0x6, 0x1d, 11, 10, sync_bit); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x12, 15, 0, am_period); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x13, 7, 0, all_am_markers); /* CFG_AM0_M0 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x13, 15, 8, all_am_markers); /* CFG_AM0_M1 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x14, 7, 0, all_am_markers); /* CFG_AM0_M2 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x14, 15, 8, all_am_markers); /* CFG_AM1_M0 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x15, 7, 0, all_am_markers); /* CFG_AM1_M1 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x15, 15, 8, all_am_markers); /* CFG_AM1_M2 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x16, 7, 0, all_am_markers); /* CFG_AM2_M0 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x16, 15, 8, all_am_markers); /* CFG_AM2_M1 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x17, 7, 0, all_am_markers); /* CFG_AM2_M2 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x17, 15, 8, all_am_markers); /* CFG_AM3_M0 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x18, 7, 0, all_am_markers); /* CFG_AM3_M1 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x18, 15, 8, all_am_markers); /* CFG_AM3_M2 */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0xe, 10, 10, an_table); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x1d, 11, 10, sync_bit); - rtpcs_sds_write_bits(sds, 0x06, 0x03, 15, 15, 0x1); /* FP_TGR3_CFG_EEE_EN */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x03, 15, 15, 0x1); /* FP_TGR3_CFG_EEE_EN */ } static int rtpcs_93xx_init(struct rtpcs_ctrl *ctrl) @@ -1336,7 +1338,7 @@ static int rtpcs_93xx_sds_get_pll_config(struct rtpcs_serdes *sds, enum rtpcs_sd */ sbit = pll == RTPCS_SDS_PLL_TYPE_LC ? 8 : 12; - speed_val = rtpcs_sds_read_bits(even_sds, 0x20, 0x12, sbit + 3, sbit); + speed_val = rtpcs_sds_read_bits(even_sds, PAGE_ANA_MISC, 0x12, sbit + 3, sbit); if (speed_val < 0) return speed_val; @@ -1366,12 +1368,13 @@ static int rtpcs_93xx_sds_set_pll_config(struct rtpcs_serdes *sds, enum rtpcs_sd * LC PLL. As it is unclear if disabling PLLs has any positive or negative effect, * always activate both. */ - ret = rtpcs_sds_write_bits(even_sds, 0x20, 0x12, 3, 0, 0xf); + ret = rtpcs_sds_write_bits(even_sds, PAGE_ANA_MISC, 0x12, 3, 0, 0xf); if (ret < 0) return ret; /* bit 0 is force-bit, bits [3:1] are speed selector */ - ret = rtpcs_sds_write_bits(even_sds, 0x20, 0x12, sbit + 3, sbit, (speed << 1) | BIT(0)); + ret = rtpcs_sds_write_bits(even_sds, PAGE_ANA_MISC, 0x12, sbit + 3, sbit, + (speed << 1) | BIT(0)); if (ret < 0) return ret; @@ -1524,7 +1527,7 @@ static int rtpcs_93xx_sds_set_mac_driven_mode(struct rtpcs_serdes *sds, { int ret; - ret = rtpcs_sds_write_bits(sds, 0x1f, 0x09, 6, 6, 0); + ret = rtpcs_sds_write_bits(sds, PAGE_WDIG, 0x09, 6, 6, 0); if (ret) return ret; @@ -1545,7 +1548,7 @@ static int rtpcs_93xx_sds_get_ip_mode(struct rtpcs_serdes *sds) const s16 *vals = sds->ctrl->cfg->sds_hw_mode_vals; int raw; - raw = rtpcs_sds_read_bits(sds, 0x1f, 0x09, 11, 7); + raw = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x09, 11, 7); if (raw < 0) return raw; @@ -1568,7 +1571,7 @@ static int rtpcs_93xx_sds_set_ip_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_m return -EOPNOTSUPP; /* BIT(0) is force mode enable bit */ - return rtpcs_sds_write_bits(sds, 0x1f, 0x09, 11, 6, raw << 1 | BIT(0)); + return rtpcs_sds_write_bits(sds, PAGE_WDIG, 0x09, 11, 6, raw << 1 | BIT(0)); } static void rtpcs_93xx_sds_fill_caps(struct rtpcs_serdes *sds) @@ -1640,16 +1643,16 @@ static int rtpcs_930x_sds_get_phys_sds_id(int sds_id, int page) return sds_id; } -static int rtpcs_930x_sds_op_read(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow) +static int rtpcs_930x_sds_op_read(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow) { int sds_id = rtpcs_930x_sds_get_phys_sds_id(sds->id, page); return __rtpcs_sds_read_raw(sds->ctrl, sds_id, page, regnum, bithigh, bitlow); } -static int rtpcs_930x_sds_op_write(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, - int bitlow, u16 value) +static int rtpcs_930x_sds_op_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, + int bithigh, int bitlow, u16 value) { int sds_id = rtpcs_930x_sds_get_phys_sds_id(sds->id, page); @@ -1662,7 +1665,7 @@ static int rtpcs_930x_sds_op_write(struct rtpcs_serdes *sds, int page, int regnu * This implements 'dal_longan_sds_xsg_field_write' and a combination of * '_rtl9300_serdes_index_to_physical' and '_rtl9300_serdes_reg_write' from the SDK. */ -static int rtpcs_930x_sds_op_xsg_write(struct rtpcs_serdes *sds, int page, int regnum, +static int rtpcs_930x_sds_op_xsg_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, int bithigh, int bitlow, u16 value) { int phys_sds_id, ret; @@ -1692,10 +1695,10 @@ static int rtpcs_930x_sds_op_xsg_write(struct rtpcs_serdes *sds, int page, int r static void rtpcs_930x_sds_rx_reset(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { - int page = 0x2e; /* 10GR and USXGMII */ + enum rtpcs_page page = PAGE_ANA_10G; /* 10GR and USXGMII */ if (hw_mode == RTPCS_SDS_MODE_1000BASEX) - page = 0x24; + page = PAGE_ANA_1G2; rtpcs_sds_write_bits(sds, page, 0x15, 4, 4, 0x1); mdelay(5); @@ -1708,7 +1711,7 @@ static int rtpcs_930x_sds_get_pll_select(struct rtpcs_serdes *sds, enum rtpcs_sd int pbit = (sds == even_sds) ? 4 : 6; int pll_sel; - pll_sel = rtpcs_sds_read_bits(even_sds, 0x20, 0x12, pbit + 1, pbit); + pll_sel = rtpcs_sds_read_bits(even_sds, PAGE_ANA_MISC, 0x12, pbit + 1, pbit); if (pll_sel < 0) return pll_sel; @@ -1726,7 +1729,8 @@ static int rtpcs_930x_sds_set_pll_select(struct rtpcs_serdes *sds, enum rtpcs_sd /* Selecting the PLL a SerDes uses is done in the even lane register */ /* bit 0 is force-bit, bit 1 is PLL selector */ - return rtpcs_sds_write_bits(even_sds, 0x20, 0x12, pbit + 1, pbit, (pll << 1) | BIT(0)); + return rtpcs_sds_write_bits(even_sds, PAGE_ANA_MISC, 0x12, pbit + 1, pbit, + (pll << 1) | BIT(0)); } static int rtpcs_930x_sds_reset_cmu(struct rtpcs_serdes *sds, enum rtpcs_sds_pll_type pll) @@ -1744,7 +1748,7 @@ static int rtpcs_930x_sds_reset_cmu(struct rtpcs_serdes *sds, enum rtpcs_sds_pll bit = pll == RTPCS_SDS_PLL_TYPE_LC ? 2 : 0; for (i = 0; i < ARRAY_SIZE(reset_sequence); i++) { - ret = rtpcs_sds_write_bits(even_sds, 0x21, 0x0b, bit + 1, bit, + ret = rtpcs_sds_write_bits(even_sds, PAGE_ANA_COM, 0x0b, bit + 1, bit, reset_sequence[i]); if (ret < 0) return ret; @@ -1766,8 +1770,8 @@ static int rtpcs_930x_sds_wait_clock_ready(struct rtpcs_serdes *sds) for (i = 0; i < 20; i++) { usleep_range(10000, 15000); - rtpcs_sds_write(even_sds, 0x1f, 0x02, 53); - ready = rtpcs_sds_read_bits(even_sds, 0x1f, 0x14, bit, bit); + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x02, 53); + ready = rtpcs_sds_read_bits(even_sds, PAGE_WDIG, 0x14, bit, bit); ready_cnt = ready ? ready_cnt + 1 : 0; if (ready_cnt >= 3) @@ -1782,8 +1786,8 @@ static void rtpcs_930x_sds_set_power(struct rtpcs_serdes *sds, bool on) int power_down = on ? 0x0 : 0x3; int rx_enable = on ? 0x3 : 0x1; - rtpcs_sds_write_bits(sds, 0x20, 0x00, 7, 6, power_down); - rtpcs_sds_write_bits(sds, 0x20, 0x00, 5, 4, rx_enable); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x00, 7, 6, power_down); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x00, 5, 4, rx_enable); } static int rtpcs_930x_sds_reconfigure_to_pll(struct rtpcs_serdes *sds, enum rtpcs_sds_pll_type pll) @@ -1825,9 +1829,9 @@ static int rtpcs_930x_sds_reconfigure_to_pll(struct rtpcs_serdes *sds, enum rtpc static void rtpcs_930x_sds_reset_state_machine(struct rtpcs_serdes *sds) { - rtpcs_sds_write_bits(sds, 0x06, 0x02, 12, 12, 0x01); /* SM_RESET bit */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x02, 12, 12, 0x01); /* SM_RESET bit */ usleep_range(10000, 20000); - rtpcs_sds_write_bits(sds, 0x06, 0x02, 12, 12, 0x00); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x02, 12, 12, 0x00); usleep_range(10000, 20000); } @@ -1843,18 +1847,20 @@ static int rtpcs_930x_sds_init_state_machine(struct rtpcs_serdes *sds, * works properly for 10G. To verify operation readyness run a connection check via * loopback. */ - loopback = rtpcs_sds_read_bits(sds, 0x06, 0x01, 2, 2); /* CFG_AFE_LPK bit */ - rtpcs_sds_write_bits(sds, 0x06, 0x01, 2, 2, 0x01); + loopback = rtpcs_sds_read_bits(sds, PAGE_TGR_PRO_0, 0x01, 2, 2); /* CFG_AFE_LPK bit */ + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x01, 2, 2, 0x01); while (cnt-- && ret) { rtpcs_930x_sds_reset_state_machine(sds); - link = rtpcs_sds_read_bits(sds, 0x05, 0x00, 12, 12); /* 10G link state (latched) */ - link = rtpcs_sds_read_bits(sds, 0x05, 0x00, 12, 12); + + /* 10G link state (latched) */ + link = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0x00, 12, 12); + link = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0x00, 12, 12); if (link) ret = 0; } - rtpcs_sds_write_bits(sds, 0x06, 0x01, 2, 2, loopback); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x01, 2, 2, loopback); rtpcs_930x_sds_reset_state_machine(sds); return ret; @@ -1938,17 +1944,17 @@ static int rtpcs_930x_sds_deactivate(struct rtpcs_serdes *sds) return ret; /* Disable fiber RX. */ - ret = rtpcs_sds_write_bits(sds, 0x20, 2, 12, 12, 1); + ret = rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 2, 12, 12, 1); if (ret) return ret; /* Power down the 1G PHY block. */ - ret = rtpcs_sds_write_bits(sds, 0x02, MII_BMCR, 11, 11, 1); /* BMCR_PDOWN */ + ret = rtpcs_sds_write_bits(sds, PAGE_FIB, MII_BMCR, 11, 11, 1); /* BMCR_PDOWN */ if (ret) return ret; /* Power down the 10G PHY block. */ - return rtpcs_sds_write_bits(sds, 0x04, MII_BMCR, 11, 11, 1); /* BMCR_PDOWN */ + return rtpcs_sds_write_bits(sds, PAGE_TGR_STD_0, MII_BMCR, 11, 11, 1); /* BMCR_PDOWN */ } static int rtpcs_930x_sds_activate(struct rtpcs_serdes *sds) @@ -1960,30 +1966,30 @@ static int rtpcs_930x_sds_activate(struct rtpcs_serdes *sds) rtpcs_930x_sds_rx_reset(sds, sds->hw_mode); /* Enable fiber RX. */ - ret = rtpcs_sds_write_bits(sds, 0x20, 2, 12, 12, 0); + ret = rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 2, 12, 12, 0); if (ret) return ret; /* Power up the 1G PHY block. */ - ret = rtpcs_sds_write_bits(sds, 0x02, MII_BMCR, 11, 11, 0); /* BMCR_PDOWN */ + ret = rtpcs_sds_write_bits(sds, PAGE_FIB, MII_BMCR, 11, 11, 0); /* BMCR_PDOWN */ if (ret) return ret; /* Power up the 10G PHY block. */ - return rtpcs_sds_write_bits(sds, 0x04, MII_BMCR, 11, 11, 0); /* BMCR_PDOWN */ + return rtpcs_sds_write_bits(sds, PAGE_TGR_STD_0, MII_BMCR, 11, 11, 0); /* BMCR_PDOWN */ } static void rtpcs_930x_sds_tx_config(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { /* parameters: rtl9303_80G_txParam_s2 */ + enum rtpcs_page page; int impedance = 0x8; int pre_amp = 0x2; int main_amp = 0x9; int post_amp = 0x2; int pre_en = 0x1; int post_en = 0x1; - int page; switch (hw_mode) { case RTPCS_SDS_MODE_1000BASEX: @@ -1991,13 +1997,13 @@ static void rtpcs_930x_sds_tx_config(struct rtpcs_serdes *sds, pre_amp = 0x1; main_amp = 0x9; post_amp = 0x1; - page = 0x25; + page = PAGE_ANA_1G2_EXT; break; case RTPCS_SDS_MODE_2500BASEX: pre_amp = 0; post_amp = 0x8; pre_en = 0; - page = 0x29; + page = PAGE_ANA_3G1_EXT; break; case RTPCS_SDS_MODE_10GBASER: case RTPCS_SDS_MODE_USXGMII_10GSXGMII: @@ -2008,7 +2014,7 @@ static void rtpcs_930x_sds_tx_config(struct rtpcs_serdes *sds, main_amp = 0x10; post_amp = 0; post_en = 0; - page = 0x2f; + page = PAGE_ANA_10G_EXT; break; case RTPCS_SDS_MODE_QSGMII: return; @@ -2032,34 +2038,34 @@ static void rtpcs_930x_sds_rxcal_dcvs_manual(struct rtpcs_serdes *sds, if (manual) { switch (dcvs_id) { case 0: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 14, 14, 0x1); - rtpcs_sds_write_bits(sds, 0x2f, 0x03, 5, 5, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2f, 0x03, 4, 0, dvcs_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 14, 14, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 5, 5, dvcs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 4, 0, dvcs_list[1]); break; case 1: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 13, 13, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 15, 15, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 14, 11, dvcs_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 13, 13, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 15, 15, dvcs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 14, 11, dvcs_list[1]); break; case 2: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 12, 12, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 10, 10, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 9, 6, dvcs_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 12, 12, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 10, 10, dvcs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 9, 6, dvcs_list[1]); break; case 3: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 11, 11, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 5, 5, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 4, 1, dvcs_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 11, 11, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 5, 5, dvcs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 4, 1, dvcs_list[1]); break; case 4: - rtpcs_sds_write_bits(sds, 0x2e, 0x01, 15, 15, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x11, 10, 10, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x11, 9, 6, dvcs_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 15, 15, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 10, 10, dvcs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 9, 6, dvcs_list[1]); break; case 5: - rtpcs_sds_write_bits(sds, 0x2e, 0x02, 11, 11, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x11, 4, 4, dvcs_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x11, 3, 0, dvcs_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x02, 11, 11, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 4, 4, dvcs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 3, 0, dvcs_list[1]); break; default: break; @@ -2067,22 +2073,22 @@ static void rtpcs_930x_sds_rxcal_dcvs_manual(struct rtpcs_serdes *sds, } else { switch (dcvs_id) { case 0: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 14, 14, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 14, 14, 0x0); break; case 1: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 13, 13, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 13, 13, 0x0); break; case 2: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 12, 12, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 12, 12, 0x0); break; case 3: - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 11, 11, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 11, 11, 0x0); break; case 4: - rtpcs_sds_write_bits(sds, 0x2e, 0x01, 15, 15, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 15, 15, 0x0); break; case 5: - rtpcs_sds_write_bits(sds, 0x2e, 0x02, 11, 11, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x02, 11, 11, 0x0); break; default: break; @@ -2100,71 +2106,71 @@ static void rtpcs_930x_sds_rxcal_dcvs_get(struct rtpcs_serdes *sds, bool dcvs_manual; if (sds == even_sds) - rtpcs_sds_write(sds, 0x1f, 0x2, 0x2f); + rtpcs_sds_write(sds, PAGE_WDIG, 0x2, 0x2f); else - rtpcs_sds_write(even_sds, 0x1f, 0x2, 0x31); + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, 0x31); - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ - rtpcs_sds_write_bits(sds, 0x21, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ switch (dcvs_id) { case 0: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x22); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x22); mdelay(1); /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x1e, 14, 14); + dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); + dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); + dcvs_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x1e, 14, 14); break; case 1: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x23); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x23); mdelay(1); /* ##DCVS0 Read Out */ - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x1e, 13, 13); + dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); + dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); + dcvs_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x1e, 13, 13); break; case 2: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x24); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x24); mdelay(1); /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x1e, 12, 12); + dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); + dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); + dcvs_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x1e, 12, 12); break; case 3: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x25); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x25); mdelay(1); /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = rtpcs_sds_read_bits(sds, 0x2e, 0x1e, 11, 11); + dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); + dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); + dcvs_manual = rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x1e, 11, 11); break; case 4: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x2c); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x2c); mdelay(1); /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x01, 15, 15); + dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); + dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); + dcvs_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x01, 15, 15); break; case 5: - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0x2d); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x2d); mdelay(1); /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 3, 0); - dcvs_manual = rtpcs_sds_read_bits(sds, 0x2e, 0x02, 11, 11); + dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); + dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); + dcvs_manual = rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x02, 11, 11); break; default: @@ -2182,10 +2188,10 @@ static void rtpcs_930x_sds_rxcal_leq_manual(struct rtpcs_serdes *sds, bool manual, u32 leq_gray) { if (manual) { - rtpcs_sds_write_bits(sds, 0x2e, 0x18, 15, 15, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x16, 14, 10, leq_gray); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x18, 15, 15, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x16, 14, 10, leq_gray); } else { - rtpcs_sds_write_bits(sds, 0x2e, 0x18, 15, 15, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x18, 15, 15, 0x0); mdelay(100); } } @@ -2194,9 +2200,9 @@ static void rtpcs_930x_sds_rxcal_leq_offset_manual(struct rtpcs_serdes *sds, bool manual, u32 offset) { if (manual) { - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 6, 2, offset); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 6, 2, offset); } else { - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 6, 2, offset); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 6, 2, offset); mdelay(1); } } @@ -2234,14 +2240,14 @@ static u32 rtpcs_930x_sds_rxcal_leq_read(struct rtpcs_serdes *sds) u32 leq_gray, leq_bin; bool leq_manual; - rtpcs_sds_write(even_sds, 0x1f, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ - rtpcs_sds_write_bits(sds, 0x21, 0x06, 11, 6, 0x10); /* REG0_RX_DEBUG_SEL */ + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x10); /* REG0_RX_DEBUG_SEL */ mdelay(1); /* ##LEQ Read Out */ - leq_gray = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 7, 3); - leq_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x18, 15, 15); + leq_gray = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 7, 3); + leq_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x18, 15, 15); leq_bin = rtpcs_930x_sds_rxcal_gray_to_binary(leq_gray); pr_info("LEQ gray: %u, LEQ bin: %u, LEQ manual: %u\n", leq_gray, leq_bin, leq_manual); @@ -2252,11 +2258,11 @@ static void rtpcs_930x_sds_rxcal_vth_manual(struct rtpcs_serdes *sds, bool manual, u32 vth_list[]) { if (manual) { - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, 13, 13, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 5, 3, vth_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 2, 0, vth_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 13, 13, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 5, 3, vth_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 2, 0, vth_list[1]); } else { - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, 13, 13, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 13, 13, 0x0); mdelay(10); } } @@ -2267,17 +2273,17 @@ static void rtpcs_930x_sds_rxcal_vth_get(struct rtpcs_serdes *sds, struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); int vth_manual; - rtpcs_sds_write(even_sds, 0x1f, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ - rtpcs_sds_write_bits(sds, 0x21, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0xc); /* REG0_COEF_SEL */ + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0xc); /* REG0_COEF_SEL */ mdelay(1); /* ##VthP & VthN Read Out */ - vth_list[0] = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 2, 0); /* v_thp set bin */ - vth_list[1] = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 3); /* v_thn set bin */ - vth_manual = rtpcs_sds_read_bits(sds, 0x2e, 0x0f, 13, 13); + vth_list[0] = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 2, 0); /* v_thp set bin */ + vth_list[1] = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 3); /* v_thn set bin */ + vth_manual = rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x0f, 13, 13); pr_info("vthp_set_bin = %d, vthn_set_bin = %d, manual = %d\n", vth_list[0], vth_list[1], vth_manual); @@ -2290,43 +2296,48 @@ static void rtpcs_930x_sds_rxcal_tap_manual(struct rtpcs_serdes *sds, switch (tap_id) { case 0: /* ##REG0_LOAD_IN_INIT[0]=1; REG0_TAP0_INIT[5:0]=Tap0_Value */ - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, 0x2f, 0x03, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, 0x2f, 0x03, 4, 0, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, + tap_id + 7, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 4, 0, tap_list[1]); break; case 1: - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, 0x21, 0x07, 6, 6, tap_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x09, 11, 6, tap_list[1]); - rtpcs_sds_write_bits(sds, 0x21, 0x07, 5, 5, tap_list[2]); - rtpcs_sds_write_bits(sds, 0x2f, 0x12, 5, 0, tap_list[3]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, + tap_id + 7, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x07, 6, 6, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 11, 6, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x07, 5, 5, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x12, 5, 0, tap_list[3]); break; case 2: - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x09, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x09, 4, 0, tap_list[1]); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 11, 11, tap_list[2]); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 10, 6, tap_list[3]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, + tap_id + 7, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 4, 0, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 11, 11, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 10, 6, tap_list[3]); break; case 3: - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 4, 0, tap_list[1]); - rtpcs_sds_write_bits(sds, 0x2e, 0x06, 5, 5, tap_list[2]); - rtpcs_sds_write_bits(sds, 0x2e, 0x06, 4, 0, tap_list[3]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, + tap_id + 7, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 4, 0, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 5, 5, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 4, 0, tap_list[3]); break; case 4: - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, 0x2f, 0x01, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, 0x2f, 0x01, 4, 0, tap_list[1]); - rtpcs_sds_write_bits(sds, 0x2e, 0x06, 11, 11, tap_list[2]); - rtpcs_sds_write_bits(sds, 0x2e, 0x06, 10, 6, tap_list[3]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, + tap_id + 7, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 4, 0, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 11, 11, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 10, 6, tap_list[3]); break; default: break; } } else { - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, tap_id + 7, 0x0); mdelay(10); } } @@ -2343,16 +2354,16 @@ static void rtpcs_930x_sds_rxcal_tap_get(struct rtpcs_serdes *sds, u32 tap_coef_bin_odd; bool tap_manual; - rtpcs_sds_write(even_sds, 0x1f, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ - rtpcs_sds_write_bits(sds, 0x21, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, (sds == even_sds) ? 0x2f : 0x31); /* REG_DBGO_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ if (!tap_id) { - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0); /* REG0_COEF_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0); /* REG0_COEF_SEL */ /* ##Tap1 Even Read Out */ mdelay(1); - tap0_sign_out = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 5); - tap0_coef_bin = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 0); + tap0_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 5); + tap0_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 0); pr_info("tap0: coef_bin = %d, sign = %s\n", tap0_coef_bin, tap0_sign_out ? "-" : "+"); @@ -2360,19 +2371,19 @@ static void rtpcs_930x_sds_rxcal_tap_get(struct rtpcs_serdes *sds, tap_list[0] = tap0_sign_out; tap_list[1] = tap0_coef_bin; - tap_manual = !!rtpcs_sds_read_bits(sds, 0x2e, 0x0f, 7, 7); + tap_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x0f, 7, 7); pr_info("tap0: manual = %u\n", tap_manual); } else { - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, tap_id); /* REG0_COEF_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, tap_id); /* REG0_COEF_SEL */ mdelay(1); /* ##Tap1 Even Read Out */ - tap_sign_out_even = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 5); - tap_coef_bin_even = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 0); + tap_sign_out_even = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 5); + tap_coef_bin_even = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 0); - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, (tap_id + 5)); /* REG0_COEF_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, (tap_id + 5)); /* REG0_COEF_SEL */ /* ##Tap1 Odd Read Out */ - tap_sign_out_odd = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 5); - tap_coef_bin_odd = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 4, 0); + tap_sign_out_odd = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 5); + tap_coef_bin_odd = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 0); pr_info("tap%u: even coefficient = %u, sign = %s\n", tap_id, tap_coef_bin_even, tap_sign_out_even ? "-" : "+"); @@ -2385,7 +2396,8 @@ static void rtpcs_930x_sds_rxcal_tap_get(struct rtpcs_serdes *sds, tap_list[2] = tap_sign_out_odd; tap_list[3] = tap_coef_bin_odd; - tap_manual = rtpcs_sds_read_bits(sds, 0x2e, 0x0f, tap_id + 7, tap_id + 7); + tap_manual = rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, + tap_id + 7); pr_info("tap%u: manual = %d\n", tap_id, tap_manual); } } @@ -2398,83 +2410,83 @@ static void rtpcs_930x_sds_do_rx_calibration_1(struct rtpcs_serdes *sds, int vth_min = 0x1; /* 1.1.1 --- */ - rtpcs_sds_write(sds, 6, 0, 0); /* initial value */ + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0, 0); /* initial value */ /* FGCAL */ - rtpcs_sds_write_bits(sds, 0x2e, 0x01, 14, 14, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 10, 5, 0x20); - rtpcs_sds_write_bits(sds, 0x2f, 0x02, 0, 0, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 14, 14, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 10, 5, 0x20); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x02, 0, 0, 0x01); /* DCVS */ - rtpcs_sds_write_bits(sds, 0x2e, 0x1e, 14, 11, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x01, 15, 15, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x02, 11, 11, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 4, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 15, 11, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 10, 6, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 5, 1, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x02, 10, 6, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x11, 4, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2f, 0x00, 3, 0, 0x0f); - rtpcs_sds_write_bits(sds, 0x2e, 0x04, 6, 6, 0x01); - rtpcs_sds_write_bits(sds, 0x2e, 0x04, 7, 7, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 14, 11, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 15, 15, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x02, 11, 11, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 4, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 15, 11, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 10, 6, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 5, 1, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x02, 10, 6, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 4, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x00, 3, 0, 0x0f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x04, 6, 6, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x04, 7, 7, 0x01); /* LEQ (Long Term Equivalent signal level) */ - rtpcs_sds_write_bits(sds, 0x2e, 0x16, 14, 8, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x16, 14, 8, 0x00); /* DFE (Decision Fed Equalizer) */ - rtpcs_sds_write_bits(sds, 0x2f, 0x03, 5, 0, tap0_init_val); - rtpcs_sds_write_bits(sds, 0x2e, 0x09, 11, 6, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x09, 5, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 5, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2f, 0x01, 5, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2f, 0x12, 5, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x0a, 11, 6, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x06, 5, 0, 0x00); - rtpcs_sds_write_bits(sds, 0x2f, 0x01, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 5, 0, tap0_init_val); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 11, 6, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x12, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 11, 6, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 5, 0, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 5, 0, 0x00); /* Vth */ - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 5, 3, 0x07); - rtpcs_sds_write_bits(sds, 0x2e, 0x13, 2, 0, 0x07); - rtpcs_sds_write_bits(sds, 0x2f, 0x0b, 5, 3, vth_min); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 5, 3, 0x07); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 2, 0, 0x07); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0b, 5, 3, vth_min); /* --- 1.1.1 */ /* 1.1.2 Load DFE initial value --- */ - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, 13, 7, 0x7f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 13, 7, 0x7f); /* --- 1.1.2 */ /* 1.1.3 disable LEQ training, enable DFE clock --- */ - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 7, 7, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 6, 2, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x0c, 8, 8, 0x00); - rtpcs_sds_write_bits(sds, 0x2e, 0x0b, 4, 4, 0x01); - rtpcs_sds_write_bits(sds, 0x2e, 0x12, 14, 14, 0x00); - rtpcs_sds_write_bits(sds, 0x2f, 0x02, 15, 15, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 6, 2, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0c, 8, 8, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0b, 4, 4, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x12, 14, 14, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x02, 15, 15, 0x00); /* --- 1.1.3 */ /* 1.1.4 offset cali setting --- */ - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, 15, 14, 0x03); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 15, 14, 0x03); /* --- 1.1.4 */ /* 1.1.5 LEQ and DFE setting --- */ /* assume this is equivalent with (PHY_TYPE == SERDES && MEDIA == FIBER_10G) for now */ if (hw_mode == RTPCS_SDS_MODE_10GBASER) { - rtpcs_sds_write_bits(sds, 0x2e, 0x03, 13, 8, 0x1f); - rtpcs_sds_write_bits(sds, 0x2e, 0x00, 13, 13, 0x01); - rtpcs_sds_write_bits(sds, 0x2e, 0x16, 14, 8, 0x00); /* REG0_FILTER_OUT */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x03, 13, 8, 0x1f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x00, 13, 13, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x16, 14, 8, 0x00); /* REG0_FILTER_OUT */ } - /* REG0_LEQ_DC_GAIN */ - rtpcs_sds_write_bits(sds, 0x2e, 0x16, 3, 2, 0x02); /* REG0_LEQ_DC_GAIN, 0x01 for short DACs */ - rtpcs_sds_write_bits(sds, 0x2e, 0x0f, 6, 0, 0x5f); - rtpcs_sds_write_bits(sds, 0x2f, 0x05, 7, 2, 0x1f); - rtpcs_sds_write_bits(sds, 0x2e, 0x19, 9, 5, 0x1f); - rtpcs_sds_write_bits(sds, 0x2f, 0x0b, 15, 9, 0x3c); - rtpcs_sds_write_bits(sds, 0x2e, 0x0b, 1, 0, 0x03); + /* REG0_LEQ_DC_GAIN, 0x01 for short DACs */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x16, 3, 2, 0x02); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 6, 0, 0x5f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x05, 7, 2, 0x1f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x19, 9, 5, 0x1f); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0b, 15, 9, 0x3c); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0b, 1, 0, 0x03); /* --- 1.1.5 */ } @@ -2484,10 +2496,10 @@ static void rtpcs_930x_sds_do_rx_calibration_2_1(struct rtpcs_serdes *sds) /* 1.2.1 ForegroundOffsetCal_Manual --- */ /* Gray config endis to 1 */ - rtpcs_sds_write_bits(sds, 0x2f, 0x02, 2, 2, 0x01); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x02, 2, 2, 0x01); /* ForegroundOffsetCal_Manual(auto mode) */ - rtpcs_sds_write_bits(sds, 0x2e, 0x01, 14, 14, 0x00); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 14, 14, 0x00); /* --- 1.2.1 */ } @@ -2495,7 +2507,7 @@ static void rtpcs_930x_sds_do_rx_calibration_2_1(struct rtpcs_serdes *sds) static void rtpcs_930x_sds_do_rx_calibration_2_2(struct rtpcs_serdes *sds) { /* Force Rx-Run = 0 */ - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 8, 8, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 8, 8, 0x0); rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); } @@ -2510,16 +2522,16 @@ static void rtpcs_930x_sds_do_rx_calibration_2_3(struct rtpcs_serdes *sds) for (int run = 0; run < 10; run++) { /* REG_DBGO_SEL */ - rtpcs_sds_write(even_sds, 0x1f, 0x2, (sds == even_sds) ? 0x2f : 0x31); - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ - rtpcs_sds_write_bits(sds, 0x21, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, (sds == even_sds) ? 0x2f : 0x31); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0xf); /* REG0_COEF_SEL */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0xf); /* REG0_COEF_SEL */ /* ##FGCAL read gray */ - fgcal_gray = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 0); - rtpcs_sds_write_bits(sds, 0x2f, 0x0c, 5, 0, 0xe); /* REG0_COEF_SEL */ + fgcal_gray = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0xe); /* REG0_COEF_SEL */ /* ##FGCAL read binary */ - fgcal_binary = rtpcs_sds_read_bits(sds, 0x1f, 0x14, 5, 0); + fgcal_binary = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 5, 0); if (fgcal_binary <= 60 && fgcal_binary >= 3) break; @@ -2527,14 +2539,14 @@ static void rtpcs_930x_sds_do_rx_calibration_2_3(struct rtpcs_serdes *sds) pr_info("%s: fgcal_gray = %d, fgcal_binary = %d\n", __func__, fgcal_gray, fgcal_binary); - offset_range = rtpcs_sds_read_bits(sds, 0x2e, 0x15, 15, 14); + offset_range = rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x15, 15, 14); if (offset_range == 3) { pr_info("%s: Foreground Calibration result marginal!", __func__); break; } offset_range++; - rtpcs_sds_write_bits(sds, 0x2e, 0x15, 15, 14, offset_range); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 15, 14, offset_range); rtpcs_930x_sds_do_rx_calibration_2_2(sds); } /* --- 1.2.3 */ @@ -2555,9 +2567,9 @@ static void rtpcs_930x_sds_rxcal_3_1(struct rtpcs_serdes *sds, if (hw_mode != RTPCS_SDS_MODE_10GBASER && hw_mode != RTPCS_SDS_MODE_1000BASEX && hw_mode != RTPCS_SDS_MODE_SGMII) - rtpcs_sds_write_bits(sds, 0x2e, 0xc, 8, 8, 0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xc, 8, 8, 0); - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 7, 7, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x0); rtpcs_930x_sds_rxcal_leq_manual(sds, false, 0); /* --- 1.3.1 */ @@ -2604,7 +2616,7 @@ static void rtpcs_930x_sds_rxcal_3_2(struct rtpcs_serdes *sds, if (dac_long_cable_offset) { rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, dac_long_cable_offset); - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 7, 7, + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, eq_hold_enabled); if (hw_mode == RTPCS_SDS_MODE_10GBASER) rtpcs_930x_sds_rxcal_leq_manual(sds, @@ -2612,12 +2624,12 @@ static void rtpcs_930x_sds_rxcal_3_2(struct rtpcs_serdes *sds, } else { if (sum10 >= 5) { rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, 3); - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 7, 7, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x1); if (hw_mode == RTPCS_SDS_MODE_10GBASER) rtpcs_930x_sds_rxcal_leq_manual(sds, true, avg10); } else { rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, 0); - rtpcs_sds_write_bits(sds, 0x2e, 0x17, 7, 7, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x1); if (hw_mode == RTPCS_SDS_MODE_10GBASER) rtpcs_930x_sds_rxcal_leq_manual(sds, true, avg10); } @@ -2732,9 +2744,9 @@ static void rtpcs_930x_sds_do_rx_calibration(struct rtpcs_serdes *sds, /* Do this only for 10GR mode */ if (hw_mode == RTPCS_SDS_MODE_10GBASER) { - latch_sts = rtpcs_sds_read_bits(sds, 0x4, 1, 2, 2); + latch_sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_0, 1, 2, 2); mdelay(1); - latch_sts = rtpcs_sds_read_bits(sds, 0x4, 1, 2, 2); + latch_sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_0, 1, 2, 2); if (latch_sts) { rtpcs_930x_sds_do_rx_calibration_dfe_disable(sds); rtpcs_930x_sds_do_rx_calibration_4(sds); @@ -2752,8 +2764,8 @@ static int rtpcs_930x_sds_sym_err_reset(struct rtpcs_serdes *sds, case RTPCS_SDS_MODE_10GBASER: case RTPCS_SDS_MODE_USXGMII_10GSXGMII: /* Read twice to clear */ - rtpcs_sds_read(sds, 0x5, 0x1); - rtpcs_sds_read(sds, 0x5, 0x1); + rtpcs_sds_read(sds, PAGE_TGR_STD_1, 0x1); + rtpcs_sds_read(sds, PAGE_TGR_STD_1, 0x1); return 0; case RTPCS_SDS_MODE_XSGMII: @@ -2767,23 +2779,23 @@ static int rtpcs_930x_sds_sym_err_reset(struct rtpcs_serdes *sds, for (channel = 0; channel < channels; channel++) { if (hw_mode == RTPCS_SDS_MODE_XSGMII) { - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x18, 2, 0, channel); - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x3, 15, 8, 0x0); - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x2, 15, 0, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x18, 2, 0, channel); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x3, 15, 8, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x2, 15, 0, 0x0); } else { - rtpcs_sds_write_bits(sds, 0x1, 0x18, 2, 0, channel); - rtpcs_sds_write_bits(sds, 0x1, 0x3, 15, 8, 0x0); - rtpcs_sds_write_bits(sds, 0x1, 0x2, 15, 0, 0x0); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x18, 2, 0, channel); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x3, 15, 8, 0x0); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x2, 15, 0, 0x0); } } if (channels > 1) { if (hw_mode == RTPCS_SDS_MODE_XSGMII) { - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x0, 15, 0, 0x0); - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x1, 15, 8, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x0, 15, 0, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x1, 15, 8, 0x0); } else { - rtpcs_sds_write_bits(sds, 0x1, 0x0, 15, 0, 0x0); - rtpcs_sds_write_bits(sds, 0x1, 0x1, 15, 8, 0x0); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x0, 15, 0, 0x0); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 0x1, 15, 8, 0x0); } } @@ -2798,8 +2810,8 @@ static u32 rtpcs_930x_sds_sym_err_get(struct rtpcs_serdes *sds, switch (hw_mode) { case RTPCS_SDS_MODE_QSGMII: case RTPCS_SDS_MODE_XSGMII: - v = rtpcs_sds_read_bits(sds, 0x1, 0x1, 15, 8) << 16; /* ALL_SYMBOLERR_CNT_NEW_23_16 */ - v |= rtpcs_sds_read_bits(sds, 0x1, 0x0, 15, 0); /* ALL_SYMBOLERR_CNT_NEW_15_0 */ + v = rtpcs_sds_read_bits(sds, PAGE_SDS_EXT, 0x1, 15, 8) << 16; /* ALL_SYMBOLERR_CNT_NEW_23_16 */ + v |= rtpcs_sds_read_bits(sds, PAGE_SDS_EXT, 0x0, 15, 0); /* ALL_SYMBOLERR_CNT_NEW_15_0 */ break; case RTPCS_SDS_MODE_USXGMII_10GQXGMII: @@ -2809,15 +2821,15 @@ static u32 rtpcs_930x_sds_sym_err_get(struct rtpcs_serdes *sds, case RTPCS_SDS_MODE_SGMII: case RTPCS_SDS_MODE_10GBASER: case RTPCS_SDS_MODE_USXGMII_10GSXGMII: - v = rtpcs_sds_read(sds, 0x5, 0x1); + v = rtpcs_sds_read(sds, PAGE_TGR_STD_1, 0x1); v &= 0xff; break; default: - rtpcs_sds_write_bits(sds, 0x1, 24, 2, 0, 0); + rtpcs_sds_write_bits(sds, PAGE_SDS_EXT, 24, 2, 0, 0); - v = rtpcs_sds_read_bits(sds, 0x1, 0x3, 15, 8) << 16; /* MUX_SYMBOLERR_CNT_NEW_23_16 */ - v |= rtpcs_sds_read_bits(sds, 0x1, 0x2, 15, 0); /* MUX_SYMBOLERR_CNT_NEW_15_0 */ + v = rtpcs_sds_read_bits(sds, PAGE_SDS_EXT, 0x3, 15, 8) << 16; /* MUX_SYMBOLERR_CNT_NEW_23_16 */ + v |= rtpcs_sds_read_bits(sds, PAGE_SDS_EXT, 0x2, 15, 0); /* MUX_SYMBOLERR_CNT_NEW_15_0 */ } return v; @@ -2865,8 +2877,8 @@ static int rtpcs_930x_sds_10g_idle(struct rtpcs_serdes *sds) timeout = ktime_add_us(ktime_get(), 10000); /* timeout after 10 msecs */ do { - rtpcs_sds_write(even_sds, 0x1f, 0x2, 53); - busy = rtpcs_sds_read_bits(even_sds, 0x1f, 0x14, bit, bit); + rtpcs_sds_write(even_sds, PAGE_WDIG, 0x2, 53); + busy = rtpcs_sds_read_bits(even_sds, PAGE_WDIG, 0x14, bit, bit); if (busy < 0) return busy; @@ -2891,73 +2903,101 @@ static int rtpcs_930x_sds_config_polarity(struct rtpcs_serdes *sds, unsigned int /* 10GR */ val = (tx_val << 1) | rx_val; - ret = rtpcs_sds_write_bits(sds, 0x6, 0x2, 14, 13, val); + ret = rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x2, 14, 13, val); if (ret) return ret; /* 1G */ val = (rx_val << 1) | tx_val; - return rtpcs_sds_write_bits(sds, 0x0, 0x0, 9, 8, val); + return rtpcs_sds_write_bits(sds, PAGE_SDS, 0x0, 9, 8, val); } static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_ana_com[] = { - {0x21, 0x03, 0x8206}, {0x21, 0x05, 0x40B0}, {0x21, 0x06, 0x0010}, {0x21, 0x07, 0xF09F}, - {0x21, 0x0A, 0x0003}, {0x21, 0x0B, 0x0005}, {0x21, 0x0C, 0x0007}, {0x21, 0x0D, 0x6009}, - {0x21, 0x0E, 0x0000}, {0x21, 0x0F, 0x0008} + {PAGE_ANA_COM, 0x03, 0x8206}, {PAGE_ANA_COM, 0x05, 0x40B0}, + {PAGE_ANA_COM, 0x06, 0x0010}, {PAGE_ANA_COM, 0x07, 0xF09F}, + {PAGE_ANA_COM, 0x0A, 0x0003}, {PAGE_ANA_COM, 0x0B, 0x0005}, + {PAGE_ANA_COM, 0x0C, 0x0007}, {PAGE_ANA_COM, 0x0D, 0x6009}, + {PAGE_ANA_COM, 0x0E, 0x0000}, {PAGE_ANA_COM, 0x0F, 0x0008} }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_ana_1g[] = { - {0x24, 0x00, 0x0668}, {0x24, 0x02, 0xD020}, {0x24, 0x06, 0xC000}, {0x24, 0x0B, 0x1892}, - {0x24, 0x0F, 0xFFDF}, {0x24, 0x12, 0x03C4}, {0x24, 0x13, 0x027F}, {0x24, 0x14, 0x1311}, - {0x24, 0x16, 0x00C9}, {0x24, 0x17, 0xA100}, {0x24, 0x1A, 0x0001}, {0x24, 0x1C, 0x0400}, - {0x25, 0x00, 0x820F}, {0x25, 0x01, 0x0300}, {0x25, 0x02, 0x1017}, {0x25, 0x03, 0xFFDF}, - {0x25, 0x05, 0x7F7C}, {0x25, 0x07, 0x8100}, {0x25, 0x08, 0x0001}, {0x25, 0x09, 0xFFD4}, - {0x25, 0x0A, 0x7C2F}, {0x25, 0x0E, 0x003F}, {0x25, 0x0F, 0x0121}, {0x25, 0x10, 0x0020}, - {0x25, 0x11, 0x8840} + {PAGE_ANA_1G2, 0x00, 0x0668}, {PAGE_ANA_1G2, 0x02, 0xD020}, + {PAGE_ANA_1G2, 0x06, 0xC000}, {PAGE_ANA_1G2, 0x0B, 0x1892}, + {PAGE_ANA_1G2, 0x0F, 0xFFDF}, {PAGE_ANA_1G2, 0x12, 0x03C4}, + {PAGE_ANA_1G2, 0x13, 0x027F}, {PAGE_ANA_1G2, 0x14, 0x1311}, + {PAGE_ANA_1G2, 0x16, 0x00C9}, {PAGE_ANA_1G2, 0x17, 0xA100}, + {PAGE_ANA_1G2, 0x1A, 0x0001}, {PAGE_ANA_1G2, 0x1C, 0x0400}, + {PAGE_ANA_1G2_EXT, 0x00, 0x820F}, {PAGE_ANA_1G2_EXT, 0x01, 0x0300}, + {PAGE_ANA_1G2_EXT, 0x02, 0x1017}, {PAGE_ANA_1G2_EXT, 0x03, 0xFFDF}, + {PAGE_ANA_1G2_EXT, 0x05, 0x7F7C}, {PAGE_ANA_1G2_EXT, 0x07, 0x8100}, + {PAGE_ANA_1G2_EXT, 0x08, 0x0001}, {PAGE_ANA_1G2_EXT, 0x09, 0xFFD4}, + {PAGE_ANA_1G2_EXT, 0x0A, 0x7C2F}, {PAGE_ANA_1G2_EXT, 0x0E, 0x003F}, + {PAGE_ANA_1G2_EXT, 0x0F, 0x0121}, {PAGE_ANA_1G2_EXT, 0x10, 0x0020}, + {PAGE_ANA_1G2_EXT, 0x11, 0x8840} }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_ana_3g[] = { - {0x28, 0x00, 0x0668}, {0x28, 0x02, 0xD020}, {0x28, 0x06, 0xC000}, {0x28, 0x0B, 0x1892}, - {0x28, 0x0F, 0xFFDF}, {0x28, 0x12, 0x01C4}, {0x28, 0x13, 0x027F}, {0x28, 0x14, 0x1311}, - {0x28, 0x16, 0x00C9}, {0x28, 0x17, 0xA100}, {0x28, 0x1A, 0x0001}, {0x28, 0x1C, 0x0400}, - {0x29, 0x00, 0x820F}, {0x29, 0x01, 0x0300}, {0x29, 0x02, 0x1017}, {0x29, 0x03, 0xFFDF}, - {0x29, 0x05, 0x7F7C}, {0x29, 0x07, 0x8100}, {0x29, 0x08, 0x0001}, {0x29, 0x09, 0xFFD4}, - {0x29, 0x0A, 0x7C2F}, {0x29, 0x0E, 0x003F}, {0x29, 0x0F, 0x0121}, {0x29, 0x10, 0x0020}, - {0x29, 0x11, 0x8840}, + {PAGE_ANA_3G1, 0x00, 0x0668}, {PAGE_ANA_3G1, 0x02, 0xD020}, + {PAGE_ANA_3G1, 0x06, 0xC000}, {PAGE_ANA_3G1, 0x0B, 0x1892}, + {PAGE_ANA_3G1, 0x0F, 0xFFDF}, {PAGE_ANA_3G1, 0x12, 0x01C4}, + {PAGE_ANA_3G1, 0x13, 0x027F}, {PAGE_ANA_3G1, 0x14, 0x1311}, + {PAGE_ANA_3G1, 0x16, 0x00C9}, {PAGE_ANA_3G1, 0x17, 0xA100}, + {PAGE_ANA_3G1, 0x1A, 0x0001}, {PAGE_ANA_3G1, 0x1C, 0x0400}, + {PAGE_ANA_3G1_EXT, 0x00, 0x820F}, {PAGE_ANA_3G1_EXT, 0x01, 0x0300}, + {PAGE_ANA_3G1_EXT, 0x02, 0x1017}, {PAGE_ANA_3G1_EXT, 0x03, 0xFFDF}, + {PAGE_ANA_3G1_EXT, 0x05, 0x7F7C}, {PAGE_ANA_3G1_EXT, 0x07, 0x8100}, + {PAGE_ANA_3G1_EXT, 0x08, 0x0001}, {PAGE_ANA_3G1_EXT, 0x09, 0xFFD4}, + {PAGE_ANA_3G1_EXT, 0x0A, 0x7C2F}, {PAGE_ANA_3G1_EXT, 0x0E, 0x003F}, + {PAGE_ANA_3G1_EXT, 0x0F, 0x0121}, {PAGE_ANA_3G1_EXT, 0x10, 0x0020}, + {PAGE_ANA_3G1_EXT, 0x11, 0x8840}, }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_ana_10g[] = { - {0x2E, 0x00, 0xA668}, {0x2E, 0x01, 0x2088}, {0x2E, 0x02, 0xD020}, {0x2E, 0x06, 0xC000}, - {0x2E, 0x0B, 0x1892}, {0x2E, 0x0F, 0xFFDF}, {0x2E, 0x11, 0x8280}, {0x2E, 0x12, 0x0044}, - {0x2E, 0x13, 0x027F}, {0x2E, 0x14, 0x1311}, {0x2E, 0x17, 0xA100}, {0x2E, 0x1A, 0x0001}, - {0x2E, 0x1C, 0x0400}, {0x2F, 0x00, 0x820F}, {0x2F, 0x01, 0x0300}, {0x2F, 0x02, 0x1217}, - {0x2F, 0x03, 0xFFDF}, {0x2F, 0x05, 0x7F7C}, {0x2F, 0x07, 0x80C4}, {0x2F, 0x08, 0x0001}, - {0x2F, 0x09, 0xFFD4}, {0x2F, 0x0A, 0x7C2F}, {0x2F, 0x0E, 0x003F}, {0x2F, 0x0F, 0x0121}, - {0x2F, 0x10, 0x0020}, {0x2F, 0x11, 0x8840}, + {PAGE_ANA_10G, 0x00, 0xA668}, {PAGE_ANA_10G, 0x01, 0x2088}, + {PAGE_ANA_10G, 0x02, 0xD020}, {PAGE_ANA_10G, 0x06, 0xC000}, + {PAGE_ANA_10G, 0x0B, 0x1892}, {PAGE_ANA_10G, 0x0F, 0xFFDF}, + {PAGE_ANA_10G, 0x11, 0x8280}, {PAGE_ANA_10G, 0x12, 0x0044}, + {PAGE_ANA_10G, 0x13, 0x027F}, {PAGE_ANA_10G, 0x14, 0x1311}, + {PAGE_ANA_10G, 0x17, 0xA100}, {PAGE_ANA_10G, 0x1A, 0x0001}, + {PAGE_ANA_10G, 0x1C, 0x0400}, + {PAGE_ANA_10G_EXT, 0x00, 0x820F}, {PAGE_ANA_10G_EXT, 0x01, 0x0300}, + {PAGE_ANA_10G_EXT, 0x02, 0x1217}, {PAGE_ANA_10G_EXT, 0x03, 0xFFDF}, + {PAGE_ANA_10G_EXT, 0x05, 0x7F7C}, {PAGE_ANA_10G_EXT, 0x07, 0x80C4}, + {PAGE_ANA_10G_EXT, 0x08, 0x0001}, {PAGE_ANA_10G_EXT, 0x09, 0xFFD4}, + {PAGE_ANA_10G_EXT, 0x0A, 0x7C2F}, {PAGE_ANA_10G_EXT, 0x0E, 0x003F}, + {PAGE_ANA_10G_EXT, 0x0F, 0x0121}, {PAGE_ANA_10G_EXT, 0x10, 0x0020}, + {PAGE_ANA_10G_EXT, 0x11, 0x8840}, }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_usxgmii_xsgmii[] = { - {0x2E, 0x12, 0x0484}, {0x2F, 0x02, 0x1017}, {0x2F, 0x07, 0x8104} + {PAGE_ANA_10G, 0x12, 0x0484}, + {PAGE_ANA_10G_EXT, 0x02, 0x1017}, {PAGE_ANA_10G_EXT, 0x07, 0x8104} }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_5g_qsgmii[] = { - {0x21, 0x00, 0x3C91},{0x21, 0x02, 0xB602},{0x21, 0x07, 0xFA66},{0x21, 0x0A, 0xDF40}, - {0x2A, 0x02, 0x35A1},{0x2A, 0x03, 0x6960}, + {PAGE_ANA_COM, 0x00, 0x3C91}, {PAGE_ANA_COM, 0x02, 0xB602}, + {PAGE_ANA_COM, 0x07, 0xFA66}, {PAGE_ANA_COM, 0x0A, 0xDF40}, + {PAGE_ANA_5G0, 0x02, 0x35A1}, {PAGE_ANA_5G0, 0x03, 0x6960}, }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_final_even[] = { - {0x2B, 0x13, 0x0050}, {0x2B, 0x18, 0x8E88}, {0x2B, 0x19, 0x4902}, {0x2B, 0x1D, 0x2501}, - {0x2D, 0x13, 0x0050}, {0x2D, 0x17, 0x4109}, {0x2D, 0x18, 0x8E88}, {0x2D, 0x19, 0x4902}, - {0x2D, 0x1C, 0x1109}, {0x2D, 0x1D, 0x2641}, {0x2F, 0x13, 0x0050}, {0x2F, 0x18, 0x8E88}, - {0x2F, 0x19, 0x4902}, {0x2F, 0x1D, 0x66E1}, + {PAGE_ANA_5G0_EXT, 0x13, 0x0050}, {PAGE_ANA_5G0_EXT, 0x18, 0x8E88}, + {PAGE_ANA_5G0_EXT, 0x19, 0x4902}, {PAGE_ANA_5G0_EXT, 0x1D, 0x2501}, + + {PAGE_ANA_6G2_EXT, 0x13, 0x0050}, {PAGE_ANA_6G2_EXT, 0x17, 0x4109}, + {PAGE_ANA_6G2_EXT, 0x18, 0x8E88}, {PAGE_ANA_6G2_EXT, 0x19, 0x4902}, + {PAGE_ANA_6G2_EXT, 0x1C, 0x1109}, {PAGE_ANA_6G2_EXT, 0x1D, 0x2641}, + + {PAGE_ANA_10G_EXT, 0x13, 0x0050}, {PAGE_ANA_10G_EXT, 0x18, 0x8E88}, + {PAGE_ANA_10G_EXT, 0x19, 0x4902}, {PAGE_ANA_10G_EXT, 0x1D, 0x66E1}, }; static const struct rtpcs_sds_config rtpcs_930x_sds_cfg_final_odd[] = { - {0x2B, 0x13, 0x3D87}, {0x2B, 0x14, 0x3108}, - {0x2D, 0x13, 0x3C87}, {0x2D, 0x14, 0x1808} + {PAGE_ANA_5G0_EXT, 0x13, 0x3D87}, {PAGE_ANA_5G0_EXT, 0x14, 0x3108}, + {PAGE_ANA_6G2_EXT, 0x13, 0x3C87}, {PAGE_ANA_6G2_EXT, 0x14, 0x1808} }; static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) @@ -2980,10 +3020,10 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd if (hw_mode != RTPCS_SDS_MODE_USXGMII_10GSXGMII && hw_mode != RTPCS_SDS_MODE_USXGMII_10GQXGMII) { if (is_xsgmii) - rtpcs_sds_xsg_write(sds, 0x00, 0x0E, 0x3053); + rtpcs_sds_xsg_write(sds, PAGE_SDS, 0x0E, 0x3053); else { - rtpcs_sds_write(sds, 0x00, 0x0E, 0x3053); - rtpcs_sds_write(sds, 0x01, 0x14, 0x0100); + rtpcs_sds_write(sds, PAGE_SDS, 0x0E, 0x3053); + rtpcs_sds_write(sds, PAGE_SDS_EXT, 0x14, 0x0100); } } @@ -3002,9 +3042,9 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd break; case RTPCS_SDS_MODE_10GBASER: - rtpcs_sds_write(sds, 0x06, 0x0D, 0x0F00); - rtpcs_sds_write(sds, 0x06, 0x00, 0x0000); - rtpcs_sds_write(sds, 0x06, 0x01, 0xC800); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x0D, 0x0F00); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x00, 0x0000); + rtpcs_sds_write(sds, PAGE_TGR_PRO_0, 0x01, 0xC800); /* * TODO: Do the 1G and 3G sequences need to be applied? The SDK usually * uses a 10GR-1000BX automatic mode covering all speeds. But in Linux, @@ -3026,7 +3066,7 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd if (ret < 0) return ret; - rtpcs_sds_write(sds, 0x2F, 0x14, 0xE008); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x14, 0xE008); break; case RTPCS_SDS_MODE_2500BASEX: @@ -3075,7 +3115,7 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd return ret; if (hw_mode == RTPCS_SDS_MODE_10GBASER && is_even_sds) - rtpcs_sds_write(sds, 0x2F, 0x1D, 0x76E1); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x1D, 0x76E1); return 0; } @@ -3088,7 +3128,7 @@ static int rtpcs_930x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_ * TODO: this is unconditional regardless of hw_mode; needs mode-aware * handling. */ - rtpcs_sds_write_bits(sds, 0x1f, 11, 1, 1, 1); + rtpcs_sds_write_bits(sds, PAGE_WDIG, 11, 1, 1, 1); rtpcs_930x_sds_tx_config(sds, hw_mode); return 0; @@ -3156,17 +3196,17 @@ static int rtpcs_930x_sds_probe(struct rtpcs_serdes *sds) * An XSG write operates on digital SDS 1 and digital SDS 2. Map that to the * page ranges accordingly. */ -static int rtpcs_931x_sds_op_xsg_write(struct rtpcs_serdes *sds, int page, int regnum, +static int rtpcs_931x_sds_op_xsg_write(struct rtpcs_serdes *sds, enum rtpcs_page page, int regnum, int bithigh, int bitlow, u16 value) { int ret; - ret = __rtpcs_sds_write_raw(sds->ctrl, sds->id, page + 0x40, regnum, bithigh, bitlow, + ret = __rtpcs_sds_write_raw(sds->ctrl, sds->id, DIGI_1(page), regnum, bithigh, bitlow, value); if (ret) return ret; - return __rtpcs_sds_write_raw(sds->ctrl, sds->id, page + 0x80, regnum, bithigh, bitlow, + return __rtpcs_sds_write_raw(sds->ctrl, sds->id, DIGI_2(page), regnum, bithigh, bitlow, value); } @@ -3178,13 +3218,13 @@ static int rtpcs_931x_sds_fiber_get_symerr(struct rtpcs_serdes *sds, switch (hw_mode) { case RTPCS_SDS_MODE_10GBASER: - symerr = rtpcs_sds_read_bits(sds, 0x5, 0x1, 7, 0); + symerr = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0x1, 7, 0); break; case RTPCS_SDS_MODE_1000BASEX: - rtpcs_sds_write_bits(sds, 0x41, 0x18, 2, 0, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x18, 2, 0, 0x0); - val = rtpcs_sds_read_bits(sds, 0x41, 0x3, 15, 8); - val2 = rtpcs_sds_read_bits(sds, 0x41, 0x2, 15, 0); + val = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x3, 15, 8); + val2 = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x2, 15, 0); symerr = (val << 16) | val2; break; default: @@ -3201,22 +3241,22 @@ static void rtpcs_931x_sds_clear_symerr(struct rtpcs_serdes *sds, case RTPCS_SDS_MODE_SGMII: case RTPCS_SDS_MODE_XSGMII: for (int i = 0; i < 4; ++i) { - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x18, 2, 0, i); - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x3, 15, 8, 0x0); - rtpcs_sds_xsg_write(sds, 0x1, 0x2, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x18, 2, 0, i); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x3, 15, 8, 0x0); + rtpcs_sds_xsg_write(sds, PAGE_SDS_EXT, 0x2, 0x0); } - rtpcs_sds_xsg_write(sds, 0x1, 0x0, 0x0); - rtpcs_sds_xsg_write_bits(sds, 0x1, 0x1, 15, 8, 0x0); + rtpcs_sds_xsg_write(sds, PAGE_SDS_EXT, 0x0, 0x0); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS_EXT, 0x1, 15, 8, 0x0); break; case RTPCS_SDS_MODE_1000BASEX: - rtpcs_sds_write_bits(sds, 0x41, 0x18, 2, 0, 0x0); - rtpcs_sds_write_bits(sds, 0x41, 0x3, 15, 8, 0x0); - rtpcs_sds_write_bits(sds, 0x41, 0x2, 15, 0, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x18, 2, 0, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x3, 15, 8, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x2, 15, 0, 0x0); break; case RTPCS_SDS_MODE_10GBASER: /* to be verified: clear on read? */ - rtpcs_sds_read_bits(sds, 0x5, 0x1, 7, 0); + rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0x1, 7, 0); break; case RTPCS_SDS_MODE_OFF: default: @@ -3240,17 +3280,17 @@ static void rtpcs_931x_sds_clear_symerr(struct rtpcs_serdes *sds, */ static int rtpcs_931x_sds_reset_leq_dfe(struct rtpcs_serdes *sds) { - rtpcs_sds_write_bits(sds, 0x2e, 0xd, 6, 0, 0x0); /* [6:2] LEQ gain */ - rtpcs_sds_write_bits(sds, 0x2e, 0xd, 7, 7, 0x1); /* LEQ manual 1=true,0=false */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xd, 6, 0, 0x0); /* [6:2] LEQ gain */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xd, 7, 7, 0x1); /* LEQ manual 1=true,0=false */ - rtpcs_sds_write_bits(sds, 0x2e, 0x1c, 5, 0, 0x1e); /* TAP0 */ - rtpcs_sds_write_bits(sds, 0x2e, 0x1d, 11, 0, 0x0); /* TAP1 [11:6] ODD | [5:0] EVEN */ - rtpcs_sds_write_bits(sds, 0x2e, 0x1f, 11, 0, 0x0); /* TAP2 [11:6] ODD | [5:0] EVEN */ - rtpcs_sds_write_bits(sds, 0x2f, 0x0, 11, 0, 0x0); /* TAP3 [11:6] ODD | [5:0] EVEN */ - rtpcs_sds_write_bits(sds, 0x2f, 0x1, 11, 0, 0x0); /* TAP4 [11:6] ODD | [5:0] EVEN */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1c, 5, 0, 0x1e); /* TAP0 */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 11, 0, 0x0); /* TAP1 [11:6] ODD | [5:0] EVEN */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1f, 11, 0, 0x0); /* TAP2 [11:6] ODD | [5:0] EVEN */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0, 11, 0, 0x0); /* TAP3 [11:6] ODD | [5:0] EVEN */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x1, 11, 0, 0x0); /* TAP4 [11:6] ODD | [5:0] EVEN */ - rtpcs_sds_write_bits(sds, 0x2e, 0xf, 12, 6, 0x7f); /* set manual mode */ - rtpcs_sds_write(sds, 0x2f, 0x12, 0xaaa); /* [11:8] VTHN | [7:4] VTHP */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xf, 12, 6, 0x7f); /* set manual mode */ + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x12, 0xaaa); /* [11:8] VTHN | [7:4] VTHP */ return 0; } @@ -3342,15 +3382,15 @@ static void rtpcs_931x_sds_rx_reset(struct rtpcs_serdes *sds) if (sds->type != RTPCS_SDS_TYPE_10G) return; - rtpcs_sds_write(sds, 0x2e, 0x12, 0x2740); - rtpcs_sds_write(sds, 0x2f, 0x0, 0x0); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ - rtpcs_sds_write(sds, 0x2f, 0x2, 0x2010); - rtpcs_sds_write(sds, 0x20, 0x0, 0xc10); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x12, 0x2740); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x0, 0x0); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x2, 0x2010); + rtpcs_sds_write(sds, PAGE_ANA_MISC, 0x0, 0xc10); - rtpcs_sds_write(sds, 0x2e, 0x12, 0x27c0); - rtpcs_sds_write(sds, 0x2f, 0x0, 0xc000); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ - rtpcs_sds_write(sds, 0x2f, 0x2, 0x6010); - rtpcs_sds_write(sds, 0x20, 0x0, 0xc30); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x12, 0x27c0); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x0, 0xc000); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x2, 0x6010); + rtpcs_sds_write(sds, PAGE_ANA_MISC, 0x0, 0xc30); mdelay(50); } @@ -3360,12 +3400,12 @@ static int rtpcs_931x_sds_cmu_page_get(enum rtpcs_sds_mode hw_mode) switch (hw_mode) { case RTPCS_SDS_MODE_SGMII: case RTPCS_SDS_MODE_1000BASEX: - return 0x24; /* ANA_1G */ + return PAGE_ANA_1G2; case RTPCS_SDS_MODE_2500BASEX: - return 0x28; /* ANA_3G */ + return PAGE_ANA_3G1; case RTPCS_SDS_MODE_QSGMII: - return 0x2a; /* ANA_5G/6G */ - // return 0x34; + return PAGE_ANA_5G0; + // return PAGE_ANA_6G0; case RTPCS_SDS_MODE_XSGMII: case RTPCS_SDS_MODE_USXGMII_10GSXGMII: case RTPCS_SDS_MODE_USXGMII_10GDXGMII: @@ -3374,7 +3414,7 @@ static int rtpcs_931x_sds_cmu_page_get(enum rtpcs_sds_mode hw_mode) case RTPCS_SDS_MODE_USXGMII_5GDXGMII: case RTPCS_SDS_MODE_USXGMII_2_5GSXGMII: case RTPCS_SDS_MODE_10GBASER: - return 0x2e; /* ANA_10G */ + return PAGE_ANA_10G; default: return -ENOTSUPP; } @@ -3418,7 +3458,7 @@ static int rtpcs_931x_sds_set_pll_select(struct rtpcs_serdes *sds, enum rtpcs_sd */ val = (pll == RTPCS_SDS_PLL_TYPE_LC) ? 0x3 : 0x1; frc_lc_mode_bit = (sds == even_sds) ? 4 : 6; - ret = rtpcs_sds_write_bits(even_sds, 0x20, 0x12, frc_lc_mode_bit + 1, + ret = rtpcs_sds_write_bits(even_sds, PAGE_ANA_MISC, 0x12, frc_lc_mode_bit + 1, frc_lc_mode_bit, val); if (ret < 0) return ret; @@ -3475,23 +3515,23 @@ static int rtpcs_931x_sds_link_sts_get(struct rtpcs_serdes *sds) switch (sds->hw_mode) { case RTPCS_SDS_MODE_XSGMII: - sts = rtpcs_sds_read_bits(sds, 0x41, 29, 8, 0); - sts1 = rtpcs_sds_read_bits(sds, 0x81, 29, 8, 0); - latch_sts = rtpcs_sds_read_bits(sds, 0x41, 30, 8, 0); - latch_sts1 = rtpcs_sds_read_bits(sds, 0x81, 30, 8, 0); + sts = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 29, 8, 0); + sts1 = rtpcs_sds_read_bits(sds, DIGI_2(PAGE_SDS_EXT), 29, 8, 0); + latch_sts = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 30, 8, 0); + latch_sts1 = rtpcs_sds_read_bits(sds, DIGI_2(PAGE_SDS_EXT), 30, 8, 0); break; case RTPCS_SDS_MODE_SGMII: case RTPCS_SDS_MODE_2500BASEX: - sts = rtpcs_sds_read_bits(sds, 0x41, 29, 8, 0); - latch_sts = rtpcs_sds_read_bits(sds, 0x41, 30, 8, 0); + sts = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 29, 8, 0); + latch_sts = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_SDS_EXT), 30, 8, 0); break; default: - sts = rtpcs_sds_read_bits(sds, 0x5, 0, 12, 12); - latch_sts = rtpcs_sds_read_bits(sds, 0x4, 1, 2, 2); - latch_sts1 = rtpcs_sds_read_bits(sds, 0x42, 1, 2, 2); - sts1 = rtpcs_sds_read_bits(sds, 0x42, 1, 2, 2); + sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_1, 0, 12, 12); + latch_sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_0, 1, 2, 2); + latch_sts1 = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_FIB), 1, 2, 2); + sts1 = rtpcs_sds_read_bits(sds, DIGI_1(PAGE_FIB), 1, 2, 2); } pr_info("%s: serdes %d sts %d, sts1 %d, latch_sts %d, latch_sts1 %d\n", __func__, @@ -3510,13 +3550,13 @@ static int rtpcs_931x_sds_config_polarity(struct rtpcs_serdes *sds, unsigned int /* 10gr_*_inv */ val = (tx_val << 1) | rx_val; - ret = rtpcs_sds_write_bits(sds, 0x6, 0x2, 14, 13, val); + ret = rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0x2, 14, 13, val); if (ret) return ret; /* xsg_*_inv */ val = (rx_val << 1) | tx_val; - return rtpcs_sds_xsg_write_bits(sds, 0x0, 0x0, 9, 8, val); + return rtpcs_sds_xsg_write_bits(sds, PAGE_SDS, 0x0, 9, 8, val); } static const struct rtpcs_sds_tx_config rtpcs_931x_sds_tx_cfg_v1[] = { @@ -3571,7 +3611,7 @@ static int rtpcs_931x_sds_config_tx_amps(struct rtpcs_serdes *sds, u8 pre_amp, u cfg_val = FIELD_PREP(RTPCS_931X_SDS_PRE_AMP_MASK, pre_amp) | FIELD_PREP(RTPCS_931X_SDS_MAIN_AMP_MASK, main_amp) | FIELD_PREP(RTPCS_931X_SDS_POST_AMP_MASK, post_amp); - ret = rtpcs_sds_write(sds, 0x2e, 0x1, cfg_val); + ret = rtpcs_sds_write(sds, PAGE_ANA_10G, 0x1, cfg_val); if (ret < 0) return ret; @@ -3581,7 +3621,7 @@ static int rtpcs_931x_sds_config_tx_amps(struct rtpcs_serdes *sds, u8 pre_amp, u if (pre_amp) en_val |= BIT(1); - return rtpcs_sds_write_bits(sds, 0x2e, 0x0, 1, 0, en_val); + return rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0, 1, 0, en_val); } /** @@ -3640,10 +3680,10 @@ static int rtpcs_931x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_ * here and later deactivated for non-10G and XSGMII. * (from DMS1250 SDK) */ - rtpcs_sds_write_bits(sds, 0x5f, 0x1, 0, 0, 0x1); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_WDIG), 0x1, 0, 0, 0x1); /* from _phy_rtl9310_sds_init */ - rtpcs_sds_write_bits(sds, 0x2e, 0xe, 13, 11, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xe, 13, 11, 0x0); if (hw_mode != RTPCS_SDS_MODE_XSGMII) rtpcs_931x_sds_reset_leq_dfe(sds); @@ -3654,13 +3694,13 @@ static int rtpcs_931x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_ * - the last one slightly differs in the value. Something is taken into power down * while rx_reset doesn't do this. */ - rtpcs_sds_write(sds, 0x2e, 0x12, 0x2740); - rtpcs_sds_write(sds, 0x2f, 0x0, 0x0); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ - rtpcs_sds_write(sds, 0x2f, 0x2, 0x2010); - rtpcs_sds_write(sds, 0x20, 0x0, 0xcd1); /* from 930x: [7:6] POWER_DOWN OF ?? */ + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x12, 0x2740); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x0, 0x0); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x2, 0x2010); + rtpcs_sds_write(sds, PAGE_ANA_MISC, 0x0, 0xcd1); /* from 930x: [7:6] POWER_DOWN OF ?? */ - rtpcs_sds_write_bits(sds, 0x2e, 0xf, 5, 0, 0x4); - rtpcs_sds_write_bits(sds, 0x2a, 0x12, 7, 6, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xf, 5, 0, 0x4); + rtpcs_sds_write_bits(sds, PAGE_ANA_5G0, 0x12, 7, 6, 0x1); if (sds_media == RTPCS_SDS_MEDIA_NONE) return 0; @@ -3681,44 +3721,44 @@ static int rtpcs_931x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_ hw_mode == RTPCS_SDS_MODE_XSGMII || rtpcs_sds_mode_is_usxgmii(hw_mode)); - rtpcs_sds_write_bits(sds, 0x20, 0x0, 11, 10, 0x0); - rtpcs_sds_write_bits(sds, 0x2a, 0x7, 15, 15, is_dac ? 0x1 : 0x0); - rtpcs_sds_write_bits(sds, 0x20, 0x0, 11, 10, 0x3); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x0, 11, 10, 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_5G0, 0x7, 15, 15, is_dac ? 0x1 : 0x0); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x0, 11, 10, 0x3); switch (sds_media) { case RTPCS_SDS_MEDIA_DAC_SHORT: case RTPCS_SDS_MEDIA_DAC_LONG: - rtpcs_sds_write(sds, 0x21, 0x19, 0xf0a5); /* from XS1930-10 SDK */ - rtpcs_sds_write(even_sds, 0x2e, 0x8, 0x02a0); /* [10:7] impedance */ + rtpcs_sds_write(sds, PAGE_ANA_COM, 0x19, 0xf0a5); /* from XS1930-10 SDK */ + rtpcs_sds_write(even_sds, PAGE_ANA_10G, 0x8, 0x02a0); /* [10:7] impedance */ break; case RTPCS_SDS_MEDIA_FIBER: if (is_10g) - rtpcs_sds_write_bits(sds, 0x2e, 0xf, 5, 0, 0x2); /* from DMS1250 SDK */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xf, 5, 0, 0x2); /* from DMS1250 SDK */ fallthrough; default: - rtpcs_sds_write(sds, 0x21, 0x19, 0xf0f0); /* from XS1930 SDK */ - rtpcs_sds_write(even_sds, 0x2e, 0x8, 0x0294); /* [10:7] TX impedance */ + rtpcs_sds_write(sds, PAGE_ANA_COM, 0x19, 0xf0f0); /* from XS1930 SDK */ + rtpcs_sds_write(even_sds, PAGE_ANA_10G, 0x8, 0x0294); /* [10:7] TX impedance */ break; } /* CFG_LINKDW_SEL? (same semantics as 930x) */ - rtpcs_sds_write_bits(sds, 0x6, 0xd, 6, 6, is_dac ? 0x0 : 0x1); + rtpcs_sds_write_bits(sds, PAGE_TGR_PRO_0, 0xd, 6, 6, is_dac ? 0x0 : 0x1); if (is_10g) { - rtpcs_sds_write(sds, 0x2e, 0x12, 0x27c0); - rtpcs_sds_write(sds, 0x2f, 0x0, 0xc000); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ - rtpcs_sds_write(sds, 0x2f, 0x2, 0x6010); + rtpcs_sds_write(sds, PAGE_ANA_10G, 0x12, 0x27c0); + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x0, 0xc000); /* [11:6] DFE_TAP3_ODD | [5:0] DFE_TAP3_EVEN */ + rtpcs_sds_write(sds, PAGE_ANA_10G_EXT, 0x2, 0x6010); } /* FIXME: is this redundant with the writes below? */ - rtpcs_sds_write(sds, 0x20, 0x0, 0xc30); /* from 930x: [7:6] POWER_DOWN OF ?? */ - rtpcs_sds_write_bits(sds, 0x20, 0x0, 9, 0, 0x30); - rtpcs_sds_write_bits(sds, 0x2a, 0x12, 7, 6, 0x3); + rtpcs_sds_write(sds, PAGE_ANA_MISC, 0x0, 0xc30); /* from 930x: [7:6] POWER_DOWN OF ?? */ + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x0, 9, 0, 0x30); + rtpcs_sds_write_bits(sds, PAGE_ANA_5G0, 0x12, 7, 6, 0x3); - rtpcs_sds_write_bits(sds, 0x20, 0x0, 11, 10, 0x1); - rtpcs_sds_write_bits(sds, 0x20, 0x0, 11, 10, 0x3); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x0, 11, 10, 0x1); + rtpcs_sds_write_bits(sds, PAGE_ANA_MISC, 0x0, 11, 10, 0x3); /* clear pending SerDes RX idle interrupt flag */ regmap_write_bits(sds->ctrl->map, RTPCS_931X_ISR_SERDES_RXIDLE, @@ -3726,17 +3766,17 @@ static int rtpcs_931x_sds_config_media(struct rtpcs_serdes *sds, enum rtpcs_sds_ /* Gating as mentioned above, deactivated here for non-10G and XSGMII */ if (!is_10g || hw_mode == RTPCS_SDS_MODE_XSGMII) - rtpcs_sds_write_bits(sds, 0x5f, 0x1, 0, 0, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_WDIG), 0x1, 0, 0, 0x0); return 0; } static int rtpcs_931x_sds_config_fiber_1g(struct rtpcs_serdes *sds) { - rtpcs_sds_write_bits(sds, 0x43, 0x12, 15, 14, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_FIB_EXT), 0x12, 15, 14, 0x0); - rtpcs_sds_write_bits(sds, 0x42, 0x0, 6, 6, 0x1); - rtpcs_sds_write_bits(sds, 0x42, 0x0, 13, 13, 0x0); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_FIB), 0x0, 6, 6, 0x1); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_FIB), 0x0, 13, 13, 0x0); return 0; } @@ -3753,27 +3793,27 @@ static int rtpcs_931x_sds_config_hw_mode(struct rtpcs_serdes *sds, break; case RTPCS_SDS_MODE_2500BASEX: - rtpcs_sds_write_bits(sds, 0x41, 0x14, 8, 8, 1); + rtpcs_sds_write_bits(sds, DIGI_1(PAGE_SDS_EXT), 0x14, 8, 8, 1); break; case RTPCS_SDS_MODE_10GBASER: /* 10GR1000BX_AUTO */ /* configure 10GR fiber mode=1 */ - rtpcs_sds_write_bits(sds, 0x1f, 0xb, 1, 1, 1); + rtpcs_sds_write_bits(sds, PAGE_WDIG, 0xb, 1, 1, 1); rtpcs_931x_sds_config_fiber_1g(sds); /* init auto */ - rtpcs_sds_write_bits(sds, 0x1f, 13, 15, 0, 0x109e); - rtpcs_sds_write_bits(sds, 0x1f, 0x6, 14, 10, 0x8); - rtpcs_sds_write_bits(sds, 0x1f, 0x7, 10, 4, 0x7f); + rtpcs_sds_write_bits(sds, PAGE_WDIG, 13, 15, 0, 0x109e); + rtpcs_sds_write_bits(sds, PAGE_WDIG, 0x6, 14, 10, 0x8); + rtpcs_sds_write_bits(sds, PAGE_WDIG, 0x7, 10, 4, 0x7f); break; case RTPCS_SDS_MODE_SGMII: - rtpcs_sds_write_bits(sds, 0x24, 0x9, 15, 15, 0); + rtpcs_sds_write_bits(sds, PAGE_ANA_1G2, 0x9, 15, 15, 0); break; case RTPCS_SDS_MODE_XSGMII: - rtpcs_sds_xsg_write_bits(sds, 0x0, 0xe, 12, 12, 0x1); + rtpcs_sds_xsg_write_bits(sds, PAGE_SDS, 0xe, 12, 12, 0x1); break; case RTPCS_SDS_MODE_USXGMII_10GSXGMII: @@ -4337,9 +4377,9 @@ static const struct rtpcs_sds_ops rtpcs_838x_sds_ops = { }; static const struct rtpcs_sds_regs rtpcs_838x_sds_regs = { - .an_enable = { .page = 0x2, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, - .an_restart = { .page = 0x2, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, - .an_advertise = { .page = 0x2, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, + .an_enable = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, + .an_restart = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, + .an_advertise = { .page = PAGE_FIB, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, }; static const struct rtpcs_config rtpcs_838x_cfg = { @@ -4377,9 +4417,9 @@ static const struct rtpcs_sds_ops rtpcs_839x_sds_ops = { }; static const struct rtpcs_sds_regs rtpcs_839x_sds_regs = { - .an_enable = { .page = 0x2, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, - .an_restart = { .page = 0x2, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, - .an_advertise = { .page = 0x2, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, + .an_enable = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, + .an_restart = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, + .an_advertise = { .page = PAGE_FIB, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, }; static const struct rtpcs_config rtpcs_839x_cfg = { @@ -4425,9 +4465,9 @@ static const struct rtpcs_sds_ops rtpcs_930x_sds_ops = { }; static const struct rtpcs_sds_regs rtpcs_930x_sds_regs = { - .an_enable = { .page = 0x2, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, - .an_restart = { .page = 0x2, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, - .an_advertise = { .page = 0x2, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, + .an_enable = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, + .an_restart = { .page = PAGE_FIB, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, + .an_advertise = { .page = PAGE_FIB, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, }; static const struct rtpcs_config rtpcs_930x_cfg = { @@ -4471,9 +4511,9 @@ static const struct rtpcs_sds_ops rtpcs_931x_sds_ops = { }; static const struct rtpcs_sds_regs rtpcs_931x_sds_regs = { - .an_enable = { .page = 0x42, .reg = MII_BMCR, .msb = 12, .lsb = 12 }, - .an_restart = { .page = 0x42, .reg = MII_BMCR, .msb = 9, .lsb = 9 }, - .an_advertise = { .page = 0x42, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, + .an_enable = { .page = DIGI_1(PAGE_FIB), .reg = MII_BMCR, .msb = 12, .lsb = 12 }, + .an_restart = { .page = DIGI_1(PAGE_FIB), .reg = MII_BMCR, .msb = 9, .lsb = 9 }, + .an_advertise = { .page = DIGI_1(PAGE_FIB), .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 }, }; static const struct rtpcs_config rtpcs_931x_cfg = { From f7864649ce601d0c1fb8f78366a0f0aaca7f4af2 Mon Sep 17 00:00:00 2001 From: YaleiZang Date: Tue, 23 Jun 2026 11:02:22 +0800 Subject: [PATCH 159/228] airoha: correct node addresses for crypto and thermal-sensor Update the @ address suffix of crypto and thermal-sensor nodes in the device tree to match the reg properties for consistency. Signed-off-by: YaleiZang Link: https://github.com/openwrt/openwrt/pull/23920 Signed-off-by: Jonas Jelonek --- target/linux/airoha/dts/an7581.dtsi | 4 ++-- target/linux/airoha/dts/an7583.dtsi | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/airoha/dts/an7581.dtsi b/target/linux/airoha/dts/an7581.dtsi index efbb4ca54e..e7bfd69165 100644 --- a/target/linux/airoha/dts/an7581.dtsi +++ b/target/linux/airoha/dts/an7581.dtsi @@ -632,14 +632,14 @@ #phy-cells = <1>; }; - crypto@1e004000 { + crypto@1fb70000 { compatible = "inside-secure,safexcel-eip93ies"; reg = <0x0 0x1fb70000 0x0 0x1000>; interrupts = ; }; - thermal: thermal-sensor@1efbd800 { + thermal: thermal-sensor@1efbd000 { compatible = "airoha,en7581-thermal"; reg = <0x0 0x1efbd000 0x0 0xd5c>; interrupts = ; diff --git a/target/linux/airoha/dts/an7583.dtsi b/target/linux/airoha/dts/an7583.dtsi index 743eeb7cec..98feaa1338 100644 --- a/target/linux/airoha/dts/an7583.dtsi +++ b/target/linux/airoha/dts/an7583.dtsi @@ -539,7 +539,7 @@ status = "disabled"; }; - crypto@1e004000 { + crypto@1fb70000 { compatible = "inside-secure,safexcel-eip93ies"; reg = <0x0 0x1fb70000 0x0 0x1000>; From 4745f757a7d6b571d2279052b40a0dc5ba1ab2a0 Mon Sep 17 00:00:00 2001 From: YaleiZang Date: Tue, 23 Jun 2026 11:34:02 +0800 Subject: [PATCH 160/228] airoha: align ethernet-phy node name with reg property Change ethernet-phy node name for alignment with reg. This enhances the clarity and maintainability of the device-tree. Signed-off-by: YaleiZang Link: https://github.com/openwrt/openwrt/pull/23920 Signed-off-by: Jonas Jelonek --- target/linux/airoha/dts/an7583.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/airoha/dts/an7583.dtsi b/target/linux/airoha/dts/an7583.dtsi index 98feaa1338..33ac571ca3 100644 --- a/target/linux/airoha/dts/an7583.dtsi +++ b/target/linux/airoha/dts/an7583.dtsi @@ -751,7 +751,7 @@ #address-cells = <1>; #size-cells = <0>; - gsw_phy1: ethernet-phy@1 { + gsw_phy1: ethernet-phy@9 { compatible = "ethernet-phy-ieee802.3-c22"; reg = <9>; phy-mode = "internal"; @@ -774,7 +774,7 @@ }; }; - gsw_phy2: ethernet-phy@2 { + gsw_phy2: ethernet-phy@a { compatible = "ethernet-phy-ieee802.3-c22"; reg = <10>; phy-mode = "internal"; @@ -797,7 +797,7 @@ }; }; - gsw_phy3: ethernet-phy@3 { + gsw_phy3: ethernet-phy@b { compatible = "ethernet-phy-ieee802.3-c22"; reg = <11>; phy-mode = "internal"; @@ -820,7 +820,7 @@ }; }; - gsw_phy4: ethernet-phy@4 { + gsw_phy4: ethernet-phy@c { compatible = "ethernet-phy-ieee802.3-c22"; reg = <12>; phy-mode = "internal"; From 82f26df15c56437fbac2b6711402a3d37f3f7571 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sun, 21 Jun 2026 21:05:51 +0000 Subject: [PATCH 161/228] toolchain: binutils: change default to 2.46 Change default to latest upstream release. Link: https://github.com/openwrt/openwrt/pull/23907 Signed-off-by: Jonas Jelonek --- toolchain/binutils/Config.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolchain/binutils/Config.version b/toolchain/binutils/Config.version index c706c5a111..ca38e8c07e 100644 --- a/toolchain/binutils/Config.version +++ b/toolchain/binutils/Config.version @@ -1,12 +1,12 @@ config BINUTILS_VERSION_2_44 - default y if !TOOLCHAINOPTS bool config BINUTILS_VERSION_2_45 bool config BINUTILS_VERSION_2_46 + default y if !TOOLCHAINOPTS bool config BINUTILS_VERSION From 1e45d12ebd646a3469bf39b5ddd7d3d30fbed495 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Wed, 24 Jun 2026 11:27:18 +0200 Subject: [PATCH 162/228] realtek: eth: rename dest_port to port Just variable renaming. No functional change. Link: https://github.com/openwrt/openwrt/pull/23948 Signed-off-by: Markus Stockhausen --- .../drivers/net/ethernet/rtl838x_eth.c | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c index 06fe6f7ed0..82b1273c41 100644 --- a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c @@ -123,34 +123,34 @@ struct rteth_ctrl { struct rteth_tx *tx_data; }; -static void rteth_838x_create_tx_header(struct rteth_packet *h, unsigned int dest_port, int prio) +static void rteth_838x_create_tx_header(struct rteth_packet *h, unsigned int port, int prio) { /* cpu_tag[0] is reserved on the RTL83XX SoCs */ h->cpu_tag[1] = 0x0400; /* BIT 10: RTL8380_CPU_TAG */ h->cpu_tag[2] = 0x0200; /* Set only AS_DPM, to enable DPM settings below */ h->cpu_tag[3] = 0x0000; - h->cpu_tag[4] = BIT(dest_port) >> 16; - h->cpu_tag[5] = BIT(dest_port) & 0xffff; + h->cpu_tag[4] = BIT(port) >> 16; + h->cpu_tag[5] = BIT(port) & 0xffff; /* Set internal priority (PRI) and enable (AS_PRI) */ if (prio >= 0) h->cpu_tag[2] |= ((prio & 0x7) | BIT(3)) << 12; } -static void rteth_839x_create_tx_header(struct rteth_packet *h, unsigned int dest_port, int prio) +static void rteth_839x_create_tx_header(struct rteth_packet *h, unsigned int port, int prio) { /* cpu_tag[0] is reserved on the RTL83XX SoCs */ h->cpu_tag[1] = 0x0100; /* RTL8390_CPU_TAG marker */ h->cpu_tag[2] = BIT(4); /* AS_DPM flag */ h->cpu_tag[3] = h->cpu_tag[4] = h->cpu_tag[5] = 0; /* h->cpu_tag[1] |= BIT(1) | BIT(0); */ /* Bypass filter 1/2 */ - if (dest_port >= 32) { - dest_port -= 32; - h->cpu_tag[2] |= (BIT(dest_port) >> 16) & 0xf; - h->cpu_tag[3] = BIT(dest_port) & 0xffff; + if (port >= 32) { + port -= 32; + h->cpu_tag[2] |= (BIT(port) >> 16) & 0xf; + h->cpu_tag[3] = BIT(port) & 0xffff; } else { - h->cpu_tag[4] = BIT(dest_port) >> 16; - h->cpu_tag[5] = BIT(dest_port) & 0xffff; + h->cpu_tag[4] = BIT(port) >> 16; + h->cpu_tag[5] = BIT(port) & 0xffff; } /* Set internal priority (PRI) and enable (AS_PRI) */ @@ -158,7 +158,7 @@ static void rteth_839x_create_tx_header(struct rteth_packet *h, unsigned int des h->cpu_tag[2] |= ((prio & 0x7) | BIT(3)) << 8; } -static void rteth_93xx_create_tx_header(struct rteth_packet *h, unsigned int dest_port, int prio) +static void rteth_93xx_create_tx_header(struct rteth_packet *h, unsigned int port, int prio) { h->cpu_tag[0] = 0x8000; /* CPU tag marker */ h->cpu_tag[1] = FIELD_PREP(RTL93XX_CPU_TAG1_FWD_MASK, RTL93XX_CPU_TAG1_FWD_PHYSICAL) | @@ -166,10 +166,10 @@ static void rteth_93xx_create_tx_header(struct rteth_packet *h, unsigned int des h->cpu_tag[2] = (prio >= 0) ? (BIT(5) | (prio & 0x1f)) << 8 : 0; h->cpu_tag[3] = 0; - h->cpu_tag[4] = BIT_ULL(dest_port) >> 48; - h->cpu_tag[5] = BIT_ULL(dest_port) >> 32; - h->cpu_tag[6] = BIT_ULL(dest_port) >> 16; - h->cpu_tag[7] = BIT_ULL(dest_port) & 0xffff; + h->cpu_tag[4] = BIT_ULL(port) >> 48; + h->cpu_tag[5] = BIT_ULL(port) >> 32; + h->cpu_tag[6] = BIT_ULL(port) >> 16; + h->cpu_tag[7] = BIT_ULL(port) & 0xffff; } static inline void rteth_reenable_irq(struct rteth_ctrl *ctrl, int ring) @@ -1004,7 +1004,7 @@ static void rteth_tx_timeout(struct net_device *dev, unsigned int txqueue) static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct rteth_ctrl *ctrl = netdev_priv(dev); - int val, slot, len = skb->len, dest_port = -1; + int val, slot, len = skb->len, port = -1; int ring = skb_get_queue_mapping(skb); struct rteth_packet *packet; dma_addr_t packet_dma; @@ -1014,7 +1014,7 @@ static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->data[len - 3] < ctrl->r->cpu_port && skb->data[len - 2] == 0x10 && skb->data[len - 1] == 0x00) { - dest_port = skb->data[len - 3]; + port = skb->data[len - 3]; /* space will be reused for 4 byte layer 2 FCS */ } else { /* No DSA tag, add space for 4 byte layer 2 FCS */ @@ -1056,8 +1056,8 @@ static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - if (dest_port >= 0) - ctrl->r->create_tx_header(packet, dest_port, 0); // TODO ok to set prio to 0? + if (port >= 0) + ctrl->r->create_tx_header(packet, port, 0); // TODO ok to set prio to 0? /* Transfer data and hand packet over to switch */ packet->len = len; From c77ac7db48c565ebc84f5c6f1f1131abbc57130f Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Wed, 24 Jun 2026 11:45:40 +0200 Subject: [PATCH 163/228] realtek: eth: fix tx_bytes calculation When sending data packets the hardware expects data size plus 4 bytes for the layer 2 checksum (FCS). This does not count into "bytes sent" metric. Fix that. Link: https://github.com/openwrt/openwrt/pull/23948 Signed-off-by: Markus Stockhausen --- .../linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c index 82b1273c41..c0f8cd8663 100644 --- a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c @@ -1081,7 +1081,7 @@ static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) regmap_write(ctrl->map, ctrl->r->dma_if_ctrl, val | RTETH_TX_TRIGGER(ctrl, ring)); dev->stats.tx_packets++; - dev->stats.tx_bytes += len; + dev->stats.tx_bytes += len - ETH_FCS_LEN; spin_unlock(&ctrl->tx_lock); From bc910540adbafd4cc811dcdf69e9baa562e9fffb Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Wed, 24 Jun 2026 11:59:29 +0200 Subject: [PATCH 164/228] realtek: dsa/eth: adapt transmit path This is just some reordering/simplifcation of the transmit path. Relocate the port extraction into a separate helper for a smaller xmit function. While we are here add some documentation and reorder the tag and its contents. As these are only arbitrary values that help the ethernet driver to identifiy the tag this is just cosmetic. Link: https://github.com/openwrt/openwrt/pull/23948 Signed-off-by: Markus Stockhausen --- .../drivers/net/ethernet/rtl838x_eth.c | 35 +++++++++++-------- .../realtek/files-6.18/net/dsa/tag_rtl_otto.c | 34 +++++++----------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c index c0f8cd8663..b9cb572492 100644 --- a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c @@ -1001,25 +1001,32 @@ static void rteth_tx_timeout(struct net_device *dev, unsigned int txqueue) } } -static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) +static int rteth_get_dsa_port(struct sk_buff *skb, struct net_device *dev) { struct rteth_ctrl *ctrl = netdev_priv(dev); - int val, slot, len = skb->len, port = -1; - int ring = skb_get_queue_mapping(skb); + u8 *trailer = &skb->data[skb->len - 4]; + + if (netdev_uses_dsa(dev) && + dev->dsa_ptr->tag_ops->proto == DSA_TAG_PROTO_RTL_OTTO && + trailer[0] < ctrl->r->cpu_port && + trailer[1] == 0xab && + trailer[2] == 0xcd && + trailer[3] == 0xef) + return trailer[0]; + + return -1; +} + +static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int port, val, slot, len = skb->len, ring = skb_get_queue_mapping(skb); + struct rteth_ctrl *ctrl = netdev_priv(dev); struct rteth_packet *packet; dma_addr_t packet_dma; - if (netdev_uses_dsa(dev) && - skb->data[len - 4] == 0x80 && - skb->data[len - 3] < ctrl->r->cpu_port && - skb->data[len - 2] == 0x10 && - skb->data[len - 1] == 0x00) { - port = skb->data[len - 3]; - /* space will be reused for 4 byte layer 2 FCS */ - } else { - /* No DSA tag, add space for 4 byte layer 2 FCS */ - len += ETH_FCS_LEN; - } + port = rteth_get_dsa_port(skb, dev); + if (port < 0) + len += ETH_FCS_LEN; /* No reusable 4 byte tag, add space for 4 byte layer 2 FCS */ len = max(ETH_ZLEN + ETH_FCS_LEN, len); if (unlikely(skb_put_padto(skb, len))) { diff --git a/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c b/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c index 08a9915584..2048d5addb 100644 --- a/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c +++ b/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c @@ -1,8 +1,4 @@ // SPDX-License-Identifier: GPL-2.0+ -/* - * net/dsa/tag_trailer.c - Trailer tag format handling - * Copyright (c) 2008-2009 Marvell Semiconductor - */ #include #include @@ -10,24 +6,20 @@ #include "tag.h" -#define RTL_OTTO_NAME "rtl_otto" - -/* - * TODO: This driver was copied over from trailer tagging. It will be developed - * downstream in OpenWrt in conjunction with the Realtek Otto ethernet driver. - * For now rely on the old trailer handling and keep everything as is. - */ +#define RTL_OTTO_NAME "rtl_otto" +#define RTL_OTTO_TAILROOM 4 static struct sk_buff *rtl_otto_xmit(struct sk_buff *skb, struct net_device *dev) { struct dsa_port *dp = dsa_user_to_port(dev); u8 *trailer; - trailer = skb_put(skb, 4); - trailer[0] = 0x80; - trailer[1] = dp->index; - trailer[2] = 0x10; - trailer[3] = 0x00; + /* Hardware needs space for Layer 2 FCS. Align tag size with that. */ + trailer = skb_put(skb, RTL_OTTO_TAILROOM); + trailer[0] = dp->index; + trailer[1] = 0xab; + trailer[2] = 0xcd; + trailer[3] = 0xef; return skb; } @@ -62,11 +54,11 @@ static struct sk_buff *rtl_otto_rcv(struct sk_buff *skb, struct net_device *dev) } static const struct dsa_device_ops rtl_otto_netdev_ops = { - .name = RTL_OTTO_NAME, - .proto = DSA_TAG_PROTO_RTL_OTTO, - .xmit = rtl_otto_xmit, - .rcv = rtl_otto_rcv, - .needed_tailroom = 4, + .name = RTL_OTTO_NAME, + .proto = DSA_TAG_PROTO_RTL_OTTO, + .xmit = rtl_otto_xmit, + .rcv = rtl_otto_rcv, + .needed_tailroom = RTL_OTTO_TAILROOM, }; MODULE_DESCRIPTION("DSA tag driver for Realtek Otto switches (RTL83xx/RTL93xx)"); From e59484b39ea79e8a77f3bb953f25b25769ef9ebe Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Tue, 23 Jun 2026 18:50:48 +0200 Subject: [PATCH 165/228] realtek: dsa/eth: adapt receive path Improve the DSA receive tagging. For this convert the receive path to METADATA_HW_PORT_MUX. This way no skb data mangling is needed. See e.g. airoha_eth.c or mtk_eth_soc.c. Link: https://github.com/openwrt/openwrt/pull/23948 Signed-off-by: Markus Stockhausen --- .../drivers/net/ethernet/rtl838x_eth.c | 56 ++++++++++++++----- .../realtek/files-6.18/net/dsa/tag_rtl_otto.c | 25 +-------- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c index b9cb572492..0dfd36a82f 100644 --- a/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.18/drivers/net/ethernet/rtl838x_eth.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -113,6 +114,7 @@ struct rteth_ctrl { struct phylink_config phylink_config; const struct rteth_config *r; u32 lastEvent; + struct metadata_dst *dsa_meta[RTETH_931X_CPU_PORT]; /* receive handling */ dma_addr_t rx_data_dma; spinlock_t rx_lock; @@ -1097,11 +1099,10 @@ static int rteth_start_xmit(struct sk_buff *skb, struct net_device *dev) static int rteth_hw_receive(struct net_device *dev, int ring, int budget) { - int slot, len, work_done = 0, rx_packets = 0, rx_bytes = 0; + int slot, work_done = 0, rx_packets = 0, rx_bytes = 0; struct rteth_ctrl *ctrl = netdev_priv(dev); - unsigned int new_offset, old_offset; + unsigned int len, new_offset, old_offset; struct page *old_page, *new_page; - bool dsa = netdev_uses_dsa(dev); struct rteth_packet *packet; dma_addr_t packet_dma; struct sk_buff *skb; @@ -1116,9 +1117,9 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget) break; packet = &ctrl->rx_data[ring].packet[slot]; - len = packet->len; + len = packet->len - ETH_FCS_LEN; - if (unlikely(len < ETH_FCS_LEN || len > RING_BUFFER)) { + if (unlikely(len > RING_BUFFER)) { netdev_err(dev, "invalid packet with %d bytes received\n", len); dev->stats.rx_errors++; goto recycle; @@ -1138,9 +1139,6 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget) packet->page_offset = new_offset; packet->dma = page_pool_get_dma_addr(new_page) + new_offset + RTETH_SKB_HEADROOM; - if (!dsa) - len -= ETH_FCS_LEN; - page_pool_dma_sync_for_cpu(ctrl->rx_qs[ring].page_pool, old_page, old_offset + RTETH_SKB_HEADROOM, len); @@ -1156,13 +1154,11 @@ static int rteth_hw_receive(struct net_device *dev, int ring, int budget) skb_put(skb, len); ctrl->r->decode_tag(packet, &tag); - if (dsa) { - skb->data[len - 4] = 0x80; - skb->data[len - 3] = tag.port; - skb->data[len - 2] = 0x10; - skb->data[len - 1] = 0x00; + if (netdev_uses_dsa(dev)) { + if (tag.port < ctrl->r->cpu_port) + skb_dst_set_noref(skb, &ctrl->dsa_meta[tag.port]->dst); if (tag.l2_offloaded) - skb->data[len - 3] |= 0x40; + skb->offload_fwd_mark = 1; } skb->protocol = eth_type_trans(skb, dev); @@ -1606,6 +1602,32 @@ static const struct ethtool_ops rteth_ethtool_ops = { .set_link_ksettings = rteth_set_link_ksettings, }; +static int rteth_metadata_dst_alloc(struct rteth_ctrl *ctrl) +{ + struct metadata_dst *md_dst; + + for (int i = 0; i < ARRAY_SIZE(ctrl->dsa_meta); i++) { + md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL); + if (!md_dst) + return -ENOMEM; + + md_dst->u.port_info.port_id = i; + ctrl->dsa_meta[i] = md_dst; + } + + return 0; +} + +static void rteth_metadata_dst_free(struct rteth_ctrl *ctrl) +{ + for (int i = 0; i < ARRAY_SIZE(ctrl->dsa_meta); i++) { + if (!ctrl->dsa_meta[i]) + continue; + + metadata_dst_free(ctrl->dsa_meta[i]); + } +} + static int rteth_probe(struct platform_device *pdev) { struct page_pool_params pp_params = { @@ -1762,6 +1784,10 @@ static int rteth_probe(struct platform_device *pdev) } } + err = rteth_metadata_dst_alloc(ctrl); + if (err) + goto cleanup; + err = register_netdev(dev); if (err) goto cleanup; @@ -1769,6 +1795,7 @@ static int rteth_probe(struct platform_device *pdev) return 0; cleanup: + rteth_metadata_dst_free(ctrl); if (ctrl->phylink) phylink_destroy(ctrl->phylink); for (int i = 0; i < RTETH_RX_RINGS; i++) { @@ -1787,6 +1814,7 @@ static void rteth_remove(struct platform_device *pdev) pr_info("Removing platform driver for rtl838x-eth\n"); unregister_netdev(dev); + rteth_metadata_dst_free(ctrl); if (ctrl->phylink) phylink_destroy(ctrl->phylink); diff --git a/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c b/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c index 2048d5addb..ecbf67b42a 100644 --- a/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c +++ b/target/linux/realtek/files-6.18/net/dsa/tag_rtl_otto.c @@ -26,29 +26,8 @@ static struct sk_buff *rtl_otto_xmit(struct sk_buff *skb, struct net_device *dev static struct sk_buff *rtl_otto_rcv(struct sk_buff *skb, struct net_device *dev) { - u8 *trailer; - int source_port; - - if (skb_linearize(skb)) - return NULL; - - trailer = skb_tail_pointer(skb) - 4; - - if (trailer[0] != 0x80 || (trailer[1] & 0x80) != 0x00 || - (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00) - return NULL; - - if (trailer[1] & 0x40) - skb->offload_fwd_mark = 1; - - source_port = trailer[1] & 0x3f; - - skb->dev = dsa_conduit_find_user(dev, 0, source_port); - if (!skb->dev) - return NULL; - - if (pskb_trim_rcsum(skb, skb->len - 4)) - return NULL; + /* RX path uses METADATA_HW_PORT_MUX. This function just makes netdev_uses_dsa() happy. */ + netdev_err(dev, "ethernet driver did not set METADATA\n"); return skb; } From 47aa3ec222a3b0eb2979c412133da9fc9c49a0f9 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Fri, 26 Jun 2026 10:08:43 +0000 Subject: [PATCH 166/228] realtek: mdio: add polling setup support for RTL8264B Add polling setup support for RTL8264B PHY to avoid 'skip polling' message during boot. Rely on the default register values for polling for now, similar to RTL8261. Link: https://github.com/openwrt/openwrt/pull/23946 Signed-off-by: Jonas Jelonek --- .../realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c b/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c index c4d425b784..0a4214166f 100644 --- a/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/mdio/mdio-realtek-otto.c @@ -92,6 +92,7 @@ #define RTMD_PHY_RTL8224 0x001ccad0 #define RTMD_PHY_RTL8226 0x001cc838 #define RTMD_PHY_RTL8261 0x001ccaf3 +#define RTMD_PHY_RTL8264B 0x001cc813 #define RTMD_PHY_MAC_1G 3 #define RTMD_PHY_MAC_2G_PLUS 1 @@ -737,6 +738,7 @@ static int rtmd_get_phy_info(struct rtmd_ctrl *ctrl, int pn, struct rtmd_phy_inf phyinfo->poll_lpa_1000 = RTMD_PHY_POLL_MMD(31, 0xa414, 11); break; case RTMD_PHY_RTL8261: + case RTMD_PHY_RTL8264B: phyinfo->mac_type = RTMD_PHY_MAC_2G_PLUS; phyinfo->has_giga_lite = true; phyinfo->has_res_reg = true; From b586e843dedd34b7f339375f03eb26e9b35ed5bc Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Wed, 24 Jun 2026 22:41:15 +0200 Subject: [PATCH 167/228] realtek: l3: separate L3 coding from DSA DSA is layer 2 and not layer 3. Nevertheless all routing management needs a home. Separate it into its own source file. This first step is far from perfect but at least it guides the DSA driver into the right direction. No functional changes. Just relocating, renaming and proper including. Link: https://github.com/openwrt/openwrt/pull/23937 Signed-off-by: Markus Stockhausen --- .../drivers/net/dsa/rtl83xx/Makefile | 2 +- .../drivers/net/dsa/rtl83xx/common.c | 694 +----------------- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 692 +++++++++++++++++ .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 56 ++ .../drivers/net/dsa/rtl83xx/rtl-otto.h | 57 +- .../drivers/net/dsa/rtl83xx/rtl838x.c | 5 +- .../drivers/net/dsa/rtl83xx/rtl839x.c | 5 +- .../drivers/net/dsa/rtl83xx/rtl930x.c | 15 +- 8 files changed, 782 insertions(+), 744 deletions(-) create mode 100644 target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c create mode 100644 target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/Makefile b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/Makefile index 1511dae8ea..21b681918f 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/Makefile +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_NET_DSA_RTL83XX) += rtl_otto_dsa.o -rtl_otto_dsa-objs := common.o dsa.o rtl838x.o rtl839x.o rtl930x.o rtl931x.o debugfs.o qos.o tc.o +rtl_otto_dsa-objs := common.o dsa.o rtl838x.o rtl839x.o rtl930x.o rtl931x.o debugfs.o qos.o tc.o l3.o diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c index 88e7984b8b..b72b401d8e 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c @@ -14,6 +14,7 @@ #include #include +#include "l3.h" #include "rtl-otto.h" int rtldsa_port_get_stp_state(struct rtl838x_switch_priv *priv, int port) @@ -695,7 +696,7 @@ int rtl83xx_packet_cntr_alloc(struct rtl838x_switch_priv *priv) * Called from the L3 layer * The index in the L2 hash table is filled into nh->l2_id; */ -static int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl83xx_nexthop *nh) +int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct otto_l3_nexthop *nh) { struct rtl838x_l2_entry e; u64 seed = priv->r->l2_hash_seed(nh->mac, nh->rvid); @@ -762,7 +763,7 @@ static int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct rtl83 * If it was static, the entire entry is removed, otherwise the nexthop bit is cleared * and we wait until the entry ages out */ -static int rtl83xx_l2_nexthop_rm(struct rtl838x_switch_priv *priv, struct rtl83xx_nexthop *nh) +int rtl83xx_l2_nexthop_rm(struct rtl838x_switch_priv *priv, struct otto_l3_nexthop *nh) { struct rtl838x_l2_entry e; u32 key = nh->l2_id >> 2; @@ -808,689 +809,6 @@ int rtl83xx_port_is_under(const struct net_device *dev, struct rtl838x_switch_pr return -EINVAL; } -static const struct rhashtable_params route_ht_params = { - .key_len = sizeof(u32), - .key_offset = offsetof(struct rtl83xx_route, gw_ip), - .head_offset = offsetof(struct rtl83xx_route, linkage), -}; - -/* Updates an L3 next hop entry in the ROUTING table */ -static int rtl83xx_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_addr, u64 mac) -{ - struct rtl83xx_route *r; - struct rhlist_head *tmp, *list; - - rcu_read_lock(); - list = rhltable_lookup(&priv->routes, &ip_addr, route_ht_params); - if (!list) { - rcu_read_unlock(); - return -ENOENT; - } - - rhl_for_each_entry_rcu(r, tmp, list, linkage) { - pr_debug("%s: Setting up fwding: ip %pI4, GW mac %016llx\n", - __func__, &ip_addr, mac); - - /* Reads the ROUTING table entry associated with the route */ - priv->r->route_read(r->id, r); - pr_debug("Route with id %d to %pI4 / %d\n", r->id, &r->dst_ip, r->prefix_len); - - r->nh.mac = r->nh.gw = mac; - r->nh.port = priv->r->port_ignore; - r->nh.id = r->id; - - /* Do we need to explicitly add a DMAC entry with the route's nh index? */ - if (priv->r->set_l3_egress_mac) - priv->r->set_l3_egress_mac(r->id, mac); - - /* Update ROUTING table: map gateway-mac and switch-mac id to route id */ - rtl83xx_l2_nexthop_add(priv, &r->nh); - - r->attr.valid = true; - r->attr.action = ROUTE_ACT_FORWARD; - r->attr.type = 0; - r->attr.hit = false; /* Reset route-used indicator */ - - /* Add PIE entry with dst_ip and prefix_len */ - r->pr.dip = r->dst_ip; - r->pr.dip_m = inet_make_mask(r->prefix_len); - - if (r->is_host_route) { - int slot = priv->r->find_l3_slot(r, false); - - pr_info("%s: Got slot for route: %d\n", __func__, slot); - priv->r->host_route_write(slot, r); - } else { - priv->r->route_write(r->id, r); - r->pr.fwd_sel = true; - r->pr.fwd_data = r->nh.l2_id; - r->pr.fwd_act = PIE_ACT_ROUTE_UC; - } - - if (priv->r->set_l3_nexthop) - priv->r->set_l3_nexthop(r->nh.id, r->nh.l2_id, r->nh.if_id); - - if (r->pr.id < 0) { - r->pr.packet_cntr = rtl83xx_packet_cntr_alloc(priv); - if (r->pr.packet_cntr >= 0) { - pr_info("Using packet counter %d\n", r->pr.packet_cntr); - r->pr.log_sel = true; - r->pr.log_data = r->pr.packet_cntr; - } - priv->r->pie_rule_add(priv, &r->pr); - } else { - int pkts = priv->r->packet_cntr_read(r->pr.packet_cntr); - - pr_debug("%s: total packets: %d\n", __func__, pkts); - - priv->r->pie_rule_write(priv, r->pr.id, &r->pr); - } - } - rcu_read_unlock(); - - return 0; -} - -static int rtl83xx_port_ipv4_resolve(struct rtl838x_switch_priv *priv, - struct net_device *dev, __be32 ip_addr) -{ - struct neighbour *n = neigh_lookup(&arp_tbl, &ip_addr, dev); - int err = 0; - u64 mac; - - if (!n) { - n = neigh_create(&arp_tbl, &ip_addr, dev); - if (IS_ERR(n)) - return PTR_ERR(n); - } - - /* If the neigh is already resolved, then go ahead and - * install the entry, otherwise start the ARP process to - * resolve the neigh. - */ - if (n->nud_state & NUD_VALID) { - mac = ether_addr_to_u64(n->ha); - pr_info("%s: resolved mac: %016llx\n", __func__, mac); - rtl83xx_l3_nexthop_update(priv, ip_addr, mac); - } else { - pr_info("%s: need to wait\n", __func__); - neigh_event_send(n, NULL); - } - - neigh_release(n); - - return err; -} - -struct rtl83xx_walk_data { - struct rtl838x_switch_priv *priv; - int port; -}; - -static int rtl83xx_port_lower_walk(struct net_device *lower, struct netdev_nested_priv *_priv) -{ - struct rtl83xx_walk_data *data = (struct rtl83xx_walk_data *)_priv->data; - struct rtl838x_switch_priv *priv = data->priv; - int ret = 0; - int index; - - index = rtl83xx_port_is_under(lower, priv); - data->port = index; - if (index >= 0) { - pr_debug("Found DSA-port, index %d\n", index); - ret = 1; - } - - return ret; -} - -static int rtl83xx_port_dev_lower_find(struct net_device *dev, struct rtl838x_switch_priv *priv) -{ - struct rtl83xx_walk_data data; - struct netdev_nested_priv _priv; - - data.priv = priv; - data.port = 0; - _priv.data = (void *)&data; - - netdev_walk_all_lower_dev(dev, rtl83xx_port_lower_walk, &_priv); - - return data.port; -} - -static struct rtl83xx_route *rtl83xx_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) -{ - struct rtl83xx_route *r; - int idx = 0, err; - - mutex_lock(&priv->reg_mutex); - - idx = find_first_zero_bit(priv->route_use_bm, MAX_ROUTES); - pr_debug("%s id: %d, ip %pI4\n", __func__, idx, &ip); - - r = kzalloc(sizeof(*r), GFP_KERNEL); - if (!r) { - mutex_unlock(&priv->reg_mutex); - return r; - } - - r->id = idx; - r->gw_ip = ip; - r->pr.id = -1; /* We still need to allocate a rule in HW */ - r->is_host_route = false; - - err = rhltable_insert(&priv->routes, &r->linkage, route_ht_params); - if (err) { - pr_err("Could not insert new rule\n"); - mutex_unlock(&priv->reg_mutex); - goto out_free; - } - - set_bit(idx, priv->route_use_bm); - - mutex_unlock(&priv->reg_mutex); - - return r; - -out_free: - kfree(r); - - return NULL; -} - -static struct rtl83xx_route *rtl83xx_host_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) -{ - struct rtl83xx_route *r; - int idx = 0, err; - - mutex_lock(&priv->reg_mutex); - - idx = find_first_zero_bit(priv->host_route_use_bm, MAX_HOST_ROUTES); - pr_debug("%s id: %d, ip %pI4\n", __func__, idx, &ip); - - r = kzalloc(sizeof(*r), GFP_KERNEL); - if (!r) { - mutex_unlock(&priv->reg_mutex); - return r; - } - - /* We require a unique route ID irrespective of whether it is a prefix or host - * route (on RTL93xx) as we use this ID to associate a DMAC and next-hop entry - */ - r->id = idx + MAX_ROUTES; - - r->gw_ip = ip; - r->pr.id = -1; /* We still need to allocate a rule in HW */ - r->is_host_route = true; - - err = rhltable_insert(&priv->routes, &r->linkage, route_ht_params); - if (err) { - pr_err("Could not insert new rule\n"); - mutex_unlock(&priv->reg_mutex); - goto out_free; - } - - set_bit(idx, priv->host_route_use_bm); - - mutex_unlock(&priv->reg_mutex); - - return r; - -out_free: - kfree(r); - - return NULL; -} - -static void rtl83xx_route_rm(struct rtl838x_switch_priv *priv, struct rtl83xx_route *r) -{ - int id; - - if (rhltable_remove(&priv->routes, &r->linkage, route_ht_params)) - dev_warn(priv->dev, "Could not remove route\n"); - - if (r->is_host_route) { - id = priv->r->find_l3_slot(r, false); - pr_debug("%s: Got id for host route: %d\n", __func__, id); - r->attr.valid = false; - priv->r->host_route_write(id, r); - clear_bit(r->id - MAX_ROUTES, priv->host_route_use_bm); - } else { - /* If there is a HW representation of the route, delete it */ - if (priv->r->route_lookup_hw) { - id = priv->r->route_lookup_hw(r); - pr_info("%s: Got id for prefix route: %d\n", __func__, id); - r->attr.valid = false; - priv->r->route_write(id, r); - } - clear_bit(r->id, priv->route_use_bm); - } - - kfree(r); -} - -static int rtldsa_fib4_check(struct rtl838x_switch_priv *priv, - struct fib_entry_notifier_info *info, - enum fib_event_type event) -{ - struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; - int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; - struct fib_nh *nh = fib_info_nh(info->fi, 0); - char gw_message[32] = ""; - - if (nh->fib_nh_gw4) - snprintf(gw_message, sizeof(gw_message), "via %pI4 ", &nh->fib_nh_gw4); - - dev_info(priv->dev, "%s IPv4 route %pI4/%d %s(VLAN %d, MAC %pM)\n", - event == FIB_EVENT_ENTRY_ADD ? "add" : "delete", - &info->dst, info->dst_len, gw_message, vlan, ndev->dev_addr); - - if ((info->type == RTN_BROADCAST) || ipv4_is_loopback(info->dst) || !info->dst) { - dev_warn(priv->dev, "skip loopback/broadcast addresses and default routes\n"); - return -EINVAL; - } - - return 0; -} - -static int rtldsa_fib4_del(struct rtl838x_switch_priv *priv, - struct fib_entry_notifier_info *info) -{ - struct fib_nh *nh = fib_info_nh(info->fi, 0); - struct rhlist_head *tmp, *list; - struct rtl83xx_route *route; - - if (rtldsa_fib4_check(priv, info, FIB_EVENT_ENTRY_DEL)) - return 0; - - rcu_read_lock(); - list = rhltable_lookup(&priv->routes, &nh->fib_nh_gw4, route_ht_params); - if (!list) { - rcu_read_unlock(); - dev_err(priv->dev, "no such gateway: %pI4\n", &nh->fib_nh_gw4); - return -ENOENT; - } - rhl_for_each_entry_rcu(route, tmp, list, linkage) { - if (route->dst_ip == info->dst && route->prefix_len == info->dst_len) { - dev_info(priv->dev, "found a route with id %d, nh-id %d\n", - route->id, route->nh.id); - break; - } - } - rcu_read_unlock(); - - rtl83xx_l2_nexthop_rm(priv, &route->nh); - - dev_info(priv->dev, "releasing packet counter %d\n", route->pr.packet_cntr); - set_bit(route->pr.packet_cntr, priv->packet_cntr_use_bm); - priv->r->pie_rule_rm(priv, &route->pr); - - rtl83xx_route_rm(priv, route); - - nh->fib_nh_flags &= ~RTNH_F_OFFLOAD; - - return 0; -} - -/* On the RTL93xx, an L3 termination endpoint MAC address on which the router waits - * for packets to be routed needs to be allocated. - */ -static int rtl83xx_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac) -{ - int free_mac = -1; - struct rtl93xx_rt_mac m; - - mutex_lock(&priv->reg_mutex); - for (int i = 0; i < MAX_ROUTER_MACS; i++) { - priv->r->get_l3_router_mac(i, &m); - if (free_mac < 0 && !m.valid) { - free_mac = i; - continue; - } - if (m.valid && m.mac == mac) { - free_mac = i; - break; - } - } - - if (free_mac < 0) { - pr_err("No free router MACs, cannot offload\n"); - mutex_unlock(&priv->reg_mutex); - return -1; - } - - m.valid = true; - m.mac = mac; - m.p_type = 0; /* An individual port, not a trunk port */ - m.p_id = 0x3f; /* Listen on any port */ - m.p_id_mask = 0; - m.vid = 0; /* Listen on any VLAN... */ - m.vid_mask = 0; /* ... so mask needs to be 0 */ - m.mac_mask = 0xffffffffffffULL; /* We want an exact match of the interface MAC */ - m.action = L3_FORWARD; /* Route the packet */ - priv->r->set_l3_router_mac(free_mac, &m); - - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -static int rtl83xx_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac, int vlan) -{ - int free_mac = -1; - struct rtl838x_l3_intf intf; - u64 m; - - mutex_lock(&priv->reg_mutex); - for (int i = 0; i < MAX_SMACS; i++) { - m = priv->r->get_l3_egress_mac(L3_EGRESS_DMACS + i); - if (free_mac < 0 && !m) { - free_mac = i; - continue; - } - if (m == mac) { - mutex_unlock(&priv->reg_mutex); - return i; - } - } - - if (free_mac < 0) { - pr_err("No free egress interface, cannot offload\n"); - return -1; - } - - /* Set up default egress interface 1 */ - intf.vid = vlan; - intf.smac_idx = free_mac; - intf.ip4_mtu_id = 1; - intf.ip6_mtu_id = 1; - intf.ttl_scope = 1; /* TTL */ - intf.hl_scope = 1; /* Hop Limit */ - intf.ip4_icmp_redirect = intf.ip6_icmp_redirect = 2; /* FORWARD */ - intf.ip4_pbr_icmp_redirect = intf.ip6_pbr_icmp_redirect = 2; /* FORWARD; */ - priv->r->set_l3_egress_intf(free_mac, &intf); - - priv->r->set_l3_egress_mac(L3_EGRESS_DMACS + free_mac, mac); - - mutex_unlock(&priv->reg_mutex); - - return free_mac; -} - -static int rtldsa_fib4_add(struct rtl838x_switch_priv *priv, - struct fib_entry_notifier_info *info) -{ - struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; - int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; - struct fib_nh *nh = fib_info_nh(info->fi, 0); - struct rtl83xx_route *route; - int port; - - if (rtldsa_fib4_check(priv, info, FIB_EVENT_ENTRY_ADD)) - return 0; - - port = rtl83xx_port_dev_lower_find(ndev, priv); - if (port < 0) { - dev_err(priv->dev, "lower interface %s not found\n", ndev->name); - return -ENODEV; - } - - /* Allocate route or host-route entry (if hardware supports this) */ - if (info->dst_len == 32 && priv->r->host_route_write) - route = rtl83xx_host_route_alloc(priv, nh->fib_nh_gw4); - else - route = rtl83xx_route_alloc(priv, nh->fib_nh_gw4); - - if (route) - dev_info(priv->dev, "route hashtable extended for gw %pI4\n", &nh->fib_nh_gw4); - else { - dev_err(priv->dev, "could not extend route hashtable for gw %pI4\n", &nh->fib_nh_gw4); - return -ENOSPC; - } - - route->dst_ip = info->dst; - route->prefix_len = info->dst_len; - route->nh.rvid = vlan; - - if (priv->r->set_l3_router_mac) { - u64 mac = ether_addr_to_u64(ndev->dev_addr); - - pr_debug("Local route and router MAC %pM\n", ndev->dev_addr); - if (rtl83xx_alloc_router_mac(priv, mac)) - goto out_free_rt; - - /* vid = 0: Do not care about VID */ - route->nh.if_id = rtl83xx_alloc_egress_intf(priv, mac, vlan); - if (route->nh.if_id < 0) - goto out_free_rmac; - - if (!nh->fib_nh_gw4) { - int slot; - - route->nh.mac = mac; - route->nh.port = priv->r->port_ignore; - route->attr.valid = true; - route->attr.action = ROUTE_ACT_TRAP2CPU; - route->attr.type = 0; - - slot = priv->r->find_l3_slot(route, false); - pr_debug("%s: Got slot for route: %d\n", __func__, slot); - priv->r->host_route_write(slot, route); - } - } - - /* We need to resolve the mac address of the GW */ - if (nh->fib_nh_gw4) - rtl83xx_port_ipv4_resolve(priv, ndev, nh->fib_nh_gw4); - - nh->fib_nh_flags |= RTNH_F_OFFLOAD; - - return 0; - -out_free_rmac: -out_free_rt: - return 0; -} - -static int rtl83xx_fib6_add(struct rtl838x_switch_priv *priv, - struct fib6_entry_notifier_info *info) -{ - pr_debug("In %s\n", __func__); -/* nh->fib_nh_flags |= RTNH_F_OFFLOAD; */ - - return 0; -} - -struct net_event_work { - struct work_struct work; - struct rtl838x_switch_priv *priv; - u64 mac; - u32 gw_addr; -}; - -static void rtl83xx_net_event_work_do(struct work_struct *work) -{ - struct net_event_work *net_work = - container_of(work, struct net_event_work, work); - struct rtl838x_switch_priv *priv = net_work->priv; - - rtl83xx_l3_nexthop_update(priv, net_work->gw_addr, net_work->mac); - - kfree(net_work); -} - -static int rtl83xx_netevent_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct rtl838x_switch_priv *priv; - struct net_device *dev; - struct neighbour *n = ptr; - int err, port; - struct net_event_work *net_work; - - priv = container_of(this, struct rtl838x_switch_priv, ne_nb); - - switch (event) { - case NETEVENT_NEIGH_UPDATE: - /* ignore events for HW with missing L3 offloading implementation */ - if (!priv->r->l3_setup) - return NOTIFY_DONE; - - if (n->tbl != &arp_tbl) - return NOTIFY_DONE; - dev = n->dev; - port = rtl83xx_port_dev_lower_find(dev, priv); - if (port < 0 || !(n->nud_state & NUD_VALID)) { - pr_debug("%s: Neigbour invalid, not updating\n", __func__); - return NOTIFY_DONE; - } - - net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC); - if (!net_work) - return NOTIFY_BAD; - - INIT_WORK(&net_work->work, rtl83xx_net_event_work_do); - net_work->priv = priv; - - net_work->mac = ether_addr_to_u64(n->ha); - net_work->gw_addr = *(__be32 *)n->primary_key; - - pr_debug("%s: updating neighbour on port %d, mac %016llx\n", - __func__, port, net_work->mac); - queue_work(priv->wq, &net_work->work); - if (err) - netdev_warn(dev, "failed to handle neigh update (err %d)\n", err); - break; - } - - return NOTIFY_DONE; -} - -struct rtl83xx_fib_event_work { - struct work_struct work; - union { - struct fib_entry_notifier_info fen_info; - struct fib6_entry_notifier_info fen6_info; - struct fib_rule_notifier_info fr_info; - }; - struct rtl838x_switch_priv *priv; - bool is_fib6; - unsigned long event; -}; - -static void rtl83xx_fib_event_work_do(struct work_struct *work) -{ - struct rtl83xx_fib_event_work *fib_work = - container_of(work, struct rtl83xx_fib_event_work, work); - struct rtl838x_switch_priv *priv = fib_work->priv; - struct fib_rule *rule; - int err; - - /* Protect internal structures from changes */ - rtnl_lock(); - pr_debug("%s: doing work, event %ld\n", __func__, fib_work->event); - switch (fib_work->event) { - case FIB_EVENT_ENTRY_ADD: - case FIB_EVENT_ENTRY_REPLACE: - case FIB_EVENT_ENTRY_APPEND: - if (fib_work->is_fib6) - err = rtl83xx_fib6_add(priv, &fib_work->fen6_info); - else - err = rtldsa_fib4_add(priv, &fib_work->fen_info); - if (err) - dev_err(priv->dev, "fib_add() failed\n"); - - fib_info_put(fib_work->fen_info.fi); - break; - case FIB_EVENT_ENTRY_DEL: - err = rtldsa_fib4_del(priv, &fib_work->fen_info); - if (err) - dev_err(priv->dev, "fib_del() failed\n"); - - fib_info_put(fib_work->fen_info.fi); - break; - case FIB_EVENT_RULE_ADD: - case FIB_EVENT_RULE_DEL: - rule = fib_work->fr_info.rule; - if (!fib4_rule_default(rule)) - pr_err("%s: FIB4 default rule failed\n", __func__); - fib_rule_put(rule); - break; - } - rtnl_unlock(); - kfree(fib_work); -} - -/* Called with rcu_read_lock() */ -static int rtl83xx_fib_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct fib_notifier_info *info = ptr; - struct rtl838x_switch_priv *priv; - struct rtl83xx_fib_event_work *fib_work; - - if ((info->family != AF_INET && info->family != AF_INET6 && - info->family != RTNL_FAMILY_IPMR && - info->family != RTNL_FAMILY_IP6MR)) - return NOTIFY_DONE; - - priv = container_of(this, struct rtl838x_switch_priv, fib_nb); - - /* ignore FIB events for HW with missing L3 offloading implementation */ - if (!priv->r->l3_setup) - return NOTIFY_DONE; - - fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); - if (!fib_work) - return NOTIFY_BAD; - - INIT_WORK(&fib_work->work, rtl83xx_fib_event_work_do); - fib_work->priv = priv; - fib_work->event = event; - fib_work->is_fib6 = false; - - switch (event) { - case FIB_EVENT_ENTRY_ADD: - case FIB_EVENT_ENTRY_REPLACE: - case FIB_EVENT_ENTRY_APPEND: - case FIB_EVENT_ENTRY_DEL: - pr_debug("%s: FIB_ENTRY ADD/DEL, event %ld\n", __func__, event); - if (info->family == AF_INET) { - struct fib_entry_notifier_info *fen_info = ptr; - - if (fen_info->fi->fib_nh_is_v6) { - NL_SET_ERR_MSG_MOD(info->extack, - "IPv6 gateway with IPv4 route is not supported"); - kfree(fib_work); - return notifier_from_errno(-EINVAL); - } - - memcpy(&fib_work->fen_info, ptr, sizeof(fib_work->fen_info)); - /* Take referece on fib_info to prevent it from being - * freed while work is queued. Release it afterwards. - */ - fib_info_hold(fib_work->fen_info.fi); - - } else if (info->family == AF_INET6) { - //struct fib6_entry_notifier_info *fen6_info = ptr; - pr_warn("%s: FIB_RULE ADD/DEL for IPv6 not supported\n", __func__); - kfree(fib_work); - return NOTIFY_DONE; - } - break; - - case FIB_EVENT_RULE_ADD: - case FIB_EVENT_RULE_DEL: - pr_debug("%s: FIB_RULE ADD/DEL, event: %ld\n", __func__, event); - memcpy(&fib_work->fr_info, ptr, sizeof(fib_work->fr_info)); - fib_rule_get(fib_work->fr_info.rule); - break; - } - - queue_work(priv->wq, &fib_work->work); - - return NOTIFY_DONE; -} - static irqreturn_t rtldsa_switch_irq(int irq, void *dev_id) { struct rtl838x_switch_priv *priv; @@ -1662,19 +980,19 @@ static int rtl83xx_sw_probe(struct platform_device *pdev) priv->mirror_group_ports[i] = -1; /* Initialize hash table for L3 routing */ - rhltable_init(&priv->routes, &route_ht_params); + rhltable_init(&priv->routes, &otto_l3_route_ht_params); /* Register netevent notifier callback to catch notifications about neighboring * changes to update nexthop entries for L3 routing. */ - priv->ne_nb.notifier_call = rtl83xx_netevent_event; + priv->ne_nb.notifier_call = otto_l3_netevent_notifier; if (register_netevent_notifier(&priv->ne_nb)) { priv->ne_nb.notifier_call = NULL; dev_err(dev, "Failed to register netevent notifier\n"); goto err_register_ne_nb; } - priv->fib_nb.notifier_call = rtl83xx_fib_event; + priv->fib_nb.notifier_call = otto_l3_fib_notifier; /* Register Forwarding Information Base notifier to offload routes where * possible diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c new file mode 100644 index 0000000000..7c3dd28be9 --- /dev/null +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -0,0 +1,692 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "l3.h" +#include "rtl-otto.h" + +struct otto_l3_net_event_work { + struct work_struct work; + struct rtl838x_switch_priv *priv; + u64 mac; + u32 gw_addr; +}; + +struct otto_l3_fib_event_work { + struct work_struct work; + union { + struct fib_entry_notifier_info fen_info; + struct fib6_entry_notifier_info fen6_info; + struct fib_rule_notifier_info fr_info; + }; + struct rtl838x_switch_priv *priv; + bool is_fib6; + unsigned long event; +}; + +struct otto_l3_walk_data { + struct rtl838x_switch_priv *priv; + int port; +}; + +static int otto_l3_port_lower_walk(struct net_device *lower, struct netdev_nested_priv *_priv) +{ + struct otto_l3_walk_data *data = (struct otto_l3_walk_data *)_priv->data; + struct rtl838x_switch_priv *priv = data->priv; + int ret = 0; + int index; + + index = rtl83xx_port_is_under(lower, priv); + data->port = index; + if (index >= 0) { + pr_debug("Found DSA-port, index %d\n", index); + ret = 1; + } + + return ret; +} + +static int otto_l3_port_dev_lower_find(struct net_device *dev, struct rtl838x_switch_priv *priv) +{ + struct otto_l3_walk_data data; + struct netdev_nested_priv _priv; + + data.priv = priv; + data.port = 0; + _priv.data = (void *)&data; + + netdev_walk_all_lower_dev(dev, otto_l3_port_lower_walk, &_priv); + + return data.port; +} + +/* On the RTL93xx, an L3 termination endpoint MAC address on which the router waits + * for packets to be routed needs to be allocated. + */ +static int otto_l3_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac) +{ + int free_mac = -1; + struct rtl93xx_rt_mac m; + + mutex_lock(&priv->reg_mutex); + for (int i = 0; i < MAX_ROUTER_MACS; i++) { + priv->r->get_l3_router_mac(i, &m); + if (free_mac < 0 && !m.valid) { + free_mac = i; + continue; + } + if (m.valid && m.mac == mac) { + free_mac = i; + break; + } + } + + if (free_mac < 0) { + pr_err("No free router MACs, cannot offload\n"); + mutex_unlock(&priv->reg_mutex); + return -1; + } + + m.valid = true; + m.mac = mac; + m.p_type = 0; /* An individual port, not a trunk port */ + m.p_id = 0x3f; /* Listen on any port */ + m.p_id_mask = 0; + m.vid = 0; /* Listen on any VLAN... */ + m.vid_mask = 0; /* ... so mask needs to be 0 */ + m.mac_mask = 0xffffffffffffULL; /* We want an exact match of the interface MAC */ + m.action = L3_FORWARD; /* Route the packet */ + priv->r->set_l3_router_mac(free_mac, &m); + + mutex_unlock(&priv->reg_mutex); + + return 0; +} + +static int otto_l3_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac, int vlan) +{ + int free_mac = -1; + struct rtl838x_l3_intf intf; + u64 m; + + mutex_lock(&priv->reg_mutex); + for (int i = 0; i < MAX_SMACS; i++) { + m = priv->r->get_l3_egress_mac(L3_EGRESS_DMACS + i); + if (free_mac < 0 && !m) { + free_mac = i; + continue; + } + if (m == mac) { + mutex_unlock(&priv->reg_mutex); + return i; + } + } + + if (free_mac < 0) { + pr_err("No free egress interface, cannot offload\n"); + return -1; + } + + /* Set up default egress interface 1 */ + intf.vid = vlan; + intf.smac_idx = free_mac; + intf.ip4_mtu_id = 1; + intf.ip6_mtu_id = 1; + intf.ttl_scope = 1; /* TTL */ + intf.hl_scope = 1; /* Hop Limit */ + intf.ip4_icmp_redirect = intf.ip6_icmp_redirect = 2; /* FORWARD */ + intf.ip4_pbr_icmp_redirect = intf.ip6_pbr_icmp_redirect = 2; /* FORWARD; */ + priv->r->set_l3_egress_intf(free_mac, &intf); + + priv->r->set_l3_egress_mac(L3_EGRESS_DMACS + free_mac, mac); + + mutex_unlock(&priv->reg_mutex); + + return free_mac; +} + +/* Updates an L3 next hop entry in the ROUTING table */ +static int otto_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_addr, u64 mac) +{ + struct otto_l3_route *r; + struct rhlist_head *tmp, *list; + + rcu_read_lock(); + list = rhltable_lookup(&priv->routes, &ip_addr, otto_l3_route_ht_params); + if (!list) { + rcu_read_unlock(); + return -ENOENT; + } + + rhl_for_each_entry_rcu(r, tmp, list, linkage) { + pr_debug("%s: Setting up fwding: ip %pI4, GW mac %016llx\n", + __func__, &ip_addr, mac); + + /* Reads the ROUTING table entry associated with the route */ + priv->r->route_read(r->id, r); + pr_debug("Route with id %d to %pI4 / %d\n", r->id, &r->dst_ip, r->prefix_len); + + r->nh.mac = r->nh.gw = mac; + r->nh.port = priv->r->port_ignore; + r->nh.id = r->id; + + /* Do we need to explicitly add a DMAC entry with the route's nh index? */ + if (priv->r->set_l3_egress_mac) + priv->r->set_l3_egress_mac(r->id, mac); + + /* Update ROUTING table: map gateway-mac and switch-mac id to route id */ + rtl83xx_l2_nexthop_add(priv, &r->nh); + + r->attr.valid = true; + r->attr.action = ROUTE_ACT_FORWARD; + r->attr.type = 0; + r->attr.hit = false; /* Reset route-used indicator */ + + /* Add PIE entry with dst_ip and prefix_len */ + r->pr.dip = r->dst_ip; + r->pr.dip_m = inet_make_mask(r->prefix_len); + + if (r->is_host_route) { + int slot = priv->r->find_l3_slot(r, false); + + pr_info("%s: Got slot for route: %d\n", __func__, slot); + priv->r->host_route_write(slot, r); + } else { + priv->r->route_write(r->id, r); + r->pr.fwd_sel = true; + r->pr.fwd_data = r->nh.l2_id; + r->pr.fwd_act = PIE_ACT_ROUTE_UC; + } + + if (priv->r->set_l3_nexthop) + priv->r->set_l3_nexthop(r->nh.id, r->nh.l2_id, r->nh.if_id); + + if (r->pr.id < 0) { + r->pr.packet_cntr = rtl83xx_packet_cntr_alloc(priv); + if (r->pr.packet_cntr >= 0) { + pr_info("Using packet counter %d\n", r->pr.packet_cntr); + r->pr.log_sel = true; + r->pr.log_data = r->pr.packet_cntr; + } + priv->r->pie_rule_add(priv, &r->pr); + } else { + int pkts = priv->r->packet_cntr_read(r->pr.packet_cntr); + + pr_debug("%s: total packets: %d\n", __func__, pkts); + + priv->r->pie_rule_write(priv, r->pr.id, &r->pr); + } + } + rcu_read_unlock(); + + return 0; +} + +static int otto_l3_port_ipv4_resolve(struct rtl838x_switch_priv *priv, + struct net_device *dev, __be32 ip_addr) +{ + struct neighbour *n = neigh_lookup(&arp_tbl, &ip_addr, dev); + int err = 0; + u64 mac; + + if (!n) { + n = neigh_create(&arp_tbl, &ip_addr, dev); + if (IS_ERR(n)) + return PTR_ERR(n); + } + + /* If the neigh is already resolved, then go ahead and + * install the entry, otherwise start the ARP process to + * resolve the neigh. + */ + if (n->nud_state & NUD_VALID) { + mac = ether_addr_to_u64(n->ha); + pr_info("%s: resolved mac: %016llx\n", __func__, mac); + otto_l3_nexthop_update(priv, ip_addr, mac); + } else { + pr_info("%s: need to wait\n", __func__); + neigh_event_send(n, NULL); + } + + neigh_release(n); + + return err; +} + +static void otto_l3_route_remove(struct rtl838x_switch_priv *priv, struct otto_l3_route *r) +{ + int id; + + if (rhltable_remove(&priv->routes, &r->linkage, otto_l3_route_ht_params)) + dev_warn(priv->dev, "Could not remove route\n"); + + if (r->is_host_route) { + id = priv->r->find_l3_slot(r, false); + pr_debug("%s: Got id for host route: %d\n", __func__, id); + r->attr.valid = false; + priv->r->host_route_write(id, r); + clear_bit(r->id - MAX_ROUTES, priv->host_route_use_bm); + } else { + /* If there is a HW representation of the route, delete it */ + if (priv->r->route_lookup_hw) { + id = priv->r->route_lookup_hw(r); + pr_info("%s: Got id for prefix route: %d\n", __func__, id); + r->attr.valid = false; + priv->r->route_write(id, r); + } + clear_bit(r->id, priv->route_use_bm); + } + + kfree(r); +} + +static struct otto_l3_route *otto_l3_host_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) +{ + struct otto_l3_route *r; + int idx = 0, err; + + mutex_lock(&priv->reg_mutex); + + idx = find_first_zero_bit(priv->host_route_use_bm, MAX_HOST_ROUTES); + pr_debug("%s id: %d, ip %pI4\n", __func__, idx, &ip); + + r = kzalloc(sizeof(*r), GFP_KERNEL); + if (!r) { + mutex_unlock(&priv->reg_mutex); + return r; + } + + /* We require a unique route ID irrespective of whether it is a prefix or host + * route (on RTL93xx) as we use this ID to associate a DMAC and next-hop entry + */ + r->id = idx + MAX_ROUTES; + + r->gw_ip = ip; + r->pr.id = -1; /* We still need to allocate a rule in HW */ + r->is_host_route = true; + + err = rhltable_insert(&priv->routes, &r->linkage, otto_l3_route_ht_params); + if (err) { + pr_err("Could not insert new rule\n"); + mutex_unlock(&priv->reg_mutex); + goto out_free; + } + + set_bit(idx, priv->host_route_use_bm); + + mutex_unlock(&priv->reg_mutex); + + return r; + +out_free: + kfree(r); + + return NULL; +} + +static struct otto_l3_route *otto_l3_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) +{ + struct otto_l3_route *r; + int idx = 0, err; + + mutex_lock(&priv->reg_mutex); + + idx = find_first_zero_bit(priv->route_use_bm, MAX_ROUTES); + pr_debug("%s id: %d, ip %pI4\n", __func__, idx, &ip); + + r = kzalloc(sizeof(*r), GFP_KERNEL); + if (!r) { + mutex_unlock(&priv->reg_mutex); + return r; + } + + r->id = idx; + r->gw_ip = ip; + r->pr.id = -1; /* We still need to allocate a rule in HW */ + r->is_host_route = false; + + err = rhltable_insert(&priv->routes, &r->linkage, otto_l3_route_ht_params); + if (err) { + pr_err("Could not insert new rule\n"); + mutex_unlock(&priv->reg_mutex); + goto out_free; + } + + set_bit(idx, priv->route_use_bm); + + mutex_unlock(&priv->reg_mutex); + + return r; + +out_free: + kfree(r); + + return NULL; +} + +static int otto_l3_fib_check_v4(struct rtl838x_switch_priv *priv, + struct fib_entry_notifier_info *info, + enum fib_event_type event) +{ + struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; + int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; + struct fib_nh *nh = fib_info_nh(info->fi, 0); + char gw_message[32] = ""; + + if (nh->fib_nh_gw4) + snprintf(gw_message, sizeof(gw_message), "via %pI4 ", &nh->fib_nh_gw4); + + dev_info(priv->dev, "%s IPv4 route %pI4/%d %s(VLAN %d, MAC %pM)\n", + event == FIB_EVENT_ENTRY_ADD ? "add" : "delete", + &info->dst, info->dst_len, gw_message, vlan, ndev->dev_addr); + + if ((info->type == RTN_BROADCAST) || ipv4_is_loopback(info->dst) || !info->dst) { + dev_warn(priv->dev, "skip loopback/broadcast addresses and default routes\n"); + return -EINVAL; + } + + return 0; +} + +static int otto_l3_fib_add_v4(struct rtl838x_switch_priv *priv, + struct fib_entry_notifier_info *info) +{ + struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; + int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; + struct fib_nh *nh = fib_info_nh(info->fi, 0); + struct otto_l3_route *route; + int port; + + if (otto_l3_fib_check_v4(priv, info, FIB_EVENT_ENTRY_ADD)) + return 0; + + port = otto_l3_port_dev_lower_find(ndev, priv); + if (port < 0) { + dev_err(priv->dev, "lower interface %s not found\n", ndev->name); + return -ENODEV; + } + + /* Allocate route or host-route entry (if hardware supports this) */ + if (info->dst_len == 32 && priv->r->host_route_write) + route = otto_l3_host_route_alloc(priv, nh->fib_nh_gw4); + else + route = otto_l3_route_alloc(priv, nh->fib_nh_gw4); + + if (route) + dev_info(priv->dev, "route hashtable extended for gw %pI4\n", &nh->fib_nh_gw4); + else { + dev_err(priv->dev, "could not extend route hashtable for gw %pI4\n", &nh->fib_nh_gw4); + return -ENOSPC; + } + + route->dst_ip = info->dst; + route->prefix_len = info->dst_len; + route->nh.rvid = vlan; + + if (priv->r->set_l3_router_mac) { + u64 mac = ether_addr_to_u64(ndev->dev_addr); + + pr_debug("Local route and router MAC %pM\n", ndev->dev_addr); + if (otto_l3_alloc_router_mac(priv, mac)) + goto out_free_rt; + + /* vid = 0: Do not care about VID */ + route->nh.if_id = otto_l3_alloc_egress_intf(priv, mac, vlan); + if (route->nh.if_id < 0) + goto out_free_rmac; + + if (!nh->fib_nh_gw4) { + int slot; + + route->nh.mac = mac; + route->nh.port = priv->r->port_ignore; + route->attr.valid = true; + route->attr.action = ROUTE_ACT_TRAP2CPU; + route->attr.type = 0; + + slot = priv->r->find_l3_slot(route, false); + pr_debug("%s: Got slot for route: %d\n", __func__, slot); + priv->r->host_route_write(slot, route); + } + } + + /* We need to resolve the mac address of the GW */ + if (nh->fib_nh_gw4) + otto_l3_port_ipv4_resolve(priv, ndev, nh->fib_nh_gw4); + + nh->fib_nh_flags |= RTNH_F_OFFLOAD; + + return 0; + +out_free_rmac: +out_free_rt: + return 0; +} + +static int otto_l3_fib_del_v4(struct rtl838x_switch_priv *priv, + struct fib_entry_notifier_info *info) +{ + struct fib_nh *nh = fib_info_nh(info->fi, 0); + struct rhlist_head *tmp, *list; + struct otto_l3_route *route; + + if (otto_l3_fib_check_v4(priv, info, FIB_EVENT_ENTRY_DEL)) + return 0; + + rcu_read_lock(); + list = rhltable_lookup(&priv->routes, &nh->fib_nh_gw4, otto_l3_route_ht_params); + if (!list) { + rcu_read_unlock(); + dev_err(priv->dev, "no such gateway: %pI4\n", &nh->fib_nh_gw4); + return -ENOENT; + } + rhl_for_each_entry_rcu(route, tmp, list, linkage) { + if (route->dst_ip == info->dst && route->prefix_len == info->dst_len) { + dev_info(priv->dev, "found a route with id %d, nh-id %d\n", + route->id, route->nh.id); + break; + } + } + rcu_read_unlock(); + + rtl83xx_l2_nexthop_rm(priv, &route->nh); + + dev_info(priv->dev, "releasing packet counter %d\n", route->pr.packet_cntr); + set_bit(route->pr.packet_cntr, priv->packet_cntr_use_bm); + priv->r->pie_rule_rm(priv, &route->pr); + + otto_l3_route_remove(priv, route); + + nh->fib_nh_flags &= ~RTNH_F_OFFLOAD; + + return 0; +} + +static int otto_l3_fib_add_v6(struct rtl838x_switch_priv *priv, + struct fib6_entry_notifier_info *info) +{ + pr_debug("In %s\n", __func__); +/* nh->fib_nh_flags |= RTNH_F_OFFLOAD; */ + + return 0; +} + +static void otto_l3_fib_event_work_do(struct work_struct *work) +{ + struct otto_l3_fib_event_work *fib_work = + container_of(work, struct otto_l3_fib_event_work, work); + struct rtl838x_switch_priv *priv = fib_work->priv; + struct fib_rule *rule; + int err; + + /* Protect internal structures from changes */ + rtnl_lock(); + pr_debug("%s: doing work, event %ld\n", __func__, fib_work->event); + switch (fib_work->event) { + case FIB_EVENT_ENTRY_ADD: + case FIB_EVENT_ENTRY_REPLACE: + case FIB_EVENT_ENTRY_APPEND: + if (fib_work->is_fib6) + err = otto_l3_fib_add_v6(priv, &fib_work->fen6_info); + else + err = otto_l3_fib_add_v4(priv, &fib_work->fen_info); + if (err) + dev_err(priv->dev, "fib_add() failed\n"); + + fib_info_put(fib_work->fen_info.fi); + break; + case FIB_EVENT_ENTRY_DEL: + err = otto_l3_fib_del_v4(priv, &fib_work->fen_info); + if (err) + dev_err(priv->dev, "fib_del() failed\n"); + + fib_info_put(fib_work->fen_info.fi); + break; + case FIB_EVENT_RULE_ADD: + case FIB_EVENT_RULE_DEL: + rule = fib_work->fr_info.rule; + if (!fib4_rule_default(rule)) + pr_err("%s: FIB4 default rule failed\n", __func__); + fib_rule_put(rule); + break; + } + rtnl_unlock(); + kfree(fib_work); +} + + +/* Called with rcu_read_lock() */ +int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct fib_notifier_info *info = ptr; + struct rtl838x_switch_priv *priv; + struct otto_l3_fib_event_work *fib_work; + + if ((info->family != AF_INET && info->family != AF_INET6 && + info->family != RTNL_FAMILY_IPMR && + info->family != RTNL_FAMILY_IP6MR)) + return NOTIFY_DONE; + + priv = container_of(this, struct rtl838x_switch_priv, fib_nb); + + /* ignore FIB events for HW with missing L3 offloading implementation */ + if (!priv->r->l3_setup) + return NOTIFY_DONE; + + fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); + if (!fib_work) + return NOTIFY_BAD; + + INIT_WORK(&fib_work->work, otto_l3_fib_event_work_do); + fib_work->priv = priv; + fib_work->event = event; + fib_work->is_fib6 = false; + + switch (event) { + case FIB_EVENT_ENTRY_ADD: + case FIB_EVENT_ENTRY_REPLACE: + case FIB_EVENT_ENTRY_APPEND: + case FIB_EVENT_ENTRY_DEL: + pr_debug("%s: FIB_ENTRY ADD/DEL, event %ld\n", __func__, event); + if (info->family == AF_INET) { + struct fib_entry_notifier_info *fen_info = ptr; + + if (fen_info->fi->fib_nh_is_v6) { + NL_SET_ERR_MSG_MOD(info->extack, + "IPv6 gateway with IPv4 route is not supported"); + kfree(fib_work); + return notifier_from_errno(-EINVAL); + } + + memcpy(&fib_work->fen_info, ptr, sizeof(fib_work->fen_info)); + /* Take referece on fib_info to prevent it from being + * freed while work is queued. Release it afterwards. + */ + fib_info_hold(fib_work->fen_info.fi); + + } else if (info->family == AF_INET6) { + //struct fib6_entry_notifier_info *fen6_info = ptr; + pr_warn("%s: FIB_RULE ADD/DEL for IPv6 not supported\n", __func__); + kfree(fib_work); + return NOTIFY_DONE; + } + break; + + case FIB_EVENT_RULE_ADD: + case FIB_EVENT_RULE_DEL: + pr_debug("%s: FIB_RULE ADD/DEL, event: %ld\n", __func__, event); + memcpy(&fib_work->fr_info, ptr, sizeof(fib_work->fr_info)); + fib_rule_get(fib_work->fr_info.rule); + break; + } + + queue_work(priv->wq, &fib_work->work); + + return NOTIFY_DONE; +} + +static void otto_l3_net_event_work_do(struct work_struct *work) +{ + struct otto_l3_net_event_work *net_work = + container_of(work, struct otto_l3_net_event_work, work); + struct rtl838x_switch_priv *priv = net_work->priv; + + otto_l3_nexthop_update(priv, net_work->gw_addr, net_work->mac); + + kfree(net_work); +} + +int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct rtl838x_switch_priv *priv; + struct net_device *dev; + struct neighbour *n = ptr; + int err, port; + struct otto_l3_net_event_work *net_work; + + priv = container_of(this, struct rtl838x_switch_priv, ne_nb); + + switch (event) { + case NETEVENT_NEIGH_UPDATE: + /* ignore events for HW with missing L3 offloading implementation */ + if (!priv->r->l3_setup) + return NOTIFY_DONE; + + if (n->tbl != &arp_tbl) + return NOTIFY_DONE; + dev = n->dev; + port = otto_l3_port_dev_lower_find(dev, priv); + if (port < 0 || !(n->nud_state & NUD_VALID)) { + pr_debug("%s: Neigbour invalid, not updating\n", __func__); + return NOTIFY_DONE; + } + + net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC); + if (!net_work) + return NOTIFY_BAD; + + INIT_WORK(&net_work->work, otto_l3_net_event_work_do); + net_work->priv = priv; + + net_work->mac = ether_addr_to_u64(n->ha); + net_work->gw_addr = *(__be32 *)n->primary_key; + + pr_debug("%s: updating neighbour on port %d, mac %016llx\n", + __func__, port, net_work->mac); + queue_work(priv->wq, &net_work->work); + if (err) + netdev_warn(dev, "failed to handle neigh update (err %d)\n", err); + break; + } + + return NOTIFY_DONE; +} diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h new file mode 100644 index 0000000000..5025798404 --- /dev/null +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _OTTO_L3_H +#define _OTTO_L3_H + +#include "rtl-otto.h" + +struct otto_l3_route_attr { + bool valid; + bool hit; + bool ttl_dec; + bool ttl_check; + bool dst_null; + bool qos_as; + u8 qos_prio; + u8 type; + u8 action; +}; + +struct otto_l3_nexthop { + u16 id; /* ID: L3_NEXT_HOP table-index or route-index set in L2_NEXT_HOP */ + u32 dev_id; + u16 port; + u16 vid; /* VLAN-ID for L2 table entry (saved from L2-UC entry) */ + u16 rvid; /* Relay VID/FID for the L2 table entry */ + u64 mac; /* The MAC address of the entry in the L2_NEXT_HOP table */ + u16 mac_id; + u16 l2_id; /* Index of this next hop forwarding entry in L2 FIB table */ + u64 gw; /* The gateway MAC address packets are forwarded to */ + int if_id; /* Interface (into L3_EGR_INTF_IDX) */ +}; + +struct otto_l3_route { + u32 gw_ip; /* IP of the route's gateway */ + u32 dst_ip; /* IP of the destination net */ + struct in6_addr dst_ip6; + int prefix_len; /* Network prefix len of the destination net */ + bool is_host_route; + int id; /* ID number of this route */ + struct rhlist_head linkage; + u16 switch_mac_id; /* Index into switch's own MACs, RTL839X only */ + struct otto_l3_nexthop nh; + struct pie_rule pr; + struct otto_l3_route_attr attr; +}; + +static const struct rhashtable_params otto_l3_route_ht_params = { + .key_len = sizeof(u32), + .key_offset = offsetof(struct otto_l3_route, gw_ip), + .head_offset = offsetof(struct otto_l3_route, linkage), +}; + +int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event, void *ptr); +int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, void *ptr); + +#endif /* _OTTO_L3_H */ diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index 6ed1ed4fc1..8a1aca7cfa 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -898,6 +898,8 @@ typedef enum { */ #define RTLDSA_COUNTERS_FAST_POLL_INTERVAL (3 * HZ) +struct otto_l3_route; + enum pbvlan_type { PBVLAN_TYPE_INNER = 0, PBVLAN_TYPE_OUTER, @@ -1302,19 +1304,6 @@ struct rtl93xx_rt_mac { u64 mac_mask; }; -struct rtl83xx_nexthop { - u16 id; /* ID: L3_NEXT_HOP table-index or route-index set in L2_NEXT_HOP */ - u32 dev_id; - u16 port; - u16 vid; /* VLAN-ID for L2 table entry (saved from L2-UC entry) */ - u16 rvid; /* Relay VID/FID for the L2 table entry */ - u64 mac; /* The MAC address of the entry in the L2_NEXT_HOP table */ - u16 mac_id; - u16 l2_id; /* Index of this next hop forwarding entry in L2 FIB table */ - u64 gw; /* The gateway MAC address packets are forwarded to */ - int if_id; /* Interface (into L3_EGR_INTF_IDX) */ -}; - struct rtl838x_switch_priv; struct rtl83xx_flow { @@ -1326,32 +1315,6 @@ struct rtl83xx_flow { u32 flags; }; -struct rtl93xx_route_attr { - bool valid; - bool hit; - bool ttl_dec; - bool ttl_check; - bool dst_null; - bool qos_as; - u8 qos_prio; - u8 type; - u8 action; -}; - -struct rtl83xx_route { - u32 gw_ip; /* IP of the route's gateway */ - u32 dst_ip; /* IP of the destination net */ - struct in6_addr dst_ip6; - int prefix_len; /* Network prefix len of the destination net */ - bool is_host_route; - int id; /* ID number of this route */ - struct rhlist_head linkage; - u16 switch_mac_id; /* Index into switch's own MACs, RTL839X only */ - struct rtl83xx_nexthop nh; - struct pie_rule pr; - struct rtl93xx_route_attr attr; -}; - /** * struct rtldsa_mirror_config - Mirror configuration for specific group and port */ @@ -1474,16 +1437,16 @@ struct rtldsa_config { void (*l2_learning_setup)(void); u32 (*packet_cntr_read)(int counter); void (*packet_cntr_clear)(int counter); - void (*route_read)(int idx, struct rtl83xx_route *rt); - void (*route_write)(int idx, struct rtl83xx_route *rt); - void (*host_route_write)(int idx, struct rtl83xx_route *rt); + void (*route_read)(int idx, struct otto_l3_route *rt); + void (*route_write)(int idx, struct otto_l3_route *rt); + void (*host_route_write)(int idx, struct otto_l3_route *rt); int (*l3_setup)(struct rtl838x_switch_priv *priv); void (*set_l3_nexthop)(int idx, u16 dmac_id, u16 interface); void (*get_l3_nexthop)(int idx, u16 *dmac_id, u16 *interface); u64 (*get_l3_egress_mac)(u32 idx); void (*set_l3_egress_mac)(u32 idx, u64 mac); - int (*find_l3_slot)(struct rtl83xx_route *rt, bool must_exist); - int (*route_lookup_hw)(struct rtl83xx_route *rt); + int (*find_l3_slot)(struct otto_l3_route *rt, bool must_exist); + int (*route_lookup_hw)(struct otto_l3_route *rt); void (*get_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m); void (*set_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m); void (*set_l3_egress_intf)(int idx, struct rtl838x_l3_intf *intf); @@ -1789,6 +1752,12 @@ void rtldsa_counters_unlock_table(struct rtl838x_switch_priv *priv, int port) void rtldsa_update_counters_atomically(struct rtl838x_switch_priv *priv, int port); + +struct otto_l3_nexthop; +int rtl83xx_l2_nexthop_add(struct rtl838x_switch_priv *priv, struct otto_l3_nexthop *nh); +int rtl83xx_l2_nexthop_rm(struct rtl838x_switch_priv *priv, struct otto_l3_nexthop *nh); + + extern int rtldsa_max_available_queue[]; extern int rtldsa_default_queue_weights[]; diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c index aa118ff7ca..ae193e2537 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c @@ -5,6 +5,7 @@ #include #include +#include "l3.h" #include "rtl-otto.h" #define RTL838X_VLAN_PORT_TAG_STS_UNTAG 0x0 @@ -1627,7 +1628,7 @@ static void rtl838x_packet_cntr_clear(int counter) rtl_table_release(r); } -static void rtl838x_route_read(int idx, struct rtl83xx_route *rt) +static void rtl838x_route_read(int idx, struct otto_l3_route *rt) { /* Read ROUTING table (2) via register RTL8380_TBL_1 */ struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); @@ -1643,7 +1644,7 @@ static void rtl838x_route_read(int idx, struct rtl83xx_route *rt) rtl_table_release(r); } -static void rtl838x_route_write(int idx, struct rtl83xx_route *rt) +static void rtl838x_route_write(int idx, struct otto_l3_route *rt) { /* Access ROUTING table (2) via register RTL8380_TBL_1 */ struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c index b932cee3b1..9e9d11a544 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c @@ -3,6 +3,7 @@ #include #include +#include "l3.h" #include "rtl-otto.h" #define RTL839X_VLAN_PORT_TAG_STS_UNTAG 0x0 @@ -1532,7 +1533,7 @@ static void rtl839x_packet_cntr_clear(int counter) rtl_table_release(r); } -static void rtl839x_route_read(int idx, struct rtl83xx_route *rt) +static void rtl839x_route_read(int idx, struct otto_l3_route *rt) { u64 v; /* Read ROUTING table (2) via register RTL8390_TBL_1 */ @@ -1551,7 +1552,7 @@ static void rtl839x_route_read(int idx, struct rtl83xx_route *rt) rtl_table_release(r); } -static void rtl839x_route_write(int idx, struct rtl83xx_route *rt) +static void rtl839x_route_write(int idx, struct otto_l3_route *rt) { u32 v; diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c index 3e406824f5..1c83510d9e 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c @@ -4,6 +4,7 @@ #include #include +#include "l3.h" #include "rtl-otto.h" #define RTL930X_VLAN_PORT_TAG_STS_INTERNAL 0x0 @@ -1262,7 +1263,7 @@ static u32 rtl930x_l3_hash4(u32 ip, int algorithm, bool move_dip) /* Read a prefix route entry from the L3_PREFIX_ROUTE_IPUC table * We currently only support IPv4 and IPv6 unicast route */ -static void rtl930x_route_read(int idx, struct rtl83xx_route *rt) +static void rtl930x_route_read(int idx, struct otto_l3_route *rt) { u32 v, ip4_m; bool host_route, default_route; @@ -1344,7 +1345,7 @@ static void rtl930x_net6_mask(int prefix_len, struct in6_addr *ip6_m) /* Read a host route entry from the table using its index * We currently only support IPv4 and IPv6 unicast route */ -static void rtl930x_host_route_read(int idx, struct rtl83xx_route *rt) +static void rtl930x_host_route_read(int idx, struct otto_l3_route *rt) { u32 v; /* Read L3_HOST_ROUTE_IPUC table (1) via register RTL9300_TBL_1 */ @@ -1396,7 +1397,7 @@ out: /* Write a host route entry from the table using its index * We currently only support IPv4 and IPv6 unicast route */ -static void rtl930x_host_route_write(int idx, struct rtl83xx_route *rt) +static void rtl930x_host_route_write(int idx, struct otto_l3_route *rt) { u32 v; /* Access L3_HOST_ROUTE_IPUC table (1) via register RTL9300_TBL_1 */ @@ -1451,7 +1452,7 @@ out: /* Look up the index of a prefix route in the routing table CAM for unicast IPv4/6 routes * using hardware offload. */ -static int rtl930x_route_lookup_hw(struct rtl83xx_route *rt) +static int rtl930x_route_lookup_hw(struct otto_l3_route *rt) { u32 ip4_m, v; struct in6_addr ip6_m; @@ -1492,11 +1493,11 @@ static int rtl930x_route_lookup_hw(struct rtl83xx_route *rt) return -1; } -static int rtl930x_find_l3_slot(struct rtl83xx_route *rt, bool must_exist) +static int rtl930x_find_l3_slot(struct otto_l3_route *rt, bool must_exist) { int slot_width, algorithm, addr, idx; u32 hash; - struct rtl83xx_route route_entry; + struct otto_l3_route route_entry; /* IPv6 entries take up 3 slots */ slot_width = (rt->attr.type == 0) || (rt->attr.type == 2) ? 1 : 3; @@ -1529,7 +1530,7 @@ static int rtl930x_find_l3_slot(struct rtl83xx_route *rt, bool must_exist) /* Write a prefix route into the routing table CAM at position idx * Currently only IPv4 and IPv6 unicast routes are supported */ -static void rtl930x_route_write(int idx, struct rtl83xx_route *rt) +static void rtl930x_route_write(int idx, struct otto_l3_route *rt) { u32 v, ip4_m; struct in6_addr ip6_m; From 113103739144f7e53eb8236f23d3012f104981f3 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Thu, 25 Jun 2026 10:05:28 +0200 Subject: [PATCH 168/228] realtek: l3: provide probe/remove helpers The L3 code is manually initialized and finalized in the DSA probe/remove functions. Relocate the code into seperate helpers that encapsule all required steps. Make no longer exposed L3 functions static. Link: https://github.com/openwrt/openwrt/pull/23937 Signed-off-by: Markus Stockhausen --- .../drivers/net/dsa/rtl83xx/common.c | 31 ++---------- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 50 ++++++++++++++++++- .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 4 +- 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c index b72b401d8e..75529ac5f5 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/common.c @@ -979,29 +979,9 @@ static int rtl83xx_sw_probe(struct platform_device *pdev) for (int i = 0; i < 4; i++) priv->mirror_group_ports[i] = -1; - /* Initialize hash table for L3 routing */ - rhltable_init(&priv->routes, &otto_l3_route_ht_params); - - /* Register netevent notifier callback to catch notifications about neighboring - * changes to update nexthop entries for L3 routing. - */ - priv->ne_nb.notifier_call = otto_l3_netevent_notifier; - if (register_netevent_notifier(&priv->ne_nb)) { - priv->ne_nb.notifier_call = NULL; - dev_err(dev, "Failed to register netevent notifier\n"); - goto err_register_ne_nb; - } - - priv->fib_nb.notifier_call = otto_l3_fib_notifier; - - /* Register Forwarding Information Base notifier to offload routes where - * possible - * Only FIBs pointing to our own netdevs are programmed into - * the device, so no need to pass a callback. - */ - err = register_fib_notifier(&init_net, &priv->fib_nb, NULL, NULL); + err = otto_l3_probe(dev, priv); if (err) - goto err_register_fib_nb; + goto err_register_l3; /* TODO: put this into l2_setup() */ switch (soc_info.family) { @@ -1026,9 +1006,7 @@ static int rtl83xx_sw_probe(struct platform_device *pdev) return 0; -err_register_fib_nb: - unregister_netevent_notifier(&priv->ne_nb); -err_register_ne_nb: +err_register_l3: dsa_switch_shutdown(priv->ds); err_register_switch: destroy_workqueue(priv->wq); @@ -1075,8 +1053,7 @@ static void rtl83xx_sw_remove(struct platform_device *pdev) * work items to avoid them still accessing the DSA structures * when they are getting shut down. */ - unregister_fib_notifier(&init_net, &priv->fib_nb); - unregister_netevent_notifier(&priv->ne_nb); + otto_l3_remove(priv); cancel_delayed_work_sync(&priv->counters_work); dsa_switch_shutdown(priv->ds); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index 7c3dd28be9..6cacf2252e 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -565,7 +565,7 @@ static void otto_l3_fib_event_work_do(struct work_struct *work) /* Called with rcu_read_lock() */ -int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event, void *ptr) +static int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event, void *ptr) { struct fib_notifier_info *info = ptr; struct rtl838x_switch_priv *priv; @@ -645,7 +645,7 @@ static void otto_l3_net_event_work_do(struct work_struct *work) kfree(net_work); } -int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, void *ptr) +static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, void *ptr) { struct rtl838x_switch_priv *priv; struct net_device *dev; @@ -690,3 +690,49 @@ int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, return NOTIFY_DONE; } + +void otto_l3_remove(struct rtl838x_switch_priv *priv) +{ + if (priv->ne_nb.notifier_call) { + unregister_netevent_notifier(&priv->ne_nb); + priv->ne_nb.notifier_call = NULL; + } + if (priv->fib_nb.notifier_call) { + unregister_fib_notifier(&init_net, &priv->fib_nb); + priv->fib_nb.notifier_call = NULL; + } +} + +int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv) +{ + int err; + + /* Initialize hash table for L3 routing */ + rhltable_init(&priv->routes, &otto_l3_route_ht_params); + + /* + * Register netevent notifier callback to catch notifications about neighboring changes + * to update nexthop entries for L3 routing. + */ + priv->ne_nb.notifier_call = otto_l3_netevent_notifier; + err = register_netevent_notifier(&priv->ne_nb); + if (err) { + priv->ne_nb.notifier_call = NULL; + return dev_err_probe(dev, err, "Failed to register netevent notifier\n"); + } + + /* + * Register Forwarding Information Base notifier to offload routes where possible. Only + * FIBs pointing to our own netdevs are programmed into the device, so no need to pass a + * callback. + */ + priv->fib_nb.notifier_call = otto_l3_fib_notifier; + err = register_fib_notifier(&init_net, &priv->fib_nb, NULL, NULL); + if (err) { + priv->fib_nb.notifier_call = NULL; + otto_l3_remove(priv); + return dev_err_probe(dev, err, "Failed to register fib event notifier\n"); + } + + return 0; +} diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index 5025798404..82fcbc8549 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -50,7 +50,7 @@ static const struct rhashtable_params otto_l3_route_ht_params = { .head_offset = offsetof(struct otto_l3_route, linkage), }; -int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event, void *ptr); -int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, void *ptr); +int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv); +void otto_l3_remove(struct rtl838x_switch_priv *priv); #endif /* _OTTO_L3_H */ From 8c2ef13ec60979a8e15cf4016d4f9ace31cabdd7 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Thu, 25 Jun 2026 10:46:17 +0200 Subject: [PATCH 169/228] realtek: l3: add private structure The DSA private structure provides an overwhelming mix of information. L3 data is part of this. Provide a new separated structure that is linked bidirectionally to the old data. For the start it only contains a reference pointer and no L3 specific data. Link: https://github.com/openwrt/openwrt/pull/23937 Signed-off-by: Markus Stockhausen --- .../linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c | 7 +++++++ .../linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h | 4 ++++ .../realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h | 1 + 3 files changed, 12 insertions(+) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index 6cacf2252e..00d4623691 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -705,8 +705,15 @@ void otto_l3_remove(struct rtl838x_switch_priv *priv) int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv) { + struct otto_l3_ctrl *ctrl; int err; + ctrl = devm_kzalloc(dev, sizeof(struct otto_l3_ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + priv->l3_ctrl = ctrl; + ctrl->priv = priv; + /* Initialize hash table for L3 routing */ rhltable_init(&priv->routes, &otto_l3_route_ht_params); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index 82fcbc8549..ac9ea1664c 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -5,6 +5,10 @@ #include "rtl-otto.h" +struct otto_l3_ctrl { + struct rtl838x_switch_priv *priv; +}; + struct otto_l3_route_attr { bool valid; bool hit; diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index 8a1aca7cfa..f81156bbd7 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -1483,6 +1483,7 @@ struct rtl838x_switch_priv { int link_state_irq; int mirror_group_ports[4]; const struct rtldsa_config *r; + struct otto_l3_ctrl *l3_ctrl; u64 irq_mask; struct dentry *dbgfs_dir; From 626cc6770b02613e9705449755035cac571039f3 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Thu, 25 Jun 2026 11:20:16 +0200 Subject: [PATCH 170/228] realtek: l3: move notifier blocks to private structure Relocate the notification handlers into the new L3 ecosystem. Link: https://github.com/openwrt/openwrt/pull/23937 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 44 +++++++++---------- .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 2 + .../drivers/net/dsa/rtl83xx/rtl-otto.h | 2 - 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index 00d4623691..db3caadb8b 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -567,17 +567,16 @@ static void otto_l3_fib_event_work_do(struct work_struct *work) /* Called with rcu_read_lock() */ static int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event, void *ptr) { - struct fib_notifier_info *info = ptr; - struct rtl838x_switch_priv *priv; + struct otto_l3_ctrl *ctrl = container_of(this, struct otto_l3_ctrl, fib_nb); + struct rtl838x_switch_priv *priv = ctrl->priv; struct otto_l3_fib_event_work *fib_work; + struct fib_notifier_info *info = ptr; if ((info->family != AF_INET && info->family != AF_INET6 && info->family != RTNL_FAMILY_IPMR && info->family != RTNL_FAMILY_IP6MR)) return NOTIFY_DONE; - priv = container_of(this, struct rtl838x_switch_priv, fib_nb); - /* ignore FIB events for HW with missing L3 offloading implementation */ if (!priv->r->l3_setup) return NOTIFY_DONE; @@ -647,13 +646,12 @@ static void otto_l3_net_event_work_do(struct work_struct *work) static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, void *ptr) { - struct rtl838x_switch_priv *priv; - struct net_device *dev; - struct neighbour *n = ptr; - int err, port; + struct otto_l3_ctrl *ctrl = container_of(this, struct otto_l3_ctrl, ne_nb); + struct rtl838x_switch_priv *priv = ctrl->priv; struct otto_l3_net_event_work *net_work; - - priv = container_of(this, struct rtl838x_switch_priv, ne_nb); + struct neighbour *n = ptr; + struct net_device *dev; + int err, port; switch (event) { case NETEVENT_NEIGH_UPDATE: @@ -693,13 +691,15 @@ static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long void otto_l3_remove(struct rtl838x_switch_priv *priv) { - if (priv->ne_nb.notifier_call) { - unregister_netevent_notifier(&priv->ne_nb); - priv->ne_nb.notifier_call = NULL; + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; + + if (ctrl->ne_nb.notifier_call) { + unregister_netevent_notifier(&ctrl->ne_nb); + ctrl->ne_nb.notifier_call = NULL; } - if (priv->fib_nb.notifier_call) { - unregister_fib_notifier(&init_net, &priv->fib_nb); - priv->fib_nb.notifier_call = NULL; + if (ctrl->fib_nb.notifier_call) { + unregister_fib_notifier(&init_net, &ctrl->fib_nb); + ctrl->fib_nb.notifier_call = NULL; } } @@ -721,10 +721,10 @@ int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv) * Register netevent notifier callback to catch notifications about neighboring changes * to update nexthop entries for L3 routing. */ - priv->ne_nb.notifier_call = otto_l3_netevent_notifier; - err = register_netevent_notifier(&priv->ne_nb); + ctrl->ne_nb.notifier_call = otto_l3_netevent_notifier; + err = register_netevent_notifier(&ctrl->ne_nb); if (err) { - priv->ne_nb.notifier_call = NULL; + ctrl->ne_nb.notifier_call = NULL; return dev_err_probe(dev, err, "Failed to register netevent notifier\n"); } @@ -733,10 +733,10 @@ int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv) * FIBs pointing to our own netdevs are programmed into the device, so no need to pass a * callback. */ - priv->fib_nb.notifier_call = otto_l3_fib_notifier; - err = register_fib_notifier(&init_net, &priv->fib_nb, NULL, NULL); + ctrl->fib_nb.notifier_call = otto_l3_fib_notifier; + err = register_fib_notifier(&init_net, &ctrl->fib_nb, NULL, NULL); if (err) { - priv->fib_nb.notifier_call = NULL; + ctrl->fib_nb.notifier_call = NULL; otto_l3_remove(priv); return dev_err_probe(dev, err, "Failed to register fib event notifier\n"); } diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index ac9ea1664c..d61087dfff 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -7,6 +7,8 @@ struct otto_l3_ctrl { struct rtl838x_switch_priv *priv; + struct notifier_block fib_nb; + struct notifier_block ne_nb; }; struct otto_l3_route_attr { diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index f81156bbd7..832f047562 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -1504,8 +1504,6 @@ struct rtl838x_switch_priv { /** @lagmembers: Port (bit) is part of any LAG */ u64 lagmembers; struct workqueue_struct *wq; - struct notifier_block ne_nb; - struct notifier_block fib_nb; bool eee_enabled; unsigned long mc_group_bm[MAX_MC_GROUPS >> 5]; struct rhashtable tc_ht; From b226f382888a961080aada251c983c2bab86506d Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Thu, 2 Apr 2026 23:47:03 +0200 Subject: [PATCH 171/228] kernel/layerscape: create files for v6.18 (from v6.12) This is an automatically generated commit. When doing `git bisect`, consider `git bisect --skip`. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- target/linux/layerscape/armv7/{config-6.12 => config-6.18} | 0 target/linux/layerscape/armv8_64b/{config-6.12 => config-6.18} | 0 .../302-arm64-dts-ls1012a-update-with-ppfe-support.patch | 0 ...303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch | 0 ...304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch | 0 ...305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch | 0 ...400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch | 0 .../701-staging-add-fsl_ppfe-driver.patch | 0 .../702-phy-Add-2.5G-SGMII-interface-mode.patch | 0 ...03-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch | 0 ...900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename target/linux/layerscape/armv7/{config-6.12 => config-6.18} (100%) rename target/linux/layerscape/armv8_64b/{config-6.12 => config-6.18} (100%) rename target/linux/layerscape/{patches-6.12 => patches-6.18}/302-arm64-dts-ls1012a-update-with-ppfe-support.patch (100%) rename target/linux/layerscape/{patches-6.12 => patches-6.18}/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch (100%) rename target/linux/layerscape/{patches-6.12 => patches-6.18}/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch (100%) rename target/linux/layerscape/{patches-6.12 => patches-6.18}/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch (100%) rename target/linux/layerscape/{patches-6.12 => patches-6.18}/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch (100%) rename target/linux/layerscape/{patches-6.12 => patches-6.18}/701-staging-add-fsl_ppfe-driver.patch (100%) rename target/linux/layerscape/{patches-6.12 => patches-6.18}/702-phy-Add-2.5G-SGMII-interface-mode.patch (100%) rename target/linux/layerscape/{patches-6.12 => patches-6.18}/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch (100%) rename target/linux/layerscape/{patches-6.12 => patches-6.18}/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch (100%) diff --git a/target/linux/layerscape/armv7/config-6.12 b/target/linux/layerscape/armv7/config-6.18 similarity index 100% rename from target/linux/layerscape/armv7/config-6.12 rename to target/linux/layerscape/armv7/config-6.18 diff --git a/target/linux/layerscape/armv8_64b/config-6.12 b/target/linux/layerscape/armv8_64b/config-6.18 similarity index 100% rename from target/linux/layerscape/armv8_64b/config-6.12 rename to target/linux/layerscape/armv8_64b/config-6.18 diff --git a/target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch b/target/linux/layerscape/patches-6.18/302-arm64-dts-ls1012a-update-with-ppfe-support.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch rename to target/linux/layerscape/patches-6.18/302-arm64-dts-ls1012a-update-with-ppfe-support.patch diff --git a/target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch b/target/linux/layerscape/patches-6.18/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch rename to target/linux/layerscape/patches-6.18/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch diff --git a/target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch b/target/linux/layerscape/patches-6.18/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch rename to target/linux/layerscape/patches-6.18/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch diff --git a/target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch b/target/linux/layerscape/patches-6.18/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch rename to target/linux/layerscape/patches-6.18/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch diff --git a/target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch b/target/linux/layerscape/patches-6.18/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch rename to target/linux/layerscape/patches-6.18/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch diff --git a/target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch b/target/linux/layerscape/patches-6.18/701-staging-add-fsl_ppfe-driver.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch rename to target/linux/layerscape/patches-6.18/701-staging-add-fsl_ppfe-driver.patch diff --git a/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-6.18/702-phy-Add-2.5G-SGMII-interface-mode.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch rename to target/linux/layerscape/patches-6.18/702-phy-Add-2.5G-SGMII-interface-mode.patch diff --git a/target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch b/target/linux/layerscape/patches-6.18/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch rename to target/linux/layerscape/patches-6.18/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch diff --git a/target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch b/target/linux/layerscape/patches-6.18/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch similarity index 100% rename from target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch rename to target/linux/layerscape/patches-6.18/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch From 9e9474fbdc248988765664ed8c89bd8b5b4d9933 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Thu, 2 Apr 2026 23:47:03 +0200 Subject: [PATCH 172/228] kernel/layerscape: restore files for v6.12 This is an automatically generated commit which aids following Kernel patch history, as git will see the move and copy as a rename thus defeating the purpose. For the original discussion see: https://lists.openwrt.org/pipermail/openwrt-devel/2023-October/041673.html Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- target/linux/layerscape/armv7/config-6.12 | 697 + target/linux/layerscape/armv8_64b/config-6.12 | 887 ++ ...dts-ls1012a-update-with-ppfe-support.patch | 228 + ...a-frdm-workaround-by-updating-qspi-f.patch | 41 + ...a-rdb-workaround-by-updating-qspi-fl.patch | 29 + ...a-rdb-Update-qspi-spi-rx-bus-width-t.patch | 34 + ...nor-Use-1-bit-mode-of-spansion-s25fs.patch | 28 + .../701-staging-add-fsl_ppfe-driver.patch | 11851 ++++++++++++++++ ...02-phy-Add-2.5G-SGMII-interface-mode.patch | 73 + ...ix-compilation-warning-for-fsl-ppfe-.patch | 239 + ...s1012a-frdm-add-GPIO-hog-for-PHY-res.patch | 36 + 11 files changed, 14143 insertions(+) create mode 100644 target/linux/layerscape/armv7/config-6.12 create mode 100644 target/linux/layerscape/armv8_64b/config-6.12 create mode 100644 target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch create mode 100644 target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch create mode 100644 target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch create mode 100644 target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch create mode 100644 target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch create mode 100644 target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch create mode 100644 target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch create mode 100644 target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch create mode 100644 target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch diff --git a/target/linux/layerscape/armv7/config-6.12 b/target/linux/layerscape/armv7/config-6.12 new file mode 100644 index 0000000000..cf9d642980 --- /dev/null +++ b/target/linux/layerscape/armv7/config-6.12 @@ -0,0 +1,697 @@ +CONFIG_AD525X_DPOT=y +CONFIG_AD525X_DPOT_I2C=y +# CONFIG_AD525X_DPOT_SPI is not set +CONFIG_ALIGNMENT_TRAP=y +CONFIG_APDS9802ALS=y +CONFIG_AQUANTIA_PHY=y +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MULTIPLATFORM=y +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MXC=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y +CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARM_ERRATA_430973=y +CONFIG_ARM_ERRATA_643719=y +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_754327=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_ARM_ERRATA_798181=y +CONFIG_ARM_GIC=y +CONFIG_ARM_HAS_GROUP_RELOCS=y +CONFIG_ARM_HEAVY_MB=y +# CONFIG_ARM_HIGHBANK_CPUIDLE is not set +# CONFIG_ARM_IMX8M_DDRC_DEVFREQ is not set +# CONFIG_ARM_IMX_BUS_DEVFREQ is not set +# CONFIG_ARM_IMX_CPUFREQ_DT is not set +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_LPAE=y +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_ARM_PSCI=y +CONFIG_ARM_PSCI_FW=y +# CONFIG_ARM_SMMU is not set +CONFIG_ARM_THUMB=y +CONFIG_ARM_THUMBEE=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_ATAGS=y +CONFIG_AUTOFS_FS=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BATTERY_SBS=y +CONFIG_BCM_NET_PHYLIB=y +CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSG_COMMON=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=262144 +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_MQ_VIRTIO=y +CONFIG_BLK_PM=y +CONFIG_BOUNCE=y +CONFIG_BROADCOM_PHY=y +CONFIG_BUFFER_HEAD=y +CONFIG_CACHE_L2X0=y +CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y +CONFIG_CDROM=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_CHR_DEV_SG=y +CONFIG_CLKSRC_IMX_GPT=y +CONFIG_CLKSRC_MMIO=y +# CONFIG_CLK_IMX8MM is not set +# CONFIG_CLK_IMX8MN is not set +# CONFIG_CLK_IMX8MP is not set +# CONFIG_CLK_IMX8MQ is not set +# CONFIG_CLK_IMX8ULP is not set +# CONFIG_CLK_IMX93 is not set +# CONFIG_CLK_IMX95_BLK_CTL is not set +CONFIG_CLK_QORIQ=y +# CONFIG_CLK_VEXPRESS_OSC is not set +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMA=y +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_SIZE_MBYTES=64 +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SYSFS is not set +CONFIG_CMDLINE_PARTITION=y +CONFIG_COMMON_CLK=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CONTIG_ALLOC=y +CONFIG_COREDUMP=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MITIGATIONS=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SPECTRE=y +CONFIG_CPU_THERMAL=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +CONFIG_CRC_CCITT=y +CONFIG_CRC_ITU_T=y +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_CURRENT_POINTER_IN_TPIDRURO=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_ALIGN_RODATA=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_DEVFREQ_GOV_PASSIVE is not set +# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set +# CONFIG_DEVFREQ_GOV_POWERSAVE is not set +# CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND is not set +# CONFIG_DEVFREQ_GOV_USERSPACE is not set +# CONFIG_DEVFREQ_THERMAL is not set +CONFIG_DMADEVICES=y +CONFIG_DMA_CMA=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_NEED_SYNC=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS_HELPERS=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DNOTIFY=y +CONFIG_DTC=y +CONFIG_DT_IDLE_STATES=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_DW_DMAC=y +CONFIG_DW_DMAC_CORE=y +CONFIG_DW_WATCHDOG=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EEPROM_93CX6=y +CONFIG_EEPROM_AT24=y +CONFIG_ELF_CORE=y +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_F2FS_FS=y +CONFIG_FAILOVER=y +CONFIG_FAT_FS=y +# CONFIG_FEC is not set +CONFIG_FHANDLE=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FREEZER=y +CONFIG_FSL_EDMA=y +CONFIG_FSL_GUTS=y +CONFIG_FSL_IFC=y +# CONFIG_FSL_PPFE is not set +CONFIG_FSL_PQ_MDIO=y +CONFIG_FSL_RCPM=y +CONFIG_FSL_XGMAC_MDIO=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +CONFIG_FTRACE=y +# CONFIG_FTRACE_SYSCALLS is not set +CONFIG_FUNCTION_ALIGNMENT=0 +CONFIG_FUSE_FS=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_CACHE=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_VDSO_32=y +CONFIG_GIANFAR=y +CONFIG_GLOB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_MPC8XXX=y +CONFIG_GPIO_MXC=y +CONFIG_GPIO_VF610=y +# CONFIG_HARDEN_BRANCH_HISTORY is not set +# CONFIG_HARDEN_BRANCH_PREDICTOR is not set +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAVE_SMP=y +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y +# CONFIG_HIST_TRIGGERS is not set +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HVC_DRIVER=y +CONFIG_HW_RANDOM=y +CONFIG_HZ_FIXED=0 +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_DEMUX_PINCTRL=y +CONFIG_I2C_DESIGNWARE_CORE=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_IMX=y +# CONFIG_I2C_IMX_LPI2C is not set +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_MUX_PINCTRL=y +CONFIG_I2C_RK3X=y +CONFIG_I2C_SLAVE=y +CONFIG_I2C_SLAVE_EEPROM=y +# CONFIG_I2C_SLAVE_TESTUNIT is not set +CONFIG_I2C_XILINX=y +CONFIG_ICPLUS_PHY=y +CONFIG_ICS932S401=y +CONFIG_IMX2_WDT=y +# CONFIG_IMX7ULP_WDT is not set +# CONFIG_IMX8MM_THERMAL is not set +CONFIG_IMX_DMA=y +# CONFIG_IMX_GPCV2_PM_DOMAINS is not set +CONFIG_IMX_INTMUX=y +# CONFIG_IMX_IRQSTEER is not set +# CONFIG_IMX_MU_MSI is not set +CONFIG_IMX_SDMA=y +# CONFIG_IMX_WEIM is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INPUT=y +# CONFIG_INPUT_BBNSM_PWRKEY is not set +# CONFIG_IOMMUFD is not set +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set +CONFIG_IOMMU_SUPPORT=y +CONFIG_IPC_NS=y +CONFIG_IRQCHIP=y +CONFIG_IRQSTACKS=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +# CONFIG_ISDN is not set +CONFIG_ISL29003=y +CONFIG_JBD2=y +CONFIG_KALLSYMS=y +CONFIG_KCMP=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_XZ is not set +CONFIG_KEXEC=y +CONFIG_KEXEC_CORE=y +CONFIG_KMAP_LOCAL=y +CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y +CONFIG_LEGACY_DIRECT_IO=y +CONFIG_LIBFDT=y +CONFIG_LOCALVERSION_AUTO=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LS_EXTIRQ=y +CONFIG_LS_SCFG_MSI=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MARVELL_PHY=y +CONFIG_MCPM=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +# CONFIG_MDIO_GPIO is not set +CONFIG_MEMORY=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_MFD_HI6421_SPMI is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_VEXPRESS_SYSREG is not set +CONFIG_MICREL_PHY=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=16 +# CONFIG_MMC_MXC is not set +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_ESDHC_IMX is not set +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_OF_ESDHC=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MSDOS_FS=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_DATAFLASH=y +# CONFIG_MTD_DATAFLASH_OTP is not set +# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_FSL_IFC=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_MTD_SST25L=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_BLOCK is not set +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_MXC_CLK=y +# CONFIG_MXS_DMA is not set +CONFIG_NAMESPACES=y +CONFIG_NATIONAL_PHY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SRCU_NMI_SAFE=y +CONFIG_NEON=y +CONFIG_NET_DEVMEM=y +CONFIG_NET_EGRESS=y +CONFIG_NET_FAILOVER=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_NS=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_NO_HZ=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=16 +# CONFIG_NSM is not set +CONFIG_NTFS3_FS=y +CONFIG_NTFS_FS=y +CONFIG_NVMEM=y +# CONFIG_NVMEM_IMX_IIM is not set +# CONFIG_NVMEM_IMX_OCOTP_ELE is not set +CONFIG_NVMEM_LAYOUTS=y +# CONFIG_NVMEM_SNVS_LPGPR is not set +# CONFIG_NVMEM_SPMI_SDAM is not set +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_PACKET_DIAG=y +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_PERFORMANCE is not set +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_ECAM=y +CONFIG_PCI_HOST_COMMON=y +CONFIG_PCI_HOST_GENERIC=y +# CONFIG_PCI_IMX6_HOST is not set +CONFIG_PCI_LAYERSCAPE=y +CONFIG_PCI_MSI=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PER_VMA_LOCK=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PID_NS=y +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_IMX8ULP is not set +# CONFIG_PINCTRL_IMX91 is not set +# CONFIG_PINCTRL_IMX93 is not set +# CONFIG_PINCTRL_IMXRT1050 is not set +# CONFIG_PINCTRL_IMXRT1170 is not set +CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_727915=y +CONFIG_PL310_ERRATA_753970=y +CONFIG_PL310_ERRATA_769419=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_DEVFREQ=y +# CONFIG_PM_DEVFREQ_EVENT is not set +CONFIG_PM_OPP=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_BRCMKONA=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_POWER_RESET_VEXPRESS=y +CONFIG_POWER_SUPPLY=y +CONFIG_PPS=y +CONFIG_PRINTK_TIME=y +CONFIG_PROC_CHILDREN=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PSTORE=y +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PTP_1588_CLOCK_QORIQ=y +CONFIG_QORIQ_CPUFREQ=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_RD_BZIP2=y +CONFIG_RD_GZIP=y +CONFIG_RD_LZMA=y +CONFIG_RD_LZO=y +CONFIG_RD_XZ=y +CONFIG_REALTEK_PHY=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_SPI=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_IMX8MP_AUDIOMIX is not set +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DRV_BBNSM is not set +# CONFIG_RTC_DRV_CMOS is not set +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_DS3232=y +CONFIG_RTC_DRV_EM3027=y +CONFIG_RTC_DRV_FSL_FTM_ALARM=y +# CONFIG_RTC_DRV_IMXDI is not set +# CONFIG_RTC_DRV_MXC is not set +# CONFIG_RTC_DRV_MXC_V2 is not set +CONFIG_RTC_DRV_PCF2127=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCHED_DEBUG=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +CONFIG_SECCOMP=y +CONFIG_SECCOMP_FILTER=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PCILIB=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_CONEXANT_DIGICOLOR=y +CONFIG_SERIAL_CONEXANT_DIGICOLOR_CONSOLE=y +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_IMX_EARLYCON=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_ST_ASC=y +CONFIG_SERIAL_ST_ASC_CONSOLE=y +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_SMSC_PHY=y +CONFIG_SOCK_DIAG=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BUS=y +# CONFIG_SOC_IMX50 is not set +# CONFIG_SOC_IMX51 is not set +# CONFIG_SOC_IMX53 is not set +# CONFIG_SOC_IMX6Q is not set +# CONFIG_SOC_IMX6SL is not set +# CONFIG_SOC_IMX6SLL is not set +# CONFIG_SOC_IMX6SX is not set +# CONFIG_SOC_IMX6UL is not set +# CONFIG_SOC_IMX7D is not set +# CONFIG_SOC_IMX7ULP is not set +# CONFIG_SOC_IMX8M is not set +# CONFIG_SOC_IMX9 is not set +CONFIG_SOC_LS1021A=y +# CONFIG_SOC_VF610 is not set +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_CADENCE=y +CONFIG_SPI_DYNAMIC=y +# CONFIG_SPI_FSL_LPSPI is not set +# CONFIG_SPI_FSL_QUADSPI is not set +# CONFIG_SPI_IMX is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_SPIDEV=y +CONFIG_SPI_XILINX=y +CONFIG_SPLIT_PTE_PTLOCKS=y +CONFIG_SPMI=y +# CONFIG_SPMI_HISI3670 is not set +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SRAM=y +CONFIG_SRAM_EXEC=y +CONFIG_STACKTRACE=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYNC_FILE=y +CONFIG_SYSFS_SYSCALL=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UCLAMP_TASK is not set +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_UNIX_DIAG=y +CONFIG_UNWINDER_ARM=y +CONFIG_USB_SUPPORT=y +CONFIG_USER_NS=y +CONFIG_USE_OF=y +CONFIG_UTS_NS=y +CONFIG_VEXPRESS_CONFIG=y +CONFIG_VFAT_FS=y +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_ANCHOR=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_CONSOLE=y +# CONFIG_VIRTIO_DEBUG is not set +CONFIG_VIRTIO_MMIO=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_PCI_LEGACY=y +CONFIG_VIRTIO_PCI_LIB=y +CONFIG_VIRTIO_PCI_LIB_LEGACY=y +CONFIG_VITESSE_PHY=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_XILINX_WATCHDOG=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_X86=y +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/layerscape/armv8_64b/config-6.12 b/target/linux/layerscape/armv8_64b/config-6.12 new file mode 100644 index 0000000000..d2b0907534 --- /dev/null +++ b/target/linux/layerscape/armv8_64b/config-6.12 @@ -0,0 +1,887 @@ +CONFIG_64BIT=y +CONFIG_AQUANTIA_PHY=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_ARCH_HIBERNATION_HEADER=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_LAYERSCAPE=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=33 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_NXP=y +CONFIG_ARCH_PKEY_BITS=3 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_EXECMEM_LATE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_ERRATUM_1165522=y +CONFIG_ARM64_ERRATUM_1286807=y +CONFIG_ARM64_ERRATUM_2051678=y +CONFIG_ARM64_ERRATUM_2054223=y +CONFIG_ARM64_ERRATUM_2067961=y +CONFIG_ARM64_ERRATUM_2077057=y +CONFIG_ARM64_ERRATUM_2658417=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PLATFORM_DEVICES=y +CONFIG_ARM64_PTR_AUTH=y +CONFIG_ARM64_PTR_AUTH_KERNEL=y +CONFIG_ARM64_SVE=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=48 +# CONFIG_ARM64_VA_BITS_39 is not set +CONFIG_ARM64_VA_BITS_48=y +CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y +CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y +CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y +CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_FSL_MC=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_SMMU=y +# CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT is not set +# CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS is not set +CONFIG_ARM_SMMU_V3=y +# CONFIG_ARM_SMMU_V3_SVA is not set +CONFIG_ARM_SP805_WATCHDOG=y +CONFIG_ASM_MODVERSIONS=y +CONFIG_ASN1=y +CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y +CONFIG_ATA=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_AUDIT_GENERIC=y +CONFIG_AUTOFS_FS=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BALLOON_COMPACTION=y +CONFIG_BATTERY_BQ27XXX=y +# CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM is not set +CONFIG_BATTERY_BQ27XXX_I2C=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_BSG_COMMON=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=262144 +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_MQ_VIRTIO=y +CONFIG_BLK_PM=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_BUFFER_HEAD=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y +CONFIG_CAVIUM_ERRATUM_22375=y +CONFIG_CAVIUM_ERRATUM_23144=y +CONFIG_CAVIUM_ERRATUM_23154=y +CONFIG_CAVIUM_ERRATUM_27456=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_CHROME_PLATFORMS=y +CONFIG_CLK_LS1028A_PLLDIG=y +CONFIG_CLK_QORIQ=y +# CONFIG_CLK_VEXPRESS_OSC is not set +CONFIG_CLONE_BACKWARDS=y +CONFIG_CLZ_TAB=y +CONFIG_CMA=y +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_SIZE_MBYTES=16 +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SYSFS is not set +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_CS2000_CP=y +CONFIG_COMMON_CLK_FSL_FLEXSPI=y +# CONFIG_COMMON_CLK_FSL_SAI is not set +CONFIG_COMMON_CLK_XGENE=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CONTIG_ALLOC=y +CONFIG_COREDUMP=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_THERMAL=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MITIGATIONS=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_THERMAL=y +CONFIG_CRC16=y +CONFIG_CRC64=y +CONFIG_CRC64_ROCKSOFT=y +CONFIG_CRC7=y +CONFIG_CRC_CCITT=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC_T10DIF=y +CONFIG_CROSS_MEMORY_ATTACH=y +# CONFIG_CROS_EC is not set +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AUTHENC=y +CONFIG_CRYPTO_BLAKE2B=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC64_ROCKSOFT=y +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_CURVE25519=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC=y +CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON=y +CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC=y +CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI=y +CONFIG_CRYPTO_DEV_FSL_CAAM_JR=y +CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API=y +CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9 +CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y +CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_ENGINE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=y +CONFIG_CRYPTO_LIB_CURVE25519_INTERNAL=y +CONFIG_CRYPTO_LIB_DES=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RSA=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA256_ARM64=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_XTS=y +CONFIG_CRYPTO_XXHASH=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DMADEVICES=y +CONFIG_DMATEST=y +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_CMA=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_ENGINE_RAID=y +CONFIG_DMA_NEED_SYNC=y +# CONFIG_DMA_NUMA_CMA is not set +CONFIG_DMA_OF=y +CONFIG_DMA_OPS_HELPERS=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DNOTIFY=y +CONFIG_DPAA2_CONSOLE=y +CONFIG_DPAA_ERRATUM_A050385=y +CONFIG_DTC=y +CONFIG_DT_IDLE_STATES=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EEPROM_AT24=y +CONFIG_ELF_CORE=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_EXTCON=y +CONFIG_EXTCON_USB_GPIO=y +CONFIG_F2FS_FS=y +CONFIG_FAILOVER=y +CONFIG_FANOTIFY=y +CONFIG_FAT_FS=y +CONFIG_FB=y +CONFIG_FB_CORE=y +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_SYSMEM_FOPS=y +CONFIG_FB_SYSMEM_HELPERS=y +CONFIG_FB_SYSMEM_HELPERS_DEFERRED=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_IMAGEBLIT=y +CONFIG_FHANDLE=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FONT_8x16=y +CONFIG_FONT_8x8=y +CONFIG_FONT_SUPPORT=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FRAME_POINTER=y +CONFIG_FREEZER=y +# CONFIG_FSL_BMAN_TEST is not set +CONFIG_FSL_DPAA=y +CONFIG_FSL_DPAA2_ETH=y +CONFIG_FSL_DPAA2_PTP_CLOCK=y +# CONFIG_FSL_DPAA2_QDMA is not set +# CONFIG_FSL_DPAA_CHECKING is not set +CONFIG_FSL_DPAA_ETH=y +CONFIG_FSL_EDMA=y +CONFIG_FSL_ENETC=y +CONFIG_FSL_ENETC_CORE=y +CONFIG_FSL_ENETC_IERB=y +CONFIG_FSL_ENETC_MDIO=y +CONFIG_FSL_ENETC_PTP_CLOCK=y +CONFIG_FSL_ENETC_VF=y +CONFIG_FSL_ERRATUM_A008585=y +CONFIG_FSL_FMAN=y +CONFIG_FSL_GUTS=y +CONFIG_FSL_IFC=y +CONFIG_FSL_MC_BUS=y +CONFIG_FSL_MC_DPIO=y +CONFIG_FSL_MC_UAPI_SUPPORT=y +# CONFIG_FSL_PPFE is not set +# CONFIG_FSL_QMAN_TEST is not set +CONFIG_FSL_RCPM=y +CONFIG_FSL_XGMAC_MDIO=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +CONFIG_FUNCTION_ALIGNMENT=4 +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FUSE_FS=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_CACHE=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_GARP=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_NUMA=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +# CONFIG_GIANFAR is not set +CONFIG_GLOB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_MPC8XXX=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_GRO_CELLS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HIBERNATION=y +CONFIG_HIBERNATION_COMP_LZO=y +CONFIG_HIBERNATION_DEF_COMP="lzo" +CONFIG_HIBERNATION_SNAPSHOT_DEV=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING=y +CONFIG_HVC_DRIVER=y +CONFIG_HVC_IRQ=y +CONFIG_HVC_XEN=y +CONFIG_HVC_XEN_FRONTEND=y +CONFIG_HW_RANDOM=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_DESIGNWARE_CORE=y +CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_IMX=y +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_RK3X=y +CONFIG_I2C_SLAVE=y +# CONFIG_I2C_SLAVE_TESTUNIT is not set +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_IMX2_WDT=y +CONFIG_INET_DIAG=y +# CONFIG_INET_DIAG_DESTROY is not set +# CONFIG_INET_RAW_DIAG is not set +CONFIG_INET_TCP_DIAG=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INPUT=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_KEYBOARD=y +CONFIG_INPUT_MOUSE=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_VIVALDIFMAP=y +CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y +CONFIG_INTERVAL_TREE=y +# CONFIG_IOMMUFD is not set +CONFIG_IOMMU_API=y +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set +# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set +CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y +CONFIG_IOMMU_DMA=y +CONFIG_IOMMU_IOVA=y +CONFIG_IOMMU_IO_PGTABLE=y +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +# CONFIG_IOMMU_IO_PGTABLE_DART is not set +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +CONFIG_IOMMU_SUPPORT=y +CONFIG_IPC_NS=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_BYPASS_MANAGER=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_IOMMU=y +CONFIG_IRQ_MSI_LIB=y +CONFIG_IRQ_WORK=y +# CONFIG_ISDN is not set +CONFIG_JBD2=y +CONFIG_JUMP_LABEL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_KCMP=y +CONFIG_KEXEC=y +CONFIG_KEXEC_CORE=y +CONFIG_KEYBOARD_ATKBD=y +CONFIG_KEYBOARD_GPIO=y +CONFIG_KSM=y +CONFIG_LEGACY_DIRECT_IO=y +CONFIG_LIBCRC32C=y +CONFIG_LIBFDT=y +CONFIG_LOCALVERSION_AUTO=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LRU_GEN_WALKS_MMU=y +CONFIG_LS_EXTIRQ=y +CONFIG_LS_SCFG_MSI=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_BUS_MUX=y +CONFIG_MDIO_BUS_MUX_MMIOREG=y +CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +# CONFIG_MDIO_GPIO is not set +CONFIG_MEMORY=y +CONFIG_MEMORY_BALLOON=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_MEMTEST=y +# CONFIG_MFD_HI6421_SPMI is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_VEXPRESS_SYSREG is not set +CONFIG_MICREL_PHY=y +CONFIG_MICROSEMI_PHY=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_OF_ESDHC=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MMU_NOTIFIER=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_BYD=y +CONFIG_MOUSE_PS2_CYPRESS=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SMBUS=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_TRACKPOINT=y +CONFIG_MPILIB=y +CONFIG_MRP=y +CONFIG_MSCC_OCELOT_SWITCH_LIB=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_DATAFLASH=y +# CONFIG_MTD_DATAFLASH_OTP is not set +# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_FSL_IFC=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_SST25L=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MULTIPLEXER=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_MUX_MMIO=y +CONFIG_MV_XOR_V2=y +CONFIG_NAMESPACES=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_NEED_SG_DMA_FLAGS=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DEVMEM=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MSCC_FELIX=y +CONFIG_NET_DSA_MSCC_FELIX_DSA_LIB=y +CONFIG_NET_DSA_TAG_OCELOT=y +CONFIG_NET_DSA_TAG_OCELOT_8021Q=y +CONFIG_NET_EGRESS=y +CONFIG_NET_FAILOVER=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_NS=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NODES_SHIFT=2 +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=64 +# CONFIG_NSM is not set +CONFIG_NUMA=y +CONFIG_NUMA_BALANCING=y +CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y +# CONFIG_NUMA_EMU is not set +CONFIG_NUMA_MEMBLKS=y +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYERSCAPE_SFP=y +CONFIG_NVMEM_LAYOUTS=y +# CONFIG_NVMEM_SPMI_SDAM is not set +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IOMMU=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_NUMA=y +CONFIG_PACKET_DIAG=y +CONFIG_PACKING=y +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_REPORTING=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +CONFIG_PARAVIRT=y +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_PERFORMANCE is not set +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_LAYERSCAPE_GEN4=y +CONFIG_PCIE_MOBIVEIL=y +CONFIG_PCIE_MOBIVEIL_HOST=y +CONFIG_PCIE_PME=y +CONFIG_PCI_ATS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_ECAM=y +CONFIG_PCI_HISI=y +CONFIG_PCI_HOST_COMMON=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCI_IOV=y +CONFIG_PCI_LAYERSCAPE=y +CONFIG_PCI_MSI=y +CONFIG_PCS_LYNX=y +CONFIG_PER_VMA_LOCK=y +CONFIG_PGTABLE_HAS_HUGE_LEAVES=y +CONFIG_PGTABLE_LEVELS=4 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PHY_FSL_LYNX_28G is not set +CONFIG_PID_IN_CONTEXTIDR=y +CONFIG_PID_NS=y +CONFIG_PL330_DMA=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_OPP=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_STD_PARTITION="" +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_VEXPRESS=y +CONFIG_POWER_RESET_XGENE=y +CONFIG_POWER_SUPPLY=y +CONFIG_PPS=y +CONFIG_PRINTK_TIME=y +CONFIG_PROC_CHILDREN=y +CONFIG_PROFILING=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PTP_1588_CLOCK_QORIQ=y +CONFIG_QCOM_HIDMA=y +CONFIG_QCOM_HIDMA_MGMT=y +CONFIG_QCOM_QDF2400_ERRATUM_0065=y +# CONFIG_QFMT_V2 is not set +CONFIG_QORIQ_CPUFREQ=y +CONFIG_QORIQ_THERMAL=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_QUOTA=y +CONFIG_QUOTACTL=y +# CONFIG_RANDOMIZE_KSTACK_OFFSET is not set +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_RD_BZIP2=y +CONFIG_RD_GZIP=y +CONFIG_RD_LZMA=y +CONFIG_RD_LZO=y +CONFIG_RD_XZ=y +CONFIG_REALTEK_PHY=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_SPI=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_DS3232=y +CONFIG_RTC_DRV_FSL_FTM_ALARM=y +CONFIG_RTC_DRV_PCF2127=y +CONFIG_RTC_DRV_PL031=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCHED_HW_PRESSURE=y +CONFIG_SCHED_INFO=y +CONFIG_SCHED_MC=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +# CONFIG_SCSI_PROC_FS is not set +# CONFIG_SCSI_SAS_ATA is not set +CONFIG_SCSI_SAS_ATTRS=y +CONFIG_SCSI_SAS_HOST_SMP=y +CONFIG_SCSI_SAS_LIBSAS=y +CONFIG_SECCOMP=y +CONFIG_SECCOMP_FILTER=y +CONFIG_SECRETMEM=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PCILIB=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_SC16IS7XX=y +CONFIG_SERIAL_SC16IS7XX_I2C=y +CONFIG_SERIAL_SC16IS7XX_SPI=y +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +CONFIG_SERIO=y +CONFIG_SERIO_AMBAKMI=y +CONFIG_SERIO_LIBPS2=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SOCK_DIAG=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BUS=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_FSL_DSPI=y +CONFIG_SPI_FSL_QUADSPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_NXP_FLEXSPI=y +CONFIG_SPI_PL022=y +CONFIG_SPLIT_PMD_PTLOCKS=y +CONFIG_SPLIT_PTE_PTLOCKS=y +CONFIG_SPMI=y +# CONFIG_SPMI_HISI3670 is not set +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +# CONFIG_SQUASHFS_XZ is not set +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SRAM=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_SWIOTLB=y +CONFIG_SWIOTLB_XEN=y +CONFIG_SWPHY=y +CONFIG_SYNC_FILE=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYSFS_SYSCALL=y +CONFIG_SYS_HYPERVISOR=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_TASK_XACCT=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_EMULATION=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THP_SWAP=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TOOLS_SUPPORT_RELR=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y +# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set +# CONFIG_TRANSPARENT_HUGEPAGE_NEVER is not set +CONFIG_TRANS_TABLE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UCLAMP_TASK is not set +CONFIG_UIO=y +CONFIG_UIO_AEC=y +CONFIG_UIO_CIF=y +CONFIG_UIO_DMEM_GENIRQ=y +CONFIG_UIO_MF624=y +CONFIG_UIO_NETX=y +CONFIG_UIO_PCI_GENERIC=y +CONFIG_UIO_PDRV_GENIRQ=y +CONFIG_UIO_SERCOS3=y +CONFIG_UNIX_DIAG=y +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_USB_SUPPORT=y +CONFIG_USER_NS=y +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_USE_PERCPU_NUMA_NODE_ID=y +CONFIG_UTS_NS=y +CONFIG_VDSO_GETRANDOM=y +CONFIG_VEXPRESS_CONFIG=y +CONFIG_VFAT_FS=y +CONFIG_VFIO=y +# CONFIG_VFIO_AMBA is not set +CONFIG_VFIO_CONTAINER=y +CONFIG_VFIO_FSL_MC=y +CONFIG_VFIO_GROUP=y +CONFIG_VFIO_IOMMU_TYPE1=y +# CONFIG_VFIO_NOIOMMU is not set +CONFIG_VFIO_PCI=y +CONFIG_VFIO_PCI_CORE=y +CONFIG_VFIO_PCI_INTX=y +CONFIG_VFIO_PCI_MMAP=y +CONFIG_VFIO_VIRQFD=y +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_VIDEO=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_ANCHOR=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_CONSOLE=y +# CONFIG_VIRTIO_DEBUG is not set +# CONFIG_VIRTIO_IOMMU is not set +CONFIG_VIRTIO_MMIO=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_PCI_LEGACY=y +CONFIG_VIRTIO_PCI_LIB=y +CONFIG_VIRTIO_PCI_LIB_LEGACY=y +CONFIG_VITESSE_PHY=y +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +CONFIG_VMAP_STACK=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_XARRAY_MULTI=y +CONFIG_XEN=y +CONFIG_XENFS=y +CONFIG_XEN_AUTO_XLATE=y +CONFIG_XEN_BACKEND=y +CONFIG_XEN_BALLOON=y +# CONFIG_XEN_BLKDEV_BACKEND is not set +CONFIG_XEN_BLKDEV_FRONTEND=y +CONFIG_XEN_COMPAT_XENFS=y +CONFIG_XEN_DEV_EVTCHN=y +CONFIG_XEN_DOM0=y +CONFIG_XEN_FBDEV_FRONTEND=y +CONFIG_XEN_GNTDEV=y +CONFIG_XEN_GRANT_DEV_ALLOC=y +# CONFIG_XEN_NETDEV_BACKEND is not set +CONFIG_XEN_NETDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_STUB is not set +CONFIG_XEN_PRIVCMD=y +# CONFIG_XEN_PVCALLS_BACKEND is not set +# CONFIG_XEN_SCSI_FRONTEND is not set +CONFIG_XEN_SYS_HYPERVISOR=y +# CONFIG_XEN_VIRTIO is not set +# CONFIG_XEN_WDT is not set +CONFIG_XEN_XENBUS_FRONTEND=y +CONFIG_XFS_FS=y +CONFIG_XFS_RT=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_X86=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch b/target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch new file mode 100644 index 0000000000..bd69aa042d --- /dev/null +++ b/target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch @@ -0,0 +1,228 @@ +From 008465a02bf29b366ca7a56dba48ad3a85417ba2 Mon Sep 17 00:00:00 2001 +From: Li Yang +Date: Thu, 18 Nov 2021 21:46:21 -0600 +Subject: [PATCH] arm64: dts: ls1012a: add ppfe support to boards + +Update ls1012a dtsi and platform dts files with +support for ppfe. + +Signed-off-by: Calvin Johnson +Signed-off-by: Anjaneyulu Jagarlmudi +Signed-off-by: Li Yang +--- + .../boot/dts/freescale/fsl-ls1012a-frdm.dts | 44 +++++++++++++++++++ + .../boot/dts/freescale/fsl-ls1012a-qds.dts | 43 ++++++++++++++++++ + .../boot/dts/freescale/fsl-ls1012a-rdb.dts | 40 +++++++++++++++++ + .../arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 29 ++++++++++++ + 4 files changed, 156 insertions(+) + +--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts +@@ -14,6 +14,11 @@ + model = "LS1012A Freedom Board"; + compatible = "fsl,ls1012a-frdm", "fsl,ls1012a"; + ++ aliases { ++ ethernet0 = &pfe_mac0; ++ ethernet1 = &pfe_mac1; ++ }; ++ + sys_mclk: clock-mclk { + compatible = "fixed-clock"; + #clock-cells = <0>; +@@ -110,6 +115,45 @@ + }; + }; + ++&pfe { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pfe_mac0: ethernet@0 { ++ compatible = "fsl,pfe-gemac-port"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0>; /* GEM_ID */ ++ fsl,mdio-mux-val = <0x0>; ++ phy-mode = "sgmii"; ++ phy-handle = <&sgmii_phy1>; ++ }; ++ ++ pfe_mac1: ethernet@1 { ++ compatible = "fsl,pfe-gemac-port"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x1>; /* GEM_ID */ ++ fsl,mdio-mux-val = <0x0>; ++ phy-mode = "sgmii"; ++ phy-handle = <&sgmii_phy2>; ++ }; ++ ++ mdio@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ sgmii_phy1: ethernet-phy@2 { ++ reg = <0x2>; ++ }; ++ ++ sgmii_phy2: ethernet-phy@1 { ++ reg = <0x1>; ++ }; ++ }; ++}; ++ + &sai2 { + status = "okay"; + }; +--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts +@@ -16,6 +16,8 @@ + aliases { + mmc0 = &esdhc0; + mmc1 = &esdhc1; ++ ethernet0 = &pfe_mac0; ++ ethernet1 = &pfe_mac1; + }; + + sys_mclk: clock-mclk { +@@ -148,6 +150,47 @@ + }; + }; + ++&pfe { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pfe_mac0: ethernet@0 { ++ compatible = "fsl,pfe-gemac-port"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0>; /* GEM_ID */ ++ fsl,mdio-mux-val = <0x2>; ++ phy-mode = "sgmii-2500"; ++ phy-handle = <&sgmii_phy1>; ++ }; ++ ++ pfe_mac1: ethernet@1 { ++ compatible = "fsl,pfe-gemac-port"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x1>; /* GEM_ID */ ++ fsl,mdio-mux-val = <0x3>; ++ phy-mode = "sgmii-2500"; ++ phy-handle = <&sgmii_phy2>; ++ }; ++ ++ mdio@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ sgmii_phy1: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c45"; ++ reg = <0x1>; ++ }; ++ ++ sgmii_phy2: ethernet-phy@2 { ++ compatible = "ethernet-phy-ieee802.3-c45"; ++ reg = <0x2>; ++ }; ++ }; ++}; ++ + &sai2 { + status = "okay"; + }; +--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts +@@ -18,6 +18,8 @@ + serial0 = &duart0; + mmc0 = &esdhc0; + mmc1 = &esdhc1; ++ ethernet0 = &pfe_mac0; ++ ethernet1 = &pfe_mac1; + }; + }; + +@@ -104,3 +106,41 @@ + &sata { + status = "okay"; + }; ++ ++&pfe { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pfe_mac0: ethernet@0 { ++ compatible = "fsl,pfe-gemac-port"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0>; /* GEM_ID */ ++ fsl,mdio-mux-val = <0x0>; ++ phy-mode = "sgmii"; ++ phy-handle = <&sgmii_phy>; ++ }; ++ ++ pfe_mac1: ethernet@1 { ++ compatible = "fsl,pfe-gemac-port"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x1>; /* GEM_ID */ ++ fsl,mdio-mux-val = <0x0>; ++ phy-mode = "rgmii-id"; ++ phy-handle = <&rgmii_phy>; ++ }; ++ mdio@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ sgmii_phy: ethernet-phy@2 { ++ reg = <0x2>; ++ }; ++ ++ rgmii_phy: ethernet-phy@1 { ++ reg = <0x1>; ++ }; ++ }; ++}; +--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi +@@ -568,6 +568,35 @@ + }; + }; + ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ pfe_reserved: packetbuffer@83400000 { ++ reg = <0 0x83400000 0 0xc00000>; ++ }; ++ }; ++ ++ pfe: pfe@4000000 { ++ compatible = "fsl,pfe"; ++ reg = <0x0 0x04000000 0x0 0xc00000>, /* AXI 16M */ ++ <0x0 0x83400000 0x0 0xc00000>; /* PFE DDR 12M */ ++ reg-names = "pfe", "pfe-ddr"; ++ fsl,pfe-num-interfaces = <0x2>; ++ interrupts = <0 172 0x4>, /* HIF interrupt */ ++ <0 173 0x4>, /*HIF_NOCPY interrupt */ ++ <0 174 0x4>; /* WoL interrupt */ ++ interrupt-names = "pfe_hif", "pfe_hif_nocpy", "pfe_wol"; ++ memory-region = <&pfe_reserved>; ++ fsl,pfe-scfg = <&scfg 0>; ++ fsl,rcpm-wakeup = <&rcpm 0xf0000020>; ++ clocks = <&clockgen 4 0>; ++ clock-names = "pfe"; ++ ++ status = "okay"; ++ }; ++ + firmware { + optee { + compatible = "linaro,optee-tz"; diff --git a/target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch b/target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch new file mode 100644 index 0000000000..f42859b7ac --- /dev/null +++ b/target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch @@ -0,0 +1,41 @@ +From 9c5c18dbf8e1845d349ef7020f8af5bc9b56ed1f Mon Sep 17 00:00:00 2001 +From: Pawel Dembicki +Date: Fri, 28 Sep 2022 17:14:32 +0200 +Subject: [PATCH] arm64: dts: ls1012a-frdm/qds: workaround by updating qspi flash to + single mode + +Update rx and tx bus-width to 1 to use single mode to workaround ubifs +issue found with double mode. (The same method as RDB board) + +Signed-off-by: Pawel Dembicki +--- + arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts | 4 ++-- + arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts | 4 ++-- + 2 file changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts +@@ -110,8 +110,8 @@ + spi-max-frequency = <50000000>; + m25p,fast-read; + reg = <0>; +- spi-rx-bus-width = <2>; +- spi-tx-bus-width = <2>; ++ spi-rx-bus-width = <1>; ++ spi-tx-bus-width = <1>; + }; + }; + +--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts +@@ -145,8 +145,8 @@ + spi-max-frequency = <50000000>; + m25p,fast-read; + reg = <0>; +- spi-rx-bus-width = <2>; +- spi-tx-bus-width = <2>; ++ spi-rx-bus-width = <1>; ++ spi-tx-bus-width = <1>; + }; + }; + diff --git a/target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch b/target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch new file mode 100644 index 0000000000..fd1dff747b --- /dev/null +++ b/target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch @@ -0,0 +1,29 @@ +From 9c5c18dbf8e1845d349ef7020f8af5bc9b56ed1f Mon Sep 17 00:00:00 2001 +From: Kuldeep Singh +Date: Tue, 7 Jan 2020 17:14:32 +0530 +Subject: [PATCH] arm64: dts: ls1012a-rdb: workaround by updating qspi flash to + single mode + +Update rx and tx bus-width to 1 to use single mode to workaround ubifs +issue found with double mode. + +[ Leo: Local workaround ] + +Signed-off-by: Kuldeep Singh +--- + arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts +@@ -98,8 +98,8 @@ + spi-max-frequency = <50000000>; + m25p,fast-read; + reg = <0>; +- spi-rx-bus-width = <2>; +- spi-tx-bus-width = <2>; ++ spi-rx-bus-width = <1>; ++ spi-tx-bus-width = <1>; + }; + }; + diff --git a/target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch b/target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch new file mode 100644 index 0000000000..9bc4e2b520 --- /dev/null +++ b/target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch @@ -0,0 +1,34 @@ +From 38093ebbf25eb60a1aa863f46118a68a0300c56e Mon Sep 17 00:00:00 2001 +From: Kuldeep Singh +Date: Fri, 3 Jan 2020 14:49:07 +0530 +Subject: [PATCH] arm64: dts: ls1046a-rdb: Update qspi spi-rx-bus-width to 1 + +Update rx width from quad mode to single mode as a workaround. + +[Leo: Local workaround ] + +Signed-off-by: Kuldeep Singh +--- + arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts +@@ -104,7 +104,7 @@ + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; +- spi-rx-bus-width = <4>; ++ spi-rx-bus-width = <1>; + spi-tx-bus-width = <1>; + reg = <0>; + }; +@@ -114,7 +114,7 @@ + #address-cells = <1>; + #size-cells = <1>; + spi-max-frequency = <50000000>; +- spi-rx-bus-width = <4>; ++ spi-rx-bus-width = <1>; + spi-tx-bus-width = <1>; + reg = <1>; + }; diff --git a/target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch b/target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch new file mode 100644 index 0000000000..f9ea6a6e4e --- /dev/null +++ b/target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch @@ -0,0 +1,28 @@ +From fa47ee1700323a0c3163c18941659692e5c22cff Mon Sep 17 00:00:00 2001 +From: Han Xu +Date: Tue, 23 Jan 2024 20:51:49 -0600 +Subject: [PATCH] LF-20-3 mtd: spi-nor: Use 1 bit mode of spansion(s25fs512s) + flash + +This is a workaround patch which uses only single bit mode of s25fs512s +flash + +Signed-off-by: Han Xu +Signed-off-by: Kuldeep Singh +--- + drivers/mtd/spi-nor/spansion.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/spi-nor/spansion.c ++++ b/drivers/mtd/spi-nor/spansion.c +@@ -859,9 +859,9 @@ static const struct flash_info spansion_ + .name = "s25fs512s", + .size = SZ_64M, + .sector_size = SZ_256K, +- .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, + .mfr_flags = USE_CLSR, + .fixups = &s25fs_s_nor_fixups, ++ .fixup_flags = SPI_NOR_4B_OPCODES, + }, { + .id = SNOR_ID(0x01, 0x20, 0x18, 0x03, 0x00), + .name = "s25sl12800", diff --git a/target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch b/target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch new file mode 100644 index 0000000000..279391531a --- /dev/null +++ b/target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch @@ -0,0 +1,11851 @@ +From 81f5150aba929b222783a60a408b9a20a23bd171 Mon Sep 17 00:00:00 2001 +From: Calvin Johnson +Date: Sat, 16 Sep 2017 07:05:49 +0530 +Subject: [PATCH] staging: add fsl_ppfe driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is squash of all commits with ppfe driver taken from NXP 6.12 tree: +https://github.com/nxp-qoriq/linux/tree/lf-6.12.y + +net: fsl_ppfe: dts binding for ppfe + +Signed-off-by: Calvin Johnson +Signed-off-by: Anjaneyulu Jagarlmudi + +staging: fsl_ppfe/eth: header files for pfe driver + +This patch has all pfe header files. + +Signed-off-by: Calvin Johnson +Signed-off-by: Anjaneyulu Jagarlmudi + +staging: fsl_ppfe/eth: introduce pfe driver + + This patch introduces Linux support for NXP's LS1012A Packet +Forwarding Engine (pfe_eth). LS1012A uses hardware packet forwarding +engine to provide high performance Ethernet interfaces. The device +includes two Ethernet ports. + +Signed-off-by: Calvin Johnson +Signed-off-by: Anjaneyulu Jagarlmudi + +staging: fsl_ppfe/eth: fix RGMII tx delay issue + +Recently logic to enable RGMII tx delay was changed by +below patch. + +https://patchwork.kernel.org/patch/9447581/ + +Based on the patch, appropriate change is made in PFE driver. + +Signed-off-by: Calvin Johnson +Signed-off-by: Anjaneyulu Jagarlmudi + +staging: fsl_ppfe/eth: remove unused functions + +Remove unused functions hif_xmit_pkt & hif_lib_xmit_pkt. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: fix read/write/ack idx issue + +While fixing checkpatch errors some of the index increments +were commented out. They are enabled. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: Make phy_ethtool_ksettings_get return void + +Make return value void since function never return meaningful value + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: add function to update tmu credits + +__hif_lib_update_credit function is used to update the tmu credits. +If tx_qos is set, tmu credit is updated based on the number of packets +transmitted by tmu. + +Signed-off-by: Calvin Johnson +Signed-off-by: Anjaneyulu Jagarlmudi + +staging: fsl_ppfe/eth: Avoid packet drop at TMU queues + +Added flow control between TMU queues and PFE Linux driver, +based on TMU credits availability. +Added tx_qos module parameter to control this behavior. +Use queue-0 as default queue to transmit packets. + +Signed-off-by: Calvin Johnson +Signed-off-by: Akhila Kavi +Signed-off-by: Anjaneyulu Jagarlmudi + +staging: fsl_ppfe/eth: Enable PFE in clause 45 mode + +when we opearate in clause 45 mode, we need to call +the function get_phy_device() with its 3rd argument as +"true" and then the resultant phy device needs to be +register with phy layer via phy_device_register() + +Signed-off-by: Bhaskar Upadhaya + +staging: fsl_ppfe/eth: Disable autonegotiation for 2.5G SGMII + +PCS initialization sequence for 2.5G SGMII interface governs +auto negotiation to be in disabled mode + +Signed-off-by: Bhaskar Upadhaya + +staging: fsl_ppfe/eth: calculate PFE_PKT_SIZE with SKB_DATA_ALIGN + +pfe packet size was calculated without considering skb data alignment +and this resulted in jumbo frames crashing kernel when the +cacheline size increased from 64 to 128 bytes with +commit 97303480753e ("arm64: Increase the max granular size"). + +Modify pfe packet size caclulation to include skb data alignment of +sizeof(struct skb_shared_info). + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: support for userspace networking + +This patch adds the userspace mode support to fsl_ppfe network driver. +In the new mode, basic hardware initialization is performed in kernel, while +the datapath and HIF handling is the responsibility of the userspace. + +The new command line parameter is added to initialize the ppfe module +in userspace mode. By default the module remains in kernelspace networking +mode. +To enable userspace mode, use "insmod pfe.ko us=1" + +Signed-off-by: Akhil Goyal +Signed-off-by: Gagandeep Singh + +staging: fsl_ppfe/eth: unregister netdev after pfe_phy_exit + +rmmod pfe.ko throws below warning: + +kernfs: can not remove 'phydev', no directory +------------[ cut here ]------------ +WARNING: CPU: 0 PID: 2230 at fs/kernfs/dir.c:1481 +kernfs_remove_by_name_ns+0x90/0xa0 + +This is caused when the unregistered netdev structure is accessed to +disconnect phy. + +Resolve the issue by unregistering netdev after disconnecting phy. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: HW parse results for DPDK + +HW Parse results are included in the packet headroom. +Length and Offset calculation now accommodates parse info size. + +Signed-off-by: Archana Madhavan + +staging: fsl_ppfe/eth: reorganize pfe_netdev_ops + +Reorganize members of struct pfe_netdev_ops to match with the order +of members in struct net_device_ops defined in include/linux/netdevice.h + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: use mask for rx max frame len + +Define and use PFE_RCR_MAX_FL_MASK to properly set Rx max frame +length of MAC Receive Control Register. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: define pfe ndo_change_mtu function + +Define ndo_change_mtu function for pfe. This sets the max Rx frame +length to the new mtu. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: remove jumbo frame enable from gemac init + +MAC Receive Control Register was configured to allow jumbo frames. +This is removed as jumbo frames can be supported anytime by changing +mtu which will in turn modify MAX_FL field of MAC RCR. +Jumbo frames caused pfe to hang on LS1012A rev 1.0 Silicon due to +erratum A-010897. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: disable CRC removal + +Disable CRC removal from the packet, so that packets are forwarded +as is to Linux. +CRC configuration in MAC will be reflected in the packet received +to Linux. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: handle ls1012a errata_a010897 + +On LS1012A rev 1.0, Jumbo frames are not supported as it causes +the PFE controller to hang. A reset of the entire chip is required +to resume normal operation. + +To handle this errata, frames with length > 1900 are truncated for +rev 1.0 of LS1012A. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: replace magic numbers + +Replace magic numbers and some cosmetic changes. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: resolve indentation warning + +Resolve the following indentation warning: + +drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c: +In function ‘pfe_get_gemac_if_proprties’: +drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c:96:2: +warning: this ‘else’ clause does not guard... +[-Wmisleading-indentation] + else + ^~~~ +drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c:98:3: +note: ...this statement, but the latter is misleadingly indented as +if it were guarded by the ‘else’ + pdata->ls1012a_eth_pdata[port].mdio_muxval = phy_id; + ^~~~~ + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: add fixed-link support + +In cases where MAC is not connected to a normal MDIO-managed PHY +device, and instead to a switch, it is configured as a "fixed-link". +Code to handle this scenario is added here. + +phy_node in the dtb is checked to identify a fixed-link. +On identification of a fixed-link, it is registered and connected. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe: add support for a char dev for link status + +Read and IOCTL support is added. Application would need to open, +read/ioctl the /dev/pfe_us_cdev device. +select is pending as it requires a wait_queue. + +Signed-off-by: Shreyansh Jain +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe: enable hif event from userspace + +HIF interrupts are enabled using ioctl from user space, +and epoll wait from user space wakes up when there is an HIF +interrupt. + +Signed-off-by: Akhil Goyal + +staging: fsl_ppfe: performance tuning for user space + +interrupt coalescing of 100 usec is added. + +Signed-off-by: Akhil Goyal +Signed-off-by: Sachin Saxena + +staging: fsl_ppfe/eth: Update to use SPDX identifiers + +Replace license text with corresponding SPDX identifiers and update the +format of existing SPDX identifiers to follow the new guideline +Documentation/process/license-rules.rst. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: misc clean up + +- remove redundant hwfeature init +- remove unused vars from ls1012a_eth_platform_data +- To handle ls1012a errata_a010897, PPFE driver requires GUTS driver +to be compiled in. Select FSL_GUTS when PPFE driver is compiled. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: reorganize platform phy parameters + +- Use "phy-handle" and of_* functions to get phy node and fixed-link +parameters + +- Reorganize phy parameters and initialize them only if phy-handle +or fixed-link is defined in the dtb. + +- correct typo pfe_get_gemac_if_proprties to pfe_get_gemac_if_properties + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: support single interface initialization + +- arrange members of struct mii_bus in sequence matching phy.h +- if mdio node is defined, use of_mdiobus_register to register + child nodes (phy devices) available on the mdio bus. +- remove of_phy_register_fixed_link from pfe_phy_init as it is being + handled in pfe_get_gemac_if_properties +- remove mdio enabled check +- skip phy init, if no PHY or fixed-link + +Signed-off-by: Calvin Johnson + +net: fsl_ppfe: update dts properties for phy + +Use commonly used phy-handle property and mdio subnode to handle +phy properties. + +Deprecate bindings fsl,gemac-phy-id & fsl,pfe-phy-if-flags. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: remove unused code + +- remove gemac-bus-id related code that is unused. +- remove unused prototype gemac_set_mdc_div. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: separate mdio init from mac init + +- separate mdio initialization from mac initialization +- Define pfe_mdio_priv_s structure to hold mii_bus structure and other + related data. +- Modify functions to work with the separted mdio init model. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: adapt to link mode based phydev changes + +Setting link mode bits have changed with the integration of +commit (3c1bcc8 net: ethernet: Convert phydev advertize and +supported from u32 to link mode). Adapt to the new method of +setting and clearing the link mode bits. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: use generic soc_device infra instead of fsl_guts_get_svr() + +Commit ("soc: fsl: guts: make fsl_guts_get_svr() static") has +made fsl_guts_get_svr() static and hence use generic soc_device +infrastructure to check SoC revision. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: use memremap() to map RAM area used by PFE + +RAM area used by PFE should be mapped using memremap() instead of +directly traslating physical addr to virtual. This will ensure proper +checks are done before the area is used. + +Signed-off-by: Calvin Johnson + +staging: fsl_ppfe/eth: remove 'fallback' argument from dev->ndo_select_queue() + +To be consistent with upstream API change. + +Signed-off-by: Li Yang + +staging: fsl_ppfe/eth: prefix header search paths with $(srctree)/ + +Currently, the rules for configuring search paths in Kbuild have +changed: https://lkml.org/lkml/2019/5/13/37 + +This will lead the below error: + +fatal error: pfe/pfe.h: No such file or directory + +Fix it by adding $(srctree)/ prefix to the search paths. + +Signed-off-by: Ting Liu + +staging: fsl_ppfe/eth: add pfe support to Kconfig and Makefile + +Signed-off-by: Calvin Johnson +[ Aisheng: fix minor conflict due to removed VBOXSF_FS ] +Signed-off-by: Dong Aisheng + +staging: fsl_ppfe/eth: Disable termination of CRC fwd. + +LS1012A MAC PCS block has an erratum that is seen with specific PHY AR803x. +The issue is triggered by the (spec-compliant) operation of the AR803x PHY +on the LS1012A-FRWY board.Due to this, good FCS packet is reported as error +packet by MAC, so for these error packets FCS should be validated and +discard only real error packets in PFE Rx packet path. + +Signed-off-by: Nagesh Koneti +Signed-off-by: Nagesh Koneti <“koneti.nagesh@nxp.com”> + +net: ppfe: Cope with of_get_phy_mode() API change + +Signed-off-by: Li Yang + +staging: fsl_ppfe/eth: Enhance error checking in platform probe + +Fix the kernel crash when MAC addr is not passed in dtb. + +Signed-off-by: Anji Jagarlmudi + +staging: fsl_ppfe/eth: reject unsupported coalescing params + +Set ethtool_ops->supported_coalesce_params to let +the core reject unsupported coalescing parameters. + +Signed-off-by: Anji Jagarlmudi + +staging: fsl_ppfe/eth:check "reg" property before pfe_get_gemac_if_properties() + +It has been observed that the function pfe_get_gemac_if_properties() is +been called blindly for the next two child nodes. There might be some +cases where it may go wrong and that lead to missing interfaces. +with these changes it is ensured thats not the case. + +Signed-off-by: Chaitanya Sakinam +Signed-off-by: Anji J + +staging: fsl_ppfe/eth: "struct firmware" dereference is reduced in many functions + +firmware structure's data variable is the actual elf data. It has been +dereferenced in multiple functions and this has been reduced. + +Signed-off-by: Chaitanya Sakinam +Signed-off-by: Anji J + +staging: fsl_ppfe/eth: LF-27 load pfe binaries from FDT + +FDT prepared in uboot now has pfe firmware part of it. +These changes will read the firmware by default from it and tries to load +the elf into the PFE PEs. This help build the pfe driver pasrt of kernel. + +Signed-off-by: Chaitanya Sakinam +Signed-off-by: Anji J + +staging: fsl_ppfe/eth: proper handling for RGMII delay mode + +The correct setting for the RGMII ports on LS1012ARDB is to +enable delay on both Tx and Rx. So the phy mode to be matched +is PHY_INTERFACE_MODE_RGMII_ID. + +Signed-off-by: Chaitanya Sakinam +Signed-off-by: Anji Jagarlmudi + +LF-1762-2 staging: fsl_ppfe: replace '---help---' in Kconfig files with 'help' + +Update Kconfig to cope with upstream change +commit 84af7a6194e4 ("checkpatch: kconfig: prefer 'help' over +'---help---'"). + +Signed-off-by: Dong Aisheng + +staging: fsl_ppfe/eth: Nesting level does not match indentation + +corrected nesting level +LF-1661 and Coverity CID: 8879316 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: Initialized scalar variable + +Proper initialization of scalar variable +LF-1657 and Coverity CID: 3335133 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: misspelt variable name + +variable name corrected +LF-1656 and Coverity CID: 3335119 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: Avoiding out-of-bound writes + +avoid out-of-bound writes with proper error handling +LF-1654, LF-1652 and Coverity CID: 3335106, 3335090 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: Initializing scalar variable + +proper initialization of scalar variable. +LF-1653 and Coverity CID: 3335101 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: checking return value + +proper checks added and handled for return value. +LF-1644 and Coverity CID: 241888 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: Avoid out-of-bound access + +proper handling to avoid out-of-bound access +LF-1642, LF-1641 and Coverity CID: 240910, 240891 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: Avoiding out-of-bound writes + +avoid out-of-bound writes with proper error handling +LF-1654, LF-1652 and Coverity CID: 3335106, 3335090 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: return value init in error case + +proper err return in error case. +LF-1806 and Coverity CID: 10468592 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: Avoid recursion in header inclusion + +Avoiding header inclusions that are not necessary and also that are +causing header inclusion recursion. + +LF-2102 and Coverity CID: 240838 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: Avoiding return value overwrite + +avoid return value overwrite at the end of function. +LF-2136, LF-2137 and Coverity CID: 8879341, 8879364 + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: LF-27 enabling PFE firmware load from FDT + +The macro, "LOAD_PFEFIRMWARE_FROM_FILESYSTEM" is been disabled to load +the firmware from FDT by default. Enabling the macro will load the +firmware from filesystem. + +Also, the Makefile is now tuned to build pfe as per the config option + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: Ethtool stats correction for IEEE_rx_drop counter + +Due to carrier extended bug the phy counter IEEE_rx_drop counter is +incremented some times and phy reports the packet has crc error. +Because of this PFE revalidates all the packets that are marked crc +error by phy. Now, the counter phy reports is till bogus and this +patch decrements the counter by pfe revalidated (and are crc ok) +counter amount. + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe/eth: PFE firmware load enhancements + +PFE driver enhancements to load the PE firmware from filesystem +when the firmware is not found in FDT. + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe: deal with upstream API change of of_get_mac_address() + +Uptream commit 83216e398 changed the of_get_mac_address() API, update +the user accordingly. + +Signed-off-by: Li Yang + +staging: fsl_ppfe: update coalesce setting uAPI usage + +API changed since: +f3ccfda19319 ("ethtool: extend coalesce setting uAPI with CQE mode") + +Signed-off-by: Dong Aisheng + +staging: fsl_ppfe: Addressed build warnings + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe: Addressed build warnings + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe: Remove C45 check and related code in driver + +The MDIO core will not pass a C45 request via the C22 API call any +more. So, removed the code. The old way of C45 muxed addresses is +removed from the upstream kernel after clear seperation of C45 and +C22. +Upstream kernel commit details for reference: +99d5fe9c7f3d net: mdio: Remove support for building C45 muxed addresses + +Signed-off-by: Chaitanya Sakinam + +staging: fsl_ppfe: update class_create() usage + +Cope with API change: +1aaba11da9aa ("driver core: class: remove module * from class_create()") + +Signed-off-by: Krishna Chaitanya Sakinam + +LF-10777-2 staging: fsl_ppfe: remove unused pfe_eth_mdio_write_addr + +Fix the following build warning: +drivers/staging/fsl_ppfe/pfe_eth.c:887:12: warning: ‘pfe_eth_mdio_write_addr’ defined but not used [-Wunused-function] + 887 | static int pfe_eth_mdio_write_addr(struct mii_bus *bus, int mii_id, + +The only user of this API is MII_ADDR_C45 checking logic which +was removed since the commit 9d95b13bd084 ("staging: fsl_ppfe: Remove +C45 check and related code in driver"). So this API should be removed +together as no users anymore. + +Fixes: 9d95b13bd084 ("staging: fsl_ppfe: Remove C45 check and related code in driver") +Reviewed-by: Jason Liu +Signed-off-by: Dong Aisheng + +LF-13827-2 net: pfe: fix Wmissing-prototypes build warnings + +drivers/staging/fsl_ppfe/pfe_firmware.c:128:5: warning: no previous prototype for ‘pfe_load_elf’ [-Wmissing-prototypes] + 128 | int pfe_load_elf(int pe_mask, const u8 *fw, struct pfe *pfe) + | ^~~~~~~~~~~~ +drivers/staging/fsl_ppfe/pfe_firmware.c:185:5: warning: no previous prototype for ‘get_firmware_in_fdt’ [-Wmissing-prototypes] + 185 | int get_firmware_in_fdt(const u8 **pe_fw, const char *name) + | ^~~~~~~~~~~~~~~~~~~ + +Reviewed-by: Wei Fang +Signed-off-by: Dong Aisheng + +LF-13827-3 net/pfe: use $(src) instead of $(srctree)/$(src) + +Cope with upstream change +b1992c3772e6 ("kbuild: use $(src) instead of $(srctree)/$(src) for source directory") + +Reviewed-by: Wei Fang +Signed-off-by: Dong Aisheng + +LF-13827-6 net: ppfe: update the usage of eventfd_signal + +Cope with the API change since the commit +1808acc4fab2 ("eventfd: simplify eventfd_signal()") + +Otherwise will meet the following build error: +drivers/staging/fsl_ppfe/pfe_cdev.c: In function ‘hif_us_isr’: +drivers/staging/fsl_ppfe/pfe_cdev.c:112:17: error: too many arguments to function ‘eventfd_signal’ + 112 | eventfd_signal(trigger, 1); + | ^~~~~~~~~~~~~~ + +Reviewed-by: Wei Fang +Signed-off-by: Dong Aisheng + +LF-13827-7 net: pfe: Replace strlcpy() with strscpy() for many drivers + +Cope with upstream change: +commit d26270061ae6 ("string: Remove strlcpy()") + +e.g. +../drivers/i2c/busses/i2c-flexio.c: In function ‘imx_flexio_i2c_master_probe’: +../drivers/i2c/busses/i2c-flexio.c:683:9: error: implicit declaration of function ‘strlcpy’; did you mean ‘strncpy’? [-Werror=implicit-function-declaration] + 683 | strlcpy(i2c_dev->adapter.name, dev_name(i2c_dev->dev), + | ^~~~~~~ + | strncpy + +Signed-off-by: Dong Aisheng + +drivers: make all local platform_driver::remove() return void + +0edb555a65d1 ("platform: Make platform_driver::remove() return void") + +Signed-off-by: Dong Aisheng +--- + .../devicetree/bindings/net/fsl_ppfe/pfe.txt | 199 ++ + MAINTAINERS | 8 + + drivers/staging/Kconfig | 2 + + drivers/staging/Makefile | 1 + + drivers/staging/fsl_ppfe/Kconfig | 21 + + drivers/staging/fsl_ppfe/Makefile | 20 + + drivers/staging/fsl_ppfe/TODO | 2 + + drivers/staging/fsl_ppfe/include/pfe/cbus.h | 78 + + .../staging/fsl_ppfe/include/pfe/cbus/bmu.h | 55 + + .../fsl_ppfe/include/pfe/cbus/class_csr.h | 289 ++ + .../fsl_ppfe/include/pfe/cbus/emac_mtip.h | 242 ++ + .../staging/fsl_ppfe/include/pfe/cbus/gpi.h | 86 + + .../staging/fsl_ppfe/include/pfe/cbus/hif.h | 100 + + .../fsl_ppfe/include/pfe/cbus/hif_nocpy.h | 50 + + .../fsl_ppfe/include/pfe/cbus/tmu_csr.h | 168 ++ + .../fsl_ppfe/include/pfe/cbus/util_csr.h | 61 + + drivers/staging/fsl_ppfe/include/pfe/pfe.h | 372 +++ + drivers/staging/fsl_ppfe/pfe_cdev.c | 258 ++ + drivers/staging/fsl_ppfe/pfe_cdev.h | 41 + + drivers/staging/fsl_ppfe/pfe_ctrl.c | 226 ++ + drivers/staging/fsl_ppfe/pfe_ctrl.h | 100 + + drivers/staging/fsl_ppfe/pfe_debugfs.c | 99 + + drivers/staging/fsl_ppfe/pfe_debugfs.h | 13 + + drivers/staging/fsl_ppfe/pfe_eth.c | 2550 +++++++++++++++++ + drivers/staging/fsl_ppfe/pfe_eth.h | 175 ++ + drivers/staging/fsl_ppfe/pfe_firmware.c | 398 +++ + drivers/staging/fsl_ppfe/pfe_firmware.h | 21 + + drivers/staging/fsl_ppfe/pfe_hal.c | 1517 ++++++++++ + drivers/staging/fsl_ppfe/pfe_hif.c | 1063 +++++++ + drivers/staging/fsl_ppfe/pfe_hif.h | 199 ++ + drivers/staging/fsl_ppfe/pfe_hif_lib.c | 628 ++++ + drivers/staging/fsl_ppfe/pfe_hif_lib.h | 229 ++ + drivers/staging/fsl_ppfe/pfe_hw.c | 164 ++ + drivers/staging/fsl_ppfe/pfe_hw.h | 15 + + .../staging/fsl_ppfe/pfe_ls1012a_platform.c | 381 +++ + drivers/staging/fsl_ppfe/pfe_mod.c | 158 + + drivers/staging/fsl_ppfe/pfe_mod.h | 103 + + drivers/staging/fsl_ppfe/pfe_perfmon.h | 26 + + drivers/staging/fsl_ppfe/pfe_sysfs.c | 840 ++++++ + drivers/staging/fsl_ppfe/pfe_sysfs.h | 17 + + 40 files changed, 10975 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/fsl_ppfe/pfe.txt + create mode 100644 drivers/staging/fsl_ppfe/Kconfig + create mode 100644 drivers/staging/fsl_ppfe/Makefile + create mode 100644 drivers/staging/fsl_ppfe/TODO + create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus.h + create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/bmu.h + create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/class_csr.h + create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/emac_mtip.h + create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/gpi.h + create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/hif.h + create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/hif_nocpy.h + create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/tmu_csr.h + create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/util_csr.h + create mode 100644 drivers/staging/fsl_ppfe/include/pfe/pfe.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_cdev.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_cdev.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_ctrl.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_ctrl.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_debugfs.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_debugfs.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_eth.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_eth.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_firmware.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_firmware.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_hal.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_hif.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_hif.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_hif_lib.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_hif_lib.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_hw.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_hw.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_mod.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_mod.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_perfmon.h + create mode 100644 drivers/staging/fsl_ppfe/pfe_sysfs.c + create mode 100644 drivers/staging/fsl_ppfe/pfe_sysfs.h + +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/fsl_ppfe/pfe.txt +@@ -0,0 +1,199 @@ ++============================================================================= ++NXP Programmable Packet Forwarding Engine Device Bindings ++ ++CONTENTS ++ - PFE Node ++ - Ethernet Node ++ ++============================================================================= ++PFE Node ++ ++DESCRIPTION ++ ++PFE Node has all the properties associated with Packet Forwarding Engine block. ++ ++PROPERTIES ++ ++- compatible ++ Usage: required ++ Value type: ++ Definition: Must include "fsl,pfe" ++ ++- reg ++ Usage: required ++ Value type: ++ Definition: A standard property. ++ Specifies the offset of the following registers: ++ - PFE configuration registers ++ - DDR memory used by PFE ++ ++- fsl,pfe-num-interfaces ++ Usage: required ++ Value type: ++ Definition: Must be present. Value can be either one or two. ++ ++- interrupts ++ Usage: required ++ Value type: ++ Definition: Three interrupts are specified in this property. ++ - HIF interrupt ++ - HIF NO COPY interrupt ++ - Wake On LAN interrupt ++ ++- interrupt-names ++ Usage: required ++ Value type: ++ Definition: Following strings are defined for the 3 interrupts. ++ "pfe_hif" - HIF interrupt ++ "pfe_hif_nocpy" - HIF NO COPY interrupt ++ "pfe_wol" - Wake On LAN interrupt ++ ++- memory-region ++ Usage: required ++ Value type: ++ Definition: phandle to a node describing reserved memory used by pfe. ++ Refer:- Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt ++ ++- fsl,pfe-scfg ++ Usage: required ++ Value type: ++ Definition: phandle for scfg. ++ ++- fsl,rcpm-wakeup ++ Usage: required ++ Value type: ++ Definition: phandle for rcpm. ++ ++- clocks ++ Usage: required ++ Value type: ++ Definition: phandle for clockgen. ++ ++- clock-names ++ Usage: required ++ Value type: ++ Definition: phandle for clock name. ++ ++EXAMPLE ++ ++pfe: pfe@04000000 { ++ compatible = "fsl,pfe"; ++ reg = <0x0 0x04000000 0x0 0xc00000>, /* AXI 16M */ ++ <0x0 0x83400000 0x0 0xc00000>; /* PFE DDR 12M */ ++ reg-names = "pfe", "pfe-ddr"; ++ fsl,pfe-num-interfaces = <0x2>; ++ interrupts = <0 172 0x4>, /* HIF interrupt */ ++ <0 173 0x4>, /*HIF_NOCPY interrupt */ ++ <0 174 0x4>; /* WoL interrupt */ ++ interrupt-names = "pfe_hif", "pfe_hif_nocpy", "pfe_wol"; ++ memory-region = <&pfe_reserved>; ++ fsl,pfe-scfg = <&scfg 0>; ++ fsl,rcpm-wakeup = <&rcpm 0xf0000020>; ++ clocks = <&clockgen 4 0>; ++ clock-names = "pfe"; ++ ++ status = "okay"; ++ pfe_mac0: ethernet@0 { ++ }; ++ ++ pfe_mac1: ethernet@1 { ++ }; ++}; ++ ++============================================================================= ++Ethernet Node ++ ++DESCRIPTION ++ ++Ethernet Node has all the properties associated with PFE used by platforms to ++connect to PHY: ++ ++PROPERTIES ++ ++- compatible ++ Usage: required ++ Value type: ++ Definition: Must include "fsl,pfe-gemac-port" ++ ++- reg ++ Usage: required ++ Value type: ++ Definition: A standard property. ++ Specifies the gemacid of the interface. ++ ++- fsl,gemac-bus-id ++ Usage: required ++ Value type: ++ Definition: Must be present. Value should be the id of the bus ++ connected to gemac. ++ ++- fsl,gemac-phy-id (deprecated binding) ++ Usage: required ++ Value type: ++ Definition: This binding shouldn't be used with new platforms. ++ Must be present. Value should be the id of the phy ++ connected to gemac. ++ ++- fsl,mdio-mux-val ++ Usage: required ++ Value type: ++ Definition: Must be present. Value can be either 0 or 2 or 3. ++ This value is used to configure the mux to enable mdio. ++ ++- phy-mode ++ Usage: required ++ Value type: ++ Definition: Must include "sgmii" ++ ++- fsl,pfe-phy-if-flags (deprecated binding) ++ Usage: required ++ Value type: ++ Definition: This binding shouldn't be used with new platforms. ++ Must be present. Value should be 0 by default. ++ If there is not phy connected, this need to be 1. ++ ++- phy-handle ++ Usage: optional ++ Value type: ++ Definition: phandle to the PHY device connected to this device. ++ ++- mdio : A required subnode which specifies the mdio bus in the PFE and used as ++a container for phy nodes according to ../phy.txt. ++ ++EXAMPLE ++ ++ethernet@0 { ++ compatible = "fsl,pfe-gemac-port"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0>; /* GEM_ID */ ++ fsl,gemac-bus-id = <0x0>; /* BUS_ID */ ++ fsl,mdio-mux-val = <0x0>; ++ phy-mode = "sgmii"; ++ phy-handle = <&sgmii_phy1>; ++}; ++ ++ ++ethernet@1 { ++ compatible = "fsl,pfe-gemac-port"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x1>; /* GEM_ID */ ++ fsl,gemac-bus-id = <0x1>; /* BUS_ID */ ++ fsl,mdio-mux-val = <0x0>; ++ phy-mode = "sgmii"; ++ phy-handle = <&sgmii_phy2>; ++}; ++ ++mdio@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ sgmii_phy1: ethernet-phy@2 { ++ reg = <0x2>; ++ }; ++ ++ sgmii_phy2: ethernet-phy@1 { ++ reg = <0x1>; ++ }; ++}; +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -9114,6 +9114,14 @@ F: drivers/ptp/ptp_qoriq.c + F: drivers/ptp/ptp_qoriq_debugfs.c + F: include/linux/fsl/ptp_qoriq.h + ++FREESCALE QORIQ PPFE ETHERNET DRIVER ++M: Anji Jagarlmudi ++M: Calvin Johnson ++L: netdev@vger.kernel.org ++S: Maintained ++F: drivers/staging/fsl_ppfe ++F: Documentation/devicetree/bindings/net/fsl_ppfe/pfe.txt ++ + FREESCALE QUAD SPI DRIVER + M: Han Xu + L: linux-spi@vger.kernel.org +--- a/drivers/staging/Kconfig ++++ b/drivers/staging/Kconfig +@@ -62,4 +62,6 @@ source "drivers/staging/fieldbus/Kconfig + + source "drivers/staging/vme_user/Kconfig" + ++source "drivers/staging/fsl_ppfe/Kconfig" ++ + endif # STAGING +--- a/drivers/staging/Makefile ++++ b/drivers/staging/Makefile +@@ -20,3 +20,4 @@ obj-$(CONFIG_GREYBUS) += greybus/ + obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ + obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ + obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ ++obj-$(CONFIG_FSL_PPFE) += fsl_ppfe/ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/Kconfig +@@ -0,0 +1,21 @@ ++# ++# Freescale Programmable Packet Forwarding Engine driver ++# ++config FSL_PPFE ++ tristate "Freescale PPFE Driver" ++ select FSL_GUTS ++ default n ++ help ++ Freescale LS1012A SoC has a Programmable Packet Forwarding Engine. ++ It provides two high performance ethernet interfaces. ++ This driver initializes, programs and controls the PPFE. ++ Use this driver to enable network connectivity on LS1012A platforms. ++ ++if FSL_PPFE ++ ++config FSL_PPFE_UTIL_DISABLED ++ bool "Disable PPFE UTIL Processor Engine" ++ help ++ UTIL PE has to be enabled only if required. ++ ++endif # FSL_PPFE +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/Makefile +@@ -0,0 +1,20 @@ ++# ++# Makefile for Freesecale PPFE driver ++# ++ ++ccflags-y += -I $(src)/include -I $(src) ++ ++obj-$(CONFIG_FSL_PPFE) += pfe.o ++ ++pfe-y += pfe_mod.o \ ++ pfe_hw.o \ ++ pfe_firmware.o \ ++ pfe_ctrl.o \ ++ pfe_hif.o \ ++ pfe_hif_lib.o\ ++ pfe_eth.o \ ++ pfe_sysfs.o \ ++ pfe_debugfs.o \ ++ pfe_ls1012a_platform.o \ ++ pfe_hal.o \ ++ pfe_cdev.o +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/TODO +@@ -0,0 +1,2 @@ ++TODO: ++ - provide pfe pe monitoring support +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/include/pfe/cbus.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _CBUS_H_ ++#define _CBUS_H_ ++ ++#define EMAC1_BASE_ADDR (CBUS_BASE_ADDR + 0x200000) ++#define EGPI1_BASE_ADDR (CBUS_BASE_ADDR + 0x210000) ++#define EMAC2_BASE_ADDR (CBUS_BASE_ADDR + 0x220000) ++#define EGPI2_BASE_ADDR (CBUS_BASE_ADDR + 0x230000) ++#define BMU1_BASE_ADDR (CBUS_BASE_ADDR + 0x240000) ++#define BMU2_BASE_ADDR (CBUS_BASE_ADDR + 0x250000) ++#define ARB_BASE_ADDR (CBUS_BASE_ADDR + 0x260000) ++#define DDR_CONFIG_BASE_ADDR (CBUS_BASE_ADDR + 0x270000) ++#define HIF_BASE_ADDR (CBUS_BASE_ADDR + 0x280000) ++#define HGPI_BASE_ADDR (CBUS_BASE_ADDR + 0x290000) ++#define LMEM_BASE_ADDR (CBUS_BASE_ADDR + 0x300000) ++#define LMEM_SIZE 0x10000 ++#define LMEM_END (LMEM_BASE_ADDR + LMEM_SIZE) ++#define TMU_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x310000) ++#define CLASS_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x320000) ++#define HIF_NOCPY_BASE_ADDR (CBUS_BASE_ADDR + 0x350000) ++#define UTIL_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x360000) ++#define CBUS_GPT_BASE_ADDR (CBUS_BASE_ADDR + 0x370000) ++ ++/* ++ * defgroup XXX_MEM_ACCESS_ADDR PE memory access through CSR ++ * XXX_MEM_ACCESS_ADDR register bit definitions. ++ */ ++#define PE_MEM_ACCESS_WRITE BIT(31) /* Internal Memory Write. */ ++#define PE_MEM_ACCESS_IMEM BIT(15) ++#define PE_MEM_ACCESS_DMEM BIT(16) ++ ++/* Byte Enables of the Internal memory access. These are interpred in BE */ ++#define PE_MEM_ACCESS_BYTE_ENABLE(offset, size) \ ++ ({ typeof(size) size_ = (size); \ ++ (((BIT(size_) - 1) << (4 - (offset) - (size_))) & 0xf) << 24; }) ++ ++#include "cbus/emac_mtip.h" ++#include "cbus/gpi.h" ++#include "cbus/bmu.h" ++#include "cbus/hif.h" ++#include "cbus/tmu_csr.h" ++#include "cbus/class_csr.h" ++#include "cbus/hif_nocpy.h" ++#include "cbus/util_csr.h" ++ ++/* PFE cores states */ ++#define CORE_DISABLE 0x00000000 ++#define CORE_ENABLE 0x00000001 ++#define CORE_SW_RESET 0x00000002 ++ ++/* LMEM defines */ ++#define LMEM_HDR_SIZE 0x0010 ++#define LMEM_BUF_SIZE_LN2 0x7 ++#define LMEM_BUF_SIZE BIT(LMEM_BUF_SIZE_LN2) ++ ++/* DDR defines */ ++#define DDR_HDR_SIZE 0x0100 ++#define DDR_BUF_SIZE_LN2 0xb ++#define DDR_BUF_SIZE BIT(DDR_BUF_SIZE_LN2) ++ ++#endif /* _CBUS_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/bmu.h +@@ -0,0 +1,55 @@ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _BMU_H_ ++#define _BMU_H_ ++ ++#define BMU_VERSION 0x000 ++#define BMU_CTRL 0x004 ++#define BMU_UCAST_CONFIG 0x008 ++#define BMU_UCAST_BASE_ADDR 0x00c ++#define BMU_BUF_SIZE 0x010 ++#define BMU_BUF_CNT 0x014 ++#define BMU_THRES 0x018 ++#define BMU_INT_SRC 0x020 ++#define BMU_INT_ENABLE 0x024 ++#define BMU_ALLOC_CTRL 0x030 ++#define BMU_FREE_CTRL 0x034 ++#define BMU_FREE_ERR_ADDR 0x038 ++#define BMU_CURR_BUF_CNT 0x03c ++#define BMU_MCAST_CNT 0x040 ++#define BMU_MCAST_ALLOC_CTRL 0x044 ++#define BMU_REM_BUF_CNT 0x048 ++#define BMU_LOW_WATERMARK 0x050 ++#define BMU_HIGH_WATERMARK 0x054 ++#define BMU_INT_MEM_ACCESS 0x100 ++ ++struct BMU_CFG { ++ unsigned long baseaddr; ++ u32 count; ++ u32 size; ++ u32 low_watermark; ++ u32 high_watermark; ++}; ++ ++#define BMU1_BUF_SIZE LMEM_BUF_SIZE_LN2 ++#define BMU2_BUF_SIZE DDR_BUF_SIZE_LN2 ++ ++#define BMU2_MCAST_ALLOC_CTRL (BMU2_BASE_ADDR + BMU_MCAST_ALLOC_CTRL) ++ ++#endif /* _BMU_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/class_csr.h +@@ -0,0 +1,289 @@ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _CLASS_CSR_H_ ++#define _CLASS_CSR_H_ ++ ++/* @file class_csr.h. ++ * class_csr - block containing all the classifier control and status register. ++ * Mapped on CBUS and accessible from all PE's and ARM. ++ */ ++#define CLASS_VERSION (CLASS_CSR_BASE_ADDR + 0x000) ++#define CLASS_TX_CTRL (CLASS_CSR_BASE_ADDR + 0x004) ++#define CLASS_INQ_PKTPTR (CLASS_CSR_BASE_ADDR + 0x010) ++ ++/* (ddr_hdr_size[24:16], lmem_hdr_size[5:0]) */ ++#define CLASS_HDR_SIZE (CLASS_CSR_BASE_ADDR + 0x014) ++ ++/* LMEM header size for the Classifier block.\ Data in the LMEM ++ * is written from this offset. ++ */ ++#define CLASS_HDR_SIZE_LMEM(off) ((off) & 0x3f) ++ ++/* DDR header size for the Classifier block.\ Data in the DDR ++ * is written from this offset. ++ */ ++#define CLASS_HDR_SIZE_DDR(off) (((off) & 0x1ff) << 16) ++ ++#define CLASS_PE0_QB_DM_ADDR0 (CLASS_CSR_BASE_ADDR + 0x020) ++ ++/* DMEM address of first [15:0] and second [31:16] buffers on QB side. */ ++#define CLASS_PE0_QB_DM_ADDR1 (CLASS_CSR_BASE_ADDR + 0x024) ++ ++/* DMEM address of third [15:0] and fourth [31:16] buffers on QB side. */ ++#define CLASS_PE0_RO_DM_ADDR0 (CLASS_CSR_BASE_ADDR + 0x060) ++ ++/* DMEM address of first [15:0] and second [31:16] buffers on RO side. */ ++#define CLASS_PE0_RO_DM_ADDR1 (CLASS_CSR_BASE_ADDR + 0x064) ++ ++/* DMEM address of third [15:0] and fourth [31:16] buffers on RO side. */ ++ ++/* @name Class PE memory access. Allows external PE's and HOST to ++ * read/write PMEM/DMEM memory ranges for each classifier PE. ++ */ ++/* {sr_pe_mem_cmd[31], csr_pe_mem_wren[27:24], csr_pe_mem_addr[23:0]}, ++ * See \ref XXX_MEM_ACCESS_ADDR for details. ++ */ ++#define CLASS_MEM_ACCESS_ADDR (CLASS_CSR_BASE_ADDR + 0x100) ++ ++/* Internal Memory Access Write Data [31:0] */ ++#define CLASS_MEM_ACCESS_WDATA (CLASS_CSR_BASE_ADDR + 0x104) ++ ++/* Internal Memory Access Read Data [31:0] */ ++#define CLASS_MEM_ACCESS_RDATA (CLASS_CSR_BASE_ADDR + 0x108) ++#define CLASS_TM_INQ_ADDR (CLASS_CSR_BASE_ADDR + 0x114) ++#define CLASS_PE_STATUS (CLASS_CSR_BASE_ADDR + 0x118) ++ ++#define CLASS_PHY1_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x11c) ++#define CLASS_PHY1_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x120) ++#define CLASS_PHY1_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x124) ++#define CLASS_PHY1_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x128) ++#define CLASS_PHY1_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x12c) ++#define CLASS_PHY1_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x130) ++#define CLASS_PHY1_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x134) ++#define CLASS_PHY1_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x138) ++#define CLASS_PHY1_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x13c) ++#define CLASS_PHY1_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x140) ++#define CLASS_PHY2_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x144) ++#define CLASS_PHY2_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x148) ++#define CLASS_PHY2_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x14c) ++#define CLASS_PHY2_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x150) ++#define CLASS_PHY2_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x154) ++#define CLASS_PHY2_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x158) ++#define CLASS_PHY2_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x15c) ++#define CLASS_PHY2_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x160) ++#define CLASS_PHY2_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x164) ++#define CLASS_PHY2_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x168) ++#define CLASS_PHY3_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x16c) ++#define CLASS_PHY3_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x170) ++#define CLASS_PHY3_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x174) ++#define CLASS_PHY3_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x178) ++#define CLASS_PHY3_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x17c) ++#define CLASS_PHY3_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x180) ++#define CLASS_PHY3_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x184) ++#define CLASS_PHY3_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x188) ++#define CLASS_PHY3_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x18c) ++#define CLASS_PHY3_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x190) ++#define CLASS_PHY1_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x194) ++#define CLASS_PHY1_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x198) ++#define CLASS_PHY1_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x19c) ++#define CLASS_PHY1_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1a0) ++#define CLASS_PHY2_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1a4) ++#define CLASS_PHY2_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1a8) ++#define CLASS_PHY2_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x1ac) ++#define CLASS_PHY2_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1b0) ++#define CLASS_PHY3_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1b4) ++#define CLASS_PHY3_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1b8) ++#define CLASS_PHY3_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x1bc) ++#define CLASS_PHY3_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1c0) ++#define CLASS_PHY4_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1c4) ++#define CLASS_PHY4_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1c8) ++#define CLASS_PHY4_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x1cc) ++#define CLASS_PHY4_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1d0) ++#define CLASS_PHY4_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x1d4) ++#define CLASS_PHY4_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x1d8) ++#define CLASS_PHY4_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x1dc) ++#define CLASS_PHY4_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x1e0) ++#define CLASS_PHY4_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x1e4) ++#define CLASS_PHY4_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x1e8) ++#define CLASS_PHY4_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x1ec) ++#define CLASS_PHY4_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x1f0) ++#define CLASS_PHY4_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x1f4) ++#define CLASS_PHY4_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x1f8) ++ ++#define CLASS_PE_SYS_CLK_RATIO (CLASS_CSR_BASE_ADDR + 0x200) ++#define CLASS_AFULL_THRES (CLASS_CSR_BASE_ADDR + 0x204) ++#define CLASS_GAP_BETWEEN_READS (CLASS_CSR_BASE_ADDR + 0x208) ++#define CLASS_MAX_BUF_CNT (CLASS_CSR_BASE_ADDR + 0x20c) ++#define CLASS_TSQ_FIFO_THRES (CLASS_CSR_BASE_ADDR + 0x210) ++#define CLASS_TSQ_MAX_CNT (CLASS_CSR_BASE_ADDR + 0x214) ++#define CLASS_IRAM_DATA_0 (CLASS_CSR_BASE_ADDR + 0x218) ++#define CLASS_IRAM_DATA_1 (CLASS_CSR_BASE_ADDR + 0x21c) ++#define CLASS_IRAM_DATA_2 (CLASS_CSR_BASE_ADDR + 0x220) ++#define CLASS_IRAM_DATA_3 (CLASS_CSR_BASE_ADDR + 0x224) ++ ++#define CLASS_BUS_ACCESS_ADDR (CLASS_CSR_BASE_ADDR + 0x228) ++ ++#define CLASS_BUS_ACCESS_WDATA (CLASS_CSR_BASE_ADDR + 0x22c) ++#define CLASS_BUS_ACCESS_RDATA (CLASS_CSR_BASE_ADDR + 0x230) ++ ++/* (route_entry_size[9:0], route_hash_size[23:16] ++ * (this is actually ln2(size))) ++ */ ++#define CLASS_ROUTE_HASH_ENTRY_SIZE (CLASS_CSR_BASE_ADDR + 0x234) ++ ++#define CLASS_ROUTE_ENTRY_SIZE(size) ((size) & 0x1ff) ++#define CLASS_ROUTE_HASH_SIZE(hash_bits) (((hash_bits) & 0xff) << 16) ++ ++#define CLASS_ROUTE_TABLE_BASE (CLASS_CSR_BASE_ADDR + 0x238) ++ ++#define CLASS_ROUTE_MULTI (CLASS_CSR_BASE_ADDR + 0x23c) ++#define CLASS_SMEM_OFFSET (CLASS_CSR_BASE_ADDR + 0x240) ++#define CLASS_LMEM_BUF_SIZE (CLASS_CSR_BASE_ADDR + 0x244) ++#define CLASS_VLAN_ID (CLASS_CSR_BASE_ADDR + 0x248) ++#define CLASS_BMU1_BUF_FREE (CLASS_CSR_BASE_ADDR + 0x24c) ++#define CLASS_USE_TMU_INQ (CLASS_CSR_BASE_ADDR + 0x250) ++#define CLASS_VLAN_ID1 (CLASS_CSR_BASE_ADDR + 0x254) ++ ++#define CLASS_BUS_ACCESS_BASE (CLASS_CSR_BASE_ADDR + 0x258) ++#define CLASS_BUS_ACCESS_BASE_MASK (0xFF000000) ++/* bit 31:24 of PE peripheral address are stored in CLASS_BUS_ACCESS_BASE */ ++ ++#define CLASS_HIF_PARSE (CLASS_CSR_BASE_ADDR + 0x25c) ++ ++#define CLASS_HOST_PE0_GP (CLASS_CSR_BASE_ADDR + 0x260) ++#define CLASS_PE0_GP (CLASS_CSR_BASE_ADDR + 0x264) ++#define CLASS_HOST_PE1_GP (CLASS_CSR_BASE_ADDR + 0x268) ++#define CLASS_PE1_GP (CLASS_CSR_BASE_ADDR + 0x26c) ++#define CLASS_HOST_PE2_GP (CLASS_CSR_BASE_ADDR + 0x270) ++#define CLASS_PE2_GP (CLASS_CSR_BASE_ADDR + 0x274) ++#define CLASS_HOST_PE3_GP (CLASS_CSR_BASE_ADDR + 0x278) ++#define CLASS_PE3_GP (CLASS_CSR_BASE_ADDR + 0x27c) ++#define CLASS_HOST_PE4_GP (CLASS_CSR_BASE_ADDR + 0x280) ++#define CLASS_PE4_GP (CLASS_CSR_BASE_ADDR + 0x284) ++#define CLASS_HOST_PE5_GP (CLASS_CSR_BASE_ADDR + 0x288) ++#define CLASS_PE5_GP (CLASS_CSR_BASE_ADDR + 0x28c) ++ ++#define CLASS_PE_INT_SRC (CLASS_CSR_BASE_ADDR + 0x290) ++#define CLASS_PE_INT_ENABLE (CLASS_CSR_BASE_ADDR + 0x294) ++ ++#define CLASS_TPID0_TPID1 (CLASS_CSR_BASE_ADDR + 0x298) ++#define CLASS_TPID2 (CLASS_CSR_BASE_ADDR + 0x29c) ++ ++#define CLASS_L4_CHKSUM_ADDR (CLASS_CSR_BASE_ADDR + 0x2a0) ++ ++#define CLASS_PE0_DEBUG (CLASS_CSR_BASE_ADDR + 0x2a4) ++#define CLASS_PE1_DEBUG (CLASS_CSR_BASE_ADDR + 0x2a8) ++#define CLASS_PE2_DEBUG (CLASS_CSR_BASE_ADDR + 0x2ac) ++#define CLASS_PE3_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b0) ++#define CLASS_PE4_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b4) ++#define CLASS_PE5_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b8) ++ ++#define CLASS_STATE (CLASS_CSR_BASE_ADDR + 0x2bc) ++ ++/* CLASS defines */ ++#define CLASS_PBUF_SIZE 0x100 /* Fixed by hardware */ ++#define CLASS_PBUF_HEADER_OFFSET 0x80 /* Can be configured */ ++ ++/* Can be configured */ ++#define CLASS_PBUF0_BASE_ADDR 0x000 ++/* Can be configured */ ++#define CLASS_PBUF1_BASE_ADDR (CLASS_PBUF0_BASE_ADDR + CLASS_PBUF_SIZE) ++/* Can be configured */ ++#define CLASS_PBUF2_BASE_ADDR (CLASS_PBUF1_BASE_ADDR + CLASS_PBUF_SIZE) ++/* Can be configured */ ++#define CLASS_PBUF3_BASE_ADDR (CLASS_PBUF2_BASE_ADDR + CLASS_PBUF_SIZE) ++ ++#define CLASS_PBUF0_HEADER_BASE_ADDR (CLASS_PBUF0_BASE_ADDR + \ ++ CLASS_PBUF_HEADER_OFFSET) ++#define CLASS_PBUF1_HEADER_BASE_ADDR (CLASS_PBUF1_BASE_ADDR + \ ++ CLASS_PBUF_HEADER_OFFSET) ++#define CLASS_PBUF2_HEADER_BASE_ADDR (CLASS_PBUF2_BASE_ADDR + \ ++ CLASS_PBUF_HEADER_OFFSET) ++#define CLASS_PBUF3_HEADER_BASE_ADDR (CLASS_PBUF3_BASE_ADDR + \ ++ CLASS_PBUF_HEADER_OFFSET) ++ ++#define CLASS_PE0_RO_DM_ADDR0_VAL ((CLASS_PBUF1_BASE_ADDR << 16) | \ ++ CLASS_PBUF0_BASE_ADDR) ++#define CLASS_PE0_RO_DM_ADDR1_VAL ((CLASS_PBUF3_BASE_ADDR << 16) | \ ++ CLASS_PBUF2_BASE_ADDR) ++ ++#define CLASS_PE0_QB_DM_ADDR0_VAL ((CLASS_PBUF1_HEADER_BASE_ADDR << 16) |\ ++ CLASS_PBUF0_HEADER_BASE_ADDR) ++#define CLASS_PE0_QB_DM_ADDR1_VAL ((CLASS_PBUF3_HEADER_BASE_ADDR << 16) |\ ++ CLASS_PBUF2_HEADER_BASE_ADDR) ++ ++#define CLASS_ROUTE_SIZE 128 ++#define CLASS_MAX_ROUTE_SIZE 256 ++#define CLASS_ROUTE_HASH_BITS 20 ++#define CLASS_ROUTE_HASH_MASK (BIT(CLASS_ROUTE_HASH_BITS) - 1) ++ ++/* Can be configured */ ++#define CLASS_ROUTE0_BASE_ADDR 0x400 ++/* Can be configured */ ++#define CLASS_ROUTE1_BASE_ADDR (CLASS_ROUTE0_BASE_ADDR + CLASS_ROUTE_SIZE) ++/* Can be configured */ ++#define CLASS_ROUTE2_BASE_ADDR (CLASS_ROUTE1_BASE_ADDR + CLASS_ROUTE_SIZE) ++/* Can be configured */ ++#define CLASS_ROUTE3_BASE_ADDR (CLASS_ROUTE2_BASE_ADDR + CLASS_ROUTE_SIZE) ++ ++#define CLASS_SA_SIZE 128 ++#define CLASS_IPSEC_SA0_BASE_ADDR 0x600 ++/* not used */ ++#define CLASS_IPSEC_SA1_BASE_ADDR (CLASS_IPSEC_SA0_BASE_ADDR + CLASS_SA_SIZE) ++/* not used */ ++#define CLASS_IPSEC_SA2_BASE_ADDR (CLASS_IPSEC_SA1_BASE_ADDR + CLASS_SA_SIZE) ++/* not used */ ++#define CLASS_IPSEC_SA3_BASE_ADDR (CLASS_IPSEC_SA2_BASE_ADDR + CLASS_SA_SIZE) ++ ++/* generic purpose free dmem buffer, last portion of 2K dmem pbuf */ ++#define CLASS_GP_DMEM_BUF_SIZE (2048 - (CLASS_PBUF_SIZE * 4) - \ ++ (CLASS_ROUTE_SIZE * 4) - (CLASS_SA_SIZE)) ++#define CLASS_GP_DMEM_BUF ((void *)(CLASS_IPSEC_SA0_BASE_ADDR + \ ++ CLASS_SA_SIZE)) ++ ++#define TWO_LEVEL_ROUTE BIT(0) ++#define PHYNO_IN_HASH BIT(1) ++#define HW_ROUTE_FETCH BIT(3) ++#define HW_BRIDGE_FETCH BIT(5) ++#define IP_ALIGNED BIT(6) ++#define ARC_HIT_CHECK_EN BIT(7) ++#define CLASS_TOE BIT(11) ++#define HASH_NORMAL (0 << 12) ++#define HASH_CRC_PORT BIT(12) ++#define HASH_CRC_IP (2 << 12) ++#define HASH_CRC_PORT_IP (3 << 12) ++#define QB2BUS_LE BIT(15) ++ ++#define TCP_CHKSUM_DROP BIT(0) ++#define UDP_CHKSUM_DROP BIT(1) ++#define IPV4_CHKSUM_DROP BIT(9) ++ ++/*CLASS_HIF_PARSE bits*/ ++#define HIF_PKT_CLASS_EN BIT(0) ++#define HIF_PKT_OFFSET(ofst) (((ofst) & 0xF) << 1) ++ ++struct class_cfg { ++ u32 toe_mode; ++ unsigned long route_table_baseaddr; ++ u32 route_table_hash_bits; ++ u32 pe_sys_clk_ratio; ++ u32 resume; ++}; ++ ++#endif /* _CLASS_CSR_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/emac_mtip.h +@@ -0,0 +1,242 @@ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _EMAC_H_ ++#define _EMAC_H_ ++ ++#include ++ ++#define EMAC_IEVENT_REG 0x004 ++#define EMAC_IMASK_REG 0x008 ++#define EMAC_R_DES_ACTIVE_REG 0x010 ++#define EMAC_X_DES_ACTIVE_REG 0x014 ++#define EMAC_ECNTRL_REG 0x024 ++#define EMAC_MII_DATA_REG 0x040 ++#define EMAC_MII_CTRL_REG 0x044 ++#define EMAC_MIB_CTRL_STS_REG 0x064 ++#define EMAC_RCNTRL_REG 0x084 ++#define EMAC_TCNTRL_REG 0x0C4 ++#define EMAC_PHY_ADDR_LOW 0x0E4 ++#define EMAC_PHY_ADDR_HIGH 0x0E8 ++#define EMAC_GAUR 0x120 ++#define EMAC_GALR 0x124 ++#define EMAC_TFWR_STR_FWD 0x144 ++#define EMAC_RX_SECTION_FULL 0x190 ++#define EMAC_RX_SECTION_EMPTY 0x194 ++#define EMAC_TX_SECTION_EMPTY 0x1A0 ++#define EMAC_TRUNC_FL 0x1B0 ++ ++#define RMON_T_DROP 0x200 /* Count of frames not cntd correctly */ ++#define RMON_T_PACKETS 0x204 /* RMON TX packet count */ ++#define RMON_T_BC_PKT 0x208 /* RMON TX broadcast pkts */ ++#define RMON_T_MC_PKT 0x20c /* RMON TX multicast pkts */ ++#define RMON_T_CRC_ALIGN 0x210 /* RMON TX pkts with CRC align err */ ++#define RMON_T_UNDERSIZE 0x214 /* RMON TX pkts < 64 bytes, good CRC */ ++#define RMON_T_OVERSIZE 0x218 /* RMON TX pkts > MAX_FL bytes good CRC */ ++#define RMON_T_FRAG 0x21c /* RMON TX pkts < 64 bytes, bad CRC */ ++#define RMON_T_JAB 0x220 /* RMON TX pkts > MAX_FL bytes, bad CRC */ ++#define RMON_T_COL 0x224 /* RMON TX collision count */ ++#define RMON_T_P64 0x228 /* RMON TX 64 byte pkts */ ++#define RMON_T_P65TO127 0x22c /* RMON TX 65 to 127 byte pkts */ ++#define RMON_T_P128TO255 0x230 /* RMON TX 128 to 255 byte pkts */ ++#define RMON_T_P256TO511 0x234 /* RMON TX 256 to 511 byte pkts */ ++#define RMON_T_P512TO1023 0x238 /* RMON TX 512 to 1023 byte pkts */ ++#define RMON_T_P1024TO2047 0x23c /* RMON TX 1024 to 2047 byte pkts */ ++#define RMON_T_P_GTE2048 0x240 /* RMON TX pkts > 2048 bytes */ ++#define RMON_T_OCTETS 0x244 /* RMON TX octets */ ++#define IEEE_T_DROP 0x248 /* Count of frames not counted crtly */ ++#define IEEE_T_FRAME_OK 0x24c /* Frames tx'd OK */ ++#define IEEE_T_1COL 0x250 /* Frames tx'd with single collision */ ++#define IEEE_T_MCOL 0x254 /* Frames tx'd with multiple collision */ ++#define IEEE_T_DEF 0x258 /* Frames tx'd after deferral delay */ ++#define IEEE_T_LCOL 0x25c /* Frames tx'd with late collision */ ++#define IEEE_T_EXCOL 0x260 /* Frames tx'd with excesv collisions */ ++#define IEEE_T_MACERR 0x264 /* Frames tx'd with TX FIFO underrun */ ++#define IEEE_T_CSERR 0x268 /* Frames tx'd with carrier sense err */ ++#define IEEE_T_SQE 0x26c /* Frames tx'd with SQE err */ ++#define IEEE_T_FDXFC 0x270 /* Flow control pause frames tx'd */ ++#define IEEE_T_OCTETS_OK 0x274 /* Octet count for frames tx'd w/o err */ ++#define RMON_R_PACKETS 0x284 /* RMON RX packet count */ ++#define RMON_R_BC_PKT 0x288 /* RMON RX broadcast pkts */ ++#define RMON_R_MC_PKT 0x28c /* RMON RX multicast pkts */ ++#define RMON_R_CRC_ALIGN 0x290 /* RMON RX pkts with CRC alignment err */ ++#define RMON_R_UNDERSIZE 0x294 /* RMON RX pkts < 64 bytes, good CRC */ ++#define RMON_R_OVERSIZE 0x298 /* RMON RX pkts > MAX_FL bytes good CRC */ ++#define RMON_R_FRAG 0x29c /* RMON RX pkts < 64 bytes, bad CRC */ ++#define RMON_R_JAB 0x2a0 /* RMON RX pkts > MAX_FL bytes, bad CRC */ ++#define RMON_R_RESVD_O 0x2a4 /* Reserved */ ++#define RMON_R_P64 0x2a8 /* RMON RX 64 byte pkts */ ++#define RMON_R_P65TO127 0x2ac /* RMON RX 65 to 127 byte pkts */ ++#define RMON_R_P128TO255 0x2b0 /* RMON RX 128 to 255 byte pkts */ ++#define RMON_R_P256TO511 0x2b4 /* RMON RX 256 to 511 byte pkts */ ++#define RMON_R_P512TO1023 0x2b8 /* RMON RX 512 to 1023 byte pkts */ ++#define RMON_R_P1024TO2047 0x2bc /* RMON RX 1024 to 2047 byte pkts */ ++#define RMON_R_P_GTE2048 0x2c0 /* RMON RX pkts > 2048 bytes */ ++#define RMON_R_OCTETS 0x2c4 /* RMON RX octets */ ++#define IEEE_R_DROP 0x2c8 /* Count frames not counted correctly */ ++#define IEEE_R_FRAME_OK 0x2cc /* Frames rx'd OK */ ++#define IEEE_R_CRC 0x2d0 /* Frames rx'd with CRC err */ ++#define IEEE_R_ALIGN 0x2d4 /* Frames rx'd with alignment err */ ++#define IEEE_R_MACERR 0x2d8 /* Receive FIFO overflow count */ ++#define IEEE_R_FDXFC 0x2dc /* Flow control pause frames rx'd */ ++#define IEEE_R_OCTETS_OK 0x2e0 /* Octet cnt for frames rx'd w/o err */ ++ ++#define EMAC_SMAC_0_0 0x500 /*Supplemental MAC Address 0 (RW).*/ ++#define EMAC_SMAC_0_1 0x504 /*Supplemental MAC Address 0 (RW).*/ ++ ++/* GEMAC definitions and settings */ ++ ++#define EMAC_PORT_0 0 ++#define EMAC_PORT_1 1 ++ ++/* GEMAC Bit definitions */ ++#define EMAC_IEVENT_HBERR 0x80000000 ++#define EMAC_IEVENT_BABR 0x40000000 ++#define EMAC_IEVENT_BABT 0x20000000 ++#define EMAC_IEVENT_GRA 0x10000000 ++#define EMAC_IEVENT_TXF 0x08000000 ++#define EMAC_IEVENT_TXB 0x04000000 ++#define EMAC_IEVENT_RXF 0x02000000 ++#define EMAC_IEVENT_RXB 0x01000000 ++#define EMAC_IEVENT_MII 0x00800000 ++#define EMAC_IEVENT_EBERR 0x00400000 ++#define EMAC_IEVENT_LC 0x00200000 ++#define EMAC_IEVENT_RL 0x00100000 ++#define EMAC_IEVENT_UN 0x00080000 ++ ++#define EMAC_IMASK_HBERR 0x80000000 ++#define EMAC_IMASK_BABR 0x40000000 ++#define EMAC_IMASKT_BABT 0x20000000 ++#define EMAC_IMASK_GRA 0x10000000 ++#define EMAC_IMASKT_TXF 0x08000000 ++#define EMAC_IMASK_TXB 0x04000000 ++#define EMAC_IMASKT_RXF 0x02000000 ++#define EMAC_IMASK_RXB 0x01000000 ++#define EMAC_IMASK_MII 0x00800000 ++#define EMAC_IMASK_EBERR 0x00400000 ++#define EMAC_IMASK_LC 0x00200000 ++#define EMAC_IMASKT_RL 0x00100000 ++#define EMAC_IMASK_UN 0x00080000 ++ ++#define EMAC_RCNTRL_MAX_FL_SHIFT 16 ++#define EMAC_RCNTRL_LOOP 0x00000001 ++#define EMAC_RCNTRL_DRT 0x00000002 ++#define EMAC_RCNTRL_MII_MODE 0x00000004 ++#define EMAC_RCNTRL_PROM 0x00000008 ++#define EMAC_RCNTRL_BC_REJ 0x00000010 ++#define EMAC_RCNTRL_FCE 0x00000020 ++#define EMAC_RCNTRL_RGMII 0x00000040 ++#define EMAC_RCNTRL_SGMII 0x00000080 ++#define EMAC_RCNTRL_RMII 0x00000100 ++#define EMAC_RCNTRL_RMII_10T 0x00000200 ++#define EMAC_RCNTRL_CRC_FWD 0x00004000 ++ ++#define EMAC_TCNTRL_GTS 0x00000001 ++#define EMAC_TCNTRL_HBC 0x00000002 ++#define EMAC_TCNTRL_FDEN 0x00000004 ++#define EMAC_TCNTRL_TFC_PAUSE 0x00000008 ++#define EMAC_TCNTRL_RFC_PAUSE 0x00000010 ++ ++#define EMAC_ECNTRL_RESET 0x00000001 /* reset the EMAC */ ++#define EMAC_ECNTRL_ETHER_EN 0x00000002 /* enable the EMAC */ ++#define EMAC_ECNTRL_MAGIC_ENA 0x00000004 ++#define EMAC_ECNTRL_SLEEP 0x00000008 ++#define EMAC_ECNTRL_SPEED 0x00000020 ++#define EMAC_ECNTRL_DBSWAP 0x00000100 ++ ++#define EMAC_X_WMRK_STRFWD 0x00000100 ++ ++#define EMAC_X_DES_ACTIVE_TDAR 0x01000000 ++#define EMAC_R_DES_ACTIVE_RDAR 0x01000000 ++ ++#define EMAC_RX_SECTION_EMPTY_V 0x00010006 ++/* ++ * The possible operating speeds of the MAC, currently supporting 10, 100 and ++ * 1000Mb modes. ++ */ ++enum mac_speed {SPEED_10M, SPEED_100M, SPEED_1000M, SPEED_1000M_PCS}; ++ ++/* MII-related definitios */ ++#define EMAC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */ ++#define EMAC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */ ++#define EMAC_MII_DATA_OP_CL45_RD 0x30000000 /* Perform a read operation */ ++#define EMAC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */ ++#define EMAC_MII_DATA_OP_CL45_WR 0x10000000 /* Perform a write operation */ ++#define EMAC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */ ++#define EMAC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */ ++#define EMAC_MII_DATA_TA 0x00020000 /* Turnaround */ ++#define EMAC_MII_DATA_DATAMSK 0x0000ffff /* PHY data field */ ++ ++#define EMAC_MII_DATA_RA_SHIFT 18 /* MII Register address bits */ ++#define EMAC_MII_DATA_RA_MASK 0x1F /* MII Register address mask */ ++#define EMAC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */ ++#define EMAC_MII_DATA_PA_MASK 0x1F /* MII PHY address mask */ ++ ++#define EMAC_MII_DATA_RA(v) (((v) & EMAC_MII_DATA_RA_MASK) << \ ++ EMAC_MII_DATA_RA_SHIFT) ++#define EMAC_MII_DATA_PA(v) (((v) & EMAC_MII_DATA_RA_MASK) << \ ++ EMAC_MII_DATA_PA_SHIFT) ++#define EMAC_MII_DATA(v) ((v) & 0xffff) ++ ++#define EMAC_MII_SPEED_SHIFT 1 ++#define EMAC_HOLDTIME_SHIFT 8 ++#define EMAC_HOLDTIME_MASK 0x7 ++#define EMAC_HOLDTIME(v) (((v) & EMAC_HOLDTIME_MASK) << \ ++ EMAC_HOLDTIME_SHIFT) ++ ++/* ++ * The Address organisation for the MAC device. All addresses are split into ++ * two 32-bit register fields. The first one (bottom) is the lower 32-bits of ++ * the address and the other field are the high order bits - this may be 16-bits ++ * in the case of MAC addresses, or 32-bits for the hash address. ++ * In terms of memory storage, the first item (bottom) is assumed to be at a ++ * lower address location than 'top'. i.e. top should be at address location of ++ * 'bottom' + 4 bytes. ++ */ ++struct pfe_mac_addr { ++ u32 bottom; /* Lower 32-bits of address. */ ++ u32 top; /* Upper 32-bits of address. */ ++}; ++ ++/* ++ * The following is the organisation of the address filters section of the MAC ++ * registers. The Cadence MAC contains four possible specific address match ++ * addresses, if an incoming frame corresponds to any one of these four ++ * addresses then the frame will be copied to memory. ++ * It is not necessary for all four of the address match registers to be ++ * programmed, this is application dependent. ++ */ ++struct spec_addr { ++ struct pfe_mac_addr one; /* Specific address register 1. */ ++ struct pfe_mac_addr two; /* Specific address register 2. */ ++ struct pfe_mac_addr three; /* Specific address register 3. */ ++ struct pfe_mac_addr four; /* Specific address register 4. */ ++}; ++ ++struct gemac_cfg { ++ u32 mode; ++ u32 speed; ++ u32 duplex; ++}; ++ ++/* EMAC Hash size */ ++#define EMAC_HASH_REG_BITS 64 ++ ++#define EMAC_SPEC_ADDR_MAX 4 ++ ++#endif /* _EMAC_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/gpi.h +@@ -0,0 +1,86 @@ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _GPI_H_ ++#define _GPI_H_ ++ ++#define GPI_VERSION 0x00 ++#define GPI_CTRL 0x04 ++#define GPI_RX_CONFIG 0x08 ++#define GPI_HDR_SIZE 0x0c ++#define GPI_BUF_SIZE 0x10 ++#define GPI_LMEM_ALLOC_ADDR 0x14 ++#define GPI_LMEM_FREE_ADDR 0x18 ++#define GPI_DDR_ALLOC_ADDR 0x1c ++#define GPI_DDR_FREE_ADDR 0x20 ++#define GPI_CLASS_ADDR 0x24 ++#define GPI_DRX_FIFO 0x28 ++#define GPI_TRX_FIFO 0x2c ++#define GPI_INQ_PKTPTR 0x30 ++#define GPI_DDR_DATA_OFFSET 0x34 ++#define GPI_LMEM_DATA_OFFSET 0x38 ++#define GPI_TMLF_TX 0x4c ++#define GPI_DTX_ASEQ 0x50 ++#define GPI_FIFO_STATUS 0x54 ++#define GPI_FIFO_DEBUG 0x58 ++#define GPI_TX_PAUSE_TIME 0x5c ++#define GPI_LMEM_SEC_BUF_DATA_OFFSET 0x60 ++#define GPI_DDR_SEC_BUF_DATA_OFFSET 0x64 ++#define GPI_TOE_CHKSUM_EN 0x68 ++#define GPI_OVERRUN_DROPCNT 0x6c ++#define GPI_CSR_MTIP_PAUSE_REG 0x74 ++#define GPI_CSR_MTIP_PAUSE_QUANTUM 0x78 ++#define GPI_CSR_RX_CNT 0x7c ++#define GPI_CSR_TX_CNT 0x80 ++#define GPI_CSR_DEBUG1 0x84 ++#define GPI_CSR_DEBUG2 0x88 ++ ++struct gpi_cfg { ++ u32 lmem_rtry_cnt; ++ u32 tmlf_txthres; ++ u32 aseq_len; ++ u32 mtip_pause_reg; ++}; ++ ++/* GPI commons defines */ ++#define GPI_LMEM_BUF_EN 0x1 ++#define GPI_DDR_BUF_EN 0x1 ++ ++/* EGPI 1 defines */ ++#define EGPI1_LMEM_RTRY_CNT 0x40 ++#define EGPI1_TMLF_TXTHRES 0xBC ++#define EGPI1_ASEQ_LEN 0x50 ++ ++/* EGPI 2 defines */ ++#define EGPI2_LMEM_RTRY_CNT 0x40 ++#define EGPI2_TMLF_TXTHRES 0xBC ++#define EGPI2_ASEQ_LEN 0x40 ++ ++/* EGPI 3 defines */ ++#define EGPI3_LMEM_RTRY_CNT 0x40 ++#define EGPI3_TMLF_TXTHRES 0xBC ++#define EGPI3_ASEQ_LEN 0x40 ++ ++/* HGPI defines */ ++#define HGPI_LMEM_RTRY_CNT 0x40 ++#define HGPI_TMLF_TXTHRES 0xBC ++#define HGPI_ASEQ_LEN 0x40 ++ ++#define EGPI_PAUSE_TIME 0x000007D0 ++#define EGPI_PAUSE_ENABLE 0x40000000 ++#endif /* _GPI_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/hif.h +@@ -0,0 +1,100 @@ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _HIF_H_ ++#define _HIF_H_ ++ ++/* @file hif.h. ++ * hif - PFE hif block control and status register. ++ * Mapped on CBUS and accessible from all PE's and ARM. ++ */ ++#define HIF_VERSION (HIF_BASE_ADDR + 0x00) ++#define HIF_TX_CTRL (HIF_BASE_ADDR + 0x04) ++#define HIF_TX_CURR_BD_ADDR (HIF_BASE_ADDR + 0x08) ++#define HIF_TX_ALLOC (HIF_BASE_ADDR + 0x0c) ++#define HIF_TX_BDP_ADDR (HIF_BASE_ADDR + 0x10) ++#define HIF_TX_STATUS (HIF_BASE_ADDR + 0x14) ++#define HIF_RX_CTRL (HIF_BASE_ADDR + 0x20) ++#define HIF_RX_BDP_ADDR (HIF_BASE_ADDR + 0x24) ++#define HIF_RX_STATUS (HIF_BASE_ADDR + 0x30) ++#define HIF_INT_SRC (HIF_BASE_ADDR + 0x34) ++#define HIF_INT_ENABLE (HIF_BASE_ADDR + 0x38) ++#define HIF_POLL_CTRL (HIF_BASE_ADDR + 0x3c) ++#define HIF_RX_CURR_BD_ADDR (HIF_BASE_ADDR + 0x40) ++#define HIF_RX_ALLOC (HIF_BASE_ADDR + 0x44) ++#define HIF_TX_DMA_STATUS (HIF_BASE_ADDR + 0x48) ++#define HIF_RX_DMA_STATUS (HIF_BASE_ADDR + 0x4c) ++#define HIF_INT_COAL (HIF_BASE_ADDR + 0x50) ++ ++/* HIF_INT_SRC/ HIF_INT_ENABLE control bits */ ++#define HIF_INT BIT(0) ++#define HIF_RXBD_INT BIT(1) ++#define HIF_RXPKT_INT BIT(2) ++#define HIF_TXBD_INT BIT(3) ++#define HIF_TXPKT_INT BIT(4) ++ ++/* HIF_TX_CTRL bits */ ++#define HIF_CTRL_DMA_EN BIT(0) ++#define HIF_CTRL_BDP_POLL_CTRL_EN BIT(1) ++#define HIF_CTRL_BDP_CH_START_WSTB BIT(2) ++ ++/* HIF_RX_STATUS bits */ ++#define BDP_CSR_RX_DMA_ACTV BIT(16) ++ ++/* HIF_INT_ENABLE bits */ ++#define HIF_INT_EN BIT(0) ++#define HIF_RXBD_INT_EN BIT(1) ++#define HIF_RXPKT_INT_EN BIT(2) ++#define HIF_TXBD_INT_EN BIT(3) ++#define HIF_TXPKT_INT_EN BIT(4) ++ ++/* HIF_POLL_CTRL bits*/ ++#define HIF_RX_POLL_CTRL_CYCLE 0x0400 ++#define HIF_TX_POLL_CTRL_CYCLE 0x0400 ++ ++/* HIF_INT_COAL bits*/ ++#define HIF_INT_COAL_ENABLE BIT(31) ++ ++/* Buffer descriptor control bits */ ++#define BD_CTRL_BUFLEN_MASK 0x3fff ++#define BD_BUF_LEN(x) ((x) & BD_CTRL_BUFLEN_MASK) ++#define BD_CTRL_CBD_INT_EN BIT(16) ++#define BD_CTRL_PKT_INT_EN BIT(17) ++#define BD_CTRL_LIFM BIT(18) ++#define BD_CTRL_LAST_BD BIT(19) ++#define BD_CTRL_DIR BIT(20) ++#define BD_CTRL_LMEM_CPY BIT(21) /* Valid only for HIF_NOCPY */ ++#define BD_CTRL_PKT_XFER BIT(24) ++#define BD_CTRL_DESC_EN BIT(31) ++#define BD_CTRL_PARSE_DISABLE BIT(25) ++#define BD_CTRL_BRFETCH_DISABLE BIT(26) ++#define BD_CTRL_RTFETCH_DISABLE BIT(27) ++ ++/* Buffer descriptor status bits*/ ++#define BD_STATUS_CONN_ID(x) ((x) & 0xffff) ++#define BD_STATUS_DIR_PROC_ID BIT(16) ++#define BD_STATUS_CONN_ID_EN BIT(17) ++#define BD_STATUS_PE2PROC_ID(x) (((x) & 7) << 18) ++#define BD_STATUS_LE_DATA BIT(21) ++#define BD_STATUS_CHKSUM_EN BIT(22) ++ ++/* HIF Buffer descriptor status bits */ ++#define DIR_PROC_ID BIT(16) ++#define PROC_ID(id) ((id) << 18) ++ ++#endif /* _HIF_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/hif_nocpy.h +@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _HIF_NOCPY_H_ ++#define _HIF_NOCPY_H_ ++ ++#define HIF_NOCPY_VERSION (HIF_NOCPY_BASE_ADDR + 0x00) ++#define HIF_NOCPY_TX_CTRL (HIF_NOCPY_BASE_ADDR + 0x04) ++#define HIF_NOCPY_TX_CURR_BD_ADDR (HIF_NOCPY_BASE_ADDR + 0x08) ++#define HIF_NOCPY_TX_ALLOC (HIF_NOCPY_BASE_ADDR + 0x0c) ++#define HIF_NOCPY_TX_BDP_ADDR (HIF_NOCPY_BASE_ADDR + 0x10) ++#define HIF_NOCPY_TX_STATUS (HIF_NOCPY_BASE_ADDR + 0x14) ++#define HIF_NOCPY_RX_CTRL (HIF_NOCPY_BASE_ADDR + 0x20) ++#define HIF_NOCPY_RX_BDP_ADDR (HIF_NOCPY_BASE_ADDR + 0x24) ++#define HIF_NOCPY_RX_STATUS (HIF_NOCPY_BASE_ADDR + 0x30) ++#define HIF_NOCPY_INT_SRC (HIF_NOCPY_BASE_ADDR + 0x34) ++#define HIF_NOCPY_INT_ENABLE (HIF_NOCPY_BASE_ADDR + 0x38) ++#define HIF_NOCPY_POLL_CTRL (HIF_NOCPY_BASE_ADDR + 0x3c) ++#define HIF_NOCPY_RX_CURR_BD_ADDR (HIF_NOCPY_BASE_ADDR + 0x40) ++#define HIF_NOCPY_RX_ALLOC (HIF_NOCPY_BASE_ADDR + 0x44) ++#define HIF_NOCPY_TX_DMA_STATUS (HIF_NOCPY_BASE_ADDR + 0x48) ++#define HIF_NOCPY_RX_DMA_STATUS (HIF_NOCPY_BASE_ADDR + 0x4c) ++#define HIF_NOCPY_RX_INQ0_PKTPTR (HIF_NOCPY_BASE_ADDR + 0x50) ++#define HIF_NOCPY_RX_INQ1_PKTPTR (HIF_NOCPY_BASE_ADDR + 0x54) ++#define HIF_NOCPY_TX_PORT_NO (HIF_NOCPY_BASE_ADDR + 0x60) ++#define HIF_NOCPY_LMEM_ALLOC_ADDR (HIF_NOCPY_BASE_ADDR + 0x64) ++#define HIF_NOCPY_CLASS_ADDR (HIF_NOCPY_BASE_ADDR + 0x68) ++#define HIF_NOCPY_TMU_PORT0_ADDR (HIF_NOCPY_BASE_ADDR + 0x70) ++#define HIF_NOCPY_TMU_PORT1_ADDR (HIF_NOCPY_BASE_ADDR + 0x74) ++#define HIF_NOCPY_TMU_PORT2_ADDR (HIF_NOCPY_BASE_ADDR + 0x7c) ++#define HIF_NOCPY_TMU_PORT3_ADDR (HIF_NOCPY_BASE_ADDR + 0x80) ++#define HIF_NOCPY_TMU_PORT4_ADDR (HIF_NOCPY_BASE_ADDR + 0x84) ++#define HIF_NOCPY_INT_COAL (HIF_NOCPY_BASE_ADDR + 0x90) ++ ++#endif /* _HIF_NOCPY_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/tmu_csr.h +@@ -0,0 +1,168 @@ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _TMU_CSR_H_ ++#define _TMU_CSR_H_ ++ ++#define TMU_VERSION (TMU_CSR_BASE_ADDR + 0x000) ++#define TMU_INQ_WATERMARK (TMU_CSR_BASE_ADDR + 0x004) ++#define TMU_PHY_INQ_PKTPTR (TMU_CSR_BASE_ADDR + 0x008) ++#define TMU_PHY_INQ_PKTINFO (TMU_CSR_BASE_ADDR + 0x00c) ++#define TMU_PHY_INQ_FIFO_CNT (TMU_CSR_BASE_ADDR + 0x010) ++#define TMU_SYS_GENERIC_CONTROL (TMU_CSR_BASE_ADDR + 0x014) ++#define TMU_SYS_GENERIC_STATUS (TMU_CSR_BASE_ADDR + 0x018) ++#define TMU_SYS_GEN_CON0 (TMU_CSR_BASE_ADDR + 0x01c) ++#define TMU_SYS_GEN_CON1 (TMU_CSR_BASE_ADDR + 0x020) ++#define TMU_SYS_GEN_CON2 (TMU_CSR_BASE_ADDR + 0x024) ++#define TMU_SYS_GEN_CON3 (TMU_CSR_BASE_ADDR + 0x028) ++#define TMU_SYS_GEN_CON4 (TMU_CSR_BASE_ADDR + 0x02c) ++#define TMU_TEQ_DISABLE_DROPCHK (TMU_CSR_BASE_ADDR + 0x030) ++#define TMU_TEQ_CTRL (TMU_CSR_BASE_ADDR + 0x034) ++#define TMU_TEQ_QCFG (TMU_CSR_BASE_ADDR + 0x038) ++#define TMU_TEQ_DROP_STAT (TMU_CSR_BASE_ADDR + 0x03c) ++#define TMU_TEQ_QAVG (TMU_CSR_BASE_ADDR + 0x040) ++#define TMU_TEQ_WREG_PROB (TMU_CSR_BASE_ADDR + 0x044) ++#define TMU_TEQ_TRANS_STAT (TMU_CSR_BASE_ADDR + 0x048) ++#define TMU_TEQ_HW_PROB_CFG0 (TMU_CSR_BASE_ADDR + 0x04c) ++#define TMU_TEQ_HW_PROB_CFG1 (TMU_CSR_BASE_ADDR + 0x050) ++#define TMU_TEQ_HW_PROB_CFG2 (TMU_CSR_BASE_ADDR + 0x054) ++#define TMU_TEQ_HW_PROB_CFG3 (TMU_CSR_BASE_ADDR + 0x058) ++#define TMU_TEQ_HW_PROB_CFG4 (TMU_CSR_BASE_ADDR + 0x05c) ++#define TMU_TEQ_HW_PROB_CFG5 (TMU_CSR_BASE_ADDR + 0x060) ++#define TMU_TEQ_HW_PROB_CFG6 (TMU_CSR_BASE_ADDR + 0x064) ++#define TMU_TEQ_HW_PROB_CFG7 (TMU_CSR_BASE_ADDR + 0x068) ++#define TMU_TEQ_HW_PROB_CFG8 (TMU_CSR_BASE_ADDR + 0x06c) ++#define TMU_TEQ_HW_PROB_CFG9 (TMU_CSR_BASE_ADDR + 0x070) ++#define TMU_TEQ_HW_PROB_CFG10 (TMU_CSR_BASE_ADDR + 0x074) ++#define TMU_TEQ_HW_PROB_CFG11 (TMU_CSR_BASE_ADDR + 0x078) ++#define TMU_TEQ_HW_PROB_CFG12 (TMU_CSR_BASE_ADDR + 0x07c) ++#define TMU_TEQ_HW_PROB_CFG13 (TMU_CSR_BASE_ADDR + 0x080) ++#define TMU_TEQ_HW_PROB_CFG14 (TMU_CSR_BASE_ADDR + 0x084) ++#define TMU_TEQ_HW_PROB_CFG15 (TMU_CSR_BASE_ADDR + 0x088) ++#define TMU_TEQ_HW_PROB_CFG16 (TMU_CSR_BASE_ADDR + 0x08c) ++#define TMU_TEQ_HW_PROB_CFG17 (TMU_CSR_BASE_ADDR + 0x090) ++#define TMU_TEQ_HW_PROB_CFG18 (TMU_CSR_BASE_ADDR + 0x094) ++#define TMU_TEQ_HW_PROB_CFG19 (TMU_CSR_BASE_ADDR + 0x098) ++#define TMU_TEQ_HW_PROB_CFG20 (TMU_CSR_BASE_ADDR + 0x09c) ++#define TMU_TEQ_HW_PROB_CFG21 (TMU_CSR_BASE_ADDR + 0x0a0) ++#define TMU_TEQ_HW_PROB_CFG22 (TMU_CSR_BASE_ADDR + 0x0a4) ++#define TMU_TEQ_HW_PROB_CFG23 (TMU_CSR_BASE_ADDR + 0x0a8) ++#define TMU_TEQ_HW_PROB_CFG24 (TMU_CSR_BASE_ADDR + 0x0ac) ++#define TMU_TEQ_HW_PROB_CFG25 (TMU_CSR_BASE_ADDR + 0x0b0) ++#define TMU_TDQ_IIFG_CFG (TMU_CSR_BASE_ADDR + 0x0b4) ++/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. ++ * This is a global Enable for all schedulers in PHY0 ++ */ ++#define TMU_TDQ0_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x0b8) ++ ++#define TMU_LLM_CTRL (TMU_CSR_BASE_ADDR + 0x0bc) ++#define TMU_LLM_BASE_ADDR (TMU_CSR_BASE_ADDR + 0x0c0) ++#define TMU_LLM_QUE_LEN (TMU_CSR_BASE_ADDR + 0x0c4) ++#define TMU_LLM_QUE_HEADPTR (TMU_CSR_BASE_ADDR + 0x0c8) ++#define TMU_LLM_QUE_TAILPTR (TMU_CSR_BASE_ADDR + 0x0cc) ++#define TMU_LLM_QUE_DROPCNT (TMU_CSR_BASE_ADDR + 0x0d0) ++#define TMU_INT_EN (TMU_CSR_BASE_ADDR + 0x0d4) ++#define TMU_INT_SRC (TMU_CSR_BASE_ADDR + 0x0d8) ++#define TMU_INQ_STAT (TMU_CSR_BASE_ADDR + 0x0dc) ++#define TMU_CTRL (TMU_CSR_BASE_ADDR + 0x0e0) ++ ++/* [31] Mem Access Command. 0 = Internal Memory Read, 1 = Internal memory ++ * Write [27:24] Byte Enables of the Internal memory access [23:0] Address of ++ * the internal memory. This address is used to access both the PM and DM of ++ * all the PE's ++ */ ++#define TMU_MEM_ACCESS_ADDR (TMU_CSR_BASE_ADDR + 0x0e4) ++ ++/* Internal Memory Access Write Data */ ++#define TMU_MEM_ACCESS_WDATA (TMU_CSR_BASE_ADDR + 0x0e8) ++/* Internal Memory Access Read Data. The commands are blocked ++ * at the mem_access only ++ */ ++#define TMU_MEM_ACCESS_RDATA (TMU_CSR_BASE_ADDR + 0x0ec) ++ ++/* [31:0] PHY0 in queue address (must be initialized with one of the ++ * xxx_INQ_PKTPTR cbus addresses) ++ */ ++#define TMU_PHY0_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f0) ++/* [31:0] PHY1 in queue address (must be initialized with one of the ++ * xxx_INQ_PKTPTR cbus addresses) ++ */ ++#define TMU_PHY1_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f4) ++/* [31:0] PHY2 in queue address (must be initialized with one of the ++ * xxx_INQ_PKTPTR cbus addresses) ++ */ ++#define TMU_PHY2_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f8) ++/* [31:0] PHY3 in queue address (must be initialized with one of the ++ * xxx_INQ_PKTPTR cbus addresses) ++ */ ++#define TMU_PHY3_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0fc) ++#define TMU_BMU_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x100) ++#define TMU_TX_CTRL (TMU_CSR_BASE_ADDR + 0x104) ++ ++#define TMU_BUS_ACCESS_WDATA (TMU_CSR_BASE_ADDR + 0x108) ++#define TMU_BUS_ACCESS (TMU_CSR_BASE_ADDR + 0x10c) ++#define TMU_BUS_ACCESS_RDATA (TMU_CSR_BASE_ADDR + 0x110) ++ ++#define TMU_PE_SYS_CLK_RATIO (TMU_CSR_BASE_ADDR + 0x114) ++#define TMU_PE_STATUS (TMU_CSR_BASE_ADDR + 0x118) ++#define TMU_TEQ_MAX_THRESHOLD (TMU_CSR_BASE_ADDR + 0x11c) ++/* [31:0] PHY4 in queue address (must be initialized with one of the ++ * xxx_INQ_PKTPTR cbus addresses) ++ */ ++#define TMU_PHY4_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x134) ++/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. ++ * This is a global Enable for all schedulers in PHY1 ++ */ ++#define TMU_TDQ1_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x138) ++/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. ++ * This is a global Enable for all schedulers in PHY2 ++ */ ++#define TMU_TDQ2_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x13c) ++/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. ++ * This is a global Enable for all schedulers in PHY3 ++ */ ++#define TMU_TDQ3_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x140) ++#define TMU_BMU_BUF_SIZE (TMU_CSR_BASE_ADDR + 0x144) ++/* [31:0] PHY5 in queue address (must be initialized with one of the ++ * xxx_INQ_PKTPTR cbus addresses) ++ */ ++#define TMU_PHY5_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x148) ++ ++#define SW_RESET BIT(0) /* Global software reset */ ++#define INQ_RESET BIT(2) ++#define TEQ_RESET BIT(3) ++#define TDQ_RESET BIT(4) ++#define PE_RESET BIT(5) ++#define MEM_INIT BIT(6) ++#define MEM_INIT_DONE BIT(7) ++#define LLM_INIT BIT(8) ++#define LLM_INIT_DONE BIT(9) ++#define ECC_MEM_INIT_DONE BIT(10) ++ ++struct tmu_cfg { ++ u32 pe_sys_clk_ratio; ++ unsigned long llm_base_addr; ++ u32 llm_queue_len; ++}; ++ ++/* Not HW related for pfe_ctrl / pfe common defines */ ++#define DEFAULT_MAX_QDEPTH 80 ++#define DEFAULT_Q0_QDEPTH 511 /*We keep one large queue for host tx qos */ ++#define DEFAULT_TMU3_QDEPTH 127 ++ ++#endif /* _TMU_CSR_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/util_csr.h +@@ -0,0 +1,61 @@ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _UTIL_CSR_H_ ++#define _UTIL_CSR_H_ ++ ++#define UTIL_VERSION (UTIL_CSR_BASE_ADDR + 0x000) ++#define UTIL_TX_CTRL (UTIL_CSR_BASE_ADDR + 0x004) ++#define UTIL_INQ_PKTPTR (UTIL_CSR_BASE_ADDR + 0x010) ++ ++#define UTIL_HDR_SIZE (UTIL_CSR_BASE_ADDR + 0x014) ++ ++#define UTIL_PE0_QB_DM_ADDR0 (UTIL_CSR_BASE_ADDR + 0x020) ++#define UTIL_PE0_QB_DM_ADDR1 (UTIL_CSR_BASE_ADDR + 0x024) ++#define UTIL_PE0_RO_DM_ADDR0 (UTIL_CSR_BASE_ADDR + 0x060) ++#define UTIL_PE0_RO_DM_ADDR1 (UTIL_CSR_BASE_ADDR + 0x064) ++ ++#define UTIL_MEM_ACCESS_ADDR (UTIL_CSR_BASE_ADDR + 0x100) ++#define UTIL_MEM_ACCESS_WDATA (UTIL_CSR_BASE_ADDR + 0x104) ++#define UTIL_MEM_ACCESS_RDATA (UTIL_CSR_BASE_ADDR + 0x108) ++ ++#define UTIL_TM_INQ_ADDR (UTIL_CSR_BASE_ADDR + 0x114) ++#define UTIL_PE_STATUS (UTIL_CSR_BASE_ADDR + 0x118) ++ ++#define UTIL_PE_SYS_CLK_RATIO (UTIL_CSR_BASE_ADDR + 0x200) ++#define UTIL_AFULL_THRES (UTIL_CSR_BASE_ADDR + 0x204) ++#define UTIL_GAP_BETWEEN_READS (UTIL_CSR_BASE_ADDR + 0x208) ++#define UTIL_MAX_BUF_CNT (UTIL_CSR_BASE_ADDR + 0x20c) ++#define UTIL_TSQ_FIFO_THRES (UTIL_CSR_BASE_ADDR + 0x210) ++#define UTIL_TSQ_MAX_CNT (UTIL_CSR_BASE_ADDR + 0x214) ++#define UTIL_IRAM_DATA_0 (UTIL_CSR_BASE_ADDR + 0x218) ++#define UTIL_IRAM_DATA_1 (UTIL_CSR_BASE_ADDR + 0x21c) ++#define UTIL_IRAM_DATA_2 (UTIL_CSR_BASE_ADDR + 0x220) ++#define UTIL_IRAM_DATA_3 (UTIL_CSR_BASE_ADDR + 0x224) ++ ++#define UTIL_BUS_ACCESS_ADDR (UTIL_CSR_BASE_ADDR + 0x228) ++#define UTIL_BUS_ACCESS_WDATA (UTIL_CSR_BASE_ADDR + 0x22c) ++#define UTIL_BUS_ACCESS_RDATA (UTIL_CSR_BASE_ADDR + 0x230) ++ ++#define UTIL_INQ_AFULL_THRES (UTIL_CSR_BASE_ADDR + 0x234) ++ ++struct util_cfg { ++ u32 pe_sys_clk_ratio; ++}; ++ ++#endif /* _UTIL_CSR_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/include/pfe/pfe.h +@@ -0,0 +1,372 @@ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _PFE_H_ ++#define _PFE_H_ ++ ++#include "cbus.h" ++ ++#define CLASS_DMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20)) ++/* ++ * Only valid for mem access register interface ++ */ ++#define CLASS_IMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20)) ++#define CLASS_DMEM_SIZE 0x00002000 ++#define CLASS_IMEM_SIZE 0x00008000 ++ ++#define TMU_DMEM_BASE_ADDR(i) (0x00000000 + ((i) << 20)) ++/* ++ * Only valid for mem access register interface ++ */ ++#define TMU_IMEM_BASE_ADDR(i) (0x00000000 + ((i) << 20)) ++#define TMU_DMEM_SIZE 0x00000800 ++#define TMU_IMEM_SIZE 0x00002000 ++ ++#define UTIL_DMEM_BASE_ADDR 0x00000000 ++#define UTIL_DMEM_SIZE 0x00002000 ++ ++#define PE_LMEM_BASE_ADDR 0xc3010000 ++#define PE_LMEM_SIZE 0x8000 ++#define PE_LMEM_END (PE_LMEM_BASE_ADDR + PE_LMEM_SIZE) ++ ++#define DMEM_BASE_ADDR 0x00000000 ++#define DMEM_SIZE 0x2000 /* TMU has less... */ ++#define DMEM_END (DMEM_BASE_ADDR + DMEM_SIZE) ++ ++#define PMEM_BASE_ADDR 0x00010000 ++#define PMEM_SIZE 0x8000 /* TMU has less... */ ++#define PMEM_END (PMEM_BASE_ADDR + PMEM_SIZE) ++ ++/* These check memory ranges from PE point of view/memory map */ ++#define IS_DMEM(addr, len) \ ++ ({ typeof(addr) addr_ = (addr); \ ++ ((unsigned long)(addr_) >= DMEM_BASE_ADDR) && \ ++ (((unsigned long)(addr_) + (len)) <= DMEM_END); }) ++ ++#define IS_PMEM(addr, len) \ ++ ({ typeof(addr) addr_ = (addr); \ ++ ((unsigned long)(addr_) >= PMEM_BASE_ADDR) && \ ++ (((unsigned long)(addr_) + (len)) <= PMEM_END); }) ++ ++#define IS_PE_LMEM(addr, len) \ ++ ({ typeof(addr) addr_ = (addr); \ ++ ((unsigned long)(addr_) >= \ ++ PE_LMEM_BASE_ADDR) && \ ++ (((unsigned long)(addr_) + \ ++ (len)) <= PE_LMEM_END); }) ++ ++#define IS_PFE_LMEM(addr, len) \ ++ ({ typeof(addr) addr_ = (addr); \ ++ ((unsigned long)(addr_) >= \ ++ CBUS_VIRT_TO_PFE(LMEM_BASE_ADDR)) && \ ++ (((unsigned long)(addr_) + (len)) <= \ ++ CBUS_VIRT_TO_PFE(LMEM_END)); }) ++ ++#define __IS_PHYS_DDR(addr, len) \ ++ ({ typeof(addr) addr_ = (addr); \ ++ ((unsigned long)(addr_) >= \ ++ DDR_PHYS_BASE_ADDR) && \ ++ (((unsigned long)(addr_) + (len)) <= \ ++ DDR_PHYS_END); }) ++ ++#define IS_PHYS_DDR(addr, len) __IS_PHYS_DDR(DDR_PFE_TO_PHYS(addr), len) ++ ++/* ++ * If using a run-time virtual address for the cbus base address use this code ++ */ ++extern void *cbus_base_addr; ++extern void *ddr_base_addr; ++extern unsigned long ddr_phys_base_addr; ++extern unsigned int ddr_size; ++ ++#define CBUS_BASE_ADDR cbus_base_addr ++#define DDR_PHYS_BASE_ADDR ddr_phys_base_addr ++#define DDR_BASE_ADDR ddr_base_addr ++#define DDR_SIZE ddr_size ++ ++#define DDR_PHYS_END (DDR_PHYS_BASE_ADDR + DDR_SIZE) ++ ++#define LS1012A_PFE_RESET_WA /* ++ * PFE doesn't have global reset and re-init ++ * should takecare few things to make PFE ++ * functional after reset ++ */ ++#define PFE_CBUS_PHYS_BASE_ADDR 0xc0000000 /* CBUS physical base address ++ * as seen by PE's. ++ */ ++/* CBUS physical base address as seen by PE's. */ ++#define PFE_CBUS_PHYS_BASE_ADDR_FROM_PFE 0xc0000000 ++ ++#define DDR_PHYS_TO_PFE(p) (((unsigned long int)(p)) & 0x7FFFFFFF) ++#define DDR_PFE_TO_PHYS(p) (((unsigned long int)(p)) | 0x80000000) ++#define CBUS_PHYS_TO_PFE(p) (((p) - PFE_CBUS_PHYS_BASE_ADDR) + \ ++ PFE_CBUS_PHYS_BASE_ADDR_FROM_PFE) ++/* Translates to PFE address map */ ++ ++#define DDR_PHYS_TO_VIRT(p) (((p) - DDR_PHYS_BASE_ADDR) + DDR_BASE_ADDR) ++#define DDR_VIRT_TO_PHYS(v) (((v) - DDR_BASE_ADDR) + DDR_PHYS_BASE_ADDR) ++#define DDR_VIRT_TO_PFE(p) (DDR_PHYS_TO_PFE(DDR_VIRT_TO_PHYS(p))) ++ ++#define CBUS_VIRT_TO_PFE(v) (((v) - CBUS_BASE_ADDR) + \ ++ PFE_CBUS_PHYS_BASE_ADDR) ++#define CBUS_PFE_TO_VIRT(p) (((unsigned long int)(p) - \ ++ PFE_CBUS_PHYS_BASE_ADDR) + CBUS_BASE_ADDR) ++ ++/* The below part of the code is used in QOS control driver from host */ ++#define TMU_APB_BASE_ADDR 0xc1000000 /* TMU base address seen by ++ * pe's ++ */ ++ ++enum { ++ CLASS0_ID = 0, ++ CLASS1_ID, ++ CLASS2_ID, ++ CLASS3_ID, ++ CLASS4_ID, ++ CLASS5_ID, ++ TMU0_ID, ++ TMU1_ID, ++ TMU2_ID, ++ TMU3_ID, ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ UTIL_ID, ++#endif ++ MAX_PE ++}; ++ ++#define CLASS_MASK (BIT(CLASS0_ID) | BIT(CLASS1_ID) |\ ++ BIT(CLASS2_ID) | BIT(CLASS3_ID) |\ ++ BIT(CLASS4_ID) | BIT(CLASS5_ID)) ++#define CLASS_MAX_ID CLASS5_ID ++ ++#define TMU_MASK (BIT(TMU0_ID) | BIT(TMU1_ID) |\ ++ BIT(TMU3_ID)) ++ ++#define TMU_MAX_ID TMU3_ID ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++#define UTIL_MASK BIT(UTIL_ID) ++#endif ++ ++struct pe_status { ++ u32 cpu_state; ++ u32 activity_counter; ++ u32 rx; ++ union { ++ u32 tx; ++ u32 tmu_qstatus; ++ }; ++ u32 drop; ++#if defined(CFG_PE_DEBUG) ++ u32 debug_indicator; ++ u32 debug[16]; ++#endif ++} __aligned(16); ++ ++struct pe_sync_mailbox { ++ u32 stop; ++ u32 stopped; ++}; ++ ++/* Drop counter definitions */ ++ ++#define CLASS_NUM_DROP_COUNTERS 13 ++#define UTIL_NUM_DROP_COUNTERS 8 ++ ++/* PE information. ++ * Structure containing PE's specific information. It is used to create ++ * generic C functions common to all PE's. ++ * Before using the library functions this structure needs to be initialized ++ * with the different registers virtual addresses ++ * (according to the ARM MMU mmaping). The default initialization supports a ++ * virtual == physical mapping. ++ */ ++struct pe_info { ++ u32 dmem_base_addr; /* PE's dmem base address */ ++ u32 pmem_base_addr; /* PE's pmem base address */ ++ u32 pmem_size; /* PE's pmem size */ ++ ++ void *mem_access_wdata; /* PE's _MEM_ACCESS_WDATA register ++ * address ++ */ ++ void *mem_access_addr; /* PE's _MEM_ACCESS_ADDR register ++ * address ++ */ ++ void *mem_access_rdata; /* PE's _MEM_ACCESS_RDATA register ++ * address ++ */ ++}; ++ ++void pe_lmem_read(u32 *dst, u32 len, u32 offset); ++void pe_lmem_write(u32 *src, u32 len, u32 offset); ++ ++void pe_dmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len); ++void pe_pmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len); ++ ++u32 pe_pmem_read(int id, u32 addr, u8 size); ++ ++void pe_dmem_write(int id, u32 val, u32 addr, u8 size); ++u32 pe_dmem_read(int id, u32 addr, u8 size); ++void class_pe_lmem_memcpy_to32(u32 dst, const void *src, unsigned int len); ++void class_pe_lmem_memset(u32 dst, int val, unsigned int len); ++void class_bus_write(u32 val, u32 addr, u8 size); ++u32 class_bus_read(u32 addr, u8 size); ++ ++#define class_bus_readl(addr) class_bus_read(addr, 4) ++#define class_bus_readw(addr) class_bus_read(addr, 2) ++#define class_bus_readb(addr) class_bus_read(addr, 1) ++ ++#define class_bus_writel(val, addr) class_bus_write(val, addr, 4) ++#define class_bus_writew(val, addr) class_bus_write(val, addr, 2) ++#define class_bus_writeb(val, addr) class_bus_write(val, addr, 1) ++ ++#define pe_dmem_readl(id, addr) pe_dmem_read(id, addr, 4) ++#define pe_dmem_readw(id, addr) pe_dmem_read(id, addr, 2) ++#define pe_dmem_readb(id, addr) pe_dmem_read(id, addr, 1) ++ ++#define pe_dmem_writel(id, val, addr) pe_dmem_write(id, val, addr, 4) ++#define pe_dmem_writew(id, val, addr) pe_dmem_write(id, val, addr, 2) ++#define pe_dmem_writeb(id, val, addr) pe_dmem_write(id, val, addr, 1) ++ ++/*int pe_load_elf_section(int id, const void *data, elf32_shdr *shdr); */ ++int pe_load_elf_section(int id, const void *data, struct elf32_shdr *shdr, ++ struct device *dev); ++ ++void pfe_lib_init(void *cbus_base, void *ddr_base, unsigned long ddr_phys_base, ++ unsigned int ddr_size); ++void bmu_init(void *base, struct BMU_CFG *cfg); ++void bmu_reset(void *base); ++void bmu_enable(void *base); ++void bmu_disable(void *base); ++void bmu_set_config(void *base, struct BMU_CFG *cfg); ++ ++/* ++ * An enumerated type for loopback values. This can be one of three values, no ++ * loopback -normal operation, local loopback with internal loopback module of ++ * MAC or PHY loopback which is through the external PHY. ++ */ ++#ifndef __MAC_LOOP_ENUM__ ++#define __MAC_LOOP_ENUM__ ++enum mac_loop {LB_NONE, LB_EXT, LB_LOCAL}; ++#endif ++ ++void gemac_init(void *base, void *config); ++void gemac_disable_rx_checksum_offload(void *base); ++void gemac_enable_rx_checksum_offload(void *base); ++void gemac_set_speed(void *base, enum mac_speed gem_speed); ++void gemac_set_duplex(void *base, int duplex); ++void gemac_set_mode(void *base, int mode); ++void gemac_enable(void *base); ++void gemac_tx_disable(void *base); ++void gemac_tx_enable(void *base); ++void gemac_disable(void *base); ++void gemac_reset(void *base); ++void gemac_set_address(void *base, struct spec_addr *addr); ++struct spec_addr gemac_get_address(void *base); ++void gemac_set_loop(void *base, enum mac_loop gem_loop); ++void gemac_set_laddr1(void *base, struct pfe_mac_addr *address); ++void gemac_set_laddr2(void *base, struct pfe_mac_addr *address); ++void gemac_set_laddr3(void *base, struct pfe_mac_addr *address); ++void gemac_set_laddr4(void *base, struct pfe_mac_addr *address); ++void gemac_set_laddrN(void *base, struct pfe_mac_addr *address, ++ unsigned int entry_index); ++void gemac_clear_laddr1(void *base); ++void gemac_clear_laddr2(void *base); ++void gemac_clear_laddr3(void *base); ++void gemac_clear_laddr4(void *base); ++void gemac_clear_laddrN(void *base, unsigned int entry_index); ++struct pfe_mac_addr gemac_get_hash(void *base); ++void gemac_set_hash(void *base, struct pfe_mac_addr *hash); ++struct pfe_mac_addr gem_get_laddr1(void *base); ++struct pfe_mac_addr gem_get_laddr2(void *base); ++struct pfe_mac_addr gem_get_laddr3(void *base); ++struct pfe_mac_addr gem_get_laddr4(void *base); ++struct pfe_mac_addr gem_get_laddrN(void *base, unsigned int entry_index); ++void gemac_set_config(void *base, struct gemac_cfg *cfg); ++void gemac_allow_broadcast(void *base); ++void gemac_no_broadcast(void *base); ++void gemac_enable_1536_rx(void *base); ++void gemac_disable_1536_rx(void *base); ++void gemac_set_rx_max_fl(void *base, int mtu); ++void gemac_enable_rx_jmb(void *base); ++void gemac_disable_rx_jmb(void *base); ++void gemac_enable_stacked_vlan(void *base); ++void gemac_disable_stacked_vlan(void *base); ++void gemac_enable_pause_rx(void *base); ++void gemac_disable_pause_rx(void *base); ++void gemac_enable_copy_all(void *base); ++void gemac_disable_copy_all(void *base); ++void gemac_set_bus_width(void *base, int width); ++void gemac_set_wol(void *base, u32 wol_conf); ++ ++void gpi_init(void *base, struct gpi_cfg *cfg); ++void gpi_reset(void *base); ++void gpi_enable(void *base); ++void gpi_disable(void *base); ++void gpi_set_config(void *base, struct gpi_cfg *cfg); ++ ++void class_init(struct class_cfg *cfg); ++void class_reset(void); ++void class_enable(void); ++void class_disable(void); ++void class_set_config(struct class_cfg *cfg); ++ ++void tmu_reset(void); ++void tmu_init(struct tmu_cfg *cfg); ++void tmu_enable(u32 pe_mask); ++void tmu_disable(u32 pe_mask); ++u32 tmu_qstatus(u32 if_id); ++u32 tmu_pkts_processed(u32 if_id); ++ ++void util_init(struct util_cfg *cfg); ++void util_reset(void); ++void util_enable(void); ++void util_disable(void); ++ ++void hif_init(void); ++void hif_tx_enable(void); ++void hif_tx_disable(void); ++void hif_rx_enable(void); ++void hif_rx_disable(void); ++ ++/* Get Chip Revision level ++ * ++ */ ++static inline unsigned int CHIP_REVISION(void) ++{ ++ /*For LS1012A return always 1 */ ++ return 1; ++} ++ ++/* Start HIF rx DMA ++ * ++ */ ++static inline void hif_rx_dma_start(void) ++{ ++ writel(HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB, HIF_RX_CTRL); ++} ++ ++/* Start HIF tx DMA ++ * ++ */ ++static inline void hif_tx_dma_start(void) ++{ ++ writel(HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB, HIF_TX_CTRL); ++} ++ ++#endif /* _PFE_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_cdev.c +@@ -0,0 +1,258 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2018 NXP ++ */ ++ ++/* @pfe_cdev.c. ++ * Dummy device representing the PFE US in userspace. ++ * - used for interacting with the kernel layer for link status ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "pfe_cdev.h" ++#include "pfe_mod.h" ++ ++static int pfe_majno; ++static struct class *pfe_char_class; ++static struct device *pfe_char_dev; ++struct eventfd_ctx *g_trigger; ++ ++struct pfe_shared_info link_states[PFE_CDEV_ETH_COUNT]; ++ ++static int pfe_cdev_open(struct inode *inp, struct file *fp) ++{ ++ pr_debug("PFE CDEV device opened.\n"); ++ return 0; ++} ++ ++static ssize_t pfe_cdev_read(struct file *fp, char *buf, ++ size_t len, loff_t *off) ++{ ++ int ret = 0; ++ ++ pr_info("PFE CDEV attempt copying (%lu) size of user.\n", ++ sizeof(link_states)); ++ ++ pr_debug("Dump link_state on screen before copy_to_user\n"); ++ for (; ret < PFE_CDEV_ETH_COUNT; ret++) { ++ pr_debug("%u %u", link_states[ret].phy_id, ++ link_states[ret].state); ++ pr_debug("\n"); ++ } ++ ++ /* Copy to user the value in buffer sized len */ ++ ret = copy_to_user(buf, &link_states, sizeof(link_states)); ++ if (ret != 0) { ++ pr_err("Failed to send (%d)bytes of (%lu) requested.\n", ++ ret, len); ++ return -EFAULT; ++ } ++ ++ /* offset set back to 0 as there is contextual reading offset */ ++ *off = 0; ++ pr_debug("Read of (%lu) bytes performed.\n", sizeof(link_states)); ++ ++ return sizeof(link_states); ++} ++ ++/** ++ * This function is for getting some commands from user through non-IOCTL ++ * channel. It can used to configure the device. ++ * TODO: To be filled in future, if require duplex communication with user ++ * space. ++ */ ++static ssize_t pfe_cdev_write(struct file *fp, const char *buf, ++ size_t len, loff_t *off) ++{ ++ pr_info("PFE CDEV Write operation not supported!\n"); ++ ++ return -EFAULT; ++} ++ ++static int pfe_cdev_release(struct inode *inp, struct file *fp) ++{ ++ if (g_trigger) { ++ free_irq(pfe->hif_irq, g_trigger); ++ eventfd_ctx_put(g_trigger); ++ g_trigger = NULL; ++ } ++ ++ pr_info("PFE_CDEV: Device successfully closed\n"); ++ return 0; ++} ++ ++/* ++ * hif_us_isr- ++ * This ISR routine processes Rx/Tx done interrupts from the HIF hardware block ++ */ ++static irqreturn_t hif_us_isr(int irq, void *arg) ++{ ++ struct eventfd_ctx *trigger = (struct eventfd_ctx *)arg; ++ int int_status; ++ int int_enable_mask; ++ ++ /*Read hif interrupt source register */ ++ int_status = readl_relaxed(HIF_INT_SRC); ++ int_enable_mask = readl_relaxed(HIF_INT_ENABLE); ++ ++ if ((int_status & HIF_INT) == 0) ++ return IRQ_NONE; ++ ++ if (int_status & HIF_RXPKT_INT) { ++ int_enable_mask &= ~(HIF_RXPKT_INT); ++ /* Disable interrupts, they will be enabled after ++ * they are serviced ++ */ ++ writel_relaxed(int_enable_mask, HIF_INT_ENABLE); ++ ++ eventfd_signal(trigger); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++#define PFE_INTR_COAL_USECS 100 ++static long pfe_cdev_ioctl(struct file *fp, unsigned int cmd, ++ unsigned long arg) ++{ ++ int ret = -EFAULT; ++ int __user *argp = (int __user *)arg; ++ ++ pr_debug("PFE CDEV IOCTL Called with cmd=(%u)\n", cmd); ++ ++ switch (cmd) { ++ case PFE_CDEV_ETH0_STATE_GET: ++ /* Return an unsigned int (link state) for ETH0 */ ++ *argp = link_states[0].state; ++ pr_debug("Returning state=%d for ETH0\n", *argp); ++ ret = 0; ++ break; ++ case PFE_CDEV_ETH1_STATE_GET: ++ /* Return an unsigned int (link state) for ETH0 */ ++ *argp = link_states[1].state; ++ pr_debug("Returning state=%d for ETH1\n", *argp); ++ ret = 0; ++ break; ++ case PFE_CDEV_HIF_INTR_EN: ++ /* Return success/failure */ ++ g_trigger = eventfd_ctx_fdget(*argp); ++ if (IS_ERR(g_trigger)) ++ return PTR_ERR(g_trigger); ++ ret = request_irq(pfe->hif_irq, hif_us_isr, 0, "pfe_hif", ++ g_trigger); ++ if (ret) { ++ pr_err("%s: failed to get the hif IRQ = %d\n", ++ __func__, pfe->hif_irq); ++ eventfd_ctx_put(g_trigger); ++ g_trigger = NULL; ++ } ++ writel((PFE_INTR_COAL_USECS * (pfe->ctrl.sys_clk / 1000)) | ++ HIF_INT_COAL_ENABLE, HIF_INT_COAL); ++ ++ pr_debug("request_irq for hif interrupt: %d\n", pfe->hif_irq); ++ ret = 0; ++ break; ++ default: ++ pr_info("Unsupport cmd (%d) for PFE CDEV.\n", cmd); ++ break; ++ }; ++ ++ return ret; ++} ++ ++static unsigned int pfe_cdev_poll(struct file *fp, ++ struct poll_table_struct *wait) ++{ ++ pr_info("PFE CDEV poll method not supported\n"); ++ return 0; ++} ++ ++static const struct file_operations pfe_cdev_fops = { ++ .open = pfe_cdev_open, ++ .read = pfe_cdev_read, ++ .write = pfe_cdev_write, ++ .release = pfe_cdev_release, ++ .unlocked_ioctl = pfe_cdev_ioctl, ++ .poll = pfe_cdev_poll, ++}; ++ ++int pfe_cdev_init(void) ++{ ++ int ret; ++ ++ pr_debug("PFE CDEV initialization begin\n"); ++ ++ /* Register the major number for the device */ ++ pfe_majno = register_chrdev(0, PFE_CDEV_NAME, &pfe_cdev_fops); ++ if (pfe_majno < 0) { ++ pr_err("Unable to register PFE CDEV. PFE CDEV not available\n"); ++ ret = pfe_majno; ++ goto cleanup; ++ } ++ ++ pr_debug("PFE CDEV assigned major number: %d\n", pfe_majno); ++ ++ /* Register the class for the device */ ++ pfe_char_class = class_create(PFE_CLASS_NAME); ++ if (IS_ERR(pfe_char_class)) { ++ pr_err( ++ "Failed to init class for PFE CDEV. PFE CDEV not available.\n"); ++ ret = PTR_ERR(pfe_char_class); ++ goto cleanup; ++ } ++ ++ pr_debug("PFE CDEV Class created successfully.\n"); ++ ++ /* Create the device without any parent and without any callback data */ ++ pfe_char_dev = device_create(pfe_char_class, NULL, ++ MKDEV(pfe_majno, 0), NULL, ++ PFE_CDEV_NAME); ++ if (IS_ERR(pfe_char_dev)) { ++ pr_err("Unable to PFE CDEV device. PFE CDEV not available.\n"); ++ ret = PTR_ERR(pfe_char_dev); ++ goto cleanup; ++ } ++ ++ /* Information structure being shared with the userspace */ ++ memset(link_states, 0, sizeof(struct pfe_shared_info) * ++ PFE_CDEV_ETH_COUNT); ++ ++ pr_info("PFE CDEV created: %s\n", PFE_CDEV_NAME); ++ ++ ret = 0; ++ return ret; ++ ++cleanup: ++ if (!IS_ERR(pfe_char_class)) ++ class_destroy(pfe_char_class); ++ ++ if (pfe_majno > 0) ++ unregister_chrdev(pfe_majno, PFE_CDEV_NAME); ++ ++ return ret; ++} ++ ++void pfe_cdev_exit(void) ++{ ++ if (!IS_ERR(pfe_char_dev)) ++ device_destroy(pfe_char_class, MKDEV(pfe_majno, 0)); ++ ++ if (!IS_ERR(pfe_char_class)) { ++ class_unregister(pfe_char_class); ++ class_destroy(pfe_char_class); ++ } ++ ++ if (pfe_majno > 0) ++ unregister_chrdev(pfe_majno, PFE_CDEV_NAME); ++ ++ /* reset the variables */ ++ pfe_majno = 0; ++ pfe_char_class = NULL; ++ pfe_char_dev = NULL; ++ ++ pr_info("PFE CDEV Removed.\n"); ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_cdev.h +@@ -0,0 +1,41 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2018 NXP ++ */ ++ ++#ifndef _PFE_CDEV_H_ ++#define _PFE_CDEV_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PFE_CDEV_NAME "pfe_us_cdev" ++#define PFE_CLASS_NAME "ppfe_us" ++ ++/* Extracted from ls1012a_pfe_platform_data, there are 3 interfaces which are ++ * supported by PFE driver. Should be updated if number of eth devices are ++ * changed. ++ */ ++#define PFE_CDEV_ETH_COUNT 3 ++ ++struct pfe_shared_info { ++ uint32_t phy_id; /* Link phy ID */ ++ uint8_t state; /* Has either 0 or 1 */ ++}; ++ ++extern struct pfe_shared_info link_states[PFE_CDEV_ETH_COUNT]; ++ ++/* IOCTL Commands */ ++#define PFE_CDEV_ETH0_STATE_GET _IOR('R', 0, int) ++#define PFE_CDEV_ETH1_STATE_GET _IOR('R', 1, int) ++#define PFE_CDEV_HIF_INTR_EN _IOWR('R', 2, int) ++ ++int pfe_cdev_init(void); ++void pfe_cdev_exit(void); ++ ++#endif /* _PFE_CDEV_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_ctrl.c +@@ -0,0 +1,226 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "pfe_mod.h" ++#include "pfe_ctrl.h" ++ ++#define TIMEOUT_MS 1000 ++ ++int relax(unsigned long end) ++{ ++ if (time_after(jiffies, end)) { ++ if (time_after(jiffies, end + (TIMEOUT_MS * HZ) / 1000)) ++ return -1; ++ ++ if (need_resched()) ++ schedule(); ++ } ++ ++ return 0; ++} ++ ++void pfe_ctrl_suspend(struct pfe_ctrl *ctrl) ++{ ++ int id; ++ ++ mutex_lock(&ctrl->mutex); ++ ++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) ++ pe_dmem_write(id, cpu_to_be32(0x1), CLASS_DM_RESUME, 4); ++ ++ for (id = TMU0_ID; id <= TMU_MAX_ID; id++) { ++ if (id == TMU2_ID) ++ continue; ++ pe_dmem_write(id, cpu_to_be32(0x1), TMU_DM_RESUME, 4); ++ } ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ pe_dmem_write(UTIL_ID, cpu_to_be32(0x1), UTIL_DM_RESUME, 4); ++#endif ++ mutex_unlock(&ctrl->mutex); ++} ++ ++void pfe_ctrl_resume(struct pfe_ctrl *ctrl) ++{ ++ int pe_mask = CLASS_MASK | TMU_MASK; ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ pe_mask |= UTIL_MASK; ++#endif ++ mutex_lock(&ctrl->mutex); ++ pe_start(&pfe->ctrl, pe_mask); ++ mutex_unlock(&ctrl->mutex); ++} ++ ++/* PE sync stop. ++ * Stops packet processing for a list of PE's (specified using a bitmask). ++ * The caller must hold ctrl->mutex. ++ * ++ * @param ctrl Control context ++ * @param pe_mask Mask of PE id's to stop ++ * ++ */ ++int pe_sync_stop(struct pfe_ctrl *ctrl, int pe_mask) ++{ ++ struct pe_sync_mailbox *mbox; ++ int pe_stopped = 0; ++ unsigned long end = jiffies + 2; ++ int i; ++ ++ pe_mask &= 0x2FF; /*Exclude Util + TMU2 */ ++ ++ for (i = 0; i < MAX_PE; i++) ++ if (pe_mask & (1 << i)) { ++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; ++ ++ pe_dmem_write(i, cpu_to_be32(0x1), (unsigned ++ long)&mbox->stop, 4); ++ } ++ ++ while (pe_stopped != pe_mask) { ++ for (i = 0; i < MAX_PE; i++) ++ if ((pe_mask & (1 << i)) && !(pe_stopped & (1 << i))) { ++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; ++ ++ if (pe_dmem_read(i, (unsigned ++ long)&mbox->stopped, 4) & ++ cpu_to_be32(0x1)) ++ pe_stopped |= (1 << i); ++ } ++ ++ if (relax(end) < 0) ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_err("%s: timeout, %x %x\n", __func__, pe_mask, pe_stopped); ++ ++ for (i = 0; i < MAX_PE; i++) ++ if (pe_mask & (1 << i)) { ++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; ++ ++ pe_dmem_write(i, cpu_to_be32(0x0), (unsigned ++ long)&mbox->stop, 4); ++ } ++ ++ return -EIO; ++} ++ ++/* PE start. ++ * Starts packet processing for a list of PE's (specified using a bitmask). ++ * The caller must hold ctrl->mutex. ++ * ++ * @param ctrl Control context ++ * @param pe_mask Mask of PE id's to start ++ * ++ */ ++void pe_start(struct pfe_ctrl *ctrl, int pe_mask) ++{ ++ struct pe_sync_mailbox *mbox; ++ int i; ++ ++ for (i = 0; i < MAX_PE; i++) ++ if (pe_mask & (1 << i)) { ++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; ++ ++ pe_dmem_write(i, cpu_to_be32(0x0), (unsigned ++ long)&mbox->stop, 4); ++ } ++} ++ ++/* This function will ensure all PEs are put in to idle state */ ++int pe_reset_all(struct pfe_ctrl *ctrl) ++{ ++ struct pe_sync_mailbox *mbox; ++ int pe_stopped = 0; ++ unsigned long end = jiffies + 2; ++ int i; ++ int pe_mask = CLASS_MASK | TMU_MASK; ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ pe_mask |= UTIL_MASK; ++#endif ++ ++ for (i = 0; i < MAX_PE; i++) ++ if (pe_mask & (1 << i)) { ++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; ++ ++ pe_dmem_write(i, cpu_to_be32(0x2), (unsigned ++ long)&mbox->stop, 4); ++ } ++ ++ while (pe_stopped != pe_mask) { ++ for (i = 0; i < MAX_PE; i++) ++ if ((pe_mask & (1 << i)) && !(pe_stopped & (1 << i))) { ++ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; ++ ++ if (pe_dmem_read(i, (unsigned long) ++ &mbox->stopped, 4) & ++ cpu_to_be32(0x1)) ++ pe_stopped |= (1 << i); ++ } ++ ++ if (relax(end) < 0) ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ pr_err("%s: timeout, %x %x\n", __func__, pe_mask, pe_stopped); ++ return -EIO; ++} ++ ++int pfe_ctrl_init(struct pfe *pfe) ++{ ++ struct pfe_ctrl *ctrl = &pfe->ctrl; ++ int id; ++ ++ pr_info("%s\n", __func__); ++ ++ mutex_init(&ctrl->mutex); ++ spin_lock_init(&ctrl->lock); ++ ++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { ++ ctrl->sync_mailbox_baseaddr[id] = CLASS_DM_SYNC_MBOX; ++ ctrl->msg_mailbox_baseaddr[id] = CLASS_DM_MSG_MBOX; ++ } ++ ++ for (id = TMU0_ID; id <= TMU_MAX_ID; id++) { ++ if (id == TMU2_ID) ++ continue; ++ ctrl->sync_mailbox_baseaddr[id] = TMU_DM_SYNC_MBOX; ++ ctrl->msg_mailbox_baseaddr[id] = TMU_DM_MSG_MBOX; ++ } ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ ctrl->sync_mailbox_baseaddr[UTIL_ID] = UTIL_DM_SYNC_MBOX; ++ ctrl->msg_mailbox_baseaddr[UTIL_ID] = UTIL_DM_MSG_MBOX; ++#endif ++ ++ ctrl->hash_array_baseaddr = pfe->ddr_baseaddr + ROUTE_TABLE_BASEADDR; ++ ctrl->hash_array_phys_baseaddr = pfe->ddr_phys_baseaddr + ++ ROUTE_TABLE_BASEADDR; ++ ++ ctrl->dev = pfe->dev; ++ ++ pr_info("%s finished\n", __func__); ++ ++ return 0; ++} ++ ++void pfe_ctrl_exit(struct pfe *pfe) ++{ ++ pr_info("%s\n", __func__); ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_ctrl.h +@@ -0,0 +1,100 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#ifndef _PFE_CTRL_H_ ++#define _PFE_CTRL_H_ ++ ++#include ++ ++#include "pfe/pfe.h" ++ ++#define DMA_BUF_SIZE_128 0x80 /* enough for 1 conntracks */ ++#define DMA_BUF_SIZE_256 0x100 ++/* enough for 2 conntracks, 1 bridge entry or 1 multicast entry */ ++#define DMA_BUF_SIZE_512 0x200 ++/* 512bytes dma allocated buffers used by rtp relay feature */ ++#define DMA_BUF_MIN_ALIGNMENT 8 ++#define DMA_BUF_BOUNDARY (4 * 1024) ++/* bursts can not cross 4k boundary */ ++ ++#define CMD_TX_ENABLE 0x0501 ++#define CMD_TX_DISABLE 0x0502 ++ ++#define CMD_RX_LRO 0x0011 ++#define CMD_PKTCAP_ENABLE 0x0d01 ++#define CMD_QM_EXPT_RATE 0x020c ++ ++#define CLASS_DM_SH_STATIC (0x800) ++#define CLASS_DM_CPU_TICKS (CLASS_DM_SH_STATIC) ++#define CLASS_DM_SYNC_MBOX (0x808) ++#define CLASS_DM_MSG_MBOX (0x810) ++#define CLASS_DM_DROP_CNTR (0x820) ++#define CLASS_DM_RESUME (0x854) ++#define CLASS_DM_PESTATUS (0x860) ++#define CLASS_DM_CRC_VALIDATED (0x14b0) ++ ++#define TMU_DM_SH_STATIC (0x80) ++#define TMU_DM_CPU_TICKS (TMU_DM_SH_STATIC) ++#define TMU_DM_SYNC_MBOX (0x88) ++#define TMU_DM_MSG_MBOX (0x90) ++#define TMU_DM_RESUME (0xA0) ++#define TMU_DM_PESTATUS (0xB0) ++#define TMU_DM_CONTEXT (0x300) ++#define TMU_DM_TX_TRANS (0x480) ++ ++#define UTIL_DM_SH_STATIC (0x0) ++#define UTIL_DM_CPU_TICKS (UTIL_DM_SH_STATIC) ++#define UTIL_DM_SYNC_MBOX (0x8) ++#define UTIL_DM_MSG_MBOX (0x10) ++#define UTIL_DM_DROP_CNTR (0x20) ++#define UTIL_DM_RESUME (0x40) ++#define UTIL_DM_PESTATUS (0x50) ++ ++struct pfe_ctrl { ++ struct mutex mutex; /* to serialize pfe control access */ ++ spinlock_t lock; ++ ++ void *dma_pool; ++ void *dma_pool_512; ++ void *dma_pool_128; ++ ++ struct device *dev; ++ ++ void *hash_array_baseaddr; /* ++ * Virtual base address of ++ * the conntrack hash array ++ */ ++ unsigned long hash_array_phys_baseaddr; /* ++ * Physical base address of ++ * the conntrack hash array ++ */ ++ ++ int (*event_cb)(u16, u16, u16*); ++ ++ unsigned long sync_mailbox_baseaddr[MAX_PE]; /* ++ * Sync mailbox PFE ++ * internal address, ++ * initialized ++ * when parsing elf images ++ */ ++ unsigned long msg_mailbox_baseaddr[MAX_PE]; /* ++ * Msg mailbox PFE internal ++ * address, initialized ++ * when parsing elf images ++ */ ++ unsigned int sys_clk; /* AXI clock value, in KHz */ ++}; ++ ++int pfe_ctrl_init(struct pfe *pfe); ++void pfe_ctrl_exit(struct pfe *pfe); ++int pe_sync_stop(struct pfe_ctrl *ctrl, int pe_mask); ++void pe_start(struct pfe_ctrl *ctrl, int pe_mask); ++int pe_reset_all(struct pfe_ctrl *ctrl); ++void pfe_ctrl_suspend(struct pfe_ctrl *ctrl); ++void pfe_ctrl_resume(struct pfe_ctrl *ctrl); ++int relax(unsigned long end); ++ ++#endif /* _PFE_CTRL_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_debugfs.c +@@ -0,0 +1,99 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#include ++#include ++#include ++ ++#include "pfe_mod.h" ++ ++static int dmem_show(struct seq_file *s, void *unused) ++{ ++ u32 dmem_addr, val; ++ int id = (long int)s->private; ++ int i; ++ ++ for (dmem_addr = 0; dmem_addr < CLASS_DMEM_SIZE; dmem_addr += 8 * 4) { ++ seq_printf(s, "%04x:", dmem_addr); ++ ++ for (i = 0; i < 8; i++) { ++ val = pe_dmem_read(id, dmem_addr + i * 4, 4); ++ seq_printf(s, " %02x %02x %02x %02x", val & 0xff, ++ (val >> 8) & 0xff, (val >> 16) & 0xff, ++ (val >> 24) & 0xff); ++ } ++ ++ seq_puts(s, "\n"); ++ } ++ ++ return 0; ++} ++ ++static int dmem_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, dmem_show, inode->i_private); ++} ++ ++static const struct file_operations dmem_fops = { ++ .open = dmem_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++int pfe_debugfs_init(struct pfe *pfe) ++{ ++ struct dentry *d; ++ ++ pr_info("%s\n", __func__); ++ ++ pfe->dentry = debugfs_create_dir("pfe", NULL); ++ if (IS_ERR_OR_NULL(pfe->dentry)) ++ goto err_dir; ++ ++ d = debugfs_create_file("pe0_dmem", 0444, pfe->dentry, (void *)0, ++ &dmem_fops); ++ if (IS_ERR_OR_NULL(d)) ++ goto err_pe; ++ ++ d = debugfs_create_file("pe1_dmem", 0444, pfe->dentry, (void *)1, ++ &dmem_fops); ++ if (IS_ERR_OR_NULL(d)) ++ goto err_pe; ++ ++ d = debugfs_create_file("pe2_dmem", 0444, pfe->dentry, (void *)2, ++ &dmem_fops); ++ if (IS_ERR_OR_NULL(d)) ++ goto err_pe; ++ ++ d = debugfs_create_file("pe3_dmem", 0444, pfe->dentry, (void *)3, ++ &dmem_fops); ++ if (IS_ERR_OR_NULL(d)) ++ goto err_pe; ++ ++ d = debugfs_create_file("pe4_dmem", 0444, pfe->dentry, (void *)4, ++ &dmem_fops); ++ if (IS_ERR_OR_NULL(d)) ++ goto err_pe; ++ ++ d = debugfs_create_file("pe5_dmem", 0444, pfe->dentry, (void *)5, ++ &dmem_fops); ++ if (IS_ERR_OR_NULL(d)) ++ goto err_pe; ++ ++ return 0; ++ ++err_pe: ++ debugfs_remove_recursive(pfe->dentry); ++ ++err_dir: ++ return -1; ++} ++ ++void pfe_debugfs_exit(struct pfe *pfe) ++{ ++ debugfs_remove_recursive(pfe->dentry); ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_debugfs.h +@@ -0,0 +1,13 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#ifndef _PFE_DEBUGFS_H_ ++#define _PFE_DEBUGFS_H_ ++ ++int pfe_debugfs_init(struct pfe *pfe); ++void pfe_debugfs_exit(struct pfe *pfe); ++ ++#endif /* _PFE_DEBUGFS_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_eth.c +@@ -0,0 +1,2550 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++/* @pfe_eth.c. ++ * Ethernet driver for to handle exception path for PFE. ++ * - uses HIF functions to send/receive packets. ++ * - uses ctrl function to start/stop interfaces. ++ * - uses direct register accesses to control phy operation. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_NF_CONNTRACK_MARK) ++#include ++#endif ++ ++#include "pfe_mod.h" ++#include "pfe_eth.h" ++#include "pfe_cdev.h" ++ ++#define LS1012A_REV_1_0 0x87040010 ++ ++bool pfe_use_old_dts_phy; ++bool pfe_errata_a010897; ++ ++static void *cbus_emac_base[3]; ++static void *cbus_gpi_base[3]; ++ ++/* Forward Declaration */ ++static void pfe_eth_exit_one(struct pfe_eth_priv_s *priv); ++static void pfe_eth_flush_tx(struct pfe_eth_priv_s *priv); ++static void pfe_eth_flush_txQ(struct pfe_eth_priv_s *priv, int tx_q_num, int ++ from_tx, int n_desc); ++ ++/* MDIO registers */ ++#define MDIO_SGMII_CR 0x00 ++#define MDIO_SGMII_SR 0x01 ++#define MDIO_SGMII_DEV_ABIL_SGMII 0x04 ++#define MDIO_SGMII_LINK_TMR_L 0x12 ++#define MDIO_SGMII_LINK_TMR_H 0x13 ++#define MDIO_SGMII_IF_MODE 0x14 ++ ++/* SGMII Control defines */ ++#define SGMII_CR_RST 0x8000 ++#define SGMII_CR_AN_EN 0x1000 ++#define SGMII_CR_RESTART_AN 0x0200 ++#define SGMII_CR_FD 0x0100 ++#define SGMII_CR_SPEED_SEL1_1G 0x0040 ++#define SGMII_CR_DEF_VAL (SGMII_CR_AN_EN | SGMII_CR_FD | \ ++ SGMII_CR_SPEED_SEL1_1G) ++ ++/* SGMII IF Mode */ ++#define SGMII_DUPLEX_HALF 0x10 ++#define SGMII_SPEED_10MBPS 0x00 ++#define SGMII_SPEED_100MBPS 0x04 ++#define SGMII_SPEED_1GBPS 0x08 ++#define SGMII_USE_SGMII_AN 0x02 ++#define SGMII_EN 0x01 ++ ++/* SGMII Device Ability for SGMII */ ++#define SGMII_DEV_ABIL_ACK 0x4000 ++#define SGMII_DEV_ABIL_EEE_CLK_STP_EN 0x0100 ++#define SGMII_DEV_ABIL_SGMII 0x0001 ++ ++unsigned int gemac_regs[] = { ++ 0x0004, /* Interrupt event */ ++ 0x0008, /* Interrupt mask */ ++ 0x0024, /* Ethernet control */ ++ 0x0064, /* MIB Control/Status */ ++ 0x0084, /* Receive control/status */ ++ 0x00C4, /* Transmit control */ ++ 0x00E4, /* Physical address low */ ++ 0x00E8, /* Physical address high */ ++ 0x0144, /* Transmit FIFO Watermark and Store and Forward Control*/ ++ 0x0190, /* Receive FIFO Section Full Threshold */ ++ 0x01A0, /* Transmit FIFO Section Empty Threshold */ ++ 0x01B0, /* Frame Truncation Length */ ++}; ++ ++const struct soc_device_attribute ls1012a_rev1_soc_attr[] = { ++ { .family = "QorIQ LS1012A", ++ .soc_id = "svr:0x87040010", ++ .revision = "1.0", ++ .data = NULL }, ++ { }, ++}; ++ ++/********************************************************************/ ++/* SYSFS INTERFACE */ ++/********************************************************************/ ++ ++#ifdef PFE_ETH_NAPI_STATS ++/* ++ * pfe_eth_show_napi_stats ++ */ ++static ssize_t pfe_eth_show_napi_stats(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ ssize_t len = 0; ++ ++ len += sprintf(buf + len, "sched: %u\n", ++ priv->napi_counters[NAPI_SCHED_COUNT]); ++ len += sprintf(buf + len, "poll: %u\n", ++ priv->napi_counters[NAPI_POLL_COUNT]); ++ len += sprintf(buf + len, "packet: %u\n", ++ priv->napi_counters[NAPI_PACKET_COUNT]); ++ len += sprintf(buf + len, "budget: %u\n", ++ priv->napi_counters[NAPI_FULL_BUDGET_COUNT]); ++ len += sprintf(buf + len, "desc: %u\n", ++ priv->napi_counters[NAPI_DESC_COUNT]); ++ ++ return len; ++} ++ ++/* ++ * pfe_eth_set_napi_stats ++ */ ++static ssize_t pfe_eth_set_napi_stats(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ ++ memset(priv->napi_counters, 0, sizeof(priv->napi_counters)); ++ ++ return count; ++} ++#endif ++#ifdef PFE_ETH_TX_STATS ++/* pfe_eth_show_tx_stats ++ * ++ */ ++static ssize_t pfe_eth_show_tx_stats(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ ssize_t len = 0; ++ int i; ++ ++ len += sprintf(buf + len, "TX queues stats:\n"); ++ ++ for (i = 0; i < emac_txq_cnt; i++) { ++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, ++ i); ++ ++ len += sprintf(buf + len, "\n"); ++ __netif_tx_lock_bh(tx_queue); ++ ++ hif_tx_lock(&pfe->hif); ++ len += sprintf(buf + len, ++ "Queue %2d : credits = %10d\n" ++ , i, hif_lib_tx_credit_avail(pfe, priv->id, i)); ++ len += sprintf(buf + len, ++ " tx packets = %10d\n" ++ , pfe->tmu_credit.tx_packets[priv->id][i]); ++ hif_tx_unlock(&pfe->hif); ++ ++ /* Don't output additionnal stats if queue never used */ ++ if (!pfe->tmu_credit.tx_packets[priv->id][i]) ++ goto skip; ++ ++ len += sprintf(buf + len, ++ " clean_fail = %10d\n" ++ , priv->clean_fail[i]); ++ len += sprintf(buf + len, ++ " stop_queue = %10d\n" ++ , priv->stop_queue_total[i]); ++ len += sprintf(buf + len, ++ " stop_queue_hif = %10d\n" ++ , priv->stop_queue_hif[i]); ++ len += sprintf(buf + len, ++ " stop_queue_hif_client = %10d\n" ++ , priv->stop_queue_hif_client[i]); ++ len += sprintf(buf + len, ++ " stop_queue_credit = %10d\n" ++ , priv->stop_queue_credit[i]); ++skip: ++ __netif_tx_unlock_bh(tx_queue); ++ } ++ return len; ++} ++ ++/* pfe_eth_set_tx_stats ++ * ++ */ ++static ssize_t pfe_eth_set_tx_stats(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ int i; ++ ++ for (i = 0; i < emac_txq_cnt; i++) { ++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, ++ i); ++ ++ __netif_tx_lock_bh(tx_queue); ++ priv->clean_fail[i] = 0; ++ priv->stop_queue_total[i] = 0; ++ priv->stop_queue_hif[i] = 0; ++ priv->stop_queue_hif_client[i] = 0; ++ priv->stop_queue_credit[i] = 0; ++ __netif_tx_unlock_bh(tx_queue); ++ } ++ ++ return count; ++} ++#endif ++/* pfe_eth_show_txavail ++ * ++ */ ++static ssize_t pfe_eth_show_txavail(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ ssize_t len = 0; ++ int i; ++ ++ for (i = 0; i < emac_txq_cnt; i++) { ++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, ++ i); ++ ++ __netif_tx_lock_bh(tx_queue); ++ ++ len += sprintf(buf + len, "%d", ++ hif_lib_tx_avail(&priv->client, i)); ++ ++ __netif_tx_unlock_bh(tx_queue); ++ ++ if (i == (emac_txq_cnt - 1)) ++ len += sprintf(buf + len, "\n"); ++ else ++ len += sprintf(buf + len, " "); ++ } ++ ++ return len; ++} ++ ++/* pfe_eth_show_default_priority ++ * ++ */ ++static ssize_t pfe_eth_show_default_priority(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ unsigned long flags; ++ int rc; ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ rc = sprintf(buf, "%d\n", priv->default_priority); ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ return rc; ++} ++ ++/* pfe_eth_set_default_priority ++ * ++ */ ++ ++static ssize_t pfe_eth_set_default_priority(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ priv->default_priority = kstrtoul(buf, 0, 0); ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(txavail, 0444, pfe_eth_show_txavail, NULL); ++static DEVICE_ATTR(default_priority, 0644, pfe_eth_show_default_priority, ++ pfe_eth_set_default_priority); ++ ++#ifdef PFE_ETH_NAPI_STATS ++static DEVICE_ATTR(napi_stats, 0644, pfe_eth_show_napi_stats, ++ pfe_eth_set_napi_stats); ++#endif ++ ++#ifdef PFE_ETH_TX_STATS ++static DEVICE_ATTR(tx_stats, 0644, pfe_eth_show_tx_stats, ++ pfe_eth_set_tx_stats); ++#endif ++ ++/* ++ * pfe_eth_sysfs_init ++ * ++ */ ++static int pfe_eth_sysfs_init(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ int err; ++ ++ /* Initialize the default values */ ++ ++ /* ++ * By default, packets without conntrack will use this default low ++ * priority queue ++ */ ++ priv->default_priority = 0; ++ ++ /* Create our sysfs files */ ++ err = device_create_file(&ndev->dev, &dev_attr_default_priority); ++ if (err) { ++ netdev_err(ndev, ++ "failed to create default_priority sysfs files\n"); ++ goto err_priority; ++ } ++ ++ err = device_create_file(&ndev->dev, &dev_attr_txavail); ++ if (err) { ++ netdev_err(ndev, ++ "failed to create default_priority sysfs files\n"); ++ goto err_txavail; ++ } ++ ++#ifdef PFE_ETH_NAPI_STATS ++ err = device_create_file(&ndev->dev, &dev_attr_napi_stats); ++ if (err) { ++ netdev_err(ndev, "failed to create napi stats sysfs files\n"); ++ goto err_napi; ++ } ++#endif ++ ++#ifdef PFE_ETH_TX_STATS ++ err = device_create_file(&ndev->dev, &dev_attr_tx_stats); ++ if (err) { ++ netdev_err(ndev, "failed to create tx stats sysfs files\n"); ++ goto err_tx; ++ } ++#endif ++ ++ return 0; ++ ++#ifdef PFE_ETH_TX_STATS ++err_tx: ++#endif ++#ifdef PFE_ETH_NAPI_STATS ++ device_remove_file(&ndev->dev, &dev_attr_napi_stats); ++ ++err_napi: ++#endif ++ device_remove_file(&ndev->dev, &dev_attr_txavail); ++ ++err_txavail: ++ device_remove_file(&ndev->dev, &dev_attr_default_priority); ++ ++err_priority: ++ return -1; ++} ++ ++/* pfe_eth_sysfs_exit ++ * ++ */ ++static void pfe_eth_sysfs_exit(struct net_device *ndev) ++{ ++#ifdef PFE_ETH_TX_STATS ++ device_remove_file(&ndev->dev, &dev_attr_tx_stats); ++#endif ++ ++#ifdef PFE_ETH_NAPI_STATS ++ device_remove_file(&ndev->dev, &dev_attr_napi_stats); ++#endif ++ device_remove_file(&ndev->dev, &dev_attr_txavail); ++ device_remove_file(&ndev->dev, &dev_attr_default_priority); ++} ++ ++/*************************************************************************/ ++/* ETHTOOL INTERCAE */ ++/*************************************************************************/ ++ ++/*MTIP GEMAC */ ++static const struct fec_stat { ++ char name[ETH_GSTRING_LEN]; ++ u16 offset; ++} fec_stats[] = { ++ /* RMON TX */ ++ { "tx_dropped", RMON_T_DROP }, ++ { "tx_packets", RMON_T_PACKETS }, ++ { "tx_broadcast", RMON_T_BC_PKT }, ++ { "tx_multicast", RMON_T_MC_PKT }, ++ { "tx_crc_errors", RMON_T_CRC_ALIGN }, ++ { "tx_undersize", RMON_T_UNDERSIZE }, ++ { "tx_oversize", RMON_T_OVERSIZE }, ++ { "tx_fragment", RMON_T_FRAG }, ++ { "tx_jabber", RMON_T_JAB }, ++ { "tx_collision", RMON_T_COL }, ++ { "tx_64byte", RMON_T_P64 }, ++ { "tx_65to127byte", RMON_T_P65TO127 }, ++ { "tx_128to255byte", RMON_T_P128TO255 }, ++ { "tx_256to511byte", RMON_T_P256TO511 }, ++ { "tx_512to1023byte", RMON_T_P512TO1023 }, ++ { "tx_1024to2047byte", RMON_T_P1024TO2047 }, ++ { "tx_GTE2048byte", RMON_T_P_GTE2048 }, ++ { "tx_octets", RMON_T_OCTETS }, ++ ++ /* IEEE TX */ ++ { "IEEE_tx_drop", IEEE_T_DROP }, ++ { "IEEE_tx_frame_ok", IEEE_T_FRAME_OK }, ++ { "IEEE_tx_1col", IEEE_T_1COL }, ++ { "IEEE_tx_mcol", IEEE_T_MCOL }, ++ { "IEEE_tx_def", IEEE_T_DEF }, ++ { "IEEE_tx_lcol", IEEE_T_LCOL }, ++ { "IEEE_tx_excol", IEEE_T_EXCOL }, ++ { "IEEE_tx_macerr", IEEE_T_MACERR }, ++ { "IEEE_tx_cserr", IEEE_T_CSERR }, ++ { "IEEE_tx_sqe", IEEE_T_SQE }, ++ { "IEEE_tx_fdxfc", IEEE_T_FDXFC }, ++ { "IEEE_tx_octets_ok", IEEE_T_OCTETS_OK }, ++ ++ /* RMON RX */ ++ { "rx_packets", RMON_R_PACKETS }, ++ { "rx_broadcast", RMON_R_BC_PKT }, ++ { "rx_multicast", RMON_R_MC_PKT }, ++ { "rx_crc_errors", RMON_R_CRC_ALIGN }, ++ { "rx_undersize", RMON_R_UNDERSIZE }, ++ { "rx_oversize", RMON_R_OVERSIZE }, ++ { "rx_fragment", RMON_R_FRAG }, ++ { "rx_jabber", RMON_R_JAB }, ++ { "rx_64byte", RMON_R_P64 }, ++ { "rx_65to127byte", RMON_R_P65TO127 }, ++ { "rx_128to255byte", RMON_R_P128TO255 }, ++ { "rx_256to511byte", RMON_R_P256TO511 }, ++ { "rx_512to1023byte", RMON_R_P512TO1023 }, ++ { "rx_1024to2047byte", RMON_R_P1024TO2047 }, ++ { "rx_GTE2048byte", RMON_R_P_GTE2048 }, ++ { "rx_octets", RMON_R_OCTETS }, ++ ++ /* IEEE RX */ ++ { "IEEE_rx_drop", IEEE_R_DROP }, ++ { "IEEE_rx_frame_ok", IEEE_R_FRAME_OK }, ++ { "IEEE_rx_crc", IEEE_R_CRC }, ++ { "IEEE_rx_align", IEEE_R_ALIGN }, ++ { "IEEE_rx_macerr", IEEE_R_MACERR }, ++ { "IEEE_rx_fdxfc", IEEE_R_FDXFC }, ++ { "IEEE_rx_octets_ok", IEEE_R_OCTETS_OK }, ++}; ++ ++static void pfe_eth_fill_stats(struct net_device *ndev, struct ethtool_stats ++ *stats, u64 *data) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ int i; ++ u64 pfe_crc_validated = 0; ++ int id; ++ ++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { ++ pfe_crc_validated += be32_to_cpu(pe_dmem_read(id, ++ CLASS_DM_CRC_VALIDATED + (priv->id * 4), 4)); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(fec_stats); i++) { ++ data[i] = readl(priv->EMAC_baseaddr + fec_stats[i].offset); ++ ++ if (fec_stats[i].offset == IEEE_R_DROP) ++ data[i] -= pfe_crc_validated; ++ } ++} ++ ++static void pfe_eth_gstrings(struct net_device *netdev, ++ u32 stringset, u8 *data) ++{ ++ int i; ++ ++ switch (stringset) { ++ case ETH_SS_STATS: ++ for (i = 0; i < ARRAY_SIZE(fec_stats); i++) ++ memcpy(data + i * ETH_GSTRING_LEN, ++ fec_stats[i].name, ETH_GSTRING_LEN); ++ break; ++ } ++} ++ ++static int pfe_eth_stats_count(struct net_device *ndev, int sset) ++{ ++ switch (sset) { ++ case ETH_SS_STATS: ++ return ARRAY_SIZE(fec_stats); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++/* ++ * pfe_eth_gemac_reglen - Return the length of the register structure. ++ * ++ */ ++static int pfe_eth_gemac_reglen(struct net_device *ndev) ++{ ++ pr_info("%s()\n", __func__); ++ return (sizeof(gemac_regs) / sizeof(u32)); ++} ++ ++/* ++ * pfe_eth_gemac_get_regs - Return the gemac register structure. ++ * ++ */ ++static void pfe_eth_gemac_get_regs(struct net_device *ndev, struct ethtool_regs ++ *regs, void *regbuf) ++{ ++ int i; ++ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ u32 *buf = (u32 *)regbuf; ++ ++ pr_info("%s()\n", __func__); ++ for (i = 0; i < sizeof(gemac_regs) / sizeof(u32); i++) ++ buf[i] = readl(priv->EMAC_baseaddr + gemac_regs[i]); ++} ++ ++/* ++ * pfe_eth_set_wol - Set the magic packet option, in WoL register. ++ * ++ */ ++static int pfe_eth_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ if (wol->wolopts & ~WAKE_MAGIC) ++ return -EOPNOTSUPP; ++ ++ /* for MTIP we store wol->wolopts */ ++ priv->wol = wol->wolopts; ++ ++ device_set_wakeup_enable(&ndev->dev, wol->wolopts & WAKE_MAGIC); ++ ++ return 0; ++} ++ ++/* ++ * ++ * pfe_eth_get_wol - Get the WoL options. ++ * ++ */ ++static void pfe_eth_get_wol(struct net_device *ndev, struct ethtool_wolinfo ++ *wol) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ wol->supported = WAKE_MAGIC; ++ wol->wolopts = 0; ++ ++ if (priv->wol & WAKE_MAGIC) ++ wol->wolopts = WAKE_MAGIC; ++ ++ memset(&wol->sopass, 0, sizeof(wol->sopass)); ++} ++ ++/* ++ * pfe_eth_get_drvinfo - Fills in the drvinfo structure with some basic info ++ * ++ */ ++static void pfe_eth_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo ++ *drvinfo) ++{ ++ strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); ++ strscpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version)); ++ strscpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); ++ strscpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info)); ++} ++ ++/* ++ * pfe_eth_set_settings - Used to send commands to PHY. ++ * ++ */ ++static int pfe_eth_set_settings(struct net_device *ndev, ++ const struct ethtool_link_ksettings *cmd) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ struct phy_device *phydev = priv->phydev; ++ ++ if (!phydev) ++ return -ENODEV; ++ ++ return phy_ethtool_ksettings_set(phydev, cmd); ++} ++ ++/* ++ * pfe_eth_getsettings - Return the current settings in the ethtool_cmd ++ * structure. ++ * ++ */ ++static int pfe_eth_get_settings(struct net_device *ndev, ++ struct ethtool_link_ksettings *cmd) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ struct phy_device *phydev = priv->phydev; ++ ++ if (!phydev) ++ return -ENODEV; ++ ++ phy_ethtool_ksettings_get(phydev, cmd); ++ ++ return 0; ++} ++ ++/* ++ * pfe_eth_get_msglevel - Gets the debug message mask. ++ * ++ */ ++static uint32_t pfe_eth_get_msglevel(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ return priv->msg_enable; ++} ++ ++/* ++ * pfe_eth_set_msglevel - Sets the debug message mask. ++ * ++ */ ++static void pfe_eth_set_msglevel(struct net_device *ndev, uint32_t data) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ priv->msg_enable = data; ++} ++ ++#define HIF_RX_COAL_MAX_CLKS (~(1 << 31)) ++#define HIF_RX_COAL_CLKS_PER_USEC (pfe->ctrl.sys_clk / 1000) ++#define HIF_RX_COAL_MAX_USECS (HIF_RX_COAL_MAX_CLKS / \ ++ HIF_RX_COAL_CLKS_PER_USEC) ++ ++/* ++ * pfe_eth_set_coalesce - Sets rx interrupt coalescing timer. ++ * ++ */ ++static int pfe_eth_set_coalesce(struct net_device *ndev, ++ struct ethtool_coalesce *ec, ++ struct kernel_ethtool_coalesce *kernel_coal, ++ struct netlink_ext_ack *extack) ++{ ++ if (ec->rx_coalesce_usecs > HIF_RX_COAL_MAX_USECS) ++ return -EINVAL; ++ ++ if (!ec->rx_coalesce_usecs) { ++ writel(0, HIF_INT_COAL); ++ return 0; ++ } ++ ++ writel((ec->rx_coalesce_usecs * HIF_RX_COAL_CLKS_PER_USEC) | ++ HIF_INT_COAL_ENABLE, HIF_INT_COAL); ++ ++ return 0; ++} ++ ++/* ++ * pfe_eth_get_coalesce - Gets rx interrupt coalescing timer value. ++ * ++ */ ++static int pfe_eth_get_coalesce(struct net_device *ndev, ++ struct ethtool_coalesce *ec, ++ struct kernel_ethtool_coalesce *kernel_coal, ++ struct netlink_ext_ack *extack) ++{ ++ int reg_val = readl(HIF_INT_COAL); ++ ++ if (reg_val & HIF_INT_COAL_ENABLE) ++ ec->rx_coalesce_usecs = (reg_val & HIF_RX_COAL_MAX_CLKS) / ++ HIF_RX_COAL_CLKS_PER_USEC; ++ else ++ ec->rx_coalesce_usecs = 0; ++ ++ return 0; ++} ++ ++/* ++ * pfe_eth_set_pauseparam - Sets pause parameters ++ * ++ */ ++static int pfe_eth_set_pauseparam(struct net_device *ndev, ++ struct ethtool_pauseparam *epause) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ if (epause->tx_pause != epause->rx_pause) { ++ netdev_info(ndev, ++ "hardware only support enable/disable both tx and rx\n"); ++ return -EINVAL; ++ } ++ ++ priv->pause_flag = 0; ++ priv->pause_flag |= epause->rx_pause ? PFE_PAUSE_FLAG_ENABLE : 0; ++ priv->pause_flag |= epause->autoneg ? PFE_PAUSE_FLAG_AUTONEG : 0; ++ ++ if (epause->rx_pause || epause->autoneg) { ++ gemac_enable_pause_rx(priv->EMAC_baseaddr); ++ writel((readl(priv->GPI_baseaddr + GPI_TX_PAUSE_TIME) | ++ EGPI_PAUSE_ENABLE), ++ priv->GPI_baseaddr + GPI_TX_PAUSE_TIME); ++ if (priv->phydev) { ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, ++ priv->phydev->supported); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, ++ priv->phydev->supported); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, ++ priv->phydev->advertising); ++ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, ++ priv->phydev->advertising); ++ } ++ } else { ++ gemac_disable_pause_rx(priv->EMAC_baseaddr); ++ writel((readl(priv->GPI_baseaddr + GPI_TX_PAUSE_TIME) & ++ ~EGPI_PAUSE_ENABLE), ++ priv->GPI_baseaddr + GPI_TX_PAUSE_TIME); ++ if (priv->phydev) { ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, ++ priv->phydev->supported); ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, ++ priv->phydev->supported); ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, ++ priv->phydev->advertising); ++ linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, ++ priv->phydev->advertising); ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * pfe_eth_get_pauseparam - Gets pause parameters ++ * ++ */ ++static void pfe_eth_get_pauseparam(struct net_device *ndev, ++ struct ethtool_pauseparam *epause) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ epause->autoneg = (priv->pause_flag & PFE_PAUSE_FLAG_AUTONEG) != 0; ++ epause->tx_pause = (priv->pause_flag & PFE_PAUSE_FLAG_ENABLE) != 0; ++ epause->rx_pause = epause->tx_pause; ++} ++ ++/* ++ * pfe_eth_get_hash ++ */ ++#define PFE_HASH_BITS 6 /* #bits in hash */ ++#define CRC32_POLY 0xEDB88320 ++ ++static int pfe_eth_get_hash(u8 *addr) ++{ ++ unsigned int i, bit, data, crc, hash; ++ ++ /* calculate crc32 value of mac address */ ++ crc = 0xffffffff; ++ ++ for (i = 0; i < 6; i++) { ++ data = addr[i]; ++ for (bit = 0; bit < 8; bit++, data >>= 1) { ++ crc = (crc >> 1) ^ ++ (((crc ^ data) & 1) ? CRC32_POLY : 0); ++ } ++ } ++ ++ /* ++ * only upper 6 bits (PFE_HASH_BITS) are used ++ * which point to specific bit in the hash registers ++ */ ++ hash = (crc >> (32 - PFE_HASH_BITS)) & 0x3f; ++ ++ return hash; ++} ++ ++const struct ethtool_ops pfe_ethtool_ops = { ++ .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS, ++ .get_drvinfo = pfe_eth_get_drvinfo, ++ .get_regs_len = pfe_eth_gemac_reglen, ++ .get_regs = pfe_eth_gemac_get_regs, ++ .get_link = ethtool_op_get_link, ++ .get_wol = pfe_eth_get_wol, ++ .set_wol = pfe_eth_set_wol, ++ .set_pauseparam = pfe_eth_set_pauseparam, ++ .get_pauseparam = pfe_eth_get_pauseparam, ++ .get_strings = pfe_eth_gstrings, ++ .get_sset_count = pfe_eth_stats_count, ++ .get_ethtool_stats = pfe_eth_fill_stats, ++ .get_msglevel = pfe_eth_get_msglevel, ++ .set_msglevel = pfe_eth_set_msglevel, ++ .set_coalesce = pfe_eth_set_coalesce, ++ .get_coalesce = pfe_eth_get_coalesce, ++ .get_link_ksettings = pfe_eth_get_settings, ++ .set_link_ksettings = pfe_eth_set_settings, ++}; ++ ++/* pfe_eth_mdio_reset ++ */ ++int pfe_eth_mdio_reset(struct mii_bus *bus) ++{ ++ struct pfe_mdio_priv_s *priv = (struct pfe_mdio_priv_s *)bus->priv; ++ u32 phy_speed; ++ ++ ++ mutex_lock(&bus->mdio_lock); ++ ++ /* ++ * Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed) ++ * ++ * The formula for FEC MDC is 'ref_freq / (MII_SPEED x 2)' while ++ * for ENET-MAC is 'ref_freq / ((MII_SPEED + 1) x 2)'. ++ */ ++ phy_speed = (DIV_ROUND_UP((pfe->ctrl.sys_clk * 1000), 4000000) ++ << EMAC_MII_SPEED_SHIFT); ++ phy_speed |= EMAC_HOLDTIME(0x5); ++ __raw_writel(phy_speed, priv->mdio_base + EMAC_MII_CTRL_REG); ++ ++ mutex_unlock(&bus->mdio_lock); ++ ++ return 0; ++} ++ ++/* pfe_eth_mdio_timeout ++ * ++ */ ++static int pfe_eth_mdio_timeout(struct pfe_mdio_priv_s *priv, int timeout) ++{ ++ while (!(__raw_readl(priv->mdio_base + EMAC_IEVENT_REG) & ++ EMAC_IEVENT_MII)) { ++ if (timeout-- <= 0) ++ return -1; ++ usleep_range(10, 20); ++ } ++ __raw_writel(EMAC_IEVENT_MII, priv->mdio_base + EMAC_IEVENT_REG); ++ return 0; ++} ++ ++static int pfe_eth_mdio_mux(u8 muxval) ++{ ++ struct i2c_adapter *a; ++ struct i2c_msg msg; ++ unsigned char buf[2]; ++ int ret; ++ ++ a = i2c_get_adapter(0); ++ if (!a) ++ return -ENODEV; ++ ++ /* set bit 1 (the second bit) of chip at 0x09, register 0x13 */ ++ buf[0] = 0x54; /* reg number */ ++ buf[1] = (muxval << 6) | 0x3; /* data */ ++ msg.addr = 0x66; ++ msg.buf = buf; ++ msg.len = 2; ++ msg.flags = 0; ++ ret = i2c_transfer(a, &msg, 1); ++ i2c_put_adapter(a); ++ if (ret != 1) ++ return -ENODEV; ++ return 0; ++} ++ ++static int pfe_eth_mdio_write(struct mii_bus *bus, int mii_id, int regnum, ++ u16 value) ++{ ++ struct pfe_mdio_priv_s *priv = (struct pfe_mdio_priv_s *)bus->priv; ++ ++ /*To access external PHYs on QDS board mux needs to be configured*/ ++ if ((mii_id) && (pfe->mdio_muxval[mii_id])) ++ pfe_eth_mdio_mux(pfe->mdio_muxval[mii_id]); ++ ++ /* start a write op */ ++ __raw_writel(EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR | ++ EMAC_MII_DATA_PA(mii_id) | ++ EMAC_MII_DATA_RA(regnum) | ++ EMAC_MII_DATA_TA | EMAC_MII_DATA(value), ++ priv->mdio_base + EMAC_MII_DATA_REG); ++ ++ if (pfe_eth_mdio_timeout(priv, EMAC_MDIO_TIMEOUT)) { ++ dev_err(&bus->dev, "%s: phy MDIO write timeout\n", __func__); ++ return -1; ++ } ++ return 0; ++} ++ ++static int pfe_eth_mdio_read(struct mii_bus *bus, int mii_id, int regnum) ++{ ++ struct pfe_mdio_priv_s *priv = (struct pfe_mdio_priv_s *)bus->priv; ++ u16 value = 0; ++ ++ /*To access external PHYs on QDS board mux needs to be configured*/ ++ if ((mii_id) && (pfe->mdio_muxval[mii_id])) ++ pfe_eth_mdio_mux(pfe->mdio_muxval[mii_id]); ++ ++ /* start a read op */ ++ __raw_writel(EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD | ++ EMAC_MII_DATA_PA(mii_id) | ++ EMAC_MII_DATA_RA(regnum) | ++ EMAC_MII_DATA_TA, priv->mdio_base + ++ EMAC_MII_DATA_REG); ++ ++ if (pfe_eth_mdio_timeout(priv, EMAC_MDIO_TIMEOUT)) { ++ dev_err(&bus->dev, "%s: phy MDIO read timeout\n", __func__); ++ return -1; ++ } ++ ++ value = EMAC_MII_DATA(__raw_readl(priv->mdio_base + ++ EMAC_MII_DATA_REG)); ++ return value; ++} ++ ++static int pfe_eth_mdio_init(struct pfe *pfe, ++ struct ls1012a_pfe_platform_data *pfe_info, ++ int ii) ++{ ++ struct pfe_mdio_priv_s *priv = NULL; ++ struct ls1012a_mdio_platform_data *mdio_info; ++ struct mii_bus *bus; ++ struct device_node *mdio_node; ++ int rc = 0; ++ ++ mdio_info = (struct ls1012a_mdio_platform_data *) ++ pfe_info->ls1012a_mdio_pdata; ++ mdio_info->id = ii; ++ ++ bus = mdiobus_alloc_size(sizeof(struct pfe_mdio_priv_s)); ++ if (!bus) { ++ pr_err("mdiobus_alloc() failed\n"); ++ rc = -ENOMEM; ++ goto err_mdioalloc; ++ } ++ ++ bus->name = "ls1012a MDIO Bus"; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "ls1012a-%x", mdio_info->id); ++ ++ bus->read = &pfe_eth_mdio_read; ++ bus->write = &pfe_eth_mdio_write; ++ bus->reset = &pfe_eth_mdio_reset; ++ bus->parent = pfe->dev; ++ bus->phy_mask = mdio_info->phy_mask; ++ bus->irq[0] = mdio_info->irq[0]; ++ priv = bus->priv; ++ priv->mdio_base = cbus_emac_base[ii]; ++ ++ priv->mdc_div = mdio_info->mdc_div; ++ if (!priv->mdc_div) ++ priv->mdc_div = 64; ++ ++ dev_info(bus->parent, "%s: mdc_div: %d, phy_mask: %x\n", ++ __func__, priv->mdc_div, bus->phy_mask); ++ mdio_node = of_get_child_by_name(pfe->dev->of_node, "mdio"); ++ if ((mdio_info->id == 0) && mdio_node) { ++ rc = of_mdiobus_register(bus, mdio_node); ++ of_node_put(mdio_node); ++ } else { ++ rc = mdiobus_register(bus); ++ } ++ ++ if (rc) { ++ dev_err(bus->parent, "mdiobus_register(%s) failed\n", ++ bus->name); ++ goto err_mdioregister; ++ } ++ ++ priv->mii_bus = bus; ++ pfe->mdio.mdio_priv[ii] = priv; ++ ++ pfe_eth_mdio_reset(bus); ++ ++ return 0; ++ ++err_mdioregister: ++ mdiobus_free(bus); ++err_mdioalloc: ++ return rc; ++} ++ ++/* pfe_eth_mdio_exit ++ */ ++static void pfe_eth_mdio_exit(struct pfe *pfe, ++ int ii) ++{ ++ struct pfe_mdio_priv_s *mdio_priv = pfe->mdio.mdio_priv[ii]; ++ struct mii_bus *bus = mdio_priv->mii_bus; ++ ++ if (!bus) ++ return; ++ mdiobus_unregister(bus); ++ mdiobus_free(bus); ++} ++ ++/* pfe_get_phydev_speed ++ */ ++static int pfe_get_phydev_speed(struct phy_device *phydev) ++{ ++ switch (phydev->speed) { ++ case 10: ++ return SPEED_10M; ++ case 100: ++ return SPEED_100M; ++ case 1000: ++ default: ++ return SPEED_1000M; ++ } ++} ++ ++/* pfe_set_rgmii_speed ++ */ ++#define RGMIIPCR 0x434 ++/* RGMIIPCR bit definitions*/ ++#define SCFG_RGMIIPCR_EN_AUTO (0x00000008) ++#define SCFG_RGMIIPCR_SETSP_1000M (0x00000004) ++#define SCFG_RGMIIPCR_SETSP_100M (0x00000000) ++#define SCFG_RGMIIPCR_SETSP_10M (0x00000002) ++#define SCFG_RGMIIPCR_SETFD (0x00000001) ++ ++#define MDIOSELCR 0x484 ++#define MDIOSEL_SERDES 0x0 ++#define MDIOSEL_EXTPHY 0x80000000 ++ ++static void pfe_set_rgmii_speed(struct phy_device *phydev) ++{ ++ u32 rgmii_pcr; ++ ++ regmap_read(pfe->scfg, RGMIIPCR, &rgmii_pcr); ++ rgmii_pcr &= ~(SCFG_RGMIIPCR_SETSP_1000M | SCFG_RGMIIPCR_SETSP_10M); ++ ++ switch (phydev->speed) { ++ case 10: ++ rgmii_pcr |= SCFG_RGMIIPCR_SETSP_10M; ++ break; ++ case 1000: ++ rgmii_pcr |= SCFG_RGMIIPCR_SETSP_1000M; ++ break; ++ case 100: ++ default: ++ /* Default is 100M */ ++ break; ++ } ++ regmap_write(pfe->scfg, RGMIIPCR, rgmii_pcr); ++} ++ ++/* pfe_get_phydev_duplex ++ */ ++static int pfe_get_phydev_duplex(struct phy_device *phydev) ++{ ++ /*return (phydev->duplex == DUPLEX_HALF) ? DUP_HALF:DUP_FULL ; */ ++ return DUPLEX_FULL; ++} ++ ++/* pfe_eth_adjust_link ++ */ ++static void pfe_eth_adjust_link(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ unsigned long flags; ++ struct phy_device *phydev = priv->phydev; ++ int new_state = 0; ++ ++ netif_info(priv, drv, ndev, "%s\n", __func__); ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ ++ if (phydev->link) { ++ /* ++ * Now we make sure that we can be in full duplex mode. ++ * If not, we operate in half-duplex mode. ++ */ ++ if (phydev->duplex != priv->oldduplex) { ++ new_state = 1; ++ gemac_set_duplex(priv->EMAC_baseaddr, ++ pfe_get_phydev_duplex(phydev)); ++ priv->oldduplex = phydev->duplex; ++ } ++ ++ if (phydev->speed != priv->oldspeed) { ++ new_state = 1; ++ gemac_set_speed(priv->EMAC_baseaddr, ++ pfe_get_phydev_speed(phydev)); ++ if (priv->einfo->mii_config == ++ PHY_INTERFACE_MODE_RGMII_ID) ++ pfe_set_rgmii_speed(phydev); ++ priv->oldspeed = phydev->speed; ++ } ++ ++ if (!priv->oldlink) { ++ new_state = 1; ++ priv->oldlink = 1; ++ } ++ ++ } else if (priv->oldlink) { ++ new_state = 1; ++ priv->oldlink = 0; ++ priv->oldspeed = 0; ++ priv->oldduplex = -1; ++ } ++ ++ if (new_state && netif_msg_link(priv)) ++ phy_print_status(phydev); ++ ++ spin_unlock_irqrestore(&priv->lock, flags); ++ ++ /* Now, dump the details to the cdev. ++ * XXX: Locking would be required? (uniprocess arch) ++ * Or, maybe move it in spinlock above ++ */ ++ if (us && priv->einfo->gem_id < PFE_CDEV_ETH_COUNT) { ++ pr_debug("Changing link state from (%u) to (%u) for ID=(%u)\n", ++ link_states[priv->einfo->gem_id].state, ++ phydev->link, ++ priv->einfo->gem_id); ++ link_states[priv->einfo->gem_id].phy_id = priv->einfo->gem_id; ++ link_states[priv->einfo->gem_id].state = phydev->link; ++ } ++} ++ ++/* pfe_phy_exit ++ */ ++static void pfe_phy_exit(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ netif_info(priv, drv, ndev, "%s\n", __func__); ++ ++ phy_disconnect(priv->phydev); ++ priv->phydev = NULL; ++} ++ ++/* pfe_eth_stop ++ */ ++static void pfe_eth_stop(struct net_device *ndev, int wake) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ netif_info(priv, drv, ndev, "%s\n", __func__); ++ ++ if (wake) { ++ gemac_tx_disable(priv->EMAC_baseaddr); ++ } else { ++ gemac_disable(priv->EMAC_baseaddr); ++ gpi_disable(priv->GPI_baseaddr); ++ ++ if (priv->phydev) ++ phy_stop(priv->phydev); ++ } ++} ++ ++/* pfe_eth_start ++ */ ++static int pfe_eth_start(struct pfe_eth_priv_s *priv) ++{ ++ netif_info(priv, drv, priv->ndev, "%s\n", __func__); ++ ++ if (priv->phydev) ++ phy_start(priv->phydev); ++ ++ gpi_enable(priv->GPI_baseaddr); ++ gemac_enable(priv->EMAC_baseaddr); ++ ++ return 0; ++} ++ ++/* ++ * Configure on chip serdes through mdio ++ */ ++static void ls1012a_configure_serdes(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *eth_priv = netdev_priv(ndev); ++ struct pfe_mdio_priv_s *mdio_priv = pfe->mdio.mdio_priv[eth_priv->id]; ++ int sgmii_2500 = 0; ++ struct mii_bus *bus = mdio_priv->mii_bus; ++ u16 value = 0; ++ ++ if (eth_priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) ++ sgmii_2500 = 1; ++ ++ netif_info(eth_priv, drv, ndev, "%s\n", __func__); ++ /* PCS configuration done with corresponding GEMAC */ ++ ++ pfe_eth_mdio_read(bus, 0, MDIO_SGMII_CR); ++ pfe_eth_mdio_read(bus, 0, MDIO_SGMII_SR); ++ ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_CR, SGMII_CR_RST); ++ ++ if (sgmii_2500) { ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_IF_MODE, SGMII_SPEED_1GBPS ++ | SGMII_EN); ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_DEV_ABIL_SGMII, ++ SGMII_DEV_ABIL_ACK | SGMII_DEV_ABIL_SGMII); ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_LINK_TMR_L, 0xa120); ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_LINK_TMR_H, 0x7); ++ /* Autonegotiation need to be disabled for 2.5G SGMII mode*/ ++ value = SGMII_CR_FD | SGMII_CR_SPEED_SEL1_1G; ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_CR, value); ++ } else { ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_IF_MODE, ++ SGMII_SPEED_1GBPS ++ | SGMII_USE_SGMII_AN ++ | SGMII_EN); ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_DEV_ABIL_SGMII, ++ SGMII_DEV_ABIL_EEE_CLK_STP_EN ++ | 0xa0 ++ | SGMII_DEV_ABIL_SGMII); ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_LINK_TMR_L, 0x400); ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_LINK_TMR_H, 0x0); ++ value = SGMII_CR_AN_EN | SGMII_CR_FD | SGMII_CR_SPEED_SEL1_1G; ++ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_CR, value); ++ } ++} ++ ++/* ++ * pfe_phy_init ++ * ++ */ ++static int pfe_phy_init(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ struct phy_device *phydev; ++ char phy_id[MII_BUS_ID_SIZE + 3]; ++ char bus_id[MII_BUS_ID_SIZE]; ++ phy_interface_t interface; ++ ++ priv->oldlink = 0; ++ priv->oldspeed = 0; ++ priv->oldduplex = -1; ++ ++ snprintf(bus_id, MII_BUS_ID_SIZE, "ls1012a-%d", 0); ++ snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, ++ priv->einfo->phy_id); ++ netif_info(priv, drv, ndev, "%s: %s\n", __func__, phy_id); ++ interface = priv->einfo->mii_config; ++ if ((interface == PHY_INTERFACE_MODE_SGMII) || ++ (interface == PHY_INTERFACE_MODE_2500SGMII)) { ++ /*Configure SGMII PCS */ ++ if (pfe->scfg) { ++ /* Config MDIO from serdes */ ++ regmap_write(pfe->scfg, MDIOSELCR, MDIOSEL_SERDES); ++ } ++ ls1012a_configure_serdes(ndev); ++ } ++ ++ if (pfe->scfg) { ++ /*Config MDIO from PAD */ ++ regmap_write(pfe->scfg, MDIOSELCR, MDIOSEL_EXTPHY); ++ } ++ ++ priv->oldlink = 0; ++ priv->oldspeed = 0; ++ priv->oldduplex = -1; ++ pr_info("%s interface %x\n", __func__, interface); ++ ++ if (priv->phy_node) { ++ phydev = of_phy_connect(ndev, priv->phy_node, ++ pfe_eth_adjust_link, 0, ++ priv->einfo->mii_config); ++ if (!(phydev)) { ++ netdev_err(ndev, "Unable to connect to phy\n"); ++ return -ENODEV; ++ } ++ ++ } else { ++ phydev = phy_connect(ndev, phy_id, ++ &pfe_eth_adjust_link, interface); ++ if (IS_ERR(phydev)) { ++ netdev_err(ndev, "Unable to connect to phy\n"); ++ return PTR_ERR(phydev); ++ } ++ } ++ ++ priv->phydev = phydev; ++ phydev->irq = PHY_POLL; ++ ++ return 0; ++} ++ ++/* pfe_gemac_init ++ */ ++static int pfe_gemac_init(struct pfe_eth_priv_s *priv) ++{ ++ struct gemac_cfg cfg; ++ ++ netif_info(priv, ifup, priv->ndev, "%s\n", __func__); ++ ++ cfg.mode = 0; ++ cfg.speed = SPEED_1000M; ++ cfg.duplex = DUPLEX_FULL; ++ ++ gemac_set_config(priv->EMAC_baseaddr, &cfg); ++ gemac_allow_broadcast(priv->EMAC_baseaddr); ++ gemac_enable_1536_rx(priv->EMAC_baseaddr); ++ gemac_enable_stacked_vlan(priv->EMAC_baseaddr); ++ gemac_enable_pause_rx(priv->EMAC_baseaddr); ++ gemac_set_bus_width(priv->EMAC_baseaddr, 64); ++ ++ /*GEM will perform checksum verifications*/ ++ if (priv->ndev->features & NETIF_F_RXCSUM) ++ gemac_enable_rx_checksum_offload(priv->EMAC_baseaddr); ++ else ++ gemac_disable_rx_checksum_offload(priv->EMAC_baseaddr); ++ ++ return 0; ++} ++ ++/* pfe_eth_event_handler ++ */ ++static int pfe_eth_event_handler(void *data, int event, int qno) ++{ ++ struct pfe_eth_priv_s *priv = data; ++ ++ switch (event) { ++ case EVENT_RX_PKT_IND: ++ ++ if (qno == 0) { ++ if (napi_schedule_prep(&priv->high_napi)) { ++ netif_info(priv, intr, priv->ndev, ++ "%s: schedule high prio poll\n" ++ , __func__); ++ ++#ifdef PFE_ETH_NAPI_STATS ++ priv->napi_counters[NAPI_SCHED_COUNT]++; ++#endif ++ ++ __napi_schedule(&priv->high_napi); ++ } ++ } else if (qno == 1) { ++ if (napi_schedule_prep(&priv->low_napi)) { ++ netif_info(priv, intr, priv->ndev, ++ "%s: schedule low prio poll\n" ++ , __func__); ++ ++#ifdef PFE_ETH_NAPI_STATS ++ priv->napi_counters[NAPI_SCHED_COUNT]++; ++#endif ++ __napi_schedule(&priv->low_napi); ++ } ++ } else if (qno == 2) { ++ if (napi_schedule_prep(&priv->lro_napi)) { ++ netif_info(priv, intr, priv->ndev, ++ "%s: schedule lro prio poll\n" ++ , __func__); ++ ++#ifdef PFE_ETH_NAPI_STATS ++ priv->napi_counters[NAPI_SCHED_COUNT]++; ++#endif ++ __napi_schedule(&priv->lro_napi); ++ } ++ } ++ ++ break; ++ ++ case EVENT_TXDONE_IND: ++ pfe_eth_flush_tx(priv); ++ hif_lib_event_handler_start(&priv->client, EVENT_TXDONE_IND, 0); ++ break; ++ case EVENT_HIGH_RX_WM: ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int pfe_eth_change_mtu(struct net_device *ndev, int new_mtu) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ ndev->mtu = new_mtu; ++ new_mtu += ETH_HLEN + ETH_FCS_LEN; ++ gemac_set_rx_max_fl(priv->EMAC_baseaddr, new_mtu); ++ ++ return 0; ++} ++ ++/* pfe_eth_open ++ */ ++static int pfe_eth_open(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ struct hif_client_s *client; ++ int rc; ++ ++ netif_info(priv, ifup, ndev, "%s\n", __func__); ++ ++ /* Register client driver with HIF */ ++ client = &priv->client; ++ memset(client, 0, sizeof(*client)); ++ client->id = PFE_CL_GEM0 + priv->id; ++ client->tx_qn = emac_txq_cnt; ++ client->rx_qn = EMAC_RXQ_CNT; ++ client->priv = priv; ++ client->pfe = priv->pfe; ++ client->event_handler = pfe_eth_event_handler; ++ ++ client->tx_qsize = EMAC_TXQ_DEPTH; ++ client->rx_qsize = EMAC_RXQ_DEPTH; ++ ++ rc = hif_lib_client_register(client); ++ if (rc) { ++ netdev_err(ndev, "%s: hif_lib_client_register(%d) failed\n", ++ __func__, client->id); ++ goto err0; ++ } ++ ++ netif_info(priv, drv, ndev, "%s: registered client: %p\n", __func__, ++ client); ++ ++ pfe_gemac_init(priv); ++ ++ if (!is_valid_ether_addr(ndev->dev_addr)) { ++ netdev_err(ndev, "%s: invalid MAC address\n", __func__); ++ rc = -EADDRNOTAVAIL; ++ goto err1; ++ } ++ ++ gemac_set_laddrN(priv->EMAC_baseaddr, ++ (struct pfe_mac_addr *)ndev->dev_addr, 1); ++ ++ napi_enable(&priv->high_napi); ++ napi_enable(&priv->low_napi); ++ napi_enable(&priv->lro_napi); ++ ++ rc = pfe_eth_start(priv); ++ ++ netif_tx_wake_all_queues(ndev); ++ ++ return rc; ++ ++err1: ++ hif_lib_client_unregister(&priv->client); ++ ++err0: ++ return rc; ++} ++ ++/* ++ * pfe_eth_shutdown ++ */ ++static int pfe_eth_shutdown(struct net_device *ndev, int wake) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ int i, qstatus, id; ++ unsigned long next_poll = jiffies + 1, end = jiffies + ++ (TX_POLL_TIMEOUT_MS * HZ) / 1000; ++ int tx_pkts, prv_tx_pkts; ++ ++ netif_info(priv, ifdown, ndev, "%s\n", __func__); ++ ++ for (i = 0; i < emac_txq_cnt; i++) ++ hrtimer_cancel(&priv->fast_tx_timeout[i].timer); ++ ++ netif_tx_stop_all_queues(ndev); ++ ++ do { ++ tx_pkts = 0; ++ pfe_eth_flush_tx(priv); ++ ++ for (i = 0; i < emac_txq_cnt; i++) ++ tx_pkts += hif_lib_tx_pending(&priv->client, i); ++ ++ if (tx_pkts) { ++ /*Don't wait forever, break if we cross max timeout */ ++ if (time_after(jiffies, end)) { ++ pr_err( ++ "(%s)Tx is not complete after %dmsec\n", ++ ndev->name, TX_POLL_TIMEOUT_MS); ++ break; ++ } ++ ++ pr_info("%s : (%s) Waiting for tx packets to free. Pending tx pkts = %d.\n" ++ , __func__, ndev->name, tx_pkts); ++ if (need_resched()) ++ schedule(); ++ } ++ ++ } while (tx_pkts); ++ ++ end = jiffies + (TX_POLL_TIMEOUT_MS * HZ) / 1000; ++ ++ prv_tx_pkts = tmu_pkts_processed(priv->id); ++ /* ++ * Wait till TMU transmits all pending packets ++ * poll tmu_qstatus and pkts processed by TMU for every 10ms ++ * Consider TMU is busy, If we see TMU qeueu pending or any packets ++ * processed by TMU ++ */ ++ while (1) { ++ if (time_after(jiffies, next_poll)) { ++ tx_pkts = tmu_pkts_processed(priv->id); ++ qstatus = tmu_qstatus(priv->id) & 0x7ffff; ++ ++ if (!qstatus && (tx_pkts == prv_tx_pkts)) ++ break; ++ /* Don't wait forever, break if we cross max ++ * timeout(TX_POLL_TIMEOUT_MS) ++ */ ++ if (time_after(jiffies, end)) { ++ pr_err("TMU%d is busy after %dmsec\n", ++ priv->id, TX_POLL_TIMEOUT_MS); ++ break; ++ } ++ prv_tx_pkts = tx_pkts; ++ next_poll++; ++ } ++ if (need_resched()) ++ schedule(); ++ } ++ /* Wait for some more time to complete transmitting packet if any */ ++ next_poll = jiffies + 1; ++ while (1) { ++ if (time_after(jiffies, next_poll)) ++ break; ++ if (need_resched()) ++ schedule(); ++ } ++ ++ pfe_eth_stop(ndev, wake); ++ ++ napi_disable(&priv->lro_napi); ++ napi_disable(&priv->low_napi); ++ napi_disable(&priv->high_napi); ++ ++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { ++ pe_dmem_write(id, 0, CLASS_DM_CRC_VALIDATED ++ + (priv->id * 4), 4); ++ } ++ ++ hif_lib_client_unregister(&priv->client); ++ ++ return 0; ++} ++ ++/* pfe_eth_close ++ * ++ */ ++static int pfe_eth_close(struct net_device *ndev) ++{ ++ pfe_eth_shutdown(ndev, 0); ++ ++ return 0; ++} ++ ++/* pfe_eth_suspend ++ * ++ * return value : 1 if netdevice is configured to wakeup system ++ * 0 otherwise ++ */ ++int pfe_eth_suspend(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ int retval = 0; ++ ++ if (priv->wol) { ++ gemac_set_wol(priv->EMAC_baseaddr, priv->wol); ++ retval = 1; ++ } ++ pfe_eth_shutdown(ndev, priv->wol); ++ ++ return retval; ++} ++ ++/* pfe_eth_resume ++ * ++ */ ++int pfe_eth_resume(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ if (priv->wol) ++ gemac_set_wol(priv->EMAC_baseaddr, 0); ++ gemac_tx_enable(priv->EMAC_baseaddr); ++ ++ return pfe_eth_open(ndev); ++} ++ ++/* pfe_eth_get_queuenum ++ */ ++static int pfe_eth_get_queuenum(struct pfe_eth_priv_s *priv, struct sk_buff ++ *skb) ++{ ++ int queuenum = 0; ++ unsigned long flags; ++ ++ /* Get the Fast Path queue number */ ++ /* ++ * Use conntrack mark (if conntrack exists), then packet mark (if any), ++ * then fallback to default ++ */ ++#if defined(CONFIG_IP_NF_CONNTRACK_MARK) || defined(CONFIG_NF_CONNTRACK_MARK) ++ if (skb->_nfct) { ++ enum ip_conntrack_info cinfo; ++ struct nf_conn *ct; ++ ++ ct = nf_ct_get(skb, &cinfo); ++ ++ if (ct) { ++ u32 connmark; ++ ++ connmark = ct->mark; ++ ++ if ((connmark & 0x80000000) && priv->id != 0) ++ connmark >>= 16; ++ ++ queuenum = connmark & EMAC_QUEUENUM_MASK; ++ } ++ } else {/* continued after #endif ... */ ++#endif ++ if (skb->mark) { ++ queuenum = skb->mark & EMAC_QUEUENUM_MASK; ++ } else { ++ spin_lock_irqsave(&priv->lock, flags); ++ queuenum = priv->default_priority & EMAC_QUEUENUM_MASK; ++ spin_unlock_irqrestore(&priv->lock, flags); ++ } ++#if defined(CONFIG_IP_NF_CONNTRACK_MARK) || defined(CONFIG_NF_CONNTRACK_MARK) ++ } ++#endif ++ return queuenum; ++} ++ ++/* pfe_eth_might_stop_tx ++ * ++ */ ++static int pfe_eth_might_stop_tx(struct pfe_eth_priv_s *priv, int queuenum, ++ struct netdev_queue *tx_queue, ++ unsigned int n_desc, ++ unsigned int n_segs) ++{ ++ ktime_t kt; ++ int tried = 0; ++ ++try_again: ++ if (unlikely((__hif_tx_avail(&pfe->hif) < n_desc) || ++ (hif_lib_tx_avail(&priv->client, queuenum) < n_desc) || ++ (hif_lib_tx_credit_avail(pfe, priv->id, queuenum) < n_segs))) { ++ if (!tried) { ++ __hif_lib_update_credit(&priv->client, queuenum); ++ tried = 1; ++ goto try_again; ++ } ++#ifdef PFE_ETH_TX_STATS ++ if (__hif_tx_avail(&pfe->hif) < n_desc) { ++ priv->stop_queue_hif[queuenum]++; ++ } else if (hif_lib_tx_avail(&priv->client, queuenum) < n_desc) { ++ priv->stop_queue_hif_client[queuenum]++; ++ } else if (hif_lib_tx_credit_avail(pfe, priv->id, queuenum) < ++ n_segs) { ++ priv->stop_queue_credit[queuenum]++; ++ } ++ priv->stop_queue_total[queuenum]++; ++#endif ++ netif_tx_stop_queue(tx_queue); ++ ++ kt = ktime_set(0, LS1012A_TX_FAST_RECOVERY_TIMEOUT_MS * ++ NSEC_PER_MSEC); ++ hrtimer_start(&priv->fast_tx_timeout[queuenum].timer, kt, ++ HRTIMER_MODE_REL); ++ return -1; ++ } else { ++ return 0; ++ } ++} ++ ++#define SA_MAX_OP 2 ++/* pfe_hif_send_packet ++ * ++ * At this level if TX fails we drop the packet ++ */ ++static void pfe_hif_send_packet(struct sk_buff *skb, struct pfe_eth_priv_s ++ *priv, int queuenum) ++{ ++ struct skb_shared_info *sh = skb_shinfo(skb); ++ unsigned int nr_frags; ++ u32 ctrl = 0; ++ ++ netif_info(priv, tx_queued, priv->ndev, "%s\n", __func__); ++ ++ if (skb_is_gso(skb)) { ++ priv->stats.tx_dropped++; ++ return; ++ } ++ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) ++ ctrl = HIF_CTRL_TX_CHECKSUM; ++ ++ nr_frags = sh->nr_frags; ++ ++ if (nr_frags) { ++ skb_frag_t *f; ++ int i; ++ ++ __hif_lib_xmit_pkt(&priv->client, queuenum, skb->data, ++ skb_headlen(skb), ctrl, HIF_FIRST_BUFFER, ++ skb); ++ ++ for (i = 0; i < nr_frags - 1; i++) { ++ f = &sh->frags[i]; ++ __hif_lib_xmit_pkt(&priv->client, queuenum, ++ skb_frag_address(f), ++ skb_frag_size(f), ++ 0x0, 0x0, skb); ++ } ++ ++ f = &sh->frags[i]; ++ ++ __hif_lib_xmit_pkt(&priv->client, queuenum, ++ skb_frag_address(f), skb_frag_size(f), ++ 0x0, HIF_LAST_BUFFER | HIF_DATA_VALID, ++ skb); ++ ++ netif_info(priv, tx_queued, priv->ndev, ++ "%s: pkt sent successfully skb:%p nr_frags:%d len:%d\n", ++ __func__, skb, nr_frags, skb->len); ++ } else { ++ __hif_lib_xmit_pkt(&priv->client, queuenum, skb->data, ++ skb->len, ctrl, HIF_FIRST_BUFFER | ++ HIF_LAST_BUFFER | HIF_DATA_VALID, ++ skb); ++ netif_info(priv, tx_queued, priv->ndev, ++ "%s: pkt sent successfully skb:%p len:%d\n", ++ __func__, skb, skb->len); ++ } ++ hif_tx_dma_start(); ++ priv->stats.tx_packets++; ++ priv->stats.tx_bytes += skb->len; ++ hif_lib_tx_credit_use(pfe, priv->id, queuenum, 1); ++} ++ ++/* pfe_eth_flush_txQ ++ */ ++static void pfe_eth_flush_txQ(struct pfe_eth_priv_s *priv, int tx_q_num, int ++ from_tx, int n_desc) ++{ ++ struct sk_buff *skb; ++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, ++ tx_q_num); ++ unsigned int flags; ++ ++ netif_info(priv, tx_done, priv->ndev, "%s\n", __func__); ++ ++ if (!from_tx) ++ __netif_tx_lock_bh(tx_queue); ++ ++ /* Clean HIF and client queue */ ++ while ((skb = hif_lib_tx_get_next_complete(&priv->client, ++ tx_q_num, &flags, ++ HIF_TX_DESC_NT))) { ++ if (flags & HIF_DATA_VALID) ++ dev_kfree_skb_any(skb); ++ } ++ if (!from_tx) ++ __netif_tx_unlock_bh(tx_queue); ++} ++ ++/* pfe_eth_flush_tx ++ */ ++static void pfe_eth_flush_tx(struct pfe_eth_priv_s *priv) ++{ ++ int ii; ++ ++ netif_info(priv, tx_done, priv->ndev, "%s\n", __func__); ++ ++ for (ii = 0; ii < emac_txq_cnt; ii++) { ++ pfe_eth_flush_txQ(priv, ii, 0, 0); ++ __hif_lib_update_credit(&priv->client, ii); ++ } ++} ++ ++static void pfe_tx_get_req_desc(struct sk_buff *skb, unsigned int *n_desc, unsigned int ++ *n_segs) ++{ ++ struct skb_shared_info *sh = skb_shinfo(skb); ++ ++ /* Scattered data */ ++ if (sh->nr_frags) { ++ *n_desc = sh->nr_frags + 1; ++ *n_segs = 1; ++ /* Regular case */ ++ } else { ++ *n_desc = 1; ++ *n_segs = 1; ++ } ++} ++ ++/* pfe_eth_send_packet ++ */ ++static int pfe_eth_send_packet(struct sk_buff *skb, struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ int tx_q_num = skb_get_queue_mapping(skb); ++ int n_desc, n_segs; ++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, ++ tx_q_num); ++ ++ netif_info(priv, tx_queued, ndev, "%s\n", __func__); ++ ++ if ((!skb_is_gso(skb)) && (skb_headroom(skb) < (PFE_PKT_HEADER_SZ + ++ sizeof(unsigned long)))) { ++ netif_warn(priv, tx_err, priv->ndev, "%s: copying skb\n", ++ __func__); ++ ++ if (pskb_expand_head(skb, (PFE_PKT_HEADER_SZ + sizeof(unsigned ++ long)), 0, GFP_ATOMIC)) { ++ /* No need to re-transmit, no way to recover*/ ++ kfree_skb(skb); ++ priv->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++ } ++ } ++ ++ pfe_tx_get_req_desc(skb, &n_desc, &n_segs); ++ ++ hif_tx_lock(&pfe->hif); ++ if (unlikely(pfe_eth_might_stop_tx(priv, tx_q_num, tx_queue, n_desc, ++ n_segs))) { ++#ifdef PFE_ETH_TX_STATS ++ if (priv->was_stopped[tx_q_num]) { ++ priv->clean_fail[tx_q_num]++; ++ priv->was_stopped[tx_q_num] = 0; ++ } ++#endif ++ hif_tx_unlock(&pfe->hif); ++ return NETDEV_TX_BUSY; ++ } ++ ++ pfe_hif_send_packet(skb, priv, tx_q_num); ++ ++ hif_tx_unlock(&pfe->hif); ++ ++ tx_queue->trans_start = jiffies; ++ ++#ifdef PFE_ETH_TX_STATS ++ priv->was_stopped[tx_q_num] = 0; ++#endif ++ ++ return NETDEV_TX_OK; ++} ++ ++/* pfe_eth_select_queue ++ * ++ */ ++static u16 pfe_eth_select_queue(struct net_device *ndev, struct sk_buff *skb, ++ struct net_device *sb_dev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ return pfe_eth_get_queuenum(priv, skb); ++} ++ ++/* pfe_eth_get_stats ++ */ ++static struct net_device_stats *pfe_eth_get_stats(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ ++ netif_info(priv, drv, ndev, "%s\n", __func__); ++ ++ return &priv->stats; ++} ++ ++/* pfe_eth_set_mac_address ++ */ ++static int pfe_eth_set_mac_address(struct net_device *ndev, void *addr) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ struct sockaddr *sa = addr; ++ ++ netif_info(priv, drv, ndev, "%s\n", __func__); ++ ++ if (!is_valid_ether_addr(sa->sa_data)) ++ return -EADDRNOTAVAIL; ++ ++ dev_addr_set(ndev, sa->sa_data); ++ ++ gemac_set_laddrN(priv->EMAC_baseaddr, ++ (struct pfe_mac_addr *)ndev->dev_addr, 1); ++ ++ return 0; ++} ++ ++/* pfe_eth_enet_addr_byte_mac ++ */ ++static int pfe_eth_enet_addr_byte_mac(u8 *enet_byte_addr, ++ struct pfe_mac_addr *enet_addr) ++{ ++ if (!enet_byte_addr || !enet_addr) { ++ return -1; ++ ++ } else { ++ enet_addr->bottom = enet_byte_addr[0] | ++ (enet_byte_addr[1] << 8) | ++ (enet_byte_addr[2] << 16) | ++ (enet_byte_addr[3] << 24); ++ enet_addr->top = enet_byte_addr[4] | ++ (enet_byte_addr[5] << 8); ++ return 0; ++ } ++} ++ ++/* pfe_eth_set_multi ++ */ ++static void pfe_eth_set_multi(struct net_device *ndev) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ struct pfe_mac_addr hash_addr; /* hash register structure */ ++ /* specific mac address register structure */ ++ struct pfe_mac_addr spec_addr; ++ int result; /* index into hash register to set.. */ ++ int uc_count = 0; ++ struct netdev_hw_addr *ha; ++ ++ if (ndev->flags & IFF_PROMISC) { ++ netif_info(priv, drv, ndev, "entering promiscuous mode\n"); ++ ++ priv->promisc = 1; ++ gemac_enable_copy_all(priv->EMAC_baseaddr); ++ } else { ++ priv->promisc = 0; ++ gemac_disable_copy_all(priv->EMAC_baseaddr); ++ } ++ ++ /* Enable broadcast frame reception if required. */ ++ if (ndev->flags & IFF_BROADCAST) { ++ gemac_allow_broadcast(priv->EMAC_baseaddr); ++ } else { ++ netif_info(priv, drv, ndev, ++ "disabling broadcast frame reception\n"); ++ ++ gemac_no_broadcast(priv->EMAC_baseaddr); ++ } ++ ++ if (ndev->flags & IFF_ALLMULTI) { ++ /* Set the hash to rx all multicast frames */ ++ hash_addr.bottom = 0xFFFFFFFF; ++ hash_addr.top = 0xFFFFFFFF; ++ gemac_set_hash(priv->EMAC_baseaddr, &hash_addr); ++ netdev_for_each_uc_addr(ha, ndev) { ++ if (uc_count >= MAX_UC_SPEC_ADDR_REG) ++ break; ++ pfe_eth_enet_addr_byte_mac(ha->addr, &spec_addr); ++ gemac_set_laddrN(priv->EMAC_baseaddr, &spec_addr, ++ uc_count + 2); ++ uc_count++; ++ } ++ } else if ((netdev_mc_count(ndev) > 0) || (netdev_uc_count(ndev))) { ++ u8 *addr; ++ ++ hash_addr.bottom = 0; ++ hash_addr.top = 0; ++ ++ netdev_for_each_mc_addr(ha, ndev) { ++ addr = ha->addr; ++ ++ netif_info(priv, drv, ndev, ++ "adding multicast address %X:%X:%X:%X:%X:%X to gem filter\n", ++ addr[0], addr[1], addr[2], ++ addr[3], addr[4], addr[5]); ++ ++ result = pfe_eth_get_hash(addr); ++ ++ if (result < EMAC_HASH_REG_BITS) { ++ if (result < 32) ++ hash_addr.bottom |= (1 << result); ++ else ++ hash_addr.top |= (1 << (result - 32)); ++ } else { ++ break; ++ } ++ } ++ ++ uc_count = -1; ++ netdev_for_each_uc_addr(ha, ndev) { ++ addr = ha->addr; ++ ++ if (++uc_count < MAX_UC_SPEC_ADDR_REG) { ++ netdev_info(ndev, ++ "adding unicast address %02x:%02x:%02x:%02x:%02x:%02x to gem filter\n", ++ addr[0], addr[1], addr[2], ++ addr[3], addr[4], addr[5]); ++ pfe_eth_enet_addr_byte_mac(addr, &spec_addr); ++ gemac_set_laddrN(priv->EMAC_baseaddr, ++ &spec_addr, uc_count + 2); ++ } else { ++ netif_info(priv, drv, ndev, ++ "adding unicast address %02x:%02x:%02x:%02x:%02x:%02x to gem hash\n", ++ addr[0], addr[1], addr[2], ++ addr[3], addr[4], addr[5]); ++ ++ result = pfe_eth_get_hash(addr); ++ if (result >= EMAC_HASH_REG_BITS) { ++ break; ++ ++ } else { ++ if (result < 32) ++ hash_addr.bottom |= (1 << ++ result); ++ else ++ hash_addr.top |= (1 << ++ (result - 32)); ++ } ++ } ++ } ++ ++ gemac_set_hash(priv->EMAC_baseaddr, &hash_addr); ++ } ++ ++ if (!(netdev_uc_count(ndev) >= MAX_UC_SPEC_ADDR_REG)) { ++ /* ++ * Check if there are any specific address HW registers that ++ * need to be flushed ++ */ ++ for (uc_count = netdev_uc_count(ndev); uc_count < ++ MAX_UC_SPEC_ADDR_REG; uc_count++) ++ gemac_clear_laddrN(priv->EMAC_baseaddr, uc_count + 2); ++ } ++ ++ if (ndev->flags & IFF_LOOPBACK) ++ gemac_set_loop(priv->EMAC_baseaddr, LB_LOCAL); ++} ++ ++/* pfe_eth_set_features ++ */ ++static int pfe_eth_set_features(struct net_device *ndev, netdev_features_t ++ features) ++{ ++ struct pfe_eth_priv_s *priv = netdev_priv(ndev); ++ int rc = 0; ++ ++ if (features & NETIF_F_RXCSUM) ++ gemac_enable_rx_checksum_offload(priv->EMAC_baseaddr); ++ else ++ gemac_disable_rx_checksum_offload(priv->EMAC_baseaddr); ++ return rc; ++} ++ ++/* pfe_eth_fast_tx_timeout ++ */ ++static enum hrtimer_restart pfe_eth_fast_tx_timeout(struct hrtimer *timer) ++{ ++ struct pfe_eth_fast_timer *fast_tx_timeout = container_of(timer, struct ++ pfe_eth_fast_timer, ++ timer); ++ struct pfe_eth_priv_s *priv = container_of(fast_tx_timeout->base, ++ struct pfe_eth_priv_s, ++ fast_tx_timeout); ++ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, ++ fast_tx_timeout->queuenum); ++ ++ if (netif_tx_queue_stopped(tx_queue)) { ++#ifdef PFE_ETH_TX_STATS ++ priv->was_stopped[fast_tx_timeout->queuenum] = 1; ++#endif ++ netif_tx_wake_queue(tx_queue); ++ } ++ ++ return HRTIMER_NORESTART; ++} ++ ++/* pfe_eth_fast_tx_timeout_init ++ */ ++static void pfe_eth_fast_tx_timeout_init(struct pfe_eth_priv_s *priv) ++{ ++ int i; ++ ++ for (i = 0; i < emac_txq_cnt; i++) { ++ priv->fast_tx_timeout[i].queuenum = i; ++ hrtimer_init(&priv->fast_tx_timeout[i].timer, CLOCK_MONOTONIC, ++ HRTIMER_MODE_REL); ++ priv->fast_tx_timeout[i].timer.function = ++ pfe_eth_fast_tx_timeout; ++ priv->fast_tx_timeout[i].base = priv->fast_tx_timeout; ++ } ++} ++ ++static struct sk_buff *pfe_eth_rx_skb(struct net_device *ndev, ++ struct pfe_eth_priv_s *priv, ++ unsigned int qno) ++{ ++ void *buf_addr; ++ unsigned int rx_ctrl; ++ unsigned int desc_ctrl = 0; ++ struct hif_ipsec_hdr *ipsec_hdr = NULL; ++ struct sk_buff *skb; ++ struct sk_buff *skb_frag, *skb_frag_last = NULL; ++ int length = 0, offset; ++ ++ skb = priv->skb_inflight[qno]; ++ ++ if (skb) { ++ skb_frag_last = skb_shinfo(skb)->frag_list; ++ if (skb_frag_last) { ++ while (skb_frag_last->next) ++ skb_frag_last = skb_frag_last->next; ++ } ++ } ++ ++ while (!(desc_ctrl & CL_DESC_LAST)) { ++ buf_addr = hif_lib_receive_pkt(&priv->client, qno, &length, ++ &offset, &rx_ctrl, &desc_ctrl, ++ (void **)&ipsec_hdr); ++ if (!buf_addr) ++ goto incomplete; ++ ++#ifdef PFE_ETH_NAPI_STATS ++ priv->napi_counters[NAPI_DESC_COUNT]++; ++#endif ++ ++ /* First frag */ ++ if (desc_ctrl & CL_DESC_FIRST) { ++ skb = build_skb(buf_addr, 0); ++ if (unlikely(!skb)) ++ goto pkt_drop; ++ ++ skb_reserve(skb, offset); ++ skb_put(skb, length); ++ skb->dev = ndev; ++ ++ if ((ndev->features & NETIF_F_RXCSUM) && (rx_ctrl & ++ HIF_CTRL_RX_CHECKSUMMED)) ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ else ++ skb_checksum_none_assert(skb); ++ ++ } else { ++ /* Next frags */ ++ if (unlikely(!skb)) { ++ pr_err("%s: NULL skb_inflight\n", ++ __func__); ++ goto pkt_drop; ++ } ++ ++ skb_frag = build_skb(buf_addr, 0); ++ ++ if (unlikely(!skb_frag)) { ++ kfree(buf_addr); ++ goto pkt_drop; ++ } ++ ++ skb_reserve(skb_frag, offset); ++ skb_put(skb_frag, length); ++ ++ skb_frag->dev = ndev; ++ ++ if (skb_shinfo(skb)->frag_list) ++ skb_frag_last->next = skb_frag; ++ else ++ skb_shinfo(skb)->frag_list = skb_frag; ++ ++ skb->truesize += skb_frag->truesize; ++ skb->data_len += length; ++ skb->len += length; ++ skb_frag_last = skb_frag; ++ } ++ } ++ ++ priv->skb_inflight[qno] = NULL; ++ return skb; ++ ++incomplete: ++ priv->skb_inflight[qno] = skb; ++ return NULL; ++ ++pkt_drop: ++ priv->skb_inflight[qno] = NULL; ++ ++ if (skb) ++ kfree_skb(skb); ++ else ++ kfree(buf_addr); ++ ++ priv->stats.rx_errors++; ++ ++ return NULL; ++} ++ ++/* pfe_eth_poll ++ */ ++static int pfe_eth_poll(struct pfe_eth_priv_s *priv, struct napi_struct *napi, ++ unsigned int qno, int budget) ++{ ++ struct net_device *ndev = priv->ndev; ++ struct sk_buff *skb; ++ int work_done = 0; ++ unsigned int len; ++ ++ netif_info(priv, intr, priv->ndev, "%s\n", __func__); ++ ++#ifdef PFE_ETH_NAPI_STATS ++ priv->napi_counters[NAPI_POLL_COUNT]++; ++#endif ++ ++ do { ++ skb = pfe_eth_rx_skb(ndev, priv, qno); ++ ++ if (!skb) ++ break; ++ ++ len = skb->len; ++ ++ /* Packet will be processed */ ++ skb->protocol = eth_type_trans(skb, ndev); ++ ++ netif_receive_skb(skb); ++ ++ priv->stats.rx_packets++; ++ priv->stats.rx_bytes += len; ++ ++ work_done++; ++ ++#ifdef PFE_ETH_NAPI_STATS ++ priv->napi_counters[NAPI_PACKET_COUNT]++; ++#endif ++ ++ } while (work_done < budget); ++ ++ /* ++ * If no Rx receive nor cleanup work was done, exit polling mode. ++ * No more netif_running(dev) check is required here , as this is ++ * checked in net/core/dev.c (2.6.33.5 kernel specific). ++ */ ++ if (work_done < budget) { ++ napi_complete(napi); ++ ++ hif_lib_event_handler_start(&priv->client, EVENT_RX_PKT_IND, ++ qno); ++ } ++#ifdef PFE_ETH_NAPI_STATS ++ else ++ priv->napi_counters[NAPI_FULL_BUDGET_COUNT]++; ++#endif ++ ++ return work_done; ++} ++ ++/* ++ * pfe_eth_lro_poll ++ */ ++static int pfe_eth_lro_poll(struct napi_struct *napi, int budget) ++{ ++ struct pfe_eth_priv_s *priv = container_of(napi, struct pfe_eth_priv_s, ++ lro_napi); ++ ++ netif_info(priv, intr, priv->ndev, "%s\n", __func__); ++ ++ return pfe_eth_poll(priv, napi, 2, budget); ++} ++ ++/* pfe_eth_low_poll ++ */ ++static int pfe_eth_low_poll(struct napi_struct *napi, int budget) ++{ ++ struct pfe_eth_priv_s *priv = container_of(napi, struct pfe_eth_priv_s, ++ low_napi); ++ ++ netif_info(priv, intr, priv->ndev, "%s\n", __func__); ++ ++ return pfe_eth_poll(priv, napi, 1, budget); ++} ++ ++/* pfe_eth_high_poll ++ */ ++static int pfe_eth_high_poll(struct napi_struct *napi, int budget) ++{ ++ struct pfe_eth_priv_s *priv = container_of(napi, struct pfe_eth_priv_s, ++ high_napi); ++ ++ netif_info(priv, intr, priv->ndev, "%s\n", __func__); ++ ++ return pfe_eth_poll(priv, napi, 0, budget); ++} ++ ++static const struct net_device_ops pfe_netdev_ops = { ++ .ndo_open = pfe_eth_open, ++ .ndo_stop = pfe_eth_close, ++ .ndo_start_xmit = pfe_eth_send_packet, ++ .ndo_select_queue = pfe_eth_select_queue, ++ .ndo_set_rx_mode = pfe_eth_set_multi, ++ .ndo_set_mac_address = pfe_eth_set_mac_address, ++ .ndo_validate_addr = eth_validate_addr, ++ .ndo_change_mtu = pfe_eth_change_mtu, ++ .ndo_get_stats = pfe_eth_get_stats, ++ .ndo_set_features = pfe_eth_set_features, ++}; ++ ++/* pfe_eth_init_one ++ */ ++static int pfe_eth_init_one(struct pfe *pfe, ++ struct ls1012a_pfe_platform_data *pfe_info, ++ int id) ++{ ++ struct net_device *ndev = NULL; ++ struct pfe_eth_priv_s *priv = NULL; ++ struct ls1012a_eth_platform_data *einfo; ++ int err; ++ ++ einfo = (struct ls1012a_eth_platform_data *) ++ pfe_info->ls1012a_eth_pdata; ++ ++ /* einfo never be NULL, but no harm in having this check */ ++ if (!einfo) { ++ pr_err( ++ "%s: pfe missing additional gemacs platform data\n" ++ , __func__); ++ err = -ENODEV; ++ goto err0; ++ } ++ ++ if (us) ++ emac_txq_cnt = EMAC_TXQ_CNT; ++ /* Create an ethernet device instance */ ++ ndev = alloc_etherdev_mq(sizeof(*priv), emac_txq_cnt); ++ ++ if (!ndev) { ++ pr_err("%s: gemac %d device allocation failed\n", ++ __func__, einfo[id].gem_id); ++ err = -ENOMEM; ++ goto err0; ++ } ++ ++ priv = netdev_priv(ndev); ++ priv->ndev = ndev; ++ priv->id = einfo[id].gem_id; ++ priv->pfe = pfe; ++ priv->phy_node = einfo[id].phy_node; ++ ++ SET_NETDEV_DEV(priv->ndev, priv->pfe->dev); ++ ++ pfe->eth.eth_priv[id] = priv; ++ ++ /* Set the info in the priv to the current info */ ++ priv->einfo = &einfo[id]; ++ priv->EMAC_baseaddr = cbus_emac_base[id]; ++ priv->GPI_baseaddr = cbus_gpi_base[id]; ++ ++ spin_lock_init(&priv->lock); ++ ++ pfe_eth_fast_tx_timeout_init(priv); ++ ++ /* Copy the station address into the dev structure, */ ++ dev_addr_set(ndev, einfo[id].mac_addr); ++ ++ if (us) ++ goto phy_init; ++ ++ ndev->mtu = 1500; ++ ++ /* Set MTU limits */ ++ ndev->min_mtu = ETH_MIN_MTU; ++ ++/* ++ * Jumbo frames are not supported on LS1012A rev-1.0. ++ * So max mtu should be restricted to supported frame length. ++ */ ++ if (pfe_errata_a010897) ++ ndev->max_mtu = JUMBO_FRAME_SIZE_V1 - ETH_HLEN - ETH_FCS_LEN; ++ else ++ ndev->max_mtu = JUMBO_FRAME_SIZE_V2 - ETH_HLEN - ETH_FCS_LEN; ++ ++ /*Enable after checksum offload is validated */ ++ ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | ++ NETIF_F_IPV6_CSUM | NETIF_F_SG; ++ ++ /* enabled by default */ ++ ndev->features = ndev->hw_features; ++ ++ priv->usr_features = ndev->features; ++ ++ ndev->netdev_ops = &pfe_netdev_ops; ++ ++ ndev->ethtool_ops = &pfe_ethtool_ops; ++ ++ /* Enable basic messages by default */ ++ priv->msg_enable = NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_LINK | ++ NETIF_MSG_PROBE; ++ ++ netif_napi_add(ndev, &priv->low_napi, pfe_eth_low_poll); ++ netif_napi_add(ndev, &priv->high_napi, pfe_eth_high_poll); ++ netif_napi_add(ndev, &priv->lro_napi, pfe_eth_lro_poll); ++ ++ err = register_netdev(ndev); ++ if (err) { ++ netdev_err(ndev, "register_netdev() failed\n"); ++ goto err1; ++ } ++ ++ if ((!(pfe_use_old_dts_phy) && !(priv->phy_node)) || ++ ((pfe_use_old_dts_phy) && ++ (priv->einfo->phy_flags & GEMAC_NO_PHY))) { ++ pr_info("%s: No PHY or fixed-link\n", __func__); ++ goto skip_phy_init; ++ } ++ ++phy_init: ++ device_init_wakeup(&ndev->dev, true); ++ ++ err = pfe_phy_init(ndev); ++ if (err) { ++ netdev_err(ndev, "%s: pfe_phy_init() failed\n", ++ __func__); ++ goto err2; ++ } ++ ++ if (us) { ++ if (priv->phydev) ++ phy_start(priv->phydev); ++ return 0; ++ } ++ ++ netif_carrier_on(ndev); ++ ++skip_phy_init: ++ /* Create all the sysfs files */ ++ if (pfe_eth_sysfs_init(ndev)) ++ goto err3; ++ ++ netif_info(priv, probe, ndev, "%s: created interface, baseaddr: %p\n", ++ __func__, priv->EMAC_baseaddr); ++ ++ return 0; ++ ++err3: ++ pfe_phy_exit(priv->ndev); ++err2: ++ if (us) ++ goto err1; ++ unregister_netdev(ndev); ++err1: ++ free_netdev(priv->ndev); ++err0: ++ return err; ++} ++ ++/* pfe_eth_init ++ */ ++int pfe_eth_init(struct pfe *pfe) ++{ ++ int ii = 0; ++ int err; ++ struct ls1012a_pfe_platform_data *pfe_info; ++ ++ pr_info("%s\n", __func__); ++ ++ cbus_emac_base[0] = EMAC1_BASE_ADDR; ++ cbus_emac_base[1] = EMAC2_BASE_ADDR; ++ ++ cbus_gpi_base[0] = EGPI1_BASE_ADDR; ++ cbus_gpi_base[1] = EGPI2_BASE_ADDR; ++ ++ pfe_info = (struct ls1012a_pfe_platform_data *) ++ pfe->dev->platform_data; ++ if (!pfe_info) { ++ pr_err("%s: pfe missing additional platform data\n", __func__); ++ err = -ENODEV; ++ goto err_pdata; ++ } ++ ++ for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) { ++ err = pfe_eth_mdio_init(pfe, pfe_info, ii); ++ if (err) { ++ pr_err("%s: pfe_eth_mdio_init() failed\n", __func__); ++ goto err_mdio_init; ++ } ++ } ++ ++ if (soc_device_match(ls1012a_rev1_soc_attr)) ++ pfe_errata_a010897 = true; ++ else ++ pfe_errata_a010897 = false; ++ ++ for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) { ++ err = pfe_eth_init_one(pfe, pfe_info, ii); ++ if (err) ++ goto err_eth_init; ++ } ++ ++ return 0; ++ ++err_eth_init: ++ while (ii--) { ++ pfe_eth_exit_one(pfe->eth.eth_priv[ii]); ++ pfe_eth_mdio_exit(pfe, ii); ++ } ++ ++err_mdio_init: ++err_pdata: ++ return err; ++} ++ ++/* pfe_eth_exit_one ++ */ ++static void pfe_eth_exit_one(struct pfe_eth_priv_s *priv) ++{ ++ netif_info(priv, probe, priv->ndev, "%s\n", __func__); ++ ++ if (!us) ++ pfe_eth_sysfs_exit(priv->ndev); ++ ++ if ((!(pfe_use_old_dts_phy) && !(priv->phy_node)) || ++ ((pfe_use_old_dts_phy) && ++ (priv->einfo->phy_flags & GEMAC_NO_PHY))) { ++ pr_info("%s: No PHY or fixed-link\n", __func__); ++ goto skip_phy_exit; ++ } ++ ++ pfe_phy_exit(priv->ndev); ++ ++skip_phy_exit: ++ if (!us) ++ unregister_netdev(priv->ndev); ++ ++ free_netdev(priv->ndev); ++} ++ ++/* pfe_eth_exit ++ */ ++void pfe_eth_exit(struct pfe *pfe) ++{ ++ int ii; ++ ++ pr_info("%s\n", __func__); ++ ++ for (ii = NUM_GEMAC_SUPPORT - 1; ii >= 0; ii--) ++ pfe_eth_exit_one(pfe->eth.eth_priv[ii]); ++ ++ for (ii = NUM_GEMAC_SUPPORT - 1; ii >= 0; ii--) ++ pfe_eth_mdio_exit(pfe, ii); ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_eth.h +@@ -0,0 +1,175 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#ifndef _PFE_ETH_H_ ++#define _PFE_ETH_H_ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PFE_ETH_NAPI_STATS ++#define PFE_ETH_TX_STATS ++ ++#define PFE_ETH_FRAGS_MAX (65536 / HIF_RX_PKT_MIN_SIZE) ++#define LRO_LEN_COUNT_MAX 32 ++#define LRO_NB_COUNT_MAX 32 ++ ++#define PFE_PAUSE_FLAG_ENABLE 1 ++#define PFE_PAUSE_FLAG_AUTONEG 2 ++ ++/* GEMAC configured by SW */ ++/* GEMAC configured by phy lines (not for MII/GMII) */ ++ ++#define GEMAC_SW_FULL_DUPLEX BIT(9) ++#define GEMAC_SW_SPEED_10M (0 << 12) ++#define GEMAC_SW_SPEED_100M BIT(12) ++#define GEMAC_SW_SPEED_1G (2 << 12) ++ ++#define GEMAC_NO_PHY BIT(0) ++ ++struct ls1012a_eth_platform_data { ++ /* board specific information */ ++ phy_interface_t mii_config; ++ u32 phy_flags; ++ u32 gem_id; ++ u32 phy_id; ++ u32 mdio_muxval; ++ u8 mac_addr[ETH_ALEN]; ++ struct device_node *phy_node; ++}; ++ ++struct ls1012a_mdio_platform_data { ++ int id; ++ int irq[32]; ++ u32 phy_mask; ++ int mdc_div; ++}; ++ ++struct ls1012a_pfe_platform_data { ++ struct ls1012a_eth_platform_data ls1012a_eth_pdata[3]; ++ struct ls1012a_mdio_platform_data ls1012a_mdio_pdata[3]; ++}; ++ ++#define NUM_GEMAC_SUPPORT 2 ++#define DRV_NAME "pfe-eth" ++#define DRV_VERSION "1.0" ++ ++#define LS1012A_TX_FAST_RECOVERY_TIMEOUT_MS 3 ++#define TX_POLL_TIMEOUT_MS 1000 ++ ++#define EMAC_TXQ_CNT 16 ++#define EMAC_TXQ_DEPTH (HIF_TX_DESC_NT) ++ ++#define JUMBO_FRAME_SIZE_V1 1900 ++#define JUMBO_FRAME_SIZE_V2 10258 ++/* ++ * Client Tx queue threshold, for txQ flush condition. ++ * It must be smaller than the queue size (in case we ever change it in the ++ * future). ++ */ ++#define HIF_CL_TX_FLUSH_MARK 32 ++ ++/* ++ * Max number of TX resources (HIF descriptors or skbs) that will be released ++ * in a single go during batch recycling. ++ * Should be lower than the flush mark so the SW can provide the HW with a ++ * continuous stream of packets instead of bursts. ++ */ ++#define TX_FREE_MAX_COUNT 16 ++#define EMAC_RXQ_CNT 3 ++#define EMAC_RXQ_DEPTH HIF_RX_DESC_NT ++/* make sure clients can receive a full burst of packets */ ++#define EMAC_RMON_TXBYTES_POS 0x00 ++#define EMAC_RMON_RXBYTES_POS 0x14 ++ ++#define EMAC_QUEUENUM_MASK (emac_txq_cnt - 1) ++#define EMAC_MDIO_TIMEOUT 1000 ++#define MAX_UC_SPEC_ADDR_REG 31 ++ ++struct pfe_eth_fast_timer { ++ int queuenum; ++ struct hrtimer timer; ++ void *base; ++}; ++ ++struct pfe_eth_priv_s { ++ struct pfe *pfe; ++ struct hif_client_s client; ++ struct napi_struct lro_napi; ++ struct napi_struct low_napi; ++ struct napi_struct high_napi; ++ int low_tmu_q; ++ int high_tmu_q; ++ struct net_device_stats stats; ++ struct net_device *ndev; ++ int id; ++ int promisc; ++ unsigned int msg_enable; ++ unsigned int usr_features; ++ ++ spinlock_t lock; /* protect member variables */ ++ unsigned int event_status; ++ int irq; ++ void *EMAC_baseaddr; ++ void *GPI_baseaddr; ++ /* PHY stuff */ ++ struct phy_device *phydev; ++ int oldspeed; ++ int oldduplex; ++ int oldlink; ++ struct device_node *phy_node; ++ struct clk *gemtx_clk; ++ int wol; ++ int pause_flag; ++ ++ int default_priority; ++ struct pfe_eth_fast_timer fast_tx_timeout[EMAC_TXQ_CNT]; ++ ++ struct ls1012a_eth_platform_data *einfo; ++ struct sk_buff *skb_inflight[EMAC_RXQ_CNT + 6]; ++ ++#ifdef PFE_ETH_TX_STATS ++ unsigned int stop_queue_total[EMAC_TXQ_CNT]; ++ unsigned int stop_queue_hif[EMAC_TXQ_CNT]; ++ unsigned int stop_queue_hif_client[EMAC_TXQ_CNT]; ++ unsigned int stop_queue_credit[EMAC_TXQ_CNT]; ++ unsigned int clean_fail[EMAC_TXQ_CNT]; ++ unsigned int was_stopped[EMAC_TXQ_CNT]; ++#endif ++ ++#ifdef PFE_ETH_NAPI_STATS ++ unsigned int napi_counters[NAPI_MAX_COUNT]; ++#endif ++ unsigned int frags_inflight[EMAC_RXQ_CNT + 6]; ++}; ++ ++struct pfe_eth { ++ struct pfe_eth_priv_s *eth_priv[3]; ++}; ++ ++struct pfe_mdio_priv_s { ++ void __iomem *mdio_base; ++ int mdc_div; ++ struct mii_bus *mii_bus; ++}; ++ ++struct pfe_mdio { ++ struct pfe_mdio_priv_s *mdio_priv[3]; ++}; ++ ++int pfe_eth_init(struct pfe *pfe); ++void pfe_eth_exit(struct pfe *pfe); ++int pfe_eth_suspend(struct net_device *dev); ++int pfe_eth_resume(struct net_device *dev); ++int pfe_eth_mdio_reset(struct mii_bus *bus); ++ ++#endif /* _PFE_ETH_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_firmware.c +@@ -0,0 +1,398 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++/* ++ * @file ++ * Contains all the functions to handle parsing and loading of PE firmware ++ * files. ++ */ ++#include ++ ++#include "pfe_mod.h" ++#include "pfe_firmware.h" ++#include "pfe/pfe.h" ++#include ++#include ++ ++static struct elf32_shdr *get_elf_section_header(const u8 *fw, ++ const char *section) ++{ ++ struct elf32_hdr *elf_hdr = (struct elf32_hdr *)fw; ++ struct elf32_shdr *shdr; ++ struct elf32_shdr *shdr_shstr; ++ Elf32_Off e_shoff = be32_to_cpu(elf_hdr->e_shoff); ++ Elf32_Half e_shentsize = be16_to_cpu(elf_hdr->e_shentsize); ++ Elf32_Half e_shnum = be16_to_cpu(elf_hdr->e_shnum); ++ Elf32_Half e_shstrndx = be16_to_cpu(elf_hdr->e_shstrndx); ++ Elf32_Off shstr_offset; ++ Elf32_Word sh_name; ++ const char *name; ++ int i; ++ ++ /* Section header strings */ ++ shdr_shstr = (struct elf32_shdr *)((u8 *)elf_hdr + e_shoff + e_shstrndx ++ * e_shentsize); ++ shstr_offset = be32_to_cpu(shdr_shstr->sh_offset); ++ ++ for (i = 0; i < e_shnum; i++) { ++ shdr = (struct elf32_shdr *)((u8 *)elf_hdr + e_shoff ++ + i * e_shentsize); ++ ++ sh_name = be32_to_cpu(shdr->sh_name); ++ ++ name = (const char *)((u8 *)elf_hdr + shstr_offset + sh_name); ++ ++ if (!strcmp(name, section)) ++ return shdr; ++ } ++ ++ pr_err("%s: didn't find section %s\n", __func__, section); ++ ++ return NULL; ++} ++ ++#if defined(CFG_DIAGS) ++static int pfe_get_diags_info(const u8 *fw, struct pfe_diags_info ++ *diags_info) ++{ ++ struct elf32_shdr *shdr; ++ unsigned long offset, size; ++ ++ shdr = get_elf_section_header(fw, ".pfe_diags_str"); ++ if (shdr) { ++ offset = be32_to_cpu(shdr->sh_offset); ++ size = be32_to_cpu(shdr->sh_size); ++ diags_info->diags_str_base = be32_to_cpu(shdr->sh_addr); ++ diags_info->diags_str_size = size; ++ diags_info->diags_str_array = kmalloc(size, GFP_KERNEL); ++ memcpy(diags_info->diags_str_array, fw + offset, size); ++ ++ return 0; ++ } else { ++ return -1; ++ } ++} ++#endif ++ ++static void pfe_check_version_info(const u8 *fw) ++{ ++ /*static char *version = NULL;*/ ++ const u8 *elf_data = fw; ++ static char *version; ++ ++ struct elf32_shdr *shdr = get_elf_section_header(fw, ".version"); ++ ++ if (shdr) { ++ if (!version) { ++ /* ++ * this is the first fw we load, use its version ++ * string as reference (whatever it is) ++ */ ++ version = (char *)(elf_data + ++ be32_to_cpu(shdr->sh_offset)); ++ ++ pr_info("PFE binary version: %s\n", version); ++ } else { ++ /* ++ * already have loaded at least one firmware, check ++ * sequence can start now ++ */ ++ if (strcmp(version, (char *)(elf_data + ++ be32_to_cpu(shdr->sh_offset)))) { ++ pr_info( ++ "WARNING: PFE firmware binaries from incompatible version\n"); ++ } ++ } ++ } else { ++ /* ++ * version cannot be verified, a potential issue that should ++ * be reported ++ */ ++ pr_info( ++ "WARNING: PFE firmware binaries from incompatible version\n"); ++ } ++} ++ ++/* PFE elf firmware loader. ++ * Loads an elf firmware image into a list of PE's (specified using a bitmask) ++ * ++ * @param pe_mask Mask of PE id's to load firmware to ++ * @param fw Pointer to the firmware image ++ * ++ * @return 0 on success, a negative value on error ++ * ++ */ ++static int pfe_load_elf(int pe_mask, const u8 *fw, struct pfe *pfe) ++{ ++ struct elf32_hdr *elf_hdr = (struct elf32_hdr *)fw; ++ Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum); ++ struct elf32_shdr *shdr = (struct elf32_shdr *)(fw + ++ be32_to_cpu(elf_hdr->e_shoff)); ++ int id, section; ++ int rc; ++ ++ pr_info("%s\n", __func__); ++ ++ /* Some sanity checks */ ++ if (strncmp(&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) { ++ pr_err("%s: incorrect elf magic number\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) { ++ pr_err("%s: incorrect elf class(%x)\n", __func__, ++ elf_hdr->e_ident[EI_CLASS]); ++ return -EINVAL; ++ } ++ ++ if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) { ++ pr_err("%s: incorrect elf data(%x)\n", __func__, ++ elf_hdr->e_ident[EI_DATA]); ++ return -EINVAL; ++ } ++ ++ if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) { ++ pr_err("%s: incorrect elf file type(%x)\n", __func__, ++ be16_to_cpu(elf_hdr->e_type)); ++ return -EINVAL; ++ } ++ ++ for (section = 0; section < sections; section++, shdr++) { ++ if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC | ++ SHF_EXECINSTR))) ++ continue; ++ ++ for (id = 0; id < MAX_PE; id++) ++ if (pe_mask & (1 << id)) { ++ rc = pe_load_elf_section(id, elf_hdr, shdr, ++ pfe->dev); ++ if (rc < 0) ++ goto err; ++ } ++ } ++ ++ pfe_check_version_info(fw); ++ ++ return 0; ++ ++err: ++ return rc; ++} ++ ++static int get_firmware_in_fdt(const u8 **pe_fw, const char *name) ++{ ++ struct device_node *np; ++ const unsigned int *len; ++ const void *data; ++ ++ if (!strcmp(name, CLASS_FIRMWARE_FILENAME)) { ++ /* The firmware should be inside the device tree. */ ++ np = of_find_compatible_node(NULL, NULL, ++ "fsl,pfe-class-firmware"); ++ if (!np) { ++ pr_info("Failed to find the node\n"); ++ return -ENOENT; ++ } ++ ++ data = of_get_property(np, "fsl,class-firmware", NULL); ++ if (data) { ++ len = of_get_property(np, "length", NULL); ++ pr_info("CLASS fw of length %d bytes loaded from FDT.\n", ++ be32_to_cpu(*len)); ++ } else { ++ pr_info("fsl,class-firmware not found!!!!\n"); ++ return -ENOENT; ++ } ++ of_node_put(np); ++ *pe_fw = data; ++ } else if (!strcmp(name, TMU_FIRMWARE_FILENAME)) { ++ np = of_find_compatible_node(NULL, NULL, ++ "fsl,pfe-tmu-firmware"); ++ if (!np) { ++ pr_info("Failed to find the node\n"); ++ return -ENOENT; ++ } ++ ++ data = of_get_property(np, "fsl,tmu-firmware", NULL); ++ if (data) { ++ len = of_get_property(np, "length", NULL); ++ pr_info("TMU fw of length %d bytes loaded from FDT.\n", ++ be32_to_cpu(*len)); ++ } else { ++ pr_info("fsl,tmu-firmware not found!!!!\n"); ++ return -ENOENT; ++ } ++ of_node_put(np); ++ *pe_fw = data; ++ } else if (!strcmp(name, UTIL_FIRMWARE_FILENAME)) { ++ np = of_find_compatible_node(NULL, NULL, ++ "fsl,pfe-util-firmware"); ++ if (!np) { ++ pr_info("Failed to find the node\n"); ++ return -ENOENT; ++ } ++ ++ data = of_get_property(np, "fsl,util-firmware", NULL); ++ if (data) { ++ len = of_get_property(np, "length", NULL); ++ pr_info("UTIL fw of length %d bytes loaded from FDT.\n", ++ be32_to_cpu(*len)); ++ } else { ++ pr_info("fsl,util-firmware not found!!!!\n"); ++ return -ENOENT; ++ } ++ of_node_put(np); ++ *pe_fw = data; ++ } else { ++ pr_err("firmware:%s not known\n", name); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* PFE firmware initialization. ++ * Loads different firmware files from filesystem. ++ * Initializes PE IMEM/DMEM and UTIL-PE DDR ++ * Initializes control path symbol addresses (by looking them up in the elf ++ * firmware files ++ * Takes PE's out of reset ++ * ++ * @return 0 on success, a negative value on error ++ * ++ */ ++int pfe_firmware_init(struct pfe *pfe) ++{ ++ const struct firmware *class_fw, *tmu_fw; ++ const u8 *class_elf_fw, *tmu_elf_fw; ++ int rc = 0, fs_load = 0; ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ const struct firmware *util_fw; ++ const u8 *util_elf_fw; ++ ++#endif ++ ++ pr_info("%s\n", __func__); ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ if (get_firmware_in_fdt(&class_elf_fw, CLASS_FIRMWARE_FILENAME) || ++ get_firmware_in_fdt(&tmu_elf_fw, TMU_FIRMWARE_FILENAME) || ++ get_firmware_in_fdt(&util_elf_fw, UTIL_FIRMWARE_FILENAME)) ++#else ++ if (get_firmware_in_fdt(&class_elf_fw, CLASS_FIRMWARE_FILENAME) || ++ get_firmware_in_fdt(&tmu_elf_fw, TMU_FIRMWARE_FILENAME)) ++#endif ++ { ++ pr_info("%s:PFE firmware not found in FDT.\n", __func__); ++ pr_info("%s:Trying to load firmware from filesystem...!\n", __func__); ++ ++ /* look for firmware in filesystem...!*/ ++ fs_load = 1; ++ if (request_firmware(&class_fw, CLASS_FIRMWARE_FILENAME, pfe->dev)) { ++ pr_err("%s: request firmware %s failed\n", __func__, ++ CLASS_FIRMWARE_FILENAME); ++ rc = -ETIMEDOUT; ++ goto err0; ++ } ++ class_elf_fw = class_fw->data; ++ ++ if (request_firmware(&tmu_fw, TMU_FIRMWARE_FILENAME, pfe->dev)) { ++ pr_err("%s: request firmware %s failed\n", __func__, ++ TMU_FIRMWARE_FILENAME); ++ rc = -ETIMEDOUT; ++ goto err1; ++ } ++ tmu_elf_fw = tmu_fw->data; ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ if (request_firmware(&util_fw, UTIL_FIRMWARE_FILENAME, pfe->dev)) { ++ pr_err("%s: request firmware %s failed\n", __func__, ++ UTIL_FIRMWARE_FILENAME); ++ rc = -ETIMEDOUT; ++ goto err2; ++ } ++ util_elf_fw = util_fw->data; ++#endif ++ } ++ ++ rc = pfe_load_elf(CLASS_MASK, class_elf_fw, pfe); ++ if (rc < 0) { ++ pr_err("%s: class firmware load failed\n", __func__); ++ goto err3; ++ } ++ ++#if defined(CFG_DIAGS) ++ rc = pfe_get_diags_info(class_elf_fw, &pfe->diags.class_diags_info); ++ if (rc < 0) { ++ pr_warn( ++ "PFE diags won't be available for class PEs\n"); ++ rc = 0; ++ } ++#endif ++ ++ rc = pfe_load_elf(TMU_MASK, tmu_elf_fw, pfe); ++ if (rc < 0) { ++ pr_err("%s: tmu firmware load failed\n", __func__); ++ goto err3; ++ } ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ rc = pfe_load_elf(UTIL_MASK, util_elf_fw, pfe); ++ if (rc < 0) { ++ pr_err("%s: util firmware load failed\n", __func__); ++ goto err3; ++ } ++ ++#if defined(CFG_DIAGS) ++ rc = pfe_get_diags_info(util_elf_fw, &pfe->diags.util_diags_info); ++ if (rc < 0) { ++ pr_warn( ++ "PFE diags won't be available for util PE\n"); ++ rc = 0; ++ } ++#endif ++ ++ util_enable(); ++#endif ++ ++ tmu_enable(0xf); ++ class_enable(); ++ ++err3: ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ if (fs_load) ++ release_firmware(util_fw); ++err2: ++#endif ++ if (fs_load) ++ release_firmware(tmu_fw); ++ ++err1: ++ if (fs_load) ++ release_firmware(class_fw); ++ ++err0: ++ return rc; ++} ++ ++/* PFE firmware cleanup ++ * Puts PE's in reset ++ * ++ * ++ */ ++void pfe_firmware_exit(struct pfe *pfe) ++{ ++ pr_info("%s\n", __func__); ++ ++ if (pe_reset_all(&pfe->ctrl) != 0) ++ pr_err("Error: Failed to stop PEs, PFE reload may not work correctly\n"); ++ ++ class_disable(); ++ tmu_disable(0xf); ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ util_disable(); ++#endif ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_firmware.h +@@ -0,0 +1,21 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#ifndef _PFE_FIRMWARE_H_ ++#define _PFE_FIRMWARE_H_ ++ ++#define CLASS_FIRMWARE_FILENAME "ppfe_class_ls1012a.elf" ++#define TMU_FIRMWARE_FILENAME "ppfe_tmu_ls1012a.elf" ++#define UTIL_FIRMWARE_FILENAME "ppfe_util_ls1012a.elf" ++ ++#define PFE_FW_CHECK_PASS 0 ++#define PFE_FW_CHECK_FAIL 1 ++#define NUM_PFE_FW 3 ++ ++int pfe_firmware_init(struct pfe *pfe); ++void pfe_firmware_exit(struct pfe *pfe); ++ ++#endif /* _PFE_FIRMWARE_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_hal.c +@@ -0,0 +1,1517 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#include "pfe_mod.h" ++#include "pfe/pfe.h" ++ ++/* A-010897: Jumbo frame is not supported */ ++extern bool pfe_errata_a010897; ++ ++#define PFE_RCR_MAX_FL_MASK 0xC000FFFF ++ ++void *cbus_base_addr; ++void *ddr_base_addr; ++unsigned long ddr_phys_base_addr; ++unsigned int ddr_size; ++ ++static struct pe_info pe[MAX_PE]; ++ ++/* Initializes the PFE library. ++ * Must be called before using any of the library functions. ++ * ++ * @param[in] cbus_base CBUS virtual base address (as mapped in ++ * the host CPU address space) ++ * @param[in] ddr_base PFE DDR range virtual base address (as ++ * mapped in the host CPU address space) ++ * @param[in] ddr_phys_base PFE DDR range physical base address (as ++ * mapped in platform) ++ * @param[in] size PFE DDR range size (as defined by the host ++ * software) ++ */ ++void pfe_lib_init(void *cbus_base, void *ddr_base, unsigned long ddr_phys_base, ++ unsigned int size) ++{ ++ cbus_base_addr = cbus_base; ++ ddr_base_addr = ddr_base; ++ ddr_phys_base_addr = ddr_phys_base; ++ ddr_size = size; ++ ++ pe[CLASS0_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(0); ++ pe[CLASS0_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(0); ++ pe[CLASS0_ID].pmem_size = CLASS_IMEM_SIZE; ++ pe[CLASS0_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; ++ pe[CLASS0_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; ++ pe[CLASS0_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; ++ ++ pe[CLASS1_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(1); ++ pe[CLASS1_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(1); ++ pe[CLASS1_ID].pmem_size = CLASS_IMEM_SIZE; ++ pe[CLASS1_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; ++ pe[CLASS1_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; ++ pe[CLASS1_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; ++ ++ pe[CLASS2_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(2); ++ pe[CLASS2_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(2); ++ pe[CLASS2_ID].pmem_size = CLASS_IMEM_SIZE; ++ pe[CLASS2_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; ++ pe[CLASS2_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; ++ pe[CLASS2_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; ++ ++ pe[CLASS3_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(3); ++ pe[CLASS3_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(3); ++ pe[CLASS3_ID].pmem_size = CLASS_IMEM_SIZE; ++ pe[CLASS3_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; ++ pe[CLASS3_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; ++ pe[CLASS3_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; ++ ++ pe[CLASS4_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(4); ++ pe[CLASS4_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(4); ++ pe[CLASS4_ID].pmem_size = CLASS_IMEM_SIZE; ++ pe[CLASS4_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; ++ pe[CLASS4_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; ++ pe[CLASS4_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; ++ ++ pe[CLASS5_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(5); ++ pe[CLASS5_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(5); ++ pe[CLASS5_ID].pmem_size = CLASS_IMEM_SIZE; ++ pe[CLASS5_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; ++ pe[CLASS5_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; ++ pe[CLASS5_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; ++ ++ pe[TMU0_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(0); ++ pe[TMU0_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(0); ++ pe[TMU0_ID].pmem_size = TMU_IMEM_SIZE; ++ pe[TMU0_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA; ++ pe[TMU0_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR; ++ pe[TMU0_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA; ++ ++ pe[TMU1_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(1); ++ pe[TMU1_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(1); ++ pe[TMU1_ID].pmem_size = TMU_IMEM_SIZE; ++ pe[TMU1_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA; ++ pe[TMU1_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR; ++ pe[TMU1_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA; ++ ++ pe[TMU3_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(3); ++ pe[TMU3_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(3); ++ pe[TMU3_ID].pmem_size = TMU_IMEM_SIZE; ++ pe[TMU3_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA; ++ pe[TMU3_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR; ++ pe[TMU3_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA; ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ pe[UTIL_ID].dmem_base_addr = UTIL_DMEM_BASE_ADDR; ++ pe[UTIL_ID].mem_access_wdata = UTIL_MEM_ACCESS_WDATA; ++ pe[UTIL_ID].mem_access_addr = UTIL_MEM_ACCESS_ADDR; ++ pe[UTIL_ID].mem_access_rdata = UTIL_MEM_ACCESS_RDATA; ++#endif ++} ++ ++/* Writes a buffer to PE internal memory from the host ++ * through indirect access registers. ++ * ++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ++ * ..., UTIL_ID) ++ * @param[in] src Buffer source address ++ * @param[in] mem_access_addr DMEM destination address (must be 32bit ++ * aligned) ++ * @param[in] len Number of bytes to copy ++ */ ++static void pe_mem_memcpy_to32(int id, u32 mem_access_addr, const void *src, ++ unsigned int len) ++{ ++ u32 offset = 0, val, addr; ++ unsigned int len32 = len >> 2; ++ int i; ++ ++ addr = mem_access_addr | PE_MEM_ACCESS_WRITE | ++ PE_MEM_ACCESS_BYTE_ENABLE(0, 4); ++ ++ for (i = 0; i < len32; i++, offset += 4, src += 4) { ++ val = *(u32 *)src; ++ writel(cpu_to_be32(val), pe[id].mem_access_wdata); ++ writel(addr + offset, pe[id].mem_access_addr); ++ } ++ ++ len = (len & 0x3); ++ if (len) { ++ val = 0; ++ ++ addr = (mem_access_addr | PE_MEM_ACCESS_WRITE | ++ PE_MEM_ACCESS_BYTE_ENABLE(0, len)) + offset; ++ ++ for (i = 0; i < len; i++, src++) ++ val |= (*(u8 *)src) << (8 * i); ++ ++ writel(cpu_to_be32(val), pe[id].mem_access_wdata); ++ writel(addr, pe[id].mem_access_addr); ++ } ++} ++ ++/* Writes a buffer to PE internal data memory (DMEM) from the host ++ * through indirect access registers. ++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ++ * ..., UTIL_ID) ++ * @param[in] src Buffer source address ++ * @param[in] dst DMEM destination address (must be 32bit ++ * aligned) ++ * @param[in] len Number of bytes to copy ++ */ ++void pe_dmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len) ++{ ++ pe_mem_memcpy_to32(id, pe[id].dmem_base_addr | dst | ++ PE_MEM_ACCESS_DMEM, src, len); ++} ++ ++/* Writes a buffer to PE internal program memory (PMEM) from the host ++ * through indirect access registers. ++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ++ * ..., TMU3_ID) ++ * @param[in] src Buffer source address ++ * @param[in] dst PMEM destination address (must be 32bit ++ * aligned) ++ * @param[in] len Number of bytes to copy ++ */ ++void pe_pmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len) ++{ ++ pe_mem_memcpy_to32(id, pe[id].pmem_base_addr | (dst & (pe[id].pmem_size ++ - 1)) | PE_MEM_ACCESS_IMEM, src, len); ++} ++ ++/* Reads PE internal program memory (IMEM) from the host ++ * through indirect access registers. ++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ++ * ..., TMU3_ID) ++ * @param[in] addr PMEM read address (must be aligned on size) ++ * @param[in] size Number of bytes to read (maximum 4, must not ++ * cross 32bit boundaries) ++ * @return the data read (in PE endianness, i.e BE). ++ */ ++u32 pe_pmem_read(int id, u32 addr, u8 size) ++{ ++ u32 offset = addr & 0x3; ++ u32 mask = 0xffffffff >> ((4 - size) << 3); ++ u32 val; ++ ++ addr = pe[id].pmem_base_addr | ((addr & ~0x3) & (pe[id].pmem_size - 1)) ++ | PE_MEM_ACCESS_IMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size); ++ ++ writel(addr, pe[id].mem_access_addr); ++ val = be32_to_cpu(readl(pe[id].mem_access_rdata)); ++ ++ return (val >> (offset << 3)) & mask; ++} ++ ++/* Writes PE internal data memory (DMEM) from the host ++ * through indirect access registers. ++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ++ * ..., UTIL_ID) ++ * @param[in] addr DMEM write address (must be aligned on size) ++ * @param[in] val Value to write (in PE endianness, i.e BE) ++ * @param[in] size Number of bytes to write (maximum 4, must not ++ * cross 32bit boundaries) ++ */ ++void pe_dmem_write(int id, u32 val, u32 addr, u8 size) ++{ ++ u32 offset = addr & 0x3; ++ ++ addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_WRITE | ++ PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size); ++ ++ /* Indirect access interface is byte swapping data being written */ ++ writel(cpu_to_be32(val << (offset << 3)), pe[id].mem_access_wdata); ++ writel(addr, pe[id].mem_access_addr); ++} ++ ++/* Reads PE internal data memory (DMEM) from the host ++ * through indirect access registers. ++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ++ * ..., UTIL_ID) ++ * @param[in] addr DMEM read address (must be aligned on size) ++ * @param[in] size Number of bytes to read (maximum 4, must not ++ * cross 32bit boundaries) ++ * @return the data read (in PE endianness, i.e BE). ++ */ ++u32 pe_dmem_read(int id, u32 addr, u8 size) ++{ ++ u32 offset = addr & 0x3; ++ u32 mask = 0xffffffff >> ((4 - size) << 3); ++ u32 val; ++ ++ addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_DMEM | ++ PE_MEM_ACCESS_BYTE_ENABLE(offset, size); ++ ++ writel(addr, pe[id].mem_access_addr); ++ ++ /* Indirect access interface is byte swapping data being read */ ++ val = be32_to_cpu(readl(pe[id].mem_access_rdata)); ++ ++ return (val >> (offset << 3)) & mask; ++} ++ ++/* This function is used to write to CLASS internal bus peripherals (ccu, ++ * pe-lem) from the host ++ * through indirect access registers. ++ * @param[in] val value to write ++ * @param[in] addr Address to write to (must be aligned on size) ++ * @param[in] size Number of bytes to write (1, 2 or 4) ++ * ++ */ ++void class_bus_write(u32 val, u32 addr, u8 size) ++{ ++ u32 offset = addr & 0x3; ++ ++ writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE); ++ ++ addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | PE_MEM_ACCESS_WRITE | ++ (size << 24); ++ ++ writel(cpu_to_be32(val << (offset << 3)), CLASS_BUS_ACCESS_WDATA); ++ writel(addr, CLASS_BUS_ACCESS_ADDR); ++} ++ ++/* Reads from CLASS internal bus peripherals (ccu, pe-lem) from the host ++ * through indirect access registers. ++ * @param[in] addr Address to read from (must be aligned on size) ++ * @param[in] size Number of bytes to read (1, 2 or 4) ++ * @return the read data ++ * ++ */ ++u32 class_bus_read(u32 addr, u8 size) ++{ ++ u32 offset = addr & 0x3; ++ u32 mask = 0xffffffff >> ((4 - size) << 3); ++ u32 val; ++ ++ writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE); ++ ++ addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | (size << 24); ++ ++ writel(addr, CLASS_BUS_ACCESS_ADDR); ++ val = be32_to_cpu(readl(CLASS_BUS_ACCESS_RDATA)); ++ ++ return (val >> (offset << 3)) & mask; ++} ++ ++/* Writes data to the cluster memory (PE_LMEM) ++ * @param[in] dst PE LMEM destination address (must be 32bit aligned) ++ * @param[in] src Buffer source address ++ * @param[in] len Number of bytes to copy ++ */ ++void class_pe_lmem_memcpy_to32(u32 dst, const void *src, unsigned int len) ++{ ++ u32 len32 = len >> 2; ++ int i; ++ ++ for (i = 0; i < len32; i++, src += 4, dst += 4) ++ class_bus_write(*(u32 *)src, dst, 4); ++ ++ if (len & 0x2) { ++ class_bus_write(*(u16 *)src, dst, 2); ++ src += 2; ++ dst += 2; ++ } ++ ++ if (len & 0x1) { ++ class_bus_write(*(u8 *)src, dst, 1); ++ src++; ++ dst++; ++ } ++} ++ ++/* Writes value to the cluster memory (PE_LMEM) ++ * @param[in] dst PE LMEM destination address (must be 32bit aligned) ++ * @param[in] val Value to write ++ * @param[in] len Number of bytes to write ++ */ ++void class_pe_lmem_memset(u32 dst, int val, unsigned int len) ++{ ++ u32 len32 = len >> 2; ++ int i; ++ ++ val = val | (val << 8) | (val << 16) | (val << 24); ++ ++ for (i = 0; i < len32; i++, dst += 4) ++ class_bus_write(val, dst, 4); ++ ++ if (len & 0x2) { ++ class_bus_write(val, dst, 2); ++ dst += 2; ++ } ++ ++ if (len & 0x1) { ++ class_bus_write(val, dst, 1); ++ dst++; ++ } ++} ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ ++/* Writes UTIL program memory (DDR) from the host. ++ * ++ * @param[in] addr Address to write (virtual, must be aligned on size) ++ * @param[in] val Value to write (in PE endianness, i.e BE) ++ * @param[in] size Number of bytes to write (2 or 4) ++ */ ++static void util_pmem_write(u32 val, void *addr, u8 size) ++{ ++ void *addr64 = (void *)((unsigned long)addr & ~0x7); ++ unsigned long off = 8 - ((unsigned long)addr & 0x7) - size; ++ ++ /* ++ * IMEM should be loaded as a 64bit swapped value in a 64bit aligned ++ * location ++ */ ++ if (size == 4) ++ writel(be32_to_cpu(val), addr64 + off); ++ else ++ writew(be16_to_cpu((u16)val), addr64 + off); ++} ++ ++/* Writes a buffer to UTIL program memory (DDR) from the host. ++ * ++ * @param[in] dst Address to write (virtual, must be at least 16bit ++ * aligned) ++ * @param[in] src Buffer to write (in PE endianness, i.e BE, must have ++ * same alignment as dst) ++ * @param[in] len Number of bytes to write (must be at least 16bit ++ * aligned) ++ */ ++static void util_pmem_memcpy(void *dst, const void *src, unsigned int len) ++{ ++ unsigned int len32; ++ int i; ++ ++ if ((unsigned long)src & 0x2) { ++ util_pmem_write(*(u16 *)src, dst, 2); ++ src += 2; ++ dst += 2; ++ len -= 2; ++ } ++ ++ len32 = len >> 2; ++ ++ for (i = 0; i < len32; i++, dst += 4, src += 4) ++ util_pmem_write(*(u32 *)src, dst, 4); ++ ++ if (len & 0x2) ++ util_pmem_write(*(u16 *)src, dst, len & 0x2); ++} ++#endif ++ ++/* Loads an elf section into pmem ++ * Code needs to be at least 16bit aligned and only PROGBITS sections are ++ * supported ++ * ++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ..., ++ * TMU3_ID) ++ * @param[in] data pointer to the elf firmware ++ * @param[in] shdr pointer to the elf section header ++ * ++ */ ++static int pe_load_pmem_section(int id, const void *data, ++ struct elf32_shdr *shdr) ++{ ++ u32 offset = be32_to_cpu(shdr->sh_offset); ++ u32 addr = be32_to_cpu(shdr->sh_addr); ++ u32 size = be32_to_cpu(shdr->sh_size); ++ u32 type = be32_to_cpu(shdr->sh_type); ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ if (id == UTIL_ID) { ++ pr_err("%s: unsupported pmem section for UTIL\n", ++ __func__); ++ return -EINVAL; ++ } ++#endif ++ ++ if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) { ++ pr_err( ++ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n" ++ , __func__, addr, (unsigned long)data + offset); ++ ++ return -EINVAL; ++ } ++ ++ if (addr & 0x1) { ++ pr_err("%s: load address(%x) is not 16bit aligned\n", ++ __func__, addr); ++ return -EINVAL; ++ } ++ ++ if (size & 0x1) { ++ pr_err("%s: load size(%x) is not 16bit aligned\n", ++ __func__, size); ++ return -EINVAL; ++ } ++ ++ switch (type) { ++ case SHT_PROGBITS: ++ pe_pmem_memcpy_to32(id, addr, data + offset, size); ++ ++ break; ++ ++ default: ++ pr_err("%s: unsupported section type(%x)\n", __func__, ++ type); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* Loads an elf section into dmem ++ * Data needs to be at least 32bit aligned, NOBITS sections are correctly ++ * initialized to 0 ++ * ++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ++ * ..., UTIL_ID) ++ * @param[in] data pointer to the elf firmware ++ * @param[in] shdr pointer to the elf section header ++ * ++ */ ++static int pe_load_dmem_section(int id, const void *data, ++ struct elf32_shdr *shdr) ++{ ++ u32 offset = be32_to_cpu(shdr->sh_offset); ++ u32 addr = be32_to_cpu(shdr->sh_addr); ++ u32 size = be32_to_cpu(shdr->sh_size); ++ u32 type = be32_to_cpu(shdr->sh_type); ++ u32 size32 = size >> 2; ++ int i; ++ ++ if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) { ++ pr_err( ++ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n", ++ __func__, addr, (unsigned long)data + offset); ++ ++ return -EINVAL; ++ } ++ ++ if (addr & 0x3) { ++ pr_err("%s: load address(%x) is not 32bit aligned\n", ++ __func__, addr); ++ return -EINVAL; ++ } ++ ++ switch (type) { ++ case SHT_PROGBITS: ++ pe_dmem_memcpy_to32(id, addr, data + offset, size); ++ break; ++ ++ case SHT_NOBITS: ++ for (i = 0; i < size32; i++, addr += 4) ++ pe_dmem_write(id, 0, addr, 4); ++ ++ if (size & 0x3) ++ pe_dmem_write(id, 0, addr, size & 0x3); ++ ++ break; ++ ++ default: ++ pr_err("%s: unsupported section type(%x)\n", __func__, ++ type); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* Loads an elf section into DDR ++ * Data needs to be at least 32bit aligned, NOBITS sections are correctly ++ * initialized to 0 ++ * ++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ++ * ..., UTIL_ID) ++ * @param[in] data pointer to the elf firmware ++ * @param[in] shdr pointer to the elf section header ++ * ++ */ ++static int pe_load_ddr_section(int id, const void *data, ++ struct elf32_shdr *shdr, ++ struct device *dev) { ++ u32 offset = be32_to_cpu(shdr->sh_offset); ++ u32 addr = be32_to_cpu(shdr->sh_addr); ++ u32 size = be32_to_cpu(shdr->sh_size); ++ u32 type = be32_to_cpu(shdr->sh_type); ++ u32 flags = be32_to_cpu(shdr->sh_flags); ++ ++ switch (type) { ++ case SHT_PROGBITS: ++ if (flags & SHF_EXECINSTR) { ++ if (id <= CLASS_MAX_ID) { ++ /* DO the loading only once in DDR */ ++ if (id == CLASS0_ID) { ++ pr_err( ++ "%s: load address(%x) and elf file address(%lx) rcvd\n", ++ __func__, addr, ++ (unsigned long)data + offset); ++ if (((unsigned long)(data + offset) ++ & 0x3) != (addr & 0x3)) { ++ pr_err( ++ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n" ++ , __func__, addr, ++ (unsigned long)data + offset); ++ ++ return -EINVAL; ++ } ++ ++ if (addr & 0x1) { ++ pr_err( ++ "%s: load address(%x) is not 16bit aligned\n" ++ , __func__, addr); ++ return -EINVAL; ++ } ++ ++ if (size & 0x1) { ++ pr_err( ++ "%s: load length(%x) is not 16bit aligned\n" ++ , __func__, size); ++ return -EINVAL; ++ } ++ memcpy(DDR_PHYS_TO_VIRT( ++ DDR_PFE_TO_PHYS(addr)), ++ data + offset, size); ++ } ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ } else if (id == UTIL_ID) { ++ if (((unsigned long)(data + offset) & 0x3) ++ != (addr & 0x3)) { ++ pr_err( ++ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n" ++ , __func__, addr, ++ (unsigned long)data + offset); ++ ++ return -EINVAL; ++ } ++ ++ if (addr & 0x1) { ++ pr_err( ++ "%s: load address(%x) is not 16bit aligned\n" ++ , __func__, addr); ++ return -EINVAL; ++ } ++ ++ if (size & 0x1) { ++ pr_err( ++ "%s: load length(%x) is not 16bit aligned\n" ++ , __func__, size); ++ return -EINVAL; ++ } ++ ++ util_pmem_memcpy(DDR_PHYS_TO_VIRT( ++ DDR_PFE_TO_PHYS(addr)), ++ data + offset, size); ++ } ++#endif ++ } else { ++ pr_err( ++ "%s: unsupported ddr section type(%x) for PE(%d)\n" ++ , __func__, type, id); ++ return -EINVAL; ++ } ++ ++ } else { ++ memcpy(DDR_PHYS_TO_VIRT(DDR_PFE_TO_PHYS(addr)), data ++ + offset, size); ++ } ++ ++ break; ++ ++ case SHT_NOBITS: ++ memset(DDR_PHYS_TO_VIRT(DDR_PFE_TO_PHYS(addr)), 0, size); ++ ++ break; ++ ++ default: ++ pr_err("%s: unsupported section type(%x)\n", __func__, ++ type); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* Loads an elf section into pe lmem ++ * Data needs to be at least 32bit aligned, NOBITS sections are correctly ++ * initialized to 0 ++ * ++ * @param[in] id PE identification (CLASS0_ID,..., CLASS5_ID) ++ * @param[in] data pointer to the elf firmware ++ * @param[in] shdr pointer to the elf section header ++ * ++ */ ++static int pe_load_pe_lmem_section(int id, const void *data, ++ struct elf32_shdr *shdr) ++{ ++ u32 offset = be32_to_cpu(shdr->sh_offset); ++ u32 addr = be32_to_cpu(shdr->sh_addr); ++ u32 size = be32_to_cpu(shdr->sh_size); ++ u32 type = be32_to_cpu(shdr->sh_type); ++ ++ if (id > CLASS_MAX_ID) { ++ pr_err( ++ "%s: unsupported pe-lmem section type(%x) for PE(%d)\n", ++ __func__, type, id); ++ return -EINVAL; ++ } ++ ++ if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) { ++ pr_err( ++ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n", ++ __func__, addr, (unsigned long)data + offset); ++ ++ return -EINVAL; ++ } ++ ++ if (addr & 0x3) { ++ pr_err("%s: load address(%x) is not 32bit aligned\n", ++ __func__, addr); ++ return -EINVAL; ++ } ++ ++ switch (type) { ++ case SHT_PROGBITS: ++ class_pe_lmem_memcpy_to32(addr, data + offset, size); ++ break; ++ ++ case SHT_NOBITS: ++ class_pe_lmem_memset(addr, 0, size); ++ break; ++ ++ default: ++ pr_err("%s: unsupported section type(%x)\n", __func__, ++ type); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* Loads an elf section into a PE ++ * For now only supports loading a section to dmem (all PE's), pmem (class and ++ * tmu PE's), ++ * DDDR (util PE code) ++ * ++ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ++ * ..., UTIL_ID) ++ * @param[in] data pointer to the elf firmware ++ * @param[in] shdr pointer to the elf section header ++ * ++ */ ++int pe_load_elf_section(int id, const void *data, struct elf32_shdr *shdr, ++ struct device *dev) { ++ u32 addr = be32_to_cpu(shdr->sh_addr); ++ u32 size = be32_to_cpu(shdr->sh_size); ++ ++ if (IS_DMEM(addr, size)) ++ return pe_load_dmem_section(id, data, shdr); ++ else if (IS_PMEM(addr, size)) ++ return pe_load_pmem_section(id, data, shdr); ++ else if (IS_PFE_LMEM(addr, size)) ++ return 0; ++ else if (IS_PHYS_DDR(addr, size)) ++ return pe_load_ddr_section(id, data, shdr, dev); ++ else if (IS_PE_LMEM(addr, size)) ++ return pe_load_pe_lmem_section(id, data, shdr); ++ ++ pr_err("%s: unsupported memory range(%x)\n", __func__, ++ addr); ++ return 0; ++} ++ ++/**************************** BMU ***************************/ ++ ++/* Initializes a BMU block. ++ * @param[in] base BMU block base address ++ * @param[in] cfg BMU configuration ++ */ ++void bmu_init(void *base, struct BMU_CFG *cfg) ++{ ++ bmu_disable(base); ++ ++ bmu_set_config(base, cfg); ++ ++ bmu_reset(base); ++} ++ ++/* Resets a BMU block. ++ * @param[in] base BMU block base address ++ */ ++void bmu_reset(void *base) ++{ ++ writel(CORE_SW_RESET, base + BMU_CTRL); ++ ++ /* Wait for self clear */ ++ while (readl(base + BMU_CTRL) & CORE_SW_RESET) ++ ; ++} ++ ++/* Enabled a BMU block. ++ * @param[in] base BMU block base address ++ */ ++void bmu_enable(void *base) ++{ ++ writel(CORE_ENABLE, base + BMU_CTRL); ++} ++ ++/* Disables a BMU block. ++ * @param[in] base BMU block base address ++ */ ++void bmu_disable(void *base) ++{ ++ writel(CORE_DISABLE, base + BMU_CTRL); ++} ++ ++/* Sets the configuration of a BMU block. ++ * @param[in] base BMU block base address ++ * @param[in] cfg BMU configuration ++ */ ++void bmu_set_config(void *base, struct BMU_CFG *cfg) ++{ ++ writel(cfg->baseaddr, base + BMU_UCAST_BASE_ADDR); ++ writel(cfg->count & 0xffff, base + BMU_UCAST_CONFIG); ++ writel(cfg->size & 0xffff, base + BMU_BUF_SIZE); ++ ++ /* Interrupts are never used */ ++ writel(cfg->low_watermark, base + BMU_LOW_WATERMARK); ++ writel(cfg->high_watermark, base + BMU_HIGH_WATERMARK); ++ writel(0x0, base + BMU_INT_ENABLE); ++} ++ ++/**************************** MTIP GEMAC ***************************/ ++ ++/* Enable Rx Checksum Engine. With this enabled, Frame with bad IP, ++ * TCP or UDP checksums are discarded ++ * ++ * @param[in] base GEMAC base address. ++ */ ++void gemac_enable_rx_checksum_offload(void *base) ++{ ++ /*Do not find configuration to do this */ ++} ++ ++/* Disable Rx Checksum Engine. ++ * ++ * @param[in] base GEMAC base address. ++ */ ++void gemac_disable_rx_checksum_offload(void *base) ++{ ++ /*Do not find configuration to do this */ ++} ++ ++/* GEMAC set speed. ++ * @param[in] base GEMAC base address ++ * @param[in] speed GEMAC speed (10, 100 or 1000 Mbps) ++ */ ++void gemac_set_speed(void *base, enum mac_speed gem_speed) ++{ ++ u32 ecr = readl(base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_SPEED; ++ u32 rcr = readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_RMII_10T; ++ ++ switch (gem_speed) { ++ case SPEED_10M: ++ rcr |= EMAC_RCNTRL_RMII_10T; ++ break; ++ ++ case SPEED_1000M: ++ ecr |= EMAC_ECNTRL_SPEED; ++ break; ++ ++ case SPEED_100M: ++ default: ++ /*It is in 100M mode */ ++ break; ++ } ++ writel(ecr, (base + EMAC_ECNTRL_REG)); ++ writel(rcr, (base + EMAC_RCNTRL_REG)); ++} ++ ++/* GEMAC set duplex. ++ * @param[in] base GEMAC base address ++ * @param[in] duplex GEMAC duplex mode (Full, Half) ++ */ ++void gemac_set_duplex(void *base, int duplex) ++{ ++ if (duplex == DUPLEX_HALF) { ++ writel(readl(base + EMAC_TCNTRL_REG) & ~EMAC_TCNTRL_FDEN, base ++ + EMAC_TCNTRL_REG); ++ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_DRT, (base ++ + EMAC_RCNTRL_REG)); ++ } else{ ++ writel(readl(base + EMAC_TCNTRL_REG) | EMAC_TCNTRL_FDEN, base ++ + EMAC_TCNTRL_REG); ++ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_DRT, (base ++ + EMAC_RCNTRL_REG)); ++ } ++} ++ ++/* GEMAC set mode. ++ * @param[in] base GEMAC base address ++ * @param[in] mode GEMAC operation mode (MII, RMII, RGMII, SGMII) ++ */ ++void gemac_set_mode(void *base, int mode) ++{ ++ u32 val = readl(base + EMAC_RCNTRL_REG); ++ ++ /*Remove loopbank*/ ++ val &= ~EMAC_RCNTRL_LOOP; ++ ++ /* Enable flow control and MII mode.PFE firmware always expects ++ CRC should be forwarded by MAC to validate CRC in software.*/ ++ val |= (EMAC_RCNTRL_FCE | EMAC_RCNTRL_MII_MODE); ++ ++ writel(val, base + EMAC_RCNTRL_REG); ++} ++ ++/* GEMAC enable function. ++ * @param[in] base GEMAC base address ++ */ ++void gemac_enable(void *base) ++{ ++ writel(readl(base + EMAC_ECNTRL_REG) | EMAC_ECNTRL_ETHER_EN, base + ++ EMAC_ECNTRL_REG); ++} ++ ++/* GEMAC disable function. ++ * @param[in] base GEMAC base address ++ */ ++void gemac_disable(void *base) ++{ ++ writel(readl(base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_ETHER_EN, base + ++ EMAC_ECNTRL_REG); ++} ++ ++/* GEMAC TX disable function. ++ * @param[in] base GEMAC base address ++ */ ++void gemac_tx_disable(void *base) ++{ ++ writel(readl(base + EMAC_TCNTRL_REG) | EMAC_TCNTRL_GTS, base + ++ EMAC_TCNTRL_REG); ++} ++ ++void gemac_tx_enable(void *base) ++{ ++ writel(readl(base + EMAC_TCNTRL_REG) & ~EMAC_TCNTRL_GTS, base + ++ EMAC_TCNTRL_REG); ++} ++ ++/* Sets the hash register of the MAC. ++ * This register is used for matching unicast and multicast frames. ++ * ++ * @param[in] base GEMAC base address. ++ * @param[in] hash 64-bit hash to be configured. ++ */ ++void gemac_set_hash(void *base, struct pfe_mac_addr *hash) ++{ ++ writel(hash->bottom, base + EMAC_GALR); ++ writel(hash->top, base + EMAC_GAUR); ++} ++ ++void gemac_set_laddrN(void *base, struct pfe_mac_addr *address, ++ unsigned int entry_index) ++{ ++ if ((entry_index < 1) || (entry_index > EMAC_SPEC_ADDR_MAX)) ++ return; ++ ++ entry_index = entry_index - 1; ++ if (entry_index < 1) { ++ writel(htonl(address->bottom), base + EMAC_PHY_ADDR_LOW); ++ writel((htonl(address->top) | 0x8808), base + ++ EMAC_PHY_ADDR_HIGH); ++ } else { ++ writel(htonl(address->bottom), base + ((entry_index - 1) * 8) ++ + EMAC_SMAC_0_0); ++ writel((htonl(address->top) | 0x8808), base + ((entry_index - ++ 1) * 8) + EMAC_SMAC_0_1); ++ } ++} ++ ++void gemac_clear_laddrN(void *base, unsigned int entry_index) ++{ ++ if ((entry_index < 1) || (entry_index > EMAC_SPEC_ADDR_MAX)) ++ return; ++ ++ entry_index = entry_index - 1; ++ if (entry_index < 1) { ++ writel(0, base + EMAC_PHY_ADDR_LOW); ++ writel(0, base + EMAC_PHY_ADDR_HIGH); ++ } else { ++ writel(0, base + ((entry_index - 1) * 8) + EMAC_SMAC_0_0); ++ writel(0, base + ((entry_index - 1) * 8) + EMAC_SMAC_0_1); ++ } ++} ++ ++/* Set the loopback mode of the MAC. This can be either no loopback for ++ * normal operation, local loopback through MAC internal loopback module or PHY ++ * loopback for external loopback through a PHY. This asserts the external ++ * loop pin. ++ * ++ * @param[in] base GEMAC base address. ++ * @param[in] gem_loop Loopback mode to be enabled. LB_LOCAL - MAC ++ * Loopback, ++ * LB_EXT - PHY Loopback. ++ */ ++void gemac_set_loop(void *base, enum mac_loop gem_loop) ++{ ++ pr_info("%s()\n", __func__); ++ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_LOOP, (base + ++ EMAC_RCNTRL_REG)); ++} ++ ++/* GEMAC allow frames ++ * @param[in] base GEMAC base address ++ */ ++void gemac_enable_copy_all(void *base) ++{ ++ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_PROM, (base + ++ EMAC_RCNTRL_REG)); ++} ++ ++/* GEMAC do not allow frames ++ * @param[in] base GEMAC base address ++ */ ++void gemac_disable_copy_all(void *base) ++{ ++ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_PROM, (base + ++ EMAC_RCNTRL_REG)); ++} ++ ++/* GEMAC allow broadcast function. ++ * @param[in] base GEMAC base address ++ */ ++void gemac_allow_broadcast(void *base) ++{ ++ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_BC_REJ, base + ++ EMAC_RCNTRL_REG); ++} ++ ++/* GEMAC no broadcast function. ++ * @param[in] base GEMAC base address ++ */ ++void gemac_no_broadcast(void *base) ++{ ++ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_BC_REJ, base + ++ EMAC_RCNTRL_REG); ++} ++ ++/* GEMAC enable 1536 rx function. ++ * @param[in] base GEMAC base address ++ */ ++void gemac_enable_1536_rx(void *base) ++{ ++ /* Set 1536 as Maximum frame length */ ++ writel((readl(base + EMAC_RCNTRL_REG) & PFE_RCR_MAX_FL_MASK) ++ | (1536 << 16), base + EMAC_RCNTRL_REG); ++} ++ ++/* GEMAC set rx Max frame length. ++ * @param[in] base GEMAC base address ++ * @param[in] mtu new mtu ++ */ ++void gemac_set_rx_max_fl(void *base, int mtu) ++{ ++ /* Set mtu as Maximum frame length */ ++ writel((readl(base + EMAC_RCNTRL_REG) & PFE_RCR_MAX_FL_MASK) ++ | (mtu << 16), base + EMAC_RCNTRL_REG); ++} ++ ++/* GEMAC enable stacked vlan function. ++ * @param[in] base GEMAC base address ++ */ ++void gemac_enable_stacked_vlan(void *base) ++{ ++ /* MTIP doesn't support stacked vlan */ ++} ++ ++/* GEMAC enable pause rx function. ++ * @param[in] base GEMAC base address ++ */ ++void gemac_enable_pause_rx(void *base) ++{ ++ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_FCE, ++ base + EMAC_RCNTRL_REG); ++} ++ ++/* GEMAC disable pause rx function. ++ * @param[in] base GEMAC base address ++ */ ++void gemac_disable_pause_rx(void *base) ++{ ++ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_FCE, ++ base + EMAC_RCNTRL_REG); ++} ++ ++/* GEMAC enable pause tx function. ++ * @param[in] base GEMAC base address ++ */ ++static void __maybe_unused gemac_enable_pause_tx(void *base) ++{ ++ writel(EMAC_RX_SECTION_EMPTY_V, base + EMAC_RX_SECTION_EMPTY); ++} ++ ++/* GEMAC disable pause tx function. ++ * @param[in] base GEMAC base address ++ */ ++static void __maybe_unused gemac_disable_pause_tx(void *base) ++{ ++ writel(0x0, base + EMAC_RX_SECTION_EMPTY); ++} ++ ++/* GEMAC wol configuration ++ * @param[in] base GEMAC base address ++ * @param[in] wol_conf WoL register configuration ++ */ ++void gemac_set_wol(void *base, u32 wol_conf) ++{ ++ u32 val = readl(base + EMAC_ECNTRL_REG); ++ ++ if (wol_conf) ++ val |= (EMAC_ECNTRL_MAGIC_ENA | EMAC_ECNTRL_SLEEP); ++ else ++ val &= ~(EMAC_ECNTRL_MAGIC_ENA | EMAC_ECNTRL_SLEEP); ++ writel(val, base + EMAC_ECNTRL_REG); ++} ++ ++/* Sets Gemac bus width to 64bit ++ * @param[in] base GEMAC base address ++ * @param[in] width gemac bus width to be set possible values are 32/64/128 ++ */ ++void gemac_set_bus_width(void *base, int width) ++{ ++} ++ ++/* Sets Gemac configuration. ++ * @param[in] base GEMAC base address ++ * @param[in] cfg GEMAC configuration ++ */ ++void gemac_set_config(void *base, struct gemac_cfg *cfg) ++{ ++ /*GEMAC config taken from VLSI */ ++ writel(0x00000004, base + EMAC_TFWR_STR_FWD); ++ writel(0x00000005, base + EMAC_RX_SECTION_FULL); ++ ++ if (pfe_errata_a010897) ++ writel(0x0000076c, base + EMAC_TRUNC_FL); ++ else ++ writel(0x00003fff, base + EMAC_TRUNC_FL); ++ ++ writel(0x00000030, base + EMAC_TX_SECTION_EMPTY); ++ writel(0x00000000, base + EMAC_MIB_CTRL_STS_REG); ++ ++ gemac_set_mode(base, cfg->mode); ++ ++ gemac_set_speed(base, cfg->speed); ++ ++ gemac_set_duplex(base, cfg->duplex); ++} ++ ++/**************************** GPI ***************************/ ++ ++/* Initializes a GPI block. ++ * @param[in] base GPI base address ++ * @param[in] cfg GPI configuration ++ */ ++void gpi_init(void *base, struct gpi_cfg *cfg) ++{ ++ gpi_reset(base); ++ ++ gpi_disable(base); ++ ++ gpi_set_config(base, cfg); ++} ++ ++/* Resets a GPI block. ++ * @param[in] base GPI base address ++ */ ++void gpi_reset(void *base) ++{ ++ writel(CORE_SW_RESET, base + GPI_CTRL); ++} ++ ++/* Enables a GPI block. ++ * @param[in] base GPI base address ++ */ ++void gpi_enable(void *base) ++{ ++ writel(CORE_ENABLE, base + GPI_CTRL); ++} ++ ++/* Disables a GPI block. ++ * @param[in] base GPI base address ++ */ ++void gpi_disable(void *base) ++{ ++ writel(CORE_DISABLE, base + GPI_CTRL); ++} ++ ++/* Sets the configuration of a GPI block. ++ * @param[in] base GPI base address ++ * @param[in] cfg GPI configuration ++ */ ++void gpi_set_config(void *base, struct gpi_cfg *cfg) ++{ ++ writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_ALLOC_CTRL), base ++ + GPI_LMEM_ALLOC_ADDR); ++ writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_FREE_CTRL), base ++ + GPI_LMEM_FREE_ADDR); ++ writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_ALLOC_CTRL), base ++ + GPI_DDR_ALLOC_ADDR); ++ writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), base ++ + GPI_DDR_FREE_ADDR); ++ writel(CBUS_VIRT_TO_PFE(CLASS_INQ_PKTPTR), base + GPI_CLASS_ADDR); ++ writel(DDR_HDR_SIZE, base + GPI_DDR_DATA_OFFSET); ++ writel(LMEM_HDR_SIZE, base + GPI_LMEM_DATA_OFFSET); ++ writel(0, base + GPI_LMEM_SEC_BUF_DATA_OFFSET); ++ writel(0, base + GPI_DDR_SEC_BUF_DATA_OFFSET); ++ writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, base + GPI_HDR_SIZE); ++ writel((DDR_BUF_SIZE << 16) | LMEM_BUF_SIZE, base + GPI_BUF_SIZE); ++ ++ writel(((cfg->lmem_rtry_cnt << 16) | (GPI_DDR_BUF_EN << 1) | ++ GPI_LMEM_BUF_EN), base + GPI_RX_CONFIG); ++ writel(cfg->tmlf_txthres, base + GPI_TMLF_TX); ++ writel(cfg->aseq_len, base + GPI_DTX_ASEQ); ++ writel(1, base + GPI_TOE_CHKSUM_EN); ++ ++ if (cfg->mtip_pause_reg) { ++ writel(cfg->mtip_pause_reg, base + GPI_CSR_MTIP_PAUSE_REG); ++ writel(EGPI_PAUSE_TIME, base + GPI_TX_PAUSE_TIME); ++ } ++} ++ ++/**************************** CLASSIFIER ***************************/ ++ ++/* Initializes CLASSIFIER block. ++ * @param[in] cfg CLASSIFIER configuration ++ */ ++void class_init(struct class_cfg *cfg) ++{ ++ class_reset(); ++ ++ class_disable(); ++ ++ class_set_config(cfg); ++} ++ ++/* Resets CLASSIFIER block. ++ * ++ */ ++void class_reset(void) ++{ ++ writel(CORE_SW_RESET, CLASS_TX_CTRL); ++} ++ ++/* Enables all CLASS-PE's cores. ++ * ++ */ ++void class_enable(void) ++{ ++ writel(CORE_ENABLE, CLASS_TX_CTRL); ++} ++ ++/* Disables all CLASS-PE's cores. ++ * ++ */ ++void class_disable(void) ++{ ++ writel(CORE_DISABLE, CLASS_TX_CTRL); ++} ++ ++/* ++ * Sets the configuration of the CLASSIFIER block. ++ * @param[in] cfg CLASSIFIER configuration ++ */ ++void class_set_config(struct class_cfg *cfg) ++{ ++ u32 val; ++ ++ /* Initialize route table */ ++ if (!cfg->resume) ++ memset(DDR_PHYS_TO_VIRT(cfg->route_table_baseaddr), 0, (1 << ++ cfg->route_table_hash_bits) * CLASS_ROUTE_SIZE); ++ ++#if !defined(LS1012A_PFE_RESET_WA) ++ writel(cfg->pe_sys_clk_ratio, CLASS_PE_SYS_CLK_RATIO); ++#endif ++ ++ writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, CLASS_HDR_SIZE); ++ writel(LMEM_BUF_SIZE, CLASS_LMEM_BUF_SIZE); ++ writel(CLASS_ROUTE_ENTRY_SIZE(CLASS_ROUTE_SIZE) | ++ CLASS_ROUTE_HASH_SIZE(cfg->route_table_hash_bits), ++ CLASS_ROUTE_HASH_ENTRY_SIZE); ++ writel(HIF_PKT_CLASS_EN | HIF_PKT_OFFSET(sizeof(struct hif_hdr)), ++ CLASS_HIF_PARSE); ++ ++ val = HASH_CRC_PORT_IP | QB2BUS_LE; ++ ++#if defined(CONFIG_IP_ALIGNED) ++ val |= IP_ALIGNED; ++#endif ++ ++ /* ++ * Class PE packet steering will only work if TOE mode, bridge fetch or ++ * route fetch are enabled (see class/qb_fet.v). Route fetch would ++ * trigger additional memory copies (likely from DDR because of hash ++ * table size, which cannot be reduced because PE software still ++ * relies on hash value computed in HW), so when not in TOE mode we ++ * simply enable HW bridge fetch even though we don't use it. ++ */ ++ if (cfg->toe_mode) ++ val |= CLASS_TOE; ++ else ++ val |= HW_BRIDGE_FETCH; ++ ++ writel(val, CLASS_ROUTE_MULTI); ++ ++ writel(DDR_PHYS_TO_PFE(cfg->route_table_baseaddr), ++ CLASS_ROUTE_TABLE_BASE); ++ writel(CLASS_PE0_RO_DM_ADDR0_VAL, CLASS_PE0_RO_DM_ADDR0); ++ writel(CLASS_PE0_RO_DM_ADDR1_VAL, CLASS_PE0_RO_DM_ADDR1); ++ writel(CLASS_PE0_QB_DM_ADDR0_VAL, CLASS_PE0_QB_DM_ADDR0); ++ writel(CLASS_PE0_QB_DM_ADDR1_VAL, CLASS_PE0_QB_DM_ADDR1); ++ writel(CBUS_VIRT_TO_PFE(TMU_PHY_INQ_PKTPTR), CLASS_TM_INQ_ADDR); ++ ++ writel(23, CLASS_AFULL_THRES); ++ writel(23, CLASS_TSQ_FIFO_THRES); ++ ++ writel(24, CLASS_MAX_BUF_CNT); ++ writel(24, CLASS_TSQ_MAX_CNT); ++} ++ ++/**************************** TMU ***************************/ ++ ++void tmu_reset(void) ++{ ++ writel(SW_RESET, TMU_CTRL); ++} ++ ++/* Initializes TMU block. ++ * @param[in] cfg TMU configuration ++ */ ++void tmu_init(struct tmu_cfg *cfg) ++{ ++ int q, phyno; ++ ++ tmu_disable(0xF); ++ mdelay(10); ++ ++#if !defined(LS1012A_PFE_RESET_WA) ++ /* keep in soft reset */ ++ writel(SW_RESET, TMU_CTRL); ++#endif ++ writel(0x3, TMU_SYS_GENERIC_CONTROL); ++ writel(750, TMU_INQ_WATERMARK); ++ writel(CBUS_VIRT_TO_PFE(EGPI1_BASE_ADDR + ++ GPI_INQ_PKTPTR), TMU_PHY0_INQ_ADDR); ++ writel(CBUS_VIRT_TO_PFE(EGPI2_BASE_ADDR + ++ GPI_INQ_PKTPTR), TMU_PHY1_INQ_ADDR); ++ writel(CBUS_VIRT_TO_PFE(HGPI_BASE_ADDR + ++ GPI_INQ_PKTPTR), TMU_PHY3_INQ_ADDR); ++ writel(CBUS_VIRT_TO_PFE(HIF_NOCPY_RX_INQ0_PKTPTR), TMU_PHY4_INQ_ADDR); ++ writel(CBUS_VIRT_TO_PFE(UTIL_INQ_PKTPTR), TMU_PHY5_INQ_ADDR); ++ writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), ++ TMU_BMU_INQ_ADDR); ++ ++ writel(0x3FF, TMU_TDQ0_SCH_CTRL); /* ++ * enabling all 10 ++ * schedulers [9:0] of each TDQ ++ */ ++ writel(0x3FF, TMU_TDQ1_SCH_CTRL); ++ writel(0x3FF, TMU_TDQ3_SCH_CTRL); ++ ++#if !defined(LS1012A_PFE_RESET_WA) ++ writel(cfg->pe_sys_clk_ratio, TMU_PE_SYS_CLK_RATIO); ++#endif ++ ++#if !defined(LS1012A_PFE_RESET_WA) ++ writel(DDR_PHYS_TO_PFE(cfg->llm_base_addr), TMU_LLM_BASE_ADDR); ++ /* Extra packet pointers will be stored from this address onwards */ ++ ++ writel(cfg->llm_queue_len, TMU_LLM_QUE_LEN); ++ writel(5, TMU_TDQ_IIFG_CFG); ++ writel(DDR_BUF_SIZE, TMU_BMU_BUF_SIZE); ++ ++ writel(0x0, TMU_CTRL); ++ ++ /* MEM init */ ++ pr_info("%s: mem init\n", __func__); ++ writel(MEM_INIT, TMU_CTRL); ++ ++ while (!(readl(TMU_CTRL) & MEM_INIT_DONE)) ++ ; ++ ++ /* LLM init */ ++ pr_info("%s: lmem init\n", __func__); ++ writel(LLM_INIT, TMU_CTRL); ++ ++ while (!(readl(TMU_CTRL) & LLM_INIT_DONE)) ++ ; ++#endif ++ /* set up each queue for tail drop */ ++ for (phyno = 0; phyno < 4; phyno++) { ++ if (phyno == 2) ++ continue; ++ for (q = 0; q < 16; q++) { ++ u32 qdepth; ++ ++ writel((phyno << 8) | q, TMU_TEQ_CTRL); ++ writel(1 << 22, TMU_TEQ_QCFG); /*Enable tail drop */ ++ ++ if (phyno == 3) ++ qdepth = DEFAULT_TMU3_QDEPTH; ++ else ++ qdepth = (q == 0) ? DEFAULT_Q0_QDEPTH : ++ DEFAULT_MAX_QDEPTH; ++ ++ /* LOG: 68855 */ ++ /* ++ * The following is a workaround for the reordered ++ * packet and BMU2 buffer leakage issue. ++ */ ++ if (CHIP_REVISION() == 0) ++ qdepth = 31; ++ ++ writel(qdepth << 18, TMU_TEQ_HW_PROB_CFG2); ++ writel(qdepth >> 14, TMU_TEQ_HW_PROB_CFG3); ++ } ++ } ++ ++#ifdef CFG_LRO ++ /* Set TMU-3 queue 5 (LRO) in no-drop mode */ ++ writel((3 << 8) | TMU_QUEUE_LRO, TMU_TEQ_CTRL); ++ writel(0, TMU_TEQ_QCFG); ++#endif ++ ++ writel(0x05, TMU_TEQ_DISABLE_DROPCHK); ++ ++ writel(0x0, TMU_CTRL); ++} ++ ++/* Enables TMU-PE cores. ++ * @param[in] pe_mask TMU PE mask ++ */ ++void tmu_enable(u32 pe_mask) ++{ ++ writel(readl(TMU_TX_CTRL) | (pe_mask & 0xF), TMU_TX_CTRL); ++} ++ ++/* Disables TMU cores. ++ * @param[in] pe_mask TMU PE mask ++ */ ++void tmu_disable(u32 pe_mask) ++{ ++ writel(readl(TMU_TX_CTRL) & ~(pe_mask & 0xF), TMU_TX_CTRL); ++} ++ ++/* This will return the tmu queue status ++ * @param[in] if_id gem interface id or TMU index ++ * @return returns the bit mask of busy queues, zero means all ++ * queues are empty ++ */ ++u32 tmu_qstatus(u32 if_id) ++{ ++ return cpu_to_be32(pe_dmem_read(TMU0_ID + if_id, TMU_DM_PESTATUS + ++ offsetof(struct pe_status, tmu_qstatus), 4)); ++} ++ ++u32 tmu_pkts_processed(u32 if_id) ++{ ++ return cpu_to_be32(pe_dmem_read(TMU0_ID + if_id, TMU_DM_PESTATUS + ++ offsetof(struct pe_status, rx), 4)); ++} ++ ++/**************************** UTIL ***************************/ ++ ++/* Resets UTIL block. ++ */ ++void util_reset(void) ++{ ++ writel(CORE_SW_RESET, UTIL_TX_CTRL); ++} ++ ++/* Initializes UTIL block. ++ * @param[in] cfg UTIL configuration ++ */ ++void util_init(struct util_cfg *cfg) ++{ ++ writel(cfg->pe_sys_clk_ratio, UTIL_PE_SYS_CLK_RATIO); ++} ++ ++/* Enables UTIL-PE core. ++ * ++ */ ++void util_enable(void) ++{ ++ writel(CORE_ENABLE, UTIL_TX_CTRL); ++} ++ ++/* Disables UTIL-PE core. ++ * ++ */ ++void util_disable(void) ++{ ++ writel(CORE_DISABLE, UTIL_TX_CTRL); ++} ++ ++/**************************** HIF ***************************/ ++/* Initializes HIF copy block. ++ * ++ */ ++void hif_init(void) ++{ ++ /*Initialize HIF registers*/ ++ writel((HIF_RX_POLL_CTRL_CYCLE << 16) | HIF_TX_POLL_CTRL_CYCLE, ++ HIF_POLL_CTRL); ++} ++ ++/* Enable hif tx DMA and interrupt ++ * ++ */ ++void hif_tx_enable(void) ++{ ++ writel(HIF_CTRL_DMA_EN, HIF_TX_CTRL); ++ writel((readl(HIF_INT_ENABLE) | HIF_INT_EN | HIF_TXPKT_INT_EN), ++ HIF_INT_ENABLE); ++} ++ ++/* Disable hif tx DMA and interrupt ++ * ++ */ ++void hif_tx_disable(void) ++{ ++ u32 hif_int; ++ ++ writel(0, HIF_TX_CTRL); ++ ++ hif_int = readl(HIF_INT_ENABLE); ++ hif_int &= HIF_TXPKT_INT_EN; ++ writel(hif_int, HIF_INT_ENABLE); ++} ++ ++/* Enable hif rx DMA and interrupt ++ * ++ */ ++void hif_rx_enable(void) ++{ ++ hif_rx_dma_start(); ++ writel((readl(HIF_INT_ENABLE) | HIF_INT_EN | HIF_RXPKT_INT_EN), ++ HIF_INT_ENABLE); ++} ++ ++/* Disable hif rx DMA and interrupt ++ * ++ */ ++void hif_rx_disable(void) ++{ ++ u32 hif_int; ++ ++ writel(0, HIF_RX_CTRL); ++ ++ hif_int = readl(HIF_INT_ENABLE); ++ hif_int &= HIF_RXPKT_INT_EN; ++ writel(hif_int, HIF_INT_ENABLE); ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_hif.c +@@ -0,0 +1,1063 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "pfe_mod.h" ++ ++#define HIF_INT_MASK (HIF_INT | HIF_RXPKT_INT | HIF_TXPKT_INT) ++ ++unsigned char napi_first_batch; ++ ++static void pfe_tx_do_cleanup(unsigned long data); ++ ++static int pfe_hif_alloc_descr(struct pfe_hif *hif) ++{ ++ void *addr; ++ dma_addr_t dma_addr; ++ int err = 0; ++ ++ pr_info("%s\n", __func__); ++ addr = dma_alloc_coherent(pfe->dev, ++ HIF_RX_DESC_NT * sizeof(struct hif_desc) + ++ HIF_TX_DESC_NT * sizeof(struct hif_desc), ++ &dma_addr, GFP_KERNEL); ++ ++ if (!addr) { ++ pr_err("%s: Could not allocate buffer descriptors!\n" ++ , __func__); ++ err = -ENOMEM; ++ goto err0; ++ } ++ ++ hif->descr_baseaddr_p = dma_addr; ++ hif->descr_baseaddr_v = addr; ++ hif->rx_ring_size = HIF_RX_DESC_NT; ++ hif->tx_ring_size = HIF_TX_DESC_NT; ++ ++ return 0; ++ ++err0: ++ return err; ++} ++ ++#if defined(LS1012A_PFE_RESET_WA) ++static void pfe_hif_disable_rx_desc(struct pfe_hif *hif) ++{ ++ int ii; ++ struct hif_desc *desc = hif->rx_base; ++ ++ /*Mark all descriptors as LAST_BD */ ++ for (ii = 0; ii < hif->rx_ring_size; ii++) { ++ desc->ctrl |= BD_CTRL_LAST_BD; ++ desc++; ++ } ++} ++ ++struct class_rx_hdr_t { ++ u32 next_ptr; /* ptr to the start of the first DDR buffer */ ++ u16 length; /* total packet length */ ++ u16 phyno; /* input physical port number */ ++ u32 status; /* gemac status bits */ ++ u32 status2; /* reserved for software usage */ ++}; ++ ++/* STATUS_BAD_FRAME_ERR is set for all errors (including checksums if enabled) ++ * except overflow ++ */ ++#define STATUS_BAD_FRAME_ERR BIT(16) ++#define STATUS_LENGTH_ERR BIT(17) ++#define STATUS_CRC_ERR BIT(18) ++#define STATUS_TOO_SHORT_ERR BIT(19) ++#define STATUS_TOO_LONG_ERR BIT(20) ++#define STATUS_CODE_ERR BIT(21) ++#define STATUS_MC_HASH_MATCH BIT(22) ++#define STATUS_CUMULATIVE_ARC_HIT BIT(23) ++#define STATUS_UNICAST_HASH_MATCH BIT(24) ++#define STATUS_IP_CHECKSUM_CORRECT BIT(25) ++#define STATUS_TCP_CHECKSUM_CORRECT BIT(26) ++#define STATUS_UDP_CHECKSUM_CORRECT BIT(27) ++#define STATUS_OVERFLOW_ERR BIT(28) /* GPI error */ ++#define MIN_PKT_SIZE 64 ++ ++static inline void copy_to_lmem(u32 *dst, u32 *src, int len) ++{ ++ int i; ++ ++ for (i = 0; i < len; i += sizeof(u32)) { ++ *dst = htonl(*src); ++ dst++; src++; ++ } ++} ++ ++static void send_dummy_pkt_to_hif(void) ++{ ++ void *lmem_ptr, *ddr_ptr, *lmem_virt_addr; ++ u32 physaddr; ++ struct class_rx_hdr_t local_hdr; ++ static u32 dummy_pkt[] = { ++ 0x33221100, 0x2b785544, 0xd73093cb, 0x01000608, ++ 0x04060008, 0x2b780200, 0xd73093cb, 0x0a01a8c0, ++ 0x33221100, 0xa8c05544, 0x00000301, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, 0xbe86c51f }; ++ ++ ddr_ptr = (void *)((u64)readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL)); ++ if (!ddr_ptr) ++ return; ++ ++ lmem_ptr = (void *)((u64)readl(BMU1_BASE_ADDR + BMU_ALLOC_CTRL)); ++ if (!lmem_ptr) ++ return; ++ ++ pr_info("Sending a dummy pkt to HIF %p %p\n", ddr_ptr, lmem_ptr); ++ physaddr = (u32)DDR_VIRT_TO_PFE(ddr_ptr); ++ ++ lmem_virt_addr = (void *)CBUS_PFE_TO_VIRT((unsigned long int)lmem_ptr); ++ ++ local_hdr.phyno = htons(0); /* RX_PHY_0 */ ++ local_hdr.length = htons(MIN_PKT_SIZE); ++ ++ local_hdr.next_ptr = htonl((u32)physaddr); ++ /*Mark checksum is correct */ ++ local_hdr.status = htonl((STATUS_IP_CHECKSUM_CORRECT | ++ STATUS_UDP_CHECKSUM_CORRECT | ++ STATUS_TCP_CHECKSUM_CORRECT | ++ STATUS_UNICAST_HASH_MATCH | ++ STATUS_CUMULATIVE_ARC_HIT)); ++ local_hdr.status2 = 0; ++ ++ copy_to_lmem((u32 *)lmem_virt_addr, (u32 *)&local_hdr, ++ sizeof(local_hdr)); ++ ++ copy_to_lmem((u32 *)(lmem_virt_addr + LMEM_HDR_SIZE), (u32 *)dummy_pkt, ++ 0x40); ++ ++ writel((unsigned long int)lmem_ptr, CLASS_INQ_PKTPTR); ++} ++ ++void pfe_hif_rx_idle(struct pfe_hif *hif) ++{ ++ int hif_stop_loop = 10; ++ u32 rx_status; ++ ++ pfe_hif_disable_rx_desc(hif); ++ pr_info("Bringing hif to idle state..."); ++ writel(0, HIF_INT_ENABLE); ++ /*If HIF Rx BDP is busy send a dummy packet */ ++ do { ++ rx_status = readl(HIF_RX_STATUS); ++ if (rx_status & BDP_CSR_RX_DMA_ACTV) ++ send_dummy_pkt_to_hif(); ++ ++ usleep_range(100, 150); ++ } while (--hif_stop_loop); ++ ++ if (readl(HIF_RX_STATUS) & BDP_CSR_RX_DMA_ACTV) ++ pr_info("Failed\n"); ++ else ++ pr_info("Done\n"); ++} ++#endif ++ ++static void pfe_hif_free_descr(struct pfe_hif *hif) ++{ ++ pr_info("%s\n", __func__); ++ ++ dma_free_coherent(pfe->dev, ++ hif->rx_ring_size * sizeof(struct hif_desc) + ++ hif->tx_ring_size * sizeof(struct hif_desc), ++ hif->descr_baseaddr_v, hif->descr_baseaddr_p); ++} ++ ++static void __maybe_unused pfe_hif_desc_dump(struct pfe_hif *hif) ++{ ++ struct hif_desc *desc; ++ unsigned long desc_p; ++ int ii = 0; ++ ++ pr_info("%s\n", __func__); ++ ++ desc = hif->rx_base; ++ desc_p = (u32)((u64)desc - (u64)hif->descr_baseaddr_v + ++ hif->descr_baseaddr_p); ++ ++ pr_info("HIF Rx desc base %p physical %x\n", desc, (u32)desc_p); ++ for (ii = 0; ii < hif->rx_ring_size; ii++) { ++ pr_info("status: %08x, ctrl: %08x, data: %08x, next: %x\n", ++ readl(&desc->status), readl(&desc->ctrl), ++ readl(&desc->data), readl(&desc->next)); ++ desc++; ++ } ++ ++ desc = hif->tx_base; ++ desc_p = ((u64)desc - (u64)hif->descr_baseaddr_v + ++ hif->descr_baseaddr_p); ++ ++ pr_info("HIF Tx desc base %p physical %x\n", desc, (u32)desc_p); ++ for (ii = 0; ii < hif->tx_ring_size; ii++) { ++ pr_info("status: %08x, ctrl: %08x, data: %08x, next: %x\n", ++ readl(&desc->status), readl(&desc->ctrl), ++ readl(&desc->data), readl(&desc->next)); ++ desc++; ++ } ++} ++ ++/* pfe_hif_release_buffers */ ++static void pfe_hif_release_buffers(struct pfe_hif *hif) ++{ ++ struct hif_desc *desc; ++ int i = 0; ++ ++ hif->rx_base = hif->descr_baseaddr_v; ++ ++ pr_info("%s\n", __func__); ++ ++ /*Free Rx buffers */ ++ desc = hif->rx_base; ++ for (i = 0; i < hif->rx_ring_size; i++) { ++ if (readl(&desc->data)) { ++ if ((i < hif->shm->rx_buf_pool_cnt) && ++ (!hif->shm->rx_buf_pool[i])) { ++ /* ++ * dma_unmap_single(hif->dev, desc->data, ++ * hif->rx_buf_len[i], DMA_FROM_DEVICE); ++ */ ++ dma_unmap_single(hif->dev, ++ DDR_PFE_TO_PHYS( ++ readl(&desc->data)), ++ hif->rx_buf_len[i], ++ DMA_FROM_DEVICE); ++ hif->shm->rx_buf_pool[i] = hif->rx_buf_addr[i]; ++ } else { ++ pr_err("%s: buffer pool already full\n" ++ , __func__); ++ } ++ } ++ ++ writel(0, &desc->data); ++ writel(0, &desc->status); ++ writel(0, &desc->ctrl); ++ desc++; ++ } ++} ++ ++/* ++ * pfe_hif_init_buffers ++ * This function initializes the HIF Rx/Tx ring descriptors and ++ * initialize Rx queue with buffers. ++ */ ++static int pfe_hif_init_buffers(struct pfe_hif *hif) ++{ ++ struct hif_desc *desc, *first_desc_p; ++ u32 data; ++ int i = 0; ++ ++ pr_info("%s\n", __func__); ++ ++ /* Check enough Rx buffers available in the shared memory */ ++ if (hif->shm->rx_buf_pool_cnt < hif->rx_ring_size) ++ return -ENOMEM; ++ ++ hif->rx_base = hif->descr_baseaddr_v; ++ memset(hif->rx_base, 0, hif->rx_ring_size * sizeof(struct hif_desc)); ++ ++ /*Initialize Rx descriptors */ ++ desc = hif->rx_base; ++ first_desc_p = (struct hif_desc *)hif->descr_baseaddr_p; ++ ++ for (i = 0; i < hif->rx_ring_size; i++) { ++ /* Initialize Rx buffers from the shared memory */ ++ ++ data = (u32)dma_map_single(hif->dev, hif->shm->rx_buf_pool[i], ++ pfe_pkt_size, DMA_FROM_DEVICE); ++ hif->rx_buf_addr[i] = hif->shm->rx_buf_pool[i]; ++ hif->rx_buf_len[i] = pfe_pkt_size; ++ hif->shm->rx_buf_pool[i] = NULL; ++ ++ if (likely(dma_mapping_error(hif->dev, data) == 0)) { ++ writel(DDR_PHYS_TO_PFE(data), &desc->data); ++ } else { ++ pr_err("%s : low on mem\n", __func__); ++ ++ goto err; ++ } ++ ++ writel(0, &desc->status); ++ ++ /* ++ * Ensure everything else is written to DDR before ++ * writing bd->ctrl ++ */ ++ wmb(); ++ ++ writel((BD_CTRL_PKT_INT_EN | BD_CTRL_LIFM ++ | BD_CTRL_DIR | BD_CTRL_DESC_EN ++ | BD_BUF_LEN(pfe_pkt_size)), &desc->ctrl); ++ ++ /* Chain descriptors */ ++ writel((u32)DDR_PHYS_TO_PFE(first_desc_p + i + 1), &desc->next); ++ desc++; ++ } ++ ++ /* Overwrite last descriptor to chain it to first one*/ ++ desc--; ++ writel((u32)DDR_PHYS_TO_PFE(first_desc_p), &desc->next); ++ ++ hif->rxtoclean_index = 0; ++ ++ /*Initialize Rx buffer descriptor ring base address */ ++ writel(DDR_PHYS_TO_PFE(hif->descr_baseaddr_p), HIF_RX_BDP_ADDR); ++ ++ hif->tx_base = hif->rx_base + hif->rx_ring_size; ++ first_desc_p = (struct hif_desc *)hif->descr_baseaddr_p + ++ hif->rx_ring_size; ++ memset(hif->tx_base, 0, hif->tx_ring_size * sizeof(struct hif_desc)); ++ ++ /*Initialize tx descriptors */ ++ desc = hif->tx_base; ++ ++ for (i = 0; i < hif->tx_ring_size; i++) { ++ /* Chain descriptors */ ++ writel((u32)DDR_PHYS_TO_PFE(first_desc_p + i + 1), &desc->next); ++ writel(0, &desc->ctrl); ++ desc++; ++ } ++ ++ /* Overwrite last descriptor to chain it to first one */ ++ desc--; ++ writel((u32)DDR_PHYS_TO_PFE(first_desc_p), &desc->next); ++ hif->txavail = hif->tx_ring_size; ++ hif->txtosend = 0; ++ hif->txtoclean = 0; ++ hif->txtoflush = 0; ++ ++ /*Initialize Tx buffer descriptor ring base address */ ++ writel((u32)DDR_PHYS_TO_PFE(first_desc_p), HIF_TX_BDP_ADDR); ++ ++ return 0; ++ ++err: ++ pfe_hif_release_buffers(hif); ++ return -ENOMEM; ++} ++ ++/* ++ * pfe_hif_client_register ++ * ++ * This function used to register a client driver with the HIF driver. ++ * ++ * Return value: ++ * 0 - on Successful registration ++ */ ++static int pfe_hif_client_register(struct pfe_hif *hif, u32 client_id, ++ struct hif_client_shm *client_shm) ++{ ++ struct hif_client *client = &hif->client[client_id]; ++ u32 i, cnt; ++ struct rx_queue_desc *rx_qbase; ++ struct tx_queue_desc *tx_qbase; ++ struct hif_rx_queue *rx_queue; ++ struct hif_tx_queue *tx_queue; ++ int err = 0; ++ ++ pr_info("%s\n", __func__); ++ ++ spin_lock_bh(&hif->tx_lock); ++ ++ if (test_bit(client_id, &hif->shm->g_client_status[0])) { ++ pr_err("%s: client %d already registered\n", ++ __func__, client_id); ++ err = -1; ++ goto unlock; ++ } ++ ++ memset(client, 0, sizeof(struct hif_client)); ++ ++ /* Initialize client Rx queues baseaddr, size */ ++ ++ cnt = CLIENT_CTRL_RX_Q_CNT(client_shm->ctrl); ++ /* Check if client is requesting for more queues than supported */ ++ if (cnt > HIF_CLIENT_QUEUES_MAX) ++ cnt = HIF_CLIENT_QUEUES_MAX; ++ ++ client->rx_qn = cnt; ++ rx_qbase = (struct rx_queue_desc *)client_shm->rx_qbase; ++ for (i = 0; i < cnt; i++) { ++ rx_queue = &client->rx_q[i]; ++ rx_queue->base = rx_qbase + i * client_shm->rx_qsize; ++ rx_queue->size = client_shm->rx_qsize; ++ rx_queue->write_idx = 0; ++ } ++ ++ /* Initialize client Tx queues baseaddr, size */ ++ cnt = CLIENT_CTRL_TX_Q_CNT(client_shm->ctrl); ++ ++ /* Check if client is requesting for more queues than supported */ ++ if (cnt > HIF_CLIENT_QUEUES_MAX) ++ cnt = HIF_CLIENT_QUEUES_MAX; ++ ++ client->tx_qn = cnt; ++ tx_qbase = (struct tx_queue_desc *)client_shm->tx_qbase; ++ for (i = 0; i < cnt; i++) { ++ tx_queue = &client->tx_q[i]; ++ tx_queue->base = tx_qbase + i * client_shm->tx_qsize; ++ tx_queue->size = client_shm->tx_qsize; ++ tx_queue->ack_idx = 0; ++ } ++ ++ set_bit(client_id, &hif->shm->g_client_status[0]); ++ ++unlock: ++ spin_unlock_bh(&hif->tx_lock); ++ ++ return err; ++} ++ ++/* ++ * pfe_hif_client_unregister ++ * ++ * This function used to unregister a client from the HIF driver. ++ * ++ */ ++static void pfe_hif_client_unregister(struct pfe_hif *hif, u32 client_id) ++{ ++ pr_info("%s\n", __func__); ++ ++ /* ++ * Mark client as no longer available (which prevents further packet ++ * receive for this client) ++ */ ++ spin_lock_bh(&hif->tx_lock); ++ ++ if (!test_bit(client_id, &hif->shm->g_client_status[0])) { ++ pr_err("%s: client %d not registered\n", __func__, ++ client_id); ++ ++ spin_unlock_bh(&hif->tx_lock); ++ return; ++ } ++ ++ clear_bit(client_id, &hif->shm->g_client_status[0]); ++ ++ spin_unlock_bh(&hif->tx_lock); ++} ++ ++/* ++ * client_put_rxpacket- ++ * This functions puts the Rx pkt in the given client Rx queue. ++ * It actually swap the Rx pkt in the client Rx descriptor buffer ++ * and returns the free buffer from it. ++ * ++ * If the function returns NULL means client Rx queue is full and ++ * packet couldn't send to client queue. ++ */ ++static void *client_put_rxpacket(struct hif_rx_queue *queue, void *pkt, u32 len, ++ u32 flags, u32 client_ctrl, u32 *rem_len) ++{ ++ void *free_pkt = NULL; ++ struct rx_queue_desc *desc = queue->base + queue->write_idx; ++ ++ if (readl(&desc->ctrl) & CL_DESC_OWN) { ++ if (page_mode) { ++ int rem_page_size = PAGE_SIZE - ++ PRESENT_OFST_IN_PAGE(pkt); ++ int cur_pkt_size = ROUND_MIN_RX_SIZE(len + ++ pfe_pkt_headroom); ++ *rem_len = (rem_page_size - cur_pkt_size); ++ if (*rem_len) { ++ free_pkt = pkt + cur_pkt_size; ++ get_page(virt_to_page(free_pkt)); ++ } else { ++ free_pkt = (void ++ *)__get_free_page(GFP_ATOMIC | GFP_DMA_PFE); ++ *rem_len = pfe_pkt_size; ++ } ++ } else { ++ free_pkt = kmalloc(PFE_BUF_SIZE, GFP_ATOMIC | ++ GFP_DMA_PFE); ++ *rem_len = PFE_BUF_SIZE - pfe_pkt_headroom; ++ } ++ ++ if (free_pkt) { ++ desc->data = pkt; ++ desc->client_ctrl = client_ctrl; ++ /* ++ * Ensure everything else is written to DDR before ++ * writing bd->ctrl ++ */ ++ smp_wmb(); ++ writel(CL_DESC_BUF_LEN(len) | flags, &desc->ctrl); ++ queue->write_idx = (queue->write_idx + 1) ++ & (queue->size - 1); ++ ++ free_pkt += pfe_pkt_headroom; ++ } ++ } ++ ++ return free_pkt; ++} ++ ++/* ++ * pfe_hif_rx_process- ++ * This function does pfe hif rx queue processing. ++ * Dequeue packet from Rx queue and send it to corresponding client queue ++ */ ++static int pfe_hif_rx_process(struct pfe_hif *hif, int budget) ++{ ++ struct hif_desc *desc; ++ struct hif_hdr *pkt_hdr; ++ struct __hif_hdr hif_hdr; ++ void *free_buf; ++ int rtc, len, rx_processed = 0; ++ struct __hif_desc local_desc; ++ int flags; ++ unsigned int desc_p; ++ unsigned int buf_size = 0; ++ ++ spin_lock_bh(&hif->lock); ++ ++ rtc = hif->rxtoclean_index; ++ ++ while (rx_processed < budget) { ++ desc = hif->rx_base + rtc; ++ ++ __memcpy12(&local_desc, desc); ++ ++ /* ACK pending Rx interrupt */ ++ if (local_desc.ctrl & BD_CTRL_DESC_EN) { ++ writel(HIF_INT | HIF_RXPKT_INT, HIF_INT_SRC); ++ ++ if (rx_processed == 0) { ++ if (napi_first_batch == 1) { ++ desc_p = hif->descr_baseaddr_p + ++ ((unsigned long int)(desc) - ++ (unsigned long ++ int)hif->descr_baseaddr_v); ++ napi_first_batch = 0; ++ } ++ } ++ ++ __memcpy12(&local_desc, desc); ++ ++ if (local_desc.ctrl & BD_CTRL_DESC_EN) ++ break; ++ } ++ ++ napi_first_batch = 0; ++ ++#ifdef HIF_NAPI_STATS ++ hif->napi_counters[NAPI_DESC_COUNT]++; ++#endif ++ len = BD_BUF_LEN(local_desc.ctrl); ++ /* ++ * dma_unmap_single(hif->dev, DDR_PFE_TO_PHYS(local_desc.data), ++ * hif->rx_buf_len[rtc], DMA_FROM_DEVICE); ++ */ ++ dma_unmap_single(hif->dev, DDR_PFE_TO_PHYS(local_desc.data), ++ hif->rx_buf_len[rtc], DMA_FROM_DEVICE); ++ ++ pkt_hdr = (struct hif_hdr *)hif->rx_buf_addr[rtc]; ++ ++ /* Track last HIF header received */ ++ if (!hif->started) { ++ hif->started = 1; ++ ++ __memcpy8(&hif_hdr, pkt_hdr); ++ ++ hif->qno = hif_hdr.hdr.q_num; ++ hif->client_id = hif_hdr.hdr.client_id; ++ hif->client_ctrl = (hif_hdr.hdr.client_ctrl1 << 16) | ++ hif_hdr.hdr.client_ctrl; ++ flags = CL_DESC_FIRST; ++ ++ } else { ++ flags = 0; ++ } ++ ++ if (local_desc.ctrl & BD_CTRL_LIFM) ++ flags |= CL_DESC_LAST; ++ ++ /* Check for valid client id and still registered */ ++ if ((hif->client_id >= HIF_CLIENTS_MAX) || ++ !(test_bit(hif->client_id, ++ &hif->shm->g_client_status[0]))) { ++ printk_ratelimited("%s: packet with invalid client id %d q_num %d\n", ++ __func__, ++ hif->client_id, ++ hif->qno); ++ ++ free_buf = pkt_hdr; ++ ++ goto pkt_drop; ++ } ++ ++ /* Check to valid queue number */ ++ if (hif->client[hif->client_id].rx_qn <= hif->qno) { ++ pr_info("%s: packet with invalid queue: %d\n" ++ , __func__, hif->qno); ++ hif->qno = 0; ++ } ++ ++ free_buf = ++ client_put_rxpacket(&hif->client[hif->client_id].rx_q[hif->qno], ++ (void *)pkt_hdr, len, flags, ++ hif->client_ctrl, &buf_size); ++ ++ hif_lib_indicate_client(hif->client_id, EVENT_RX_PKT_IND, ++ hif->qno); ++ ++ if (unlikely(!free_buf)) { ++#ifdef HIF_NAPI_STATS ++ hif->napi_counters[NAPI_CLIENT_FULL_COUNT]++; ++#endif ++ /* ++ * If we want to keep in polling mode to retry later, ++ * we need to tell napi that we consumed ++ * the full budget or we will hit a livelock scenario. ++ * The core code keeps this napi instance ++ * at the head of the list and none of the other ++ * instances get to run ++ */ ++ rx_processed = budget; ++ ++ if (flags & CL_DESC_FIRST) ++ hif->started = 0; ++ ++ break; ++ } ++ ++pkt_drop: ++ /*Fill free buffer in the descriptor */ ++ hif->rx_buf_addr[rtc] = free_buf; ++ hif->rx_buf_len[rtc] = min(pfe_pkt_size, buf_size); ++ writel((DDR_PHYS_TO_PFE ++ ((u32)dma_map_single(hif->dev, ++ free_buf, hif->rx_buf_len[rtc], DMA_FROM_DEVICE))), ++ &desc->data); ++ /* ++ * Ensure everything else is written to DDR before ++ * writing bd->ctrl ++ */ ++ wmb(); ++ writel((BD_CTRL_PKT_INT_EN | BD_CTRL_LIFM | BD_CTRL_DIR | ++ BD_CTRL_DESC_EN | BD_BUF_LEN(hif->rx_buf_len[rtc])), ++ &desc->ctrl); ++ ++ rtc = (rtc + 1) & (hif->rx_ring_size - 1); ++ ++ if (local_desc.ctrl & BD_CTRL_LIFM) { ++ if (!(hif->client_ctrl & HIF_CTRL_RX_CONTINUED)) { ++ rx_processed++; ++ ++#ifdef HIF_NAPI_STATS ++ hif->napi_counters[NAPI_PACKET_COUNT]++; ++#endif ++ } ++ hif->started = 0; ++ } ++ } ++ ++ hif->rxtoclean_index = rtc; ++ spin_unlock_bh(&hif->lock); ++ ++ /* we made some progress, re-start rx dma in case it stopped */ ++ hif_rx_dma_start(); ++ ++ return rx_processed; ++} ++ ++/* ++ * client_ack_txpacket- ++ * This function ack the Tx packet in the give client Tx queue by resetting ++ * ownership bit in the descriptor. ++ */ ++static int client_ack_txpacket(struct pfe_hif *hif, unsigned int client_id, ++ unsigned int q_no) ++{ ++ struct hif_tx_queue *queue = &hif->client[client_id].tx_q[q_no]; ++ struct tx_queue_desc *desc = queue->base + queue->ack_idx; ++ ++ if (readl(&desc->ctrl) & CL_DESC_OWN) { ++ writel((readl(&desc->ctrl) & ~CL_DESC_OWN), &desc->ctrl); ++ queue->ack_idx = (queue->ack_idx + 1) & (queue->size - 1); ++ ++ return 0; ++ ++ } else { ++ /*This should not happen */ ++ pr_err("%s: %d %d %d %d %d %p %d\n", __func__, ++ hif->txtosend, hif->txtoclean, hif->txavail, ++ client_id, q_no, queue, queue->ack_idx); ++ WARN(1, "%s: doesn't own this descriptor", __func__); ++ return 1; ++ } ++} ++ ++void __hif_tx_done_process(struct pfe_hif *hif, int count) ++{ ++ struct hif_desc *desc; ++ struct hif_desc_sw *desc_sw; ++ int ttc, tx_avl; ++ int pkts_done[HIF_CLIENTS_MAX] = {0, 0}; ++ ++ ttc = hif->txtoclean; ++ tx_avl = hif->txavail; ++ ++ while ((tx_avl < hif->tx_ring_size) && count--) { ++ desc = hif->tx_base + ttc; ++ ++ if (readl(&desc->ctrl) & BD_CTRL_DESC_EN) ++ break; ++ ++ desc_sw = &hif->tx_sw_queue[ttc]; ++ ++ if (desc_sw->data) { ++ /* ++ * dmap_unmap_single(hif->dev, desc_sw->data, ++ * desc_sw->len, DMA_TO_DEVICE); ++ */ ++ dma_unmap_single(hif->dev, desc_sw->data, ++ desc_sw->len, DMA_TO_DEVICE); ++ } ++ ++ if (desc_sw->client_id >= HIF_CLIENTS_MAX) { ++ pr_err("Invalid cl id %d\n", desc_sw->client_id); ++ break; ++ } ++ ++ pkts_done[desc_sw->client_id]++; ++ ++ client_ack_txpacket(hif, desc_sw->client_id, desc_sw->q_no); ++ ++ ttc = (ttc + 1) & (hif->tx_ring_size - 1); ++ tx_avl++; ++ } ++ ++ if (pkts_done[0]) ++ hif_lib_indicate_client(0, EVENT_TXDONE_IND, 0); ++ if (pkts_done[1]) ++ hif_lib_indicate_client(1, EVENT_TXDONE_IND, 0); ++ ++ hif->txtoclean = ttc; ++ hif->txavail = tx_avl; ++ ++ if (!count) { ++ tasklet_schedule(&hif->tx_cleanup_tasklet); ++ } else { ++ /*Enable Tx done interrupt */ ++ writel(readl_relaxed(HIF_INT_ENABLE) | HIF_TXPKT_INT, ++ HIF_INT_ENABLE); ++ } ++} ++ ++static void pfe_tx_do_cleanup(unsigned long data) ++{ ++ struct pfe_hif *hif = (struct pfe_hif *)data; ++ ++ writel(HIF_INT | HIF_TXPKT_INT, HIF_INT_SRC); ++ ++ hif_tx_done_process(hif, 64); ++} ++ ++/* ++ * __hif_xmit_pkt - ++ * This function puts one packet in the HIF Tx queue ++ */ ++void __hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int ++ q_no, void *data, u32 len, unsigned int flags) ++{ ++ struct hif_desc *desc; ++ struct hif_desc_sw *desc_sw; ++ ++ desc = hif->tx_base + hif->txtosend; ++ desc_sw = &hif->tx_sw_queue[hif->txtosend]; ++ ++ desc_sw->len = len; ++ desc_sw->client_id = client_id; ++ desc_sw->q_no = q_no; ++ desc_sw->flags = flags; ++ ++ if (flags & HIF_DONT_DMA_MAP) { ++ desc_sw->data = 0; ++ writel((u32)DDR_PHYS_TO_PFE(data), &desc->data); ++ } else { ++ desc_sw->data = dma_map_single(hif->dev, data, len, ++ DMA_TO_DEVICE); ++ writel((u32)DDR_PHYS_TO_PFE(desc_sw->data), &desc->data); ++ } ++ ++ hif->txtosend = (hif->txtosend + 1) & (hif->tx_ring_size - 1); ++ hif->txavail--; ++ ++ if ((!((flags & HIF_DATA_VALID) && (flags & ++ HIF_LAST_BUFFER)))) ++ goto skip_tx; ++ ++ /* ++ * Ensure everything else is written to DDR before ++ * writing bd->ctrl ++ */ ++ wmb(); ++ ++ do { ++ desc_sw = &hif->tx_sw_queue[hif->txtoflush]; ++ desc = hif->tx_base + hif->txtoflush; ++ ++ if (desc_sw->flags & HIF_LAST_BUFFER) { ++ writel((BD_CTRL_LIFM | ++ BD_CTRL_BRFETCH_DISABLE | BD_CTRL_RTFETCH_DISABLE ++ | BD_CTRL_PARSE_DISABLE | BD_CTRL_DESC_EN | ++ BD_CTRL_PKT_INT_EN | BD_BUF_LEN(desc_sw->len)), ++ &desc->ctrl); ++ } else { ++ writel((BD_CTRL_DESC_EN | ++ BD_BUF_LEN(desc_sw->len)), &desc->ctrl); ++ } ++ hif->txtoflush = (hif->txtoflush + 1) & (hif->tx_ring_size - 1); ++ } ++ while (hif->txtoflush != hif->txtosend) ++ ; ++ ++skip_tx: ++ return; ++} ++ ++static irqreturn_t wol_isr(int irq, void *dev_id) ++{ ++ pr_info("WoL\n"); ++ gemac_set_wol(EMAC1_BASE_ADDR, 0); ++ gemac_set_wol(EMAC2_BASE_ADDR, 0); ++ return IRQ_HANDLED; ++} ++ ++/* ++ * hif_isr- ++ * This ISR routine processes Rx/Tx done interrupts from the HIF hardware block ++ */ ++static irqreturn_t hif_isr(int irq, void *dev_id) ++{ ++ struct pfe_hif *hif = (struct pfe_hif *)dev_id; ++ int int_status; ++ int int_enable_mask; ++ ++ /*Read hif interrupt source register */ ++ int_status = readl_relaxed(HIF_INT_SRC); ++ int_enable_mask = readl_relaxed(HIF_INT_ENABLE); ++ ++ if ((int_status & HIF_INT) == 0) ++ return IRQ_NONE; ++ ++ int_status &= ~(HIF_INT); ++ ++ if (int_status & HIF_RXPKT_INT) { ++ int_status &= ~(HIF_RXPKT_INT); ++ int_enable_mask &= ~(HIF_RXPKT_INT); ++ ++ napi_first_batch = 1; ++ ++ if (napi_schedule_prep(&hif->napi)) { ++#ifdef HIF_NAPI_STATS ++ hif->napi_counters[NAPI_SCHED_COUNT]++; ++#endif ++ __napi_schedule(&hif->napi); ++ } ++ } ++ ++ if (int_status & HIF_TXPKT_INT) { ++ int_status &= ~(HIF_TXPKT_INT); ++ int_enable_mask &= ~(HIF_TXPKT_INT); ++ /*Schedule tx cleanup tassklet */ ++ tasklet_schedule(&hif->tx_cleanup_tasklet); ++ } ++ ++ /*Disable interrupts, they will be enabled after they are serviced */ ++ writel_relaxed(int_enable_mask, HIF_INT_ENABLE); ++ ++ if (int_status) { ++ pr_info("%s : Invalid interrupt : %d\n", __func__, ++ int_status); ++ writel(int_status, HIF_INT_SRC); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++void hif_process_client_req(struct pfe_hif *hif, int req, int data1, int data2) ++{ ++ unsigned int client_id = data1; ++ ++ if (client_id >= HIF_CLIENTS_MAX) { ++ pr_err("%s: client id %d out of bounds\n", __func__, ++ client_id); ++ return; ++ } ++ ++ switch (req) { ++ case REQUEST_CL_REGISTER: ++ /* Request for register a client */ ++ pr_info("%s: register client_id %d\n", ++ __func__, client_id); ++ pfe_hif_client_register(hif, client_id, (struct ++ hif_client_shm *)&hif->shm->client[client_id]); ++ break; ++ ++ case REQUEST_CL_UNREGISTER: ++ pr_info("%s: unregister client_id %d\n", ++ __func__, client_id); ++ ++ /* Request for unregister a client */ ++ pfe_hif_client_unregister(hif, client_id); ++ ++ break; ++ ++ default: ++ pr_err("%s: unsupported request %d\n", ++ __func__, req); ++ break; ++ } ++ ++ /* ++ * Process client Tx queues ++ * Currently we don't have checking for tx pending ++ */ ++} ++ ++/* ++ * pfe_hif_rx_poll ++ * This function is NAPI poll function to process HIF Rx queue. ++ */ ++static int pfe_hif_rx_poll(struct napi_struct *napi, int budget) ++{ ++ struct pfe_hif *hif = container_of(napi, struct pfe_hif, napi); ++ int work_done; ++ ++#ifdef HIF_NAPI_STATS ++ hif->napi_counters[NAPI_POLL_COUNT]++; ++#endif ++ ++ work_done = pfe_hif_rx_process(hif, budget); ++ ++ if (work_done < budget) { ++ napi_complete(napi); ++ writel(readl_relaxed(HIF_INT_ENABLE) | HIF_RXPKT_INT, ++ HIF_INT_ENABLE); ++ } ++#ifdef HIF_NAPI_STATS ++ else ++ hif->napi_counters[NAPI_FULL_BUDGET_COUNT]++; ++#endif ++ ++ return work_done; ++} ++ ++/* ++ * pfe_hif_init ++ * This function initializes the baseaddresses and irq, etc. ++ */ ++int pfe_hif_init(struct pfe *pfe) ++{ ++ struct pfe_hif *hif = &pfe->hif; ++ int err; ++ ++ pr_info("%s\n", __func__); ++ ++ hif->dev = pfe->dev; ++ hif->irq = pfe->hif_irq; ++ ++ err = pfe_hif_alloc_descr(hif); ++ if (err) ++ goto err0; ++ ++ if (pfe_hif_init_buffers(hif)) { ++ pr_err("%s: Could not initialize buffer descriptors\n" ++ , __func__); ++ err = -ENOMEM; ++ goto err1; ++ } ++ ++ /* Initialize NAPI for Rx processing */ ++ init_dummy_netdev(&hif->dummy_dev); ++ netif_napi_add(&hif->dummy_dev, &hif->napi, pfe_hif_rx_poll); ++ napi_enable(&hif->napi); ++ ++ spin_lock_init(&hif->tx_lock); ++ spin_lock_init(&hif->lock); ++ ++ hif_init(); ++ hif_rx_enable(); ++ hif_tx_enable(); ++ ++ /* Disable tx done interrupt */ ++ writel(HIF_INT_MASK, HIF_INT_ENABLE); ++ ++ gpi_enable(HGPI_BASE_ADDR); ++ ++ err = request_irq(hif->irq, hif_isr, 0, "pfe_hif", hif); ++ if (err) { ++ pr_err("%s: failed to get the hif IRQ = %d\n", ++ __func__, hif->irq); ++ goto err1; ++ } ++ ++ err = request_irq(pfe->wol_irq, wol_isr, 0, "pfe_wol", pfe); ++ if (err) { ++ pr_err("%s: failed to get the wol IRQ = %d\n", ++ __func__, pfe->wol_irq); ++ goto err1; ++ } ++ ++ tasklet_init(&hif->tx_cleanup_tasklet, ++ (void(*)(unsigned long))pfe_tx_do_cleanup, ++ (unsigned long)hif); ++ ++ return 0; ++err1: ++ pfe_hif_free_descr(hif); ++err0: ++ return err; ++} ++ ++/* pfe_hif_exit- */ ++void pfe_hif_exit(struct pfe *pfe) ++{ ++ struct pfe_hif *hif = &pfe->hif; ++ ++ pr_info("%s\n", __func__); ++ ++ tasklet_kill(&hif->tx_cleanup_tasklet); ++ ++ spin_lock_bh(&hif->lock); ++ hif->shm->g_client_status[0] = 0; ++ /* Make sure all clients are disabled*/ ++ hif->shm->g_client_status[1] = 0; ++ ++ spin_unlock_bh(&hif->lock); ++ ++ /*Disable Rx/Tx */ ++ gpi_disable(HGPI_BASE_ADDR); ++ hif_rx_disable(); ++ hif_tx_disable(); ++ ++ napi_disable(&hif->napi); ++ netif_napi_del(&hif->napi); ++ ++ free_irq(pfe->wol_irq, pfe); ++ free_irq(hif->irq, hif); ++ ++ pfe_hif_release_buffers(hif); ++ pfe_hif_free_descr(hif); ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_hif.h +@@ -0,0 +1,199 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#ifndef _PFE_HIF_H_ ++#define _PFE_HIF_H_ ++ ++#include ++ ++#define HIF_NAPI_STATS ++ ++#define HIF_CLIENT_QUEUES_MAX 16 ++#define HIF_RX_POLL_WEIGHT 64 ++ ++#define HIF_RX_PKT_MIN_SIZE 0x800 /* 2KB */ ++#define HIF_RX_PKT_MIN_SIZE_MASK ~(HIF_RX_PKT_MIN_SIZE - 1) ++#define ROUND_MIN_RX_SIZE(_sz) (((_sz) + (HIF_RX_PKT_MIN_SIZE - 1)) \ ++ & HIF_RX_PKT_MIN_SIZE_MASK) ++#define PRESENT_OFST_IN_PAGE(_buf) (((unsigned long int)(_buf) & (PAGE_SIZE \ ++ - 1)) & HIF_RX_PKT_MIN_SIZE_MASK) ++ ++enum { ++ NAPI_SCHED_COUNT = 0, ++ NAPI_POLL_COUNT, ++ NAPI_PACKET_COUNT, ++ NAPI_DESC_COUNT, ++ NAPI_FULL_BUDGET_COUNT, ++ NAPI_CLIENT_FULL_COUNT, ++ NAPI_MAX_COUNT ++}; ++ ++/* ++ * HIF_TX_DESC_NT value should be always greter than 4, ++ * Otherwise HIF_TX_POLL_MARK will become zero. ++ */ ++#define HIF_RX_DESC_NT 256 ++#define HIF_TX_DESC_NT 2048 ++ ++#define HIF_FIRST_BUFFER BIT(0) ++#define HIF_LAST_BUFFER BIT(1) ++#define HIF_DONT_DMA_MAP BIT(2) ++#define HIF_DATA_VALID BIT(3) ++#define HIF_TSO BIT(4) ++ ++enum { ++ PFE_CL_GEM0 = 0, ++ PFE_CL_GEM1, ++ HIF_CLIENTS_MAX ++}; ++ ++/*structure to store client queue info */ ++struct hif_rx_queue { ++ struct rx_queue_desc *base; ++ u32 size; ++ u32 write_idx; ++}; ++ ++struct hif_tx_queue { ++ struct tx_queue_desc *base; ++ u32 size; ++ u32 ack_idx; ++}; ++ ++/*Structure to store the client info */ ++struct hif_client { ++ int rx_qn; ++ struct hif_rx_queue rx_q[HIF_CLIENT_QUEUES_MAX]; ++ int tx_qn; ++ struct hif_tx_queue tx_q[HIF_CLIENT_QUEUES_MAX]; ++}; ++ ++/*HIF hardware buffer descriptor */ ++struct hif_desc { ++ u32 ctrl; ++ u32 status; ++ u32 data; ++ u32 next; ++}; ++ ++struct __hif_desc { ++ u32 ctrl; ++ u32 status; ++ u32 data; ++}; ++ ++struct hif_desc_sw { ++ dma_addr_t data; ++ u16 len; ++ u8 client_id; ++ u8 q_no; ++ u16 flags; ++}; ++ ++struct hif_hdr { ++ u8 client_id; ++ u8 q_num; ++ u16 client_ctrl; ++ u16 client_ctrl1; ++}; ++ ++struct __hif_hdr { ++ union { ++ struct hif_hdr hdr; ++ u32 word[2]; ++ }; ++}; ++ ++struct hif_ipsec_hdr { ++ u16 sa_handle[2]; ++} __packed; ++ ++/* HIF_CTRL_TX... defines */ ++#define HIF_CTRL_TX_CHECKSUM BIT(2) ++ ++/* HIF_CTRL_RX... defines */ ++#define HIF_CTRL_RX_OFFSET_OFST (24) ++#define HIF_CTRL_RX_CHECKSUMMED BIT(2) ++#define HIF_CTRL_RX_CONTINUED BIT(1) ++ ++struct pfe_hif { ++ /* To store registered clients in hif layer */ ++ struct hif_client client[HIF_CLIENTS_MAX]; ++ struct hif_shm *shm; ++ int irq; ++ ++ void *descr_baseaddr_v; ++ unsigned long descr_baseaddr_p; ++ ++ struct hif_desc *rx_base; ++ u32 rx_ring_size; ++ u32 rxtoclean_index; ++ void *rx_buf_addr[HIF_RX_DESC_NT]; ++ int rx_buf_len[HIF_RX_DESC_NT]; ++ unsigned int qno; ++ unsigned int client_id; ++ unsigned int client_ctrl; ++ unsigned int started; ++ ++ struct hif_desc *tx_base; ++ u32 tx_ring_size; ++ u32 txtosend; ++ u32 txtoclean; ++ u32 txavail; ++ u32 txtoflush; ++ struct hif_desc_sw tx_sw_queue[HIF_TX_DESC_NT]; ++ ++/* tx_lock synchronizes hif packet tx as well as pfe_hif structure access */ ++ spinlock_t tx_lock; ++/* lock synchronizes hif rx queue processing */ ++ spinlock_t lock; ++ struct net_device dummy_dev; ++ struct napi_struct napi; ++ struct device *dev; ++ ++#ifdef HIF_NAPI_STATS ++ unsigned int napi_counters[NAPI_MAX_COUNT]; ++#endif ++ struct tasklet_struct tx_cleanup_tasklet; ++}; ++ ++void __hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int ++ q_no, void *data, u32 len, unsigned int flags); ++int hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int q_no, ++ void *data, unsigned int len); ++void __hif_tx_done_process(struct pfe_hif *hif, int count); ++void hif_process_client_req(struct pfe_hif *hif, int req, int data1, int ++ data2); ++int pfe_hif_init(struct pfe *pfe); ++void pfe_hif_exit(struct pfe *pfe); ++void pfe_hif_rx_idle(struct pfe_hif *hif); ++static inline void hif_tx_done_process(struct pfe_hif *hif, int count) ++{ ++ spin_lock_bh(&hif->tx_lock); ++ __hif_tx_done_process(hif, count); ++ spin_unlock_bh(&hif->tx_lock); ++} ++ ++static inline void hif_tx_lock(struct pfe_hif *hif) ++{ ++ spin_lock_bh(&hif->tx_lock); ++} ++ ++static inline void hif_tx_unlock(struct pfe_hif *hif) ++{ ++ spin_unlock_bh(&hif->tx_lock); ++} ++ ++static inline int __hif_tx_avail(struct pfe_hif *hif) ++{ ++ return hif->txavail; ++} ++ ++#define __memcpy8(dst, src) memcpy(dst, src, 8) ++#define __memcpy12(dst, src) memcpy(dst, src, 12) ++#define __memcpy(dst, src, len) memcpy(dst, src, len) ++ ++#endif /* _PFE_HIF_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_hif_lib.c +@@ -0,0 +1,628 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pfe_mod.h" ++#include "pfe_hif.h" ++#include "pfe_hif_lib.h" ++ ++unsigned int lro_mode; ++unsigned int page_mode; ++unsigned int tx_qos = 1; ++module_param(tx_qos, uint, 0444); ++MODULE_PARM_DESC(tx_qos, "0: disable ,\n" ++ "1: enable (default), guarantee no packet drop at TMU level\n"); ++unsigned int pfe_pkt_size; ++unsigned int pfe_pkt_headroom; ++unsigned int emac_txq_cnt; ++ ++/* ++ * @pfe_hal_lib.c. ++ * Common functions used by HIF client drivers ++ */ ++ ++/*HIF shared memory Global variable */ ++struct hif_shm ghif_shm; ++ ++/* Cleanup the HIF shared memory, release HIF rx_buffer_pool. ++ * This function should be called after pfe_hif_exit ++ * ++ * @param[in] hif_shm Shared memory address location in DDR ++ */ ++static void pfe_hif_shm_clean(struct hif_shm *hif_shm) ++{ ++ int i; ++ void *pkt; ++ ++ for (i = 0; i < hif_shm->rx_buf_pool_cnt; i++) { ++ pkt = hif_shm->rx_buf_pool[i]; ++ if (pkt) { ++ hif_shm->rx_buf_pool[i] = NULL; ++ pkt -= pfe_pkt_headroom; ++ ++ if (page_mode) ++ put_page(virt_to_page(pkt)); ++ else ++ kfree(pkt); ++ } ++ } ++} ++ ++/* Initialize shared memory used between HIF driver and clients, ++ * allocate rx_buffer_pool required for HIF Rx descriptors. ++ * This function should be called before initializing HIF driver. ++ * ++ * @param[in] hif_shm Shared memory address location in DDR ++ * @rerurn 0 - on succes, <0 on fail to initialize ++ */ ++static int pfe_hif_shm_init(struct hif_shm *hif_shm) ++{ ++ int i; ++ void *pkt; ++ ++ memset(hif_shm, 0, sizeof(struct hif_shm)); ++ hif_shm->rx_buf_pool_cnt = HIF_RX_DESC_NT; ++ ++ for (i = 0; i < hif_shm->rx_buf_pool_cnt; i++) { ++ if (page_mode) { ++ pkt = (void *)__get_free_page(GFP_KERNEL | ++ GFP_DMA_PFE); ++ } else { ++ pkt = kmalloc(PFE_BUF_SIZE, GFP_KERNEL | GFP_DMA_PFE); ++ } ++ ++ if (pkt) ++ hif_shm->rx_buf_pool[i] = pkt + pfe_pkt_headroom; ++ else ++ goto err0; ++ } ++ ++ return 0; ++ ++err0: ++ pr_err("%s Low memory\n", __func__); ++ pfe_hif_shm_clean(hif_shm); ++ return -ENOMEM; ++} ++ ++/*This function sends indication to HIF driver ++ * ++ * @param[in] hif hif context ++ */ ++static void hif_lib_indicate_hif(struct pfe_hif *hif, int req, int data1, int ++ data2) ++{ ++ hif_process_client_req(hif, req, data1, data2); ++} ++ ++void hif_lib_indicate_client(int client_id, int event_type, int qno) ++{ ++ struct hif_client_s *client = pfe->hif_client[client_id]; ++ ++ if (!client || (event_type >= HIF_EVENT_MAX) || (qno >= ++ HIF_CLIENT_QUEUES_MAX)) ++ return; ++ ++ if (!test_and_set_bit(qno, &client->queue_mask[event_type])) ++ client->event_handler(client->priv, event_type, qno); ++} ++ ++/*This function releases Rx queue descriptors memory and pre-filled buffers ++ * ++ * @param[in] client hif_client context ++ */ ++static void hif_lib_client_release_rx_buffers(struct hif_client_s *client) ++{ ++ struct rx_queue_desc *desc; ++ int qno, ii; ++ void *buf; ++ ++ for (qno = 0; qno < client->rx_qn; qno++) { ++ desc = client->rx_q[qno].base; ++ ++ for (ii = 0; ii < client->rx_q[qno].size; ii++) { ++ buf = (void *)desc->data; ++ if (buf) { ++ buf -= pfe_pkt_headroom; ++ ++ if (page_mode) ++ free_page((unsigned long)buf); ++ else ++ kfree(buf); ++ ++ desc->ctrl = 0; ++ } ++ ++ desc++; ++ } ++ } ++ ++ kfree(client->rx_qbase); ++} ++ ++/*This function allocates memory for the rxq descriptors and pre-fill rx queues ++ * with buffers. ++ * @param[in] client client context ++ * @param[in] q_size size of the rxQ, all queues are of same size ++ */ ++static int hif_lib_client_init_rx_buffers(struct hif_client_s *client, int ++ q_size) ++{ ++ struct rx_queue_desc *desc; ++ struct hif_client_rx_queue *queue; ++ int ii, qno; ++ ++ /*Allocate memory for the client queues */ ++ client->rx_qbase = kzalloc(client->rx_qn * q_size * sizeof(struct ++ rx_queue_desc), GFP_KERNEL); ++ if (!client->rx_qbase) ++ goto err; ++ ++ for (qno = 0; qno < client->rx_qn; qno++) { ++ queue = &client->rx_q[qno]; ++ ++ queue->base = client->rx_qbase + qno * q_size * sizeof(struct ++ rx_queue_desc); ++ queue->size = q_size; ++ queue->read_idx = 0; ++ queue->write_idx = 0; ++ ++ pr_debug("rx queue: %d, base: %p, size: %d\n", qno, ++ queue->base, queue->size); ++ } ++ ++ for (qno = 0; qno < client->rx_qn; qno++) { ++ queue = &client->rx_q[qno]; ++ desc = queue->base; ++ ++ for (ii = 0; ii < queue->size; ii++) { ++ desc->ctrl = CL_DESC_BUF_LEN(pfe_pkt_size) | ++ CL_DESC_OWN; ++ desc++; ++ } ++ } ++ ++ return 0; ++ ++err: ++ return 1; ++} ++ ++ ++static void hif_lib_client_cleanup_tx_queue(struct hif_client_tx_queue *queue) ++{ ++ pr_debug("%s\n", __func__); ++ ++ /* ++ * Check if there are any pending packets. Client must flush the tx ++ * queues before unregistering, by calling by calling ++ * hif_lib_tx_get_next_complete() ++ * ++ * Hif no longer calls since we are no longer registered ++ */ ++ if (queue->tx_pending) ++ pr_err("%s: pending transmit packets\n", __func__); ++} ++ ++static void hif_lib_client_release_tx_buffers(struct hif_client_s *client) ++{ ++ int qno; ++ ++ pr_debug("%s\n", __func__); ++ ++ for (qno = 0; qno < client->tx_qn; qno++) ++ hif_lib_client_cleanup_tx_queue(&client->tx_q[qno]); ++ ++ kfree(client->tx_qbase); ++} ++ ++static int hif_lib_client_init_tx_buffers(struct hif_client_s *client, int ++ q_size) ++{ ++ struct hif_client_tx_queue *queue; ++ int qno; ++ ++ client->tx_qbase = kzalloc(client->tx_qn * q_size * sizeof(struct ++ tx_queue_desc), GFP_KERNEL); ++ if (!client->tx_qbase) ++ return 1; ++ ++ for (qno = 0; qno < client->tx_qn; qno++) { ++ queue = &client->tx_q[qno]; ++ ++ queue->base = client->tx_qbase + qno * q_size * sizeof(struct ++ tx_queue_desc); ++ queue->size = q_size; ++ queue->read_idx = 0; ++ queue->write_idx = 0; ++ queue->tx_pending = 0; ++ queue->nocpy_flag = 0; ++ queue->prev_tmu_tx_pkts = 0; ++ queue->done_tmu_tx_pkts = 0; ++ ++ pr_debug("tx queue: %d, base: %p, size: %d\n", qno, ++ queue->base, queue->size); ++ } ++ ++ return 0; ++} ++ ++static int hif_lib_event_dummy(void *priv, int event_type, int qno) ++{ ++ return 0; ++} ++ ++int hif_lib_client_register(struct hif_client_s *client) ++{ ++ struct hif_shm *hif_shm; ++ struct hif_client_shm *client_shm; ++ int err, i; ++ /* int loop_cnt = 0; */ ++ ++ pr_debug("%s\n", __func__); ++ ++ /*Allocate memory before spin_lock*/ ++ if (hif_lib_client_init_rx_buffers(client, client->rx_qsize)) { ++ err = -ENOMEM; ++ goto err_rx; ++ } ++ ++ if (hif_lib_client_init_tx_buffers(client, client->tx_qsize)) { ++ err = -ENOMEM; ++ goto err_tx; ++ } ++ ++ spin_lock_bh(&pfe->hif.lock); ++ if (!(client->pfe) || (client->id >= HIF_CLIENTS_MAX) || ++ (pfe->hif_client[client->id])) { ++ err = -EINVAL; ++ goto err; ++ } ++ ++ hif_shm = client->pfe->hif.shm; ++ ++ if (!client->event_handler) ++ client->event_handler = hif_lib_event_dummy; ++ ++ /*Initialize client specific shared memory */ ++ client_shm = (struct hif_client_shm *)&hif_shm->client[client->id]; ++ client_shm->rx_qbase = (unsigned long int)client->rx_qbase; ++ client_shm->rx_qsize = client->rx_qsize; ++ client_shm->tx_qbase = (unsigned long int)client->tx_qbase; ++ client_shm->tx_qsize = client->tx_qsize; ++ client_shm->ctrl = (client->tx_qn << CLIENT_CTRL_TX_Q_CNT_OFST) | ++ (client->rx_qn << CLIENT_CTRL_RX_Q_CNT_OFST); ++ /* spin_lock_init(&client->rx_lock); */ ++ ++ for (i = 0; i < HIF_EVENT_MAX; i++) { ++ client->queue_mask[i] = 0; /* ++ * By default all events are ++ * unmasked ++ */ ++ } ++ ++ /*Indicate to HIF driver*/ ++ hif_lib_indicate_hif(&pfe->hif, REQUEST_CL_REGISTER, client->id, 0); ++ ++ pr_debug("%s: client: %p, client_id: %d, tx_qsize: %d, rx_qsize: %d\n", ++ __func__, client, client->id, client->tx_qsize, ++ client->rx_qsize); ++ ++ client->cpu_id = -1; ++ ++ pfe->hif_client[client->id] = client; ++ spin_unlock_bh(&pfe->hif.lock); ++ ++ return 0; ++ ++err: ++ spin_unlock_bh(&pfe->hif.lock); ++ hif_lib_client_release_tx_buffers(client); ++ ++err_tx: ++ hif_lib_client_release_rx_buffers(client); ++ ++err_rx: ++ return err; ++} ++ ++int hif_lib_client_unregister(struct hif_client_s *client) ++{ ++ struct pfe *pfe = client->pfe; ++ u32 client_id = client->id; ++ ++ pr_info( ++ "%s : client: %p, client_id: %d, txQ_depth: %d, rxQ_depth: %d\n" ++ , __func__, client, client->id, client->tx_qsize, ++ client->rx_qsize); ++ ++ spin_lock_bh(&pfe->hif.lock); ++ hif_lib_indicate_hif(&pfe->hif, REQUEST_CL_UNREGISTER, client->id, 0); ++ ++ hif_lib_client_release_tx_buffers(client); ++ hif_lib_client_release_rx_buffers(client); ++ pfe->hif_client[client_id] = NULL; ++ spin_unlock_bh(&pfe->hif.lock); ++ ++ return 0; ++} ++ ++int hif_lib_event_handler_start(struct hif_client_s *client, int event, ++ int qno) ++{ ++ struct hif_client_rx_queue *queue = &client->rx_q[qno]; ++ struct rx_queue_desc *desc = queue->base + queue->read_idx; ++ ++ if ((event >= HIF_EVENT_MAX) || (qno >= HIF_CLIENT_QUEUES_MAX)) { ++ pr_debug("%s: Unsupported event : %d queue number : %d\n", ++ __func__, event, qno); ++ return -1; ++ } ++ ++ test_and_clear_bit(qno, &client->queue_mask[event]); ++ ++ switch (event) { ++ case EVENT_RX_PKT_IND: ++ if (!(desc->ctrl & CL_DESC_OWN)) ++ hif_lib_indicate_client(client->id, ++ EVENT_RX_PKT_IND, qno); ++ break; ++ ++ case EVENT_HIGH_RX_WM: ++ case EVENT_TXDONE_IND: ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++/* ++ * This function gets one packet from the specified client queue ++ * It also refill the rx buffer ++ */ ++void *hif_lib_receive_pkt(struct hif_client_s *client, int qno, int *len, int ++ *ofst, unsigned int *rx_ctrl, ++ unsigned int *desc_ctrl, void **priv_data) ++{ ++ struct hif_client_rx_queue *queue = &client->rx_q[qno]; ++ struct rx_queue_desc *desc; ++ void *pkt = NULL; ++ ++ /* ++ * Following lock is to protect rx queue access from, ++ * hif_lib_event_handler_start. ++ * In general below lock is not required, because hif_lib_xmit_pkt and ++ * hif_lib_event_handler_start are called from napi poll and which is ++ * not re-entrant. But if some client use in different way this lock is ++ * required. ++ */ ++ /*spin_lock_irqsave(&client->rx_lock, flags); */ ++ desc = queue->base + queue->read_idx; ++ if (!(desc->ctrl & CL_DESC_OWN)) { ++ pkt = desc->data - pfe_pkt_headroom; ++ ++ *rx_ctrl = desc->client_ctrl; ++ *desc_ctrl = desc->ctrl; ++ ++ if (desc->ctrl & CL_DESC_FIRST) { ++ u16 size = *rx_ctrl >> HIF_CTRL_RX_OFFSET_OFST; ++ ++ if (size) { ++ size += PFE_PARSE_INFO_SIZE; ++ *len = CL_DESC_BUF_LEN(desc->ctrl) - ++ PFE_PKT_HEADER_SZ - size; ++ *ofst = pfe_pkt_headroom + PFE_PKT_HEADER_SZ ++ + size; ++ *priv_data = desc->data + PFE_PKT_HEADER_SZ; ++ } else { ++ *len = CL_DESC_BUF_LEN(desc->ctrl) - ++ PFE_PKT_HEADER_SZ - PFE_PARSE_INFO_SIZE; ++ *ofst = pfe_pkt_headroom ++ + PFE_PKT_HEADER_SZ ++ + PFE_PARSE_INFO_SIZE; ++ *priv_data = NULL; ++ } ++ ++ } else { ++ *len = CL_DESC_BUF_LEN(desc->ctrl); ++ *ofst = pfe_pkt_headroom; ++ } ++ ++ /* ++ * Needed so we don't free a buffer/page ++ * twice on module_exit ++ */ ++ desc->data = NULL; ++ ++ /* ++ * Ensure everything else is written to DDR before ++ * writing bd->ctrl ++ */ ++ smp_wmb(); ++ ++ desc->ctrl = CL_DESC_BUF_LEN(pfe_pkt_size) | CL_DESC_OWN; ++ queue->read_idx = (queue->read_idx + 1) & (queue->size - 1); ++ } ++ ++ /*spin_unlock_irqrestore(&client->rx_lock, flags); */ ++ return pkt; ++} ++ ++static inline void hif_hdr_write(struct hif_hdr *pkt_hdr, unsigned int ++ client_id, unsigned int qno, ++ u32 client_ctrl) ++{ ++ /* Optimize the write since the destinaton may be non-cacheable */ ++ if (!((unsigned long)pkt_hdr & 0x3)) { ++ ((u32 *)pkt_hdr)[0] = (client_ctrl << 16) | (qno << 8) | ++ client_id; ++ } else { ++ ((u16 *)pkt_hdr)[0] = (qno << 8) | (client_id & 0xFF); ++ ((u16 *)pkt_hdr)[1] = (client_ctrl & 0xFFFF); ++ } ++} ++ ++/*This function puts the given packet in the specific client queue */ ++void __hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void ++ *data, unsigned int len, u32 client_ctrl, ++ unsigned int flags, void *client_data) ++{ ++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; ++ struct tx_queue_desc *desc = queue->base + queue->write_idx; ++ ++ /* First buffer */ ++ if (flags & HIF_FIRST_BUFFER) { ++ data -= sizeof(struct hif_hdr); ++ len += sizeof(struct hif_hdr); ++ ++ hif_hdr_write(data, client->id, qno, client_ctrl); ++ } ++ ++ desc->data = client_data; ++ desc->ctrl = CL_DESC_OWN | CL_DESC_FLAGS(flags); ++ ++ __hif_xmit_pkt(&pfe->hif, client->id, qno, data, len, flags); ++ ++ queue->write_idx = (queue->write_idx + 1) & (queue->size - 1); ++ queue->tx_pending++; ++ queue->jiffies_last_packet = jiffies; ++} ++ ++void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno, ++ unsigned int *flags, int count) ++{ ++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; ++ struct tx_queue_desc *desc = queue->base + queue->read_idx; ++ ++ pr_debug("%s: qno : %d rd_indx: %d pending:%d\n", __func__, qno, ++ queue->read_idx, queue->tx_pending); ++ ++ if (!queue->tx_pending) ++ return NULL; ++ ++ if (queue->nocpy_flag && !queue->done_tmu_tx_pkts) { ++ u32 tmu_tx_pkts = be32_to_cpu(pe_dmem_read(TMU0_ID + ++ client->id, TMU_DM_TX_TRANS, 4)); ++ ++ if (queue->prev_tmu_tx_pkts > tmu_tx_pkts) ++ queue->done_tmu_tx_pkts = UINT_MAX - ++ queue->prev_tmu_tx_pkts + tmu_tx_pkts; ++ else ++ queue->done_tmu_tx_pkts = tmu_tx_pkts - ++ queue->prev_tmu_tx_pkts; ++ ++ queue->prev_tmu_tx_pkts = tmu_tx_pkts; ++ ++ if (!queue->done_tmu_tx_pkts) ++ return NULL; ++ } ++ ++ if (desc->ctrl & CL_DESC_OWN) ++ return NULL; ++ ++ queue->read_idx = (queue->read_idx + 1) & (queue->size - 1); ++ queue->tx_pending--; ++ ++ *flags = CL_DESC_GET_FLAGS(desc->ctrl); ++ ++ if (queue->done_tmu_tx_pkts && (*flags & HIF_LAST_BUFFER)) ++ queue->done_tmu_tx_pkts--; ++ ++ return desc->data; ++} ++ ++static void hif_lib_tmu_credit_init(struct pfe *pfe) ++{ ++ int i, q; ++ ++ for (i = 0; i < NUM_GEMAC_SUPPORT; i++) ++ for (q = 0; q < emac_txq_cnt; q++) { ++ pfe->tmu_credit.tx_credit_max[i][q] = (q == 0) ? ++ DEFAULT_Q0_QDEPTH : DEFAULT_MAX_QDEPTH; ++ pfe->tmu_credit.tx_credit[i][q] = ++ pfe->tmu_credit.tx_credit_max[i][q]; ++ } ++} ++ ++/* __hif_lib_update_credit ++ * ++ * @param[in] client hif client context ++ * @param[in] queue queue number in match with TMU ++ */ ++void __hif_lib_update_credit(struct hif_client_s *client, unsigned int queue) ++{ ++ unsigned int tmu_tx_packets, tmp; ++ ++ if (tx_qos) { ++ tmu_tx_packets = be32_to_cpu(pe_dmem_read(TMU0_ID + ++ client->id, (TMU_DM_TX_TRANS + (queue * 4)), 4)); ++ ++ /* tx_packets counter overflowed */ ++ if (tmu_tx_packets > ++ pfe->tmu_credit.tx_packets[client->id][queue]) { ++ tmp = UINT_MAX - tmu_tx_packets + ++ pfe->tmu_credit.tx_packets[client->id][queue]; ++ ++ pfe->tmu_credit.tx_credit[client->id][queue] = ++ pfe->tmu_credit.tx_credit_max[client->id][queue] - tmp; ++ } else { ++ /* TMU tx <= pfe_eth tx, normal case or both OF since ++ * last time ++ */ ++ pfe->tmu_credit.tx_credit[client->id][queue] = ++ pfe->tmu_credit.tx_credit_max[client->id][queue] - ++ (pfe->tmu_credit.tx_packets[client->id][queue] - ++ tmu_tx_packets); ++ } ++ } ++} ++ ++int pfe_hif_lib_init(struct pfe *pfe) ++{ ++ int rc; ++ ++ pr_info("%s\n", __func__); ++ ++ if (lro_mode) { ++ page_mode = 1; ++ pfe_pkt_size = min(PAGE_SIZE, MAX_PFE_PKT_SIZE); ++ pfe_pkt_headroom = 0; ++ } else { ++ page_mode = 0; ++ pfe_pkt_size = PFE_PKT_SIZE; ++ pfe_pkt_headroom = PFE_PKT_HEADROOM; ++ } ++ ++ if (tx_qos) ++ emac_txq_cnt = EMAC_TXQ_CNT / 2; ++ else ++ emac_txq_cnt = EMAC_TXQ_CNT; ++ ++ hif_lib_tmu_credit_init(pfe); ++ pfe->hif.shm = &ghif_shm; ++ rc = pfe_hif_shm_init(pfe->hif.shm); ++ ++ return rc; ++} ++ ++void pfe_hif_lib_exit(struct pfe *pfe) ++{ ++ pr_info("%s\n", __func__); ++ ++ pfe_hif_shm_clean(pfe->hif.shm); ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_hif_lib.h +@@ -0,0 +1,229 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#ifndef _PFE_HIF_LIB_H_ ++#define _PFE_HIF_LIB_H_ ++ ++#include "pfe_hif.h" ++ ++#define HIF_CL_REQ_TIMEOUT 10 ++#define GFP_DMA_PFE 0 ++#define PFE_PARSE_INFO_SIZE 16 ++ ++enum { ++ REQUEST_CL_REGISTER = 0, ++ REQUEST_CL_UNREGISTER, ++ HIF_REQUEST_MAX ++}; ++ ++enum { ++ /* Event to indicate that client rx queue is reached water mark level */ ++ EVENT_HIGH_RX_WM = 0, ++ /* Event to indicate that, packet received for client */ ++ EVENT_RX_PKT_IND, ++ /* Event to indicate that, packet tx done for client */ ++ EVENT_TXDONE_IND, ++ HIF_EVENT_MAX ++}; ++ ++/*structure to store client queue info */ ++ ++/*structure to store client queue info */ ++struct hif_client_rx_queue { ++ struct rx_queue_desc *base; ++ u32 size; ++ u32 read_idx; ++ u32 write_idx; ++}; ++ ++struct hif_client_tx_queue { ++ struct tx_queue_desc *base; ++ u32 size; ++ u32 read_idx; ++ u32 write_idx; ++ u32 tx_pending; ++ unsigned long jiffies_last_packet; ++ u32 nocpy_flag; ++ u32 prev_tmu_tx_pkts; ++ u32 done_tmu_tx_pkts; ++}; ++ ++struct hif_client_s { ++ int id; ++ int tx_qn; ++ int rx_qn; ++ void *rx_qbase; ++ void *tx_qbase; ++ int tx_qsize; ++ int rx_qsize; ++ int cpu_id; ++ struct hif_client_tx_queue tx_q[HIF_CLIENT_QUEUES_MAX]; ++ struct hif_client_rx_queue rx_q[HIF_CLIENT_QUEUES_MAX]; ++ int (*event_handler)(void *priv, int event, int data); ++ unsigned long queue_mask[HIF_EVENT_MAX]; ++ struct pfe *pfe; ++ void *priv; ++}; ++ ++/* ++ * Client specific shared memory ++ * It contains number of Rx/Tx queues, base addresses and queue sizes ++ */ ++struct hif_client_shm { ++ u32 ctrl; /*0-7: number of Rx queues, 8-15: number of tx queues */ ++ unsigned long rx_qbase; /*Rx queue base address */ ++ u32 rx_qsize; /*each Rx queue size, all Rx queues are of same size */ ++ unsigned long tx_qbase; /* Tx queue base address */ ++ u32 tx_qsize; /*each Tx queue size, all Tx queues are of same size */ ++}; ++ ++/*Client shared memory ctrl bit description */ ++#define CLIENT_CTRL_RX_Q_CNT_OFST 0 ++#define CLIENT_CTRL_TX_Q_CNT_OFST 8 ++#define CLIENT_CTRL_RX_Q_CNT(ctrl) (((ctrl) >> CLIENT_CTRL_RX_Q_CNT_OFST) \ ++ & 0xFF) ++#define CLIENT_CTRL_TX_Q_CNT(ctrl) (((ctrl) >> CLIENT_CTRL_TX_Q_CNT_OFST) \ ++ & 0xFF) ++ ++/* ++ * Shared memory used to communicate between HIF driver and host/client drivers ++ * Before starting the hif driver rx_buf_pool ans rx_buf_pool_cnt should be ++ * initialized with host buffers and buffers count in the pool. ++ * rx_buf_pool_cnt should be >= HIF_RX_DESC_NT. ++ * ++ */ ++struct hif_shm { ++ u32 rx_buf_pool_cnt; /*Number of rx buffers available*/ ++ /*Rx buffers required to initialize HIF rx descriptors */ ++ void *rx_buf_pool[HIF_RX_DESC_NT]; ++ unsigned long g_client_status[2]; /*Global client status bit mask */ ++ /* Client specific shared memory */ ++ struct hif_client_shm client[HIF_CLIENTS_MAX]; ++}; ++ ++#define CL_DESC_OWN BIT(31) ++/* This sets owner ship to HIF driver */ ++#define CL_DESC_LAST BIT(30) ++/* This indicates last packet for multi buffers handling */ ++#define CL_DESC_FIRST BIT(29) ++/* This indicates first packet for multi buffers handling */ ++ ++#define CL_DESC_BUF_LEN(x) ((x) & 0xFFFF) ++#define CL_DESC_FLAGS(x) (((x) & 0xF) << 16) ++#define CL_DESC_GET_FLAGS(x) (((x) >> 16) & 0xF) ++ ++struct rx_queue_desc { ++ void *data; ++ u32 ctrl; /*0-15bit len, 16-20bit flags, 31bit owner*/ ++ u32 client_ctrl; ++}; ++ ++struct tx_queue_desc { ++ void *data; ++ u32 ctrl; /*0-15bit len, 16-20bit flags, 31bit owner*/ ++}; ++ ++/* HIF Rx is not working properly for 2-byte aligned buffers and ++ * ip_header should be 4byte aligned for better iperformance. ++ * "ip_header = 64 + 6(hif_header) + 14 (MAC Header)" will be 4byte aligned. ++ */ ++#define PFE_PKT_HEADER_SZ sizeof(struct hif_hdr) ++/* must be big enough for headroom, pkt size and skb shared info */ ++#define PFE_BUF_SIZE 2048 ++#define PFE_PKT_HEADROOM 128 ++ ++#define SKB_SHARED_INFO_SIZE SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) ++#define PFE_PKT_SIZE (PFE_BUF_SIZE - PFE_PKT_HEADROOM \ ++ - SKB_SHARED_INFO_SIZE) ++#define MAX_L2_HDR_SIZE 14 /* Not correct for VLAN/PPPoE */ ++#define MAX_L3_HDR_SIZE 20 /* Not correct for IPv6 */ ++#define MAX_L4_HDR_SIZE 60 /* TCP with maximum options */ ++#define MAX_HDR_SIZE (MAX_L2_HDR_SIZE + MAX_L3_HDR_SIZE \ ++ + MAX_L4_HDR_SIZE) ++/* Used in page mode to clamp packet size to the maximum supported by the hif ++ *hw interface (<16KiB) ++ */ ++#define MAX_PFE_PKT_SIZE 16380UL ++ ++extern unsigned int pfe_pkt_size; ++extern unsigned int pfe_pkt_headroom; ++extern unsigned int page_mode; ++extern unsigned int lro_mode; ++extern unsigned int tx_qos; ++extern unsigned int emac_txq_cnt; ++ ++int pfe_hif_lib_init(struct pfe *pfe); ++void pfe_hif_lib_exit(struct pfe *pfe); ++int hif_lib_client_register(struct hif_client_s *client); ++int hif_lib_client_unregister(struct hif_client_s *client); ++void __hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void ++ *data, unsigned int len, u32 client_ctrl, ++ unsigned int flags, void *client_data); ++int hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void *data, ++ unsigned int len, u32 client_ctrl, void *client_data); ++void hif_lib_indicate_client(int cl_id, int event, int data); ++int hif_lib_event_handler_start(struct hif_client_s *client, int event, int ++ data); ++int hif_lib_tmu_queue_start(struct hif_client_s *client, int qno); ++int hif_lib_tmu_queue_stop(struct hif_client_s *client, int qno); ++void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno, ++ unsigned int *flags, int count); ++void *hif_lib_receive_pkt(struct hif_client_s *client, int qno, int *len, int ++ *ofst, unsigned int *rx_ctrl, ++ unsigned int *desc_ctrl, void **priv_data); ++void __hif_lib_update_credit(struct hif_client_s *client, unsigned int queue); ++void hif_lib_set_rx_cpu_affinity(struct hif_client_s *client, int cpu_id); ++void hif_lib_set_tx_queue_nocpy(struct hif_client_s *client, int qno, int ++ enable); ++static inline int hif_lib_tx_avail(struct hif_client_s *client, unsigned int ++ qno) ++{ ++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; ++ ++ return (queue->size - queue->tx_pending); ++} ++ ++static inline int hif_lib_get_tx_wr_index(struct hif_client_s *client, unsigned ++ int qno) ++{ ++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; ++ ++ return queue->write_idx; ++} ++ ++static inline int hif_lib_tx_pending(struct hif_client_s *client, unsigned int ++ qno) ++{ ++ struct hif_client_tx_queue *queue = &client->tx_q[qno]; ++ ++ return queue->tx_pending; ++} ++ ++#define hif_lib_tx_credit_avail(pfe, id, qno) \ ++ ((pfe)->tmu_credit.tx_credit[id][qno]) ++ ++#define hif_lib_tx_credit_max(pfe, id, qno) \ ++ ((pfe)->tmu_credit.tx_credit_max[id][qno]) ++ ++/* ++ * Test comment ++ */ ++#define hif_lib_tx_credit_use(pfe, id, qno, credit) \ ++ ({ typeof(pfe) pfe_ = pfe; \ ++ typeof(id) id_ = id; \ ++ typeof(qno) qno_ = qno; \ ++ typeof(credit) credit_ = credit; \ ++ do { \ ++ if (tx_qos) { \ ++ (pfe_)->tmu_credit.tx_credit[id_][qno_]\ ++ -= credit_; \ ++ (pfe_)->tmu_credit.tx_packets[id_][qno_]\ ++ += credit_; \ ++ } \ ++ } while (0); \ ++ }) ++ ++#endif /* _PFE_HIF_LIB_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_hw.c +@@ -0,0 +1,164 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#include "pfe_mod.h" ++#include "pfe_hw.h" ++ ++/* Functions to handle most of pfe hw register initialization */ ++int pfe_hw_init(struct pfe *pfe, int resume) ++{ ++ struct class_cfg class_cfg = { ++ .pe_sys_clk_ratio = PE_SYS_CLK_RATIO, ++ .route_table_baseaddr = pfe->ddr_phys_baseaddr + ++ ROUTE_TABLE_BASEADDR, ++ .route_table_hash_bits = ROUTE_TABLE_HASH_BITS, ++ }; ++ ++ struct tmu_cfg tmu_cfg = { ++ .pe_sys_clk_ratio = PE_SYS_CLK_RATIO, ++ .llm_base_addr = pfe->ddr_phys_baseaddr + TMU_LLM_BASEADDR, ++ .llm_queue_len = TMU_LLM_QUEUE_LEN, ++ }; ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ struct util_cfg util_cfg = { ++ .pe_sys_clk_ratio = PE_SYS_CLK_RATIO, ++ }; ++#endif ++ ++ struct BMU_CFG bmu1_cfg = { ++ .baseaddr = CBUS_VIRT_TO_PFE(LMEM_BASE_ADDR + ++ BMU1_LMEM_BASEADDR), ++ .count = BMU1_BUF_COUNT, ++ .size = BMU1_BUF_SIZE, ++ .low_watermark = 10, ++ .high_watermark = 15, ++ }; ++ ++ struct BMU_CFG bmu2_cfg = { ++ .baseaddr = DDR_PHYS_TO_PFE(pfe->ddr_phys_baseaddr + ++ BMU2_DDR_BASEADDR), ++ .count = BMU2_BUF_COUNT, ++ .size = BMU2_BUF_SIZE, ++ .low_watermark = 250, ++ .high_watermark = 253, ++ }; ++ ++ struct gpi_cfg egpi1_cfg = { ++ .lmem_rtry_cnt = EGPI1_LMEM_RTRY_CNT, ++ .tmlf_txthres = EGPI1_TMLF_TXTHRES, ++ .aseq_len = EGPI1_ASEQ_LEN, ++ .mtip_pause_reg = CBUS_VIRT_TO_PFE(EMAC1_BASE_ADDR + ++ EMAC_TCNTRL_REG), ++ }; ++ ++ struct gpi_cfg egpi2_cfg = { ++ .lmem_rtry_cnt = EGPI2_LMEM_RTRY_CNT, ++ .tmlf_txthres = EGPI2_TMLF_TXTHRES, ++ .aseq_len = EGPI2_ASEQ_LEN, ++ .mtip_pause_reg = CBUS_VIRT_TO_PFE(EMAC2_BASE_ADDR + ++ EMAC_TCNTRL_REG), ++ }; ++ ++ struct gpi_cfg hgpi_cfg = { ++ .lmem_rtry_cnt = HGPI_LMEM_RTRY_CNT, ++ .tmlf_txthres = HGPI_TMLF_TXTHRES, ++ .aseq_len = HGPI_ASEQ_LEN, ++ .mtip_pause_reg = 0, ++ }; ++ ++ pr_info("%s\n", __func__); ++ ++#if !defined(LS1012A_PFE_RESET_WA) ++ /* LS1012A needs this to make PE work correctly */ ++ writel(0x3, CLASS_PE_SYS_CLK_RATIO); ++ writel(0x3, TMU_PE_SYS_CLK_RATIO); ++ writel(0x3, UTIL_PE_SYS_CLK_RATIO); ++ usleep_range(10, 20); ++#endif ++ ++ pr_info("CLASS version: %x\n", readl(CLASS_VERSION)); ++ pr_info("TMU version: %x\n", readl(TMU_VERSION)); ++ ++ pr_info("BMU1 version: %x\n", readl(BMU1_BASE_ADDR + ++ BMU_VERSION)); ++ pr_info("BMU2 version: %x\n", readl(BMU2_BASE_ADDR + ++ BMU_VERSION)); ++ ++ pr_info("EGPI1 version: %x\n", readl(EGPI1_BASE_ADDR + ++ GPI_VERSION)); ++ pr_info("EGPI2 version: %x\n", readl(EGPI2_BASE_ADDR + ++ GPI_VERSION)); ++ pr_info("HGPI version: %x\n", readl(HGPI_BASE_ADDR + ++ GPI_VERSION)); ++ ++ pr_info("HIF version: %x\n", readl(HIF_VERSION)); ++ pr_info("HIF NOPCY version: %x\n", readl(HIF_NOCPY_VERSION)); ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ pr_info("UTIL version: %x\n", readl(UTIL_VERSION)); ++#endif ++ while (!(readl(TMU_CTRL) & ECC_MEM_INIT_DONE)) ++ ; ++ ++ hif_rx_disable(); ++ hif_tx_disable(); ++ ++ bmu_init(BMU1_BASE_ADDR, &bmu1_cfg); ++ ++ pr_info("bmu_init(1) done\n"); ++ ++ bmu_init(BMU2_BASE_ADDR, &bmu2_cfg); ++ ++ pr_info("bmu_init(2) done\n"); ++ ++ class_cfg.resume = resume ? 1 : 0; ++ ++ class_init(&class_cfg); ++ ++ pr_info("class_init() done\n"); ++ ++ tmu_init(&tmu_cfg); ++ ++ pr_info("tmu_init() done\n"); ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ util_init(&util_cfg); ++ ++ pr_info("util_init() done\n"); ++#endif ++ gpi_init(EGPI1_BASE_ADDR, &egpi1_cfg); ++ ++ pr_info("gpi_init(1) done\n"); ++ ++ gpi_init(EGPI2_BASE_ADDR, &egpi2_cfg); ++ ++ pr_info("gpi_init(2) done\n"); ++ ++ gpi_init(HGPI_BASE_ADDR, &hgpi_cfg); ++ ++ pr_info("gpi_init(hif) done\n"); ++ ++ bmu_enable(BMU1_BASE_ADDR); ++ ++ pr_info("bmu_enable(1) done\n"); ++ ++ bmu_enable(BMU2_BASE_ADDR); ++ ++ pr_info("bmu_enable(2) done\n"); ++ ++ return 0; ++} ++ ++void pfe_hw_exit(struct pfe *pfe) ++{ ++ pr_info("%s\n", __func__); ++ ++ bmu_disable(BMU1_BASE_ADDR); ++ bmu_reset(BMU1_BASE_ADDR); ++ ++ bmu_disable(BMU2_BASE_ADDR); ++ bmu_reset(BMU2_BASE_ADDR); ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_hw.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#ifndef _PFE_HW_H_ ++#define _PFE_HW_H_ ++ ++#define PE_SYS_CLK_RATIO 1 /* SYS/AXI = 250MHz, HFE = 500MHz */ ++ ++int pfe_hw_init(struct pfe *pfe, int resume); ++void pfe_hw_exit(struct pfe *pfe); ++ ++#endif /* _PFE_HW_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c +@@ -0,0 +1,381 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pfe_mod.h" ++ ++extern bool pfe_use_old_dts_phy; ++struct ls1012a_pfe_platform_data pfe_platform_data; ++ ++static int pfe_get_gemac_if_properties(struct device_node *gem, ++ int port, ++ struct ls1012a_pfe_platform_data *pdata) ++{ ++ struct device_node *phy_node = NULL; ++ int size; ++ int phy_id = 0; ++ const u32 *addr; ++ int err; ++ ++ addr = of_get_property(gem, "reg", &size); ++ if (addr) ++ port = be32_to_cpup(addr); ++ else ++ goto err; ++ ++ pdata->ls1012a_eth_pdata[port].gem_id = port; ++ ++ err = of_get_mac_address(gem, pdata->ls1012a_eth_pdata[port].mac_addr); ++ ++ phy_node = of_parse_phandle(gem, "phy-handle", 0); ++ pdata->ls1012a_eth_pdata[port].phy_node = phy_node; ++ if (phy_node) { ++ pfe_use_old_dts_phy = false; ++ goto process_phynode; ++ } else if (of_phy_is_fixed_link(gem)) { ++ pfe_use_old_dts_phy = false; ++ if (of_phy_register_fixed_link(gem) < 0) { ++ pr_err("broken fixed-link specification\n"); ++ goto err; ++ } ++ phy_node = of_node_get(gem); ++ pdata->ls1012a_eth_pdata[port].phy_node = phy_node; ++ } else if (of_get_property(gem, "fsl,pfe-phy-if-flags", &size)) { ++ pfe_use_old_dts_phy = true; ++ /* Use old dts properties for phy handling */ ++ addr = of_get_property(gem, "fsl,pfe-phy-if-flags", &size); ++ pdata->ls1012a_eth_pdata[port].phy_flags = be32_to_cpup(addr); ++ ++ addr = of_get_property(gem, "fsl,gemac-phy-id", &size); ++ if (!addr) { ++ pr_err("%s:%d Invalid gemac-phy-id....\n", __func__, ++ __LINE__); ++ } else { ++ phy_id = be32_to_cpup(addr); ++ pdata->ls1012a_eth_pdata[port].phy_id = phy_id; ++ pdata->ls1012a_mdio_pdata[0].phy_mask &= ~(1 << phy_id); ++ } ++ ++ /* If PHY is enabled, read mdio properties */ ++ if (pdata->ls1012a_eth_pdata[port].phy_flags & GEMAC_NO_PHY) ++ goto done; ++ ++ } else { ++ pr_info("%s: No PHY or fixed-link\n", __func__); ++ return 0; ++ } ++ ++process_phynode: ++ err = of_get_phy_mode(gem, &pdata->ls1012a_eth_pdata[port].mii_config); ++ if (err) ++ pr_err("%s:%d Incorrect Phy mode....\n", __func__, ++ __LINE__); ++ ++ addr = of_get_property(gem, "fsl,mdio-mux-val", &size); ++ if (!addr) { ++ pr_err("%s: Invalid mdio-mux-val....\n", __func__); ++ } else { ++ phy_id = be32_to_cpup(addr); ++ pdata->ls1012a_eth_pdata[port].mdio_muxval = phy_id; ++ } ++ ++ if (pdata->ls1012a_eth_pdata[port].phy_id < 32) ++ pfe->mdio_muxval[pdata->ls1012a_eth_pdata[port].phy_id] = ++ pdata->ls1012a_eth_pdata[port].mdio_muxval; ++ ++ ++ pdata->ls1012a_mdio_pdata[port].irq[0] = PHY_POLL; ++ ++done: ++ return 0; ++ ++err: ++ return -1; ++} ++ ++/* ++ * ++ * pfe_platform_probe - ++ * ++ * ++ */ ++static int pfe_platform_probe(struct platform_device *pdev) ++{ ++ struct resource res; ++ int ii = 0, rc, interface_count = 0, size = 0; ++ const u32 *prop; ++ struct device_node *np, *gem = NULL; ++ struct clk *pfe_clk; ++ ++ np = pdev->dev.of_node; ++ ++ if (!np) { ++ pr_err("Invalid device node\n"); ++ return -EINVAL; ++ } ++ ++ pfe = kzalloc(sizeof(*pfe), GFP_KERNEL); ++ if (!pfe) { ++ rc = -ENOMEM; ++ goto err_alloc; ++ } ++ ++ platform_set_drvdata(pdev, pfe); ++ ++ if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { ++ rc = -ENOMEM; ++ pr_err("unable to configure DMA mask.\n"); ++ goto err_ddr; ++ } ++ ++ if (of_address_to_resource(np, 1, &res)) { ++ rc = -ENOMEM; ++ pr_err("failed to get ddr resource\n"); ++ goto err_ddr; ++ } ++ ++ pfe->ddr_phys_baseaddr = res.start; ++ pfe->ddr_size = resource_size(&res); ++ ++ pfe->ddr_baseaddr = memremap(res.start, resource_size(&res), ++ MEMREMAP_WB); ++ if (!pfe->ddr_baseaddr) { ++ pr_err("memremap() ddr failed\n"); ++ rc = -ENOMEM; ++ goto err_ddr; ++ } ++ ++ pfe->scfg = ++ syscon_regmap_lookup_by_phandle(pdev->dev.of_node, ++ "fsl,pfe-scfg"); ++ if (IS_ERR(pfe->scfg)) { ++ dev_err(&pdev->dev, "No syscfg phandle specified\n"); ++ return PTR_ERR(pfe->scfg); ++ } ++ ++ pfe->cbus_baseaddr = of_iomap(np, 0); ++ if (!pfe->cbus_baseaddr) { ++ rc = -ENOMEM; ++ pr_err("failed to get axi resource\n"); ++ goto err_axi; ++ } ++ ++ pfe->hif_irq = platform_get_irq(pdev, 0); ++ if (pfe->hif_irq < 0) { ++ pr_err("platform_get_irq for hif failed\n"); ++ rc = pfe->hif_irq; ++ goto err_hif_irq; ++ } ++ ++ pfe->wol_irq = platform_get_irq(pdev, 2); ++ if (pfe->wol_irq < 0) { ++ pr_err("platform_get_irq for WoL failed\n"); ++ rc = pfe->wol_irq; ++ goto err_hif_irq; ++ } ++ ++ /* Read interface count */ ++ prop = of_get_property(np, "fsl,pfe-num-interfaces", &size); ++ if (!prop) { ++ pr_err("Failed to read number of interfaces\n"); ++ rc = -ENXIO; ++ goto err_prop; ++ } ++ ++ interface_count = be32_to_cpup(prop); ++ if (interface_count <= 0) { ++ pr_err("No ethernet interface count : %d\n", ++ interface_count); ++ rc = -ENXIO; ++ goto err_prop; ++ } ++ ++ pfe_platform_data.ls1012a_mdio_pdata[0].phy_mask = 0xffffffff; ++ ++ while ((gem = of_get_next_child(np, gem))) { ++ if (of_find_property(gem, "reg", &size)) { ++ pfe_get_gemac_if_properties(gem, ii, ++ &pfe_platform_data); ++ ii++; ++ } ++ } ++ ++ if (interface_count != ii) ++ pr_info("missing some of gemac interface properties.\n"); ++ ++ pfe->dev = &pdev->dev; ++ ++ pfe->dev->platform_data = &pfe_platform_data; ++ ++ /* declare WoL capabilities */ ++ device_init_wakeup(&pdev->dev, true); ++ ++ /* find the clocks */ ++ pfe_clk = devm_clk_get(pfe->dev, "pfe"); ++ if (IS_ERR(pfe_clk)) ++ return PTR_ERR(pfe_clk); ++ ++ /* PFE clock is (platform clock / 2) */ ++ /* save sys_clk value as KHz */ ++ pfe->ctrl.sys_clk = clk_get_rate(pfe_clk) / (2 * 1000); ++ ++ rc = pfe_probe(pfe); ++ if (rc < 0) ++ goto err_probe; ++ ++ return 0; ++ ++err_probe: ++err_prop: ++err_hif_irq: ++ iounmap(pfe->cbus_baseaddr); ++ ++err_axi: ++ memunmap(pfe->ddr_baseaddr); ++ ++err_ddr: ++ platform_set_drvdata(pdev, NULL); ++ ++ kfree(pfe); ++ ++err_alloc: ++ return rc; ++} ++ ++/* ++ * pfe_platform_remove - ++ */ ++static void pfe_platform_remove(struct platform_device *pdev) ++{ ++ struct pfe *pfe = platform_get_drvdata(pdev); ++ int rc; ++ ++ pr_info("%s\n", __func__); ++ ++ rc = pfe_remove(pfe); ++ ++ iounmap(pfe->cbus_baseaddr); ++ ++ memunmap(pfe->ddr_baseaddr); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ kfree(pfe); ++} ++ ++#ifdef CONFIG_PM ++#ifdef CONFIG_PM_SLEEP ++static int pfe_platform_suspend(struct device *dev) ++{ ++ struct pfe *pfe = platform_get_drvdata(to_platform_device(dev)); ++ struct net_device *netdev; ++ int i; ++ ++ pfe->wake = 0; ++ ++ for (i = 0; i < (NUM_GEMAC_SUPPORT); i++) { ++ netdev = pfe->eth.eth_priv[i]->ndev; ++ ++ netif_device_detach(netdev); ++ ++ if (netif_running(netdev)) ++ if (pfe_eth_suspend(netdev)) ++ pfe->wake = 1; ++ } ++ ++ /* Shutdown PFE only if we're not waking up the system */ ++ if (!pfe->wake) { ++#if defined(LS1012A_PFE_RESET_WA) ++ pfe_hif_rx_idle(&pfe->hif); ++#endif ++ pfe_ctrl_suspend(&pfe->ctrl); ++ pfe_firmware_exit(pfe); ++ ++ pfe_hif_exit(pfe); ++ pfe_hif_lib_exit(pfe); ++ ++ pfe_hw_exit(pfe); ++ } ++ ++ return 0; ++} ++ ++static int pfe_platform_resume(struct device *dev) ++{ ++ struct pfe *pfe = platform_get_drvdata(to_platform_device(dev)); ++ struct net_device *netdev; ++ int i; ++ ++ if (!pfe->wake) { ++ pfe_hw_init(pfe, 1); ++ pfe_hif_lib_init(pfe); ++ pfe_hif_init(pfe); ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ util_enable(); ++#endif ++ tmu_enable(0xf); ++ class_enable(); ++ pfe_ctrl_resume(&pfe->ctrl); ++ } ++ ++ for (i = 0; i < (NUM_GEMAC_SUPPORT); i++) { ++ netdev = pfe->eth.eth_priv[i]->ndev; ++ ++ if (pfe->mdio.mdio_priv[i]->mii_bus) ++ pfe_eth_mdio_reset(pfe->mdio.mdio_priv[i]->mii_bus); ++ ++ if (netif_running(netdev)) ++ pfe_eth_resume(netdev); ++ ++ netif_device_attach(netdev); ++ } ++ return 0; ++} ++#else ++#define pfe_platform_suspend NULL ++#define pfe_platform_resume NULL ++#endif ++ ++static const struct dev_pm_ops pfe_platform_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(pfe_platform_suspend, pfe_platform_resume) ++}; ++#endif ++ ++static const struct of_device_id pfe_match[] = { ++ { ++ .compatible = "fsl,pfe", ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, pfe_match); ++ ++static struct platform_driver pfe_platform_driver = { ++ .probe = pfe_platform_probe, ++ .remove = pfe_platform_remove, ++ .driver = { ++ .name = "pfe", ++ .of_match_table = pfe_match, ++#ifdef CONFIG_PM ++ .pm = &pfe_platform_pm_ops, ++#endif ++ }, ++}; ++ ++module_platform_driver(pfe_platform_driver); ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("PFE Ethernet driver"); ++MODULE_AUTHOR("NXP DNCPE"); +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_mod.c +@@ -0,0 +1,158 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#include ++#include "pfe_mod.h" ++#include "pfe_cdev.h" ++ ++unsigned int us; ++module_param(us, uint, 0444); ++MODULE_PARM_DESC(us, "0: module enabled for kernel networking (DEFAULT)\n" ++ "1: module enabled for userspace networking\n"); ++struct pfe *pfe; ++ ++/* ++ * pfe_probe - ++ */ ++int pfe_probe(struct pfe *pfe) ++{ ++ int rc; ++ ++ if (pfe->ddr_size < DDR_MAX_SIZE) { ++ pr_err("%s: required DDR memory (%x) above platform ddr memory (%x)\n", ++ __func__, (unsigned int)DDR_MAX_SIZE, pfe->ddr_size); ++ rc = -ENOMEM; ++ goto err_hw; ++ } ++ ++ if (((int)(pfe->ddr_phys_baseaddr + BMU2_DDR_BASEADDR) & ++ (8 * SZ_1M - 1)) != 0) { ++ pr_err("%s: BMU2 base address (0x%x) must be aligned on 8MB boundary\n", ++ __func__, (int)pfe->ddr_phys_baseaddr + ++ BMU2_DDR_BASEADDR); ++ rc = -ENOMEM; ++ goto err_hw; ++ } ++ ++ pr_info("cbus_baseaddr: %lx, ddr_baseaddr: %lx, ddr_phys_baseaddr: %lx, ddr_size: %x\n", ++ (unsigned long)pfe->cbus_baseaddr, ++ (unsigned long)pfe->ddr_baseaddr, ++ pfe->ddr_phys_baseaddr, pfe->ddr_size); ++ ++ pfe_lib_init(pfe->cbus_baseaddr, pfe->ddr_baseaddr, ++ pfe->ddr_phys_baseaddr, pfe->ddr_size); ++ ++ rc = pfe_hw_init(pfe, 0); ++ if (rc < 0) ++ goto err_hw; ++ ++ if (us) ++ goto firmware_init; ++ ++ rc = pfe_hif_lib_init(pfe); ++ if (rc < 0) ++ goto err_hif_lib; ++ ++ rc = pfe_hif_init(pfe); ++ if (rc < 0) ++ goto err_hif; ++ ++firmware_init: ++ rc = pfe_firmware_init(pfe); ++ if (rc < 0) ++ goto err_firmware; ++ ++ rc = pfe_ctrl_init(pfe); ++ if (rc < 0) ++ goto err_ctrl; ++ ++ rc = pfe_eth_init(pfe); ++ if (rc < 0) ++ goto err_eth; ++ ++ rc = pfe_sysfs_init(pfe); ++ if (rc < 0) ++ goto err_sysfs; ++ ++ rc = pfe_debugfs_init(pfe); ++ if (rc < 0) ++ goto err_debugfs; ++ ++ if (us) { ++ /* Creating a character device */ ++ rc = pfe_cdev_init(); ++ if (rc < 0) ++ goto err_cdev; ++ } ++ ++ return 0; ++ ++err_cdev: ++ pfe_debugfs_exit(pfe); ++ ++err_debugfs: ++ pfe_sysfs_exit(pfe); ++ ++err_sysfs: ++ pfe_eth_exit(pfe); ++ ++err_eth: ++ pfe_ctrl_exit(pfe); ++ ++err_ctrl: ++ pfe_firmware_exit(pfe); ++ ++err_firmware: ++ if (us) ++ goto err_hif_lib; ++ ++ pfe_hif_exit(pfe); ++ ++err_hif: ++ pfe_hif_lib_exit(pfe); ++ ++err_hif_lib: ++ pfe_hw_exit(pfe); ++ ++err_hw: ++ return rc; ++} ++ ++/* ++ * pfe_remove - ++ */ ++int pfe_remove(struct pfe *pfe) ++{ ++ pr_info("%s\n", __func__); ++ ++ if (us) ++ pfe_cdev_exit(); ++ ++ pfe_debugfs_exit(pfe); ++ ++ pfe_sysfs_exit(pfe); ++ ++ pfe_eth_exit(pfe); ++ ++ pfe_ctrl_exit(pfe); ++ ++#if defined(LS1012A_PFE_RESET_WA) ++ pfe_hif_rx_idle(&pfe->hif); ++#endif ++ pfe_firmware_exit(pfe); ++ ++ if (us) ++ goto hw_exit; ++ ++ pfe_hif_exit(pfe); ++ ++ pfe_hif_lib_exit(pfe); ++ ++hw_exit: ++ pfe_hw_exit(pfe); ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_mod.h +@@ -0,0 +1,103 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#ifndef _PFE_MOD_H_ ++#define _PFE_MOD_H_ ++ ++#include ++#include ++ ++extern unsigned int us; ++ ++struct pfe; ++ ++#include "pfe_hw.h" ++#include "pfe_firmware.h" ++#include "pfe_ctrl.h" ++#include "pfe_hif.h" ++#include "pfe_hif_lib.h" ++#include "pfe_eth.h" ++#include "pfe_sysfs.h" ++#include "pfe_perfmon.h" ++#include "pfe_debugfs.h" ++ ++#define PHYID_MAX_VAL 32 ++ ++struct pfe_tmu_credit { ++ /* Number of allowed TX packet in-flight, matches TMU queue size */ ++ unsigned int tx_credit[NUM_GEMAC_SUPPORT][EMAC_TXQ_CNT]; ++ unsigned int tx_credit_max[NUM_GEMAC_SUPPORT][EMAC_TXQ_CNT]; ++ unsigned int tx_packets[NUM_GEMAC_SUPPORT][EMAC_TXQ_CNT]; ++}; ++ ++struct pfe { ++ struct regmap *scfg; ++ unsigned long ddr_phys_baseaddr; ++ void *ddr_baseaddr; ++ unsigned int ddr_size; ++ void *cbus_baseaddr; ++ void *apb_baseaddr; ++ unsigned long iram_phys_baseaddr; ++ void *iram_baseaddr; ++ unsigned long ipsec_phys_baseaddr; ++ void *ipsec_baseaddr; ++ int hif_irq; ++ int wol_irq; ++ int hif_client_irq; ++ struct device *dev; ++ struct dentry *dentry; ++ struct pfe_ctrl ctrl; ++ struct pfe_hif hif; ++ struct pfe_eth eth; ++ struct pfe_mdio mdio; ++ struct hif_client_s *hif_client[HIF_CLIENTS_MAX]; ++#if defined(CFG_DIAGS) ++ struct pfe_diags diags; ++#endif ++ struct pfe_tmu_credit tmu_credit; ++ struct pfe_cpumon cpumon; ++ struct pfe_memmon memmon; ++ int wake; ++ int mdio_muxval[PHYID_MAX_VAL]; ++ struct clk *hfe_clock; ++}; ++ ++extern struct pfe *pfe; ++ ++int pfe_probe(struct pfe *pfe); ++int pfe_remove(struct pfe *pfe); ++ ++/* DDR Mapping in reserved memory*/ ++#define ROUTE_TABLE_BASEADDR 0 ++#define ROUTE_TABLE_HASH_BITS 15 /* 32K entries */ ++#define ROUTE_TABLE_SIZE ((1 << ROUTE_TABLE_HASH_BITS) \ ++ * CLASS_ROUTE_SIZE) ++#define BMU2_DDR_BASEADDR (ROUTE_TABLE_BASEADDR + ROUTE_TABLE_SIZE) ++#define BMU2_BUF_COUNT (4096 - 256) ++/* This is to get a total DDR size of 12MiB */ ++#define BMU2_DDR_SIZE (DDR_BUF_SIZE * BMU2_BUF_COUNT) ++#define UTIL_CODE_BASEADDR (BMU2_DDR_BASEADDR + BMU2_DDR_SIZE) ++#define UTIL_CODE_SIZE (128 * SZ_1K) ++#define UTIL_DDR_DATA_BASEADDR (UTIL_CODE_BASEADDR + UTIL_CODE_SIZE) ++#define UTIL_DDR_DATA_SIZE (64 * SZ_1K) ++#define CLASS_DDR_DATA_BASEADDR (UTIL_DDR_DATA_BASEADDR + UTIL_DDR_DATA_SIZE) ++#define CLASS_DDR_DATA_SIZE (32 * SZ_1K) ++#define TMU_DDR_DATA_BASEADDR (CLASS_DDR_DATA_BASEADDR + CLASS_DDR_DATA_SIZE) ++#define TMU_DDR_DATA_SIZE (32 * SZ_1K) ++#define TMU_LLM_BASEADDR (TMU_DDR_DATA_BASEADDR + TMU_DDR_DATA_SIZE) ++#define TMU_LLM_QUEUE_LEN (8 * 512) ++/* Must be power of two and at least 16 * 8 = 128 bytes */ ++#define TMU_LLM_SIZE (4 * 16 * TMU_LLM_QUEUE_LEN) ++/* (4 TMU's x 16 queues x queue_len) */ ++ ++#define DDR_MAX_SIZE (TMU_LLM_BASEADDR + TMU_LLM_SIZE) ++ ++/* LMEM Mapping */ ++#define BMU1_LMEM_BASEADDR 0 ++#define BMU1_BUF_COUNT 256 ++#define BMU1_LMEM_SIZE (LMEM_BUF_SIZE * BMU1_BUF_COUNT) ++ ++#endif /* _PFE_MOD_H */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_perfmon.h +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#ifndef _PFE_PERFMON_H_ ++#define _PFE_PERFMON_H_ ++ ++#include "pfe/pfe.h" ++ ++#define CT_CPUMON_INTERVAL (1 * TIMER_TICKS_PER_SEC) ++ ++struct pfe_cpumon { ++ u32 cpu_usage_pct[MAX_PE]; ++ u32 class_usage_pct; ++}; ++ ++struct pfe_memmon { ++ u32 kernel_memory_allocated; ++}; ++ ++int pfe_perfmon_init(struct pfe *pfe); ++void pfe_perfmon_exit(struct pfe *pfe); ++ ++#endif /* _PFE_PERFMON_H_ */ +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_sysfs.c +@@ -0,0 +1,840 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#include ++#include ++ ++#include "pfe_mod.h" ++ ++#define PE_EXCEPTION_DUMP_ADDRESS 0x1fa8 ++#define NUM_QUEUES 16 ++ ++static char register_name[20][5] = { ++ "EPC", "ECAS", "EID", "ED", ++ "r0", "r1", "r2", "r3", ++ "r4", "r5", "r6", "r7", ++ "r8", "r9", "r10", "r11", ++ "r12", "r13", "r14", "r15", ++}; ++ ++static char exception_name[14][20] = { ++ "Reset", ++ "HardwareFailure", ++ "NMI", ++ "InstBreakpoint", ++ "DataBreakpoint", ++ "Unsupported", ++ "PrivilegeViolation", ++ "InstBusError", ++ "DataBusError", ++ "AlignmentError", ++ "ArithmeticError", ++ "SystemCall", ++ "MemoryManagement", ++ "Interrupt", ++}; ++ ++static unsigned long class_do_clear; ++static unsigned long tmu_do_clear; ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++static unsigned long util_do_clear; ++#endif ++ ++static ssize_t display_pe_status(char *buf, int id, u32 dmem_addr, unsigned long ++ do_clear) ++{ ++ ssize_t len = 0; ++ u32 val; ++ char statebuf[5]; ++ struct pfe_cpumon *cpumon = &pfe->cpumon; ++ u32 debug_indicator; ++ u32 debug[20]; ++ ++ if (id < CLASS0_ID || id >= MAX_PE) ++ return len; ++ ++ *(u32 *)statebuf = pe_dmem_read(id, dmem_addr, 4); ++ dmem_addr += 4; ++ ++ statebuf[4] = '\0'; ++ len += sprintf(buf + len, "state=%4s ", statebuf); ++ ++ val = pe_dmem_read(id, dmem_addr, 4); ++ dmem_addr += 4; ++ len += sprintf(buf + len, "ctr=%08x ", cpu_to_be32(val)); ++ ++ val = pe_dmem_read(id, dmem_addr, 4); ++ if (do_clear && val) ++ pe_dmem_write(id, 0, dmem_addr, 4); ++ dmem_addr += 4; ++ len += sprintf(buf + len, "rx=%u ", cpu_to_be32(val)); ++ ++ val = pe_dmem_read(id, dmem_addr, 4); ++ if (do_clear && val) ++ pe_dmem_write(id, 0, dmem_addr, 4); ++ dmem_addr += 4; ++ if (id >= TMU0_ID && id <= TMU_MAX_ID) ++ len += sprintf(buf + len, "qstatus=%x", cpu_to_be32(val)); ++ else ++ len += sprintf(buf + len, "tx=%u", cpu_to_be32(val)); ++ ++ val = pe_dmem_read(id, dmem_addr, 4); ++ if (do_clear && val) ++ pe_dmem_write(id, 0, dmem_addr, 4); ++ dmem_addr += 4; ++ if (val) ++ len += sprintf(buf + len, " drop=%u", cpu_to_be32(val)); ++ ++ len += sprintf(buf + len, " load=%d%%", cpumon->cpu_usage_pct[id]); ++ ++ len += sprintf(buf + len, "\n"); ++ ++ debug_indicator = pe_dmem_read(id, dmem_addr, 4); ++ dmem_addr += 4; ++ if (!strncmp((char *)&debug_indicator, "DBUG", 4)) { ++ int j, last = 0; ++ ++ for (j = 0; j < 16; j++) { ++ debug[j] = pe_dmem_read(id, dmem_addr, 4); ++ if (debug[j]) { ++ if (do_clear) ++ pe_dmem_write(id, 0, dmem_addr, 4); ++ last = j + 1; ++ } ++ dmem_addr += 4; ++ } ++ for (j = 0; j < last; j++) { ++ len += sprintf(buf + len, "%08x%s", ++ cpu_to_be32(debug[j]), ++ (j & 0x7) == 0x7 || j == last - 1 ? "\n" : " "); ++ } ++ } ++ ++ if (!strncmp(statebuf, "DEAD", 4)) { ++ u32 i, dump = PE_EXCEPTION_DUMP_ADDRESS; ++ ++ len += sprintf(buf + len, "Exception details:\n"); ++ for (i = 0; i < 20; i++) { ++ debug[i] = pe_dmem_read(id, dump, 4); ++ dump += 4; ++ if (i == 2) ++ len += sprintf(buf + len, "%4s = %08x (=%s) ", ++ register_name[i], cpu_to_be32(debug[i]), ++ exception_name[min((u32) ++ cpu_to_be32(debug[i]), (u32)13)]); ++ else ++ len += sprintf(buf + len, "%4s = %08x%s", ++ register_name[i], cpu_to_be32(debug[i]), ++ (i & 0x3) == 0x3 || i == 19 ? "\n" : " "); ++ } ++ } ++ ++ return len; ++} ++ ++static ssize_t class_phy_stats(char *buf, int phy) ++{ ++ ssize_t len = 0; ++ int off1 = phy * 0x28; ++ int off2 = phy * 0x10; ++ ++ if (phy == 3) ++ off1 = CLASS_PHY4_RX_PKTS - CLASS_PHY1_RX_PKTS; ++ ++ len += sprintf(buf + len, "phy: %d\n", phy); ++ len += sprintf(buf + len, ++ " rx: %10u, tx: %10u, intf: %10u, ipv4: %10u, ipv6: %10u\n", ++ readl(CLASS_PHY1_RX_PKTS + off1), ++ readl(CLASS_PHY1_TX_PKTS + off1), ++ readl(CLASS_PHY1_INTF_MATCH_PKTS + off1), ++ readl(CLASS_PHY1_V4_PKTS + off1), ++ readl(CLASS_PHY1_V6_PKTS + off1)); ++ ++ len += sprintf(buf + len, ++ " icmp: %10u, igmp: %10u, tcp: %10u, udp: %10u\n", ++ readl(CLASS_PHY1_ICMP_PKTS + off2), ++ readl(CLASS_PHY1_IGMP_PKTS + off2), ++ readl(CLASS_PHY1_TCP_PKTS + off2), ++ readl(CLASS_PHY1_UDP_PKTS + off2)); ++ ++ len += sprintf(buf + len, " err\n"); ++ len += sprintf(buf + len, ++ " lp: %10u, intf: %10u, l3: %10u, chcksum: %10u, ttl: %10u\n", ++ readl(CLASS_PHY1_LP_FAIL_PKTS + off1), ++ readl(CLASS_PHY1_INTF_FAIL_PKTS + off1), ++ readl(CLASS_PHY1_L3_FAIL_PKTS + off1), ++ readl(CLASS_PHY1_CHKSUM_ERR_PKTS + off1), ++ readl(CLASS_PHY1_TTL_ERR_PKTS + off1)); ++ ++ return len; ++} ++ ++/* qm_read_drop_stat ++ * This function is used to read the drop statistics from the TMU ++ * hw drop counter. Since the hw counter is always cleared afer ++ * reading, this function maintains the previous drop count, and ++ * adds the new value to it. That value can be retrieved by ++ * passing a pointer to it with the total_drops arg. ++ * ++ * @param tmu TMU number (0 - 3) ++ * @param queue queue number (0 - 15) ++ * @param total_drops pointer to location to store total drops (or NULL) ++ * @param do_reset if TRUE, clear total drops after updating ++ */ ++u32 qm_read_drop_stat(u32 tmu, u32 queue, u32 *total_drops, int do_reset) ++{ ++ static u32 qtotal[TMU_MAX_ID + 1][NUM_QUEUES]; ++ u32 val; ++ ++ writel((tmu << 8) | queue, TMU_TEQ_CTRL); ++ writel((tmu << 8) | queue, TMU_LLM_CTRL); ++ val = readl(TMU_TEQ_DROP_STAT); ++ qtotal[tmu][queue] += val; ++ if (total_drops) ++ *total_drops = qtotal[tmu][queue]; ++ if (do_reset) ++ qtotal[tmu][queue] = 0; ++ return val; ++} ++ ++static ssize_t tmu_queue_stats(char *buf, int tmu, int queue) ++{ ++ ssize_t len = 0; ++ u32 drops; ++ ++ len += sprintf(buf + len, "%d-%02d, ", tmu, queue); ++ ++ drops = qm_read_drop_stat(tmu, queue, NULL, 0); ++ ++ /* Select queue */ ++ writel((tmu << 8) | queue, TMU_TEQ_CTRL); ++ writel((tmu << 8) | queue, TMU_LLM_CTRL); ++ ++ len += sprintf(buf + len, ++ "(teq) drop: %10u, tx: %10u (llm) head: %08x, tail: %08x, drop: %10u\n", ++ drops, readl(TMU_TEQ_TRANS_STAT), ++ readl(TMU_LLM_QUE_HEADPTR), readl(TMU_LLM_QUE_TAILPTR), ++ readl(TMU_LLM_QUE_DROPCNT)); ++ ++ return len; ++} ++ ++static ssize_t tmu_queues(char *buf, int tmu) ++{ ++ ssize_t len = 0; ++ int queue; ++ ++ for (queue = 0; queue < 16; queue++) ++ len += tmu_queue_stats(buf + len, tmu, queue); ++ ++ return len; ++} ++ ++static ssize_t block_version(char *buf, void *addr) ++{ ++ ssize_t len = 0; ++ u32 val; ++ ++ val = readl(addr); ++ len += sprintf(buf + len, "revision: %x, version: %x, id: %x\n", ++ (val >> 24) & 0xff, (val >> 16) & 0xff, val & 0xffff); ++ ++ return len; ++} ++ ++static ssize_t bmu(char *buf, int id, void *base) ++{ ++ ssize_t len = 0; ++ ++ len += sprintf(buf + len, "%s: %d\n ", __func__, id); ++ ++ len += block_version(buf + len, base + BMU_VERSION); ++ ++ len += sprintf(buf + len, " buf size: %x\n", (1 << readl(base + ++ BMU_BUF_SIZE))); ++ len += sprintf(buf + len, " buf count: %x\n", readl(base + ++ BMU_BUF_CNT)); ++ len += sprintf(buf + len, " buf rem: %x\n", readl(base + ++ BMU_REM_BUF_CNT)); ++ len += sprintf(buf + len, " buf curr: %x\n", readl(base + ++ BMU_CURR_BUF_CNT)); ++ len += sprintf(buf + len, " free err: %x\n", readl(base + ++ BMU_FREE_ERR_ADDR)); ++ ++ return len; ++} ++ ++static ssize_t gpi(char *buf, int id, void *base) ++{ ++ ssize_t len = 0; ++ u32 val; ++ ++ len += sprintf(buf + len, "%s%d:\n ", __func__, id); ++ len += block_version(buf + len, base + GPI_VERSION); ++ ++ len += sprintf(buf + len, " tx under stick: %x\n", readl(base + ++ GPI_FIFO_STATUS)); ++ val = readl(base + GPI_FIFO_DEBUG); ++ len += sprintf(buf + len, " tx pkts: %x\n", (val >> 23) & ++ 0x3f); ++ len += sprintf(buf + len, " rx pkts: %x\n", (val >> 18) & ++ 0x3f); ++ len += sprintf(buf + len, " tx bytes: %x\n", (val >> 9) & ++ 0x1ff); ++ len += sprintf(buf + len, " rx bytes: %x\n", (val >> 0) & ++ 0x1ff); ++ len += sprintf(buf + len, " overrun: %x\n", readl(base + ++ GPI_OVERRUN_DROPCNT)); ++ ++ return len; ++} ++ ++static ssize_t pfe_set_class(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ class_do_clear = kstrtoul(buf, 0, 0); ++ return count; ++} ++ ++static ssize_t pfe_show_class(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ ssize_t len = 0; ++ int id; ++ u32 val; ++ struct pfe_cpumon *cpumon = &pfe->cpumon; ++ ++ len += block_version(buf + len, CLASS_VERSION); ++ ++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { ++ len += sprintf(buf + len, "%d: ", id - CLASS0_ID); ++ ++ val = readl(CLASS_PE0_DEBUG + id * 4); ++ len += sprintf(buf + len, "pc=1%04x ", val & 0xffff); ++ ++ len += display_pe_status(buf + len, id, CLASS_DM_PESTATUS, ++ class_do_clear); ++ } ++ len += sprintf(buf + len, "aggregate load=%d%%\n\n", ++ cpumon->class_usage_pct); ++ ++ len += sprintf(buf + len, "pe status: 0x%x\n", ++ readl(CLASS_PE_STATUS)); ++ len += sprintf(buf + len, "max buf cnt: 0x%x afull thres: 0x%x\n", ++ readl(CLASS_MAX_BUF_CNT), readl(CLASS_AFULL_THRES)); ++ len += sprintf(buf + len, "tsq max cnt: 0x%x tsq fifo thres: 0x%x\n", ++ readl(CLASS_TSQ_MAX_CNT), readl(CLASS_TSQ_FIFO_THRES)); ++ len += sprintf(buf + len, "state: 0x%x\n", readl(CLASS_STATE)); ++ ++ len += class_phy_stats(buf + len, 0); ++ len += class_phy_stats(buf + len, 1); ++ len += class_phy_stats(buf + len, 2); ++ len += class_phy_stats(buf + len, 3); ++ ++ return len; ++} ++ ++static ssize_t pfe_set_tmu(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ tmu_do_clear = kstrtoul(buf, 0, 0); ++ return count; ++} ++ ++static ssize_t pfe_show_tmu(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ ssize_t len = 0; ++ int id; ++ u32 val; ++ ++ len += block_version(buf + len, TMU_VERSION); ++ ++ for (id = TMU0_ID; id <= TMU_MAX_ID; id++) { ++ if (id == TMU2_ID) ++ continue; ++ len += sprintf(buf + len, "%d: ", id - TMU0_ID); ++ ++ len += display_pe_status(buf + len, id, TMU_DM_PESTATUS, ++ tmu_do_clear); ++ } ++ ++ len += sprintf(buf + len, "pe status: %x\n", readl(TMU_PE_STATUS)); ++ len += sprintf(buf + len, "inq fifo cnt: %x\n", ++ readl(TMU_PHY_INQ_FIFO_CNT)); ++ val = readl(TMU_INQ_STAT); ++ len += sprintf(buf + len, "inq wr ptr: %x\n", val & 0x3ff); ++ len += sprintf(buf + len, "inq rd ptr: %x\n", val >> 10); ++ ++ return len; ++} ++ ++static unsigned long drops_do_clear; ++static u32 class_drop_counter[CLASS_NUM_DROP_COUNTERS]; ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++static u32 util_drop_counter[UTIL_NUM_DROP_COUNTERS]; ++#endif ++ ++char *class_drop_description[CLASS_NUM_DROP_COUNTERS] = { ++ "ICC", ++ "Host Pkt Error", ++ "Rx Error", ++ "IPsec Outbound", ++ "IPsec Inbound", ++ "EXPT IPsec Error", ++ "Reassembly", ++ "Fragmenter", ++ "NAT-T", ++ "Socket", ++ "Multicast", ++ "NAT-PT", ++ "Tx Disabled", ++}; ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++char *util_drop_description[UTIL_NUM_DROP_COUNTERS] = { ++ "IPsec Outbound", ++ "IPsec Inbound", ++ "IPsec Rate Limiter", ++ "Fragmenter", ++ "Socket", ++ "Tx Disabled", ++ "Rx Error", ++}; ++#endif ++ ++static ssize_t pfe_set_drops(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ drops_do_clear = kstrtoul(buf, 0, 0); ++ return count; ++} ++ ++static u32 tmu_drops[4][16]; ++static ssize_t pfe_show_drops(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ ssize_t len = 0; ++ int id, dropnum; ++ int tmu, queue; ++ u32 val; ++ u32 dmem_addr; ++ int num_class_drops = 0, num_tmu_drops = 0, num_util_drops = 0; ++ struct pfe_ctrl *ctrl = &pfe->ctrl; ++ ++ memset(class_drop_counter, 0, sizeof(class_drop_counter)); ++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { ++ if (drops_do_clear) ++ pe_sync_stop(ctrl, (1 << id)); ++ for (dropnum = 0; dropnum < CLASS_NUM_DROP_COUNTERS; ++ dropnum++) { ++ dmem_addr = CLASS_DM_DROP_CNTR; ++ val = be32_to_cpu(pe_dmem_read(id, dmem_addr, 4)); ++ class_drop_counter[dropnum] += val; ++ num_class_drops += val; ++ if (drops_do_clear) ++ pe_dmem_write(id, 0, dmem_addr, 4); ++ } ++ if (drops_do_clear) ++ pe_start(ctrl, (1 << id)); ++ } ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ if (drops_do_clear) ++ pe_sync_stop(ctrl, (1 << UTIL_ID)); ++ for (dropnum = 0; dropnum < UTIL_NUM_DROP_COUNTERS; dropnum++) { ++ dmem_addr = UTIL_DM_DROP_CNTR; ++ val = be32_to_cpu(pe_dmem_read(UTIL_ID, dmem_addr, 4)); ++ util_drop_counter[dropnum] = val; ++ num_util_drops += val; ++ if (drops_do_clear) ++ pe_dmem_write(UTIL_ID, 0, dmem_addr, 4); ++ } ++ if (drops_do_clear) ++ pe_start(ctrl, (1 << UTIL_ID)); ++#endif ++ for (tmu = 0; tmu < 4; tmu++) { ++ for (queue = 0; queue < 16; queue++) { ++ qm_read_drop_stat(tmu, queue, &tmu_drops[tmu][queue], ++ drops_do_clear); ++ num_tmu_drops += tmu_drops[tmu][queue]; ++ } ++ } ++ ++ if (num_class_drops == 0 && num_util_drops == 0 && num_tmu_drops == 0) ++ len += sprintf(buf + len, "No PE drops\n\n"); ++ ++ if (num_class_drops > 0) { ++ len += sprintf(buf + len, "Class PE drops --\n"); ++ for (dropnum = 0; dropnum < CLASS_NUM_DROP_COUNTERS; ++ dropnum++) { ++ if (class_drop_counter[dropnum] > 0) ++ len += sprintf(buf + len, " %s: %d\n", ++ class_drop_description[dropnum], ++ class_drop_counter[dropnum]); ++ } ++ len += sprintf(buf + len, "\n"); ++ } ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ if (num_util_drops > 0) { ++ len += sprintf(buf + len, "Util PE drops --\n"); ++ for (dropnum = 0; dropnum < UTIL_NUM_DROP_COUNTERS; dropnum++) { ++ if (util_drop_counter[dropnum] > 0) ++ len += sprintf(buf + len, " %s: %d\n", ++ util_drop_description[dropnum], ++ util_drop_counter[dropnum]); ++ } ++ len += sprintf(buf + len, "\n"); ++ } ++#endif ++ if (num_tmu_drops > 0) { ++ len += sprintf(buf + len, "TMU drops --\n"); ++ for (tmu = 0; tmu < 4; tmu++) { ++ for (queue = 0; queue < 16; queue++) { ++ if (tmu_drops[tmu][queue] > 0) ++ len += sprintf(buf + len, ++ " TMU%d-Q%d: %d\n" ++ , tmu, queue, tmu_drops[tmu][queue]); ++ } ++ } ++ len += sprintf(buf + len, "\n"); ++ } ++ ++ return len; ++} ++ ++static ssize_t pfe_show_tmu0_queues(struct device *dev, struct device_attribute ++ *attr, char *buf) ++{ ++ return tmu_queues(buf, 0); ++} ++ ++static ssize_t pfe_show_tmu1_queues(struct device *dev, struct device_attribute ++ *attr, char *buf) ++{ ++ return tmu_queues(buf, 1); ++} ++ ++static ssize_t pfe_show_tmu2_queues(struct device *dev, struct device_attribute ++ *attr, char *buf) ++{ ++ return tmu_queues(buf, 2); ++} ++ ++static ssize_t pfe_show_tmu3_queues(struct device *dev, struct device_attribute ++ *attr, char *buf) ++{ ++ return tmu_queues(buf, 3); ++} ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++static ssize_t pfe_set_util(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ util_do_clear = kstrtoul(buf, NULL, 0); ++ return count; ++} ++ ++static ssize_t pfe_show_util(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ ssize_t len = 0; ++ struct pfe_ctrl *ctrl = &pfe->ctrl; ++ ++ len += block_version(buf + len, UTIL_VERSION); ++ ++ pe_sync_stop(ctrl, (1 << UTIL_ID)); ++ len += display_pe_status(buf + len, UTIL_ID, UTIL_DM_PESTATUS, ++ util_do_clear); ++ pe_start(ctrl, (1 << UTIL_ID)); ++ ++ len += sprintf(buf + len, "pe status: %x\n", readl(UTIL_PE_STATUS)); ++ len += sprintf(buf + len, "max buf cnt: %x\n", ++ readl(UTIL_MAX_BUF_CNT)); ++ len += sprintf(buf + len, "tsq max cnt: %x\n", ++ readl(UTIL_TSQ_MAX_CNT)); ++ ++ return len; ++} ++#endif ++ ++static ssize_t pfe_show_bmu(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ ssize_t len = 0; ++ ++ len += bmu(buf + len, 1, BMU1_BASE_ADDR); ++ len += bmu(buf + len, 2, BMU2_BASE_ADDR); ++ ++ return len; ++} ++ ++static ssize_t pfe_show_hif(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ ssize_t len = 0; ++ ++ len += sprintf(buf + len, "hif:\n "); ++ len += block_version(buf + len, HIF_VERSION); ++ ++ len += sprintf(buf + len, " tx curr bd: %x\n", ++ readl(HIF_TX_CURR_BD_ADDR)); ++ len += sprintf(buf + len, " tx status: %x\n", ++ readl(HIF_TX_STATUS)); ++ len += sprintf(buf + len, " tx dma status: %x\n", ++ readl(HIF_TX_DMA_STATUS)); ++ ++ len += sprintf(buf + len, " rx curr bd: %x\n", ++ readl(HIF_RX_CURR_BD_ADDR)); ++ len += sprintf(buf + len, " rx status: %x\n", ++ readl(HIF_RX_STATUS)); ++ len += sprintf(buf + len, " rx dma status: %x\n", ++ readl(HIF_RX_DMA_STATUS)); ++ ++ len += sprintf(buf + len, "hif nocopy:\n "); ++ len += block_version(buf + len, HIF_NOCPY_VERSION); ++ ++ len += sprintf(buf + len, " tx curr bd: %x\n", ++ readl(HIF_NOCPY_TX_CURR_BD_ADDR)); ++ len += sprintf(buf + len, " tx status: %x\n", ++ readl(HIF_NOCPY_TX_STATUS)); ++ len += sprintf(buf + len, " tx dma status: %x\n", ++ readl(HIF_NOCPY_TX_DMA_STATUS)); ++ ++ len += sprintf(buf + len, " rx curr bd: %x\n", ++ readl(HIF_NOCPY_RX_CURR_BD_ADDR)); ++ len += sprintf(buf + len, " rx status: %x\n", ++ readl(HIF_NOCPY_RX_STATUS)); ++ len += sprintf(buf + len, " rx dma status: %x\n", ++ readl(HIF_NOCPY_RX_DMA_STATUS)); ++ ++ return len; ++} ++ ++static ssize_t pfe_show_gpi(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ ssize_t len = 0; ++ ++ len += gpi(buf + len, 0, EGPI1_BASE_ADDR); ++ len += gpi(buf + len, 1, EGPI2_BASE_ADDR); ++ len += gpi(buf + len, 3, HGPI_BASE_ADDR); ++ ++ return len; ++} ++ ++static ssize_t pfe_show_pfemem(struct device *dev, struct device_attribute ++ *attr, char *buf) ++{ ++ ssize_t len = 0; ++ struct pfe_memmon *memmon = &pfe->memmon; ++ ++ len += sprintf(buf + len, "Kernel Memory: %d Bytes (%d KB)\n", ++ memmon->kernel_memory_allocated, ++ (memmon->kernel_memory_allocated + 1023) / 1024); ++ ++ return len; ++} ++ ++static ssize_t pfe_show_crc_revalidated(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ u64 crc_validated = 0; ++ ssize_t len = 0; ++ int id, phyid; ++ ++ len += sprintf(buf + len, "FCS re-validated by PFE:\n"); ++ ++ for (phyid = 0; phyid < 2; phyid++) { ++ crc_validated = 0; ++ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { ++ crc_validated += be32_to_cpu(pe_dmem_read(id, ++ CLASS_DM_CRC_VALIDATED + (phyid * 4), 4)); ++ } ++ len += sprintf(buf + len, "MAC %d:\n count:%10llu\n", ++ phyid, crc_validated); ++ } ++ ++ return len; ++} ++ ++#ifdef HIF_NAPI_STATS ++static ssize_t pfe_show_hif_napi_stats(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct pfe *pfe = platform_get_drvdata(pdev); ++ ssize_t len = 0; ++ ++ len += sprintf(buf + len, "sched: %u\n", ++ pfe->hif.napi_counters[NAPI_SCHED_COUNT]); ++ len += sprintf(buf + len, "poll: %u\n", ++ pfe->hif.napi_counters[NAPI_POLL_COUNT]); ++ len += sprintf(buf + len, "packet: %u\n", ++ pfe->hif.napi_counters[NAPI_PACKET_COUNT]); ++ len += sprintf(buf + len, "budget: %u\n", ++ pfe->hif.napi_counters[NAPI_FULL_BUDGET_COUNT]); ++ len += sprintf(buf + len, "desc: %u\n", ++ pfe->hif.napi_counters[NAPI_DESC_COUNT]); ++ len += sprintf(buf + len, "full: %u\n", ++ pfe->hif.napi_counters[NAPI_CLIENT_FULL_COUNT]); ++ ++ return len; ++} ++ ++static ssize_t pfe_set_hif_napi_stats(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct pfe *pfe = platform_get_drvdata(pdev); ++ ++ memset(pfe->hif.napi_counters, 0, sizeof(pfe->hif.napi_counters)); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(hif_napi_stats, 0644, pfe_show_hif_napi_stats, ++ pfe_set_hif_napi_stats); ++#endif ++ ++static DEVICE_ATTR(class, 0644, pfe_show_class, pfe_set_class); ++static DEVICE_ATTR(tmu, 0644, pfe_show_tmu, pfe_set_tmu); ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++static DEVICE_ATTR(util, 0644, pfe_show_util, pfe_set_util); ++#endif ++static DEVICE_ATTR(bmu, 0444, pfe_show_bmu, NULL); ++static DEVICE_ATTR(hif, 0444, pfe_show_hif, NULL); ++static DEVICE_ATTR(gpi, 0444, pfe_show_gpi, NULL); ++static DEVICE_ATTR(drops, 0644, pfe_show_drops, pfe_set_drops); ++static DEVICE_ATTR(tmu0_queues, 0444, pfe_show_tmu0_queues, NULL); ++static DEVICE_ATTR(tmu1_queues, 0444, pfe_show_tmu1_queues, NULL); ++static DEVICE_ATTR(tmu2_queues, 0444, pfe_show_tmu2_queues, NULL); ++static DEVICE_ATTR(tmu3_queues, 0444, pfe_show_tmu3_queues, NULL); ++static DEVICE_ATTR(pfemem, 0444, pfe_show_pfemem, NULL); ++static DEVICE_ATTR(fcs_revalidated, 0444, pfe_show_crc_revalidated, NULL); ++ ++int pfe_sysfs_init(struct pfe *pfe) ++{ ++ if (device_create_file(pfe->dev, &dev_attr_class)) ++ goto err_class; ++ ++ if (device_create_file(pfe->dev, &dev_attr_tmu)) ++ goto err_tmu; ++ ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ if (device_create_file(pfe->dev, &dev_attr_util)) ++ goto err_util; ++#endif ++ ++ if (device_create_file(pfe->dev, &dev_attr_bmu)) ++ goto err_bmu; ++ ++ if (device_create_file(pfe->dev, &dev_attr_hif)) ++ goto err_hif; ++ ++ if (device_create_file(pfe->dev, &dev_attr_gpi)) ++ goto err_gpi; ++ ++ if (device_create_file(pfe->dev, &dev_attr_drops)) ++ goto err_drops; ++ ++ if (device_create_file(pfe->dev, &dev_attr_tmu0_queues)) ++ goto err_tmu0_queues; ++ ++ if (device_create_file(pfe->dev, &dev_attr_tmu1_queues)) ++ goto err_tmu1_queues; ++ ++ if (device_create_file(pfe->dev, &dev_attr_tmu2_queues)) ++ goto err_tmu2_queues; ++ ++ if (device_create_file(pfe->dev, &dev_attr_tmu3_queues)) ++ goto err_tmu3_queues; ++ ++ if (device_create_file(pfe->dev, &dev_attr_pfemem)) ++ goto err_pfemem; ++ ++ if (device_create_file(pfe->dev, &dev_attr_fcs_revalidated)) ++ goto err_crc_revalidated; ++ ++#ifdef HIF_NAPI_STATS ++ if (device_create_file(pfe->dev, &dev_attr_hif_napi_stats)) ++ goto err_hif_napi_stats; ++#endif ++ ++ return 0; ++ ++#ifdef HIF_NAPI_STATS ++err_hif_napi_stats: ++ device_remove_file(pfe->dev, &dev_attr_fcs_revalidated); ++#endif ++ ++err_crc_revalidated: ++ device_remove_file(pfe->dev, &dev_attr_pfemem); ++ ++err_pfemem: ++ device_remove_file(pfe->dev, &dev_attr_tmu3_queues); ++ ++err_tmu3_queues: ++ device_remove_file(pfe->dev, &dev_attr_tmu2_queues); ++ ++err_tmu2_queues: ++ device_remove_file(pfe->dev, &dev_attr_tmu1_queues); ++ ++err_tmu1_queues: ++ device_remove_file(pfe->dev, &dev_attr_tmu0_queues); ++ ++err_tmu0_queues: ++ device_remove_file(pfe->dev, &dev_attr_drops); ++ ++err_drops: ++ device_remove_file(pfe->dev, &dev_attr_gpi); ++ ++err_gpi: ++ device_remove_file(pfe->dev, &dev_attr_hif); ++ ++err_hif: ++ device_remove_file(pfe->dev, &dev_attr_bmu); ++ ++err_bmu: ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ device_remove_file(pfe->dev, &dev_attr_util); ++ ++err_util: ++#endif ++ device_remove_file(pfe->dev, &dev_attr_tmu); ++ ++err_tmu: ++ device_remove_file(pfe->dev, &dev_attr_class); ++ ++err_class: ++ return -1; ++} ++ ++void pfe_sysfs_exit(struct pfe *pfe) ++{ ++#ifdef HIF_NAPI_STATS ++ device_remove_file(pfe->dev, &dev_attr_hif_napi_stats); ++#endif ++ device_remove_file(pfe->dev, &dev_attr_fcs_revalidated); ++ device_remove_file(pfe->dev, &dev_attr_pfemem); ++ device_remove_file(pfe->dev, &dev_attr_tmu3_queues); ++ device_remove_file(pfe->dev, &dev_attr_tmu2_queues); ++ device_remove_file(pfe->dev, &dev_attr_tmu1_queues); ++ device_remove_file(pfe->dev, &dev_attr_tmu0_queues); ++ device_remove_file(pfe->dev, &dev_attr_drops); ++ device_remove_file(pfe->dev, &dev_attr_gpi); ++ device_remove_file(pfe->dev, &dev_attr_hif); ++ device_remove_file(pfe->dev, &dev_attr_bmu); ++#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) ++ device_remove_file(pfe->dev, &dev_attr_util); ++#endif ++ device_remove_file(pfe->dev, &dev_attr_tmu); ++ device_remove_file(pfe->dev, &dev_attr_class); ++} +--- /dev/null ++++ b/drivers/staging/fsl_ppfe/pfe_sysfs.h +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2015-2016 Freescale Semiconductor, Inc. ++ * Copyright 2017 NXP ++ */ ++ ++#ifndef _PFE_SYSFS_H_ ++#define _PFE_SYSFS_H_ ++ ++#include ++ ++u32 qm_read_drop_stat(u32 tmu, u32 queue, u32 *total_drops, int do_reset); ++ ++int pfe_sysfs_init(struct pfe *pfe); ++void pfe_sysfs_exit(struct pfe *pfe); ++ ++#endif /* _PFE_SYSFS_H_ */ diff --git a/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch new file mode 100644 index 0000000000..dc63c7e3dd --- /dev/null +++ b/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch @@ -0,0 +1,73 @@ +From 5677c6ef5f4096f3149a4e8cfd1438bc9eb2e8a4 Mon Sep 17 00:00:00 2001 +From: Bhaskar Upadhaya +Date: Wed, 29 Nov 2017 15:27:57 +0530 +Subject: [PATCH] phy: Add 2.5G SGMII interface mode + +Add 2.5G SGMII interface mode(PHY_INTERFACE_MODE_2500SGMII) +in existing phy_interface list + +Signed-off-by: Bhaskar Upadhaya +--- + Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 + + drivers/net/phy/phy-core.c | 1 + + drivers/net/phy/phylink.c | 2 ++ + include/linux/phy.h | 3 +++ + 4 files changed, 7 insertions(+) + +--- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml ++++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml +@@ -65,6 +65,7 @@ properties: + - mii + - gmii + - sgmii ++ - sgmii-2500 + - psgmii + - qsgmii + - qusgmii +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -138,6 +138,7 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_RXAUI: + case PHY_INTERFACE_MODE_XAUI: + case PHY_INTERFACE_MODE_1000BASEKX: ++ case PHY_INTERFACE_MODE_2500SGMII: + return 1; + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -250,6 +250,7 @@ static int phylink_interface_max_speed(p + case PHY_INTERFACE_MODE_GMII: + return SPEED_1000; + ++ case PHY_INTERFACE_MODE_2500SGMII: + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_10G_QXGMII: + return SPEED_2500; +@@ -564,6 +565,7 @@ static unsigned long phylink_get_capabil + break; + + case PHY_INTERFACE_MODE_2500BASEX: ++ case PHY_INTERFACE_MODE_2500SGMII: + caps |= MAC_2500FD; + break; + +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -170,6 +170,7 @@ typedef enum { + PHY_INTERFACE_MODE_QUSGMII, + PHY_INTERFACE_MODE_1000BASEKX, + PHY_INTERFACE_MODE_10G_QXGMII, ++ PHY_INTERFACE_MODE_2500SGMII, + PHY_INTERFACE_MODE_MAX, + } phy_interface_t; + +@@ -245,6 +246,8 @@ static inline const char *phy_modes(phy_ + return "gmii"; + case PHY_INTERFACE_MODE_SGMII: + return "sgmii"; ++ case PHY_INTERFACE_MODE_2500SGMII: ++ return "sgmii-2500"; + case PHY_INTERFACE_MODE_TBI: + return "tbi"; + case PHY_INTERFACE_MODE_REVMII: diff --git a/target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch b/target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch new file mode 100644 index 0000000000..2d724bb582 --- /dev/null +++ b/target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch @@ -0,0 +1,239 @@ +From 1dc3a2e216d99adc2df022ab37eab32f61d80e0e Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 8 May 2023 19:26:48 +0200 +Subject: [PATCH] layerscape: 6.1: fix compilation warning for fsl ppfe driver + +Rework some desc dump and dummy pkt function to fix compilation warning. +Fix compilation warning: +drivers/staging/fsl_ppfe/pfe_hif.c: In function 'send_dummy_pkt_to_hif': +drivers/staging/fsl_ppfe/pfe_hif.c:118:19: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] + 118 | ddr_ptr = (void *)((u64)readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL)); + | ^ +drivers/staging/fsl_ppfe/pfe_hif.c:122:20: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] + 122 | lmem_ptr = (void *)((u64)readl(BMU1_BASE_ADDR + BMU_ALLOC_CTRL)); + | ^ +drivers/staging/fsl_ppfe/pfe_hif.c: In function 'pfe_hif_desc_dump': +drivers/staging/fsl_ppfe/pfe_hif.c:195:24: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] + 195 | desc_p = (u32)((u64)desc - (u64)hif->descr_baseaddr_v + + | ^ +drivers/staging/fsl_ppfe/pfe_hif.c:195:36: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] + 195 | desc_p = (u32)((u64)desc - (u64)hif->descr_baseaddr_v + + | ^ +drivers/staging/fsl_ppfe/pfe_hif.c:207:19: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] + 207 | desc_p = ((u64)desc - (u64)hif->descr_baseaddr_v + + | ^ +drivers/staging/fsl_ppfe/pfe_hif.c:207:31: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] + 207 | desc_p = ((u64)desc - (u64)hif->descr_baseaddr_v + + | ^ +cc1: all warnings being treated as errors + +In file included from ./include/linux/kernel.h:19, + from ./include/linux/list.h:9, + from ./include/linux/wait.h:7, + from ./include/linux/eventfd.h:13, + from drivers/staging/fsl_ppfe/pfe_cdev.c:11: +drivers/staging/fsl_ppfe/pfe_cdev.c: In function 'pfe_cdev_read': +./include/linux/kern_levels.h:5:25: error: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'int' [-Werror=format=] + 5 | #define KERN_SOH "\001" /* ASCII Start Of Header */ + | ^~~~~~ +./include/linux/printk.h:422:25: note: in definition of macro 'printk_index_wrap' + 422 | _p_func(_fmt, ##__VA_ARGS__); \ + | ^~~~ +./include/linux/printk.h:132:17: note: in expansion of macro 'printk' + 132 | printk(fmt, ##__VA_ARGS__); \ + | ^~~~~~ +./include/linux/printk.h:580:9: note: in expansion of macro 'no_printk' + 580 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) + | ^~~~~~~~~ +./include/linux/kern_levels.h:15:25: note: in expansion of macro 'KERN_SOH' + 15 | #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */ + | ^~~~~~~~ +./include/linux/printk.h:580:19: note: in expansion of macro 'KERN_DEBUG' + 580 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) + | ^~~~~~~~~~ +drivers/staging/fsl_ppfe/pfe_cdev.c:42:17: note: in expansion of macro 'pr_debug' + 42 | pr_debug("%u %lu", link_states[ret].phy_id, + | ^~~~~~~~ +./include/linux/kern_levels.h:5:25: error: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'size_t' {aka 'unsigned int'} [-Werror=format=] + 5 | #define KERN_SOH "\001" /* ASCII Start Of Header */ + | ^~~~~~ +./include/linux/printk.h:422:25: note: in definition of macro 'printk_index_wrap' + 422 | _p_func(_fmt, ##__VA_ARGS__); \ + | ^~~~ +./include/linux/printk.h:493:9: note: in expansion of macro 'printk' + 493 | printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) + | ^~~~~~ +./include/linux/kern_levels.h:11:25: note: in expansion of macro 'KERN_SOH' + 11 | #define KERN_ERR KERN_SOH "3" /* error conditions */ + | ^~~~~~~~ +./include/linux/printk.h:493:16: note: in expansion of macro 'KERN_ERR' + 493 | printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) + | ^~~~~~~~ +drivers/staging/fsl_ppfe/pfe_cdev.c:50:17: note: in expansion of macro 'pr_err' + 50 | pr_err("Failed to send (%d)bytes of (%lu) requested.\n", + | ^~~~~~ +./include/linux/kern_levels.h:5:25: error: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'unsigned int' [-Werror=format=] + 5 | #define KERN_SOH "\001" /* ASCII Start Of Header */ + | ^~~~~~ +./include/linux/printk.h:422:25: note: in definition of macro 'printk_index_wrap' + 422 | _p_func(_fmt, ##__VA_ARGS__); \ + | ^~~~ +./include/linux/printk.h:132:17: note: in expansion of macro 'printk' + 132 | printk(fmt, ##__VA_ARGS__); \ + | ^~~~~~ +./include/linux/printk.h:580:9: note: in expansion of macro 'no_printk' + 580 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) + | ^~~~~~~~~ +./include/linux/kern_levels.h:15:25: note: in expansion of macro 'KERN_SOH' + 15 | #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */ + | ^~~~~~~~ +./include/linux/printk.h:580:19: note: in expansion of macro 'KERN_DEBUG' + 580 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) + | ^~~~~~~~~~ +drivers/staging/fsl_ppfe/pfe_cdev.c:57:9: note: in expansion of macro 'pr_debug' + 57 | pr_debug("Read of (%lu) bytes performed.\n", sizeof(link_states)); + | ^~~~~~~~ +cc1: all warnings being treated as errors + +In file included from ./include/uapi/linux/posix_types.h:5, + from ./include/uapi/linux/types.h:14, + from ./include/linux/types.h:6, + from ./include/linux/list.h:5, + from ./include/linux/module.h:12, + from drivers/staging/fsl_ppfe/pfe_sysfs.c:7: +drivers/staging/fsl_ppfe/pfe_sysfs.c: In function 'pfe_set_util': +./include/linux/stddef.h:8:14: error: passing argument 2 of 'kstrtoul' makes integer from pointer without a cast [-Werror=int-conversion] + 8 | #define NULL ((void *)0) + | ^~~~~~~~~~~ + | | + | void * +drivers/staging/fsl_ppfe/pfe_sysfs.c:538:39: note: in expansion of macro 'NULL' + 538 | util_do_clear = kstrtoul(buf, NULL, 0); + | ^~~~ +In file included from ./include/linux/kernel.h:13, + from ./include/linux/list.h:9: +./include/linux/kstrtox.h:30:69: note: expected 'unsigned int' but argument is of type 'void *' + 30 | static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res) + | ~~~~~~~~~~~~~^~~~ +cc1: all warnings being treated as errors + +With UTIL compiled on, fix compilation warning: +drivers/staging/fsl_ppfe/pfe_hal.c: In function 'pe_load_ddr_section': +drivers/staging/fsl_ppfe/pfe_hal.c:617:19: error: 'else' without a previous 'if' + 617 | } else { + | ^~~~ +drivers/staging/fsl_ppfe/pfe_hal.c:622:17: error: break statement not within loop or switch + 622 | break; + | ^~~~~ +drivers/staging/fsl_ppfe/pfe_hal.c:624:9: error: case label not within a switch statement + 624 | case SHT_NOBITS: + | ^~~~ +drivers/staging/fsl_ppfe/pfe_hal.c:627:17: error: break statement not within loop or switch + 627 | break; + | ^~~~~ +drivers/staging/fsl_ppfe/pfe_hal.c:629:9: error: 'default' label not within a switch statement + 629 | default: + | ^~~~~~~ +drivers/staging/fsl_ppfe/pfe_hal.c: At top level: +drivers/staging/fsl_ppfe/pfe_hal.c:635:9: error: expected identifier or '(' before 'return' + 635 | return 0; + | ^~~~~~ +drivers/staging/fsl_ppfe/pfe_hal.c:636:1: error: expected identifier or '(' before '}' token + 636 | } + +Signed-off-by: Christian Marangi +Signed-off-by: Pawel Dembicki +--- + drivers/staging/fsl_ppfe/pfe_cdev.c | 6 +++--- + drivers/staging/fsl_ppfe/pfe_hif.c | 14 +++++++------- + drivers/staging/fsl_ppfe/pfe_sysfs.c | 2 +- + 3 files changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/staging/fsl_ppfe/pfe_cdev.c ++++ b/drivers/staging/fsl_ppfe/pfe_cdev.c +@@ -34,7 +34,7 @@ static ssize_t pfe_cdev_read(struct file + { + int ret = 0; + +- pr_info("PFE CDEV attempt copying (%lu) size of user.\n", ++ pr_info("PFE CDEV attempt copying (%zu) size of user.\n", + sizeof(link_states)); + + pr_debug("Dump link_state on screen before copy_to_user\n"); +@@ -47,14 +47,14 @@ static ssize_t pfe_cdev_read(struct file + /* Copy to user the value in buffer sized len */ + ret = copy_to_user(buf, &link_states, sizeof(link_states)); + if (ret != 0) { +- pr_err("Failed to send (%d)bytes of (%lu) requested.\n", ++ pr_err("Failed to send (%d)bytes of (%zu) requested.\n", + ret, len); + return -EFAULT; + } + + /* offset set back to 0 as there is contextual reading offset */ + *off = 0; +- pr_debug("Read of (%lu) bytes performed.\n", sizeof(link_states)); ++ pr_debug("Read of (%zu) bytes performed.\n", sizeof(link_states)); + + return sizeof(link_states); + } +--- a/drivers/staging/fsl_ppfe/pfe_hif.c ++++ b/drivers/staging/fsl_ppfe/pfe_hif.c +@@ -115,11 +115,11 @@ static void send_dummy_pkt_to_hif(void) + 0x33221100, 0xa8c05544, 0x00000301, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xbe86c51f }; + +- ddr_ptr = (void *)((u64)readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL)); ++ ddr_ptr = (void *)((uintptr_t)readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL)); + if (!ddr_ptr) + return; + +- lmem_ptr = (void *)((u64)readl(BMU1_BASE_ADDR + BMU_ALLOC_CTRL)); ++ lmem_ptr = (void *)((uintptr_t)readl(BMU1_BASE_ADDR + BMU_ALLOC_CTRL)); + if (!lmem_ptr) + return; + +@@ -186,16 +186,16 @@ static void pfe_hif_free_descr(struct pf + static void __maybe_unused pfe_hif_desc_dump(struct pfe_hif *hif) + { + struct hif_desc *desc; +- unsigned long desc_p; ++ u64 desc_p; + int ii = 0; + + pr_info("%s\n", __func__); + + desc = hif->rx_base; +- desc_p = (u32)((u64)desc - (u64)hif->descr_baseaddr_v + ++ desc_p = ((void *)desc - hif->descr_baseaddr_v + + hif->descr_baseaddr_p); + +- pr_info("HIF Rx desc base %p physical %x\n", desc, (u32)desc_p); ++ pr_info("HIF Rx desc base %p physical %llx\n", desc, desc_p); + for (ii = 0; ii < hif->rx_ring_size; ii++) { + pr_info("status: %08x, ctrl: %08x, data: %08x, next: %x\n", + readl(&desc->status), readl(&desc->ctrl), +@@ -204,10 +204,10 @@ static void __maybe_unused pfe_hif_desc_ + } + + desc = hif->tx_base; +- desc_p = ((u64)desc - (u64)hif->descr_baseaddr_v + ++ desc_p = ((void *)desc - hif->descr_baseaddr_v + + hif->descr_baseaddr_p); + +- pr_info("HIF Tx desc base %p physical %x\n", desc, (u32)desc_p); ++ pr_info("HIF Tx desc base %p physical %llx\n", desc, desc_p); + for (ii = 0; ii < hif->tx_ring_size; ii++) { + pr_info("status: %08x, ctrl: %08x, data: %08x, next: %x\n", + readl(&desc->status), readl(&desc->ctrl), +--- a/drivers/staging/fsl_ppfe/pfe_sysfs.c ++++ b/drivers/staging/fsl_ppfe/pfe_sysfs.c +@@ -535,7 +535,7 @@ static ssize_t pfe_show_tmu3_queues(stru + static ssize_t pfe_set_util(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) + { +- util_do_clear = kstrtoul(buf, NULL, 0); ++ util_do_clear = kstrtoul(buf, 0, 0); + return count; + } + diff --git a/target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch b/target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch new file mode 100644 index 0000000000..99a0dec0a8 --- /dev/null +++ b/target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch @@ -0,0 +1,36 @@ +From 3efb7aeefef62886be0dde83f6340d1a1bfcb5f6 Mon Sep 17 00:00:00 2001 +From: Pawel Dembicki +Date: Fri, 31 Oct 2025 22:46:05 +0100 +Subject: [PATCH] layerscape: dts: ls1012a-frdm: add GPIO hog for PHY reset + +On LS1012A-FRDM both PHY reset pins are tied to GPIO1_23 (active-low). +Older kernels preserved the U-Boot-configured level, but since 6.12 the +pin may default to an undefined state early in boot, leaving the PHYs in +reset and breaking detection. + +Add a GPIO hog on gpio1[23], configured as output-high, to keep the +reset line deasserted from early boot. + +Signed-off-by: Pawel Dembicki +--- + arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts +@@ -87,6 +87,15 @@ + status = "okay"; + }; + ++&gpio0 { ++ phy-reset-hog { ++ gpio-hog; ++ gpios = <23 1>; ++ output-low; ++ line-name = "phy-reset"; ++ }; ++}; ++ + &i2c0 { + status = "okay"; + From 21cb6585ccbce2082064cbdbe15c20f7b17a4901 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Fri, 26 Jun 2026 15:13:48 +0200 Subject: [PATCH 173/228] layerscape: 6.18: refresh patches Taken from 6.18 nxp tree: 701-staging-add-fsl_ppfe-driver.patch 702-phy-Add-2.5G-SGMII-interface-mode.patch Refreshed by `make target/linux/refresh`: 302-arm64-dts-ls1012a-update-with-ppfe-support.patch Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- ...dts-ls1012a-update-with-ppfe-support.patch | 2 +- .../701-staging-add-fsl_ppfe-driver.patch | 72 +++++++++++++------ ...02-phy-Add-2.5G-SGMII-interface-mode.patch | 69 ++++++++++-------- ...x-compilation-warning-for-fsl-ppfe-.patch} | 0 4 files changed, 90 insertions(+), 53 deletions(-) rename target/linux/layerscape/patches-6.18/{703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch => 703-layerscape-6.18-fix-compilation-warning-for-fsl-ppfe-.patch} (100%) diff --git a/target/linux/layerscape/patches-6.18/302-arm64-dts-ls1012a-update-with-ppfe-support.patch b/target/linux/layerscape/patches-6.18/302-arm64-dts-ls1012a-update-with-ppfe-support.patch index bd69aa042d..5ea7262da3 100644 --- a/target/linux/layerscape/patches-6.18/302-arm64-dts-ls1012a-update-with-ppfe-support.patch +++ b/target/linux/layerscape/patches-6.18/302-arm64-dts-ls1012a-update-with-ppfe-support.patch @@ -190,7 +190,7 @@ Signed-off-by: Li Yang +}; --- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi -@@ -568,6 +568,35 @@ +@@ -569,6 +569,35 @@ }; }; diff --git a/target/linux/layerscape/patches-6.18/701-staging-add-fsl_ppfe-driver.patch b/target/linux/layerscape/patches-6.18/701-staging-add-fsl_ppfe-driver.patch index 279391531a..7dc16d9231 100644 --- a/target/linux/layerscape/patches-6.18/701-staging-add-fsl_ppfe-driver.patch +++ b/target/linux/layerscape/patches-6.18/701-staging-add-fsl_ppfe-driver.patch @@ -1,4 +1,4 @@ -From 81f5150aba929b222783a60a408b9a20a23bd171 Mon Sep 17 00:00:00 2001 +From 1d4b2a1c29da59ab500c1aca751103863e2254ed Mon Sep 17 00:00:00 2001 From: Calvin Johnson Date: Sat, 16 Sep 2017 07:05:49 +0530 Subject: [PATCH] staging: add fsl_ppfe driver @@ -6,8 +6,8 @@ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -This is squash of all commits with ppfe driver taken from NXP 6.12 tree: -https://github.com/nxp-qoriq/linux/tree/lf-6.12.y +This is squash of all commits with ppfe driver taken from NXP 6.18 tree: +https://github.com/nxp-qoriq/linux/tree/lf-6.18.y net: fsl_ppfe: dts binding for ppfe @@ -656,6 +656,33 @@ e.g. Signed-off-by: Dong Aisheng +LF 16506-1 net: ppfe: remove init_dummy_netdev + +See: +commit f835bdae7167 ("net: remove init_dummy_netdev()") + +drivers/staging/fsl_ppfe/pfe_hif.c:993:9: error: implicit declaration of function ‘init_dummy_netdev’ [-Werror=implicit-function-declaration] + 993 | init_dummy_netdev(&hif->dummy_dev); + | ^~~~~~~~~~~~~~~~~ + +Reviewed-by: Wei Fang +Signed-off-by: Dong Aisheng + +LF-16506-2 net: pfe: change to use hrtimer_setup + +Cope with upstream API change: +commit 48ad7bbfd53a ("treewide: Convert new and leftover hrtimer_init() users") + +e.g. +drivers/gpu/arm/midgard/mali_kbase_kinstr_prfcnt.c: In function ‘kbase_kinstr_prfcnt_init’: +drivers/gpu/arm/midgard/mali_kbase_kinstr_prfcnt.c:1272:9: error: implicit declaration of function ‘hrtimer_init’; did you mean ‘hrtimers_init’? [-Werror=implicit-function-declaration] + 1272 | hrtimer_init(&kinstr_ctx->dump_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + | ^~~~~~~~~~~~ + | hrtimers_init + +Reviewed-by: Wei Fang +Signed-off-by: Dong Aisheng + drivers: make all local platform_driver::remove() return void 0edb555a65d1 ("platform: Make platform_driver::remove() return void") @@ -685,12 +712,12 @@ Signed-off-by: Dong Aisheng drivers/staging/fsl_ppfe/pfe_ctrl.h | 100 + drivers/staging/fsl_ppfe/pfe_debugfs.c | 99 + drivers/staging/fsl_ppfe/pfe_debugfs.h | 13 + - drivers/staging/fsl_ppfe/pfe_eth.c | 2550 +++++++++++++++++ + drivers/staging/fsl_ppfe/pfe_eth.c | 2549 +++++++++++++++++ drivers/staging/fsl_ppfe/pfe_eth.h | 175 ++ drivers/staging/fsl_ppfe/pfe_firmware.c | 398 +++ drivers/staging/fsl_ppfe/pfe_firmware.h | 21 + drivers/staging/fsl_ppfe/pfe_hal.c | 1517 ++++++++++ - drivers/staging/fsl_ppfe/pfe_hif.c | 1063 +++++++ + drivers/staging/fsl_ppfe/pfe_hif.c | 1067 +++++++ drivers/staging/fsl_ppfe/pfe_hif.h | 199 ++ drivers/staging/fsl_ppfe/pfe_hif_lib.c | 628 ++++ drivers/staging/fsl_ppfe/pfe_hif_lib.h | 229 ++ @@ -702,7 +729,7 @@ Signed-off-by: Dong Aisheng drivers/staging/fsl_ppfe/pfe_perfmon.h | 26 + drivers/staging/fsl_ppfe/pfe_sysfs.c | 840 ++++++ drivers/staging/fsl_ppfe/pfe_sysfs.h | 17 + - 40 files changed, 10975 insertions(+) + 40 files changed, 10978 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/fsl_ppfe/pfe.txt create mode 100644 drivers/staging/fsl_ppfe/Kconfig create mode 100644 drivers/staging/fsl_ppfe/Makefile @@ -945,8 +972,8 @@ Signed-off-by: Dong Aisheng +}; --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -9114,6 +9114,14 @@ F: drivers/ptp/ptp_qoriq.c - F: drivers/ptp/ptp_qoriq_debugfs.c +@@ -10002,6 +10002,14 @@ F: drivers/net/ethernet/freescale/enetc/ + F: drivers/ptp/ptp_qoriq.c F: include/linux/fsl/ptp_qoriq.h +FREESCALE QORIQ PPFE ETHERNET DRIVER @@ -962,19 +989,19 @@ Signed-off-by: Dong Aisheng L: linux-spi@vger.kernel.org --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig -@@ -62,4 +62,6 @@ source "drivers/staging/fieldbus/Kconfig +@@ -50,4 +50,6 @@ source "drivers/staging/vme_user/Kconfig - source "drivers/staging/vme_user/Kconfig" + source "drivers/staging/gpib/Kconfig" +source "drivers/staging/fsl_ppfe/Kconfig" + endif # STAGING --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile -@@ -20,3 +20,4 @@ obj-$(CONFIG_GREYBUS) += greybus/ +@@ -14,3 +14,4 @@ obj-$(CONFIG_GREYBUS) += greybus/ obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ - obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ + obj-$(CONFIG_GPIB) += gpib/ +obj-$(CONFIG_FSL_PPFE) += fsl_ppfe/ --- /dev/null +++ b/drivers/staging/fsl_ppfe/Kconfig @@ -3316,7 +3343,7 @@ Signed-off-by: Dong Aisheng +#endif /* _PFE_DEBUGFS_H_ */ --- /dev/null +++ b/drivers/staging/fsl_ppfe/pfe_eth.c -@@ -0,0 +1,2550 @@ +@@ -0,0 +1,2549 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. @@ -5406,10 +5433,9 @@ Signed-off-by: Dong Aisheng + + for (i = 0; i < emac_txq_cnt; i++) { + priv->fast_tx_timeout[i].queuenum = i; -+ hrtimer_init(&priv->fast_tx_timeout[i].timer, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); -+ priv->fast_tx_timeout[i].timer.function = -+ pfe_eth_fast_tx_timeout; ++ hrtimer_setup(&priv->fast_tx_timeout[i].timer, ++ pfe_eth_fast_tx_timeout, CLOCK_MONOTONIC, ++ HRTIMER_MODE_REL); + priv->fast_tx_timeout[i].base = priv->fast_tx_timeout; + } +} @@ -7992,7 +8018,7 @@ Signed-off-by: Dong Aisheng +} --- /dev/null +++ b/drivers/staging/fsl_ppfe/pfe_hif.c -@@ -0,0 +1,1063 @@ +@@ -0,0 +1,1067 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2015-2016 Freescale Semiconductor, Inc. @@ -8985,8 +9011,12 @@ Signed-off-by: Dong Aisheng + } + + /* Initialize NAPI for Rx processing */ -+ init_dummy_netdev(&hif->dummy_dev); -+ netif_napi_add(&hif->dummy_dev, &hif->napi, pfe_hif_rx_poll); ++ hif->dummy_dev = alloc_netdev_dummy(0); ++ if (!hif->dummy_dev) { ++ pr_err("%s: Failed to allocate pfe dummy netdev\n", __func__); ++ goto err1; ++ } ++ netif_napi_add(hif->dummy_dev, &hif->napi, pfe_hif_rx_poll); + napi_enable(&hif->napi); + + spin_lock_init(&hif->tx_lock); @@ -9211,7 +9241,7 @@ Signed-off-by: Dong Aisheng + spinlock_t tx_lock; +/* lock synchronizes hif rx queue processing */ + spinlock_t lock; -+ struct net_device dummy_dev; ++ struct net_device *dummy_dev; + struct napi_struct napi; + struct device *dev; + diff --git a/target/linux/layerscape/patches-6.18/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-6.18/702-phy-Add-2.5G-SGMII-interface-mode.patch index e44f651c25..458f2609fb 100644 --- a/target/linux/layerscape/patches-6.18/702-phy-Add-2.5G-SGMII-interface-mode.patch +++ b/target/linux/layerscape/patches-6.18/702-phy-Add-2.5G-SGMII-interface-mode.patch @@ -1,23 +1,28 @@ -From 5677c6ef5f4096f3149a4e8cfd1438bc9eb2e8a4 Mon Sep 17 00:00:00 2001 +From ae52a1f314f65822a4c3a75f292816581be22ea1 Mon Sep 17 00:00:00 2001 From: Bhaskar Upadhaya -Date: Wed, 29 Nov 2017 15:27:57 +0530 +Date: Wed, 9 Jul 2025 13:23:51 +0300 Subject: [PATCH] phy: Add 2.5G SGMII interface mode Add 2.5G SGMII interface mode(PHY_INTERFACE_MODE_2500SGMII) -in existing phy_interface list +in existing phy_interface list. This is synonymous with +PHY_INTERFACE_MODE_2500BASEX without in-band autoneg used for the sole +purpose of connecting to on-board PHYs (not SFP modules), which we keep +for backwards compatibility with NXP device trees. Signed-off-by: Bhaskar Upadhaya +Signed-off-by: Vladimir Oltean --- Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 + drivers/net/phy/phy-core.c | 1 + - drivers/net/phy/phylink.c | 2 ++ + drivers/net/phy/phy_caps.c | 1 + + drivers/net/phy/phylink.c | 1 + include/linux/phy.h | 3 +++ - 4 files changed, 7 insertions(+) + 5 files changed, 7 insertions(+) --- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml +++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml -@@ -65,6 +65,7 @@ properties: - - mii +@@ -42,6 +42,7 @@ properties: + - mii-lite - gmii - sgmii + - sgmii-2500 @@ -26,17 +31,27 @@ Signed-off-by: Bhaskar Upadhaya - qusgmii --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c -@@ -138,6 +138,7 @@ int phy_interface_num_ports(phy_interfac - case PHY_INTERFACE_MODE_RXAUI: - case PHY_INTERFACE_MODE_XAUI: - case PHY_INTERFACE_MODE_1000BASEKX: +@@ -178,6 +178,7 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_SMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_2500SGMII: - return 1; - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_5GBASER: + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_25GBASER: +--- a/drivers/net/phy/phy_caps.c ++++ b/drivers/net/phy/phy_caps.c +@@ -331,6 +331,7 @@ unsigned long phy_caps_from_interface(ph + link_caps |= BIT(LINK_CAPA_1000FD); + break; + ++ case PHY_INTERFACE_MODE_2500SGMII: + case PHY_INTERFACE_MODE_2500BASEX: + link_caps |= BIT(LINK_CAPA_2500FD); + break; --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c -@@ -266,6 +266,7 @@ static int phylink_interface_max_speed(p +@@ -274,6 +274,7 @@ static int phylink_interface_max_speed(p case PHY_INTERFACE_MODE_GMII: return SPEED_1000; @@ -44,25 +59,17 @@ Signed-off-by: Bhaskar Upadhaya case PHY_INTERFACE_MODE_2500BASEX: case PHY_INTERFACE_MODE_10G_QXGMII: return SPEED_2500; -@@ -580,6 +581,7 @@ static unsigned long phylink_get_capabil - break; - - case PHY_INTERFACE_MODE_2500BASEX: -+ case PHY_INTERFACE_MODE_2500SGMII: - caps |= MAC_2500FD; - break; - --- a/include/linux/phy.h +++ b/include/linux/phy.h -@@ -170,6 +170,7 @@ typedef enum { - PHY_INTERFACE_MODE_QUSGMII, - PHY_INTERFACE_MODE_1000BASEKX, - PHY_INTERFACE_MODE_10G_QXGMII, +@@ -136,6 +136,7 @@ typedef enum { + PHY_INTERFACE_MODE_100BASEX, + PHY_INTERFACE_MODE_1000BASEX, + PHY_INTERFACE_MODE_2500BASEX, + PHY_INTERFACE_MODE_2500SGMII, - PHY_INTERFACE_MODE_MAX, - } phy_interface_t; - -@@ -245,6 +246,8 @@ static inline const char *phy_modes(phy_ + PHY_INTERFACE_MODE_5GBASER, + PHY_INTERFACE_MODE_RXAUI, + PHY_INTERFACE_MODE_XAUI, +@@ -220,6 +221,8 @@ static inline const char *phy_modes(phy_ return "gmii"; case PHY_INTERFACE_MODE_SGMII: return "sgmii"; diff --git a/target/linux/layerscape/patches-6.18/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch b/target/linux/layerscape/patches-6.18/703-layerscape-6.18-fix-compilation-warning-for-fsl-ppfe-.patch similarity index 100% rename from target/linux/layerscape/patches-6.18/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch rename to target/linux/layerscape/patches-6.18/703-layerscape-6.18-fix-compilation-warning-for-fsl-ppfe-.patch From ed54cf8d05e64ce027dc36dd023d9c570406e891 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Mon, 27 Apr 2026 23:19:08 +0200 Subject: [PATCH 174/228] layerscape: kernel: 6.18: refresh config Done by `make kernel_oldconfig`. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- target/linux/layerscape/armv7/config-6.18 | 27 +++++----- target/linux/layerscape/armv8_64b/config-6.18 | 52 +++++++++++-------- 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/target/linux/layerscape/armv7/config-6.18 b/target/linux/layerscape/armv7/config-6.18 index c7c248458d..ef29c85e1b 100644 --- a/target/linux/layerscape/armv7/config-6.18 +++ b/target/linux/layerscape/armv7/config-6.18 @@ -19,6 +19,7 @@ CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_STACKWALK=y CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USES_CFI_GENERIC_LLVM_PASS=y CONFIG_ARM=y CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ARCH_TIMER=y @@ -68,8 +69,6 @@ CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=262144 CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y CONFIG_BLK_PM=y CONFIG_BOUNCE=y CONFIG_BROADCOM_PHY=y @@ -149,6 +148,7 @@ CONFIG_CPU_THUMB_CAPABLE=y CONFIG_CPU_TLB_V7=y CONFIG_CPU_V7=y CONFIG_CRC16=y +CONFIG_CRC32_ARCH=y CONFIG_CRC_CCITT=y CONFIG_CRC_ITU_T=y CONFIG_CROSS_MEMORY_ATTACH=y @@ -157,8 +157,9 @@ CONFIG_CRYPTO_CRC32C=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_BLAKE2S_ARCH=y CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA256_ARCH=y CONFIG_CRYPTO_LIB_UTILS=y CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_ZSTD=y @@ -174,6 +175,7 @@ CONFIG_DECOMPRESS_LZMA=y CONFIG_DECOMPRESS_LZO=y CONFIG_DECOMPRESS_XZ=y CONFIG_DETECT_HUNG_TASK=y +CONFIG_DETECT_HUNG_TASK_BLOCKER=y # CONFIG_DEVFREQ_GOV_PASSIVE is not set # CONFIG_DEVFREQ_GOV_PERFORMANCE is not set # CONFIG_DEVFREQ_GOV_POWERSAVE is not set @@ -259,7 +261,6 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_VDSO_32=y CONFIG_GIANFAR=y CONFIG_GLOB=y CONFIG_GPIOLIB_IRQCHIP=y @@ -308,11 +309,14 @@ CONFIG_ICS932S401=y CONFIG_IMX2_WDT=y # CONFIG_IMX7ULP_WDT is not set # CONFIG_IMX8MM_THERMAL is not set +# CONFIG_IMX_AIPSTZ is not set CONFIG_IMX_DMA=y # CONFIG_IMX_GPCV2_PM_DOMAINS is not set CONFIG_IMX_INTMUX=y # CONFIG_IMX_IRQSTEER is not set # CONFIG_IMX_MU_MSI is not set +# CONFIG_IMX_SCMI_CPU_DRV is not set +# CONFIG_IMX_SCMI_LMM_DRV is not set CONFIG_IMX_SDMA=y # CONFIG_IMX_WEIM is not set CONFIG_INITRAMFS_SOURCE="" @@ -329,6 +333,8 @@ CONFIG_IRQSTACKS=y CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_IOMMU=y +CONFIG_IRQ_MSI_LIB=y CONFIG_IRQ_WORK=y # CONFIG_ISDN is not set CONFIG_ISL29003=y @@ -355,8 +361,6 @@ CONFIG_MARVELL_PHY=y CONFIG_MCPM=y CONFIG_MDIO_BITBANG=y CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y # CONFIG_MDIO_GPIO is not set CONFIG_MEMORY=y CONFIG_MEMORY_ISOLATION=y @@ -434,6 +438,7 @@ CONFIG_NVMEM_LAYOUTS=y # CONFIG_NVMEM_SNVS_LPGPR is not set # CONFIG_NVMEM_SPMI_SDAM is not set CONFIG_NVMEM_SYSFS=y +# CONFIG_NXP_ENETC4 is not set CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_DYNAMIC=y @@ -449,12 +454,12 @@ CONFIG_OUTER_CACHE=y CONFIG_OUTER_CACHE_SYNC=y CONFIG_PACKET_DIAG=y CONFIG_PADATA=y +CONFIG_PAGE_BLOCK_MAX_ORDER=11 CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PAGE_POOL=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y # CONFIG_PANIC_ON_OOPS is not set -CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 CONFIG_PCI=y CONFIG_PCIEAER=y @@ -465,6 +470,7 @@ CONFIG_PCIEASPM_DEFAULT=y # CONFIG_PCIEASPM_POWER_SUPERSAVE is not set CONFIG_PCIEPORTBUS=y CONFIG_PCIE_DW=y +# CONFIG_PCIE_DW_DEBUGFS is not set CONFIG_PCIE_DW_HOST=y CONFIG_PCIE_PME=y CONFIG_PCI_DOMAINS=y @@ -481,13 +487,12 @@ CONFIG_PGTABLE_LEVELS=3 CONFIG_PHYLIB=y CONFIG_PHYLIB_LEDS=y CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_PACKAGE=y CONFIG_PID_NS=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_IMX8ULP is not set # CONFIG_PINCTRL_IMX91 is not set # CONFIG_PINCTRL_IMX93 is not set -# CONFIG_PINCTRL_IMXRT1050 is not set -# CONFIG_PINCTRL_IMXRT1170 is not set CONFIG_PL310_ERRATA_588369=y CONFIG_PL310_ERRATA_727915=y CONFIG_PL310_ERRATA_753970=y @@ -505,6 +510,7 @@ CONFIG_POWER_RESET_GPIO=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_POWER_RESET_SYSCON=y CONFIG_POWER_RESET_SYSCON_POWEROFF=y +# CONFIG_POWER_RESET_TORADEX_EC is not set CONFIG_POWER_RESET_VEXPRESS=y CONFIG_POWER_SUPPLY=y CONFIG_PPS=y @@ -553,7 +559,6 @@ CONFIG_RTC_DRV_FSL_FTM_ALARM=y CONFIG_RTC_DRV_PCF2127=y CONFIG_RTC_I2C_AND_SPI=y CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCHED_DEBUG=y CONFIG_SCSI=y CONFIG_SCSI_COMMON=y CONFIG_SECCOMP=y @@ -580,7 +585,6 @@ CONFIG_SERIAL_ST_ASC=y CONFIG_SERIAL_ST_ASC_CONSOLE=y CONFIG_SERIAL_XILINX_PS_UART=y CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y -CONFIG_SGL_ALLOC=y CONFIG_SG_POOL=y CONFIG_SMP=y CONFIG_SMP_ON_UP=y @@ -617,7 +621,6 @@ CONFIG_SPI_SPIDEV=y CONFIG_SPI_XILINX=y CONFIG_SPLIT_PTE_PTLOCKS=y CONFIG_SPMI=y -# CONFIG_SPMI_HISI3670 is not set CONFIG_SQUASHFS_FILE_CACHE=y # CONFIG_SQUASHFS_FILE_DIRECT is not set CONFIG_SQUASHFS_LZO=y diff --git a/target/linux/layerscape/armv8_64b/config-6.18 b/target/linux/layerscape/armv8_64b/config-6.18 index f9f1a777a7..53c7dde976 100644 --- a/target/linux/layerscape/armv8_64b/config-6.18 +++ b/target/linux/layerscape/armv8_64b/config-6.18 @@ -1,7 +1,6 @@ CONFIG_64BIT=y CONFIG_AQUANTIA_PHY=y CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y -CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_ARCH_FORCE_MAX_ORDER=10 @@ -20,6 +19,7 @@ CONFIG_ARCH_PROC_KCORE_TEXT=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_STACKWALK=y CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y CONFIG_ARCH_WANTS_EXECMEM_LATE=y CONFIG_ARCH_WANTS_NO_INSTR=y CONFIG_ARCH_WANTS_THP_SWAP=y @@ -38,8 +38,9 @@ CONFIG_ARM64_ERRATUM_826319=y CONFIG_ARM64_ERRATUM_827319=y CONFIG_ARM64_ERRATUM_832075=y CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_GCS=y +CONFIG_ARM64_HAFT=y CONFIG_ARM64_HW_AFDBM=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y CONFIG_ARM64_PA_BITS=48 CONFIG_ARM64_PA_BITS_48=y CONFIG_ARM64_PLATFORM_DEVICES=y @@ -59,16 +60,19 @@ CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_ITS_PARENT=y CONFIG_ARM_GIC_V2M=y CONFIG_ARM_GIC_V3=y CONFIG_ARM_GIC_V3_ITS=y CONFIG_ARM_GIC_V3_ITS_FSL_MC=y +CONFIG_ARM_GIC_V5=y # CONFIG_ARM_PL172_MPMC is not set CONFIG_ARM_PSCI_CPUIDLE=y CONFIG_ARM_PSCI_FW=y CONFIG_ARM_SMMU=y # CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT is not set # CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS is not set +# CONFIG_ARM_SMMU_MMU_500_CPRE_ERRATA is not set CONFIG_ARM_SMMU_V3=y # CONFIG_ARM_SMMU_V3_SVA is not set CONFIG_ARM_SP805_WATCHDOG=y @@ -83,6 +87,7 @@ CONFIG_AUDIT_GENERIC=y CONFIG_AUTOFS_FS=y CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BALLOON_COMPACTION=y +CONFIG_BASIC_MODVERSIONS=y CONFIG_BATTERY_BQ27XXX=y # CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM is not set CONFIG_BATTERY_BQ27XXX_I2C=y @@ -95,8 +100,6 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=262144 CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y CONFIG_BLK_PM=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y @@ -109,6 +112,7 @@ CONFIG_CAVIUM_ERRATUM_27456=y CONFIG_CC_HAVE_SHADOW_CALL_STACK=y CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y CONFIG_CHECKPOINT_RESTORE=y +# CONFIG_CHROMEOS_OF_HW_PROBER is not set CONFIG_CHROME_PLATFORMS=y CONFIG_CLK_LS1028A_PLLDIG=y CONFIG_CLK_QORIQ=y @@ -162,12 +166,13 @@ CONFIG_CPU_PM=y CONFIG_CPU_RMAP=y CONFIG_CPU_THERMAL=y CONFIG_CRC16=y +CONFIG_CRC32_ARCH=y CONFIG_CRC64=y -CONFIG_CRC64_ROCKSOFT=y CONFIG_CRC7=y CONFIG_CRC_CCITT=y CONFIG_CRC_ITU_T=y CONFIG_CRC_T10DIF=y +CONFIG_CRC_T10DIF_ARCH=y CONFIG_CROSS_MEMORY_ATTACH=y # CONFIG_CROS_EC is not set CONFIG_CRYPTO_AES_ARM64=y @@ -178,11 +183,7 @@ CONFIG_CRYPTO_AUTHENC=y CONFIG_CRYPTO_BLAKE2B=y CONFIG_CRYPTO_CRC32=y CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CRC64_ROCKSOFT=y -CONFIG_CRYPTO_CRCT10DIF=y -CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_CURVE25519=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_DEV_FSL_CAAM=y @@ -203,19 +204,15 @@ CONFIG_CRYPTO_ENGINE=y CONFIG_CRYPTO_GHASH_ARM64_CE=y CONFIG_CRYPTO_HASH_INFO=y CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=y -CONFIG_CRYPTO_LIB_CURVE25519_INTERNAL=y CONFIG_CRYPTO_LIB_DES=y CONFIG_CRYPTO_LIB_GF128MUL=y -CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_SHA256_ARCH=y CONFIG_CRYPTO_LIB_UTILS=y CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RSA=y CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA256_ARM64=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SIG=y CONFIG_CRYPTO_XTS=y CONFIG_CRYPTO_XXHASH=y CONFIG_CRYPTO_ZSTD=y @@ -229,6 +226,7 @@ CONFIG_DECOMPRESS_LZMA=y CONFIG_DECOMPRESS_LZO=y CONFIG_DECOMPRESS_XZ=y CONFIG_DETECT_HUNG_TASK=y +CONFIG_DETECT_HUNG_TASK_BLOCKER=y CONFIG_DMADEVICES=y CONFIG_DMATEST=y CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y @@ -255,6 +253,7 @@ CONFIG_EXCLUSIVE_SYSTEM_RAM=y CONFIG_EXT4_FS=y CONFIG_EXTCON=y CONFIG_EXTCON_USB_GPIO=y +# CONFIG_EXTENDED_MODVERSIONS is not set CONFIG_F2FS_FS=y CONFIG_FAILOVER=y CONFIG_FANOTIFY=y @@ -270,6 +269,7 @@ CONFIG_FB_SYS_COPYAREA=y CONFIG_FB_SYS_FILLRECT=y CONFIG_FB_SYS_IMAGEBLIT=y CONFIG_FHANDLE=y +CONFIG_FIND_NORMAL_PAGE=y CONFIG_FIXED_PHY=y CONFIG_FIX_EARLYCON_MEM=y CONFIG_FONT_8x16=y @@ -311,6 +311,7 @@ CONFIG_FS_POSIX_ACL=y CONFIG_FUNCTION_ALIGNMENT=4 CONFIG_FUNCTION_ALIGNMENT_4B=y CONFIG_FUSE_FS=y +CONFIG_FUTEX_MPOL=y CONFIG_FWNODE_MDIO=y CONFIG_FW_CACHE=y CONFIG_FW_LOADER_PAGED_BUF=y @@ -318,6 +319,7 @@ CONFIG_FW_LOADER_SYSFS=y # CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set CONFIG_GARP=y CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +# CONFIG_GENDWARFKSYMS is not set CONFIG_GENERIC_ALLOCATOR=y CONFIG_GENERIC_ARCH_NUMA=y CONFIG_GENERIC_ARCH_TOPOLOGY=y @@ -334,6 +336,8 @@ CONFIG_GENERIC_GETTIMEOFDAY=y CONFIG_GENERIC_IDLE_POLL_SETUP=y CONFIG_GENERIC_IOREMAP=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_ENTRY=y +CONFIG_GENERIC_IRQ_KEXEC_CLEAR_VM_FORWARD=y CONFIG_GENERIC_IRQ_MIGRATION=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_IRQ_SHOW_LEVEL=y @@ -346,6 +350,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_STRNCPY_FROM_USER=y CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENKSYMS=y # CONFIG_GIANFAR is not set CONFIG_GLOB=y CONFIG_GPIOLIB_IRQCHIP=y @@ -369,6 +374,7 @@ CONFIG_HIBERNATION_SNAPSHOT_DEV=y CONFIG_HOTPLUG_CORE_SYNC=y CONFIG_HOTPLUG_CORE_SYNC_DEAD=y CONFIG_HOTPLUG_CPU=y +CONFIG_HOTPLUG_SMT=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING=y @@ -442,7 +448,6 @@ CONFIG_KEYBOARD_ATKBD=y CONFIG_KEYBOARD_GPIO=y CONFIG_KSM=y CONFIG_LEGACY_DIRECT_IO=y -CONFIG_LIBCRC32C=y CONFIG_LIBFDT=y CONFIG_LOCALVERSION_AUTO=y CONFIG_LOCK_DEBUGGING_SUPPORT=y @@ -462,8 +467,6 @@ CONFIG_MDIO_BUS=y CONFIG_MDIO_BUS_MUX=y CONFIG_MDIO_BUS_MUX_MMIOREG=y CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y # CONFIG_MDIO_GPIO is not set CONFIG_MEMORY=y CONFIG_MEMORY_BALLOON=y @@ -484,6 +487,7 @@ CONFIG_MMC_SDHCI_OF_ESDHC=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMU_LAZY_TLB_REFCOUNT=y CONFIG_MMU_NOTIFIER=y +CONFIG_MM_ID=y CONFIG_MODULES_USE_ELF_RELA=y CONFIG_MODULE_FORCE_LOAD=y CONFIG_MODVERSIONS=y @@ -557,6 +561,7 @@ CONFIG_NLS_ISO8859_1=y CONFIG_NODES_SHIFT=2 CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_PAGE_MAPCOUNT is not set CONFIG_NR_CPUS=64 # CONFIG_NSM is not set CONFIG_NUMA=y @@ -569,6 +574,8 @@ CONFIG_NVMEM_LAYERSCAPE_SFP=y CONFIG_NVMEM_LAYOUTS=y # CONFIG_NVMEM_SPMI_SDAM is not set CONFIG_NVMEM_SYSFS=y +# CONFIG_NXP_ENETC4 is not set +CONFIG_NXP_ENETC_PF_COMMON=y CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_EARLY_FLATTREE=y @@ -582,12 +589,12 @@ CONFIG_OF_NUMA=y CONFIG_PACKET_DIAG=y CONFIG_PACKING=y CONFIG_PADATA=y +CONFIG_PAGE_BLOCK_MAX_ORDER=10 CONFIG_PAGE_POOL=y CONFIG_PAGE_REPORTING=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y # CONFIG_PANIC_ON_OOPS is not set -CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 CONFIG_PARAVIRT=y # CONFIG_PARTITION_ADVANCED is not set @@ -601,6 +608,7 @@ CONFIG_PCIEASPM_DEFAULT=y # CONFIG_PCIEASPM_POWER_SUPERSAVE is not set CONFIG_PCIEPORTBUS=y CONFIG_PCIE_DW=y +# CONFIG_PCIE_DW_DEBUGFS is not set CONFIG_PCIE_DW_HOST=y CONFIG_PCIE_LAYERSCAPE_GEN4=y CONFIG_PCIE_MOBIVEIL=y @@ -617,6 +625,7 @@ CONFIG_PCI_IOV=y CONFIG_PCI_LAYERSCAPE=y CONFIG_PCI_MSI=y CONFIG_PCS_LYNX=y +# CONFIG_PERSISTENT_HUGE_ZERO_FOLIO is not set CONFIG_PER_VMA_LOCK=y CONFIG_PGTABLE_HAS_HUGE_LEAVES=y CONFIG_PGTABLE_LEVELS=4 @@ -625,6 +634,7 @@ CONFIG_PHYLIB_LEDS=y CONFIG_PHYLINK=y CONFIG_PHYS_ADDR_T_64BIT=y # CONFIG_PHY_FSL_LYNX_28G is not set +CONFIG_PHY_PACKAGE=y CONFIG_PID_IN_CONTEXTIDR=y CONFIG_PID_NS=y CONFIG_PL330_DMA=y @@ -673,7 +683,6 @@ CONFIG_REGMAP_MMIO=y CONFIG_REGMAP_SPI=y CONFIG_RESET_CONTROLLER=y CONFIG_RFS_ACCEL=y -CONFIG_RODATA_FULL_DEFAULT_ENABLED=y CONFIG_RPS=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_DS1307=y @@ -720,7 +729,6 @@ CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y CONFIG_SERIO=y CONFIG_SERIO_AMBAKMI=y CONFIG_SERIO_LIBPS2=y -CONFIG_SGL_ALLOC=y CONFIG_SG_POOL=y CONFIG_SMP=y CONFIG_SOCK_DIAG=y @@ -773,7 +781,6 @@ CONFIG_THREAD_INFO_IN_TASK=y CONFIG_TICK_CPU_ACCOUNTING=y CONFIG_TIMER_OF=y CONFIG_TIMER_PROBE=y -CONFIG_TOOLS_SUPPORT_RELR=y CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y @@ -813,7 +820,6 @@ CONFIG_VFIO_IOMMU_TYPE1=y CONFIG_VFIO_PCI=y CONFIG_VFIO_PCI_CORE=y CONFIG_VFIO_PCI_INTX=y -CONFIG_VFIO_PCI_MMAP=y CONFIG_VFIO_VIRQFD=y CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 From 7c3ac472d36c7b767b59f619bcc4155676ec5b60 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 5 May 2026 22:56:06 +0200 Subject: [PATCH 175/228] layerscape: switch to 6.18 kernel Since there are no other active developers working on this target, switch it to 6.18 for wider testing. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- target/linux/layerscape/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/layerscape/Makefile b/target/linux/layerscape/Makefile index 61690b8b58..7d675335e1 100644 --- a/target/linux/layerscape/Makefile +++ b/target/linux/layerscape/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk BOARD:=layerscape BOARDNAME:=NXP Layerscape -KERNEL_PATCHVER:=6.12 +KERNEL_PATCHVER:=6.18 FEATURES:=squashfs nand usb pcie gpio fpu ubifs ext4 rootfs-part boot-part SUBTARGETS:=armv8_64b armv7 From 32b82864ba31709957e81bc1c8c2f866434b6422 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 5 May 2026 22:59:24 +0200 Subject: [PATCH 176/228] restool: bump to lf-6.18.2-1.0.0 This commit bumps restool layerscape package to lf-6.18.2-1.0.0 version. Patch to disable manpage build was dropped and replaced with MANPAGE="" in MAKE_FLAGS. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- .../network/utils/layerscape/restool/Makefile | 8 ++++---- .../restool/patches/remove-manpage.patch | 18 ------------------ 2 files changed, 4 insertions(+), 22 deletions(-) delete mode 100644 package/network/utils/layerscape/restool/patches/remove-manpage.patch diff --git a/package/network/utils/layerscape/restool/Makefile b/package/network/utils/layerscape/restool/Makefile index ac8c5887a2..eecc8d5a0d 100644 --- a/package/network/utils/layerscape/restool/Makefile +++ b/package/network/utils/layerscape/restool/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=restool -PKG_VERSION:=6.6.23.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/restool -PKG_SOURCE_VERSION:=lf-6.6.23-2.0.0 -PKG_MIRROR_HASH:=e669c9faf5a00e36d763dbbd6dd866d878b0101df086582c38908d281fa3b465 +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=d3e35b9e8e0db98aa52c0f48fba4b2c9c6e124a0d32e8bf36c208f9dfe3a8dc2 PKG_FLAGS:=nonshared @@ -27,7 +27,7 @@ define Package/restool DEPENDS:=@TARGET_layerscape_armv8_64b endef -MAKE_FLAGS += \ +MAKE_FLAGS += MANPAGE="" \ DESTDIR="$(PKG_BUILD_DIR)"/output/ \ install diff --git a/package/network/utils/layerscape/restool/patches/remove-manpage.patch b/package/network/utils/layerscape/restool/patches/remove-manpage.patch deleted file mode 100644 index ffd73c31fa..0000000000 --- a/package/network/utils/layerscape/restool/patches/remove-manpage.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/Makefile -+++ b/Makefile -@@ -55,14 +55,13 @@ restool: $(OBJ) - %.1: %.md - pandoc --standalone --to man $^ -o $@ - --install: restool scripts/ls-main scripts/ls-append-dpl scripts/ls-debug scripts/restool_completion.sh $(MANPAGE) -+install: restool scripts/ls-main scripts/ls-append-dpl scripts/ls-debug scripts/restool_completion.sh - install -D -m 755 restool $(DESTDIR)$(bindir)/restool - install -D -m 755 scripts/ls-main $(DESTDIR)$(bindir)/ls-main - install -D -m 755 scripts/ls-append-dpl $(DESTDIR)$(bindir)/ls-append-dpl - install -D -m 755 scripts/ls-debug $(DESTDIR)$(bindir)/ls-debug - $(foreach symlink, $(RESTOOL_SCRIPT_SYMLINKS), sh -c "cd $(DESTDIR)$(bindir) && ln -sf ls-main $(symlink)" ;) - install -D -m 755 scripts/restool_completion.sh $(DESTDIR)$(bindir_completion)/restool -- install -m 0644 -D $(MANPAGE) $(call get_manpage_destination,$(MANPAGE)) - - clean: - rm -f $(OBJ) $(MANPAGE) \ From d85001291de9df55df1607eb43e5e0e586dd2a7a Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 5 May 2026 23:01:15 +0200 Subject: [PATCH 177/228] ppfe-firmware: bump to lf-6.18.2-1.0.0 Bump ppfe-firmware package to lf-6.18.2-1.0.0. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- package/firmware/layerscape/ppfe-firmware/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/firmware/layerscape/ppfe-firmware/Makefile b/package/firmware/layerscape/ppfe-firmware/Makefile index 52df30c36d..81d0d3cc8e 100644 --- a/package/firmware/layerscape/ppfe-firmware/Makefile +++ b/package/firmware/layerscape/ppfe-firmware/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ppfe -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/qoriq-engine-pfe-bin -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=57ff6ebc78e774a12f64ac7d4738621edabdeee3a46c6ee69343ba0a8bff73cd +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=71bed42bc91366967a8efe9343ccecd1cec7d7538a9605f642b24cfd6a4ba07e PKG_FLAGS:=nonshared From b06e431a690f487ba14ad556cb83fc57ad26bd87 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 5 May 2026 23:03:45 +0200 Subject: [PATCH 178/228] tfa-layerscape: bump to lf-6.18.2-1.0.0 Bump tfa-layerscape package to lf-6.18.2-1.0.0. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- package/boot/tfa-layerscape/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/boot/tfa-layerscape/Makefile b/package/boot/tfa-layerscape/Makefile index b69944ff81..d734066abb 100644 --- a/package/boot/tfa-layerscape/Makefile +++ b/package/boot/tfa-layerscape/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=tfa-layerscape -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/atf -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=1e1c74900113a8d4354c06fdcedfff2cd6b0899b4a063d393de98f8ca358dfd2 +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=4baa079cdc794bd6095c4d5cecb64d38d94273d592ad6d84da955cff3d443393 PKG_BUILD_DEPENDS:=tfa-layerscape/host include $(INCLUDE_DIR)/host-build.mk From 71ae5c3e51d445ebe0d5c978d7a383ed04ba2787 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 5 May 2026 23:03:45 +0200 Subject: [PATCH 179/228] uboot-layerscape: bump to lf-6.18.2-1.0.0 Bump uboot-layerscape package to lf-6.18.2-1.0.0. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- package/boot/uboot-layerscape/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/boot/uboot-layerscape/Makefile b/package/boot/uboot-layerscape/Makefile index f97cdd9faf..de6cc2e040 100644 --- a/package/boot/uboot-layerscape/Makefile +++ b/package/boot/uboot-layerscape/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uboot-layerscape -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/u-boot -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=13594333aa3ee131d5832b4da88f73cf0744d98c28e90ad3e03594788c486e37 +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=047df1acdbf35004bc9d896ee688da5930da3b8a6f02a7bdc109a1367be61fee include $(INCLUDE_DIR)/u-boot.mk include $(INCLUDE_DIR)/package.mk From 9c4e0f167f64264f37412eae331f8d392da37cf1 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 5 May 2026 23:03:46 +0200 Subject: [PATCH 180/228] fman-ucode: bump to lf-6.18.2-1.0.0 Bump fman-ucode package to lf-6.18.2-1.0.0. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- package/firmware/layerscape/fman-ucode/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/firmware/layerscape/fman-ucode/Makefile b/package/firmware/layerscape/fman-ucode/Makefile index 315f31a6e6..934f3ad83c 100644 --- a/package/firmware/layerscape/fman-ucode/Makefile +++ b/package/firmware/layerscape/fman-ucode/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=fman-ucode -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/qoriq-fm-ucode -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=15b5df228b23b4cbdd1af484c98069b558d32ece15a80f0dabe22af6e5ee1ba1 +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=155b74a390c8eefc7767b68993eb41cf04ac6d578ae53eb82cff40a1c1251375 PKG_FLAGS:=nonshared From 865f36da49d086e21660f63fc9b80c7aca9b546d Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 5 May 2026 23:03:46 +0200 Subject: [PATCH 181/228] ls-ddr-phy: bump to lf-6.18.2-1.0.0 Bump ls-ddr-phy package to lf-6.18.2-1.0.0. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- package/firmware/layerscape/ls-ddr-phy/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/firmware/layerscape/ls-ddr-phy/Makefile b/package/firmware/layerscape/ls-ddr-phy/Makefile index ff7637ce2f..50496381ee 100644 --- a/package/firmware/layerscape/ls-ddr-phy/Makefile +++ b/package/firmware/layerscape/ls-ddr-phy/Makefile @@ -6,13 +6,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ls-ddr-phy -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/NXP/ddr-phy-binary.git -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=162616b23041e345a9a12080005ee1c24c9903d6809c60a022588a1c7f5b1577 +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=376d9af14bfe4ee6f14ae77ace9d592606d82ad3d7af87dda47d5fa8fd3ba10e PKG_BUILD_DEPENDS:=tfa-layerscape/host PKG_LICENSE:=EULA From b3d9b17b175f9c1b08f86060adfe474c7f95cd9e Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 5 May 2026 23:03:46 +0200 Subject: [PATCH 182/228] ls-dpl: bump to 10.40.0 Bump ls-dpl package to 10.40.0. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- package/firmware/layerscape/ls-dpl/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/firmware/layerscape/ls-dpl/Makefile b/package/firmware/layerscape/ls-dpl/Makefile index ade37d7dff..b09d900c7b 100644 --- a/package/firmware/layerscape/ls-dpl/Makefile +++ b/package/firmware/layerscape/ls-dpl/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ls-dpl -PKG_VERSION:=10.39.0 +PKG_VERSION:=10.40.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/mc-utils -PKG_SOURCE_VERSION:=mc_release_10.39.0 -PKG_MIRROR_HASH:=48e0ad66f536689bf8cfd115420422a1c746cd609816bd9b07ef8ef358a85cf4 +PKG_SOURCE_VERSION:=mc_release_10.40.0 +PKG_MIRROR_HASH:=d29481aeddbfff337b8bdcdd0a93c19dd0673f0408246e7f3f98cd2c0af15cc3 PKG_FLAGS:=nonshared From 5bf6f9a711328607b5fee1dd2159d70a9632c050 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 5 May 2026 23:03:46 +0200 Subject: [PATCH 183/228] ls-mc: bump to 10.40.0 Bump ls-mc package to 10.40.0. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- package/firmware/layerscape/ls-mc/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/firmware/layerscape/ls-mc/Makefile b/package/firmware/layerscape/ls-mc/Makefile index 54b17f3e97..79bc69be6a 100644 --- a/package/firmware/layerscape/ls-mc/Makefile +++ b/package/firmware/layerscape/ls-mc/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ls-mc -PKG_VERSION:=10.39.0 +PKG_VERSION:=10.40.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/NXP/qoriq-mc-binary.git -PKG_SOURCE_VERSION:=mc_release_10.39.0 -PKG_MIRROR_HASH:=0676072ec3fcb7ad3ec101ea279f5e7b41b292b44426563aba9062668f9855ab +PKG_SOURCE_VERSION:=mc_release_10.40.0 +PKG_MIRROR_HASH:=d4359637da641108f5c8b39c1db43d9dda4d2f8e64d4a4c89ce0301ebd12b3b1 PKG_FLAGS:=nonshared From 4b607bb31881b69b3f042a8b4fb8b0cbf0323e72 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 5 May 2026 23:03:46 +0200 Subject: [PATCH 184/228] ls-rcw: bump to lf-6.18.2-1.0.0 Bump ls-rcw package to lf-6.18.2-1.0.0. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/23290 Signed-off-by: Jonas Jelonek --- package/firmware/layerscape/ls-rcw/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/firmware/layerscape/ls-rcw/Makefile b/package/firmware/layerscape/ls-rcw/Makefile index 03049add1c..0ea0165d67 100644 --- a/package/firmware/layerscape/ls-rcw/Makefile +++ b/package/firmware/layerscape/ls-rcw/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ls-rcw -PKG_VERSION:=6.12.20.2.0.0 +PKG_VERSION:=6.18.2.1.0.0 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/nxp-qoriq/rcw -PKG_SOURCE_VERSION:=lf-6.12.20-2.0.0 -PKG_MIRROR_HASH:=8436e04a01fa7a0da3512dae035b47122691fc860fa2c36da20552bceec9246a +PKG_SOURCE_VERSION:=lf-6.18.2-1.0.0 +PKG_MIRROR_HASH:=a2f908c2b0a31a728f72ca9b9edb1a349c3f9037d65bed6a8236818a1a243873 PKG_FLAGS:=nonshared From 55efd11f2756bdb0a862fd04ed76a5fe73a8cb98 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Fri, 26 Jun 2026 18:57:52 +0200 Subject: [PATCH 185/228] layerscape: drop 6.12 files Remove kernel configs and patches for 6.12, now that layerscape target was switched to 6.18. This was missed during the 6.12 -> 6.18 PR. Signed-off-by: Jonas Jelonek --- target/linux/layerscape/armv7/config-6.12 | 697 - target/linux/layerscape/armv8_64b/config-6.12 | 887 -- ...dts-ls1012a-update-with-ppfe-support.patch | 228 - ...a-frdm-workaround-by-updating-qspi-f.patch | 41 - ...a-rdb-workaround-by-updating-qspi-fl.patch | 29 - ...a-rdb-Update-qspi-spi-rx-bus-width-t.patch | 34 - ...nor-Use-1-bit-mode-of-spansion-s25fs.patch | 28 - .../701-staging-add-fsl_ppfe-driver.patch | 11851 ---------------- ...02-phy-Add-2.5G-SGMII-interface-mode.patch | 73 - ...ix-compilation-warning-for-fsl-ppfe-.patch | 239 - ...s1012a-frdm-add-GPIO-hog-for-PHY-res.patch | 36 - 11 files changed, 14143 deletions(-) delete mode 100644 target/linux/layerscape/armv7/config-6.12 delete mode 100644 target/linux/layerscape/armv8_64b/config-6.12 delete mode 100644 target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch delete mode 100644 target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch delete mode 100644 target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch delete mode 100644 target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch delete mode 100644 target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch delete mode 100644 target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch delete mode 100644 target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch delete mode 100644 target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch delete mode 100644 target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch diff --git a/target/linux/layerscape/armv7/config-6.12 b/target/linux/layerscape/armv7/config-6.12 deleted file mode 100644 index cf9d642980..0000000000 --- a/target/linux/layerscape/armv7/config-6.12 +++ /dev/null @@ -1,697 +0,0 @@ -CONFIG_AD525X_DPOT=y -CONFIG_AD525X_DPOT_I2C=y -# CONFIG_AD525X_DPOT_SPI is not set -CONFIG_ALIGNMENT_TRAP=y -CONFIG_APDS9802ALS=y -CONFIG_AQUANTIA_PHY=y -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MULTIPLATFORM=y -CONFIG_ARCH_MULTI_V6_V7=y -CONFIG_ARCH_MULTI_V7=y -CONFIG_ARCH_MXC=y -CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y -CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARM=y -CONFIG_ARM_APPENDED_DTB=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_ATAG_DTB_COMPAT=y -CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y -CONFIG_ARM_CPUIDLE=y -CONFIG_ARM_CPU_SUSPEND=y -CONFIG_ARM_ERRATA_430973=y -CONFIG_ARM_ERRATA_643719=y -CONFIG_ARM_ERRATA_720789=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_ARM_ERRATA_754327=y -CONFIG_ARM_ERRATA_764369=y -CONFIG_ARM_ERRATA_775420=y -CONFIG_ARM_ERRATA_798181=y -CONFIG_ARM_GIC=y -CONFIG_ARM_HAS_GROUP_RELOCS=y -CONFIG_ARM_HEAVY_MB=y -# CONFIG_ARM_HIGHBANK_CPUIDLE is not set -# CONFIG_ARM_IMX8M_DDRC_DEVFREQ is not set -# CONFIG_ARM_IMX_BUS_DEVFREQ is not set -# CONFIG_ARM_IMX_CPUFREQ_DT is not set -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_LPAE=y -CONFIG_ARM_PATCH_IDIV=y -CONFIG_ARM_PATCH_PHYS_VIRT=y -CONFIG_ARM_PSCI=y -CONFIG_ARM_PSCI_FW=y -# CONFIG_ARM_SMMU is not set -CONFIG_ARM_THUMB=y -CONFIG_ARM_THUMBEE=y -CONFIG_ARM_UNWIND=y -CONFIG_ARM_VIRT_EXT=y -CONFIG_ATAGS=y -CONFIG_AUTOFS_FS=y -CONFIG_AUTO_ZRELADDR=y -CONFIG_BATTERY_SBS=y -CONFIG_BCM_NET_PHYLIB=y -CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y -CONFIG_BLK_DEV_BSG=y -CONFIG_BLK_DEV_BSG_COMMON=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=262144 -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y -CONFIG_BLK_PM=y -CONFIG_BOUNCE=y -CONFIG_BROADCOM_PHY=y -CONFIG_BUFFER_HEAD=y -CONFIG_CACHE_L2X0=y -CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y -CONFIG_CDROM=y -CONFIG_CHECKPOINT_RESTORE=y -CONFIG_CHR_DEV_SG=y -CONFIG_CLKSRC_IMX_GPT=y -CONFIG_CLKSRC_MMIO=y -# CONFIG_CLK_IMX8MM is not set -# CONFIG_CLK_IMX8MN is not set -# CONFIG_CLK_IMX8MP is not set -# CONFIG_CLK_IMX8MQ is not set -# CONFIG_CLK_IMX8ULP is not set -# CONFIG_CLK_IMX93 is not set -# CONFIG_CLK_IMX95_BLK_CTL is not set -CONFIG_CLK_QORIQ=y -# CONFIG_CLK_VEXPRESS_OSC is not set -CONFIG_CLONE_BACKWARDS=y -CONFIG_CMA=y -CONFIG_CMA_ALIGNMENT=8 -CONFIG_CMA_AREAS=7 -# CONFIG_CMA_DEBUGFS is not set -CONFIG_CMA_SIZE_MBYTES=64 -# CONFIG_CMA_SIZE_SEL_MAX is not set -CONFIG_CMA_SIZE_SEL_MBYTES=y -# CONFIG_CMA_SIZE_SEL_MIN is not set -# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set -# CONFIG_CMA_SYSFS is not set -CONFIG_CMDLINE_PARTITION=y -CONFIG_COMMON_CLK=y -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONFIGFS_FS=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -CONFIG_CONTIG_ALLOC=y -CONFIG_COREDUMP=y -CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y -CONFIG_CPUFREQ_DT=y -CONFIG_CPUFREQ_DT_PLATDEV=y -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MITIGATIONS=y -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_SPECTRE=y -CONFIG_CPU_THERMAL=y -CONFIG_CPU_THUMB_CAPABLE=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_V7=y -CONFIG_CRC16=y -CONFIG_CRC_CCITT=y -CONFIG_CRC_ITU_T=y -CONFIG_CROSS_MEMORY_ATTACH=y -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_GF128MUL=y -CONFIG_CRYPTO_LIB_SHA1=y -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_CURRENT_POINTER_IN_TPIDRURO=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_ALIGN_RODATA=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" -CONFIG_DECOMPRESS_BZIP2=y -CONFIG_DECOMPRESS_GZIP=y -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DECOMPRESS_LZO=y -CONFIG_DECOMPRESS_XZ=y -CONFIG_DETECT_HUNG_TASK=y -# CONFIG_DEVFREQ_GOV_PASSIVE is not set -# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set -# CONFIG_DEVFREQ_GOV_POWERSAVE is not set -# CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND is not set -# CONFIG_DEVFREQ_GOV_USERSPACE is not set -# CONFIG_DEVFREQ_THERMAL is not set -CONFIG_DMADEVICES=y -CONFIG_DMA_CMA=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_NEED_SYNC=y -CONFIG_DMA_OF=y -CONFIG_DMA_OPS_HELPERS=y -CONFIG_DMA_SHARED_BUFFER=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DNOTIFY=y -CONFIG_DTC=y -CONFIG_DT_IDLE_STATES=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_DW_DMAC=y -CONFIG_DW_DMAC_CORE=y -CONFIG_DW_WATCHDOG=y -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EEPROM_93CX6=y -CONFIG_EEPROM_AT24=y -CONFIG_ELF_CORE=y -# CONFIG_ENABLE_DEFAULT_TRACERS is not set -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_EXT4_FS=y -CONFIG_F2FS_FS=y -CONFIG_FAILOVER=y -CONFIG_FAT_FS=y -# CONFIG_FEC is not set -CONFIG_FHANDLE=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FREEZER=y -CONFIG_FSL_EDMA=y -CONFIG_FSL_GUTS=y -CONFIG_FSL_IFC=y -# CONFIG_FSL_PPFE is not set -CONFIG_FSL_PQ_MDIO=y -CONFIG_FSL_RCPM=y -CONFIG_FSL_XGMAC_MDIO=y -CONFIG_FS_IOMAP=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y -CONFIG_FTRACE=y -# CONFIG_FTRACE_SYSCALLS is not set -CONFIG_FUNCTION_ALIGNMENT=0 -CONFIG_FUSE_FS=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_CACHE=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_DEVICES=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_MIGRATION=y -CONFIG_GENERIC_IRQ_MULTI_HANDLER=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_PINCONF=y -CONFIG_GENERIC_PINCTRL_GROUPS=y -CONFIG_GENERIC_PINMUX_FUNCTIONS=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_VDSO_32=y -CONFIG_GIANFAR=y -CONFIG_GLOB=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_MPC8XXX=y -CONFIG_GPIO_MXC=y -CONFIG_GPIO_VF610=y -# CONFIG_HARDEN_BRANCH_HISTORY is not set -# CONFIG_HARDEN_BRANCH_PREDICTOR is not set -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HAVE_SMP=y -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -# CONFIG_HIST_TRIGGERS is not set -CONFIG_HOTPLUG_CORE_SYNC=y -CONFIG_HOTPLUG_CORE_SYNC_DEAD=y -CONFIG_HOTPLUG_CPU=y -CONFIG_HVC_DRIVER=y -CONFIG_HW_RANDOM=y -CONFIG_HZ_FIXED=0 -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_DEMUX_PINCTRL=y -CONFIG_I2C_DESIGNWARE_CORE=y -CONFIG_I2C_DESIGNWARE_PLATFORM=y -CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_IMX=y -# CONFIG_I2C_IMX_LPI2C is not set -CONFIG_I2C_MUX=y -CONFIG_I2C_MUX_PCA954x=y -CONFIG_I2C_MUX_PINCTRL=y -CONFIG_I2C_RK3X=y -CONFIG_I2C_SLAVE=y -CONFIG_I2C_SLAVE_EEPROM=y -# CONFIG_I2C_SLAVE_TESTUNIT is not set -CONFIG_I2C_XILINX=y -CONFIG_ICPLUS_PHY=y -CONFIG_ICS932S401=y -CONFIG_IMX2_WDT=y -# CONFIG_IMX7ULP_WDT is not set -# CONFIG_IMX8MM_THERMAL is not set -CONFIG_IMX_DMA=y -# CONFIG_IMX_GPCV2_PM_DOMAINS is not set -CONFIG_IMX_INTMUX=y -# CONFIG_IMX_IRQSTEER is not set -# CONFIG_IMX_MU_MSI is not set -CONFIG_IMX_SDMA=y -# CONFIG_IMX_WEIM is not set -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INPUT=y -# CONFIG_INPUT_BBNSM_PWRKEY is not set -# CONFIG_IOMMUFD is not set -# CONFIG_IOMMU_DEBUGFS is not set -# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set -# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set -CONFIG_IOMMU_SUPPORT=y -CONFIG_IPC_NS=y -CONFIG_IRQCHIP=y -CONFIG_IRQSTACKS=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_WORK=y -# CONFIG_ISDN is not set -CONFIG_ISL29003=y -CONFIG_JBD2=y -CONFIG_KALLSYMS=y -CONFIG_KCMP=y -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_XZ is not set -CONFIG_KEXEC=y -CONFIG_KEXEC_CORE=y -CONFIG_KMAP_LOCAL=y -CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y -CONFIG_LEGACY_DIRECT_IO=y -CONFIG_LIBFDT=y -CONFIG_LOCALVERSION_AUTO=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LS_EXTIRQ=y -CONFIG_LS_SCFG_MSI=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_MARVELL_PHY=y -CONFIG_MCPM=y -CONFIG_MDIO_BITBANG=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -# CONFIG_MDIO_GPIO is not set -CONFIG_MEMORY=y -CONFIG_MEMORY_ISOLATION=y -# CONFIG_MFD_HI6421_SPMI is not set -CONFIG_MFD_SYSCON=y -# CONFIG_MFD_VEXPRESS_SYSREG is not set -CONFIG_MICREL_PHY=y -CONFIG_MIGHT_HAVE_CACHE_L2X0=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_BLOCK_MINORS=16 -# CONFIG_MMC_MXC is not set -CONFIG_MMC_SDHCI=y -# CONFIG_MMC_SDHCI_ESDHC_IMX is not set -CONFIG_MMC_SDHCI_IO_ACCESSORS=y -CONFIG_MMC_SDHCI_OF_ESDHC=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMU_LAZY_TLB_REFCOUNT=y -CONFIG_MODULES_USE_ELF_REL=y -CONFIG_MSDOS_FS=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_GEOMETRY=y -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_DATAFLASH=y -# CONFIG_MTD_DATAFLASH_OTP is not set -# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_FSL_IFC=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y -CONFIG_MTD_SST25L=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -# CONFIG_MTD_UBI_BLOCK is not set -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_MXC_CLK=y -# CONFIG_MXS_DMA is not set -CONFIG_NAMESPACES=y -CONFIG_NATIONAL_PHY=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SRCU_NMI_SAFE=y -CONFIG_NEON=y -CONFIG_NET_DEVMEM=y -CONFIG_NET_EGRESS=y -CONFIG_NET_FAILOVER=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_INGRESS=y -CONFIG_NET_NS=y -CONFIG_NET_PTP_CLASSIFY=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_XGRESS=y -CONFIG_NLS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NLS_UTF8=y -CONFIG_NO_HZ=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=16 -# CONFIG_NSM is not set -CONFIG_NTFS3_FS=y -CONFIG_NTFS_FS=y -CONFIG_NVMEM=y -# CONFIG_NVMEM_IMX_IIM is not set -# CONFIG_NVMEM_IMX_OCOTP_ELE is not set -CONFIG_NVMEM_LAYOUTS=y -# CONFIG_NVMEM_SNVS_LPGPR is not set -# CONFIG_NVMEM_SPMI_SDAM is not set -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_DYNAMIC=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_PACKET_DIAG=y -CONFIG_PADATA=y -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PAGE_POOL=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -# CONFIG_PANIC_ON_OOPS is not set -CONFIG_PANIC_ON_OOPS_VALUE=0 -CONFIG_PANIC_TIMEOUT=0 -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEASPM=y -CONFIG_PCIEASPM_DEFAULT=y -# CONFIG_PCIEASPM_PERFORMANCE is not set -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_DW=y -CONFIG_PCIE_DW_HOST=y -CONFIG_PCIE_PME=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_ECAM=y -CONFIG_PCI_HOST_COMMON=y -CONFIG_PCI_HOST_GENERIC=y -# CONFIG_PCI_IMX6_HOST is not set -CONFIG_PCI_LAYERSCAPE=y -CONFIG_PCI_MSI=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PER_VMA_LOCK=y -CONFIG_PGTABLE_LEVELS=3 -CONFIG_PHYLIB=y -CONFIG_PHYLIB_LEDS=y -CONFIG_PHYS_ADDR_T_64BIT=y -CONFIG_PID_NS=y -CONFIG_PINCTRL=y -# CONFIG_PINCTRL_IMX8ULP is not set -# CONFIG_PINCTRL_IMX91 is not set -# CONFIG_PINCTRL_IMX93 is not set -# CONFIG_PINCTRL_IMXRT1050 is not set -# CONFIG_PINCTRL_IMXRT1170 is not set -CONFIG_PL310_ERRATA_588369=y -CONFIG_PL310_ERRATA_727915=y -CONFIG_PL310_ERRATA_753970=y -CONFIG_PL310_ERRATA_769419=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_DEVFREQ=y -# CONFIG_PM_DEVFREQ_EVENT is not set -CONFIG_PM_OPP=y -CONFIG_PM_SLEEP=y -CONFIG_PM_SLEEP_SMP=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_BRCMKONA=y -CONFIG_POWER_RESET_GPIO=y -CONFIG_POWER_RESET_GPIO_RESTART=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_RESET_SYSCON_POWEROFF=y -CONFIG_POWER_RESET_VEXPRESS=y -CONFIG_POWER_SUPPLY=y -CONFIG_PPS=y -CONFIG_PRINTK_TIME=y -CONFIG_PROC_CHILDREN=y -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_PSTORE=y -CONFIG_PSTORE_COMPRESS=y -CONFIG_PSTORE_CONSOLE=y -CONFIG_PSTORE_PMSG=y -CONFIG_PSTORE_RAM=y -CONFIG_PTP_1588_CLOCK=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PTP_1588_CLOCK_QORIQ=y -CONFIG_QORIQ_CPUFREQ=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_RD_BZIP2=y -CONFIG_RD_GZIP=y -CONFIG_RD_LZMA=y -CONFIG_RD_LZO=y -CONFIG_RD_XZ=y -CONFIG_REALTEK_PHY=y -CONFIG_REED_SOLOMON=y -CONFIG_REED_SOLOMON_DEC8=y -CONFIG_REED_SOLOMON_ENC8=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGMAP_SPI=y -CONFIG_RESET_CONTROLLER=y -# CONFIG_RESET_IMX8MP_AUDIOMIX is not set -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -# CONFIG_RTC_DRV_BBNSM is not set -# CONFIG_RTC_DRV_CMOS is not set -CONFIG_RTC_DRV_DS1307=y -CONFIG_RTC_DRV_DS3232=y -CONFIG_RTC_DRV_EM3027=y -CONFIG_RTC_DRV_FSL_FTM_ALARM=y -# CONFIG_RTC_DRV_IMXDI is not set -# CONFIG_RTC_DRV_MXC is not set -# CONFIG_RTC_DRV_MXC_V2 is not set -CONFIG_RTC_DRV_PCF2127=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCHED_DEBUG=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -CONFIG_SECCOMP=y -CONFIG_SECCOMP_FILTER=y -# CONFIG_SECURITY_DMESG_RESTRICT is not set -CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y -CONFIG_SERIAL_8250_DW=y -CONFIG_SERIAL_8250_DWLIB=y -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_PCILIB=y -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -CONFIG_SERIAL_CONEXANT_DIGICOLOR=y -CONFIG_SERIAL_CONEXANT_DIGICOLOR_CONSOLE=y -CONFIG_SERIAL_FSL_LPUART=y -CONFIG_SERIAL_FSL_LPUART_CONSOLE=y -CONFIG_SERIAL_IMX=y -CONFIG_SERIAL_IMX_CONSOLE=y -CONFIG_SERIAL_IMX_EARLYCON=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SERIAL_ST_ASC=y -CONFIG_SERIAL_ST_ASC_CONSOLE=y -CONFIG_SERIAL_XILINX_PS_UART=y -CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_SMSC_PHY=y -CONFIG_SOCK_DIAG=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BUS=y -# CONFIG_SOC_IMX50 is not set -# CONFIG_SOC_IMX51 is not set -# CONFIG_SOC_IMX53 is not set -# CONFIG_SOC_IMX6Q is not set -# CONFIG_SOC_IMX6SL is not set -# CONFIG_SOC_IMX6SLL is not set -# CONFIG_SOC_IMX6SX is not set -# CONFIG_SOC_IMX6UL is not set -# CONFIG_SOC_IMX7D is not set -# CONFIG_SOC_IMX7ULP is not set -# CONFIG_SOC_IMX8M is not set -# CONFIG_SOC_IMX9 is not set -CONFIG_SOC_LS1021A=y -# CONFIG_SOC_VF610 is not set -CONFIG_SOFTIRQ_ON_OWN_STACK=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_BITBANG=y -CONFIG_SPI_CADENCE=y -CONFIG_SPI_DYNAMIC=y -# CONFIG_SPI_FSL_LPSPI is not set -# CONFIG_SPI_FSL_QUADSPI is not set -# CONFIG_SPI_IMX is not set -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_SPIDEV=y -CONFIG_SPI_XILINX=y -CONFIG_SPLIT_PTE_PTLOCKS=y -CONFIG_SPMI=y -# CONFIG_SPMI_HISI3670 is not set -CONFIG_SQUASHFS_FILE_CACHE=y -# CONFIG_SQUASHFS_FILE_DIRECT is not set -CONFIG_SQUASHFS_LZO=y -CONFIG_SQUASHFS_ZLIB=y -CONFIG_SRAM=y -CONFIG_SRAM_EXEC=y -CONFIG_STACKTRACE=y -# CONFIG_STRIP_ASM_SYMS is not set -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_SWIOTLB=y -CONFIG_SWPHY=y -CONFIG_SWP_EMULATE=y -CONFIG_SYNC_FILE=y -CONFIG_SYSFS_SYSCALL=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_OF=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -# CONFIG_UCLAMP_TASK is not set -CONFIG_UEVENT_HELPER_PATH="" -CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -CONFIG_UNIX_DIAG=y -CONFIG_UNWINDER_ARM=y -CONFIG_USB_SUPPORT=y -CONFIG_USER_NS=y -CONFIG_USE_OF=y -CONFIG_UTS_NS=y -CONFIG_VEXPRESS_CONFIG=y -CONFIG_VFAT_FS=y -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_VIRTIO=y -CONFIG_VIRTIO_ANCHOR=y -CONFIG_VIRTIO_BLK=y -CONFIG_VIRTIO_CONSOLE=y -# CONFIG_VIRTIO_DEBUG is not set -CONFIG_VIRTIO_MMIO=y -CONFIG_VIRTIO_NET=y -CONFIG_VIRTIO_PCI=y -CONFIG_VIRTIO_PCI_LEGACY=y -CONFIG_VIRTIO_PCI_LIB=y -CONFIG_VIRTIO_PCI_LIB_LEGACY=y -CONFIG_VITESSE_PHY=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_VT_CONSOLE_SLEEP=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_WATCHDOG_CORE=y -# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set -CONFIG_XILINX_WATCHDOG=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_ARMTHUMB=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_XZ_DEC_POWERPC=y -CONFIG_XZ_DEC_SPARC=y -CONFIG_XZ_DEC_X86=y -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_ZBOOT_ROM_TEXT=0 -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/layerscape/armv8_64b/config-6.12 b/target/linux/layerscape/armv8_64b/config-6.12 deleted file mode 100644 index d2b0907534..0000000000 --- a/target/linux/layerscape/armv8_64b/config-6.12 +++ /dev/null @@ -1,887 +0,0 @@ -CONFIG_64BIT=y -CONFIG_AQUANTIA_PHY=y -CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y -CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y -CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -CONFIG_ARCH_FORCE_MAX_ORDER=10 -CONFIG_ARCH_HIBERNATION_HEADER=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_LAYERSCAPE=y -CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y -CONFIG_ARCH_MMAP_RND_BITS=18 -CONFIG_ARCH_MMAP_RND_BITS_MAX=33 -CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 -CONFIG_ARCH_NXP=y -CONFIG_ARCH_PKEY_BITS=3 -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANTS_EXECMEM_LATE=y -CONFIG_ARCH_WANTS_NO_INSTR=y -CONFIG_ARCH_WANTS_THP_SWAP=y -CONFIG_ARM64=y -CONFIG_ARM64_4K_PAGES=y -CONFIG_ARM64_ERRATUM_1165522=y -CONFIG_ARM64_ERRATUM_1286807=y -CONFIG_ARM64_ERRATUM_2051678=y -CONFIG_ARM64_ERRATUM_2054223=y -CONFIG_ARM64_ERRATUM_2067961=y -CONFIG_ARM64_ERRATUM_2077057=y -CONFIG_ARM64_ERRATUM_2658417=y -CONFIG_ARM64_ERRATUM_819472=y -CONFIG_ARM64_ERRATUM_824069=y -CONFIG_ARM64_ERRATUM_826319=y -CONFIG_ARM64_ERRATUM_827319=y -CONFIG_ARM64_ERRATUM_832075=y -CONFIG_ARM64_ERRATUM_843419=y -CONFIG_ARM64_HW_AFDBM=y -CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_PA_BITS=48 -CONFIG_ARM64_PA_BITS_48=y -CONFIG_ARM64_PLATFORM_DEVICES=y -CONFIG_ARM64_PTR_AUTH=y -CONFIG_ARM64_PTR_AUTH_KERNEL=y -CONFIG_ARM64_SVE=y -CONFIG_ARM64_TAGGED_ADDR_ABI=y -CONFIG_ARM64_VA_BITS=48 -# CONFIG_ARM64_VA_BITS_39 is not set -CONFIG_ARM64_VA_BITS_48=y -CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y -CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y -CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y -CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y -CONFIG_ARM_GIC=y -CONFIG_ARM_GIC_V2M=y -CONFIG_ARM_GIC_V3=y -CONFIG_ARM_GIC_V3_ITS=y -CONFIG_ARM_GIC_V3_ITS_FSL_MC=y -# CONFIG_ARM_PL172_MPMC is not set -CONFIG_ARM_PSCI_CPUIDLE=y -CONFIG_ARM_PSCI_FW=y -CONFIG_ARM_SMMU=y -# CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT is not set -# CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS is not set -CONFIG_ARM_SMMU_V3=y -# CONFIG_ARM_SMMU_V3_SVA is not set -CONFIG_ARM_SP805_WATCHDOG=y -CONFIG_ASM_MODVERSIONS=y -CONFIG_ASN1=y -CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y -CONFIG_ATA=y -CONFIG_AUDIT=y -CONFIG_AUDITSYSCALL=y -CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_AUDIT_GENERIC=y -CONFIG_AUTOFS_FS=y -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BALLOON_COMPACTION=y -CONFIG_BATTERY_BQ27XXX=y -# CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM is not set -CONFIG_BATTERY_BQ27XXX_I2C=y -CONFIG_BLK_DEV_BSG=y -CONFIG_BLK_DEV_BSGLIB=y -CONFIG_BLK_DEV_BSG_COMMON=y -CONFIG_BLK_DEV_INTEGRITY=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=262144 -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BLK_MQ_VIRTIO=y -CONFIG_BLK_PM=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_BUFFER_HEAD=y -CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y -CONFIG_CAVIUM_ERRATUM_22375=y -CONFIG_CAVIUM_ERRATUM_23144=y -CONFIG_CAVIUM_ERRATUM_23154=y -CONFIG_CAVIUM_ERRATUM_27456=y -CONFIG_CC_HAVE_SHADOW_CALL_STACK=y -CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y -CONFIG_CHECKPOINT_RESTORE=y -CONFIG_CHROME_PLATFORMS=y -CONFIG_CLK_LS1028A_PLLDIG=y -CONFIG_CLK_QORIQ=y -# CONFIG_CLK_VEXPRESS_OSC is not set -CONFIG_CLONE_BACKWARDS=y -CONFIG_CLZ_TAB=y -CONFIG_CMA=y -CONFIG_CMA_ALIGNMENT=8 -CONFIG_CMA_AREAS=7 -# CONFIG_CMA_DEBUGFS is not set -CONFIG_CMA_SIZE_MBYTES=16 -# CONFIG_CMA_SIZE_SEL_MAX is not set -CONFIG_CMA_SIZE_SEL_MBYTES=y -# CONFIG_CMA_SIZE_SEL_MIN is not set -# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set -# CONFIG_CMA_SYSFS is not set -CONFIG_COMMON_CLK=y -CONFIG_COMMON_CLK_CS2000_CP=y -CONFIG_COMMON_CLK_FSL_FLEXSPI=y -# CONFIG_COMMON_CLK_FSL_SAI is not set -CONFIG_COMMON_CLK_XGENE=y -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -CONFIG_COMPAT_32BIT_TIME=y -CONFIG_CONFIGFS_FS=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_CONTEXT_TRACKING=y -CONFIG_CONTEXT_TRACKING_IDLE=y -CONFIG_CONTIG_ALLOC=y -CONFIG_COREDUMP=y -CONFIG_CPUFREQ_DT=y -CONFIG_CPUFREQ_DT_PLATDEV=y -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_THERMAL=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MITIGATIONS=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_THERMAL=y -CONFIG_CRC16=y -CONFIG_CRC64=y -CONFIG_CRC64_ROCKSOFT=y -CONFIG_CRC7=y -CONFIG_CRC_CCITT=y -CONFIG_CRC_ITU_T=y -CONFIG_CRC_T10DIF=y -CONFIG_CROSS_MEMORY_ATTACH=y -# CONFIG_CROS_EC is not set -CONFIG_CRYPTO_AES_ARM64=y -CONFIG_CRYPTO_AES_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_AUTHENC=y -CONFIG_CRYPTO_BLAKE2B=y -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CRC64_ROCKSOFT=y -CONFIG_CRYPTO_CRCT10DIF=y -CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y -CONFIG_CRYPTO_CRYPTD=y -CONFIG_CRYPTO_CURVE25519=y -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_DEV_FSL_CAAM=y -CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=y -CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC=y -CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON=y -CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y -CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC=y -CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI=y -CONFIG_CRYPTO_DEV_FSL_CAAM_JR=y -CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API=y -CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API=y -CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9 -CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y -CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_ENGINE=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_HASH_INFO=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=y -CONFIG_CRYPTO_LIB_CURVE25519_INTERNAL=y -CONFIG_CRYPTO_LIB_DES=y -CONFIG_CRYPTO_LIB_GF128MUL=y -CONFIG_CRYPTO_LIB_SHA1=y -CONFIG_CRYPTO_LIB_SHA256=y -CONFIG_CRYPTO_LIB_UTILS=y -CONFIG_CRYPTO_LZO=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RSA=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA256_ARM64=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_XTS=y -CONFIG_CRYPTO_XXHASH=y -CONFIG_CRYPTO_ZSTD=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_MEMORY_INIT=y -CONFIG_DECOMPRESS_BZIP2=y -CONFIG_DECOMPRESS_GZIP=y -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DECOMPRESS_LZO=y -CONFIG_DECOMPRESS_XZ=y -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DMADEVICES=y -CONFIG_DMATEST=y -CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y -CONFIG_DMA_CMA=y -CONFIG_DMA_DIRECT_REMAP=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_ENGINE_RAID=y -CONFIG_DMA_NEED_SYNC=y -# CONFIG_DMA_NUMA_CMA is not set -CONFIG_DMA_OF=y -CONFIG_DMA_OPS_HELPERS=y -CONFIG_DMA_SHARED_BUFFER=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DNOTIFY=y -CONFIG_DPAA2_CONSOLE=y -CONFIG_DPAA_ERRATUM_A050385=y -CONFIG_DTC=y -CONFIG_DT_IDLE_STATES=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EEPROM_AT24=y -CONFIG_ELF_CORE=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -CONFIG_EXT4_FS=y -CONFIG_EXTCON=y -CONFIG_EXTCON_USB_GPIO=y -CONFIG_F2FS_FS=y -CONFIG_FAILOVER=y -CONFIG_FANOTIFY=y -CONFIG_FAT_FS=y -CONFIG_FB=y -CONFIG_FB_CORE=y -CONFIG_FB_DEFERRED_IO=y -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_SYSMEM_FOPS=y -CONFIG_FB_SYSMEM_HELPERS=y -CONFIG_FB_SYSMEM_HELPERS_DEFERRED=y -CONFIG_FB_SYS_COPYAREA=y -CONFIG_FB_SYS_FILLRECT=y -CONFIG_FB_SYS_IMAGEBLIT=y -CONFIG_FHANDLE=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FONT_8x16=y -CONFIG_FONT_8x8=y -CONFIG_FONT_SUPPORT=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FRAME_POINTER=y -CONFIG_FREEZER=y -# CONFIG_FSL_BMAN_TEST is not set -CONFIG_FSL_DPAA=y -CONFIG_FSL_DPAA2_ETH=y -CONFIG_FSL_DPAA2_PTP_CLOCK=y -# CONFIG_FSL_DPAA2_QDMA is not set -# CONFIG_FSL_DPAA_CHECKING is not set -CONFIG_FSL_DPAA_ETH=y -CONFIG_FSL_EDMA=y -CONFIG_FSL_ENETC=y -CONFIG_FSL_ENETC_CORE=y -CONFIG_FSL_ENETC_IERB=y -CONFIG_FSL_ENETC_MDIO=y -CONFIG_FSL_ENETC_PTP_CLOCK=y -CONFIG_FSL_ENETC_VF=y -CONFIG_FSL_ERRATUM_A008585=y -CONFIG_FSL_FMAN=y -CONFIG_FSL_GUTS=y -CONFIG_FSL_IFC=y -CONFIG_FSL_MC_BUS=y -CONFIG_FSL_MC_DPIO=y -CONFIG_FSL_MC_UAPI_SUPPORT=y -# CONFIG_FSL_PPFE is not set -# CONFIG_FSL_QMAN_TEST is not set -CONFIG_FSL_RCPM=y -CONFIG_FSL_XGMAC_MDIO=y -CONFIG_FS_IOMAP=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y -CONFIG_FUNCTION_ALIGNMENT=4 -CONFIG_FUNCTION_ALIGNMENT_4B=y -CONFIG_FUSE_FS=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_CACHE=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set -CONFIG_GARP=y -CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ARCH_NUMA=y -CONFIG_GENERIC_ARCH_TOPOLOGY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_DEVICES=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_CSUM=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IOREMAP=y -CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -CONFIG_GENERIC_IRQ_MIGRATION=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y -CONFIG_GENERIC_MSI_IRQ=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_PHY=y -CONFIG_GENERIC_SCHED_CLOCK=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -# CONFIG_GIANFAR is not set -CONFIG_GLOB=y -CONFIG_GPIOLIB_IRQCHIP=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_GENERIC_PLATFORM=y -CONFIG_GPIO_MPC8XXX=y -CONFIG_GPIO_PCA953X=y -CONFIG_GPIO_PCA953X_IRQ=y -CONFIG_GRO_CELLS=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HIBERNATE_CALLBACKS=y -CONFIG_HIBERNATION=y -CONFIG_HIBERNATION_COMP_LZO=y -CONFIG_HIBERNATION_DEF_COMP="lzo" -CONFIG_HIBERNATION_SNAPSHOT_DEV=y -CONFIG_HOTPLUG_CORE_SYNC=y -CONFIG_HOTPLUG_CORE_SYNC_DEAD=y -CONFIG_HOTPLUG_CPU=y -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING=y -CONFIG_HVC_DRIVER=y -CONFIG_HVC_IRQ=y -CONFIG_HVC_XEN=y -CONFIG_HVC_XEN_FRONTEND=y -CONFIG_HW_RANDOM=y -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_DESIGNWARE_CORE=y -CONFIG_I2C_DESIGNWARE_PLATFORM=y -CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_IMX=y -CONFIG_I2C_MUX=y -CONFIG_I2C_MUX_PCA954x=y -CONFIG_I2C_RK3X=y -CONFIG_I2C_SLAVE=y -# CONFIG_I2C_SLAVE_TESTUNIT is not set -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_IMX2_WDT=y -CONFIG_INET_DIAG=y -# CONFIG_INET_DIAG_DESTROY is not set -# CONFIG_INET_RAW_DIAG is not set -CONFIG_INET_TCP_DIAG=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INPUT=y -CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_FF_MEMLESS=y -CONFIG_INPUT_KEYBOARD=y -CONFIG_INPUT_MOUSE=y -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_VIVALDIFMAP=y -CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y -CONFIG_INTERVAL_TREE=y -# CONFIG_IOMMUFD is not set -CONFIG_IOMMU_API=y -# CONFIG_IOMMU_DEBUGFS is not set -# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set -# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set -CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y -CONFIG_IOMMU_DMA=y -CONFIG_IOMMU_IOVA=y -CONFIG_IOMMU_IO_PGTABLE=y -# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set -# CONFIG_IOMMU_IO_PGTABLE_DART is not set -CONFIG_IOMMU_IO_PGTABLE_LPAE=y -# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set -CONFIG_IOMMU_SUPPORT=y -CONFIG_IPC_NS=y -CONFIG_IRQCHIP=y -CONFIG_IRQ_BYPASS_MANAGER=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_MSI_IOMMU=y -CONFIG_IRQ_MSI_LIB=y -CONFIG_IRQ_WORK=y -# CONFIG_ISDN is not set -CONFIG_JBD2=y -CONFIG_JUMP_LABEL=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -CONFIG_KCMP=y -CONFIG_KEXEC=y -CONFIG_KEXEC_CORE=y -CONFIG_KEYBOARD_ATKBD=y -CONFIG_KEYBOARD_GPIO=y -CONFIG_KSM=y -CONFIG_LEGACY_DIRECT_IO=y -CONFIG_LIBCRC32C=y -CONFIG_LIBFDT=y -CONFIG_LOCALVERSION_AUTO=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_CLUT224=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_LRU_GEN_WALKS_MMU=y -CONFIG_LS_EXTIRQ=y -CONFIG_LS_SCFG_MSI=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_MDIO_BITBANG=y -CONFIG_MDIO_BUS=y -CONFIG_MDIO_BUS_MUX=y -CONFIG_MDIO_BUS_MUX_MMIOREG=y -CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -# CONFIG_MDIO_GPIO is not set -CONFIG_MEMORY=y -CONFIG_MEMORY_BALLOON=y -CONFIG_MEMORY_ISOLATION=y -CONFIG_MEMTEST=y -# CONFIG_MFD_HI6421_SPMI is not set -CONFIG_MFD_SYSCON=y -# CONFIG_MFD_VEXPRESS_SYSREG is not set -CONFIG_MICREL_PHY=y -CONFIG_MICROSEMI_PHY=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_BLOCK_MINORS=32 -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_IO_ACCESSORS=y -CONFIG_MMC_SDHCI_OF_ESDHC=y -CONFIG_MMC_SDHCI_PLTFM=y -CONFIG_MMU_LAZY_TLB_REFCOUNT=y -CONFIG_MMU_NOTIFIER=y -CONFIG_MODULES_USE_ELF_RELA=y -CONFIG_MODULE_FORCE_LOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_BYD=y -CONFIG_MOUSE_PS2_CYPRESS=y -# CONFIG_MOUSE_PS2_ELANTECH is not set -CONFIG_MOUSE_PS2_FOCALTECH=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SMBUS=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -CONFIG_MOUSE_PS2_TRACKPOINT=y -CONFIG_MPILIB=y -CONFIG_MRP=y -CONFIG_MSCC_OCELOT_SWITCH_LIB=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -# CONFIG_MTD_CFI_GEOMETRY is not set -CONFIG_MTD_CFI_STAA=y -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_DATAFLASH=y -# CONFIG_MTD_DATAFLASH_OTP is not set -# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_NAND_FSL_IFC=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NAND=y -CONFIG_MTD_SPI_NOR=y -CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y -CONFIG_MTD_SPLIT_FIRMWARE=y -CONFIG_MTD_SPLIT_FIT_FW=y -CONFIG_MTD_SST25L=y -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_BEB_LIMIT=20 -CONFIG_MTD_UBI_BLOCK=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MULTIPLEXER=y -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_MUX_MMIO=y -CONFIG_MV_XOR_V2=y -CONFIG_NAMESPACES=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y -CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y -CONFIG_NEED_SG_DMA_FLAGS=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NET_DEVLINK=y -CONFIG_NET_DEVMEM=y -CONFIG_NET_DSA=y -CONFIG_NET_DSA_MSCC_FELIX=y -CONFIG_NET_DSA_MSCC_FELIX_DSA_LIB=y -CONFIG_NET_DSA_TAG_OCELOT=y -CONFIG_NET_DSA_TAG_OCELOT_8021Q=y -CONFIG_NET_EGRESS=y -CONFIG_NET_FAILOVER=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_INGRESS=y -CONFIG_NET_NS=y -CONFIG_NET_PTP_CLASSIFY=y -CONFIG_NET_SELFTESTS=y -CONFIG_NET_XGRESS=y -CONFIG_NLS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NODES_SHIFT=2 -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=64 -# CONFIG_NSM is not set -CONFIG_NUMA=y -CONFIG_NUMA_BALANCING=y -CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y -# CONFIG_NUMA_EMU is not set -CONFIG_NUMA_MEMBLKS=y -CONFIG_NVMEM=y -CONFIG_NVMEM_LAYERSCAPE_SFP=y -CONFIG_NVMEM_LAYOUTS=y -# CONFIG_NVMEM_SPMI_SDAM is not set -CONFIG_NVMEM_SYSFS=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IOMMU=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OF_NUMA=y -CONFIG_PACKET_DIAG=y -CONFIG_PACKING=y -CONFIG_PADATA=y -CONFIG_PAGE_POOL=y -CONFIG_PAGE_REPORTING=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -# CONFIG_PANIC_ON_OOPS is not set -CONFIG_PANIC_ON_OOPS_VALUE=0 -CONFIG_PANIC_TIMEOUT=0 -CONFIG_PARAVIRT=y -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_PARTITION_PERCPU=y -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEASPM=y -CONFIG_PCIEASPM_DEFAULT=y -# CONFIG_PCIEASPM_PERFORMANCE is not set -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -CONFIG_PCIEPORTBUS=y -CONFIG_PCIE_DW=y -CONFIG_PCIE_DW_HOST=y -CONFIG_PCIE_LAYERSCAPE_GEN4=y -CONFIG_PCIE_MOBIVEIL=y -CONFIG_PCIE_MOBIVEIL_HOST=y -CONFIG_PCIE_PME=y -CONFIG_PCI_ATS=y -CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DOMAINS_GENERIC=y -CONFIG_PCI_ECAM=y -CONFIG_PCI_HISI=y -CONFIG_PCI_HOST_COMMON=y -CONFIG_PCI_HOST_GENERIC=y -CONFIG_PCI_IOV=y -CONFIG_PCI_LAYERSCAPE=y -CONFIG_PCI_MSI=y -CONFIG_PCS_LYNX=y -CONFIG_PER_VMA_LOCK=y -CONFIG_PGTABLE_HAS_HUGE_LEAVES=y -CONFIG_PGTABLE_LEVELS=4 -CONFIG_PHYLIB=y -CONFIG_PHYLIB_LEDS=y -CONFIG_PHYLINK=y -CONFIG_PHYS_ADDR_T_64BIT=y -# CONFIG_PHY_FSL_LYNX_28G is not set -CONFIG_PID_IN_CONTEXTIDR=y -CONFIG_PID_NS=y -CONFIG_PL330_DMA=y -CONFIG_PM=y -CONFIG_PM_CLK=y -CONFIG_PM_OPP=y -CONFIG_PM_SLEEP=y -CONFIG_PM_SLEEP_SMP=y -CONFIG_PM_STD_PARTITION="" -CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_SYSCON=y -CONFIG_POWER_RESET_VEXPRESS=y -CONFIG_POWER_RESET_XGENE=y -CONFIG_POWER_SUPPLY=y -CONFIG_PPS=y -CONFIG_PRINTK_TIME=y -CONFIG_PROC_CHILDREN=y -CONFIG_PROFILING=y -CONFIG_PTP_1588_CLOCK=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_PTP_1588_CLOCK_QORIQ=y -CONFIG_QCOM_HIDMA=y -CONFIG_QCOM_HIDMA_MGMT=y -CONFIG_QCOM_QDF2400_ERRATUM_0065=y -# CONFIG_QFMT_V2 is not set -CONFIG_QORIQ_CPUFREQ=y -CONFIG_QORIQ_THERMAL=y -CONFIG_QUEUED_RWLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_QUOTA=y -CONFIG_QUOTACTL=y -# CONFIG_RANDOMIZE_KSTACK_OFFSET is not set -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -CONFIG_RATIONAL=y -CONFIG_RD_BZIP2=y -CONFIG_RD_GZIP=y -CONFIG_RD_LZMA=y -CONFIG_RD_LZO=y -CONFIG_RD_XZ=y -CONFIG_REALTEK_PHY=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGMAP_SPI=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RFS_ACCEL=y -CONFIG_RODATA_FULL_DEFAULT_ENABLED=y -CONFIG_RPS=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_DS1307=y -CONFIG_RTC_DRV_DS3232=y -CONFIG_RTC_DRV_FSL_FTM_ALARM=y -CONFIG_RTC_DRV_PCF2127=y -CONFIG_RTC_DRV_PL031=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_SCHED_HW_PRESSURE=y -CONFIG_SCHED_INFO=y -CONFIG_SCHED_MC=y -CONFIG_SCSI=y -CONFIG_SCSI_COMMON=y -# CONFIG_SCSI_PROC_FS is not set -# CONFIG_SCSI_SAS_ATA is not set -CONFIG_SCSI_SAS_ATTRS=y -CONFIG_SCSI_SAS_HOST_SMP=y -CONFIG_SCSI_SAS_LIBSAS=y -CONFIG_SECCOMP=y -CONFIG_SECCOMP_FILTER=y -CONFIG_SECRETMEM=y -CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y -CONFIG_SERIAL_8250_DW=y -CONFIG_SERIAL_8250_DWLIB=y -CONFIG_SERIAL_8250_EXTENDED=y -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_PCILIB=y -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -CONFIG_SERIAL_8250_SHARE_IRQ=y -CONFIG_SERIAL_AMBA_PL011=y -CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -CONFIG_SERIAL_FSL_LPUART=y -CONFIG_SERIAL_FSL_LPUART_CONSOLE=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SERIAL_SC16IS7XX=y -CONFIG_SERIAL_SC16IS7XX_I2C=y -CONFIG_SERIAL_SC16IS7XX_SPI=y -CONFIG_SERIAL_XILINX_PS_UART=y -CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y -CONFIG_SERIO=y -CONFIG_SERIO_AMBAKMI=y -CONFIG_SERIO_LIBPS2=y -CONFIG_SGL_ALLOC=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -CONFIG_SOCK_DIAG=y -CONFIG_SOCK_RX_QUEUE_MAPPING=y -CONFIG_SOC_BUS=y -CONFIG_SOFTIRQ_ON_OWN_STACK=y -CONFIG_SPARSEMEM=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_FSL_DSPI=y -CONFIG_SPI_FSL_QUADSPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SPI_NXP_FLEXSPI=y -CONFIG_SPI_PL022=y -CONFIG_SPLIT_PMD_PTLOCKS=y -CONFIG_SPLIT_PTE_PTLOCKS=y -CONFIG_SPMI=y -# CONFIG_SPMI_HISI3670 is not set -CONFIG_SQUASHFS_FILE_CACHE=y -# CONFIG_SQUASHFS_FILE_DIRECT is not set -# CONFIG_SQUASHFS_XZ is not set -CONFIG_SQUASHFS_ZLIB=y -CONFIG_SRAM=y -# CONFIG_STRIP_ASM_SYMS is not set -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_SWIOTLB=y -CONFIG_SWIOTLB_XEN=y -CONFIG_SWPHY=y -CONFIG_SYNC_FILE=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_SYSFS_SYSCALL=y -CONFIG_SYS_HYPERVISOR=y -CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y -CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_TASK_XACCT=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 -CONFIG_THERMAL_EMULATION=y -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_OF=y -CONFIG_THP_SWAP=y -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TIMER_OF=y -CONFIG_TIMER_PROBE=y -CONFIG_TOOLS_SUPPORT_RELR=y -CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y -CONFIG_TRANSPARENT_HUGEPAGE=y -CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y -# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set -# CONFIG_TRANSPARENT_HUGEPAGE_NEVER is not set -CONFIG_TRANS_TABLE=y -CONFIG_TREE_RCU=y -CONFIG_TREE_SRCU=y -CONFIG_UBIFS_FS=y -# CONFIG_UCLAMP_TASK is not set -CONFIG_UIO=y -CONFIG_UIO_AEC=y -CONFIG_UIO_CIF=y -CONFIG_UIO_DMEM_GENIRQ=y -CONFIG_UIO_MF624=y -CONFIG_UIO_NETX=y -CONFIG_UIO_PCI_GENERIC=y -CONFIG_UIO_PDRV_GENIRQ=y -CONFIG_UIO_SERCOS3=y -CONFIG_UNIX_DIAG=y -CONFIG_UNMAP_KERNEL_AT_EL0=y -CONFIG_USB_SUPPORT=y -CONFIG_USER_NS=y -CONFIG_USER_STACKTRACE_SUPPORT=y -CONFIG_USE_PERCPU_NUMA_NODE_ID=y -CONFIG_UTS_NS=y -CONFIG_VDSO_GETRANDOM=y -CONFIG_VEXPRESS_CONFIG=y -CONFIG_VFAT_FS=y -CONFIG_VFIO=y -# CONFIG_VFIO_AMBA is not set -CONFIG_VFIO_CONTAINER=y -CONFIG_VFIO_FSL_MC=y -CONFIG_VFIO_GROUP=y -CONFIG_VFIO_IOMMU_TYPE1=y -# CONFIG_VFIO_NOIOMMU is not set -CONFIG_VFIO_PCI=y -CONFIG_VFIO_PCI_CORE=y -CONFIG_VFIO_PCI_INTX=y -CONFIG_VFIO_PCI_MMAP=y -CONFIG_VFIO_VIRQFD=y -CONFIG_VGA_ARB=y -CONFIG_VGA_ARB_MAX_GPUS=16 -CONFIG_VIDEO=y -CONFIG_VIRTIO=y -CONFIG_VIRTIO_ANCHOR=y -CONFIG_VIRTIO_BALLOON=y -CONFIG_VIRTIO_BLK=y -CONFIG_VIRTIO_CONSOLE=y -# CONFIG_VIRTIO_DEBUG is not set -# CONFIG_VIRTIO_IOMMU is not set -CONFIG_VIRTIO_MMIO=y -CONFIG_VIRTIO_NET=y -CONFIG_VIRTIO_PCI=y -CONFIG_VIRTIO_PCI_LEGACY=y -CONFIG_VIRTIO_PCI_LIB=y -CONFIG_VIRTIO_PCI_LIB_LEGACY=y -CONFIG_VITESSE_PHY=y -CONFIG_VLAN_8021Q_GVRP=y -CONFIG_VLAN_8021Q_MVRP=y -CONFIG_VMAP_STACK=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_VT_CONSOLE_SLEEP=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_WATCHDOG_CORE=y -# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set -CONFIG_XARRAY_MULTI=y -CONFIG_XEN=y -CONFIG_XENFS=y -CONFIG_XEN_AUTO_XLATE=y -CONFIG_XEN_BACKEND=y -CONFIG_XEN_BALLOON=y -# CONFIG_XEN_BLKDEV_BACKEND is not set -CONFIG_XEN_BLKDEV_FRONTEND=y -CONFIG_XEN_COMPAT_XENFS=y -CONFIG_XEN_DEV_EVTCHN=y -CONFIG_XEN_DOM0=y -CONFIG_XEN_FBDEV_FRONTEND=y -CONFIG_XEN_GNTDEV=y -CONFIG_XEN_GRANT_DEV_ALLOC=y -# CONFIG_XEN_NETDEV_BACKEND is not set -CONFIG_XEN_NETDEV_FRONTEND=y -# CONFIG_XEN_PCIDEV_STUB is not set -CONFIG_XEN_PRIVCMD=y -# CONFIG_XEN_PVCALLS_BACKEND is not set -# CONFIG_XEN_SCSI_FRONTEND is not set -CONFIG_XEN_SYS_HYPERVISOR=y -# CONFIG_XEN_VIRTIO is not set -# CONFIG_XEN_WDT is not set -CONFIG_XEN_XENBUS_FRONTEND=y -CONFIG_XFS_FS=y -CONFIG_XFS_RT=y -CONFIG_XPS=y -CONFIG_XXHASH=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_ARMTHUMB=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_XZ_DEC_POWERPC=y -CONFIG_XZ_DEC_SPARC=y -CONFIG_XZ_DEC_X86=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZONE_DMA32=y -CONFIG_ZSTD_COMMON=y -CONFIG_ZSTD_COMPRESS=y -CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch b/target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch deleted file mode 100644 index bd69aa042d..0000000000 --- a/target/linux/layerscape/patches-6.12/302-arm64-dts-ls1012a-update-with-ppfe-support.patch +++ /dev/null @@ -1,228 +0,0 @@ -From 008465a02bf29b366ca7a56dba48ad3a85417ba2 Mon Sep 17 00:00:00 2001 -From: Li Yang -Date: Thu, 18 Nov 2021 21:46:21 -0600 -Subject: [PATCH] arm64: dts: ls1012a: add ppfe support to boards - -Update ls1012a dtsi and platform dts files with -support for ppfe. - -Signed-off-by: Calvin Johnson -Signed-off-by: Anjaneyulu Jagarlmudi -Signed-off-by: Li Yang ---- - .../boot/dts/freescale/fsl-ls1012a-frdm.dts | 44 +++++++++++++++++++ - .../boot/dts/freescale/fsl-ls1012a-qds.dts | 43 ++++++++++++++++++ - .../boot/dts/freescale/fsl-ls1012a-rdb.dts | 40 +++++++++++++++++ - .../arm64/boot/dts/freescale/fsl-ls1012a.dtsi | 29 ++++++++++++ - 4 files changed, 156 insertions(+) - ---- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts -@@ -14,6 +14,11 @@ - model = "LS1012A Freedom Board"; - compatible = "fsl,ls1012a-frdm", "fsl,ls1012a"; - -+ aliases { -+ ethernet0 = &pfe_mac0; -+ ethernet1 = &pfe_mac1; -+ }; -+ - sys_mclk: clock-mclk { - compatible = "fixed-clock"; - #clock-cells = <0>; -@@ -110,6 +115,45 @@ - }; - }; - -+&pfe { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pfe_mac0: ethernet@0 { -+ compatible = "fsl,pfe-gemac-port"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x0>; /* GEM_ID */ -+ fsl,mdio-mux-val = <0x0>; -+ phy-mode = "sgmii"; -+ phy-handle = <&sgmii_phy1>; -+ }; -+ -+ pfe_mac1: ethernet@1 { -+ compatible = "fsl,pfe-gemac-port"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x1>; /* GEM_ID */ -+ fsl,mdio-mux-val = <0x0>; -+ phy-mode = "sgmii"; -+ phy-handle = <&sgmii_phy2>; -+ }; -+ -+ mdio@0 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ sgmii_phy1: ethernet-phy@2 { -+ reg = <0x2>; -+ }; -+ -+ sgmii_phy2: ethernet-phy@1 { -+ reg = <0x1>; -+ }; -+ }; -+}; -+ - &sai2 { - status = "okay"; - }; ---- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts -@@ -16,6 +16,8 @@ - aliases { - mmc0 = &esdhc0; - mmc1 = &esdhc1; -+ ethernet0 = &pfe_mac0; -+ ethernet1 = &pfe_mac1; - }; - - sys_mclk: clock-mclk { -@@ -148,6 +150,47 @@ - }; - }; - -+&pfe { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pfe_mac0: ethernet@0 { -+ compatible = "fsl,pfe-gemac-port"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x0>; /* GEM_ID */ -+ fsl,mdio-mux-val = <0x2>; -+ phy-mode = "sgmii-2500"; -+ phy-handle = <&sgmii_phy1>; -+ }; -+ -+ pfe_mac1: ethernet@1 { -+ compatible = "fsl,pfe-gemac-port"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x1>; /* GEM_ID */ -+ fsl,mdio-mux-val = <0x3>; -+ phy-mode = "sgmii-2500"; -+ phy-handle = <&sgmii_phy2>; -+ }; -+ -+ mdio@0 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ sgmii_phy1: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c45"; -+ reg = <0x1>; -+ }; -+ -+ sgmii_phy2: ethernet-phy@2 { -+ compatible = "ethernet-phy-ieee802.3-c45"; -+ reg = <0x2>; -+ }; -+ }; -+}; -+ - &sai2 { - status = "okay"; - }; ---- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts -@@ -18,6 +18,8 @@ - serial0 = &duart0; - mmc0 = &esdhc0; - mmc1 = &esdhc1; -+ ethernet0 = &pfe_mac0; -+ ethernet1 = &pfe_mac1; - }; - }; - -@@ -104,3 +106,41 @@ - &sata { - status = "okay"; - }; -+ -+&pfe { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pfe_mac0: ethernet@0 { -+ compatible = "fsl,pfe-gemac-port"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x0>; /* GEM_ID */ -+ fsl,mdio-mux-val = <0x0>; -+ phy-mode = "sgmii"; -+ phy-handle = <&sgmii_phy>; -+ }; -+ -+ pfe_mac1: ethernet@1 { -+ compatible = "fsl,pfe-gemac-port"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x1>; /* GEM_ID */ -+ fsl,mdio-mux-val = <0x0>; -+ phy-mode = "rgmii-id"; -+ phy-handle = <&rgmii_phy>; -+ }; -+ mdio@0 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ sgmii_phy: ethernet-phy@2 { -+ reg = <0x2>; -+ }; -+ -+ rgmii_phy: ethernet-phy@1 { -+ reg = <0x1>; -+ }; -+ }; -+}; ---- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi -@@ -568,6 +568,35 @@ - }; - }; - -+ reserved-memory { -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ -+ pfe_reserved: packetbuffer@83400000 { -+ reg = <0 0x83400000 0 0xc00000>; -+ }; -+ }; -+ -+ pfe: pfe@4000000 { -+ compatible = "fsl,pfe"; -+ reg = <0x0 0x04000000 0x0 0xc00000>, /* AXI 16M */ -+ <0x0 0x83400000 0x0 0xc00000>; /* PFE DDR 12M */ -+ reg-names = "pfe", "pfe-ddr"; -+ fsl,pfe-num-interfaces = <0x2>; -+ interrupts = <0 172 0x4>, /* HIF interrupt */ -+ <0 173 0x4>, /*HIF_NOCPY interrupt */ -+ <0 174 0x4>; /* WoL interrupt */ -+ interrupt-names = "pfe_hif", "pfe_hif_nocpy", "pfe_wol"; -+ memory-region = <&pfe_reserved>; -+ fsl,pfe-scfg = <&scfg 0>; -+ fsl,rcpm-wakeup = <&rcpm 0xf0000020>; -+ clocks = <&clockgen 4 0>; -+ clock-names = "pfe"; -+ -+ status = "okay"; -+ }; -+ - firmware { - optee { - compatible = "linaro,optee-tz"; diff --git a/target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch b/target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch deleted file mode 100644 index f42859b7ac..0000000000 --- a/target/linux/layerscape/patches-6.12/303-arm64-dts-ls1012a-frdm-workaround-by-updating-qspi-f.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 9c5c18dbf8e1845d349ef7020f8af5bc9b56ed1f Mon Sep 17 00:00:00 2001 -From: Pawel Dembicki -Date: Fri, 28 Sep 2022 17:14:32 +0200 -Subject: [PATCH] arm64: dts: ls1012a-frdm/qds: workaround by updating qspi flash to - single mode - -Update rx and tx bus-width to 1 to use single mode to workaround ubifs -issue found with double mode. (The same method as RDB board) - -Signed-off-by: Pawel Dembicki ---- - arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts | 4 ++-- - arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts | 4 ++-- - 2 file changed, 4 insertions(+), 4 deletions(-) - ---- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts -@@ -110,8 +110,8 @@ - spi-max-frequency = <50000000>; - m25p,fast-read; - reg = <0>; -- spi-rx-bus-width = <2>; -- spi-tx-bus-width = <2>; -+ spi-rx-bus-width = <1>; -+ spi-tx-bus-width = <1>; - }; - }; - ---- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts -@@ -145,8 +145,8 @@ - spi-max-frequency = <50000000>; - m25p,fast-read; - reg = <0>; -- spi-rx-bus-width = <2>; -- spi-tx-bus-width = <2>; -+ spi-rx-bus-width = <1>; -+ spi-tx-bus-width = <1>; - }; - }; - diff --git a/target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch b/target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch deleted file mode 100644 index fd1dff747b..0000000000 --- a/target/linux/layerscape/patches-6.12/304-arm64-dts-ls1012a-rdb-workaround-by-updating-qspi-fl.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 9c5c18dbf8e1845d349ef7020f8af5bc9b56ed1f Mon Sep 17 00:00:00 2001 -From: Kuldeep Singh -Date: Tue, 7 Jan 2020 17:14:32 +0530 -Subject: [PATCH] arm64: dts: ls1012a-rdb: workaround by updating qspi flash to - single mode - -Update rx and tx bus-width to 1 to use single mode to workaround ubifs -issue found with double mode. - -[ Leo: Local workaround ] - -Signed-off-by: Kuldeep Singh ---- - arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts -@@ -98,8 +98,8 @@ - spi-max-frequency = <50000000>; - m25p,fast-read; - reg = <0>; -- spi-rx-bus-width = <2>; -- spi-tx-bus-width = <2>; -+ spi-rx-bus-width = <1>; -+ spi-tx-bus-width = <1>; - }; - }; - diff --git a/target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch b/target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch deleted file mode 100644 index 9bc4e2b520..0000000000 --- a/target/linux/layerscape/patches-6.12/305-arm64-dts-ls1046a-rdb-Update-qspi-spi-rx-bus-width-t.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 38093ebbf25eb60a1aa863f46118a68a0300c56e Mon Sep 17 00:00:00 2001 -From: Kuldeep Singh -Date: Fri, 3 Jan 2020 14:49:07 +0530 -Subject: [PATCH] arm64: dts: ls1046a-rdb: Update qspi spi-rx-bus-width to 1 - -Update rx width from quad mode to single mode as a workaround. - -[Leo: Local workaround ] - -Signed-off-by: Kuldeep Singh ---- - arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts -@@ -104,7 +104,7 @@ - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; -- spi-rx-bus-width = <4>; -+ spi-rx-bus-width = <1>; - spi-tx-bus-width = <1>; - reg = <0>; - }; -@@ -114,7 +114,7 @@ - #address-cells = <1>; - #size-cells = <1>; - spi-max-frequency = <50000000>; -- spi-rx-bus-width = <4>; -+ spi-rx-bus-width = <1>; - spi-tx-bus-width = <1>; - reg = <1>; - }; diff --git a/target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch b/target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch deleted file mode 100644 index f9ea6a6e4e..0000000000 --- a/target/linux/layerscape/patches-6.12/400-LF-20-3-mtd-spi-nor-Use-1-bit-mode-of-spansion-s25fs.patch +++ /dev/null @@ -1,28 +0,0 @@ -From fa47ee1700323a0c3163c18941659692e5c22cff Mon Sep 17 00:00:00 2001 -From: Han Xu -Date: Tue, 23 Jan 2024 20:51:49 -0600 -Subject: [PATCH] LF-20-3 mtd: spi-nor: Use 1 bit mode of spansion(s25fs512s) - flash - -This is a workaround patch which uses only single bit mode of s25fs512s -flash - -Signed-off-by: Han Xu -Signed-off-by: Kuldeep Singh ---- - drivers/mtd/spi-nor/spansion.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/mtd/spi-nor/spansion.c -+++ b/drivers/mtd/spi-nor/spansion.c -@@ -859,9 +859,9 @@ static const struct flash_info spansion_ - .name = "s25fs512s", - .size = SZ_64M, - .sector_size = SZ_256K, -- .no_sfdp_flags = SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, - .mfr_flags = USE_CLSR, - .fixups = &s25fs_s_nor_fixups, -+ .fixup_flags = SPI_NOR_4B_OPCODES, - }, { - .id = SNOR_ID(0x01, 0x20, 0x18, 0x03, 0x00), - .name = "s25sl12800", diff --git a/target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch b/target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch deleted file mode 100644 index 279391531a..0000000000 --- a/target/linux/layerscape/patches-6.12/701-staging-add-fsl_ppfe-driver.patch +++ /dev/null @@ -1,11851 +0,0 @@ -From 81f5150aba929b222783a60a408b9a20a23bd171 Mon Sep 17 00:00:00 2001 -From: Calvin Johnson -Date: Sat, 16 Sep 2017 07:05:49 +0530 -Subject: [PATCH] staging: add fsl_ppfe driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is squash of all commits with ppfe driver taken from NXP 6.12 tree: -https://github.com/nxp-qoriq/linux/tree/lf-6.12.y - -net: fsl_ppfe: dts binding for ppfe - -Signed-off-by: Calvin Johnson -Signed-off-by: Anjaneyulu Jagarlmudi - -staging: fsl_ppfe/eth: header files for pfe driver - -This patch has all pfe header files. - -Signed-off-by: Calvin Johnson -Signed-off-by: Anjaneyulu Jagarlmudi - -staging: fsl_ppfe/eth: introduce pfe driver - - This patch introduces Linux support for NXP's LS1012A Packet -Forwarding Engine (pfe_eth). LS1012A uses hardware packet forwarding -engine to provide high performance Ethernet interfaces. The device -includes two Ethernet ports. - -Signed-off-by: Calvin Johnson -Signed-off-by: Anjaneyulu Jagarlmudi - -staging: fsl_ppfe/eth: fix RGMII tx delay issue - -Recently logic to enable RGMII tx delay was changed by -below patch. - -https://patchwork.kernel.org/patch/9447581/ - -Based on the patch, appropriate change is made in PFE driver. - -Signed-off-by: Calvin Johnson -Signed-off-by: Anjaneyulu Jagarlmudi - -staging: fsl_ppfe/eth: remove unused functions - -Remove unused functions hif_xmit_pkt & hif_lib_xmit_pkt. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: fix read/write/ack idx issue - -While fixing checkpatch errors some of the index increments -were commented out. They are enabled. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: Make phy_ethtool_ksettings_get return void - -Make return value void since function never return meaningful value - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: add function to update tmu credits - -__hif_lib_update_credit function is used to update the tmu credits. -If tx_qos is set, tmu credit is updated based on the number of packets -transmitted by tmu. - -Signed-off-by: Calvin Johnson -Signed-off-by: Anjaneyulu Jagarlmudi - -staging: fsl_ppfe/eth: Avoid packet drop at TMU queues - -Added flow control between TMU queues and PFE Linux driver, -based on TMU credits availability. -Added tx_qos module parameter to control this behavior. -Use queue-0 as default queue to transmit packets. - -Signed-off-by: Calvin Johnson -Signed-off-by: Akhila Kavi -Signed-off-by: Anjaneyulu Jagarlmudi - -staging: fsl_ppfe/eth: Enable PFE in clause 45 mode - -when we opearate in clause 45 mode, we need to call -the function get_phy_device() with its 3rd argument as -"true" and then the resultant phy device needs to be -register with phy layer via phy_device_register() - -Signed-off-by: Bhaskar Upadhaya - -staging: fsl_ppfe/eth: Disable autonegotiation for 2.5G SGMII - -PCS initialization sequence for 2.5G SGMII interface governs -auto negotiation to be in disabled mode - -Signed-off-by: Bhaskar Upadhaya - -staging: fsl_ppfe/eth: calculate PFE_PKT_SIZE with SKB_DATA_ALIGN - -pfe packet size was calculated without considering skb data alignment -and this resulted in jumbo frames crashing kernel when the -cacheline size increased from 64 to 128 bytes with -commit 97303480753e ("arm64: Increase the max granular size"). - -Modify pfe packet size caclulation to include skb data alignment of -sizeof(struct skb_shared_info). - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: support for userspace networking - -This patch adds the userspace mode support to fsl_ppfe network driver. -In the new mode, basic hardware initialization is performed in kernel, while -the datapath and HIF handling is the responsibility of the userspace. - -The new command line parameter is added to initialize the ppfe module -in userspace mode. By default the module remains in kernelspace networking -mode. -To enable userspace mode, use "insmod pfe.ko us=1" - -Signed-off-by: Akhil Goyal -Signed-off-by: Gagandeep Singh - -staging: fsl_ppfe/eth: unregister netdev after pfe_phy_exit - -rmmod pfe.ko throws below warning: - -kernfs: can not remove 'phydev', no directory -------------[ cut here ]------------ -WARNING: CPU: 0 PID: 2230 at fs/kernfs/dir.c:1481 -kernfs_remove_by_name_ns+0x90/0xa0 - -This is caused when the unregistered netdev structure is accessed to -disconnect phy. - -Resolve the issue by unregistering netdev after disconnecting phy. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: HW parse results for DPDK - -HW Parse results are included in the packet headroom. -Length and Offset calculation now accommodates parse info size. - -Signed-off-by: Archana Madhavan - -staging: fsl_ppfe/eth: reorganize pfe_netdev_ops - -Reorganize members of struct pfe_netdev_ops to match with the order -of members in struct net_device_ops defined in include/linux/netdevice.h - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: use mask for rx max frame len - -Define and use PFE_RCR_MAX_FL_MASK to properly set Rx max frame -length of MAC Receive Control Register. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: define pfe ndo_change_mtu function - -Define ndo_change_mtu function for pfe. This sets the max Rx frame -length to the new mtu. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: remove jumbo frame enable from gemac init - -MAC Receive Control Register was configured to allow jumbo frames. -This is removed as jumbo frames can be supported anytime by changing -mtu which will in turn modify MAX_FL field of MAC RCR. -Jumbo frames caused pfe to hang on LS1012A rev 1.0 Silicon due to -erratum A-010897. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: disable CRC removal - -Disable CRC removal from the packet, so that packets are forwarded -as is to Linux. -CRC configuration in MAC will be reflected in the packet received -to Linux. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: handle ls1012a errata_a010897 - -On LS1012A rev 1.0, Jumbo frames are not supported as it causes -the PFE controller to hang. A reset of the entire chip is required -to resume normal operation. - -To handle this errata, frames with length > 1900 are truncated for -rev 1.0 of LS1012A. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: replace magic numbers - -Replace magic numbers and some cosmetic changes. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: resolve indentation warning - -Resolve the following indentation warning: - -drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c: -In function ‘pfe_get_gemac_if_proprties’: -drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c:96:2: -warning: this ‘else’ clause does not guard... -[-Wmisleading-indentation] - else - ^~~~ -drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c:98:3: -note: ...this statement, but the latter is misleadingly indented as -if it were guarded by the ‘else’ - pdata->ls1012a_eth_pdata[port].mdio_muxval = phy_id; - ^~~~~ - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: add fixed-link support - -In cases where MAC is not connected to a normal MDIO-managed PHY -device, and instead to a switch, it is configured as a "fixed-link". -Code to handle this scenario is added here. - -phy_node in the dtb is checked to identify a fixed-link. -On identification of a fixed-link, it is registered and connected. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe: add support for a char dev for link status - -Read and IOCTL support is added. Application would need to open, -read/ioctl the /dev/pfe_us_cdev device. -select is pending as it requires a wait_queue. - -Signed-off-by: Shreyansh Jain -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe: enable hif event from userspace - -HIF interrupts are enabled using ioctl from user space, -and epoll wait from user space wakes up when there is an HIF -interrupt. - -Signed-off-by: Akhil Goyal - -staging: fsl_ppfe: performance tuning for user space - -interrupt coalescing of 100 usec is added. - -Signed-off-by: Akhil Goyal -Signed-off-by: Sachin Saxena - -staging: fsl_ppfe/eth: Update to use SPDX identifiers - -Replace license text with corresponding SPDX identifiers and update the -format of existing SPDX identifiers to follow the new guideline -Documentation/process/license-rules.rst. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: misc clean up - -- remove redundant hwfeature init -- remove unused vars from ls1012a_eth_platform_data -- To handle ls1012a errata_a010897, PPFE driver requires GUTS driver -to be compiled in. Select FSL_GUTS when PPFE driver is compiled. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: reorganize platform phy parameters - -- Use "phy-handle" and of_* functions to get phy node and fixed-link -parameters - -- Reorganize phy parameters and initialize them only if phy-handle -or fixed-link is defined in the dtb. - -- correct typo pfe_get_gemac_if_proprties to pfe_get_gemac_if_properties - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: support single interface initialization - -- arrange members of struct mii_bus in sequence matching phy.h -- if mdio node is defined, use of_mdiobus_register to register - child nodes (phy devices) available on the mdio bus. -- remove of_phy_register_fixed_link from pfe_phy_init as it is being - handled in pfe_get_gemac_if_properties -- remove mdio enabled check -- skip phy init, if no PHY or fixed-link - -Signed-off-by: Calvin Johnson - -net: fsl_ppfe: update dts properties for phy - -Use commonly used phy-handle property and mdio subnode to handle -phy properties. - -Deprecate bindings fsl,gemac-phy-id & fsl,pfe-phy-if-flags. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: remove unused code - -- remove gemac-bus-id related code that is unused. -- remove unused prototype gemac_set_mdc_div. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: separate mdio init from mac init - -- separate mdio initialization from mac initialization -- Define pfe_mdio_priv_s structure to hold mii_bus structure and other - related data. -- Modify functions to work with the separted mdio init model. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: adapt to link mode based phydev changes - -Setting link mode bits have changed with the integration of -commit (3c1bcc8 net: ethernet: Convert phydev advertize and -supported from u32 to link mode). Adapt to the new method of -setting and clearing the link mode bits. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: use generic soc_device infra instead of fsl_guts_get_svr() - -Commit ("soc: fsl: guts: make fsl_guts_get_svr() static") has -made fsl_guts_get_svr() static and hence use generic soc_device -infrastructure to check SoC revision. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: use memremap() to map RAM area used by PFE - -RAM area used by PFE should be mapped using memremap() instead of -directly traslating physical addr to virtual. This will ensure proper -checks are done before the area is used. - -Signed-off-by: Calvin Johnson - -staging: fsl_ppfe/eth: remove 'fallback' argument from dev->ndo_select_queue() - -To be consistent with upstream API change. - -Signed-off-by: Li Yang - -staging: fsl_ppfe/eth: prefix header search paths with $(srctree)/ - -Currently, the rules for configuring search paths in Kbuild have -changed: https://lkml.org/lkml/2019/5/13/37 - -This will lead the below error: - -fatal error: pfe/pfe.h: No such file or directory - -Fix it by adding $(srctree)/ prefix to the search paths. - -Signed-off-by: Ting Liu - -staging: fsl_ppfe/eth: add pfe support to Kconfig and Makefile - -Signed-off-by: Calvin Johnson -[ Aisheng: fix minor conflict due to removed VBOXSF_FS ] -Signed-off-by: Dong Aisheng - -staging: fsl_ppfe/eth: Disable termination of CRC fwd. - -LS1012A MAC PCS block has an erratum that is seen with specific PHY AR803x. -The issue is triggered by the (spec-compliant) operation of the AR803x PHY -on the LS1012A-FRWY board.Due to this, good FCS packet is reported as error -packet by MAC, so for these error packets FCS should be validated and -discard only real error packets in PFE Rx packet path. - -Signed-off-by: Nagesh Koneti -Signed-off-by: Nagesh Koneti <“koneti.nagesh@nxp.com”> - -net: ppfe: Cope with of_get_phy_mode() API change - -Signed-off-by: Li Yang - -staging: fsl_ppfe/eth: Enhance error checking in platform probe - -Fix the kernel crash when MAC addr is not passed in dtb. - -Signed-off-by: Anji Jagarlmudi - -staging: fsl_ppfe/eth: reject unsupported coalescing params - -Set ethtool_ops->supported_coalesce_params to let -the core reject unsupported coalescing parameters. - -Signed-off-by: Anji Jagarlmudi - -staging: fsl_ppfe/eth:check "reg" property before pfe_get_gemac_if_properties() - -It has been observed that the function pfe_get_gemac_if_properties() is -been called blindly for the next two child nodes. There might be some -cases where it may go wrong and that lead to missing interfaces. -with these changes it is ensured thats not the case. - -Signed-off-by: Chaitanya Sakinam -Signed-off-by: Anji J - -staging: fsl_ppfe/eth: "struct firmware" dereference is reduced in many functions - -firmware structure's data variable is the actual elf data. It has been -dereferenced in multiple functions and this has been reduced. - -Signed-off-by: Chaitanya Sakinam -Signed-off-by: Anji J - -staging: fsl_ppfe/eth: LF-27 load pfe binaries from FDT - -FDT prepared in uboot now has pfe firmware part of it. -These changes will read the firmware by default from it and tries to load -the elf into the PFE PEs. This help build the pfe driver pasrt of kernel. - -Signed-off-by: Chaitanya Sakinam -Signed-off-by: Anji J - -staging: fsl_ppfe/eth: proper handling for RGMII delay mode - -The correct setting for the RGMII ports on LS1012ARDB is to -enable delay on both Tx and Rx. So the phy mode to be matched -is PHY_INTERFACE_MODE_RGMII_ID. - -Signed-off-by: Chaitanya Sakinam -Signed-off-by: Anji Jagarlmudi - -LF-1762-2 staging: fsl_ppfe: replace '---help---' in Kconfig files with 'help' - -Update Kconfig to cope with upstream change -commit 84af7a6194e4 ("checkpatch: kconfig: prefer 'help' over -'---help---'"). - -Signed-off-by: Dong Aisheng - -staging: fsl_ppfe/eth: Nesting level does not match indentation - -corrected nesting level -LF-1661 and Coverity CID: 8879316 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: Initialized scalar variable - -Proper initialization of scalar variable -LF-1657 and Coverity CID: 3335133 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: misspelt variable name - -variable name corrected -LF-1656 and Coverity CID: 3335119 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: Avoiding out-of-bound writes - -avoid out-of-bound writes with proper error handling -LF-1654, LF-1652 and Coverity CID: 3335106, 3335090 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: Initializing scalar variable - -proper initialization of scalar variable. -LF-1653 and Coverity CID: 3335101 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: checking return value - -proper checks added and handled for return value. -LF-1644 and Coverity CID: 241888 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: Avoid out-of-bound access - -proper handling to avoid out-of-bound access -LF-1642, LF-1641 and Coverity CID: 240910, 240891 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: Avoiding out-of-bound writes - -avoid out-of-bound writes with proper error handling -LF-1654, LF-1652 and Coverity CID: 3335106, 3335090 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: return value init in error case - -proper err return in error case. -LF-1806 and Coverity CID: 10468592 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: Avoid recursion in header inclusion - -Avoiding header inclusions that are not necessary and also that are -causing header inclusion recursion. - -LF-2102 and Coverity CID: 240838 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: Avoiding return value overwrite - -avoid return value overwrite at the end of function. -LF-2136, LF-2137 and Coverity CID: 8879341, 8879364 - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: LF-27 enabling PFE firmware load from FDT - -The macro, "LOAD_PFEFIRMWARE_FROM_FILESYSTEM" is been disabled to load -the firmware from FDT by default. Enabling the macro will load the -firmware from filesystem. - -Also, the Makefile is now tuned to build pfe as per the config option - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: Ethtool stats correction for IEEE_rx_drop counter - -Due to carrier extended bug the phy counter IEEE_rx_drop counter is -incremented some times and phy reports the packet has crc error. -Because of this PFE revalidates all the packets that are marked crc -error by phy. Now, the counter phy reports is till bogus and this -patch decrements the counter by pfe revalidated (and are crc ok) -counter amount. - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe/eth: PFE firmware load enhancements - -PFE driver enhancements to load the PE firmware from filesystem -when the firmware is not found in FDT. - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe: deal with upstream API change of of_get_mac_address() - -Uptream commit 83216e398 changed the of_get_mac_address() API, update -the user accordingly. - -Signed-off-by: Li Yang - -staging: fsl_ppfe: update coalesce setting uAPI usage - -API changed since: -f3ccfda19319 ("ethtool: extend coalesce setting uAPI with CQE mode") - -Signed-off-by: Dong Aisheng - -staging: fsl_ppfe: Addressed build warnings - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe: Addressed build warnings - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe: Remove C45 check and related code in driver - -The MDIO core will not pass a C45 request via the C22 API call any -more. So, removed the code. The old way of C45 muxed addresses is -removed from the upstream kernel after clear seperation of C45 and -C22. -Upstream kernel commit details for reference: -99d5fe9c7f3d net: mdio: Remove support for building C45 muxed addresses - -Signed-off-by: Chaitanya Sakinam - -staging: fsl_ppfe: update class_create() usage - -Cope with API change: -1aaba11da9aa ("driver core: class: remove module * from class_create()") - -Signed-off-by: Krishna Chaitanya Sakinam - -LF-10777-2 staging: fsl_ppfe: remove unused pfe_eth_mdio_write_addr - -Fix the following build warning: -drivers/staging/fsl_ppfe/pfe_eth.c:887:12: warning: ‘pfe_eth_mdio_write_addr’ defined but not used [-Wunused-function] - 887 | static int pfe_eth_mdio_write_addr(struct mii_bus *bus, int mii_id, - -The only user of this API is MII_ADDR_C45 checking logic which -was removed since the commit 9d95b13bd084 ("staging: fsl_ppfe: Remove -C45 check and related code in driver"). So this API should be removed -together as no users anymore. - -Fixes: 9d95b13bd084 ("staging: fsl_ppfe: Remove C45 check and related code in driver") -Reviewed-by: Jason Liu -Signed-off-by: Dong Aisheng - -LF-13827-2 net: pfe: fix Wmissing-prototypes build warnings - -drivers/staging/fsl_ppfe/pfe_firmware.c:128:5: warning: no previous prototype for ‘pfe_load_elf’ [-Wmissing-prototypes] - 128 | int pfe_load_elf(int pe_mask, const u8 *fw, struct pfe *pfe) - | ^~~~~~~~~~~~ -drivers/staging/fsl_ppfe/pfe_firmware.c:185:5: warning: no previous prototype for ‘get_firmware_in_fdt’ [-Wmissing-prototypes] - 185 | int get_firmware_in_fdt(const u8 **pe_fw, const char *name) - | ^~~~~~~~~~~~~~~~~~~ - -Reviewed-by: Wei Fang -Signed-off-by: Dong Aisheng - -LF-13827-3 net/pfe: use $(src) instead of $(srctree)/$(src) - -Cope with upstream change -b1992c3772e6 ("kbuild: use $(src) instead of $(srctree)/$(src) for source directory") - -Reviewed-by: Wei Fang -Signed-off-by: Dong Aisheng - -LF-13827-6 net: ppfe: update the usage of eventfd_signal - -Cope with the API change since the commit -1808acc4fab2 ("eventfd: simplify eventfd_signal()") - -Otherwise will meet the following build error: -drivers/staging/fsl_ppfe/pfe_cdev.c: In function ‘hif_us_isr’: -drivers/staging/fsl_ppfe/pfe_cdev.c:112:17: error: too many arguments to function ‘eventfd_signal’ - 112 | eventfd_signal(trigger, 1); - | ^~~~~~~~~~~~~~ - -Reviewed-by: Wei Fang -Signed-off-by: Dong Aisheng - -LF-13827-7 net: pfe: Replace strlcpy() with strscpy() for many drivers - -Cope with upstream change: -commit d26270061ae6 ("string: Remove strlcpy()") - -e.g. -../drivers/i2c/busses/i2c-flexio.c: In function ‘imx_flexio_i2c_master_probe’: -../drivers/i2c/busses/i2c-flexio.c:683:9: error: implicit declaration of function ‘strlcpy’; did you mean ‘strncpy’? [-Werror=implicit-function-declaration] - 683 | strlcpy(i2c_dev->adapter.name, dev_name(i2c_dev->dev), - | ^~~~~~~ - | strncpy - -Signed-off-by: Dong Aisheng - -drivers: make all local platform_driver::remove() return void - -0edb555a65d1 ("platform: Make platform_driver::remove() return void") - -Signed-off-by: Dong Aisheng ---- - .../devicetree/bindings/net/fsl_ppfe/pfe.txt | 199 ++ - MAINTAINERS | 8 + - drivers/staging/Kconfig | 2 + - drivers/staging/Makefile | 1 + - drivers/staging/fsl_ppfe/Kconfig | 21 + - drivers/staging/fsl_ppfe/Makefile | 20 + - drivers/staging/fsl_ppfe/TODO | 2 + - drivers/staging/fsl_ppfe/include/pfe/cbus.h | 78 + - .../staging/fsl_ppfe/include/pfe/cbus/bmu.h | 55 + - .../fsl_ppfe/include/pfe/cbus/class_csr.h | 289 ++ - .../fsl_ppfe/include/pfe/cbus/emac_mtip.h | 242 ++ - .../staging/fsl_ppfe/include/pfe/cbus/gpi.h | 86 + - .../staging/fsl_ppfe/include/pfe/cbus/hif.h | 100 + - .../fsl_ppfe/include/pfe/cbus/hif_nocpy.h | 50 + - .../fsl_ppfe/include/pfe/cbus/tmu_csr.h | 168 ++ - .../fsl_ppfe/include/pfe/cbus/util_csr.h | 61 + - drivers/staging/fsl_ppfe/include/pfe/pfe.h | 372 +++ - drivers/staging/fsl_ppfe/pfe_cdev.c | 258 ++ - drivers/staging/fsl_ppfe/pfe_cdev.h | 41 + - drivers/staging/fsl_ppfe/pfe_ctrl.c | 226 ++ - drivers/staging/fsl_ppfe/pfe_ctrl.h | 100 + - drivers/staging/fsl_ppfe/pfe_debugfs.c | 99 + - drivers/staging/fsl_ppfe/pfe_debugfs.h | 13 + - drivers/staging/fsl_ppfe/pfe_eth.c | 2550 +++++++++++++++++ - drivers/staging/fsl_ppfe/pfe_eth.h | 175 ++ - drivers/staging/fsl_ppfe/pfe_firmware.c | 398 +++ - drivers/staging/fsl_ppfe/pfe_firmware.h | 21 + - drivers/staging/fsl_ppfe/pfe_hal.c | 1517 ++++++++++ - drivers/staging/fsl_ppfe/pfe_hif.c | 1063 +++++++ - drivers/staging/fsl_ppfe/pfe_hif.h | 199 ++ - drivers/staging/fsl_ppfe/pfe_hif_lib.c | 628 ++++ - drivers/staging/fsl_ppfe/pfe_hif_lib.h | 229 ++ - drivers/staging/fsl_ppfe/pfe_hw.c | 164 ++ - drivers/staging/fsl_ppfe/pfe_hw.h | 15 + - .../staging/fsl_ppfe/pfe_ls1012a_platform.c | 381 +++ - drivers/staging/fsl_ppfe/pfe_mod.c | 158 + - drivers/staging/fsl_ppfe/pfe_mod.h | 103 + - drivers/staging/fsl_ppfe/pfe_perfmon.h | 26 + - drivers/staging/fsl_ppfe/pfe_sysfs.c | 840 ++++++ - drivers/staging/fsl_ppfe/pfe_sysfs.h | 17 + - 40 files changed, 10975 insertions(+) - create mode 100644 Documentation/devicetree/bindings/net/fsl_ppfe/pfe.txt - create mode 100644 drivers/staging/fsl_ppfe/Kconfig - create mode 100644 drivers/staging/fsl_ppfe/Makefile - create mode 100644 drivers/staging/fsl_ppfe/TODO - create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus.h - create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/bmu.h - create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/class_csr.h - create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/emac_mtip.h - create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/gpi.h - create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/hif.h - create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/hif_nocpy.h - create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/tmu_csr.h - create mode 100644 drivers/staging/fsl_ppfe/include/pfe/cbus/util_csr.h - create mode 100644 drivers/staging/fsl_ppfe/include/pfe/pfe.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_cdev.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_cdev.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_ctrl.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_ctrl.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_debugfs.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_debugfs.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_eth.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_eth.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_firmware.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_firmware.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_hal.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_hif.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_hif.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_hif_lib.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_hif_lib.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_hw.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_hw.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_mod.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_mod.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_perfmon.h - create mode 100644 drivers/staging/fsl_ppfe/pfe_sysfs.c - create mode 100644 drivers/staging/fsl_ppfe/pfe_sysfs.h - ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/fsl_ppfe/pfe.txt -@@ -0,0 +1,199 @@ -+============================================================================= -+NXP Programmable Packet Forwarding Engine Device Bindings -+ -+CONTENTS -+ - PFE Node -+ - Ethernet Node -+ -+============================================================================= -+PFE Node -+ -+DESCRIPTION -+ -+PFE Node has all the properties associated with Packet Forwarding Engine block. -+ -+PROPERTIES -+ -+- compatible -+ Usage: required -+ Value type: -+ Definition: Must include "fsl,pfe" -+ -+- reg -+ Usage: required -+ Value type: -+ Definition: A standard property. -+ Specifies the offset of the following registers: -+ - PFE configuration registers -+ - DDR memory used by PFE -+ -+- fsl,pfe-num-interfaces -+ Usage: required -+ Value type: -+ Definition: Must be present. Value can be either one or two. -+ -+- interrupts -+ Usage: required -+ Value type: -+ Definition: Three interrupts are specified in this property. -+ - HIF interrupt -+ - HIF NO COPY interrupt -+ - Wake On LAN interrupt -+ -+- interrupt-names -+ Usage: required -+ Value type: -+ Definition: Following strings are defined for the 3 interrupts. -+ "pfe_hif" - HIF interrupt -+ "pfe_hif_nocpy" - HIF NO COPY interrupt -+ "pfe_wol" - Wake On LAN interrupt -+ -+- memory-region -+ Usage: required -+ Value type: -+ Definition: phandle to a node describing reserved memory used by pfe. -+ Refer:- Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt -+ -+- fsl,pfe-scfg -+ Usage: required -+ Value type: -+ Definition: phandle for scfg. -+ -+- fsl,rcpm-wakeup -+ Usage: required -+ Value type: -+ Definition: phandle for rcpm. -+ -+- clocks -+ Usage: required -+ Value type: -+ Definition: phandle for clockgen. -+ -+- clock-names -+ Usage: required -+ Value type: -+ Definition: phandle for clock name. -+ -+EXAMPLE -+ -+pfe: pfe@04000000 { -+ compatible = "fsl,pfe"; -+ reg = <0x0 0x04000000 0x0 0xc00000>, /* AXI 16M */ -+ <0x0 0x83400000 0x0 0xc00000>; /* PFE DDR 12M */ -+ reg-names = "pfe", "pfe-ddr"; -+ fsl,pfe-num-interfaces = <0x2>; -+ interrupts = <0 172 0x4>, /* HIF interrupt */ -+ <0 173 0x4>, /*HIF_NOCPY interrupt */ -+ <0 174 0x4>; /* WoL interrupt */ -+ interrupt-names = "pfe_hif", "pfe_hif_nocpy", "pfe_wol"; -+ memory-region = <&pfe_reserved>; -+ fsl,pfe-scfg = <&scfg 0>; -+ fsl,rcpm-wakeup = <&rcpm 0xf0000020>; -+ clocks = <&clockgen 4 0>; -+ clock-names = "pfe"; -+ -+ status = "okay"; -+ pfe_mac0: ethernet@0 { -+ }; -+ -+ pfe_mac1: ethernet@1 { -+ }; -+}; -+ -+============================================================================= -+Ethernet Node -+ -+DESCRIPTION -+ -+Ethernet Node has all the properties associated with PFE used by platforms to -+connect to PHY: -+ -+PROPERTIES -+ -+- compatible -+ Usage: required -+ Value type: -+ Definition: Must include "fsl,pfe-gemac-port" -+ -+- reg -+ Usage: required -+ Value type: -+ Definition: A standard property. -+ Specifies the gemacid of the interface. -+ -+- fsl,gemac-bus-id -+ Usage: required -+ Value type: -+ Definition: Must be present. Value should be the id of the bus -+ connected to gemac. -+ -+- fsl,gemac-phy-id (deprecated binding) -+ Usage: required -+ Value type: -+ Definition: This binding shouldn't be used with new platforms. -+ Must be present. Value should be the id of the phy -+ connected to gemac. -+ -+- fsl,mdio-mux-val -+ Usage: required -+ Value type: -+ Definition: Must be present. Value can be either 0 or 2 or 3. -+ This value is used to configure the mux to enable mdio. -+ -+- phy-mode -+ Usage: required -+ Value type: -+ Definition: Must include "sgmii" -+ -+- fsl,pfe-phy-if-flags (deprecated binding) -+ Usage: required -+ Value type: -+ Definition: This binding shouldn't be used with new platforms. -+ Must be present. Value should be 0 by default. -+ If there is not phy connected, this need to be 1. -+ -+- phy-handle -+ Usage: optional -+ Value type: -+ Definition: phandle to the PHY device connected to this device. -+ -+- mdio : A required subnode which specifies the mdio bus in the PFE and used as -+a container for phy nodes according to ../phy.txt. -+ -+EXAMPLE -+ -+ethernet@0 { -+ compatible = "fsl,pfe-gemac-port"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x0>; /* GEM_ID */ -+ fsl,gemac-bus-id = <0x0>; /* BUS_ID */ -+ fsl,mdio-mux-val = <0x0>; -+ phy-mode = "sgmii"; -+ phy-handle = <&sgmii_phy1>; -+}; -+ -+ -+ethernet@1 { -+ compatible = "fsl,pfe-gemac-port"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x1>; /* GEM_ID */ -+ fsl,gemac-bus-id = <0x1>; /* BUS_ID */ -+ fsl,mdio-mux-val = <0x0>; -+ phy-mode = "sgmii"; -+ phy-handle = <&sgmii_phy2>; -+}; -+ -+mdio@0 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ sgmii_phy1: ethernet-phy@2 { -+ reg = <0x2>; -+ }; -+ -+ sgmii_phy2: ethernet-phy@1 { -+ reg = <0x1>; -+ }; -+}; ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -9114,6 +9114,14 @@ F: drivers/ptp/ptp_qoriq.c - F: drivers/ptp/ptp_qoriq_debugfs.c - F: include/linux/fsl/ptp_qoriq.h - -+FREESCALE QORIQ PPFE ETHERNET DRIVER -+M: Anji Jagarlmudi -+M: Calvin Johnson -+L: netdev@vger.kernel.org -+S: Maintained -+F: drivers/staging/fsl_ppfe -+F: Documentation/devicetree/bindings/net/fsl_ppfe/pfe.txt -+ - FREESCALE QUAD SPI DRIVER - M: Han Xu - L: linux-spi@vger.kernel.org ---- a/drivers/staging/Kconfig -+++ b/drivers/staging/Kconfig -@@ -62,4 +62,6 @@ source "drivers/staging/fieldbus/Kconfig - - source "drivers/staging/vme_user/Kconfig" - -+source "drivers/staging/fsl_ppfe/Kconfig" -+ - endif # STAGING ---- a/drivers/staging/Makefile -+++ b/drivers/staging/Makefile -@@ -20,3 +20,4 @@ obj-$(CONFIG_GREYBUS) += greybus/ - obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ - obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ - obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ -+obj-$(CONFIG_FSL_PPFE) += fsl_ppfe/ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/Kconfig -@@ -0,0 +1,21 @@ -+# -+# Freescale Programmable Packet Forwarding Engine driver -+# -+config FSL_PPFE -+ tristate "Freescale PPFE Driver" -+ select FSL_GUTS -+ default n -+ help -+ Freescale LS1012A SoC has a Programmable Packet Forwarding Engine. -+ It provides two high performance ethernet interfaces. -+ This driver initializes, programs and controls the PPFE. -+ Use this driver to enable network connectivity on LS1012A platforms. -+ -+if FSL_PPFE -+ -+config FSL_PPFE_UTIL_DISABLED -+ bool "Disable PPFE UTIL Processor Engine" -+ help -+ UTIL PE has to be enabled only if required. -+ -+endif # FSL_PPFE ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/Makefile -@@ -0,0 +1,20 @@ -+# -+# Makefile for Freesecale PPFE driver -+# -+ -+ccflags-y += -I $(src)/include -I $(src) -+ -+obj-$(CONFIG_FSL_PPFE) += pfe.o -+ -+pfe-y += pfe_mod.o \ -+ pfe_hw.o \ -+ pfe_firmware.o \ -+ pfe_ctrl.o \ -+ pfe_hif.o \ -+ pfe_hif_lib.o\ -+ pfe_eth.o \ -+ pfe_sysfs.o \ -+ pfe_debugfs.o \ -+ pfe_ls1012a_platform.o \ -+ pfe_hal.o \ -+ pfe_cdev.o ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/TODO -@@ -0,0 +1,2 @@ -+TODO: -+ - provide pfe pe monitoring support ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/include/pfe/cbus.h -@@ -0,0 +1,78 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _CBUS_H_ -+#define _CBUS_H_ -+ -+#define EMAC1_BASE_ADDR (CBUS_BASE_ADDR + 0x200000) -+#define EGPI1_BASE_ADDR (CBUS_BASE_ADDR + 0x210000) -+#define EMAC2_BASE_ADDR (CBUS_BASE_ADDR + 0x220000) -+#define EGPI2_BASE_ADDR (CBUS_BASE_ADDR + 0x230000) -+#define BMU1_BASE_ADDR (CBUS_BASE_ADDR + 0x240000) -+#define BMU2_BASE_ADDR (CBUS_BASE_ADDR + 0x250000) -+#define ARB_BASE_ADDR (CBUS_BASE_ADDR + 0x260000) -+#define DDR_CONFIG_BASE_ADDR (CBUS_BASE_ADDR + 0x270000) -+#define HIF_BASE_ADDR (CBUS_BASE_ADDR + 0x280000) -+#define HGPI_BASE_ADDR (CBUS_BASE_ADDR + 0x290000) -+#define LMEM_BASE_ADDR (CBUS_BASE_ADDR + 0x300000) -+#define LMEM_SIZE 0x10000 -+#define LMEM_END (LMEM_BASE_ADDR + LMEM_SIZE) -+#define TMU_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x310000) -+#define CLASS_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x320000) -+#define HIF_NOCPY_BASE_ADDR (CBUS_BASE_ADDR + 0x350000) -+#define UTIL_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x360000) -+#define CBUS_GPT_BASE_ADDR (CBUS_BASE_ADDR + 0x370000) -+ -+/* -+ * defgroup XXX_MEM_ACCESS_ADDR PE memory access through CSR -+ * XXX_MEM_ACCESS_ADDR register bit definitions. -+ */ -+#define PE_MEM_ACCESS_WRITE BIT(31) /* Internal Memory Write. */ -+#define PE_MEM_ACCESS_IMEM BIT(15) -+#define PE_MEM_ACCESS_DMEM BIT(16) -+ -+/* Byte Enables of the Internal memory access. These are interpred in BE */ -+#define PE_MEM_ACCESS_BYTE_ENABLE(offset, size) \ -+ ({ typeof(size) size_ = (size); \ -+ (((BIT(size_) - 1) << (4 - (offset) - (size_))) & 0xf) << 24; }) -+ -+#include "cbus/emac_mtip.h" -+#include "cbus/gpi.h" -+#include "cbus/bmu.h" -+#include "cbus/hif.h" -+#include "cbus/tmu_csr.h" -+#include "cbus/class_csr.h" -+#include "cbus/hif_nocpy.h" -+#include "cbus/util_csr.h" -+ -+/* PFE cores states */ -+#define CORE_DISABLE 0x00000000 -+#define CORE_ENABLE 0x00000001 -+#define CORE_SW_RESET 0x00000002 -+ -+/* LMEM defines */ -+#define LMEM_HDR_SIZE 0x0010 -+#define LMEM_BUF_SIZE_LN2 0x7 -+#define LMEM_BUF_SIZE BIT(LMEM_BUF_SIZE_LN2) -+ -+/* DDR defines */ -+#define DDR_HDR_SIZE 0x0100 -+#define DDR_BUF_SIZE_LN2 0xb -+#define DDR_BUF_SIZE BIT(DDR_BUF_SIZE_LN2) -+ -+#endif /* _CBUS_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/bmu.h -@@ -0,0 +1,55 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _BMU_H_ -+#define _BMU_H_ -+ -+#define BMU_VERSION 0x000 -+#define BMU_CTRL 0x004 -+#define BMU_UCAST_CONFIG 0x008 -+#define BMU_UCAST_BASE_ADDR 0x00c -+#define BMU_BUF_SIZE 0x010 -+#define BMU_BUF_CNT 0x014 -+#define BMU_THRES 0x018 -+#define BMU_INT_SRC 0x020 -+#define BMU_INT_ENABLE 0x024 -+#define BMU_ALLOC_CTRL 0x030 -+#define BMU_FREE_CTRL 0x034 -+#define BMU_FREE_ERR_ADDR 0x038 -+#define BMU_CURR_BUF_CNT 0x03c -+#define BMU_MCAST_CNT 0x040 -+#define BMU_MCAST_ALLOC_CTRL 0x044 -+#define BMU_REM_BUF_CNT 0x048 -+#define BMU_LOW_WATERMARK 0x050 -+#define BMU_HIGH_WATERMARK 0x054 -+#define BMU_INT_MEM_ACCESS 0x100 -+ -+struct BMU_CFG { -+ unsigned long baseaddr; -+ u32 count; -+ u32 size; -+ u32 low_watermark; -+ u32 high_watermark; -+}; -+ -+#define BMU1_BUF_SIZE LMEM_BUF_SIZE_LN2 -+#define BMU2_BUF_SIZE DDR_BUF_SIZE_LN2 -+ -+#define BMU2_MCAST_ALLOC_CTRL (BMU2_BASE_ADDR + BMU_MCAST_ALLOC_CTRL) -+ -+#endif /* _BMU_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/class_csr.h -@@ -0,0 +1,289 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _CLASS_CSR_H_ -+#define _CLASS_CSR_H_ -+ -+/* @file class_csr.h. -+ * class_csr - block containing all the classifier control and status register. -+ * Mapped on CBUS and accessible from all PE's and ARM. -+ */ -+#define CLASS_VERSION (CLASS_CSR_BASE_ADDR + 0x000) -+#define CLASS_TX_CTRL (CLASS_CSR_BASE_ADDR + 0x004) -+#define CLASS_INQ_PKTPTR (CLASS_CSR_BASE_ADDR + 0x010) -+ -+/* (ddr_hdr_size[24:16], lmem_hdr_size[5:0]) */ -+#define CLASS_HDR_SIZE (CLASS_CSR_BASE_ADDR + 0x014) -+ -+/* LMEM header size for the Classifier block.\ Data in the LMEM -+ * is written from this offset. -+ */ -+#define CLASS_HDR_SIZE_LMEM(off) ((off) & 0x3f) -+ -+/* DDR header size for the Classifier block.\ Data in the DDR -+ * is written from this offset. -+ */ -+#define CLASS_HDR_SIZE_DDR(off) (((off) & 0x1ff) << 16) -+ -+#define CLASS_PE0_QB_DM_ADDR0 (CLASS_CSR_BASE_ADDR + 0x020) -+ -+/* DMEM address of first [15:0] and second [31:16] buffers on QB side. */ -+#define CLASS_PE0_QB_DM_ADDR1 (CLASS_CSR_BASE_ADDR + 0x024) -+ -+/* DMEM address of third [15:0] and fourth [31:16] buffers on QB side. */ -+#define CLASS_PE0_RO_DM_ADDR0 (CLASS_CSR_BASE_ADDR + 0x060) -+ -+/* DMEM address of first [15:0] and second [31:16] buffers on RO side. */ -+#define CLASS_PE0_RO_DM_ADDR1 (CLASS_CSR_BASE_ADDR + 0x064) -+ -+/* DMEM address of third [15:0] and fourth [31:16] buffers on RO side. */ -+ -+/* @name Class PE memory access. Allows external PE's and HOST to -+ * read/write PMEM/DMEM memory ranges for each classifier PE. -+ */ -+/* {sr_pe_mem_cmd[31], csr_pe_mem_wren[27:24], csr_pe_mem_addr[23:0]}, -+ * See \ref XXX_MEM_ACCESS_ADDR for details. -+ */ -+#define CLASS_MEM_ACCESS_ADDR (CLASS_CSR_BASE_ADDR + 0x100) -+ -+/* Internal Memory Access Write Data [31:0] */ -+#define CLASS_MEM_ACCESS_WDATA (CLASS_CSR_BASE_ADDR + 0x104) -+ -+/* Internal Memory Access Read Data [31:0] */ -+#define CLASS_MEM_ACCESS_RDATA (CLASS_CSR_BASE_ADDR + 0x108) -+#define CLASS_TM_INQ_ADDR (CLASS_CSR_BASE_ADDR + 0x114) -+#define CLASS_PE_STATUS (CLASS_CSR_BASE_ADDR + 0x118) -+ -+#define CLASS_PHY1_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x11c) -+#define CLASS_PHY1_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x120) -+#define CLASS_PHY1_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x124) -+#define CLASS_PHY1_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x128) -+#define CLASS_PHY1_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x12c) -+#define CLASS_PHY1_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x130) -+#define CLASS_PHY1_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x134) -+#define CLASS_PHY1_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x138) -+#define CLASS_PHY1_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x13c) -+#define CLASS_PHY1_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x140) -+#define CLASS_PHY2_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x144) -+#define CLASS_PHY2_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x148) -+#define CLASS_PHY2_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x14c) -+#define CLASS_PHY2_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x150) -+#define CLASS_PHY2_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x154) -+#define CLASS_PHY2_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x158) -+#define CLASS_PHY2_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x15c) -+#define CLASS_PHY2_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x160) -+#define CLASS_PHY2_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x164) -+#define CLASS_PHY2_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x168) -+#define CLASS_PHY3_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x16c) -+#define CLASS_PHY3_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x170) -+#define CLASS_PHY3_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x174) -+#define CLASS_PHY3_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x178) -+#define CLASS_PHY3_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x17c) -+#define CLASS_PHY3_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x180) -+#define CLASS_PHY3_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x184) -+#define CLASS_PHY3_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x188) -+#define CLASS_PHY3_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x18c) -+#define CLASS_PHY3_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x190) -+#define CLASS_PHY1_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x194) -+#define CLASS_PHY1_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x198) -+#define CLASS_PHY1_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x19c) -+#define CLASS_PHY1_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1a0) -+#define CLASS_PHY2_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1a4) -+#define CLASS_PHY2_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1a8) -+#define CLASS_PHY2_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x1ac) -+#define CLASS_PHY2_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1b0) -+#define CLASS_PHY3_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1b4) -+#define CLASS_PHY3_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1b8) -+#define CLASS_PHY3_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x1bc) -+#define CLASS_PHY3_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1c0) -+#define CLASS_PHY4_ICMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1c4) -+#define CLASS_PHY4_IGMP_PKTS (CLASS_CSR_BASE_ADDR + 0x1c8) -+#define CLASS_PHY4_TCP_PKTS (CLASS_CSR_BASE_ADDR + 0x1cc) -+#define CLASS_PHY4_UDP_PKTS (CLASS_CSR_BASE_ADDR + 0x1d0) -+#define CLASS_PHY4_RX_PKTS (CLASS_CSR_BASE_ADDR + 0x1d4) -+#define CLASS_PHY4_TX_PKTS (CLASS_CSR_BASE_ADDR + 0x1d8) -+#define CLASS_PHY4_LP_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x1dc) -+#define CLASS_PHY4_INTF_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x1e0) -+#define CLASS_PHY4_INTF_MATCH_PKTS (CLASS_CSR_BASE_ADDR + 0x1e4) -+#define CLASS_PHY4_L3_FAIL_PKTS (CLASS_CSR_BASE_ADDR + 0x1e8) -+#define CLASS_PHY4_V4_PKTS (CLASS_CSR_BASE_ADDR + 0x1ec) -+#define CLASS_PHY4_V6_PKTS (CLASS_CSR_BASE_ADDR + 0x1f0) -+#define CLASS_PHY4_CHKSUM_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x1f4) -+#define CLASS_PHY4_TTL_ERR_PKTS (CLASS_CSR_BASE_ADDR + 0x1f8) -+ -+#define CLASS_PE_SYS_CLK_RATIO (CLASS_CSR_BASE_ADDR + 0x200) -+#define CLASS_AFULL_THRES (CLASS_CSR_BASE_ADDR + 0x204) -+#define CLASS_GAP_BETWEEN_READS (CLASS_CSR_BASE_ADDR + 0x208) -+#define CLASS_MAX_BUF_CNT (CLASS_CSR_BASE_ADDR + 0x20c) -+#define CLASS_TSQ_FIFO_THRES (CLASS_CSR_BASE_ADDR + 0x210) -+#define CLASS_TSQ_MAX_CNT (CLASS_CSR_BASE_ADDR + 0x214) -+#define CLASS_IRAM_DATA_0 (CLASS_CSR_BASE_ADDR + 0x218) -+#define CLASS_IRAM_DATA_1 (CLASS_CSR_BASE_ADDR + 0x21c) -+#define CLASS_IRAM_DATA_2 (CLASS_CSR_BASE_ADDR + 0x220) -+#define CLASS_IRAM_DATA_3 (CLASS_CSR_BASE_ADDR + 0x224) -+ -+#define CLASS_BUS_ACCESS_ADDR (CLASS_CSR_BASE_ADDR + 0x228) -+ -+#define CLASS_BUS_ACCESS_WDATA (CLASS_CSR_BASE_ADDR + 0x22c) -+#define CLASS_BUS_ACCESS_RDATA (CLASS_CSR_BASE_ADDR + 0x230) -+ -+/* (route_entry_size[9:0], route_hash_size[23:16] -+ * (this is actually ln2(size))) -+ */ -+#define CLASS_ROUTE_HASH_ENTRY_SIZE (CLASS_CSR_BASE_ADDR + 0x234) -+ -+#define CLASS_ROUTE_ENTRY_SIZE(size) ((size) & 0x1ff) -+#define CLASS_ROUTE_HASH_SIZE(hash_bits) (((hash_bits) & 0xff) << 16) -+ -+#define CLASS_ROUTE_TABLE_BASE (CLASS_CSR_BASE_ADDR + 0x238) -+ -+#define CLASS_ROUTE_MULTI (CLASS_CSR_BASE_ADDR + 0x23c) -+#define CLASS_SMEM_OFFSET (CLASS_CSR_BASE_ADDR + 0x240) -+#define CLASS_LMEM_BUF_SIZE (CLASS_CSR_BASE_ADDR + 0x244) -+#define CLASS_VLAN_ID (CLASS_CSR_BASE_ADDR + 0x248) -+#define CLASS_BMU1_BUF_FREE (CLASS_CSR_BASE_ADDR + 0x24c) -+#define CLASS_USE_TMU_INQ (CLASS_CSR_BASE_ADDR + 0x250) -+#define CLASS_VLAN_ID1 (CLASS_CSR_BASE_ADDR + 0x254) -+ -+#define CLASS_BUS_ACCESS_BASE (CLASS_CSR_BASE_ADDR + 0x258) -+#define CLASS_BUS_ACCESS_BASE_MASK (0xFF000000) -+/* bit 31:24 of PE peripheral address are stored in CLASS_BUS_ACCESS_BASE */ -+ -+#define CLASS_HIF_PARSE (CLASS_CSR_BASE_ADDR + 0x25c) -+ -+#define CLASS_HOST_PE0_GP (CLASS_CSR_BASE_ADDR + 0x260) -+#define CLASS_PE0_GP (CLASS_CSR_BASE_ADDR + 0x264) -+#define CLASS_HOST_PE1_GP (CLASS_CSR_BASE_ADDR + 0x268) -+#define CLASS_PE1_GP (CLASS_CSR_BASE_ADDR + 0x26c) -+#define CLASS_HOST_PE2_GP (CLASS_CSR_BASE_ADDR + 0x270) -+#define CLASS_PE2_GP (CLASS_CSR_BASE_ADDR + 0x274) -+#define CLASS_HOST_PE3_GP (CLASS_CSR_BASE_ADDR + 0x278) -+#define CLASS_PE3_GP (CLASS_CSR_BASE_ADDR + 0x27c) -+#define CLASS_HOST_PE4_GP (CLASS_CSR_BASE_ADDR + 0x280) -+#define CLASS_PE4_GP (CLASS_CSR_BASE_ADDR + 0x284) -+#define CLASS_HOST_PE5_GP (CLASS_CSR_BASE_ADDR + 0x288) -+#define CLASS_PE5_GP (CLASS_CSR_BASE_ADDR + 0x28c) -+ -+#define CLASS_PE_INT_SRC (CLASS_CSR_BASE_ADDR + 0x290) -+#define CLASS_PE_INT_ENABLE (CLASS_CSR_BASE_ADDR + 0x294) -+ -+#define CLASS_TPID0_TPID1 (CLASS_CSR_BASE_ADDR + 0x298) -+#define CLASS_TPID2 (CLASS_CSR_BASE_ADDR + 0x29c) -+ -+#define CLASS_L4_CHKSUM_ADDR (CLASS_CSR_BASE_ADDR + 0x2a0) -+ -+#define CLASS_PE0_DEBUG (CLASS_CSR_BASE_ADDR + 0x2a4) -+#define CLASS_PE1_DEBUG (CLASS_CSR_BASE_ADDR + 0x2a8) -+#define CLASS_PE2_DEBUG (CLASS_CSR_BASE_ADDR + 0x2ac) -+#define CLASS_PE3_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b0) -+#define CLASS_PE4_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b4) -+#define CLASS_PE5_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b8) -+ -+#define CLASS_STATE (CLASS_CSR_BASE_ADDR + 0x2bc) -+ -+/* CLASS defines */ -+#define CLASS_PBUF_SIZE 0x100 /* Fixed by hardware */ -+#define CLASS_PBUF_HEADER_OFFSET 0x80 /* Can be configured */ -+ -+/* Can be configured */ -+#define CLASS_PBUF0_BASE_ADDR 0x000 -+/* Can be configured */ -+#define CLASS_PBUF1_BASE_ADDR (CLASS_PBUF0_BASE_ADDR + CLASS_PBUF_SIZE) -+/* Can be configured */ -+#define CLASS_PBUF2_BASE_ADDR (CLASS_PBUF1_BASE_ADDR + CLASS_PBUF_SIZE) -+/* Can be configured */ -+#define CLASS_PBUF3_BASE_ADDR (CLASS_PBUF2_BASE_ADDR + CLASS_PBUF_SIZE) -+ -+#define CLASS_PBUF0_HEADER_BASE_ADDR (CLASS_PBUF0_BASE_ADDR + \ -+ CLASS_PBUF_HEADER_OFFSET) -+#define CLASS_PBUF1_HEADER_BASE_ADDR (CLASS_PBUF1_BASE_ADDR + \ -+ CLASS_PBUF_HEADER_OFFSET) -+#define CLASS_PBUF2_HEADER_BASE_ADDR (CLASS_PBUF2_BASE_ADDR + \ -+ CLASS_PBUF_HEADER_OFFSET) -+#define CLASS_PBUF3_HEADER_BASE_ADDR (CLASS_PBUF3_BASE_ADDR + \ -+ CLASS_PBUF_HEADER_OFFSET) -+ -+#define CLASS_PE0_RO_DM_ADDR0_VAL ((CLASS_PBUF1_BASE_ADDR << 16) | \ -+ CLASS_PBUF0_BASE_ADDR) -+#define CLASS_PE0_RO_DM_ADDR1_VAL ((CLASS_PBUF3_BASE_ADDR << 16) | \ -+ CLASS_PBUF2_BASE_ADDR) -+ -+#define CLASS_PE0_QB_DM_ADDR0_VAL ((CLASS_PBUF1_HEADER_BASE_ADDR << 16) |\ -+ CLASS_PBUF0_HEADER_BASE_ADDR) -+#define CLASS_PE0_QB_DM_ADDR1_VAL ((CLASS_PBUF3_HEADER_BASE_ADDR << 16) |\ -+ CLASS_PBUF2_HEADER_BASE_ADDR) -+ -+#define CLASS_ROUTE_SIZE 128 -+#define CLASS_MAX_ROUTE_SIZE 256 -+#define CLASS_ROUTE_HASH_BITS 20 -+#define CLASS_ROUTE_HASH_MASK (BIT(CLASS_ROUTE_HASH_BITS) - 1) -+ -+/* Can be configured */ -+#define CLASS_ROUTE0_BASE_ADDR 0x400 -+/* Can be configured */ -+#define CLASS_ROUTE1_BASE_ADDR (CLASS_ROUTE0_BASE_ADDR + CLASS_ROUTE_SIZE) -+/* Can be configured */ -+#define CLASS_ROUTE2_BASE_ADDR (CLASS_ROUTE1_BASE_ADDR + CLASS_ROUTE_SIZE) -+/* Can be configured */ -+#define CLASS_ROUTE3_BASE_ADDR (CLASS_ROUTE2_BASE_ADDR + CLASS_ROUTE_SIZE) -+ -+#define CLASS_SA_SIZE 128 -+#define CLASS_IPSEC_SA0_BASE_ADDR 0x600 -+/* not used */ -+#define CLASS_IPSEC_SA1_BASE_ADDR (CLASS_IPSEC_SA0_BASE_ADDR + CLASS_SA_SIZE) -+/* not used */ -+#define CLASS_IPSEC_SA2_BASE_ADDR (CLASS_IPSEC_SA1_BASE_ADDR + CLASS_SA_SIZE) -+/* not used */ -+#define CLASS_IPSEC_SA3_BASE_ADDR (CLASS_IPSEC_SA2_BASE_ADDR + CLASS_SA_SIZE) -+ -+/* generic purpose free dmem buffer, last portion of 2K dmem pbuf */ -+#define CLASS_GP_DMEM_BUF_SIZE (2048 - (CLASS_PBUF_SIZE * 4) - \ -+ (CLASS_ROUTE_SIZE * 4) - (CLASS_SA_SIZE)) -+#define CLASS_GP_DMEM_BUF ((void *)(CLASS_IPSEC_SA0_BASE_ADDR + \ -+ CLASS_SA_SIZE)) -+ -+#define TWO_LEVEL_ROUTE BIT(0) -+#define PHYNO_IN_HASH BIT(1) -+#define HW_ROUTE_FETCH BIT(3) -+#define HW_BRIDGE_FETCH BIT(5) -+#define IP_ALIGNED BIT(6) -+#define ARC_HIT_CHECK_EN BIT(7) -+#define CLASS_TOE BIT(11) -+#define HASH_NORMAL (0 << 12) -+#define HASH_CRC_PORT BIT(12) -+#define HASH_CRC_IP (2 << 12) -+#define HASH_CRC_PORT_IP (3 << 12) -+#define QB2BUS_LE BIT(15) -+ -+#define TCP_CHKSUM_DROP BIT(0) -+#define UDP_CHKSUM_DROP BIT(1) -+#define IPV4_CHKSUM_DROP BIT(9) -+ -+/*CLASS_HIF_PARSE bits*/ -+#define HIF_PKT_CLASS_EN BIT(0) -+#define HIF_PKT_OFFSET(ofst) (((ofst) & 0xF) << 1) -+ -+struct class_cfg { -+ u32 toe_mode; -+ unsigned long route_table_baseaddr; -+ u32 route_table_hash_bits; -+ u32 pe_sys_clk_ratio; -+ u32 resume; -+}; -+ -+#endif /* _CLASS_CSR_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/emac_mtip.h -@@ -0,0 +1,242 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _EMAC_H_ -+#define _EMAC_H_ -+ -+#include -+ -+#define EMAC_IEVENT_REG 0x004 -+#define EMAC_IMASK_REG 0x008 -+#define EMAC_R_DES_ACTIVE_REG 0x010 -+#define EMAC_X_DES_ACTIVE_REG 0x014 -+#define EMAC_ECNTRL_REG 0x024 -+#define EMAC_MII_DATA_REG 0x040 -+#define EMAC_MII_CTRL_REG 0x044 -+#define EMAC_MIB_CTRL_STS_REG 0x064 -+#define EMAC_RCNTRL_REG 0x084 -+#define EMAC_TCNTRL_REG 0x0C4 -+#define EMAC_PHY_ADDR_LOW 0x0E4 -+#define EMAC_PHY_ADDR_HIGH 0x0E8 -+#define EMAC_GAUR 0x120 -+#define EMAC_GALR 0x124 -+#define EMAC_TFWR_STR_FWD 0x144 -+#define EMAC_RX_SECTION_FULL 0x190 -+#define EMAC_RX_SECTION_EMPTY 0x194 -+#define EMAC_TX_SECTION_EMPTY 0x1A0 -+#define EMAC_TRUNC_FL 0x1B0 -+ -+#define RMON_T_DROP 0x200 /* Count of frames not cntd correctly */ -+#define RMON_T_PACKETS 0x204 /* RMON TX packet count */ -+#define RMON_T_BC_PKT 0x208 /* RMON TX broadcast pkts */ -+#define RMON_T_MC_PKT 0x20c /* RMON TX multicast pkts */ -+#define RMON_T_CRC_ALIGN 0x210 /* RMON TX pkts with CRC align err */ -+#define RMON_T_UNDERSIZE 0x214 /* RMON TX pkts < 64 bytes, good CRC */ -+#define RMON_T_OVERSIZE 0x218 /* RMON TX pkts > MAX_FL bytes good CRC */ -+#define RMON_T_FRAG 0x21c /* RMON TX pkts < 64 bytes, bad CRC */ -+#define RMON_T_JAB 0x220 /* RMON TX pkts > MAX_FL bytes, bad CRC */ -+#define RMON_T_COL 0x224 /* RMON TX collision count */ -+#define RMON_T_P64 0x228 /* RMON TX 64 byte pkts */ -+#define RMON_T_P65TO127 0x22c /* RMON TX 65 to 127 byte pkts */ -+#define RMON_T_P128TO255 0x230 /* RMON TX 128 to 255 byte pkts */ -+#define RMON_T_P256TO511 0x234 /* RMON TX 256 to 511 byte pkts */ -+#define RMON_T_P512TO1023 0x238 /* RMON TX 512 to 1023 byte pkts */ -+#define RMON_T_P1024TO2047 0x23c /* RMON TX 1024 to 2047 byte pkts */ -+#define RMON_T_P_GTE2048 0x240 /* RMON TX pkts > 2048 bytes */ -+#define RMON_T_OCTETS 0x244 /* RMON TX octets */ -+#define IEEE_T_DROP 0x248 /* Count of frames not counted crtly */ -+#define IEEE_T_FRAME_OK 0x24c /* Frames tx'd OK */ -+#define IEEE_T_1COL 0x250 /* Frames tx'd with single collision */ -+#define IEEE_T_MCOL 0x254 /* Frames tx'd with multiple collision */ -+#define IEEE_T_DEF 0x258 /* Frames tx'd after deferral delay */ -+#define IEEE_T_LCOL 0x25c /* Frames tx'd with late collision */ -+#define IEEE_T_EXCOL 0x260 /* Frames tx'd with excesv collisions */ -+#define IEEE_T_MACERR 0x264 /* Frames tx'd with TX FIFO underrun */ -+#define IEEE_T_CSERR 0x268 /* Frames tx'd with carrier sense err */ -+#define IEEE_T_SQE 0x26c /* Frames tx'd with SQE err */ -+#define IEEE_T_FDXFC 0x270 /* Flow control pause frames tx'd */ -+#define IEEE_T_OCTETS_OK 0x274 /* Octet count for frames tx'd w/o err */ -+#define RMON_R_PACKETS 0x284 /* RMON RX packet count */ -+#define RMON_R_BC_PKT 0x288 /* RMON RX broadcast pkts */ -+#define RMON_R_MC_PKT 0x28c /* RMON RX multicast pkts */ -+#define RMON_R_CRC_ALIGN 0x290 /* RMON RX pkts with CRC alignment err */ -+#define RMON_R_UNDERSIZE 0x294 /* RMON RX pkts < 64 bytes, good CRC */ -+#define RMON_R_OVERSIZE 0x298 /* RMON RX pkts > MAX_FL bytes good CRC */ -+#define RMON_R_FRAG 0x29c /* RMON RX pkts < 64 bytes, bad CRC */ -+#define RMON_R_JAB 0x2a0 /* RMON RX pkts > MAX_FL bytes, bad CRC */ -+#define RMON_R_RESVD_O 0x2a4 /* Reserved */ -+#define RMON_R_P64 0x2a8 /* RMON RX 64 byte pkts */ -+#define RMON_R_P65TO127 0x2ac /* RMON RX 65 to 127 byte pkts */ -+#define RMON_R_P128TO255 0x2b0 /* RMON RX 128 to 255 byte pkts */ -+#define RMON_R_P256TO511 0x2b4 /* RMON RX 256 to 511 byte pkts */ -+#define RMON_R_P512TO1023 0x2b8 /* RMON RX 512 to 1023 byte pkts */ -+#define RMON_R_P1024TO2047 0x2bc /* RMON RX 1024 to 2047 byte pkts */ -+#define RMON_R_P_GTE2048 0x2c0 /* RMON RX pkts > 2048 bytes */ -+#define RMON_R_OCTETS 0x2c4 /* RMON RX octets */ -+#define IEEE_R_DROP 0x2c8 /* Count frames not counted correctly */ -+#define IEEE_R_FRAME_OK 0x2cc /* Frames rx'd OK */ -+#define IEEE_R_CRC 0x2d0 /* Frames rx'd with CRC err */ -+#define IEEE_R_ALIGN 0x2d4 /* Frames rx'd with alignment err */ -+#define IEEE_R_MACERR 0x2d8 /* Receive FIFO overflow count */ -+#define IEEE_R_FDXFC 0x2dc /* Flow control pause frames rx'd */ -+#define IEEE_R_OCTETS_OK 0x2e0 /* Octet cnt for frames rx'd w/o err */ -+ -+#define EMAC_SMAC_0_0 0x500 /*Supplemental MAC Address 0 (RW).*/ -+#define EMAC_SMAC_0_1 0x504 /*Supplemental MAC Address 0 (RW).*/ -+ -+/* GEMAC definitions and settings */ -+ -+#define EMAC_PORT_0 0 -+#define EMAC_PORT_1 1 -+ -+/* GEMAC Bit definitions */ -+#define EMAC_IEVENT_HBERR 0x80000000 -+#define EMAC_IEVENT_BABR 0x40000000 -+#define EMAC_IEVENT_BABT 0x20000000 -+#define EMAC_IEVENT_GRA 0x10000000 -+#define EMAC_IEVENT_TXF 0x08000000 -+#define EMAC_IEVENT_TXB 0x04000000 -+#define EMAC_IEVENT_RXF 0x02000000 -+#define EMAC_IEVENT_RXB 0x01000000 -+#define EMAC_IEVENT_MII 0x00800000 -+#define EMAC_IEVENT_EBERR 0x00400000 -+#define EMAC_IEVENT_LC 0x00200000 -+#define EMAC_IEVENT_RL 0x00100000 -+#define EMAC_IEVENT_UN 0x00080000 -+ -+#define EMAC_IMASK_HBERR 0x80000000 -+#define EMAC_IMASK_BABR 0x40000000 -+#define EMAC_IMASKT_BABT 0x20000000 -+#define EMAC_IMASK_GRA 0x10000000 -+#define EMAC_IMASKT_TXF 0x08000000 -+#define EMAC_IMASK_TXB 0x04000000 -+#define EMAC_IMASKT_RXF 0x02000000 -+#define EMAC_IMASK_RXB 0x01000000 -+#define EMAC_IMASK_MII 0x00800000 -+#define EMAC_IMASK_EBERR 0x00400000 -+#define EMAC_IMASK_LC 0x00200000 -+#define EMAC_IMASKT_RL 0x00100000 -+#define EMAC_IMASK_UN 0x00080000 -+ -+#define EMAC_RCNTRL_MAX_FL_SHIFT 16 -+#define EMAC_RCNTRL_LOOP 0x00000001 -+#define EMAC_RCNTRL_DRT 0x00000002 -+#define EMAC_RCNTRL_MII_MODE 0x00000004 -+#define EMAC_RCNTRL_PROM 0x00000008 -+#define EMAC_RCNTRL_BC_REJ 0x00000010 -+#define EMAC_RCNTRL_FCE 0x00000020 -+#define EMAC_RCNTRL_RGMII 0x00000040 -+#define EMAC_RCNTRL_SGMII 0x00000080 -+#define EMAC_RCNTRL_RMII 0x00000100 -+#define EMAC_RCNTRL_RMII_10T 0x00000200 -+#define EMAC_RCNTRL_CRC_FWD 0x00004000 -+ -+#define EMAC_TCNTRL_GTS 0x00000001 -+#define EMAC_TCNTRL_HBC 0x00000002 -+#define EMAC_TCNTRL_FDEN 0x00000004 -+#define EMAC_TCNTRL_TFC_PAUSE 0x00000008 -+#define EMAC_TCNTRL_RFC_PAUSE 0x00000010 -+ -+#define EMAC_ECNTRL_RESET 0x00000001 /* reset the EMAC */ -+#define EMAC_ECNTRL_ETHER_EN 0x00000002 /* enable the EMAC */ -+#define EMAC_ECNTRL_MAGIC_ENA 0x00000004 -+#define EMAC_ECNTRL_SLEEP 0x00000008 -+#define EMAC_ECNTRL_SPEED 0x00000020 -+#define EMAC_ECNTRL_DBSWAP 0x00000100 -+ -+#define EMAC_X_WMRK_STRFWD 0x00000100 -+ -+#define EMAC_X_DES_ACTIVE_TDAR 0x01000000 -+#define EMAC_R_DES_ACTIVE_RDAR 0x01000000 -+ -+#define EMAC_RX_SECTION_EMPTY_V 0x00010006 -+/* -+ * The possible operating speeds of the MAC, currently supporting 10, 100 and -+ * 1000Mb modes. -+ */ -+enum mac_speed {SPEED_10M, SPEED_100M, SPEED_1000M, SPEED_1000M_PCS}; -+ -+/* MII-related definitios */ -+#define EMAC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */ -+#define EMAC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */ -+#define EMAC_MII_DATA_OP_CL45_RD 0x30000000 /* Perform a read operation */ -+#define EMAC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */ -+#define EMAC_MII_DATA_OP_CL45_WR 0x10000000 /* Perform a write operation */ -+#define EMAC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */ -+#define EMAC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */ -+#define EMAC_MII_DATA_TA 0x00020000 /* Turnaround */ -+#define EMAC_MII_DATA_DATAMSK 0x0000ffff /* PHY data field */ -+ -+#define EMAC_MII_DATA_RA_SHIFT 18 /* MII Register address bits */ -+#define EMAC_MII_DATA_RA_MASK 0x1F /* MII Register address mask */ -+#define EMAC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */ -+#define EMAC_MII_DATA_PA_MASK 0x1F /* MII PHY address mask */ -+ -+#define EMAC_MII_DATA_RA(v) (((v) & EMAC_MII_DATA_RA_MASK) << \ -+ EMAC_MII_DATA_RA_SHIFT) -+#define EMAC_MII_DATA_PA(v) (((v) & EMAC_MII_DATA_RA_MASK) << \ -+ EMAC_MII_DATA_PA_SHIFT) -+#define EMAC_MII_DATA(v) ((v) & 0xffff) -+ -+#define EMAC_MII_SPEED_SHIFT 1 -+#define EMAC_HOLDTIME_SHIFT 8 -+#define EMAC_HOLDTIME_MASK 0x7 -+#define EMAC_HOLDTIME(v) (((v) & EMAC_HOLDTIME_MASK) << \ -+ EMAC_HOLDTIME_SHIFT) -+ -+/* -+ * The Address organisation for the MAC device. All addresses are split into -+ * two 32-bit register fields. The first one (bottom) is the lower 32-bits of -+ * the address and the other field are the high order bits - this may be 16-bits -+ * in the case of MAC addresses, or 32-bits for the hash address. -+ * In terms of memory storage, the first item (bottom) is assumed to be at a -+ * lower address location than 'top'. i.e. top should be at address location of -+ * 'bottom' + 4 bytes. -+ */ -+struct pfe_mac_addr { -+ u32 bottom; /* Lower 32-bits of address. */ -+ u32 top; /* Upper 32-bits of address. */ -+}; -+ -+/* -+ * The following is the organisation of the address filters section of the MAC -+ * registers. The Cadence MAC contains four possible specific address match -+ * addresses, if an incoming frame corresponds to any one of these four -+ * addresses then the frame will be copied to memory. -+ * It is not necessary for all four of the address match registers to be -+ * programmed, this is application dependent. -+ */ -+struct spec_addr { -+ struct pfe_mac_addr one; /* Specific address register 1. */ -+ struct pfe_mac_addr two; /* Specific address register 2. */ -+ struct pfe_mac_addr three; /* Specific address register 3. */ -+ struct pfe_mac_addr four; /* Specific address register 4. */ -+}; -+ -+struct gemac_cfg { -+ u32 mode; -+ u32 speed; -+ u32 duplex; -+}; -+ -+/* EMAC Hash size */ -+#define EMAC_HASH_REG_BITS 64 -+ -+#define EMAC_SPEC_ADDR_MAX 4 -+ -+#endif /* _EMAC_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/gpi.h -@@ -0,0 +1,86 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _GPI_H_ -+#define _GPI_H_ -+ -+#define GPI_VERSION 0x00 -+#define GPI_CTRL 0x04 -+#define GPI_RX_CONFIG 0x08 -+#define GPI_HDR_SIZE 0x0c -+#define GPI_BUF_SIZE 0x10 -+#define GPI_LMEM_ALLOC_ADDR 0x14 -+#define GPI_LMEM_FREE_ADDR 0x18 -+#define GPI_DDR_ALLOC_ADDR 0x1c -+#define GPI_DDR_FREE_ADDR 0x20 -+#define GPI_CLASS_ADDR 0x24 -+#define GPI_DRX_FIFO 0x28 -+#define GPI_TRX_FIFO 0x2c -+#define GPI_INQ_PKTPTR 0x30 -+#define GPI_DDR_DATA_OFFSET 0x34 -+#define GPI_LMEM_DATA_OFFSET 0x38 -+#define GPI_TMLF_TX 0x4c -+#define GPI_DTX_ASEQ 0x50 -+#define GPI_FIFO_STATUS 0x54 -+#define GPI_FIFO_DEBUG 0x58 -+#define GPI_TX_PAUSE_TIME 0x5c -+#define GPI_LMEM_SEC_BUF_DATA_OFFSET 0x60 -+#define GPI_DDR_SEC_BUF_DATA_OFFSET 0x64 -+#define GPI_TOE_CHKSUM_EN 0x68 -+#define GPI_OVERRUN_DROPCNT 0x6c -+#define GPI_CSR_MTIP_PAUSE_REG 0x74 -+#define GPI_CSR_MTIP_PAUSE_QUANTUM 0x78 -+#define GPI_CSR_RX_CNT 0x7c -+#define GPI_CSR_TX_CNT 0x80 -+#define GPI_CSR_DEBUG1 0x84 -+#define GPI_CSR_DEBUG2 0x88 -+ -+struct gpi_cfg { -+ u32 lmem_rtry_cnt; -+ u32 tmlf_txthres; -+ u32 aseq_len; -+ u32 mtip_pause_reg; -+}; -+ -+/* GPI commons defines */ -+#define GPI_LMEM_BUF_EN 0x1 -+#define GPI_DDR_BUF_EN 0x1 -+ -+/* EGPI 1 defines */ -+#define EGPI1_LMEM_RTRY_CNT 0x40 -+#define EGPI1_TMLF_TXTHRES 0xBC -+#define EGPI1_ASEQ_LEN 0x50 -+ -+/* EGPI 2 defines */ -+#define EGPI2_LMEM_RTRY_CNT 0x40 -+#define EGPI2_TMLF_TXTHRES 0xBC -+#define EGPI2_ASEQ_LEN 0x40 -+ -+/* EGPI 3 defines */ -+#define EGPI3_LMEM_RTRY_CNT 0x40 -+#define EGPI3_TMLF_TXTHRES 0xBC -+#define EGPI3_ASEQ_LEN 0x40 -+ -+/* HGPI defines */ -+#define HGPI_LMEM_RTRY_CNT 0x40 -+#define HGPI_TMLF_TXTHRES 0xBC -+#define HGPI_ASEQ_LEN 0x40 -+ -+#define EGPI_PAUSE_TIME 0x000007D0 -+#define EGPI_PAUSE_ENABLE 0x40000000 -+#endif /* _GPI_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/hif.h -@@ -0,0 +1,100 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _HIF_H_ -+#define _HIF_H_ -+ -+/* @file hif.h. -+ * hif - PFE hif block control and status register. -+ * Mapped on CBUS and accessible from all PE's and ARM. -+ */ -+#define HIF_VERSION (HIF_BASE_ADDR + 0x00) -+#define HIF_TX_CTRL (HIF_BASE_ADDR + 0x04) -+#define HIF_TX_CURR_BD_ADDR (HIF_BASE_ADDR + 0x08) -+#define HIF_TX_ALLOC (HIF_BASE_ADDR + 0x0c) -+#define HIF_TX_BDP_ADDR (HIF_BASE_ADDR + 0x10) -+#define HIF_TX_STATUS (HIF_BASE_ADDR + 0x14) -+#define HIF_RX_CTRL (HIF_BASE_ADDR + 0x20) -+#define HIF_RX_BDP_ADDR (HIF_BASE_ADDR + 0x24) -+#define HIF_RX_STATUS (HIF_BASE_ADDR + 0x30) -+#define HIF_INT_SRC (HIF_BASE_ADDR + 0x34) -+#define HIF_INT_ENABLE (HIF_BASE_ADDR + 0x38) -+#define HIF_POLL_CTRL (HIF_BASE_ADDR + 0x3c) -+#define HIF_RX_CURR_BD_ADDR (HIF_BASE_ADDR + 0x40) -+#define HIF_RX_ALLOC (HIF_BASE_ADDR + 0x44) -+#define HIF_TX_DMA_STATUS (HIF_BASE_ADDR + 0x48) -+#define HIF_RX_DMA_STATUS (HIF_BASE_ADDR + 0x4c) -+#define HIF_INT_COAL (HIF_BASE_ADDR + 0x50) -+ -+/* HIF_INT_SRC/ HIF_INT_ENABLE control bits */ -+#define HIF_INT BIT(0) -+#define HIF_RXBD_INT BIT(1) -+#define HIF_RXPKT_INT BIT(2) -+#define HIF_TXBD_INT BIT(3) -+#define HIF_TXPKT_INT BIT(4) -+ -+/* HIF_TX_CTRL bits */ -+#define HIF_CTRL_DMA_EN BIT(0) -+#define HIF_CTRL_BDP_POLL_CTRL_EN BIT(1) -+#define HIF_CTRL_BDP_CH_START_WSTB BIT(2) -+ -+/* HIF_RX_STATUS bits */ -+#define BDP_CSR_RX_DMA_ACTV BIT(16) -+ -+/* HIF_INT_ENABLE bits */ -+#define HIF_INT_EN BIT(0) -+#define HIF_RXBD_INT_EN BIT(1) -+#define HIF_RXPKT_INT_EN BIT(2) -+#define HIF_TXBD_INT_EN BIT(3) -+#define HIF_TXPKT_INT_EN BIT(4) -+ -+/* HIF_POLL_CTRL bits*/ -+#define HIF_RX_POLL_CTRL_CYCLE 0x0400 -+#define HIF_TX_POLL_CTRL_CYCLE 0x0400 -+ -+/* HIF_INT_COAL bits*/ -+#define HIF_INT_COAL_ENABLE BIT(31) -+ -+/* Buffer descriptor control bits */ -+#define BD_CTRL_BUFLEN_MASK 0x3fff -+#define BD_BUF_LEN(x) ((x) & BD_CTRL_BUFLEN_MASK) -+#define BD_CTRL_CBD_INT_EN BIT(16) -+#define BD_CTRL_PKT_INT_EN BIT(17) -+#define BD_CTRL_LIFM BIT(18) -+#define BD_CTRL_LAST_BD BIT(19) -+#define BD_CTRL_DIR BIT(20) -+#define BD_CTRL_LMEM_CPY BIT(21) /* Valid only for HIF_NOCPY */ -+#define BD_CTRL_PKT_XFER BIT(24) -+#define BD_CTRL_DESC_EN BIT(31) -+#define BD_CTRL_PARSE_DISABLE BIT(25) -+#define BD_CTRL_BRFETCH_DISABLE BIT(26) -+#define BD_CTRL_RTFETCH_DISABLE BIT(27) -+ -+/* Buffer descriptor status bits*/ -+#define BD_STATUS_CONN_ID(x) ((x) & 0xffff) -+#define BD_STATUS_DIR_PROC_ID BIT(16) -+#define BD_STATUS_CONN_ID_EN BIT(17) -+#define BD_STATUS_PE2PROC_ID(x) (((x) & 7) << 18) -+#define BD_STATUS_LE_DATA BIT(21) -+#define BD_STATUS_CHKSUM_EN BIT(22) -+ -+/* HIF Buffer descriptor status bits */ -+#define DIR_PROC_ID BIT(16) -+#define PROC_ID(id) ((id) << 18) -+ -+#endif /* _HIF_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/hif_nocpy.h -@@ -0,0 +1,50 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _HIF_NOCPY_H_ -+#define _HIF_NOCPY_H_ -+ -+#define HIF_NOCPY_VERSION (HIF_NOCPY_BASE_ADDR + 0x00) -+#define HIF_NOCPY_TX_CTRL (HIF_NOCPY_BASE_ADDR + 0x04) -+#define HIF_NOCPY_TX_CURR_BD_ADDR (HIF_NOCPY_BASE_ADDR + 0x08) -+#define HIF_NOCPY_TX_ALLOC (HIF_NOCPY_BASE_ADDR + 0x0c) -+#define HIF_NOCPY_TX_BDP_ADDR (HIF_NOCPY_BASE_ADDR + 0x10) -+#define HIF_NOCPY_TX_STATUS (HIF_NOCPY_BASE_ADDR + 0x14) -+#define HIF_NOCPY_RX_CTRL (HIF_NOCPY_BASE_ADDR + 0x20) -+#define HIF_NOCPY_RX_BDP_ADDR (HIF_NOCPY_BASE_ADDR + 0x24) -+#define HIF_NOCPY_RX_STATUS (HIF_NOCPY_BASE_ADDR + 0x30) -+#define HIF_NOCPY_INT_SRC (HIF_NOCPY_BASE_ADDR + 0x34) -+#define HIF_NOCPY_INT_ENABLE (HIF_NOCPY_BASE_ADDR + 0x38) -+#define HIF_NOCPY_POLL_CTRL (HIF_NOCPY_BASE_ADDR + 0x3c) -+#define HIF_NOCPY_RX_CURR_BD_ADDR (HIF_NOCPY_BASE_ADDR + 0x40) -+#define HIF_NOCPY_RX_ALLOC (HIF_NOCPY_BASE_ADDR + 0x44) -+#define HIF_NOCPY_TX_DMA_STATUS (HIF_NOCPY_BASE_ADDR + 0x48) -+#define HIF_NOCPY_RX_DMA_STATUS (HIF_NOCPY_BASE_ADDR + 0x4c) -+#define HIF_NOCPY_RX_INQ0_PKTPTR (HIF_NOCPY_BASE_ADDR + 0x50) -+#define HIF_NOCPY_RX_INQ1_PKTPTR (HIF_NOCPY_BASE_ADDR + 0x54) -+#define HIF_NOCPY_TX_PORT_NO (HIF_NOCPY_BASE_ADDR + 0x60) -+#define HIF_NOCPY_LMEM_ALLOC_ADDR (HIF_NOCPY_BASE_ADDR + 0x64) -+#define HIF_NOCPY_CLASS_ADDR (HIF_NOCPY_BASE_ADDR + 0x68) -+#define HIF_NOCPY_TMU_PORT0_ADDR (HIF_NOCPY_BASE_ADDR + 0x70) -+#define HIF_NOCPY_TMU_PORT1_ADDR (HIF_NOCPY_BASE_ADDR + 0x74) -+#define HIF_NOCPY_TMU_PORT2_ADDR (HIF_NOCPY_BASE_ADDR + 0x7c) -+#define HIF_NOCPY_TMU_PORT3_ADDR (HIF_NOCPY_BASE_ADDR + 0x80) -+#define HIF_NOCPY_TMU_PORT4_ADDR (HIF_NOCPY_BASE_ADDR + 0x84) -+#define HIF_NOCPY_INT_COAL (HIF_NOCPY_BASE_ADDR + 0x90) -+ -+#endif /* _HIF_NOCPY_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/tmu_csr.h -@@ -0,0 +1,168 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _TMU_CSR_H_ -+#define _TMU_CSR_H_ -+ -+#define TMU_VERSION (TMU_CSR_BASE_ADDR + 0x000) -+#define TMU_INQ_WATERMARK (TMU_CSR_BASE_ADDR + 0x004) -+#define TMU_PHY_INQ_PKTPTR (TMU_CSR_BASE_ADDR + 0x008) -+#define TMU_PHY_INQ_PKTINFO (TMU_CSR_BASE_ADDR + 0x00c) -+#define TMU_PHY_INQ_FIFO_CNT (TMU_CSR_BASE_ADDR + 0x010) -+#define TMU_SYS_GENERIC_CONTROL (TMU_CSR_BASE_ADDR + 0x014) -+#define TMU_SYS_GENERIC_STATUS (TMU_CSR_BASE_ADDR + 0x018) -+#define TMU_SYS_GEN_CON0 (TMU_CSR_BASE_ADDR + 0x01c) -+#define TMU_SYS_GEN_CON1 (TMU_CSR_BASE_ADDR + 0x020) -+#define TMU_SYS_GEN_CON2 (TMU_CSR_BASE_ADDR + 0x024) -+#define TMU_SYS_GEN_CON3 (TMU_CSR_BASE_ADDR + 0x028) -+#define TMU_SYS_GEN_CON4 (TMU_CSR_BASE_ADDR + 0x02c) -+#define TMU_TEQ_DISABLE_DROPCHK (TMU_CSR_BASE_ADDR + 0x030) -+#define TMU_TEQ_CTRL (TMU_CSR_BASE_ADDR + 0x034) -+#define TMU_TEQ_QCFG (TMU_CSR_BASE_ADDR + 0x038) -+#define TMU_TEQ_DROP_STAT (TMU_CSR_BASE_ADDR + 0x03c) -+#define TMU_TEQ_QAVG (TMU_CSR_BASE_ADDR + 0x040) -+#define TMU_TEQ_WREG_PROB (TMU_CSR_BASE_ADDR + 0x044) -+#define TMU_TEQ_TRANS_STAT (TMU_CSR_BASE_ADDR + 0x048) -+#define TMU_TEQ_HW_PROB_CFG0 (TMU_CSR_BASE_ADDR + 0x04c) -+#define TMU_TEQ_HW_PROB_CFG1 (TMU_CSR_BASE_ADDR + 0x050) -+#define TMU_TEQ_HW_PROB_CFG2 (TMU_CSR_BASE_ADDR + 0x054) -+#define TMU_TEQ_HW_PROB_CFG3 (TMU_CSR_BASE_ADDR + 0x058) -+#define TMU_TEQ_HW_PROB_CFG4 (TMU_CSR_BASE_ADDR + 0x05c) -+#define TMU_TEQ_HW_PROB_CFG5 (TMU_CSR_BASE_ADDR + 0x060) -+#define TMU_TEQ_HW_PROB_CFG6 (TMU_CSR_BASE_ADDR + 0x064) -+#define TMU_TEQ_HW_PROB_CFG7 (TMU_CSR_BASE_ADDR + 0x068) -+#define TMU_TEQ_HW_PROB_CFG8 (TMU_CSR_BASE_ADDR + 0x06c) -+#define TMU_TEQ_HW_PROB_CFG9 (TMU_CSR_BASE_ADDR + 0x070) -+#define TMU_TEQ_HW_PROB_CFG10 (TMU_CSR_BASE_ADDR + 0x074) -+#define TMU_TEQ_HW_PROB_CFG11 (TMU_CSR_BASE_ADDR + 0x078) -+#define TMU_TEQ_HW_PROB_CFG12 (TMU_CSR_BASE_ADDR + 0x07c) -+#define TMU_TEQ_HW_PROB_CFG13 (TMU_CSR_BASE_ADDR + 0x080) -+#define TMU_TEQ_HW_PROB_CFG14 (TMU_CSR_BASE_ADDR + 0x084) -+#define TMU_TEQ_HW_PROB_CFG15 (TMU_CSR_BASE_ADDR + 0x088) -+#define TMU_TEQ_HW_PROB_CFG16 (TMU_CSR_BASE_ADDR + 0x08c) -+#define TMU_TEQ_HW_PROB_CFG17 (TMU_CSR_BASE_ADDR + 0x090) -+#define TMU_TEQ_HW_PROB_CFG18 (TMU_CSR_BASE_ADDR + 0x094) -+#define TMU_TEQ_HW_PROB_CFG19 (TMU_CSR_BASE_ADDR + 0x098) -+#define TMU_TEQ_HW_PROB_CFG20 (TMU_CSR_BASE_ADDR + 0x09c) -+#define TMU_TEQ_HW_PROB_CFG21 (TMU_CSR_BASE_ADDR + 0x0a0) -+#define TMU_TEQ_HW_PROB_CFG22 (TMU_CSR_BASE_ADDR + 0x0a4) -+#define TMU_TEQ_HW_PROB_CFG23 (TMU_CSR_BASE_ADDR + 0x0a8) -+#define TMU_TEQ_HW_PROB_CFG24 (TMU_CSR_BASE_ADDR + 0x0ac) -+#define TMU_TEQ_HW_PROB_CFG25 (TMU_CSR_BASE_ADDR + 0x0b0) -+#define TMU_TDQ_IIFG_CFG (TMU_CSR_BASE_ADDR + 0x0b4) -+/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. -+ * This is a global Enable for all schedulers in PHY0 -+ */ -+#define TMU_TDQ0_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x0b8) -+ -+#define TMU_LLM_CTRL (TMU_CSR_BASE_ADDR + 0x0bc) -+#define TMU_LLM_BASE_ADDR (TMU_CSR_BASE_ADDR + 0x0c0) -+#define TMU_LLM_QUE_LEN (TMU_CSR_BASE_ADDR + 0x0c4) -+#define TMU_LLM_QUE_HEADPTR (TMU_CSR_BASE_ADDR + 0x0c8) -+#define TMU_LLM_QUE_TAILPTR (TMU_CSR_BASE_ADDR + 0x0cc) -+#define TMU_LLM_QUE_DROPCNT (TMU_CSR_BASE_ADDR + 0x0d0) -+#define TMU_INT_EN (TMU_CSR_BASE_ADDR + 0x0d4) -+#define TMU_INT_SRC (TMU_CSR_BASE_ADDR + 0x0d8) -+#define TMU_INQ_STAT (TMU_CSR_BASE_ADDR + 0x0dc) -+#define TMU_CTRL (TMU_CSR_BASE_ADDR + 0x0e0) -+ -+/* [31] Mem Access Command. 0 = Internal Memory Read, 1 = Internal memory -+ * Write [27:24] Byte Enables of the Internal memory access [23:0] Address of -+ * the internal memory. This address is used to access both the PM and DM of -+ * all the PE's -+ */ -+#define TMU_MEM_ACCESS_ADDR (TMU_CSR_BASE_ADDR + 0x0e4) -+ -+/* Internal Memory Access Write Data */ -+#define TMU_MEM_ACCESS_WDATA (TMU_CSR_BASE_ADDR + 0x0e8) -+/* Internal Memory Access Read Data. The commands are blocked -+ * at the mem_access only -+ */ -+#define TMU_MEM_ACCESS_RDATA (TMU_CSR_BASE_ADDR + 0x0ec) -+ -+/* [31:0] PHY0 in queue address (must be initialized with one of the -+ * xxx_INQ_PKTPTR cbus addresses) -+ */ -+#define TMU_PHY0_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f0) -+/* [31:0] PHY1 in queue address (must be initialized with one of the -+ * xxx_INQ_PKTPTR cbus addresses) -+ */ -+#define TMU_PHY1_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f4) -+/* [31:0] PHY2 in queue address (must be initialized with one of the -+ * xxx_INQ_PKTPTR cbus addresses) -+ */ -+#define TMU_PHY2_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f8) -+/* [31:0] PHY3 in queue address (must be initialized with one of the -+ * xxx_INQ_PKTPTR cbus addresses) -+ */ -+#define TMU_PHY3_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0fc) -+#define TMU_BMU_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x100) -+#define TMU_TX_CTRL (TMU_CSR_BASE_ADDR + 0x104) -+ -+#define TMU_BUS_ACCESS_WDATA (TMU_CSR_BASE_ADDR + 0x108) -+#define TMU_BUS_ACCESS (TMU_CSR_BASE_ADDR + 0x10c) -+#define TMU_BUS_ACCESS_RDATA (TMU_CSR_BASE_ADDR + 0x110) -+ -+#define TMU_PE_SYS_CLK_RATIO (TMU_CSR_BASE_ADDR + 0x114) -+#define TMU_PE_STATUS (TMU_CSR_BASE_ADDR + 0x118) -+#define TMU_TEQ_MAX_THRESHOLD (TMU_CSR_BASE_ADDR + 0x11c) -+/* [31:0] PHY4 in queue address (must be initialized with one of the -+ * xxx_INQ_PKTPTR cbus addresses) -+ */ -+#define TMU_PHY4_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x134) -+/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. -+ * This is a global Enable for all schedulers in PHY1 -+ */ -+#define TMU_TDQ1_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x138) -+/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. -+ * This is a global Enable for all schedulers in PHY2 -+ */ -+#define TMU_TDQ2_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x13c) -+/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. -+ * This is a global Enable for all schedulers in PHY3 -+ */ -+#define TMU_TDQ3_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x140) -+#define TMU_BMU_BUF_SIZE (TMU_CSR_BASE_ADDR + 0x144) -+/* [31:0] PHY5 in queue address (must be initialized with one of the -+ * xxx_INQ_PKTPTR cbus addresses) -+ */ -+#define TMU_PHY5_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x148) -+ -+#define SW_RESET BIT(0) /* Global software reset */ -+#define INQ_RESET BIT(2) -+#define TEQ_RESET BIT(3) -+#define TDQ_RESET BIT(4) -+#define PE_RESET BIT(5) -+#define MEM_INIT BIT(6) -+#define MEM_INIT_DONE BIT(7) -+#define LLM_INIT BIT(8) -+#define LLM_INIT_DONE BIT(9) -+#define ECC_MEM_INIT_DONE BIT(10) -+ -+struct tmu_cfg { -+ u32 pe_sys_clk_ratio; -+ unsigned long llm_base_addr; -+ u32 llm_queue_len; -+}; -+ -+/* Not HW related for pfe_ctrl / pfe common defines */ -+#define DEFAULT_MAX_QDEPTH 80 -+#define DEFAULT_Q0_QDEPTH 511 /*We keep one large queue for host tx qos */ -+#define DEFAULT_TMU3_QDEPTH 127 -+ -+#endif /* _TMU_CSR_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/include/pfe/cbus/util_csr.h -@@ -0,0 +1,61 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _UTIL_CSR_H_ -+#define _UTIL_CSR_H_ -+ -+#define UTIL_VERSION (UTIL_CSR_BASE_ADDR + 0x000) -+#define UTIL_TX_CTRL (UTIL_CSR_BASE_ADDR + 0x004) -+#define UTIL_INQ_PKTPTR (UTIL_CSR_BASE_ADDR + 0x010) -+ -+#define UTIL_HDR_SIZE (UTIL_CSR_BASE_ADDR + 0x014) -+ -+#define UTIL_PE0_QB_DM_ADDR0 (UTIL_CSR_BASE_ADDR + 0x020) -+#define UTIL_PE0_QB_DM_ADDR1 (UTIL_CSR_BASE_ADDR + 0x024) -+#define UTIL_PE0_RO_DM_ADDR0 (UTIL_CSR_BASE_ADDR + 0x060) -+#define UTIL_PE0_RO_DM_ADDR1 (UTIL_CSR_BASE_ADDR + 0x064) -+ -+#define UTIL_MEM_ACCESS_ADDR (UTIL_CSR_BASE_ADDR + 0x100) -+#define UTIL_MEM_ACCESS_WDATA (UTIL_CSR_BASE_ADDR + 0x104) -+#define UTIL_MEM_ACCESS_RDATA (UTIL_CSR_BASE_ADDR + 0x108) -+ -+#define UTIL_TM_INQ_ADDR (UTIL_CSR_BASE_ADDR + 0x114) -+#define UTIL_PE_STATUS (UTIL_CSR_BASE_ADDR + 0x118) -+ -+#define UTIL_PE_SYS_CLK_RATIO (UTIL_CSR_BASE_ADDR + 0x200) -+#define UTIL_AFULL_THRES (UTIL_CSR_BASE_ADDR + 0x204) -+#define UTIL_GAP_BETWEEN_READS (UTIL_CSR_BASE_ADDR + 0x208) -+#define UTIL_MAX_BUF_CNT (UTIL_CSR_BASE_ADDR + 0x20c) -+#define UTIL_TSQ_FIFO_THRES (UTIL_CSR_BASE_ADDR + 0x210) -+#define UTIL_TSQ_MAX_CNT (UTIL_CSR_BASE_ADDR + 0x214) -+#define UTIL_IRAM_DATA_0 (UTIL_CSR_BASE_ADDR + 0x218) -+#define UTIL_IRAM_DATA_1 (UTIL_CSR_BASE_ADDR + 0x21c) -+#define UTIL_IRAM_DATA_2 (UTIL_CSR_BASE_ADDR + 0x220) -+#define UTIL_IRAM_DATA_3 (UTIL_CSR_BASE_ADDR + 0x224) -+ -+#define UTIL_BUS_ACCESS_ADDR (UTIL_CSR_BASE_ADDR + 0x228) -+#define UTIL_BUS_ACCESS_WDATA (UTIL_CSR_BASE_ADDR + 0x22c) -+#define UTIL_BUS_ACCESS_RDATA (UTIL_CSR_BASE_ADDR + 0x230) -+ -+#define UTIL_INQ_AFULL_THRES (UTIL_CSR_BASE_ADDR + 0x234) -+ -+struct util_cfg { -+ u32 pe_sys_clk_ratio; -+}; -+ -+#endif /* _UTIL_CSR_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/include/pfe/pfe.h -@@ -0,0 +1,372 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _PFE_H_ -+#define _PFE_H_ -+ -+#include "cbus.h" -+ -+#define CLASS_DMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20)) -+/* -+ * Only valid for mem access register interface -+ */ -+#define CLASS_IMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20)) -+#define CLASS_DMEM_SIZE 0x00002000 -+#define CLASS_IMEM_SIZE 0x00008000 -+ -+#define TMU_DMEM_BASE_ADDR(i) (0x00000000 + ((i) << 20)) -+/* -+ * Only valid for mem access register interface -+ */ -+#define TMU_IMEM_BASE_ADDR(i) (0x00000000 + ((i) << 20)) -+#define TMU_DMEM_SIZE 0x00000800 -+#define TMU_IMEM_SIZE 0x00002000 -+ -+#define UTIL_DMEM_BASE_ADDR 0x00000000 -+#define UTIL_DMEM_SIZE 0x00002000 -+ -+#define PE_LMEM_BASE_ADDR 0xc3010000 -+#define PE_LMEM_SIZE 0x8000 -+#define PE_LMEM_END (PE_LMEM_BASE_ADDR + PE_LMEM_SIZE) -+ -+#define DMEM_BASE_ADDR 0x00000000 -+#define DMEM_SIZE 0x2000 /* TMU has less... */ -+#define DMEM_END (DMEM_BASE_ADDR + DMEM_SIZE) -+ -+#define PMEM_BASE_ADDR 0x00010000 -+#define PMEM_SIZE 0x8000 /* TMU has less... */ -+#define PMEM_END (PMEM_BASE_ADDR + PMEM_SIZE) -+ -+/* These check memory ranges from PE point of view/memory map */ -+#define IS_DMEM(addr, len) \ -+ ({ typeof(addr) addr_ = (addr); \ -+ ((unsigned long)(addr_) >= DMEM_BASE_ADDR) && \ -+ (((unsigned long)(addr_) + (len)) <= DMEM_END); }) -+ -+#define IS_PMEM(addr, len) \ -+ ({ typeof(addr) addr_ = (addr); \ -+ ((unsigned long)(addr_) >= PMEM_BASE_ADDR) && \ -+ (((unsigned long)(addr_) + (len)) <= PMEM_END); }) -+ -+#define IS_PE_LMEM(addr, len) \ -+ ({ typeof(addr) addr_ = (addr); \ -+ ((unsigned long)(addr_) >= \ -+ PE_LMEM_BASE_ADDR) && \ -+ (((unsigned long)(addr_) + \ -+ (len)) <= PE_LMEM_END); }) -+ -+#define IS_PFE_LMEM(addr, len) \ -+ ({ typeof(addr) addr_ = (addr); \ -+ ((unsigned long)(addr_) >= \ -+ CBUS_VIRT_TO_PFE(LMEM_BASE_ADDR)) && \ -+ (((unsigned long)(addr_) + (len)) <= \ -+ CBUS_VIRT_TO_PFE(LMEM_END)); }) -+ -+#define __IS_PHYS_DDR(addr, len) \ -+ ({ typeof(addr) addr_ = (addr); \ -+ ((unsigned long)(addr_) >= \ -+ DDR_PHYS_BASE_ADDR) && \ -+ (((unsigned long)(addr_) + (len)) <= \ -+ DDR_PHYS_END); }) -+ -+#define IS_PHYS_DDR(addr, len) __IS_PHYS_DDR(DDR_PFE_TO_PHYS(addr), len) -+ -+/* -+ * If using a run-time virtual address for the cbus base address use this code -+ */ -+extern void *cbus_base_addr; -+extern void *ddr_base_addr; -+extern unsigned long ddr_phys_base_addr; -+extern unsigned int ddr_size; -+ -+#define CBUS_BASE_ADDR cbus_base_addr -+#define DDR_PHYS_BASE_ADDR ddr_phys_base_addr -+#define DDR_BASE_ADDR ddr_base_addr -+#define DDR_SIZE ddr_size -+ -+#define DDR_PHYS_END (DDR_PHYS_BASE_ADDR + DDR_SIZE) -+ -+#define LS1012A_PFE_RESET_WA /* -+ * PFE doesn't have global reset and re-init -+ * should takecare few things to make PFE -+ * functional after reset -+ */ -+#define PFE_CBUS_PHYS_BASE_ADDR 0xc0000000 /* CBUS physical base address -+ * as seen by PE's. -+ */ -+/* CBUS physical base address as seen by PE's. */ -+#define PFE_CBUS_PHYS_BASE_ADDR_FROM_PFE 0xc0000000 -+ -+#define DDR_PHYS_TO_PFE(p) (((unsigned long int)(p)) & 0x7FFFFFFF) -+#define DDR_PFE_TO_PHYS(p) (((unsigned long int)(p)) | 0x80000000) -+#define CBUS_PHYS_TO_PFE(p) (((p) - PFE_CBUS_PHYS_BASE_ADDR) + \ -+ PFE_CBUS_PHYS_BASE_ADDR_FROM_PFE) -+/* Translates to PFE address map */ -+ -+#define DDR_PHYS_TO_VIRT(p) (((p) - DDR_PHYS_BASE_ADDR) + DDR_BASE_ADDR) -+#define DDR_VIRT_TO_PHYS(v) (((v) - DDR_BASE_ADDR) + DDR_PHYS_BASE_ADDR) -+#define DDR_VIRT_TO_PFE(p) (DDR_PHYS_TO_PFE(DDR_VIRT_TO_PHYS(p))) -+ -+#define CBUS_VIRT_TO_PFE(v) (((v) - CBUS_BASE_ADDR) + \ -+ PFE_CBUS_PHYS_BASE_ADDR) -+#define CBUS_PFE_TO_VIRT(p) (((unsigned long int)(p) - \ -+ PFE_CBUS_PHYS_BASE_ADDR) + CBUS_BASE_ADDR) -+ -+/* The below part of the code is used in QOS control driver from host */ -+#define TMU_APB_BASE_ADDR 0xc1000000 /* TMU base address seen by -+ * pe's -+ */ -+ -+enum { -+ CLASS0_ID = 0, -+ CLASS1_ID, -+ CLASS2_ID, -+ CLASS3_ID, -+ CLASS4_ID, -+ CLASS5_ID, -+ TMU0_ID, -+ TMU1_ID, -+ TMU2_ID, -+ TMU3_ID, -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ UTIL_ID, -+#endif -+ MAX_PE -+}; -+ -+#define CLASS_MASK (BIT(CLASS0_ID) | BIT(CLASS1_ID) |\ -+ BIT(CLASS2_ID) | BIT(CLASS3_ID) |\ -+ BIT(CLASS4_ID) | BIT(CLASS5_ID)) -+#define CLASS_MAX_ID CLASS5_ID -+ -+#define TMU_MASK (BIT(TMU0_ID) | BIT(TMU1_ID) |\ -+ BIT(TMU3_ID)) -+ -+#define TMU_MAX_ID TMU3_ID -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+#define UTIL_MASK BIT(UTIL_ID) -+#endif -+ -+struct pe_status { -+ u32 cpu_state; -+ u32 activity_counter; -+ u32 rx; -+ union { -+ u32 tx; -+ u32 tmu_qstatus; -+ }; -+ u32 drop; -+#if defined(CFG_PE_DEBUG) -+ u32 debug_indicator; -+ u32 debug[16]; -+#endif -+} __aligned(16); -+ -+struct pe_sync_mailbox { -+ u32 stop; -+ u32 stopped; -+}; -+ -+/* Drop counter definitions */ -+ -+#define CLASS_NUM_DROP_COUNTERS 13 -+#define UTIL_NUM_DROP_COUNTERS 8 -+ -+/* PE information. -+ * Structure containing PE's specific information. It is used to create -+ * generic C functions common to all PE's. -+ * Before using the library functions this structure needs to be initialized -+ * with the different registers virtual addresses -+ * (according to the ARM MMU mmaping). The default initialization supports a -+ * virtual == physical mapping. -+ */ -+struct pe_info { -+ u32 dmem_base_addr; /* PE's dmem base address */ -+ u32 pmem_base_addr; /* PE's pmem base address */ -+ u32 pmem_size; /* PE's pmem size */ -+ -+ void *mem_access_wdata; /* PE's _MEM_ACCESS_WDATA register -+ * address -+ */ -+ void *mem_access_addr; /* PE's _MEM_ACCESS_ADDR register -+ * address -+ */ -+ void *mem_access_rdata; /* PE's _MEM_ACCESS_RDATA register -+ * address -+ */ -+}; -+ -+void pe_lmem_read(u32 *dst, u32 len, u32 offset); -+void pe_lmem_write(u32 *src, u32 len, u32 offset); -+ -+void pe_dmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len); -+void pe_pmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len); -+ -+u32 pe_pmem_read(int id, u32 addr, u8 size); -+ -+void pe_dmem_write(int id, u32 val, u32 addr, u8 size); -+u32 pe_dmem_read(int id, u32 addr, u8 size); -+void class_pe_lmem_memcpy_to32(u32 dst, const void *src, unsigned int len); -+void class_pe_lmem_memset(u32 dst, int val, unsigned int len); -+void class_bus_write(u32 val, u32 addr, u8 size); -+u32 class_bus_read(u32 addr, u8 size); -+ -+#define class_bus_readl(addr) class_bus_read(addr, 4) -+#define class_bus_readw(addr) class_bus_read(addr, 2) -+#define class_bus_readb(addr) class_bus_read(addr, 1) -+ -+#define class_bus_writel(val, addr) class_bus_write(val, addr, 4) -+#define class_bus_writew(val, addr) class_bus_write(val, addr, 2) -+#define class_bus_writeb(val, addr) class_bus_write(val, addr, 1) -+ -+#define pe_dmem_readl(id, addr) pe_dmem_read(id, addr, 4) -+#define pe_dmem_readw(id, addr) pe_dmem_read(id, addr, 2) -+#define pe_dmem_readb(id, addr) pe_dmem_read(id, addr, 1) -+ -+#define pe_dmem_writel(id, val, addr) pe_dmem_write(id, val, addr, 4) -+#define pe_dmem_writew(id, val, addr) pe_dmem_write(id, val, addr, 2) -+#define pe_dmem_writeb(id, val, addr) pe_dmem_write(id, val, addr, 1) -+ -+/*int pe_load_elf_section(int id, const void *data, elf32_shdr *shdr); */ -+int pe_load_elf_section(int id, const void *data, struct elf32_shdr *shdr, -+ struct device *dev); -+ -+void pfe_lib_init(void *cbus_base, void *ddr_base, unsigned long ddr_phys_base, -+ unsigned int ddr_size); -+void bmu_init(void *base, struct BMU_CFG *cfg); -+void bmu_reset(void *base); -+void bmu_enable(void *base); -+void bmu_disable(void *base); -+void bmu_set_config(void *base, struct BMU_CFG *cfg); -+ -+/* -+ * An enumerated type for loopback values. This can be one of three values, no -+ * loopback -normal operation, local loopback with internal loopback module of -+ * MAC or PHY loopback which is through the external PHY. -+ */ -+#ifndef __MAC_LOOP_ENUM__ -+#define __MAC_LOOP_ENUM__ -+enum mac_loop {LB_NONE, LB_EXT, LB_LOCAL}; -+#endif -+ -+void gemac_init(void *base, void *config); -+void gemac_disable_rx_checksum_offload(void *base); -+void gemac_enable_rx_checksum_offload(void *base); -+void gemac_set_speed(void *base, enum mac_speed gem_speed); -+void gemac_set_duplex(void *base, int duplex); -+void gemac_set_mode(void *base, int mode); -+void gemac_enable(void *base); -+void gemac_tx_disable(void *base); -+void gemac_tx_enable(void *base); -+void gemac_disable(void *base); -+void gemac_reset(void *base); -+void gemac_set_address(void *base, struct spec_addr *addr); -+struct spec_addr gemac_get_address(void *base); -+void gemac_set_loop(void *base, enum mac_loop gem_loop); -+void gemac_set_laddr1(void *base, struct pfe_mac_addr *address); -+void gemac_set_laddr2(void *base, struct pfe_mac_addr *address); -+void gemac_set_laddr3(void *base, struct pfe_mac_addr *address); -+void gemac_set_laddr4(void *base, struct pfe_mac_addr *address); -+void gemac_set_laddrN(void *base, struct pfe_mac_addr *address, -+ unsigned int entry_index); -+void gemac_clear_laddr1(void *base); -+void gemac_clear_laddr2(void *base); -+void gemac_clear_laddr3(void *base); -+void gemac_clear_laddr4(void *base); -+void gemac_clear_laddrN(void *base, unsigned int entry_index); -+struct pfe_mac_addr gemac_get_hash(void *base); -+void gemac_set_hash(void *base, struct pfe_mac_addr *hash); -+struct pfe_mac_addr gem_get_laddr1(void *base); -+struct pfe_mac_addr gem_get_laddr2(void *base); -+struct pfe_mac_addr gem_get_laddr3(void *base); -+struct pfe_mac_addr gem_get_laddr4(void *base); -+struct pfe_mac_addr gem_get_laddrN(void *base, unsigned int entry_index); -+void gemac_set_config(void *base, struct gemac_cfg *cfg); -+void gemac_allow_broadcast(void *base); -+void gemac_no_broadcast(void *base); -+void gemac_enable_1536_rx(void *base); -+void gemac_disable_1536_rx(void *base); -+void gemac_set_rx_max_fl(void *base, int mtu); -+void gemac_enable_rx_jmb(void *base); -+void gemac_disable_rx_jmb(void *base); -+void gemac_enable_stacked_vlan(void *base); -+void gemac_disable_stacked_vlan(void *base); -+void gemac_enable_pause_rx(void *base); -+void gemac_disable_pause_rx(void *base); -+void gemac_enable_copy_all(void *base); -+void gemac_disable_copy_all(void *base); -+void gemac_set_bus_width(void *base, int width); -+void gemac_set_wol(void *base, u32 wol_conf); -+ -+void gpi_init(void *base, struct gpi_cfg *cfg); -+void gpi_reset(void *base); -+void gpi_enable(void *base); -+void gpi_disable(void *base); -+void gpi_set_config(void *base, struct gpi_cfg *cfg); -+ -+void class_init(struct class_cfg *cfg); -+void class_reset(void); -+void class_enable(void); -+void class_disable(void); -+void class_set_config(struct class_cfg *cfg); -+ -+void tmu_reset(void); -+void tmu_init(struct tmu_cfg *cfg); -+void tmu_enable(u32 pe_mask); -+void tmu_disable(u32 pe_mask); -+u32 tmu_qstatus(u32 if_id); -+u32 tmu_pkts_processed(u32 if_id); -+ -+void util_init(struct util_cfg *cfg); -+void util_reset(void); -+void util_enable(void); -+void util_disable(void); -+ -+void hif_init(void); -+void hif_tx_enable(void); -+void hif_tx_disable(void); -+void hif_rx_enable(void); -+void hif_rx_disable(void); -+ -+/* Get Chip Revision level -+ * -+ */ -+static inline unsigned int CHIP_REVISION(void) -+{ -+ /*For LS1012A return always 1 */ -+ return 1; -+} -+ -+/* Start HIF rx DMA -+ * -+ */ -+static inline void hif_rx_dma_start(void) -+{ -+ writel(HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB, HIF_RX_CTRL); -+} -+ -+/* Start HIF tx DMA -+ * -+ */ -+static inline void hif_tx_dma_start(void) -+{ -+ writel(HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB, HIF_TX_CTRL); -+} -+ -+#endif /* _PFE_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_cdev.c -@@ -0,0 +1,258 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2018 NXP -+ */ -+ -+/* @pfe_cdev.c. -+ * Dummy device representing the PFE US in userspace. -+ * - used for interacting with the kernel layer for link status -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include "pfe_cdev.h" -+#include "pfe_mod.h" -+ -+static int pfe_majno; -+static struct class *pfe_char_class; -+static struct device *pfe_char_dev; -+struct eventfd_ctx *g_trigger; -+ -+struct pfe_shared_info link_states[PFE_CDEV_ETH_COUNT]; -+ -+static int pfe_cdev_open(struct inode *inp, struct file *fp) -+{ -+ pr_debug("PFE CDEV device opened.\n"); -+ return 0; -+} -+ -+static ssize_t pfe_cdev_read(struct file *fp, char *buf, -+ size_t len, loff_t *off) -+{ -+ int ret = 0; -+ -+ pr_info("PFE CDEV attempt copying (%lu) size of user.\n", -+ sizeof(link_states)); -+ -+ pr_debug("Dump link_state on screen before copy_to_user\n"); -+ for (; ret < PFE_CDEV_ETH_COUNT; ret++) { -+ pr_debug("%u %u", link_states[ret].phy_id, -+ link_states[ret].state); -+ pr_debug("\n"); -+ } -+ -+ /* Copy to user the value in buffer sized len */ -+ ret = copy_to_user(buf, &link_states, sizeof(link_states)); -+ if (ret != 0) { -+ pr_err("Failed to send (%d)bytes of (%lu) requested.\n", -+ ret, len); -+ return -EFAULT; -+ } -+ -+ /* offset set back to 0 as there is contextual reading offset */ -+ *off = 0; -+ pr_debug("Read of (%lu) bytes performed.\n", sizeof(link_states)); -+ -+ return sizeof(link_states); -+} -+ -+/** -+ * This function is for getting some commands from user through non-IOCTL -+ * channel. It can used to configure the device. -+ * TODO: To be filled in future, if require duplex communication with user -+ * space. -+ */ -+static ssize_t pfe_cdev_write(struct file *fp, const char *buf, -+ size_t len, loff_t *off) -+{ -+ pr_info("PFE CDEV Write operation not supported!\n"); -+ -+ return -EFAULT; -+} -+ -+static int pfe_cdev_release(struct inode *inp, struct file *fp) -+{ -+ if (g_trigger) { -+ free_irq(pfe->hif_irq, g_trigger); -+ eventfd_ctx_put(g_trigger); -+ g_trigger = NULL; -+ } -+ -+ pr_info("PFE_CDEV: Device successfully closed\n"); -+ return 0; -+} -+ -+/* -+ * hif_us_isr- -+ * This ISR routine processes Rx/Tx done interrupts from the HIF hardware block -+ */ -+static irqreturn_t hif_us_isr(int irq, void *arg) -+{ -+ struct eventfd_ctx *trigger = (struct eventfd_ctx *)arg; -+ int int_status; -+ int int_enable_mask; -+ -+ /*Read hif interrupt source register */ -+ int_status = readl_relaxed(HIF_INT_SRC); -+ int_enable_mask = readl_relaxed(HIF_INT_ENABLE); -+ -+ if ((int_status & HIF_INT) == 0) -+ return IRQ_NONE; -+ -+ if (int_status & HIF_RXPKT_INT) { -+ int_enable_mask &= ~(HIF_RXPKT_INT); -+ /* Disable interrupts, they will be enabled after -+ * they are serviced -+ */ -+ writel_relaxed(int_enable_mask, HIF_INT_ENABLE); -+ -+ eventfd_signal(trigger); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+#define PFE_INTR_COAL_USECS 100 -+static long pfe_cdev_ioctl(struct file *fp, unsigned int cmd, -+ unsigned long arg) -+{ -+ int ret = -EFAULT; -+ int __user *argp = (int __user *)arg; -+ -+ pr_debug("PFE CDEV IOCTL Called with cmd=(%u)\n", cmd); -+ -+ switch (cmd) { -+ case PFE_CDEV_ETH0_STATE_GET: -+ /* Return an unsigned int (link state) for ETH0 */ -+ *argp = link_states[0].state; -+ pr_debug("Returning state=%d for ETH0\n", *argp); -+ ret = 0; -+ break; -+ case PFE_CDEV_ETH1_STATE_GET: -+ /* Return an unsigned int (link state) for ETH0 */ -+ *argp = link_states[1].state; -+ pr_debug("Returning state=%d for ETH1\n", *argp); -+ ret = 0; -+ break; -+ case PFE_CDEV_HIF_INTR_EN: -+ /* Return success/failure */ -+ g_trigger = eventfd_ctx_fdget(*argp); -+ if (IS_ERR(g_trigger)) -+ return PTR_ERR(g_trigger); -+ ret = request_irq(pfe->hif_irq, hif_us_isr, 0, "pfe_hif", -+ g_trigger); -+ if (ret) { -+ pr_err("%s: failed to get the hif IRQ = %d\n", -+ __func__, pfe->hif_irq); -+ eventfd_ctx_put(g_trigger); -+ g_trigger = NULL; -+ } -+ writel((PFE_INTR_COAL_USECS * (pfe->ctrl.sys_clk / 1000)) | -+ HIF_INT_COAL_ENABLE, HIF_INT_COAL); -+ -+ pr_debug("request_irq for hif interrupt: %d\n", pfe->hif_irq); -+ ret = 0; -+ break; -+ default: -+ pr_info("Unsupport cmd (%d) for PFE CDEV.\n", cmd); -+ break; -+ }; -+ -+ return ret; -+} -+ -+static unsigned int pfe_cdev_poll(struct file *fp, -+ struct poll_table_struct *wait) -+{ -+ pr_info("PFE CDEV poll method not supported\n"); -+ return 0; -+} -+ -+static const struct file_operations pfe_cdev_fops = { -+ .open = pfe_cdev_open, -+ .read = pfe_cdev_read, -+ .write = pfe_cdev_write, -+ .release = pfe_cdev_release, -+ .unlocked_ioctl = pfe_cdev_ioctl, -+ .poll = pfe_cdev_poll, -+}; -+ -+int pfe_cdev_init(void) -+{ -+ int ret; -+ -+ pr_debug("PFE CDEV initialization begin\n"); -+ -+ /* Register the major number for the device */ -+ pfe_majno = register_chrdev(0, PFE_CDEV_NAME, &pfe_cdev_fops); -+ if (pfe_majno < 0) { -+ pr_err("Unable to register PFE CDEV. PFE CDEV not available\n"); -+ ret = pfe_majno; -+ goto cleanup; -+ } -+ -+ pr_debug("PFE CDEV assigned major number: %d\n", pfe_majno); -+ -+ /* Register the class for the device */ -+ pfe_char_class = class_create(PFE_CLASS_NAME); -+ if (IS_ERR(pfe_char_class)) { -+ pr_err( -+ "Failed to init class for PFE CDEV. PFE CDEV not available.\n"); -+ ret = PTR_ERR(pfe_char_class); -+ goto cleanup; -+ } -+ -+ pr_debug("PFE CDEV Class created successfully.\n"); -+ -+ /* Create the device without any parent and without any callback data */ -+ pfe_char_dev = device_create(pfe_char_class, NULL, -+ MKDEV(pfe_majno, 0), NULL, -+ PFE_CDEV_NAME); -+ if (IS_ERR(pfe_char_dev)) { -+ pr_err("Unable to PFE CDEV device. PFE CDEV not available.\n"); -+ ret = PTR_ERR(pfe_char_dev); -+ goto cleanup; -+ } -+ -+ /* Information structure being shared with the userspace */ -+ memset(link_states, 0, sizeof(struct pfe_shared_info) * -+ PFE_CDEV_ETH_COUNT); -+ -+ pr_info("PFE CDEV created: %s\n", PFE_CDEV_NAME); -+ -+ ret = 0; -+ return ret; -+ -+cleanup: -+ if (!IS_ERR(pfe_char_class)) -+ class_destroy(pfe_char_class); -+ -+ if (pfe_majno > 0) -+ unregister_chrdev(pfe_majno, PFE_CDEV_NAME); -+ -+ return ret; -+} -+ -+void pfe_cdev_exit(void) -+{ -+ if (!IS_ERR(pfe_char_dev)) -+ device_destroy(pfe_char_class, MKDEV(pfe_majno, 0)); -+ -+ if (!IS_ERR(pfe_char_class)) { -+ class_unregister(pfe_char_class); -+ class_destroy(pfe_char_class); -+ } -+ -+ if (pfe_majno > 0) -+ unregister_chrdev(pfe_majno, PFE_CDEV_NAME); -+ -+ /* reset the variables */ -+ pfe_majno = 0; -+ pfe_char_class = NULL; -+ pfe_char_dev = NULL; -+ -+ pr_info("PFE CDEV Removed.\n"); -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_cdev.h -@@ -0,0 +1,41 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2018 NXP -+ */ -+ -+#ifndef _PFE_CDEV_H_ -+#define _PFE_CDEV_H_ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define PFE_CDEV_NAME "pfe_us_cdev" -+#define PFE_CLASS_NAME "ppfe_us" -+ -+/* Extracted from ls1012a_pfe_platform_data, there are 3 interfaces which are -+ * supported by PFE driver. Should be updated if number of eth devices are -+ * changed. -+ */ -+#define PFE_CDEV_ETH_COUNT 3 -+ -+struct pfe_shared_info { -+ uint32_t phy_id; /* Link phy ID */ -+ uint8_t state; /* Has either 0 or 1 */ -+}; -+ -+extern struct pfe_shared_info link_states[PFE_CDEV_ETH_COUNT]; -+ -+/* IOCTL Commands */ -+#define PFE_CDEV_ETH0_STATE_GET _IOR('R', 0, int) -+#define PFE_CDEV_ETH1_STATE_GET _IOR('R', 1, int) -+#define PFE_CDEV_HIF_INTR_EN _IOWR('R', 2, int) -+ -+int pfe_cdev_init(void); -+void pfe_cdev_exit(void); -+ -+#endif /* _PFE_CDEV_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_ctrl.c -@@ -0,0 +1,226 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "pfe_mod.h" -+#include "pfe_ctrl.h" -+ -+#define TIMEOUT_MS 1000 -+ -+int relax(unsigned long end) -+{ -+ if (time_after(jiffies, end)) { -+ if (time_after(jiffies, end + (TIMEOUT_MS * HZ) / 1000)) -+ return -1; -+ -+ if (need_resched()) -+ schedule(); -+ } -+ -+ return 0; -+} -+ -+void pfe_ctrl_suspend(struct pfe_ctrl *ctrl) -+{ -+ int id; -+ -+ mutex_lock(&ctrl->mutex); -+ -+ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) -+ pe_dmem_write(id, cpu_to_be32(0x1), CLASS_DM_RESUME, 4); -+ -+ for (id = TMU0_ID; id <= TMU_MAX_ID; id++) { -+ if (id == TMU2_ID) -+ continue; -+ pe_dmem_write(id, cpu_to_be32(0x1), TMU_DM_RESUME, 4); -+ } -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ pe_dmem_write(UTIL_ID, cpu_to_be32(0x1), UTIL_DM_RESUME, 4); -+#endif -+ mutex_unlock(&ctrl->mutex); -+} -+ -+void pfe_ctrl_resume(struct pfe_ctrl *ctrl) -+{ -+ int pe_mask = CLASS_MASK | TMU_MASK; -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ pe_mask |= UTIL_MASK; -+#endif -+ mutex_lock(&ctrl->mutex); -+ pe_start(&pfe->ctrl, pe_mask); -+ mutex_unlock(&ctrl->mutex); -+} -+ -+/* PE sync stop. -+ * Stops packet processing for a list of PE's (specified using a bitmask). -+ * The caller must hold ctrl->mutex. -+ * -+ * @param ctrl Control context -+ * @param pe_mask Mask of PE id's to stop -+ * -+ */ -+int pe_sync_stop(struct pfe_ctrl *ctrl, int pe_mask) -+{ -+ struct pe_sync_mailbox *mbox; -+ int pe_stopped = 0; -+ unsigned long end = jiffies + 2; -+ int i; -+ -+ pe_mask &= 0x2FF; /*Exclude Util + TMU2 */ -+ -+ for (i = 0; i < MAX_PE; i++) -+ if (pe_mask & (1 << i)) { -+ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; -+ -+ pe_dmem_write(i, cpu_to_be32(0x1), (unsigned -+ long)&mbox->stop, 4); -+ } -+ -+ while (pe_stopped != pe_mask) { -+ for (i = 0; i < MAX_PE; i++) -+ if ((pe_mask & (1 << i)) && !(pe_stopped & (1 << i))) { -+ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; -+ -+ if (pe_dmem_read(i, (unsigned -+ long)&mbox->stopped, 4) & -+ cpu_to_be32(0x1)) -+ pe_stopped |= (1 << i); -+ } -+ -+ if (relax(end) < 0) -+ goto err; -+ } -+ -+ return 0; -+ -+err: -+ pr_err("%s: timeout, %x %x\n", __func__, pe_mask, pe_stopped); -+ -+ for (i = 0; i < MAX_PE; i++) -+ if (pe_mask & (1 << i)) { -+ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; -+ -+ pe_dmem_write(i, cpu_to_be32(0x0), (unsigned -+ long)&mbox->stop, 4); -+ } -+ -+ return -EIO; -+} -+ -+/* PE start. -+ * Starts packet processing for a list of PE's (specified using a bitmask). -+ * The caller must hold ctrl->mutex. -+ * -+ * @param ctrl Control context -+ * @param pe_mask Mask of PE id's to start -+ * -+ */ -+void pe_start(struct pfe_ctrl *ctrl, int pe_mask) -+{ -+ struct pe_sync_mailbox *mbox; -+ int i; -+ -+ for (i = 0; i < MAX_PE; i++) -+ if (pe_mask & (1 << i)) { -+ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; -+ -+ pe_dmem_write(i, cpu_to_be32(0x0), (unsigned -+ long)&mbox->stop, 4); -+ } -+} -+ -+/* This function will ensure all PEs are put in to idle state */ -+int pe_reset_all(struct pfe_ctrl *ctrl) -+{ -+ struct pe_sync_mailbox *mbox; -+ int pe_stopped = 0; -+ unsigned long end = jiffies + 2; -+ int i; -+ int pe_mask = CLASS_MASK | TMU_MASK; -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ pe_mask |= UTIL_MASK; -+#endif -+ -+ for (i = 0; i < MAX_PE; i++) -+ if (pe_mask & (1 << i)) { -+ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; -+ -+ pe_dmem_write(i, cpu_to_be32(0x2), (unsigned -+ long)&mbox->stop, 4); -+ } -+ -+ while (pe_stopped != pe_mask) { -+ for (i = 0; i < MAX_PE; i++) -+ if ((pe_mask & (1 << i)) && !(pe_stopped & (1 << i))) { -+ mbox = (void *)ctrl->sync_mailbox_baseaddr[i]; -+ -+ if (pe_dmem_read(i, (unsigned long) -+ &mbox->stopped, 4) & -+ cpu_to_be32(0x1)) -+ pe_stopped |= (1 << i); -+ } -+ -+ if (relax(end) < 0) -+ goto err; -+ } -+ -+ return 0; -+ -+err: -+ pr_err("%s: timeout, %x %x\n", __func__, pe_mask, pe_stopped); -+ return -EIO; -+} -+ -+int pfe_ctrl_init(struct pfe *pfe) -+{ -+ struct pfe_ctrl *ctrl = &pfe->ctrl; -+ int id; -+ -+ pr_info("%s\n", __func__); -+ -+ mutex_init(&ctrl->mutex); -+ spin_lock_init(&ctrl->lock); -+ -+ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { -+ ctrl->sync_mailbox_baseaddr[id] = CLASS_DM_SYNC_MBOX; -+ ctrl->msg_mailbox_baseaddr[id] = CLASS_DM_MSG_MBOX; -+ } -+ -+ for (id = TMU0_ID; id <= TMU_MAX_ID; id++) { -+ if (id == TMU2_ID) -+ continue; -+ ctrl->sync_mailbox_baseaddr[id] = TMU_DM_SYNC_MBOX; -+ ctrl->msg_mailbox_baseaddr[id] = TMU_DM_MSG_MBOX; -+ } -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ ctrl->sync_mailbox_baseaddr[UTIL_ID] = UTIL_DM_SYNC_MBOX; -+ ctrl->msg_mailbox_baseaddr[UTIL_ID] = UTIL_DM_MSG_MBOX; -+#endif -+ -+ ctrl->hash_array_baseaddr = pfe->ddr_baseaddr + ROUTE_TABLE_BASEADDR; -+ ctrl->hash_array_phys_baseaddr = pfe->ddr_phys_baseaddr + -+ ROUTE_TABLE_BASEADDR; -+ -+ ctrl->dev = pfe->dev; -+ -+ pr_info("%s finished\n", __func__); -+ -+ return 0; -+} -+ -+void pfe_ctrl_exit(struct pfe *pfe) -+{ -+ pr_info("%s\n", __func__); -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_ctrl.h -@@ -0,0 +1,100 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#ifndef _PFE_CTRL_H_ -+#define _PFE_CTRL_H_ -+ -+#include -+ -+#include "pfe/pfe.h" -+ -+#define DMA_BUF_SIZE_128 0x80 /* enough for 1 conntracks */ -+#define DMA_BUF_SIZE_256 0x100 -+/* enough for 2 conntracks, 1 bridge entry or 1 multicast entry */ -+#define DMA_BUF_SIZE_512 0x200 -+/* 512bytes dma allocated buffers used by rtp relay feature */ -+#define DMA_BUF_MIN_ALIGNMENT 8 -+#define DMA_BUF_BOUNDARY (4 * 1024) -+/* bursts can not cross 4k boundary */ -+ -+#define CMD_TX_ENABLE 0x0501 -+#define CMD_TX_DISABLE 0x0502 -+ -+#define CMD_RX_LRO 0x0011 -+#define CMD_PKTCAP_ENABLE 0x0d01 -+#define CMD_QM_EXPT_RATE 0x020c -+ -+#define CLASS_DM_SH_STATIC (0x800) -+#define CLASS_DM_CPU_TICKS (CLASS_DM_SH_STATIC) -+#define CLASS_DM_SYNC_MBOX (0x808) -+#define CLASS_DM_MSG_MBOX (0x810) -+#define CLASS_DM_DROP_CNTR (0x820) -+#define CLASS_DM_RESUME (0x854) -+#define CLASS_DM_PESTATUS (0x860) -+#define CLASS_DM_CRC_VALIDATED (0x14b0) -+ -+#define TMU_DM_SH_STATIC (0x80) -+#define TMU_DM_CPU_TICKS (TMU_DM_SH_STATIC) -+#define TMU_DM_SYNC_MBOX (0x88) -+#define TMU_DM_MSG_MBOX (0x90) -+#define TMU_DM_RESUME (0xA0) -+#define TMU_DM_PESTATUS (0xB0) -+#define TMU_DM_CONTEXT (0x300) -+#define TMU_DM_TX_TRANS (0x480) -+ -+#define UTIL_DM_SH_STATIC (0x0) -+#define UTIL_DM_CPU_TICKS (UTIL_DM_SH_STATIC) -+#define UTIL_DM_SYNC_MBOX (0x8) -+#define UTIL_DM_MSG_MBOX (0x10) -+#define UTIL_DM_DROP_CNTR (0x20) -+#define UTIL_DM_RESUME (0x40) -+#define UTIL_DM_PESTATUS (0x50) -+ -+struct pfe_ctrl { -+ struct mutex mutex; /* to serialize pfe control access */ -+ spinlock_t lock; -+ -+ void *dma_pool; -+ void *dma_pool_512; -+ void *dma_pool_128; -+ -+ struct device *dev; -+ -+ void *hash_array_baseaddr; /* -+ * Virtual base address of -+ * the conntrack hash array -+ */ -+ unsigned long hash_array_phys_baseaddr; /* -+ * Physical base address of -+ * the conntrack hash array -+ */ -+ -+ int (*event_cb)(u16, u16, u16*); -+ -+ unsigned long sync_mailbox_baseaddr[MAX_PE]; /* -+ * Sync mailbox PFE -+ * internal address, -+ * initialized -+ * when parsing elf images -+ */ -+ unsigned long msg_mailbox_baseaddr[MAX_PE]; /* -+ * Msg mailbox PFE internal -+ * address, initialized -+ * when parsing elf images -+ */ -+ unsigned int sys_clk; /* AXI clock value, in KHz */ -+}; -+ -+int pfe_ctrl_init(struct pfe *pfe); -+void pfe_ctrl_exit(struct pfe *pfe); -+int pe_sync_stop(struct pfe_ctrl *ctrl, int pe_mask); -+void pe_start(struct pfe_ctrl *ctrl, int pe_mask); -+int pe_reset_all(struct pfe_ctrl *ctrl); -+void pfe_ctrl_suspend(struct pfe_ctrl *ctrl); -+void pfe_ctrl_resume(struct pfe_ctrl *ctrl); -+int relax(unsigned long end); -+ -+#endif /* _PFE_CTRL_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_debugfs.c -@@ -0,0 +1,99 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#include -+#include -+#include -+ -+#include "pfe_mod.h" -+ -+static int dmem_show(struct seq_file *s, void *unused) -+{ -+ u32 dmem_addr, val; -+ int id = (long int)s->private; -+ int i; -+ -+ for (dmem_addr = 0; dmem_addr < CLASS_DMEM_SIZE; dmem_addr += 8 * 4) { -+ seq_printf(s, "%04x:", dmem_addr); -+ -+ for (i = 0; i < 8; i++) { -+ val = pe_dmem_read(id, dmem_addr + i * 4, 4); -+ seq_printf(s, " %02x %02x %02x %02x", val & 0xff, -+ (val >> 8) & 0xff, (val >> 16) & 0xff, -+ (val >> 24) & 0xff); -+ } -+ -+ seq_puts(s, "\n"); -+ } -+ -+ return 0; -+} -+ -+static int dmem_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, dmem_show, inode->i_private); -+} -+ -+static const struct file_operations dmem_fops = { -+ .open = dmem_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+int pfe_debugfs_init(struct pfe *pfe) -+{ -+ struct dentry *d; -+ -+ pr_info("%s\n", __func__); -+ -+ pfe->dentry = debugfs_create_dir("pfe", NULL); -+ if (IS_ERR_OR_NULL(pfe->dentry)) -+ goto err_dir; -+ -+ d = debugfs_create_file("pe0_dmem", 0444, pfe->dentry, (void *)0, -+ &dmem_fops); -+ if (IS_ERR_OR_NULL(d)) -+ goto err_pe; -+ -+ d = debugfs_create_file("pe1_dmem", 0444, pfe->dentry, (void *)1, -+ &dmem_fops); -+ if (IS_ERR_OR_NULL(d)) -+ goto err_pe; -+ -+ d = debugfs_create_file("pe2_dmem", 0444, pfe->dentry, (void *)2, -+ &dmem_fops); -+ if (IS_ERR_OR_NULL(d)) -+ goto err_pe; -+ -+ d = debugfs_create_file("pe3_dmem", 0444, pfe->dentry, (void *)3, -+ &dmem_fops); -+ if (IS_ERR_OR_NULL(d)) -+ goto err_pe; -+ -+ d = debugfs_create_file("pe4_dmem", 0444, pfe->dentry, (void *)4, -+ &dmem_fops); -+ if (IS_ERR_OR_NULL(d)) -+ goto err_pe; -+ -+ d = debugfs_create_file("pe5_dmem", 0444, pfe->dentry, (void *)5, -+ &dmem_fops); -+ if (IS_ERR_OR_NULL(d)) -+ goto err_pe; -+ -+ return 0; -+ -+err_pe: -+ debugfs_remove_recursive(pfe->dentry); -+ -+err_dir: -+ return -1; -+} -+ -+void pfe_debugfs_exit(struct pfe *pfe) -+{ -+ debugfs_remove_recursive(pfe->dentry); -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_debugfs.h -@@ -0,0 +1,13 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#ifndef _PFE_DEBUGFS_H_ -+#define _PFE_DEBUGFS_H_ -+ -+int pfe_debugfs_init(struct pfe *pfe); -+void pfe_debugfs_exit(struct pfe *pfe); -+ -+#endif /* _PFE_DEBUGFS_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_eth.c -@@ -0,0 +1,2550 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+/* @pfe_eth.c. -+ * Ethernet driver for to handle exception path for PFE. -+ * - uses HIF functions to send/receive packets. -+ * - uses ctrl function to start/stop interfaces. -+ * - uses direct register accesses to control phy operation. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#if defined(CONFIG_NF_CONNTRACK_MARK) -+#include -+#endif -+ -+#include "pfe_mod.h" -+#include "pfe_eth.h" -+#include "pfe_cdev.h" -+ -+#define LS1012A_REV_1_0 0x87040010 -+ -+bool pfe_use_old_dts_phy; -+bool pfe_errata_a010897; -+ -+static void *cbus_emac_base[3]; -+static void *cbus_gpi_base[3]; -+ -+/* Forward Declaration */ -+static void pfe_eth_exit_one(struct pfe_eth_priv_s *priv); -+static void pfe_eth_flush_tx(struct pfe_eth_priv_s *priv); -+static void pfe_eth_flush_txQ(struct pfe_eth_priv_s *priv, int tx_q_num, int -+ from_tx, int n_desc); -+ -+/* MDIO registers */ -+#define MDIO_SGMII_CR 0x00 -+#define MDIO_SGMII_SR 0x01 -+#define MDIO_SGMII_DEV_ABIL_SGMII 0x04 -+#define MDIO_SGMII_LINK_TMR_L 0x12 -+#define MDIO_SGMII_LINK_TMR_H 0x13 -+#define MDIO_SGMII_IF_MODE 0x14 -+ -+/* SGMII Control defines */ -+#define SGMII_CR_RST 0x8000 -+#define SGMII_CR_AN_EN 0x1000 -+#define SGMII_CR_RESTART_AN 0x0200 -+#define SGMII_CR_FD 0x0100 -+#define SGMII_CR_SPEED_SEL1_1G 0x0040 -+#define SGMII_CR_DEF_VAL (SGMII_CR_AN_EN | SGMII_CR_FD | \ -+ SGMII_CR_SPEED_SEL1_1G) -+ -+/* SGMII IF Mode */ -+#define SGMII_DUPLEX_HALF 0x10 -+#define SGMII_SPEED_10MBPS 0x00 -+#define SGMII_SPEED_100MBPS 0x04 -+#define SGMII_SPEED_1GBPS 0x08 -+#define SGMII_USE_SGMII_AN 0x02 -+#define SGMII_EN 0x01 -+ -+/* SGMII Device Ability for SGMII */ -+#define SGMII_DEV_ABIL_ACK 0x4000 -+#define SGMII_DEV_ABIL_EEE_CLK_STP_EN 0x0100 -+#define SGMII_DEV_ABIL_SGMII 0x0001 -+ -+unsigned int gemac_regs[] = { -+ 0x0004, /* Interrupt event */ -+ 0x0008, /* Interrupt mask */ -+ 0x0024, /* Ethernet control */ -+ 0x0064, /* MIB Control/Status */ -+ 0x0084, /* Receive control/status */ -+ 0x00C4, /* Transmit control */ -+ 0x00E4, /* Physical address low */ -+ 0x00E8, /* Physical address high */ -+ 0x0144, /* Transmit FIFO Watermark and Store and Forward Control*/ -+ 0x0190, /* Receive FIFO Section Full Threshold */ -+ 0x01A0, /* Transmit FIFO Section Empty Threshold */ -+ 0x01B0, /* Frame Truncation Length */ -+}; -+ -+const struct soc_device_attribute ls1012a_rev1_soc_attr[] = { -+ { .family = "QorIQ LS1012A", -+ .soc_id = "svr:0x87040010", -+ .revision = "1.0", -+ .data = NULL }, -+ { }, -+}; -+ -+/********************************************************************/ -+/* SYSFS INTERFACE */ -+/********************************************************************/ -+ -+#ifdef PFE_ETH_NAPI_STATS -+/* -+ * pfe_eth_show_napi_stats -+ */ -+static ssize_t pfe_eth_show_napi_stats(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); -+ ssize_t len = 0; -+ -+ len += sprintf(buf + len, "sched: %u\n", -+ priv->napi_counters[NAPI_SCHED_COUNT]); -+ len += sprintf(buf + len, "poll: %u\n", -+ priv->napi_counters[NAPI_POLL_COUNT]); -+ len += sprintf(buf + len, "packet: %u\n", -+ priv->napi_counters[NAPI_PACKET_COUNT]); -+ len += sprintf(buf + len, "budget: %u\n", -+ priv->napi_counters[NAPI_FULL_BUDGET_COUNT]); -+ len += sprintf(buf + len, "desc: %u\n", -+ priv->napi_counters[NAPI_DESC_COUNT]); -+ -+ return len; -+} -+ -+/* -+ * pfe_eth_set_napi_stats -+ */ -+static ssize_t pfe_eth_set_napi_stats(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); -+ -+ memset(priv->napi_counters, 0, sizeof(priv->napi_counters)); -+ -+ return count; -+} -+#endif -+#ifdef PFE_ETH_TX_STATS -+/* pfe_eth_show_tx_stats -+ * -+ */ -+static ssize_t pfe_eth_show_tx_stats(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); -+ ssize_t len = 0; -+ int i; -+ -+ len += sprintf(buf + len, "TX queues stats:\n"); -+ -+ for (i = 0; i < emac_txq_cnt; i++) { -+ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, -+ i); -+ -+ len += sprintf(buf + len, "\n"); -+ __netif_tx_lock_bh(tx_queue); -+ -+ hif_tx_lock(&pfe->hif); -+ len += sprintf(buf + len, -+ "Queue %2d : credits = %10d\n" -+ , i, hif_lib_tx_credit_avail(pfe, priv->id, i)); -+ len += sprintf(buf + len, -+ " tx packets = %10d\n" -+ , pfe->tmu_credit.tx_packets[priv->id][i]); -+ hif_tx_unlock(&pfe->hif); -+ -+ /* Don't output additionnal stats if queue never used */ -+ if (!pfe->tmu_credit.tx_packets[priv->id][i]) -+ goto skip; -+ -+ len += sprintf(buf + len, -+ " clean_fail = %10d\n" -+ , priv->clean_fail[i]); -+ len += sprintf(buf + len, -+ " stop_queue = %10d\n" -+ , priv->stop_queue_total[i]); -+ len += sprintf(buf + len, -+ " stop_queue_hif = %10d\n" -+ , priv->stop_queue_hif[i]); -+ len += sprintf(buf + len, -+ " stop_queue_hif_client = %10d\n" -+ , priv->stop_queue_hif_client[i]); -+ len += sprintf(buf + len, -+ " stop_queue_credit = %10d\n" -+ , priv->stop_queue_credit[i]); -+skip: -+ __netif_tx_unlock_bh(tx_queue); -+ } -+ return len; -+} -+ -+/* pfe_eth_set_tx_stats -+ * -+ */ -+static ssize_t pfe_eth_set_tx_stats(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); -+ int i; -+ -+ for (i = 0; i < emac_txq_cnt; i++) { -+ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, -+ i); -+ -+ __netif_tx_lock_bh(tx_queue); -+ priv->clean_fail[i] = 0; -+ priv->stop_queue_total[i] = 0; -+ priv->stop_queue_hif[i] = 0; -+ priv->stop_queue_hif_client[i] = 0; -+ priv->stop_queue_credit[i] = 0; -+ __netif_tx_unlock_bh(tx_queue); -+ } -+ -+ return count; -+} -+#endif -+/* pfe_eth_show_txavail -+ * -+ */ -+static ssize_t pfe_eth_show_txavail(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); -+ ssize_t len = 0; -+ int i; -+ -+ for (i = 0; i < emac_txq_cnt; i++) { -+ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, -+ i); -+ -+ __netif_tx_lock_bh(tx_queue); -+ -+ len += sprintf(buf + len, "%d", -+ hif_lib_tx_avail(&priv->client, i)); -+ -+ __netif_tx_unlock_bh(tx_queue); -+ -+ if (i == (emac_txq_cnt - 1)) -+ len += sprintf(buf + len, "\n"); -+ else -+ len += sprintf(buf + len, " "); -+ } -+ -+ return len; -+} -+ -+/* pfe_eth_show_default_priority -+ * -+ */ -+static ssize_t pfe_eth_show_default_priority(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); -+ unsigned long flags; -+ int rc; -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ rc = sprintf(buf, "%d\n", priv->default_priority); -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ return rc; -+} -+ -+/* pfe_eth_set_default_priority -+ * -+ */ -+ -+static ssize_t pfe_eth_set_default_priority(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(to_net_dev(dev)); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ priv->default_priority = kstrtoul(buf, 0, 0); -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ return count; -+} -+ -+static DEVICE_ATTR(txavail, 0444, pfe_eth_show_txavail, NULL); -+static DEVICE_ATTR(default_priority, 0644, pfe_eth_show_default_priority, -+ pfe_eth_set_default_priority); -+ -+#ifdef PFE_ETH_NAPI_STATS -+static DEVICE_ATTR(napi_stats, 0644, pfe_eth_show_napi_stats, -+ pfe_eth_set_napi_stats); -+#endif -+ -+#ifdef PFE_ETH_TX_STATS -+static DEVICE_ATTR(tx_stats, 0644, pfe_eth_show_tx_stats, -+ pfe_eth_set_tx_stats); -+#endif -+ -+/* -+ * pfe_eth_sysfs_init -+ * -+ */ -+static int pfe_eth_sysfs_init(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ int err; -+ -+ /* Initialize the default values */ -+ -+ /* -+ * By default, packets without conntrack will use this default low -+ * priority queue -+ */ -+ priv->default_priority = 0; -+ -+ /* Create our sysfs files */ -+ err = device_create_file(&ndev->dev, &dev_attr_default_priority); -+ if (err) { -+ netdev_err(ndev, -+ "failed to create default_priority sysfs files\n"); -+ goto err_priority; -+ } -+ -+ err = device_create_file(&ndev->dev, &dev_attr_txavail); -+ if (err) { -+ netdev_err(ndev, -+ "failed to create default_priority sysfs files\n"); -+ goto err_txavail; -+ } -+ -+#ifdef PFE_ETH_NAPI_STATS -+ err = device_create_file(&ndev->dev, &dev_attr_napi_stats); -+ if (err) { -+ netdev_err(ndev, "failed to create napi stats sysfs files\n"); -+ goto err_napi; -+ } -+#endif -+ -+#ifdef PFE_ETH_TX_STATS -+ err = device_create_file(&ndev->dev, &dev_attr_tx_stats); -+ if (err) { -+ netdev_err(ndev, "failed to create tx stats sysfs files\n"); -+ goto err_tx; -+ } -+#endif -+ -+ return 0; -+ -+#ifdef PFE_ETH_TX_STATS -+err_tx: -+#endif -+#ifdef PFE_ETH_NAPI_STATS -+ device_remove_file(&ndev->dev, &dev_attr_napi_stats); -+ -+err_napi: -+#endif -+ device_remove_file(&ndev->dev, &dev_attr_txavail); -+ -+err_txavail: -+ device_remove_file(&ndev->dev, &dev_attr_default_priority); -+ -+err_priority: -+ return -1; -+} -+ -+/* pfe_eth_sysfs_exit -+ * -+ */ -+static void pfe_eth_sysfs_exit(struct net_device *ndev) -+{ -+#ifdef PFE_ETH_TX_STATS -+ device_remove_file(&ndev->dev, &dev_attr_tx_stats); -+#endif -+ -+#ifdef PFE_ETH_NAPI_STATS -+ device_remove_file(&ndev->dev, &dev_attr_napi_stats); -+#endif -+ device_remove_file(&ndev->dev, &dev_attr_txavail); -+ device_remove_file(&ndev->dev, &dev_attr_default_priority); -+} -+ -+/*************************************************************************/ -+/* ETHTOOL INTERCAE */ -+/*************************************************************************/ -+ -+/*MTIP GEMAC */ -+static const struct fec_stat { -+ char name[ETH_GSTRING_LEN]; -+ u16 offset; -+} fec_stats[] = { -+ /* RMON TX */ -+ { "tx_dropped", RMON_T_DROP }, -+ { "tx_packets", RMON_T_PACKETS }, -+ { "tx_broadcast", RMON_T_BC_PKT }, -+ { "tx_multicast", RMON_T_MC_PKT }, -+ { "tx_crc_errors", RMON_T_CRC_ALIGN }, -+ { "tx_undersize", RMON_T_UNDERSIZE }, -+ { "tx_oversize", RMON_T_OVERSIZE }, -+ { "tx_fragment", RMON_T_FRAG }, -+ { "tx_jabber", RMON_T_JAB }, -+ { "tx_collision", RMON_T_COL }, -+ { "tx_64byte", RMON_T_P64 }, -+ { "tx_65to127byte", RMON_T_P65TO127 }, -+ { "tx_128to255byte", RMON_T_P128TO255 }, -+ { "tx_256to511byte", RMON_T_P256TO511 }, -+ { "tx_512to1023byte", RMON_T_P512TO1023 }, -+ { "tx_1024to2047byte", RMON_T_P1024TO2047 }, -+ { "tx_GTE2048byte", RMON_T_P_GTE2048 }, -+ { "tx_octets", RMON_T_OCTETS }, -+ -+ /* IEEE TX */ -+ { "IEEE_tx_drop", IEEE_T_DROP }, -+ { "IEEE_tx_frame_ok", IEEE_T_FRAME_OK }, -+ { "IEEE_tx_1col", IEEE_T_1COL }, -+ { "IEEE_tx_mcol", IEEE_T_MCOL }, -+ { "IEEE_tx_def", IEEE_T_DEF }, -+ { "IEEE_tx_lcol", IEEE_T_LCOL }, -+ { "IEEE_tx_excol", IEEE_T_EXCOL }, -+ { "IEEE_tx_macerr", IEEE_T_MACERR }, -+ { "IEEE_tx_cserr", IEEE_T_CSERR }, -+ { "IEEE_tx_sqe", IEEE_T_SQE }, -+ { "IEEE_tx_fdxfc", IEEE_T_FDXFC }, -+ { "IEEE_tx_octets_ok", IEEE_T_OCTETS_OK }, -+ -+ /* RMON RX */ -+ { "rx_packets", RMON_R_PACKETS }, -+ { "rx_broadcast", RMON_R_BC_PKT }, -+ { "rx_multicast", RMON_R_MC_PKT }, -+ { "rx_crc_errors", RMON_R_CRC_ALIGN }, -+ { "rx_undersize", RMON_R_UNDERSIZE }, -+ { "rx_oversize", RMON_R_OVERSIZE }, -+ { "rx_fragment", RMON_R_FRAG }, -+ { "rx_jabber", RMON_R_JAB }, -+ { "rx_64byte", RMON_R_P64 }, -+ { "rx_65to127byte", RMON_R_P65TO127 }, -+ { "rx_128to255byte", RMON_R_P128TO255 }, -+ { "rx_256to511byte", RMON_R_P256TO511 }, -+ { "rx_512to1023byte", RMON_R_P512TO1023 }, -+ { "rx_1024to2047byte", RMON_R_P1024TO2047 }, -+ { "rx_GTE2048byte", RMON_R_P_GTE2048 }, -+ { "rx_octets", RMON_R_OCTETS }, -+ -+ /* IEEE RX */ -+ { "IEEE_rx_drop", IEEE_R_DROP }, -+ { "IEEE_rx_frame_ok", IEEE_R_FRAME_OK }, -+ { "IEEE_rx_crc", IEEE_R_CRC }, -+ { "IEEE_rx_align", IEEE_R_ALIGN }, -+ { "IEEE_rx_macerr", IEEE_R_MACERR }, -+ { "IEEE_rx_fdxfc", IEEE_R_FDXFC }, -+ { "IEEE_rx_octets_ok", IEEE_R_OCTETS_OK }, -+}; -+ -+static void pfe_eth_fill_stats(struct net_device *ndev, struct ethtool_stats -+ *stats, u64 *data) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ int i; -+ u64 pfe_crc_validated = 0; -+ int id; -+ -+ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { -+ pfe_crc_validated += be32_to_cpu(pe_dmem_read(id, -+ CLASS_DM_CRC_VALIDATED + (priv->id * 4), 4)); -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(fec_stats); i++) { -+ data[i] = readl(priv->EMAC_baseaddr + fec_stats[i].offset); -+ -+ if (fec_stats[i].offset == IEEE_R_DROP) -+ data[i] -= pfe_crc_validated; -+ } -+} -+ -+static void pfe_eth_gstrings(struct net_device *netdev, -+ u32 stringset, u8 *data) -+{ -+ int i; -+ -+ switch (stringset) { -+ case ETH_SS_STATS: -+ for (i = 0; i < ARRAY_SIZE(fec_stats); i++) -+ memcpy(data + i * ETH_GSTRING_LEN, -+ fec_stats[i].name, ETH_GSTRING_LEN); -+ break; -+ } -+} -+ -+static int pfe_eth_stats_count(struct net_device *ndev, int sset) -+{ -+ switch (sset) { -+ case ETH_SS_STATS: -+ return ARRAY_SIZE(fec_stats); -+ default: -+ return -EOPNOTSUPP; -+ } -+} -+ -+/* -+ * pfe_eth_gemac_reglen - Return the length of the register structure. -+ * -+ */ -+static int pfe_eth_gemac_reglen(struct net_device *ndev) -+{ -+ pr_info("%s()\n", __func__); -+ return (sizeof(gemac_regs) / sizeof(u32)); -+} -+ -+/* -+ * pfe_eth_gemac_get_regs - Return the gemac register structure. -+ * -+ */ -+static void pfe_eth_gemac_get_regs(struct net_device *ndev, struct ethtool_regs -+ *regs, void *regbuf) -+{ -+ int i; -+ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ u32 *buf = (u32 *)regbuf; -+ -+ pr_info("%s()\n", __func__); -+ for (i = 0; i < sizeof(gemac_regs) / sizeof(u32); i++) -+ buf[i] = readl(priv->EMAC_baseaddr + gemac_regs[i]); -+} -+ -+/* -+ * pfe_eth_set_wol - Set the magic packet option, in WoL register. -+ * -+ */ -+static int pfe_eth_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ if (wol->wolopts & ~WAKE_MAGIC) -+ return -EOPNOTSUPP; -+ -+ /* for MTIP we store wol->wolopts */ -+ priv->wol = wol->wolopts; -+ -+ device_set_wakeup_enable(&ndev->dev, wol->wolopts & WAKE_MAGIC); -+ -+ return 0; -+} -+ -+/* -+ * -+ * pfe_eth_get_wol - Get the WoL options. -+ * -+ */ -+static void pfe_eth_get_wol(struct net_device *ndev, struct ethtool_wolinfo -+ *wol) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ wol->supported = WAKE_MAGIC; -+ wol->wolopts = 0; -+ -+ if (priv->wol & WAKE_MAGIC) -+ wol->wolopts = WAKE_MAGIC; -+ -+ memset(&wol->sopass, 0, sizeof(wol->sopass)); -+} -+ -+/* -+ * pfe_eth_get_drvinfo - Fills in the drvinfo structure with some basic info -+ * -+ */ -+static void pfe_eth_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo -+ *drvinfo) -+{ -+ strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); -+ strscpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version)); -+ strscpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); -+ strscpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info)); -+} -+ -+/* -+ * pfe_eth_set_settings - Used to send commands to PHY. -+ * -+ */ -+static int pfe_eth_set_settings(struct net_device *ndev, -+ const struct ethtool_link_ksettings *cmd) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ struct phy_device *phydev = priv->phydev; -+ -+ if (!phydev) -+ return -ENODEV; -+ -+ return phy_ethtool_ksettings_set(phydev, cmd); -+} -+ -+/* -+ * pfe_eth_getsettings - Return the current settings in the ethtool_cmd -+ * structure. -+ * -+ */ -+static int pfe_eth_get_settings(struct net_device *ndev, -+ struct ethtool_link_ksettings *cmd) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ struct phy_device *phydev = priv->phydev; -+ -+ if (!phydev) -+ return -ENODEV; -+ -+ phy_ethtool_ksettings_get(phydev, cmd); -+ -+ return 0; -+} -+ -+/* -+ * pfe_eth_get_msglevel - Gets the debug message mask. -+ * -+ */ -+static uint32_t pfe_eth_get_msglevel(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ return priv->msg_enable; -+} -+ -+/* -+ * pfe_eth_set_msglevel - Sets the debug message mask. -+ * -+ */ -+static void pfe_eth_set_msglevel(struct net_device *ndev, uint32_t data) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ priv->msg_enable = data; -+} -+ -+#define HIF_RX_COAL_MAX_CLKS (~(1 << 31)) -+#define HIF_RX_COAL_CLKS_PER_USEC (pfe->ctrl.sys_clk / 1000) -+#define HIF_RX_COAL_MAX_USECS (HIF_RX_COAL_MAX_CLKS / \ -+ HIF_RX_COAL_CLKS_PER_USEC) -+ -+/* -+ * pfe_eth_set_coalesce - Sets rx interrupt coalescing timer. -+ * -+ */ -+static int pfe_eth_set_coalesce(struct net_device *ndev, -+ struct ethtool_coalesce *ec, -+ struct kernel_ethtool_coalesce *kernel_coal, -+ struct netlink_ext_ack *extack) -+{ -+ if (ec->rx_coalesce_usecs > HIF_RX_COAL_MAX_USECS) -+ return -EINVAL; -+ -+ if (!ec->rx_coalesce_usecs) { -+ writel(0, HIF_INT_COAL); -+ return 0; -+ } -+ -+ writel((ec->rx_coalesce_usecs * HIF_RX_COAL_CLKS_PER_USEC) | -+ HIF_INT_COAL_ENABLE, HIF_INT_COAL); -+ -+ return 0; -+} -+ -+/* -+ * pfe_eth_get_coalesce - Gets rx interrupt coalescing timer value. -+ * -+ */ -+static int pfe_eth_get_coalesce(struct net_device *ndev, -+ struct ethtool_coalesce *ec, -+ struct kernel_ethtool_coalesce *kernel_coal, -+ struct netlink_ext_ack *extack) -+{ -+ int reg_val = readl(HIF_INT_COAL); -+ -+ if (reg_val & HIF_INT_COAL_ENABLE) -+ ec->rx_coalesce_usecs = (reg_val & HIF_RX_COAL_MAX_CLKS) / -+ HIF_RX_COAL_CLKS_PER_USEC; -+ else -+ ec->rx_coalesce_usecs = 0; -+ -+ return 0; -+} -+ -+/* -+ * pfe_eth_set_pauseparam - Sets pause parameters -+ * -+ */ -+static int pfe_eth_set_pauseparam(struct net_device *ndev, -+ struct ethtool_pauseparam *epause) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ if (epause->tx_pause != epause->rx_pause) { -+ netdev_info(ndev, -+ "hardware only support enable/disable both tx and rx\n"); -+ return -EINVAL; -+ } -+ -+ priv->pause_flag = 0; -+ priv->pause_flag |= epause->rx_pause ? PFE_PAUSE_FLAG_ENABLE : 0; -+ priv->pause_flag |= epause->autoneg ? PFE_PAUSE_FLAG_AUTONEG : 0; -+ -+ if (epause->rx_pause || epause->autoneg) { -+ gemac_enable_pause_rx(priv->EMAC_baseaddr); -+ writel((readl(priv->GPI_baseaddr + GPI_TX_PAUSE_TIME) | -+ EGPI_PAUSE_ENABLE), -+ priv->GPI_baseaddr + GPI_TX_PAUSE_TIME); -+ if (priv->phydev) { -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, -+ priv->phydev->supported); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, -+ priv->phydev->supported); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, -+ priv->phydev->advertising); -+ linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, -+ priv->phydev->advertising); -+ } -+ } else { -+ gemac_disable_pause_rx(priv->EMAC_baseaddr); -+ writel((readl(priv->GPI_baseaddr + GPI_TX_PAUSE_TIME) & -+ ~EGPI_PAUSE_ENABLE), -+ priv->GPI_baseaddr + GPI_TX_PAUSE_TIME); -+ if (priv->phydev) { -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, -+ priv->phydev->supported); -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, -+ priv->phydev->supported); -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, -+ priv->phydev->advertising); -+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, -+ priv->phydev->advertising); -+ } -+ } -+ -+ return 0; -+} -+ -+/* -+ * pfe_eth_get_pauseparam - Gets pause parameters -+ * -+ */ -+static void pfe_eth_get_pauseparam(struct net_device *ndev, -+ struct ethtool_pauseparam *epause) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ epause->autoneg = (priv->pause_flag & PFE_PAUSE_FLAG_AUTONEG) != 0; -+ epause->tx_pause = (priv->pause_flag & PFE_PAUSE_FLAG_ENABLE) != 0; -+ epause->rx_pause = epause->tx_pause; -+} -+ -+/* -+ * pfe_eth_get_hash -+ */ -+#define PFE_HASH_BITS 6 /* #bits in hash */ -+#define CRC32_POLY 0xEDB88320 -+ -+static int pfe_eth_get_hash(u8 *addr) -+{ -+ unsigned int i, bit, data, crc, hash; -+ -+ /* calculate crc32 value of mac address */ -+ crc = 0xffffffff; -+ -+ for (i = 0; i < 6; i++) { -+ data = addr[i]; -+ for (bit = 0; bit < 8; bit++, data >>= 1) { -+ crc = (crc >> 1) ^ -+ (((crc ^ data) & 1) ? CRC32_POLY : 0); -+ } -+ } -+ -+ /* -+ * only upper 6 bits (PFE_HASH_BITS) are used -+ * which point to specific bit in the hash registers -+ */ -+ hash = (crc >> (32 - PFE_HASH_BITS)) & 0x3f; -+ -+ return hash; -+} -+ -+const struct ethtool_ops pfe_ethtool_ops = { -+ .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS, -+ .get_drvinfo = pfe_eth_get_drvinfo, -+ .get_regs_len = pfe_eth_gemac_reglen, -+ .get_regs = pfe_eth_gemac_get_regs, -+ .get_link = ethtool_op_get_link, -+ .get_wol = pfe_eth_get_wol, -+ .set_wol = pfe_eth_set_wol, -+ .set_pauseparam = pfe_eth_set_pauseparam, -+ .get_pauseparam = pfe_eth_get_pauseparam, -+ .get_strings = pfe_eth_gstrings, -+ .get_sset_count = pfe_eth_stats_count, -+ .get_ethtool_stats = pfe_eth_fill_stats, -+ .get_msglevel = pfe_eth_get_msglevel, -+ .set_msglevel = pfe_eth_set_msglevel, -+ .set_coalesce = pfe_eth_set_coalesce, -+ .get_coalesce = pfe_eth_get_coalesce, -+ .get_link_ksettings = pfe_eth_get_settings, -+ .set_link_ksettings = pfe_eth_set_settings, -+}; -+ -+/* pfe_eth_mdio_reset -+ */ -+int pfe_eth_mdio_reset(struct mii_bus *bus) -+{ -+ struct pfe_mdio_priv_s *priv = (struct pfe_mdio_priv_s *)bus->priv; -+ u32 phy_speed; -+ -+ -+ mutex_lock(&bus->mdio_lock); -+ -+ /* -+ * Set MII speed to 2.5 MHz (= clk_get_rate() / 2 * phy_speed) -+ * -+ * The formula for FEC MDC is 'ref_freq / (MII_SPEED x 2)' while -+ * for ENET-MAC is 'ref_freq / ((MII_SPEED + 1) x 2)'. -+ */ -+ phy_speed = (DIV_ROUND_UP((pfe->ctrl.sys_clk * 1000), 4000000) -+ << EMAC_MII_SPEED_SHIFT); -+ phy_speed |= EMAC_HOLDTIME(0x5); -+ __raw_writel(phy_speed, priv->mdio_base + EMAC_MII_CTRL_REG); -+ -+ mutex_unlock(&bus->mdio_lock); -+ -+ return 0; -+} -+ -+/* pfe_eth_mdio_timeout -+ * -+ */ -+static int pfe_eth_mdio_timeout(struct pfe_mdio_priv_s *priv, int timeout) -+{ -+ while (!(__raw_readl(priv->mdio_base + EMAC_IEVENT_REG) & -+ EMAC_IEVENT_MII)) { -+ if (timeout-- <= 0) -+ return -1; -+ usleep_range(10, 20); -+ } -+ __raw_writel(EMAC_IEVENT_MII, priv->mdio_base + EMAC_IEVENT_REG); -+ return 0; -+} -+ -+static int pfe_eth_mdio_mux(u8 muxval) -+{ -+ struct i2c_adapter *a; -+ struct i2c_msg msg; -+ unsigned char buf[2]; -+ int ret; -+ -+ a = i2c_get_adapter(0); -+ if (!a) -+ return -ENODEV; -+ -+ /* set bit 1 (the second bit) of chip at 0x09, register 0x13 */ -+ buf[0] = 0x54; /* reg number */ -+ buf[1] = (muxval << 6) | 0x3; /* data */ -+ msg.addr = 0x66; -+ msg.buf = buf; -+ msg.len = 2; -+ msg.flags = 0; -+ ret = i2c_transfer(a, &msg, 1); -+ i2c_put_adapter(a); -+ if (ret != 1) -+ return -ENODEV; -+ return 0; -+} -+ -+static int pfe_eth_mdio_write(struct mii_bus *bus, int mii_id, int regnum, -+ u16 value) -+{ -+ struct pfe_mdio_priv_s *priv = (struct pfe_mdio_priv_s *)bus->priv; -+ -+ /*To access external PHYs on QDS board mux needs to be configured*/ -+ if ((mii_id) && (pfe->mdio_muxval[mii_id])) -+ pfe_eth_mdio_mux(pfe->mdio_muxval[mii_id]); -+ -+ /* start a write op */ -+ __raw_writel(EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR | -+ EMAC_MII_DATA_PA(mii_id) | -+ EMAC_MII_DATA_RA(regnum) | -+ EMAC_MII_DATA_TA | EMAC_MII_DATA(value), -+ priv->mdio_base + EMAC_MII_DATA_REG); -+ -+ if (pfe_eth_mdio_timeout(priv, EMAC_MDIO_TIMEOUT)) { -+ dev_err(&bus->dev, "%s: phy MDIO write timeout\n", __func__); -+ return -1; -+ } -+ return 0; -+} -+ -+static int pfe_eth_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -+{ -+ struct pfe_mdio_priv_s *priv = (struct pfe_mdio_priv_s *)bus->priv; -+ u16 value = 0; -+ -+ /*To access external PHYs on QDS board mux needs to be configured*/ -+ if ((mii_id) && (pfe->mdio_muxval[mii_id])) -+ pfe_eth_mdio_mux(pfe->mdio_muxval[mii_id]); -+ -+ /* start a read op */ -+ __raw_writel(EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD | -+ EMAC_MII_DATA_PA(mii_id) | -+ EMAC_MII_DATA_RA(regnum) | -+ EMAC_MII_DATA_TA, priv->mdio_base + -+ EMAC_MII_DATA_REG); -+ -+ if (pfe_eth_mdio_timeout(priv, EMAC_MDIO_TIMEOUT)) { -+ dev_err(&bus->dev, "%s: phy MDIO read timeout\n", __func__); -+ return -1; -+ } -+ -+ value = EMAC_MII_DATA(__raw_readl(priv->mdio_base + -+ EMAC_MII_DATA_REG)); -+ return value; -+} -+ -+static int pfe_eth_mdio_init(struct pfe *pfe, -+ struct ls1012a_pfe_platform_data *pfe_info, -+ int ii) -+{ -+ struct pfe_mdio_priv_s *priv = NULL; -+ struct ls1012a_mdio_platform_data *mdio_info; -+ struct mii_bus *bus; -+ struct device_node *mdio_node; -+ int rc = 0; -+ -+ mdio_info = (struct ls1012a_mdio_platform_data *) -+ pfe_info->ls1012a_mdio_pdata; -+ mdio_info->id = ii; -+ -+ bus = mdiobus_alloc_size(sizeof(struct pfe_mdio_priv_s)); -+ if (!bus) { -+ pr_err("mdiobus_alloc() failed\n"); -+ rc = -ENOMEM; -+ goto err_mdioalloc; -+ } -+ -+ bus->name = "ls1012a MDIO Bus"; -+ snprintf(bus->id, MII_BUS_ID_SIZE, "ls1012a-%x", mdio_info->id); -+ -+ bus->read = &pfe_eth_mdio_read; -+ bus->write = &pfe_eth_mdio_write; -+ bus->reset = &pfe_eth_mdio_reset; -+ bus->parent = pfe->dev; -+ bus->phy_mask = mdio_info->phy_mask; -+ bus->irq[0] = mdio_info->irq[0]; -+ priv = bus->priv; -+ priv->mdio_base = cbus_emac_base[ii]; -+ -+ priv->mdc_div = mdio_info->mdc_div; -+ if (!priv->mdc_div) -+ priv->mdc_div = 64; -+ -+ dev_info(bus->parent, "%s: mdc_div: %d, phy_mask: %x\n", -+ __func__, priv->mdc_div, bus->phy_mask); -+ mdio_node = of_get_child_by_name(pfe->dev->of_node, "mdio"); -+ if ((mdio_info->id == 0) && mdio_node) { -+ rc = of_mdiobus_register(bus, mdio_node); -+ of_node_put(mdio_node); -+ } else { -+ rc = mdiobus_register(bus); -+ } -+ -+ if (rc) { -+ dev_err(bus->parent, "mdiobus_register(%s) failed\n", -+ bus->name); -+ goto err_mdioregister; -+ } -+ -+ priv->mii_bus = bus; -+ pfe->mdio.mdio_priv[ii] = priv; -+ -+ pfe_eth_mdio_reset(bus); -+ -+ return 0; -+ -+err_mdioregister: -+ mdiobus_free(bus); -+err_mdioalloc: -+ return rc; -+} -+ -+/* pfe_eth_mdio_exit -+ */ -+static void pfe_eth_mdio_exit(struct pfe *pfe, -+ int ii) -+{ -+ struct pfe_mdio_priv_s *mdio_priv = pfe->mdio.mdio_priv[ii]; -+ struct mii_bus *bus = mdio_priv->mii_bus; -+ -+ if (!bus) -+ return; -+ mdiobus_unregister(bus); -+ mdiobus_free(bus); -+} -+ -+/* pfe_get_phydev_speed -+ */ -+static int pfe_get_phydev_speed(struct phy_device *phydev) -+{ -+ switch (phydev->speed) { -+ case 10: -+ return SPEED_10M; -+ case 100: -+ return SPEED_100M; -+ case 1000: -+ default: -+ return SPEED_1000M; -+ } -+} -+ -+/* pfe_set_rgmii_speed -+ */ -+#define RGMIIPCR 0x434 -+/* RGMIIPCR bit definitions*/ -+#define SCFG_RGMIIPCR_EN_AUTO (0x00000008) -+#define SCFG_RGMIIPCR_SETSP_1000M (0x00000004) -+#define SCFG_RGMIIPCR_SETSP_100M (0x00000000) -+#define SCFG_RGMIIPCR_SETSP_10M (0x00000002) -+#define SCFG_RGMIIPCR_SETFD (0x00000001) -+ -+#define MDIOSELCR 0x484 -+#define MDIOSEL_SERDES 0x0 -+#define MDIOSEL_EXTPHY 0x80000000 -+ -+static void pfe_set_rgmii_speed(struct phy_device *phydev) -+{ -+ u32 rgmii_pcr; -+ -+ regmap_read(pfe->scfg, RGMIIPCR, &rgmii_pcr); -+ rgmii_pcr &= ~(SCFG_RGMIIPCR_SETSP_1000M | SCFG_RGMIIPCR_SETSP_10M); -+ -+ switch (phydev->speed) { -+ case 10: -+ rgmii_pcr |= SCFG_RGMIIPCR_SETSP_10M; -+ break; -+ case 1000: -+ rgmii_pcr |= SCFG_RGMIIPCR_SETSP_1000M; -+ break; -+ case 100: -+ default: -+ /* Default is 100M */ -+ break; -+ } -+ regmap_write(pfe->scfg, RGMIIPCR, rgmii_pcr); -+} -+ -+/* pfe_get_phydev_duplex -+ */ -+static int pfe_get_phydev_duplex(struct phy_device *phydev) -+{ -+ /*return (phydev->duplex == DUPLEX_HALF) ? DUP_HALF:DUP_FULL ; */ -+ return DUPLEX_FULL; -+} -+ -+/* pfe_eth_adjust_link -+ */ -+static void pfe_eth_adjust_link(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ unsigned long flags; -+ struct phy_device *phydev = priv->phydev; -+ int new_state = 0; -+ -+ netif_info(priv, drv, ndev, "%s\n", __func__); -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ -+ if (phydev->link) { -+ /* -+ * Now we make sure that we can be in full duplex mode. -+ * If not, we operate in half-duplex mode. -+ */ -+ if (phydev->duplex != priv->oldduplex) { -+ new_state = 1; -+ gemac_set_duplex(priv->EMAC_baseaddr, -+ pfe_get_phydev_duplex(phydev)); -+ priv->oldduplex = phydev->duplex; -+ } -+ -+ if (phydev->speed != priv->oldspeed) { -+ new_state = 1; -+ gemac_set_speed(priv->EMAC_baseaddr, -+ pfe_get_phydev_speed(phydev)); -+ if (priv->einfo->mii_config == -+ PHY_INTERFACE_MODE_RGMII_ID) -+ pfe_set_rgmii_speed(phydev); -+ priv->oldspeed = phydev->speed; -+ } -+ -+ if (!priv->oldlink) { -+ new_state = 1; -+ priv->oldlink = 1; -+ } -+ -+ } else if (priv->oldlink) { -+ new_state = 1; -+ priv->oldlink = 0; -+ priv->oldspeed = 0; -+ priv->oldduplex = -1; -+ } -+ -+ if (new_state && netif_msg_link(priv)) -+ phy_print_status(phydev); -+ -+ spin_unlock_irqrestore(&priv->lock, flags); -+ -+ /* Now, dump the details to the cdev. -+ * XXX: Locking would be required? (uniprocess arch) -+ * Or, maybe move it in spinlock above -+ */ -+ if (us && priv->einfo->gem_id < PFE_CDEV_ETH_COUNT) { -+ pr_debug("Changing link state from (%u) to (%u) for ID=(%u)\n", -+ link_states[priv->einfo->gem_id].state, -+ phydev->link, -+ priv->einfo->gem_id); -+ link_states[priv->einfo->gem_id].phy_id = priv->einfo->gem_id; -+ link_states[priv->einfo->gem_id].state = phydev->link; -+ } -+} -+ -+/* pfe_phy_exit -+ */ -+static void pfe_phy_exit(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ netif_info(priv, drv, ndev, "%s\n", __func__); -+ -+ phy_disconnect(priv->phydev); -+ priv->phydev = NULL; -+} -+ -+/* pfe_eth_stop -+ */ -+static void pfe_eth_stop(struct net_device *ndev, int wake) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ netif_info(priv, drv, ndev, "%s\n", __func__); -+ -+ if (wake) { -+ gemac_tx_disable(priv->EMAC_baseaddr); -+ } else { -+ gemac_disable(priv->EMAC_baseaddr); -+ gpi_disable(priv->GPI_baseaddr); -+ -+ if (priv->phydev) -+ phy_stop(priv->phydev); -+ } -+} -+ -+/* pfe_eth_start -+ */ -+static int pfe_eth_start(struct pfe_eth_priv_s *priv) -+{ -+ netif_info(priv, drv, priv->ndev, "%s\n", __func__); -+ -+ if (priv->phydev) -+ phy_start(priv->phydev); -+ -+ gpi_enable(priv->GPI_baseaddr); -+ gemac_enable(priv->EMAC_baseaddr); -+ -+ return 0; -+} -+ -+/* -+ * Configure on chip serdes through mdio -+ */ -+static void ls1012a_configure_serdes(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *eth_priv = netdev_priv(ndev); -+ struct pfe_mdio_priv_s *mdio_priv = pfe->mdio.mdio_priv[eth_priv->id]; -+ int sgmii_2500 = 0; -+ struct mii_bus *bus = mdio_priv->mii_bus; -+ u16 value = 0; -+ -+ if (eth_priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) -+ sgmii_2500 = 1; -+ -+ netif_info(eth_priv, drv, ndev, "%s\n", __func__); -+ /* PCS configuration done with corresponding GEMAC */ -+ -+ pfe_eth_mdio_read(bus, 0, MDIO_SGMII_CR); -+ pfe_eth_mdio_read(bus, 0, MDIO_SGMII_SR); -+ -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_CR, SGMII_CR_RST); -+ -+ if (sgmii_2500) { -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_IF_MODE, SGMII_SPEED_1GBPS -+ | SGMII_EN); -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_DEV_ABIL_SGMII, -+ SGMII_DEV_ABIL_ACK | SGMII_DEV_ABIL_SGMII); -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_LINK_TMR_L, 0xa120); -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_LINK_TMR_H, 0x7); -+ /* Autonegotiation need to be disabled for 2.5G SGMII mode*/ -+ value = SGMII_CR_FD | SGMII_CR_SPEED_SEL1_1G; -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_CR, value); -+ } else { -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_IF_MODE, -+ SGMII_SPEED_1GBPS -+ | SGMII_USE_SGMII_AN -+ | SGMII_EN); -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_DEV_ABIL_SGMII, -+ SGMII_DEV_ABIL_EEE_CLK_STP_EN -+ | 0xa0 -+ | SGMII_DEV_ABIL_SGMII); -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_LINK_TMR_L, 0x400); -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_LINK_TMR_H, 0x0); -+ value = SGMII_CR_AN_EN | SGMII_CR_FD | SGMII_CR_SPEED_SEL1_1G; -+ pfe_eth_mdio_write(bus, 0, MDIO_SGMII_CR, value); -+ } -+} -+ -+/* -+ * pfe_phy_init -+ * -+ */ -+static int pfe_phy_init(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ struct phy_device *phydev; -+ char phy_id[MII_BUS_ID_SIZE + 3]; -+ char bus_id[MII_BUS_ID_SIZE]; -+ phy_interface_t interface; -+ -+ priv->oldlink = 0; -+ priv->oldspeed = 0; -+ priv->oldduplex = -1; -+ -+ snprintf(bus_id, MII_BUS_ID_SIZE, "ls1012a-%d", 0); -+ snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, -+ priv->einfo->phy_id); -+ netif_info(priv, drv, ndev, "%s: %s\n", __func__, phy_id); -+ interface = priv->einfo->mii_config; -+ if ((interface == PHY_INTERFACE_MODE_SGMII) || -+ (interface == PHY_INTERFACE_MODE_2500SGMII)) { -+ /*Configure SGMII PCS */ -+ if (pfe->scfg) { -+ /* Config MDIO from serdes */ -+ regmap_write(pfe->scfg, MDIOSELCR, MDIOSEL_SERDES); -+ } -+ ls1012a_configure_serdes(ndev); -+ } -+ -+ if (pfe->scfg) { -+ /*Config MDIO from PAD */ -+ regmap_write(pfe->scfg, MDIOSELCR, MDIOSEL_EXTPHY); -+ } -+ -+ priv->oldlink = 0; -+ priv->oldspeed = 0; -+ priv->oldduplex = -1; -+ pr_info("%s interface %x\n", __func__, interface); -+ -+ if (priv->phy_node) { -+ phydev = of_phy_connect(ndev, priv->phy_node, -+ pfe_eth_adjust_link, 0, -+ priv->einfo->mii_config); -+ if (!(phydev)) { -+ netdev_err(ndev, "Unable to connect to phy\n"); -+ return -ENODEV; -+ } -+ -+ } else { -+ phydev = phy_connect(ndev, phy_id, -+ &pfe_eth_adjust_link, interface); -+ if (IS_ERR(phydev)) { -+ netdev_err(ndev, "Unable to connect to phy\n"); -+ return PTR_ERR(phydev); -+ } -+ } -+ -+ priv->phydev = phydev; -+ phydev->irq = PHY_POLL; -+ -+ return 0; -+} -+ -+/* pfe_gemac_init -+ */ -+static int pfe_gemac_init(struct pfe_eth_priv_s *priv) -+{ -+ struct gemac_cfg cfg; -+ -+ netif_info(priv, ifup, priv->ndev, "%s\n", __func__); -+ -+ cfg.mode = 0; -+ cfg.speed = SPEED_1000M; -+ cfg.duplex = DUPLEX_FULL; -+ -+ gemac_set_config(priv->EMAC_baseaddr, &cfg); -+ gemac_allow_broadcast(priv->EMAC_baseaddr); -+ gemac_enable_1536_rx(priv->EMAC_baseaddr); -+ gemac_enable_stacked_vlan(priv->EMAC_baseaddr); -+ gemac_enable_pause_rx(priv->EMAC_baseaddr); -+ gemac_set_bus_width(priv->EMAC_baseaddr, 64); -+ -+ /*GEM will perform checksum verifications*/ -+ if (priv->ndev->features & NETIF_F_RXCSUM) -+ gemac_enable_rx_checksum_offload(priv->EMAC_baseaddr); -+ else -+ gemac_disable_rx_checksum_offload(priv->EMAC_baseaddr); -+ -+ return 0; -+} -+ -+/* pfe_eth_event_handler -+ */ -+static int pfe_eth_event_handler(void *data, int event, int qno) -+{ -+ struct pfe_eth_priv_s *priv = data; -+ -+ switch (event) { -+ case EVENT_RX_PKT_IND: -+ -+ if (qno == 0) { -+ if (napi_schedule_prep(&priv->high_napi)) { -+ netif_info(priv, intr, priv->ndev, -+ "%s: schedule high prio poll\n" -+ , __func__); -+ -+#ifdef PFE_ETH_NAPI_STATS -+ priv->napi_counters[NAPI_SCHED_COUNT]++; -+#endif -+ -+ __napi_schedule(&priv->high_napi); -+ } -+ } else if (qno == 1) { -+ if (napi_schedule_prep(&priv->low_napi)) { -+ netif_info(priv, intr, priv->ndev, -+ "%s: schedule low prio poll\n" -+ , __func__); -+ -+#ifdef PFE_ETH_NAPI_STATS -+ priv->napi_counters[NAPI_SCHED_COUNT]++; -+#endif -+ __napi_schedule(&priv->low_napi); -+ } -+ } else if (qno == 2) { -+ if (napi_schedule_prep(&priv->lro_napi)) { -+ netif_info(priv, intr, priv->ndev, -+ "%s: schedule lro prio poll\n" -+ , __func__); -+ -+#ifdef PFE_ETH_NAPI_STATS -+ priv->napi_counters[NAPI_SCHED_COUNT]++; -+#endif -+ __napi_schedule(&priv->lro_napi); -+ } -+ } -+ -+ break; -+ -+ case EVENT_TXDONE_IND: -+ pfe_eth_flush_tx(priv); -+ hif_lib_event_handler_start(&priv->client, EVENT_TXDONE_IND, 0); -+ break; -+ case EVENT_HIGH_RX_WM: -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static int pfe_eth_change_mtu(struct net_device *ndev, int new_mtu) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ ndev->mtu = new_mtu; -+ new_mtu += ETH_HLEN + ETH_FCS_LEN; -+ gemac_set_rx_max_fl(priv->EMAC_baseaddr, new_mtu); -+ -+ return 0; -+} -+ -+/* pfe_eth_open -+ */ -+static int pfe_eth_open(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ struct hif_client_s *client; -+ int rc; -+ -+ netif_info(priv, ifup, ndev, "%s\n", __func__); -+ -+ /* Register client driver with HIF */ -+ client = &priv->client; -+ memset(client, 0, sizeof(*client)); -+ client->id = PFE_CL_GEM0 + priv->id; -+ client->tx_qn = emac_txq_cnt; -+ client->rx_qn = EMAC_RXQ_CNT; -+ client->priv = priv; -+ client->pfe = priv->pfe; -+ client->event_handler = pfe_eth_event_handler; -+ -+ client->tx_qsize = EMAC_TXQ_DEPTH; -+ client->rx_qsize = EMAC_RXQ_DEPTH; -+ -+ rc = hif_lib_client_register(client); -+ if (rc) { -+ netdev_err(ndev, "%s: hif_lib_client_register(%d) failed\n", -+ __func__, client->id); -+ goto err0; -+ } -+ -+ netif_info(priv, drv, ndev, "%s: registered client: %p\n", __func__, -+ client); -+ -+ pfe_gemac_init(priv); -+ -+ if (!is_valid_ether_addr(ndev->dev_addr)) { -+ netdev_err(ndev, "%s: invalid MAC address\n", __func__); -+ rc = -EADDRNOTAVAIL; -+ goto err1; -+ } -+ -+ gemac_set_laddrN(priv->EMAC_baseaddr, -+ (struct pfe_mac_addr *)ndev->dev_addr, 1); -+ -+ napi_enable(&priv->high_napi); -+ napi_enable(&priv->low_napi); -+ napi_enable(&priv->lro_napi); -+ -+ rc = pfe_eth_start(priv); -+ -+ netif_tx_wake_all_queues(ndev); -+ -+ return rc; -+ -+err1: -+ hif_lib_client_unregister(&priv->client); -+ -+err0: -+ return rc; -+} -+ -+/* -+ * pfe_eth_shutdown -+ */ -+static int pfe_eth_shutdown(struct net_device *ndev, int wake) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ int i, qstatus, id; -+ unsigned long next_poll = jiffies + 1, end = jiffies + -+ (TX_POLL_TIMEOUT_MS * HZ) / 1000; -+ int tx_pkts, prv_tx_pkts; -+ -+ netif_info(priv, ifdown, ndev, "%s\n", __func__); -+ -+ for (i = 0; i < emac_txq_cnt; i++) -+ hrtimer_cancel(&priv->fast_tx_timeout[i].timer); -+ -+ netif_tx_stop_all_queues(ndev); -+ -+ do { -+ tx_pkts = 0; -+ pfe_eth_flush_tx(priv); -+ -+ for (i = 0; i < emac_txq_cnt; i++) -+ tx_pkts += hif_lib_tx_pending(&priv->client, i); -+ -+ if (tx_pkts) { -+ /*Don't wait forever, break if we cross max timeout */ -+ if (time_after(jiffies, end)) { -+ pr_err( -+ "(%s)Tx is not complete after %dmsec\n", -+ ndev->name, TX_POLL_TIMEOUT_MS); -+ break; -+ } -+ -+ pr_info("%s : (%s) Waiting for tx packets to free. Pending tx pkts = %d.\n" -+ , __func__, ndev->name, tx_pkts); -+ if (need_resched()) -+ schedule(); -+ } -+ -+ } while (tx_pkts); -+ -+ end = jiffies + (TX_POLL_TIMEOUT_MS * HZ) / 1000; -+ -+ prv_tx_pkts = tmu_pkts_processed(priv->id); -+ /* -+ * Wait till TMU transmits all pending packets -+ * poll tmu_qstatus and pkts processed by TMU for every 10ms -+ * Consider TMU is busy, If we see TMU qeueu pending or any packets -+ * processed by TMU -+ */ -+ while (1) { -+ if (time_after(jiffies, next_poll)) { -+ tx_pkts = tmu_pkts_processed(priv->id); -+ qstatus = tmu_qstatus(priv->id) & 0x7ffff; -+ -+ if (!qstatus && (tx_pkts == prv_tx_pkts)) -+ break; -+ /* Don't wait forever, break if we cross max -+ * timeout(TX_POLL_TIMEOUT_MS) -+ */ -+ if (time_after(jiffies, end)) { -+ pr_err("TMU%d is busy after %dmsec\n", -+ priv->id, TX_POLL_TIMEOUT_MS); -+ break; -+ } -+ prv_tx_pkts = tx_pkts; -+ next_poll++; -+ } -+ if (need_resched()) -+ schedule(); -+ } -+ /* Wait for some more time to complete transmitting packet if any */ -+ next_poll = jiffies + 1; -+ while (1) { -+ if (time_after(jiffies, next_poll)) -+ break; -+ if (need_resched()) -+ schedule(); -+ } -+ -+ pfe_eth_stop(ndev, wake); -+ -+ napi_disable(&priv->lro_napi); -+ napi_disable(&priv->low_napi); -+ napi_disable(&priv->high_napi); -+ -+ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { -+ pe_dmem_write(id, 0, CLASS_DM_CRC_VALIDATED -+ + (priv->id * 4), 4); -+ } -+ -+ hif_lib_client_unregister(&priv->client); -+ -+ return 0; -+} -+ -+/* pfe_eth_close -+ * -+ */ -+static int pfe_eth_close(struct net_device *ndev) -+{ -+ pfe_eth_shutdown(ndev, 0); -+ -+ return 0; -+} -+ -+/* pfe_eth_suspend -+ * -+ * return value : 1 if netdevice is configured to wakeup system -+ * 0 otherwise -+ */ -+int pfe_eth_suspend(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ int retval = 0; -+ -+ if (priv->wol) { -+ gemac_set_wol(priv->EMAC_baseaddr, priv->wol); -+ retval = 1; -+ } -+ pfe_eth_shutdown(ndev, priv->wol); -+ -+ return retval; -+} -+ -+/* pfe_eth_resume -+ * -+ */ -+int pfe_eth_resume(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ if (priv->wol) -+ gemac_set_wol(priv->EMAC_baseaddr, 0); -+ gemac_tx_enable(priv->EMAC_baseaddr); -+ -+ return pfe_eth_open(ndev); -+} -+ -+/* pfe_eth_get_queuenum -+ */ -+static int pfe_eth_get_queuenum(struct pfe_eth_priv_s *priv, struct sk_buff -+ *skb) -+{ -+ int queuenum = 0; -+ unsigned long flags; -+ -+ /* Get the Fast Path queue number */ -+ /* -+ * Use conntrack mark (if conntrack exists), then packet mark (if any), -+ * then fallback to default -+ */ -+#if defined(CONFIG_IP_NF_CONNTRACK_MARK) || defined(CONFIG_NF_CONNTRACK_MARK) -+ if (skb->_nfct) { -+ enum ip_conntrack_info cinfo; -+ struct nf_conn *ct; -+ -+ ct = nf_ct_get(skb, &cinfo); -+ -+ if (ct) { -+ u32 connmark; -+ -+ connmark = ct->mark; -+ -+ if ((connmark & 0x80000000) && priv->id != 0) -+ connmark >>= 16; -+ -+ queuenum = connmark & EMAC_QUEUENUM_MASK; -+ } -+ } else {/* continued after #endif ... */ -+#endif -+ if (skb->mark) { -+ queuenum = skb->mark & EMAC_QUEUENUM_MASK; -+ } else { -+ spin_lock_irqsave(&priv->lock, flags); -+ queuenum = priv->default_priority & EMAC_QUEUENUM_MASK; -+ spin_unlock_irqrestore(&priv->lock, flags); -+ } -+#if defined(CONFIG_IP_NF_CONNTRACK_MARK) || defined(CONFIG_NF_CONNTRACK_MARK) -+ } -+#endif -+ return queuenum; -+} -+ -+/* pfe_eth_might_stop_tx -+ * -+ */ -+static int pfe_eth_might_stop_tx(struct pfe_eth_priv_s *priv, int queuenum, -+ struct netdev_queue *tx_queue, -+ unsigned int n_desc, -+ unsigned int n_segs) -+{ -+ ktime_t kt; -+ int tried = 0; -+ -+try_again: -+ if (unlikely((__hif_tx_avail(&pfe->hif) < n_desc) || -+ (hif_lib_tx_avail(&priv->client, queuenum) < n_desc) || -+ (hif_lib_tx_credit_avail(pfe, priv->id, queuenum) < n_segs))) { -+ if (!tried) { -+ __hif_lib_update_credit(&priv->client, queuenum); -+ tried = 1; -+ goto try_again; -+ } -+#ifdef PFE_ETH_TX_STATS -+ if (__hif_tx_avail(&pfe->hif) < n_desc) { -+ priv->stop_queue_hif[queuenum]++; -+ } else if (hif_lib_tx_avail(&priv->client, queuenum) < n_desc) { -+ priv->stop_queue_hif_client[queuenum]++; -+ } else if (hif_lib_tx_credit_avail(pfe, priv->id, queuenum) < -+ n_segs) { -+ priv->stop_queue_credit[queuenum]++; -+ } -+ priv->stop_queue_total[queuenum]++; -+#endif -+ netif_tx_stop_queue(tx_queue); -+ -+ kt = ktime_set(0, LS1012A_TX_FAST_RECOVERY_TIMEOUT_MS * -+ NSEC_PER_MSEC); -+ hrtimer_start(&priv->fast_tx_timeout[queuenum].timer, kt, -+ HRTIMER_MODE_REL); -+ return -1; -+ } else { -+ return 0; -+ } -+} -+ -+#define SA_MAX_OP 2 -+/* pfe_hif_send_packet -+ * -+ * At this level if TX fails we drop the packet -+ */ -+static void pfe_hif_send_packet(struct sk_buff *skb, struct pfe_eth_priv_s -+ *priv, int queuenum) -+{ -+ struct skb_shared_info *sh = skb_shinfo(skb); -+ unsigned int nr_frags; -+ u32 ctrl = 0; -+ -+ netif_info(priv, tx_queued, priv->ndev, "%s\n", __func__); -+ -+ if (skb_is_gso(skb)) { -+ priv->stats.tx_dropped++; -+ return; -+ } -+ -+ if (skb->ip_summed == CHECKSUM_PARTIAL) -+ ctrl = HIF_CTRL_TX_CHECKSUM; -+ -+ nr_frags = sh->nr_frags; -+ -+ if (nr_frags) { -+ skb_frag_t *f; -+ int i; -+ -+ __hif_lib_xmit_pkt(&priv->client, queuenum, skb->data, -+ skb_headlen(skb), ctrl, HIF_FIRST_BUFFER, -+ skb); -+ -+ for (i = 0; i < nr_frags - 1; i++) { -+ f = &sh->frags[i]; -+ __hif_lib_xmit_pkt(&priv->client, queuenum, -+ skb_frag_address(f), -+ skb_frag_size(f), -+ 0x0, 0x0, skb); -+ } -+ -+ f = &sh->frags[i]; -+ -+ __hif_lib_xmit_pkt(&priv->client, queuenum, -+ skb_frag_address(f), skb_frag_size(f), -+ 0x0, HIF_LAST_BUFFER | HIF_DATA_VALID, -+ skb); -+ -+ netif_info(priv, tx_queued, priv->ndev, -+ "%s: pkt sent successfully skb:%p nr_frags:%d len:%d\n", -+ __func__, skb, nr_frags, skb->len); -+ } else { -+ __hif_lib_xmit_pkt(&priv->client, queuenum, skb->data, -+ skb->len, ctrl, HIF_FIRST_BUFFER | -+ HIF_LAST_BUFFER | HIF_DATA_VALID, -+ skb); -+ netif_info(priv, tx_queued, priv->ndev, -+ "%s: pkt sent successfully skb:%p len:%d\n", -+ __func__, skb, skb->len); -+ } -+ hif_tx_dma_start(); -+ priv->stats.tx_packets++; -+ priv->stats.tx_bytes += skb->len; -+ hif_lib_tx_credit_use(pfe, priv->id, queuenum, 1); -+} -+ -+/* pfe_eth_flush_txQ -+ */ -+static void pfe_eth_flush_txQ(struct pfe_eth_priv_s *priv, int tx_q_num, int -+ from_tx, int n_desc) -+{ -+ struct sk_buff *skb; -+ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, -+ tx_q_num); -+ unsigned int flags; -+ -+ netif_info(priv, tx_done, priv->ndev, "%s\n", __func__); -+ -+ if (!from_tx) -+ __netif_tx_lock_bh(tx_queue); -+ -+ /* Clean HIF and client queue */ -+ while ((skb = hif_lib_tx_get_next_complete(&priv->client, -+ tx_q_num, &flags, -+ HIF_TX_DESC_NT))) { -+ if (flags & HIF_DATA_VALID) -+ dev_kfree_skb_any(skb); -+ } -+ if (!from_tx) -+ __netif_tx_unlock_bh(tx_queue); -+} -+ -+/* pfe_eth_flush_tx -+ */ -+static void pfe_eth_flush_tx(struct pfe_eth_priv_s *priv) -+{ -+ int ii; -+ -+ netif_info(priv, tx_done, priv->ndev, "%s\n", __func__); -+ -+ for (ii = 0; ii < emac_txq_cnt; ii++) { -+ pfe_eth_flush_txQ(priv, ii, 0, 0); -+ __hif_lib_update_credit(&priv->client, ii); -+ } -+} -+ -+static void pfe_tx_get_req_desc(struct sk_buff *skb, unsigned int *n_desc, unsigned int -+ *n_segs) -+{ -+ struct skb_shared_info *sh = skb_shinfo(skb); -+ -+ /* Scattered data */ -+ if (sh->nr_frags) { -+ *n_desc = sh->nr_frags + 1; -+ *n_segs = 1; -+ /* Regular case */ -+ } else { -+ *n_desc = 1; -+ *n_segs = 1; -+ } -+} -+ -+/* pfe_eth_send_packet -+ */ -+static int pfe_eth_send_packet(struct sk_buff *skb, struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ int tx_q_num = skb_get_queue_mapping(skb); -+ int n_desc, n_segs; -+ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, -+ tx_q_num); -+ -+ netif_info(priv, tx_queued, ndev, "%s\n", __func__); -+ -+ if ((!skb_is_gso(skb)) && (skb_headroom(skb) < (PFE_PKT_HEADER_SZ + -+ sizeof(unsigned long)))) { -+ netif_warn(priv, tx_err, priv->ndev, "%s: copying skb\n", -+ __func__); -+ -+ if (pskb_expand_head(skb, (PFE_PKT_HEADER_SZ + sizeof(unsigned -+ long)), 0, GFP_ATOMIC)) { -+ /* No need to re-transmit, no way to recover*/ -+ kfree_skb(skb); -+ priv->stats.tx_dropped++; -+ return NETDEV_TX_OK; -+ } -+ } -+ -+ pfe_tx_get_req_desc(skb, &n_desc, &n_segs); -+ -+ hif_tx_lock(&pfe->hif); -+ if (unlikely(pfe_eth_might_stop_tx(priv, tx_q_num, tx_queue, n_desc, -+ n_segs))) { -+#ifdef PFE_ETH_TX_STATS -+ if (priv->was_stopped[tx_q_num]) { -+ priv->clean_fail[tx_q_num]++; -+ priv->was_stopped[tx_q_num] = 0; -+ } -+#endif -+ hif_tx_unlock(&pfe->hif); -+ return NETDEV_TX_BUSY; -+ } -+ -+ pfe_hif_send_packet(skb, priv, tx_q_num); -+ -+ hif_tx_unlock(&pfe->hif); -+ -+ tx_queue->trans_start = jiffies; -+ -+#ifdef PFE_ETH_TX_STATS -+ priv->was_stopped[tx_q_num] = 0; -+#endif -+ -+ return NETDEV_TX_OK; -+} -+ -+/* pfe_eth_select_queue -+ * -+ */ -+static u16 pfe_eth_select_queue(struct net_device *ndev, struct sk_buff *skb, -+ struct net_device *sb_dev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ return pfe_eth_get_queuenum(priv, skb); -+} -+ -+/* pfe_eth_get_stats -+ */ -+static struct net_device_stats *pfe_eth_get_stats(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ -+ netif_info(priv, drv, ndev, "%s\n", __func__); -+ -+ return &priv->stats; -+} -+ -+/* pfe_eth_set_mac_address -+ */ -+static int pfe_eth_set_mac_address(struct net_device *ndev, void *addr) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ struct sockaddr *sa = addr; -+ -+ netif_info(priv, drv, ndev, "%s\n", __func__); -+ -+ if (!is_valid_ether_addr(sa->sa_data)) -+ return -EADDRNOTAVAIL; -+ -+ dev_addr_set(ndev, sa->sa_data); -+ -+ gemac_set_laddrN(priv->EMAC_baseaddr, -+ (struct pfe_mac_addr *)ndev->dev_addr, 1); -+ -+ return 0; -+} -+ -+/* pfe_eth_enet_addr_byte_mac -+ */ -+static int pfe_eth_enet_addr_byte_mac(u8 *enet_byte_addr, -+ struct pfe_mac_addr *enet_addr) -+{ -+ if (!enet_byte_addr || !enet_addr) { -+ return -1; -+ -+ } else { -+ enet_addr->bottom = enet_byte_addr[0] | -+ (enet_byte_addr[1] << 8) | -+ (enet_byte_addr[2] << 16) | -+ (enet_byte_addr[3] << 24); -+ enet_addr->top = enet_byte_addr[4] | -+ (enet_byte_addr[5] << 8); -+ return 0; -+ } -+} -+ -+/* pfe_eth_set_multi -+ */ -+static void pfe_eth_set_multi(struct net_device *ndev) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ struct pfe_mac_addr hash_addr; /* hash register structure */ -+ /* specific mac address register structure */ -+ struct pfe_mac_addr spec_addr; -+ int result; /* index into hash register to set.. */ -+ int uc_count = 0; -+ struct netdev_hw_addr *ha; -+ -+ if (ndev->flags & IFF_PROMISC) { -+ netif_info(priv, drv, ndev, "entering promiscuous mode\n"); -+ -+ priv->promisc = 1; -+ gemac_enable_copy_all(priv->EMAC_baseaddr); -+ } else { -+ priv->promisc = 0; -+ gemac_disable_copy_all(priv->EMAC_baseaddr); -+ } -+ -+ /* Enable broadcast frame reception if required. */ -+ if (ndev->flags & IFF_BROADCAST) { -+ gemac_allow_broadcast(priv->EMAC_baseaddr); -+ } else { -+ netif_info(priv, drv, ndev, -+ "disabling broadcast frame reception\n"); -+ -+ gemac_no_broadcast(priv->EMAC_baseaddr); -+ } -+ -+ if (ndev->flags & IFF_ALLMULTI) { -+ /* Set the hash to rx all multicast frames */ -+ hash_addr.bottom = 0xFFFFFFFF; -+ hash_addr.top = 0xFFFFFFFF; -+ gemac_set_hash(priv->EMAC_baseaddr, &hash_addr); -+ netdev_for_each_uc_addr(ha, ndev) { -+ if (uc_count >= MAX_UC_SPEC_ADDR_REG) -+ break; -+ pfe_eth_enet_addr_byte_mac(ha->addr, &spec_addr); -+ gemac_set_laddrN(priv->EMAC_baseaddr, &spec_addr, -+ uc_count + 2); -+ uc_count++; -+ } -+ } else if ((netdev_mc_count(ndev) > 0) || (netdev_uc_count(ndev))) { -+ u8 *addr; -+ -+ hash_addr.bottom = 0; -+ hash_addr.top = 0; -+ -+ netdev_for_each_mc_addr(ha, ndev) { -+ addr = ha->addr; -+ -+ netif_info(priv, drv, ndev, -+ "adding multicast address %X:%X:%X:%X:%X:%X to gem filter\n", -+ addr[0], addr[1], addr[2], -+ addr[3], addr[4], addr[5]); -+ -+ result = pfe_eth_get_hash(addr); -+ -+ if (result < EMAC_HASH_REG_BITS) { -+ if (result < 32) -+ hash_addr.bottom |= (1 << result); -+ else -+ hash_addr.top |= (1 << (result - 32)); -+ } else { -+ break; -+ } -+ } -+ -+ uc_count = -1; -+ netdev_for_each_uc_addr(ha, ndev) { -+ addr = ha->addr; -+ -+ if (++uc_count < MAX_UC_SPEC_ADDR_REG) { -+ netdev_info(ndev, -+ "adding unicast address %02x:%02x:%02x:%02x:%02x:%02x to gem filter\n", -+ addr[0], addr[1], addr[2], -+ addr[3], addr[4], addr[5]); -+ pfe_eth_enet_addr_byte_mac(addr, &spec_addr); -+ gemac_set_laddrN(priv->EMAC_baseaddr, -+ &spec_addr, uc_count + 2); -+ } else { -+ netif_info(priv, drv, ndev, -+ "adding unicast address %02x:%02x:%02x:%02x:%02x:%02x to gem hash\n", -+ addr[0], addr[1], addr[2], -+ addr[3], addr[4], addr[5]); -+ -+ result = pfe_eth_get_hash(addr); -+ if (result >= EMAC_HASH_REG_BITS) { -+ break; -+ -+ } else { -+ if (result < 32) -+ hash_addr.bottom |= (1 << -+ result); -+ else -+ hash_addr.top |= (1 << -+ (result - 32)); -+ } -+ } -+ } -+ -+ gemac_set_hash(priv->EMAC_baseaddr, &hash_addr); -+ } -+ -+ if (!(netdev_uc_count(ndev) >= MAX_UC_SPEC_ADDR_REG)) { -+ /* -+ * Check if there are any specific address HW registers that -+ * need to be flushed -+ */ -+ for (uc_count = netdev_uc_count(ndev); uc_count < -+ MAX_UC_SPEC_ADDR_REG; uc_count++) -+ gemac_clear_laddrN(priv->EMAC_baseaddr, uc_count + 2); -+ } -+ -+ if (ndev->flags & IFF_LOOPBACK) -+ gemac_set_loop(priv->EMAC_baseaddr, LB_LOCAL); -+} -+ -+/* pfe_eth_set_features -+ */ -+static int pfe_eth_set_features(struct net_device *ndev, netdev_features_t -+ features) -+{ -+ struct pfe_eth_priv_s *priv = netdev_priv(ndev); -+ int rc = 0; -+ -+ if (features & NETIF_F_RXCSUM) -+ gemac_enable_rx_checksum_offload(priv->EMAC_baseaddr); -+ else -+ gemac_disable_rx_checksum_offload(priv->EMAC_baseaddr); -+ return rc; -+} -+ -+/* pfe_eth_fast_tx_timeout -+ */ -+static enum hrtimer_restart pfe_eth_fast_tx_timeout(struct hrtimer *timer) -+{ -+ struct pfe_eth_fast_timer *fast_tx_timeout = container_of(timer, struct -+ pfe_eth_fast_timer, -+ timer); -+ struct pfe_eth_priv_s *priv = container_of(fast_tx_timeout->base, -+ struct pfe_eth_priv_s, -+ fast_tx_timeout); -+ struct netdev_queue *tx_queue = netdev_get_tx_queue(priv->ndev, -+ fast_tx_timeout->queuenum); -+ -+ if (netif_tx_queue_stopped(tx_queue)) { -+#ifdef PFE_ETH_TX_STATS -+ priv->was_stopped[fast_tx_timeout->queuenum] = 1; -+#endif -+ netif_tx_wake_queue(tx_queue); -+ } -+ -+ return HRTIMER_NORESTART; -+} -+ -+/* pfe_eth_fast_tx_timeout_init -+ */ -+static void pfe_eth_fast_tx_timeout_init(struct pfe_eth_priv_s *priv) -+{ -+ int i; -+ -+ for (i = 0; i < emac_txq_cnt; i++) { -+ priv->fast_tx_timeout[i].queuenum = i; -+ hrtimer_init(&priv->fast_tx_timeout[i].timer, CLOCK_MONOTONIC, -+ HRTIMER_MODE_REL); -+ priv->fast_tx_timeout[i].timer.function = -+ pfe_eth_fast_tx_timeout; -+ priv->fast_tx_timeout[i].base = priv->fast_tx_timeout; -+ } -+} -+ -+static struct sk_buff *pfe_eth_rx_skb(struct net_device *ndev, -+ struct pfe_eth_priv_s *priv, -+ unsigned int qno) -+{ -+ void *buf_addr; -+ unsigned int rx_ctrl; -+ unsigned int desc_ctrl = 0; -+ struct hif_ipsec_hdr *ipsec_hdr = NULL; -+ struct sk_buff *skb; -+ struct sk_buff *skb_frag, *skb_frag_last = NULL; -+ int length = 0, offset; -+ -+ skb = priv->skb_inflight[qno]; -+ -+ if (skb) { -+ skb_frag_last = skb_shinfo(skb)->frag_list; -+ if (skb_frag_last) { -+ while (skb_frag_last->next) -+ skb_frag_last = skb_frag_last->next; -+ } -+ } -+ -+ while (!(desc_ctrl & CL_DESC_LAST)) { -+ buf_addr = hif_lib_receive_pkt(&priv->client, qno, &length, -+ &offset, &rx_ctrl, &desc_ctrl, -+ (void **)&ipsec_hdr); -+ if (!buf_addr) -+ goto incomplete; -+ -+#ifdef PFE_ETH_NAPI_STATS -+ priv->napi_counters[NAPI_DESC_COUNT]++; -+#endif -+ -+ /* First frag */ -+ if (desc_ctrl & CL_DESC_FIRST) { -+ skb = build_skb(buf_addr, 0); -+ if (unlikely(!skb)) -+ goto pkt_drop; -+ -+ skb_reserve(skb, offset); -+ skb_put(skb, length); -+ skb->dev = ndev; -+ -+ if ((ndev->features & NETIF_F_RXCSUM) && (rx_ctrl & -+ HIF_CTRL_RX_CHECKSUMMED)) -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ else -+ skb_checksum_none_assert(skb); -+ -+ } else { -+ /* Next frags */ -+ if (unlikely(!skb)) { -+ pr_err("%s: NULL skb_inflight\n", -+ __func__); -+ goto pkt_drop; -+ } -+ -+ skb_frag = build_skb(buf_addr, 0); -+ -+ if (unlikely(!skb_frag)) { -+ kfree(buf_addr); -+ goto pkt_drop; -+ } -+ -+ skb_reserve(skb_frag, offset); -+ skb_put(skb_frag, length); -+ -+ skb_frag->dev = ndev; -+ -+ if (skb_shinfo(skb)->frag_list) -+ skb_frag_last->next = skb_frag; -+ else -+ skb_shinfo(skb)->frag_list = skb_frag; -+ -+ skb->truesize += skb_frag->truesize; -+ skb->data_len += length; -+ skb->len += length; -+ skb_frag_last = skb_frag; -+ } -+ } -+ -+ priv->skb_inflight[qno] = NULL; -+ return skb; -+ -+incomplete: -+ priv->skb_inflight[qno] = skb; -+ return NULL; -+ -+pkt_drop: -+ priv->skb_inflight[qno] = NULL; -+ -+ if (skb) -+ kfree_skb(skb); -+ else -+ kfree(buf_addr); -+ -+ priv->stats.rx_errors++; -+ -+ return NULL; -+} -+ -+/* pfe_eth_poll -+ */ -+static int pfe_eth_poll(struct pfe_eth_priv_s *priv, struct napi_struct *napi, -+ unsigned int qno, int budget) -+{ -+ struct net_device *ndev = priv->ndev; -+ struct sk_buff *skb; -+ int work_done = 0; -+ unsigned int len; -+ -+ netif_info(priv, intr, priv->ndev, "%s\n", __func__); -+ -+#ifdef PFE_ETH_NAPI_STATS -+ priv->napi_counters[NAPI_POLL_COUNT]++; -+#endif -+ -+ do { -+ skb = pfe_eth_rx_skb(ndev, priv, qno); -+ -+ if (!skb) -+ break; -+ -+ len = skb->len; -+ -+ /* Packet will be processed */ -+ skb->protocol = eth_type_trans(skb, ndev); -+ -+ netif_receive_skb(skb); -+ -+ priv->stats.rx_packets++; -+ priv->stats.rx_bytes += len; -+ -+ work_done++; -+ -+#ifdef PFE_ETH_NAPI_STATS -+ priv->napi_counters[NAPI_PACKET_COUNT]++; -+#endif -+ -+ } while (work_done < budget); -+ -+ /* -+ * If no Rx receive nor cleanup work was done, exit polling mode. -+ * No more netif_running(dev) check is required here , as this is -+ * checked in net/core/dev.c (2.6.33.5 kernel specific). -+ */ -+ if (work_done < budget) { -+ napi_complete(napi); -+ -+ hif_lib_event_handler_start(&priv->client, EVENT_RX_PKT_IND, -+ qno); -+ } -+#ifdef PFE_ETH_NAPI_STATS -+ else -+ priv->napi_counters[NAPI_FULL_BUDGET_COUNT]++; -+#endif -+ -+ return work_done; -+} -+ -+/* -+ * pfe_eth_lro_poll -+ */ -+static int pfe_eth_lro_poll(struct napi_struct *napi, int budget) -+{ -+ struct pfe_eth_priv_s *priv = container_of(napi, struct pfe_eth_priv_s, -+ lro_napi); -+ -+ netif_info(priv, intr, priv->ndev, "%s\n", __func__); -+ -+ return pfe_eth_poll(priv, napi, 2, budget); -+} -+ -+/* pfe_eth_low_poll -+ */ -+static int pfe_eth_low_poll(struct napi_struct *napi, int budget) -+{ -+ struct pfe_eth_priv_s *priv = container_of(napi, struct pfe_eth_priv_s, -+ low_napi); -+ -+ netif_info(priv, intr, priv->ndev, "%s\n", __func__); -+ -+ return pfe_eth_poll(priv, napi, 1, budget); -+} -+ -+/* pfe_eth_high_poll -+ */ -+static int pfe_eth_high_poll(struct napi_struct *napi, int budget) -+{ -+ struct pfe_eth_priv_s *priv = container_of(napi, struct pfe_eth_priv_s, -+ high_napi); -+ -+ netif_info(priv, intr, priv->ndev, "%s\n", __func__); -+ -+ return pfe_eth_poll(priv, napi, 0, budget); -+} -+ -+static const struct net_device_ops pfe_netdev_ops = { -+ .ndo_open = pfe_eth_open, -+ .ndo_stop = pfe_eth_close, -+ .ndo_start_xmit = pfe_eth_send_packet, -+ .ndo_select_queue = pfe_eth_select_queue, -+ .ndo_set_rx_mode = pfe_eth_set_multi, -+ .ndo_set_mac_address = pfe_eth_set_mac_address, -+ .ndo_validate_addr = eth_validate_addr, -+ .ndo_change_mtu = pfe_eth_change_mtu, -+ .ndo_get_stats = pfe_eth_get_stats, -+ .ndo_set_features = pfe_eth_set_features, -+}; -+ -+/* pfe_eth_init_one -+ */ -+static int pfe_eth_init_one(struct pfe *pfe, -+ struct ls1012a_pfe_platform_data *pfe_info, -+ int id) -+{ -+ struct net_device *ndev = NULL; -+ struct pfe_eth_priv_s *priv = NULL; -+ struct ls1012a_eth_platform_data *einfo; -+ int err; -+ -+ einfo = (struct ls1012a_eth_platform_data *) -+ pfe_info->ls1012a_eth_pdata; -+ -+ /* einfo never be NULL, but no harm in having this check */ -+ if (!einfo) { -+ pr_err( -+ "%s: pfe missing additional gemacs platform data\n" -+ , __func__); -+ err = -ENODEV; -+ goto err0; -+ } -+ -+ if (us) -+ emac_txq_cnt = EMAC_TXQ_CNT; -+ /* Create an ethernet device instance */ -+ ndev = alloc_etherdev_mq(sizeof(*priv), emac_txq_cnt); -+ -+ if (!ndev) { -+ pr_err("%s: gemac %d device allocation failed\n", -+ __func__, einfo[id].gem_id); -+ err = -ENOMEM; -+ goto err0; -+ } -+ -+ priv = netdev_priv(ndev); -+ priv->ndev = ndev; -+ priv->id = einfo[id].gem_id; -+ priv->pfe = pfe; -+ priv->phy_node = einfo[id].phy_node; -+ -+ SET_NETDEV_DEV(priv->ndev, priv->pfe->dev); -+ -+ pfe->eth.eth_priv[id] = priv; -+ -+ /* Set the info in the priv to the current info */ -+ priv->einfo = &einfo[id]; -+ priv->EMAC_baseaddr = cbus_emac_base[id]; -+ priv->GPI_baseaddr = cbus_gpi_base[id]; -+ -+ spin_lock_init(&priv->lock); -+ -+ pfe_eth_fast_tx_timeout_init(priv); -+ -+ /* Copy the station address into the dev structure, */ -+ dev_addr_set(ndev, einfo[id].mac_addr); -+ -+ if (us) -+ goto phy_init; -+ -+ ndev->mtu = 1500; -+ -+ /* Set MTU limits */ -+ ndev->min_mtu = ETH_MIN_MTU; -+ -+/* -+ * Jumbo frames are not supported on LS1012A rev-1.0. -+ * So max mtu should be restricted to supported frame length. -+ */ -+ if (pfe_errata_a010897) -+ ndev->max_mtu = JUMBO_FRAME_SIZE_V1 - ETH_HLEN - ETH_FCS_LEN; -+ else -+ ndev->max_mtu = JUMBO_FRAME_SIZE_V2 - ETH_HLEN - ETH_FCS_LEN; -+ -+ /*Enable after checksum offload is validated */ -+ ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | -+ NETIF_F_IPV6_CSUM | NETIF_F_SG; -+ -+ /* enabled by default */ -+ ndev->features = ndev->hw_features; -+ -+ priv->usr_features = ndev->features; -+ -+ ndev->netdev_ops = &pfe_netdev_ops; -+ -+ ndev->ethtool_ops = &pfe_ethtool_ops; -+ -+ /* Enable basic messages by default */ -+ priv->msg_enable = NETIF_MSG_IFUP | NETIF_MSG_IFDOWN | NETIF_MSG_LINK | -+ NETIF_MSG_PROBE; -+ -+ netif_napi_add(ndev, &priv->low_napi, pfe_eth_low_poll); -+ netif_napi_add(ndev, &priv->high_napi, pfe_eth_high_poll); -+ netif_napi_add(ndev, &priv->lro_napi, pfe_eth_lro_poll); -+ -+ err = register_netdev(ndev); -+ if (err) { -+ netdev_err(ndev, "register_netdev() failed\n"); -+ goto err1; -+ } -+ -+ if ((!(pfe_use_old_dts_phy) && !(priv->phy_node)) || -+ ((pfe_use_old_dts_phy) && -+ (priv->einfo->phy_flags & GEMAC_NO_PHY))) { -+ pr_info("%s: No PHY or fixed-link\n", __func__); -+ goto skip_phy_init; -+ } -+ -+phy_init: -+ device_init_wakeup(&ndev->dev, true); -+ -+ err = pfe_phy_init(ndev); -+ if (err) { -+ netdev_err(ndev, "%s: pfe_phy_init() failed\n", -+ __func__); -+ goto err2; -+ } -+ -+ if (us) { -+ if (priv->phydev) -+ phy_start(priv->phydev); -+ return 0; -+ } -+ -+ netif_carrier_on(ndev); -+ -+skip_phy_init: -+ /* Create all the sysfs files */ -+ if (pfe_eth_sysfs_init(ndev)) -+ goto err3; -+ -+ netif_info(priv, probe, ndev, "%s: created interface, baseaddr: %p\n", -+ __func__, priv->EMAC_baseaddr); -+ -+ return 0; -+ -+err3: -+ pfe_phy_exit(priv->ndev); -+err2: -+ if (us) -+ goto err1; -+ unregister_netdev(ndev); -+err1: -+ free_netdev(priv->ndev); -+err0: -+ return err; -+} -+ -+/* pfe_eth_init -+ */ -+int pfe_eth_init(struct pfe *pfe) -+{ -+ int ii = 0; -+ int err; -+ struct ls1012a_pfe_platform_data *pfe_info; -+ -+ pr_info("%s\n", __func__); -+ -+ cbus_emac_base[0] = EMAC1_BASE_ADDR; -+ cbus_emac_base[1] = EMAC2_BASE_ADDR; -+ -+ cbus_gpi_base[0] = EGPI1_BASE_ADDR; -+ cbus_gpi_base[1] = EGPI2_BASE_ADDR; -+ -+ pfe_info = (struct ls1012a_pfe_platform_data *) -+ pfe->dev->platform_data; -+ if (!pfe_info) { -+ pr_err("%s: pfe missing additional platform data\n", __func__); -+ err = -ENODEV; -+ goto err_pdata; -+ } -+ -+ for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) { -+ err = pfe_eth_mdio_init(pfe, pfe_info, ii); -+ if (err) { -+ pr_err("%s: pfe_eth_mdio_init() failed\n", __func__); -+ goto err_mdio_init; -+ } -+ } -+ -+ if (soc_device_match(ls1012a_rev1_soc_attr)) -+ pfe_errata_a010897 = true; -+ else -+ pfe_errata_a010897 = false; -+ -+ for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) { -+ err = pfe_eth_init_one(pfe, pfe_info, ii); -+ if (err) -+ goto err_eth_init; -+ } -+ -+ return 0; -+ -+err_eth_init: -+ while (ii--) { -+ pfe_eth_exit_one(pfe->eth.eth_priv[ii]); -+ pfe_eth_mdio_exit(pfe, ii); -+ } -+ -+err_mdio_init: -+err_pdata: -+ return err; -+} -+ -+/* pfe_eth_exit_one -+ */ -+static void pfe_eth_exit_one(struct pfe_eth_priv_s *priv) -+{ -+ netif_info(priv, probe, priv->ndev, "%s\n", __func__); -+ -+ if (!us) -+ pfe_eth_sysfs_exit(priv->ndev); -+ -+ if ((!(pfe_use_old_dts_phy) && !(priv->phy_node)) || -+ ((pfe_use_old_dts_phy) && -+ (priv->einfo->phy_flags & GEMAC_NO_PHY))) { -+ pr_info("%s: No PHY or fixed-link\n", __func__); -+ goto skip_phy_exit; -+ } -+ -+ pfe_phy_exit(priv->ndev); -+ -+skip_phy_exit: -+ if (!us) -+ unregister_netdev(priv->ndev); -+ -+ free_netdev(priv->ndev); -+} -+ -+/* pfe_eth_exit -+ */ -+void pfe_eth_exit(struct pfe *pfe) -+{ -+ int ii; -+ -+ pr_info("%s\n", __func__); -+ -+ for (ii = NUM_GEMAC_SUPPORT - 1; ii >= 0; ii--) -+ pfe_eth_exit_one(pfe->eth.eth_priv[ii]); -+ -+ for (ii = NUM_GEMAC_SUPPORT - 1; ii >= 0; ii--) -+ pfe_eth_mdio_exit(pfe, ii); -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_eth.h -@@ -0,0 +1,175 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#ifndef _PFE_ETH_H_ -+#define _PFE_ETH_H_ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define PFE_ETH_NAPI_STATS -+#define PFE_ETH_TX_STATS -+ -+#define PFE_ETH_FRAGS_MAX (65536 / HIF_RX_PKT_MIN_SIZE) -+#define LRO_LEN_COUNT_MAX 32 -+#define LRO_NB_COUNT_MAX 32 -+ -+#define PFE_PAUSE_FLAG_ENABLE 1 -+#define PFE_PAUSE_FLAG_AUTONEG 2 -+ -+/* GEMAC configured by SW */ -+/* GEMAC configured by phy lines (not for MII/GMII) */ -+ -+#define GEMAC_SW_FULL_DUPLEX BIT(9) -+#define GEMAC_SW_SPEED_10M (0 << 12) -+#define GEMAC_SW_SPEED_100M BIT(12) -+#define GEMAC_SW_SPEED_1G (2 << 12) -+ -+#define GEMAC_NO_PHY BIT(0) -+ -+struct ls1012a_eth_platform_data { -+ /* board specific information */ -+ phy_interface_t mii_config; -+ u32 phy_flags; -+ u32 gem_id; -+ u32 phy_id; -+ u32 mdio_muxval; -+ u8 mac_addr[ETH_ALEN]; -+ struct device_node *phy_node; -+}; -+ -+struct ls1012a_mdio_platform_data { -+ int id; -+ int irq[32]; -+ u32 phy_mask; -+ int mdc_div; -+}; -+ -+struct ls1012a_pfe_platform_data { -+ struct ls1012a_eth_platform_data ls1012a_eth_pdata[3]; -+ struct ls1012a_mdio_platform_data ls1012a_mdio_pdata[3]; -+}; -+ -+#define NUM_GEMAC_SUPPORT 2 -+#define DRV_NAME "pfe-eth" -+#define DRV_VERSION "1.0" -+ -+#define LS1012A_TX_FAST_RECOVERY_TIMEOUT_MS 3 -+#define TX_POLL_TIMEOUT_MS 1000 -+ -+#define EMAC_TXQ_CNT 16 -+#define EMAC_TXQ_DEPTH (HIF_TX_DESC_NT) -+ -+#define JUMBO_FRAME_SIZE_V1 1900 -+#define JUMBO_FRAME_SIZE_V2 10258 -+/* -+ * Client Tx queue threshold, for txQ flush condition. -+ * It must be smaller than the queue size (in case we ever change it in the -+ * future). -+ */ -+#define HIF_CL_TX_FLUSH_MARK 32 -+ -+/* -+ * Max number of TX resources (HIF descriptors or skbs) that will be released -+ * in a single go during batch recycling. -+ * Should be lower than the flush mark so the SW can provide the HW with a -+ * continuous stream of packets instead of bursts. -+ */ -+#define TX_FREE_MAX_COUNT 16 -+#define EMAC_RXQ_CNT 3 -+#define EMAC_RXQ_DEPTH HIF_RX_DESC_NT -+/* make sure clients can receive a full burst of packets */ -+#define EMAC_RMON_TXBYTES_POS 0x00 -+#define EMAC_RMON_RXBYTES_POS 0x14 -+ -+#define EMAC_QUEUENUM_MASK (emac_txq_cnt - 1) -+#define EMAC_MDIO_TIMEOUT 1000 -+#define MAX_UC_SPEC_ADDR_REG 31 -+ -+struct pfe_eth_fast_timer { -+ int queuenum; -+ struct hrtimer timer; -+ void *base; -+}; -+ -+struct pfe_eth_priv_s { -+ struct pfe *pfe; -+ struct hif_client_s client; -+ struct napi_struct lro_napi; -+ struct napi_struct low_napi; -+ struct napi_struct high_napi; -+ int low_tmu_q; -+ int high_tmu_q; -+ struct net_device_stats stats; -+ struct net_device *ndev; -+ int id; -+ int promisc; -+ unsigned int msg_enable; -+ unsigned int usr_features; -+ -+ spinlock_t lock; /* protect member variables */ -+ unsigned int event_status; -+ int irq; -+ void *EMAC_baseaddr; -+ void *GPI_baseaddr; -+ /* PHY stuff */ -+ struct phy_device *phydev; -+ int oldspeed; -+ int oldduplex; -+ int oldlink; -+ struct device_node *phy_node; -+ struct clk *gemtx_clk; -+ int wol; -+ int pause_flag; -+ -+ int default_priority; -+ struct pfe_eth_fast_timer fast_tx_timeout[EMAC_TXQ_CNT]; -+ -+ struct ls1012a_eth_platform_data *einfo; -+ struct sk_buff *skb_inflight[EMAC_RXQ_CNT + 6]; -+ -+#ifdef PFE_ETH_TX_STATS -+ unsigned int stop_queue_total[EMAC_TXQ_CNT]; -+ unsigned int stop_queue_hif[EMAC_TXQ_CNT]; -+ unsigned int stop_queue_hif_client[EMAC_TXQ_CNT]; -+ unsigned int stop_queue_credit[EMAC_TXQ_CNT]; -+ unsigned int clean_fail[EMAC_TXQ_CNT]; -+ unsigned int was_stopped[EMAC_TXQ_CNT]; -+#endif -+ -+#ifdef PFE_ETH_NAPI_STATS -+ unsigned int napi_counters[NAPI_MAX_COUNT]; -+#endif -+ unsigned int frags_inflight[EMAC_RXQ_CNT + 6]; -+}; -+ -+struct pfe_eth { -+ struct pfe_eth_priv_s *eth_priv[3]; -+}; -+ -+struct pfe_mdio_priv_s { -+ void __iomem *mdio_base; -+ int mdc_div; -+ struct mii_bus *mii_bus; -+}; -+ -+struct pfe_mdio { -+ struct pfe_mdio_priv_s *mdio_priv[3]; -+}; -+ -+int pfe_eth_init(struct pfe *pfe); -+void pfe_eth_exit(struct pfe *pfe); -+int pfe_eth_suspend(struct net_device *dev); -+int pfe_eth_resume(struct net_device *dev); -+int pfe_eth_mdio_reset(struct mii_bus *bus); -+ -+#endif /* _PFE_ETH_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_firmware.c -@@ -0,0 +1,398 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+/* -+ * @file -+ * Contains all the functions to handle parsing and loading of PE firmware -+ * files. -+ */ -+#include -+ -+#include "pfe_mod.h" -+#include "pfe_firmware.h" -+#include "pfe/pfe.h" -+#include -+#include -+ -+static struct elf32_shdr *get_elf_section_header(const u8 *fw, -+ const char *section) -+{ -+ struct elf32_hdr *elf_hdr = (struct elf32_hdr *)fw; -+ struct elf32_shdr *shdr; -+ struct elf32_shdr *shdr_shstr; -+ Elf32_Off e_shoff = be32_to_cpu(elf_hdr->e_shoff); -+ Elf32_Half e_shentsize = be16_to_cpu(elf_hdr->e_shentsize); -+ Elf32_Half e_shnum = be16_to_cpu(elf_hdr->e_shnum); -+ Elf32_Half e_shstrndx = be16_to_cpu(elf_hdr->e_shstrndx); -+ Elf32_Off shstr_offset; -+ Elf32_Word sh_name; -+ const char *name; -+ int i; -+ -+ /* Section header strings */ -+ shdr_shstr = (struct elf32_shdr *)((u8 *)elf_hdr + e_shoff + e_shstrndx -+ * e_shentsize); -+ shstr_offset = be32_to_cpu(shdr_shstr->sh_offset); -+ -+ for (i = 0; i < e_shnum; i++) { -+ shdr = (struct elf32_shdr *)((u8 *)elf_hdr + e_shoff -+ + i * e_shentsize); -+ -+ sh_name = be32_to_cpu(shdr->sh_name); -+ -+ name = (const char *)((u8 *)elf_hdr + shstr_offset + sh_name); -+ -+ if (!strcmp(name, section)) -+ return shdr; -+ } -+ -+ pr_err("%s: didn't find section %s\n", __func__, section); -+ -+ return NULL; -+} -+ -+#if defined(CFG_DIAGS) -+static int pfe_get_diags_info(const u8 *fw, struct pfe_diags_info -+ *diags_info) -+{ -+ struct elf32_shdr *shdr; -+ unsigned long offset, size; -+ -+ shdr = get_elf_section_header(fw, ".pfe_diags_str"); -+ if (shdr) { -+ offset = be32_to_cpu(shdr->sh_offset); -+ size = be32_to_cpu(shdr->sh_size); -+ diags_info->diags_str_base = be32_to_cpu(shdr->sh_addr); -+ diags_info->diags_str_size = size; -+ diags_info->diags_str_array = kmalloc(size, GFP_KERNEL); -+ memcpy(diags_info->diags_str_array, fw + offset, size); -+ -+ return 0; -+ } else { -+ return -1; -+ } -+} -+#endif -+ -+static void pfe_check_version_info(const u8 *fw) -+{ -+ /*static char *version = NULL;*/ -+ const u8 *elf_data = fw; -+ static char *version; -+ -+ struct elf32_shdr *shdr = get_elf_section_header(fw, ".version"); -+ -+ if (shdr) { -+ if (!version) { -+ /* -+ * this is the first fw we load, use its version -+ * string as reference (whatever it is) -+ */ -+ version = (char *)(elf_data + -+ be32_to_cpu(shdr->sh_offset)); -+ -+ pr_info("PFE binary version: %s\n", version); -+ } else { -+ /* -+ * already have loaded at least one firmware, check -+ * sequence can start now -+ */ -+ if (strcmp(version, (char *)(elf_data + -+ be32_to_cpu(shdr->sh_offset)))) { -+ pr_info( -+ "WARNING: PFE firmware binaries from incompatible version\n"); -+ } -+ } -+ } else { -+ /* -+ * version cannot be verified, a potential issue that should -+ * be reported -+ */ -+ pr_info( -+ "WARNING: PFE firmware binaries from incompatible version\n"); -+ } -+} -+ -+/* PFE elf firmware loader. -+ * Loads an elf firmware image into a list of PE's (specified using a bitmask) -+ * -+ * @param pe_mask Mask of PE id's to load firmware to -+ * @param fw Pointer to the firmware image -+ * -+ * @return 0 on success, a negative value on error -+ * -+ */ -+static int pfe_load_elf(int pe_mask, const u8 *fw, struct pfe *pfe) -+{ -+ struct elf32_hdr *elf_hdr = (struct elf32_hdr *)fw; -+ Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum); -+ struct elf32_shdr *shdr = (struct elf32_shdr *)(fw + -+ be32_to_cpu(elf_hdr->e_shoff)); -+ int id, section; -+ int rc; -+ -+ pr_info("%s\n", __func__); -+ -+ /* Some sanity checks */ -+ if (strncmp(&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) { -+ pr_err("%s: incorrect elf magic number\n", __func__); -+ return -EINVAL; -+ } -+ -+ if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) { -+ pr_err("%s: incorrect elf class(%x)\n", __func__, -+ elf_hdr->e_ident[EI_CLASS]); -+ return -EINVAL; -+ } -+ -+ if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) { -+ pr_err("%s: incorrect elf data(%x)\n", __func__, -+ elf_hdr->e_ident[EI_DATA]); -+ return -EINVAL; -+ } -+ -+ if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) { -+ pr_err("%s: incorrect elf file type(%x)\n", __func__, -+ be16_to_cpu(elf_hdr->e_type)); -+ return -EINVAL; -+ } -+ -+ for (section = 0; section < sections; section++, shdr++) { -+ if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC | -+ SHF_EXECINSTR))) -+ continue; -+ -+ for (id = 0; id < MAX_PE; id++) -+ if (pe_mask & (1 << id)) { -+ rc = pe_load_elf_section(id, elf_hdr, shdr, -+ pfe->dev); -+ if (rc < 0) -+ goto err; -+ } -+ } -+ -+ pfe_check_version_info(fw); -+ -+ return 0; -+ -+err: -+ return rc; -+} -+ -+static int get_firmware_in_fdt(const u8 **pe_fw, const char *name) -+{ -+ struct device_node *np; -+ const unsigned int *len; -+ const void *data; -+ -+ if (!strcmp(name, CLASS_FIRMWARE_FILENAME)) { -+ /* The firmware should be inside the device tree. */ -+ np = of_find_compatible_node(NULL, NULL, -+ "fsl,pfe-class-firmware"); -+ if (!np) { -+ pr_info("Failed to find the node\n"); -+ return -ENOENT; -+ } -+ -+ data = of_get_property(np, "fsl,class-firmware", NULL); -+ if (data) { -+ len = of_get_property(np, "length", NULL); -+ pr_info("CLASS fw of length %d bytes loaded from FDT.\n", -+ be32_to_cpu(*len)); -+ } else { -+ pr_info("fsl,class-firmware not found!!!!\n"); -+ return -ENOENT; -+ } -+ of_node_put(np); -+ *pe_fw = data; -+ } else if (!strcmp(name, TMU_FIRMWARE_FILENAME)) { -+ np = of_find_compatible_node(NULL, NULL, -+ "fsl,pfe-tmu-firmware"); -+ if (!np) { -+ pr_info("Failed to find the node\n"); -+ return -ENOENT; -+ } -+ -+ data = of_get_property(np, "fsl,tmu-firmware", NULL); -+ if (data) { -+ len = of_get_property(np, "length", NULL); -+ pr_info("TMU fw of length %d bytes loaded from FDT.\n", -+ be32_to_cpu(*len)); -+ } else { -+ pr_info("fsl,tmu-firmware not found!!!!\n"); -+ return -ENOENT; -+ } -+ of_node_put(np); -+ *pe_fw = data; -+ } else if (!strcmp(name, UTIL_FIRMWARE_FILENAME)) { -+ np = of_find_compatible_node(NULL, NULL, -+ "fsl,pfe-util-firmware"); -+ if (!np) { -+ pr_info("Failed to find the node\n"); -+ return -ENOENT; -+ } -+ -+ data = of_get_property(np, "fsl,util-firmware", NULL); -+ if (data) { -+ len = of_get_property(np, "length", NULL); -+ pr_info("UTIL fw of length %d bytes loaded from FDT.\n", -+ be32_to_cpu(*len)); -+ } else { -+ pr_info("fsl,util-firmware not found!!!!\n"); -+ return -ENOENT; -+ } -+ of_node_put(np); -+ *pe_fw = data; -+ } else { -+ pr_err("firmware:%s not known\n", name); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* PFE firmware initialization. -+ * Loads different firmware files from filesystem. -+ * Initializes PE IMEM/DMEM and UTIL-PE DDR -+ * Initializes control path symbol addresses (by looking them up in the elf -+ * firmware files -+ * Takes PE's out of reset -+ * -+ * @return 0 on success, a negative value on error -+ * -+ */ -+int pfe_firmware_init(struct pfe *pfe) -+{ -+ const struct firmware *class_fw, *tmu_fw; -+ const u8 *class_elf_fw, *tmu_elf_fw; -+ int rc = 0, fs_load = 0; -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ const struct firmware *util_fw; -+ const u8 *util_elf_fw; -+ -+#endif -+ -+ pr_info("%s\n", __func__); -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ if (get_firmware_in_fdt(&class_elf_fw, CLASS_FIRMWARE_FILENAME) || -+ get_firmware_in_fdt(&tmu_elf_fw, TMU_FIRMWARE_FILENAME) || -+ get_firmware_in_fdt(&util_elf_fw, UTIL_FIRMWARE_FILENAME)) -+#else -+ if (get_firmware_in_fdt(&class_elf_fw, CLASS_FIRMWARE_FILENAME) || -+ get_firmware_in_fdt(&tmu_elf_fw, TMU_FIRMWARE_FILENAME)) -+#endif -+ { -+ pr_info("%s:PFE firmware not found in FDT.\n", __func__); -+ pr_info("%s:Trying to load firmware from filesystem...!\n", __func__); -+ -+ /* look for firmware in filesystem...!*/ -+ fs_load = 1; -+ if (request_firmware(&class_fw, CLASS_FIRMWARE_FILENAME, pfe->dev)) { -+ pr_err("%s: request firmware %s failed\n", __func__, -+ CLASS_FIRMWARE_FILENAME); -+ rc = -ETIMEDOUT; -+ goto err0; -+ } -+ class_elf_fw = class_fw->data; -+ -+ if (request_firmware(&tmu_fw, TMU_FIRMWARE_FILENAME, pfe->dev)) { -+ pr_err("%s: request firmware %s failed\n", __func__, -+ TMU_FIRMWARE_FILENAME); -+ rc = -ETIMEDOUT; -+ goto err1; -+ } -+ tmu_elf_fw = tmu_fw->data; -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ if (request_firmware(&util_fw, UTIL_FIRMWARE_FILENAME, pfe->dev)) { -+ pr_err("%s: request firmware %s failed\n", __func__, -+ UTIL_FIRMWARE_FILENAME); -+ rc = -ETIMEDOUT; -+ goto err2; -+ } -+ util_elf_fw = util_fw->data; -+#endif -+ } -+ -+ rc = pfe_load_elf(CLASS_MASK, class_elf_fw, pfe); -+ if (rc < 0) { -+ pr_err("%s: class firmware load failed\n", __func__); -+ goto err3; -+ } -+ -+#if defined(CFG_DIAGS) -+ rc = pfe_get_diags_info(class_elf_fw, &pfe->diags.class_diags_info); -+ if (rc < 0) { -+ pr_warn( -+ "PFE diags won't be available for class PEs\n"); -+ rc = 0; -+ } -+#endif -+ -+ rc = pfe_load_elf(TMU_MASK, tmu_elf_fw, pfe); -+ if (rc < 0) { -+ pr_err("%s: tmu firmware load failed\n", __func__); -+ goto err3; -+ } -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ rc = pfe_load_elf(UTIL_MASK, util_elf_fw, pfe); -+ if (rc < 0) { -+ pr_err("%s: util firmware load failed\n", __func__); -+ goto err3; -+ } -+ -+#if defined(CFG_DIAGS) -+ rc = pfe_get_diags_info(util_elf_fw, &pfe->diags.util_diags_info); -+ if (rc < 0) { -+ pr_warn( -+ "PFE diags won't be available for util PE\n"); -+ rc = 0; -+ } -+#endif -+ -+ util_enable(); -+#endif -+ -+ tmu_enable(0xf); -+ class_enable(); -+ -+err3: -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ if (fs_load) -+ release_firmware(util_fw); -+err2: -+#endif -+ if (fs_load) -+ release_firmware(tmu_fw); -+ -+err1: -+ if (fs_load) -+ release_firmware(class_fw); -+ -+err0: -+ return rc; -+} -+ -+/* PFE firmware cleanup -+ * Puts PE's in reset -+ * -+ * -+ */ -+void pfe_firmware_exit(struct pfe *pfe) -+{ -+ pr_info("%s\n", __func__); -+ -+ if (pe_reset_all(&pfe->ctrl) != 0) -+ pr_err("Error: Failed to stop PEs, PFE reload may not work correctly\n"); -+ -+ class_disable(); -+ tmu_disable(0xf); -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ util_disable(); -+#endif -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_firmware.h -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#ifndef _PFE_FIRMWARE_H_ -+#define _PFE_FIRMWARE_H_ -+ -+#define CLASS_FIRMWARE_FILENAME "ppfe_class_ls1012a.elf" -+#define TMU_FIRMWARE_FILENAME "ppfe_tmu_ls1012a.elf" -+#define UTIL_FIRMWARE_FILENAME "ppfe_util_ls1012a.elf" -+ -+#define PFE_FW_CHECK_PASS 0 -+#define PFE_FW_CHECK_FAIL 1 -+#define NUM_PFE_FW 3 -+ -+int pfe_firmware_init(struct pfe *pfe); -+void pfe_firmware_exit(struct pfe *pfe); -+ -+#endif /* _PFE_FIRMWARE_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_hal.c -@@ -0,0 +1,1517 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#include "pfe_mod.h" -+#include "pfe/pfe.h" -+ -+/* A-010897: Jumbo frame is not supported */ -+extern bool pfe_errata_a010897; -+ -+#define PFE_RCR_MAX_FL_MASK 0xC000FFFF -+ -+void *cbus_base_addr; -+void *ddr_base_addr; -+unsigned long ddr_phys_base_addr; -+unsigned int ddr_size; -+ -+static struct pe_info pe[MAX_PE]; -+ -+/* Initializes the PFE library. -+ * Must be called before using any of the library functions. -+ * -+ * @param[in] cbus_base CBUS virtual base address (as mapped in -+ * the host CPU address space) -+ * @param[in] ddr_base PFE DDR range virtual base address (as -+ * mapped in the host CPU address space) -+ * @param[in] ddr_phys_base PFE DDR range physical base address (as -+ * mapped in platform) -+ * @param[in] size PFE DDR range size (as defined by the host -+ * software) -+ */ -+void pfe_lib_init(void *cbus_base, void *ddr_base, unsigned long ddr_phys_base, -+ unsigned int size) -+{ -+ cbus_base_addr = cbus_base; -+ ddr_base_addr = ddr_base; -+ ddr_phys_base_addr = ddr_phys_base; -+ ddr_size = size; -+ -+ pe[CLASS0_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(0); -+ pe[CLASS0_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(0); -+ pe[CLASS0_ID].pmem_size = CLASS_IMEM_SIZE; -+ pe[CLASS0_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; -+ pe[CLASS0_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; -+ pe[CLASS0_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; -+ -+ pe[CLASS1_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(1); -+ pe[CLASS1_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(1); -+ pe[CLASS1_ID].pmem_size = CLASS_IMEM_SIZE; -+ pe[CLASS1_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; -+ pe[CLASS1_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; -+ pe[CLASS1_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; -+ -+ pe[CLASS2_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(2); -+ pe[CLASS2_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(2); -+ pe[CLASS2_ID].pmem_size = CLASS_IMEM_SIZE; -+ pe[CLASS2_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; -+ pe[CLASS2_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; -+ pe[CLASS2_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; -+ -+ pe[CLASS3_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(3); -+ pe[CLASS3_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(3); -+ pe[CLASS3_ID].pmem_size = CLASS_IMEM_SIZE; -+ pe[CLASS3_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; -+ pe[CLASS3_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; -+ pe[CLASS3_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; -+ -+ pe[CLASS4_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(4); -+ pe[CLASS4_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(4); -+ pe[CLASS4_ID].pmem_size = CLASS_IMEM_SIZE; -+ pe[CLASS4_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; -+ pe[CLASS4_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; -+ pe[CLASS4_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; -+ -+ pe[CLASS5_ID].dmem_base_addr = CLASS_DMEM_BASE_ADDR(5); -+ pe[CLASS5_ID].pmem_base_addr = CLASS_IMEM_BASE_ADDR(5); -+ pe[CLASS5_ID].pmem_size = CLASS_IMEM_SIZE; -+ pe[CLASS5_ID].mem_access_wdata = CLASS_MEM_ACCESS_WDATA; -+ pe[CLASS5_ID].mem_access_addr = CLASS_MEM_ACCESS_ADDR; -+ pe[CLASS5_ID].mem_access_rdata = CLASS_MEM_ACCESS_RDATA; -+ -+ pe[TMU0_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(0); -+ pe[TMU0_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(0); -+ pe[TMU0_ID].pmem_size = TMU_IMEM_SIZE; -+ pe[TMU0_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA; -+ pe[TMU0_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR; -+ pe[TMU0_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA; -+ -+ pe[TMU1_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(1); -+ pe[TMU1_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(1); -+ pe[TMU1_ID].pmem_size = TMU_IMEM_SIZE; -+ pe[TMU1_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA; -+ pe[TMU1_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR; -+ pe[TMU1_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA; -+ -+ pe[TMU3_ID].dmem_base_addr = TMU_DMEM_BASE_ADDR(3); -+ pe[TMU3_ID].pmem_base_addr = TMU_IMEM_BASE_ADDR(3); -+ pe[TMU3_ID].pmem_size = TMU_IMEM_SIZE; -+ pe[TMU3_ID].mem_access_wdata = TMU_MEM_ACCESS_WDATA; -+ pe[TMU3_ID].mem_access_addr = TMU_MEM_ACCESS_ADDR; -+ pe[TMU3_ID].mem_access_rdata = TMU_MEM_ACCESS_RDATA; -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ pe[UTIL_ID].dmem_base_addr = UTIL_DMEM_BASE_ADDR; -+ pe[UTIL_ID].mem_access_wdata = UTIL_MEM_ACCESS_WDATA; -+ pe[UTIL_ID].mem_access_addr = UTIL_MEM_ACCESS_ADDR; -+ pe[UTIL_ID].mem_access_rdata = UTIL_MEM_ACCESS_RDATA; -+#endif -+} -+ -+/* Writes a buffer to PE internal memory from the host -+ * through indirect access registers. -+ * -+ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, -+ * ..., UTIL_ID) -+ * @param[in] src Buffer source address -+ * @param[in] mem_access_addr DMEM destination address (must be 32bit -+ * aligned) -+ * @param[in] len Number of bytes to copy -+ */ -+static void pe_mem_memcpy_to32(int id, u32 mem_access_addr, const void *src, -+ unsigned int len) -+{ -+ u32 offset = 0, val, addr; -+ unsigned int len32 = len >> 2; -+ int i; -+ -+ addr = mem_access_addr | PE_MEM_ACCESS_WRITE | -+ PE_MEM_ACCESS_BYTE_ENABLE(0, 4); -+ -+ for (i = 0; i < len32; i++, offset += 4, src += 4) { -+ val = *(u32 *)src; -+ writel(cpu_to_be32(val), pe[id].mem_access_wdata); -+ writel(addr + offset, pe[id].mem_access_addr); -+ } -+ -+ len = (len & 0x3); -+ if (len) { -+ val = 0; -+ -+ addr = (mem_access_addr | PE_MEM_ACCESS_WRITE | -+ PE_MEM_ACCESS_BYTE_ENABLE(0, len)) + offset; -+ -+ for (i = 0; i < len; i++, src++) -+ val |= (*(u8 *)src) << (8 * i); -+ -+ writel(cpu_to_be32(val), pe[id].mem_access_wdata); -+ writel(addr, pe[id].mem_access_addr); -+ } -+} -+ -+/* Writes a buffer to PE internal data memory (DMEM) from the host -+ * through indirect access registers. -+ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, -+ * ..., UTIL_ID) -+ * @param[in] src Buffer source address -+ * @param[in] dst DMEM destination address (must be 32bit -+ * aligned) -+ * @param[in] len Number of bytes to copy -+ */ -+void pe_dmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len) -+{ -+ pe_mem_memcpy_to32(id, pe[id].dmem_base_addr | dst | -+ PE_MEM_ACCESS_DMEM, src, len); -+} -+ -+/* Writes a buffer to PE internal program memory (PMEM) from the host -+ * through indirect access registers. -+ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, -+ * ..., TMU3_ID) -+ * @param[in] src Buffer source address -+ * @param[in] dst PMEM destination address (must be 32bit -+ * aligned) -+ * @param[in] len Number of bytes to copy -+ */ -+void pe_pmem_memcpy_to32(int id, u32 dst, const void *src, unsigned int len) -+{ -+ pe_mem_memcpy_to32(id, pe[id].pmem_base_addr | (dst & (pe[id].pmem_size -+ - 1)) | PE_MEM_ACCESS_IMEM, src, len); -+} -+ -+/* Reads PE internal program memory (IMEM) from the host -+ * through indirect access registers. -+ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, -+ * ..., TMU3_ID) -+ * @param[in] addr PMEM read address (must be aligned on size) -+ * @param[in] size Number of bytes to read (maximum 4, must not -+ * cross 32bit boundaries) -+ * @return the data read (in PE endianness, i.e BE). -+ */ -+u32 pe_pmem_read(int id, u32 addr, u8 size) -+{ -+ u32 offset = addr & 0x3; -+ u32 mask = 0xffffffff >> ((4 - size) << 3); -+ u32 val; -+ -+ addr = pe[id].pmem_base_addr | ((addr & ~0x3) & (pe[id].pmem_size - 1)) -+ | PE_MEM_ACCESS_IMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size); -+ -+ writel(addr, pe[id].mem_access_addr); -+ val = be32_to_cpu(readl(pe[id].mem_access_rdata)); -+ -+ return (val >> (offset << 3)) & mask; -+} -+ -+/* Writes PE internal data memory (DMEM) from the host -+ * through indirect access registers. -+ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, -+ * ..., UTIL_ID) -+ * @param[in] addr DMEM write address (must be aligned on size) -+ * @param[in] val Value to write (in PE endianness, i.e BE) -+ * @param[in] size Number of bytes to write (maximum 4, must not -+ * cross 32bit boundaries) -+ */ -+void pe_dmem_write(int id, u32 val, u32 addr, u8 size) -+{ -+ u32 offset = addr & 0x3; -+ -+ addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_WRITE | -+ PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size); -+ -+ /* Indirect access interface is byte swapping data being written */ -+ writel(cpu_to_be32(val << (offset << 3)), pe[id].mem_access_wdata); -+ writel(addr, pe[id].mem_access_addr); -+} -+ -+/* Reads PE internal data memory (DMEM) from the host -+ * through indirect access registers. -+ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, -+ * ..., UTIL_ID) -+ * @param[in] addr DMEM read address (must be aligned on size) -+ * @param[in] size Number of bytes to read (maximum 4, must not -+ * cross 32bit boundaries) -+ * @return the data read (in PE endianness, i.e BE). -+ */ -+u32 pe_dmem_read(int id, u32 addr, u8 size) -+{ -+ u32 offset = addr & 0x3; -+ u32 mask = 0xffffffff >> ((4 - size) << 3); -+ u32 val; -+ -+ addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_DMEM | -+ PE_MEM_ACCESS_BYTE_ENABLE(offset, size); -+ -+ writel(addr, pe[id].mem_access_addr); -+ -+ /* Indirect access interface is byte swapping data being read */ -+ val = be32_to_cpu(readl(pe[id].mem_access_rdata)); -+ -+ return (val >> (offset << 3)) & mask; -+} -+ -+/* This function is used to write to CLASS internal bus peripherals (ccu, -+ * pe-lem) from the host -+ * through indirect access registers. -+ * @param[in] val value to write -+ * @param[in] addr Address to write to (must be aligned on size) -+ * @param[in] size Number of bytes to write (1, 2 or 4) -+ * -+ */ -+void class_bus_write(u32 val, u32 addr, u8 size) -+{ -+ u32 offset = addr & 0x3; -+ -+ writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE); -+ -+ addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | PE_MEM_ACCESS_WRITE | -+ (size << 24); -+ -+ writel(cpu_to_be32(val << (offset << 3)), CLASS_BUS_ACCESS_WDATA); -+ writel(addr, CLASS_BUS_ACCESS_ADDR); -+} -+ -+/* Reads from CLASS internal bus peripherals (ccu, pe-lem) from the host -+ * through indirect access registers. -+ * @param[in] addr Address to read from (must be aligned on size) -+ * @param[in] size Number of bytes to read (1, 2 or 4) -+ * @return the read data -+ * -+ */ -+u32 class_bus_read(u32 addr, u8 size) -+{ -+ u32 offset = addr & 0x3; -+ u32 mask = 0xffffffff >> ((4 - size) << 3); -+ u32 val; -+ -+ writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE); -+ -+ addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | (size << 24); -+ -+ writel(addr, CLASS_BUS_ACCESS_ADDR); -+ val = be32_to_cpu(readl(CLASS_BUS_ACCESS_RDATA)); -+ -+ return (val >> (offset << 3)) & mask; -+} -+ -+/* Writes data to the cluster memory (PE_LMEM) -+ * @param[in] dst PE LMEM destination address (must be 32bit aligned) -+ * @param[in] src Buffer source address -+ * @param[in] len Number of bytes to copy -+ */ -+void class_pe_lmem_memcpy_to32(u32 dst, const void *src, unsigned int len) -+{ -+ u32 len32 = len >> 2; -+ int i; -+ -+ for (i = 0; i < len32; i++, src += 4, dst += 4) -+ class_bus_write(*(u32 *)src, dst, 4); -+ -+ if (len & 0x2) { -+ class_bus_write(*(u16 *)src, dst, 2); -+ src += 2; -+ dst += 2; -+ } -+ -+ if (len & 0x1) { -+ class_bus_write(*(u8 *)src, dst, 1); -+ src++; -+ dst++; -+ } -+} -+ -+/* Writes value to the cluster memory (PE_LMEM) -+ * @param[in] dst PE LMEM destination address (must be 32bit aligned) -+ * @param[in] val Value to write -+ * @param[in] len Number of bytes to write -+ */ -+void class_pe_lmem_memset(u32 dst, int val, unsigned int len) -+{ -+ u32 len32 = len >> 2; -+ int i; -+ -+ val = val | (val << 8) | (val << 16) | (val << 24); -+ -+ for (i = 0; i < len32; i++, dst += 4) -+ class_bus_write(val, dst, 4); -+ -+ if (len & 0x2) { -+ class_bus_write(val, dst, 2); -+ dst += 2; -+ } -+ -+ if (len & 0x1) { -+ class_bus_write(val, dst, 1); -+ dst++; -+ } -+} -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ -+/* Writes UTIL program memory (DDR) from the host. -+ * -+ * @param[in] addr Address to write (virtual, must be aligned on size) -+ * @param[in] val Value to write (in PE endianness, i.e BE) -+ * @param[in] size Number of bytes to write (2 or 4) -+ */ -+static void util_pmem_write(u32 val, void *addr, u8 size) -+{ -+ void *addr64 = (void *)((unsigned long)addr & ~0x7); -+ unsigned long off = 8 - ((unsigned long)addr & 0x7) - size; -+ -+ /* -+ * IMEM should be loaded as a 64bit swapped value in a 64bit aligned -+ * location -+ */ -+ if (size == 4) -+ writel(be32_to_cpu(val), addr64 + off); -+ else -+ writew(be16_to_cpu((u16)val), addr64 + off); -+} -+ -+/* Writes a buffer to UTIL program memory (DDR) from the host. -+ * -+ * @param[in] dst Address to write (virtual, must be at least 16bit -+ * aligned) -+ * @param[in] src Buffer to write (in PE endianness, i.e BE, must have -+ * same alignment as dst) -+ * @param[in] len Number of bytes to write (must be at least 16bit -+ * aligned) -+ */ -+static void util_pmem_memcpy(void *dst, const void *src, unsigned int len) -+{ -+ unsigned int len32; -+ int i; -+ -+ if ((unsigned long)src & 0x2) { -+ util_pmem_write(*(u16 *)src, dst, 2); -+ src += 2; -+ dst += 2; -+ len -= 2; -+ } -+ -+ len32 = len >> 2; -+ -+ for (i = 0; i < len32; i++, dst += 4, src += 4) -+ util_pmem_write(*(u32 *)src, dst, 4); -+ -+ if (len & 0x2) -+ util_pmem_write(*(u16 *)src, dst, len & 0x2); -+} -+#endif -+ -+/* Loads an elf section into pmem -+ * Code needs to be at least 16bit aligned and only PROGBITS sections are -+ * supported -+ * -+ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ..., -+ * TMU3_ID) -+ * @param[in] data pointer to the elf firmware -+ * @param[in] shdr pointer to the elf section header -+ * -+ */ -+static int pe_load_pmem_section(int id, const void *data, -+ struct elf32_shdr *shdr) -+{ -+ u32 offset = be32_to_cpu(shdr->sh_offset); -+ u32 addr = be32_to_cpu(shdr->sh_addr); -+ u32 size = be32_to_cpu(shdr->sh_size); -+ u32 type = be32_to_cpu(shdr->sh_type); -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ if (id == UTIL_ID) { -+ pr_err("%s: unsupported pmem section for UTIL\n", -+ __func__); -+ return -EINVAL; -+ } -+#endif -+ -+ if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) { -+ pr_err( -+ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n" -+ , __func__, addr, (unsigned long)data + offset); -+ -+ return -EINVAL; -+ } -+ -+ if (addr & 0x1) { -+ pr_err("%s: load address(%x) is not 16bit aligned\n", -+ __func__, addr); -+ return -EINVAL; -+ } -+ -+ if (size & 0x1) { -+ pr_err("%s: load size(%x) is not 16bit aligned\n", -+ __func__, size); -+ return -EINVAL; -+ } -+ -+ switch (type) { -+ case SHT_PROGBITS: -+ pe_pmem_memcpy_to32(id, addr, data + offset, size); -+ -+ break; -+ -+ default: -+ pr_err("%s: unsupported section type(%x)\n", __func__, -+ type); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* Loads an elf section into dmem -+ * Data needs to be at least 32bit aligned, NOBITS sections are correctly -+ * initialized to 0 -+ * -+ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, -+ * ..., UTIL_ID) -+ * @param[in] data pointer to the elf firmware -+ * @param[in] shdr pointer to the elf section header -+ * -+ */ -+static int pe_load_dmem_section(int id, const void *data, -+ struct elf32_shdr *shdr) -+{ -+ u32 offset = be32_to_cpu(shdr->sh_offset); -+ u32 addr = be32_to_cpu(shdr->sh_addr); -+ u32 size = be32_to_cpu(shdr->sh_size); -+ u32 type = be32_to_cpu(shdr->sh_type); -+ u32 size32 = size >> 2; -+ int i; -+ -+ if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) { -+ pr_err( -+ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n", -+ __func__, addr, (unsigned long)data + offset); -+ -+ return -EINVAL; -+ } -+ -+ if (addr & 0x3) { -+ pr_err("%s: load address(%x) is not 32bit aligned\n", -+ __func__, addr); -+ return -EINVAL; -+ } -+ -+ switch (type) { -+ case SHT_PROGBITS: -+ pe_dmem_memcpy_to32(id, addr, data + offset, size); -+ break; -+ -+ case SHT_NOBITS: -+ for (i = 0; i < size32; i++, addr += 4) -+ pe_dmem_write(id, 0, addr, 4); -+ -+ if (size & 0x3) -+ pe_dmem_write(id, 0, addr, size & 0x3); -+ -+ break; -+ -+ default: -+ pr_err("%s: unsupported section type(%x)\n", __func__, -+ type); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* Loads an elf section into DDR -+ * Data needs to be at least 32bit aligned, NOBITS sections are correctly -+ * initialized to 0 -+ * -+ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, -+ * ..., UTIL_ID) -+ * @param[in] data pointer to the elf firmware -+ * @param[in] shdr pointer to the elf section header -+ * -+ */ -+static int pe_load_ddr_section(int id, const void *data, -+ struct elf32_shdr *shdr, -+ struct device *dev) { -+ u32 offset = be32_to_cpu(shdr->sh_offset); -+ u32 addr = be32_to_cpu(shdr->sh_addr); -+ u32 size = be32_to_cpu(shdr->sh_size); -+ u32 type = be32_to_cpu(shdr->sh_type); -+ u32 flags = be32_to_cpu(shdr->sh_flags); -+ -+ switch (type) { -+ case SHT_PROGBITS: -+ if (flags & SHF_EXECINSTR) { -+ if (id <= CLASS_MAX_ID) { -+ /* DO the loading only once in DDR */ -+ if (id == CLASS0_ID) { -+ pr_err( -+ "%s: load address(%x) and elf file address(%lx) rcvd\n", -+ __func__, addr, -+ (unsigned long)data + offset); -+ if (((unsigned long)(data + offset) -+ & 0x3) != (addr & 0x3)) { -+ pr_err( -+ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n" -+ , __func__, addr, -+ (unsigned long)data + offset); -+ -+ return -EINVAL; -+ } -+ -+ if (addr & 0x1) { -+ pr_err( -+ "%s: load address(%x) is not 16bit aligned\n" -+ , __func__, addr); -+ return -EINVAL; -+ } -+ -+ if (size & 0x1) { -+ pr_err( -+ "%s: load length(%x) is not 16bit aligned\n" -+ , __func__, size); -+ return -EINVAL; -+ } -+ memcpy(DDR_PHYS_TO_VIRT( -+ DDR_PFE_TO_PHYS(addr)), -+ data + offset, size); -+ } -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ } else if (id == UTIL_ID) { -+ if (((unsigned long)(data + offset) & 0x3) -+ != (addr & 0x3)) { -+ pr_err( -+ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n" -+ , __func__, addr, -+ (unsigned long)data + offset); -+ -+ return -EINVAL; -+ } -+ -+ if (addr & 0x1) { -+ pr_err( -+ "%s: load address(%x) is not 16bit aligned\n" -+ , __func__, addr); -+ return -EINVAL; -+ } -+ -+ if (size & 0x1) { -+ pr_err( -+ "%s: load length(%x) is not 16bit aligned\n" -+ , __func__, size); -+ return -EINVAL; -+ } -+ -+ util_pmem_memcpy(DDR_PHYS_TO_VIRT( -+ DDR_PFE_TO_PHYS(addr)), -+ data + offset, size); -+ } -+#endif -+ } else { -+ pr_err( -+ "%s: unsupported ddr section type(%x) for PE(%d)\n" -+ , __func__, type, id); -+ return -EINVAL; -+ } -+ -+ } else { -+ memcpy(DDR_PHYS_TO_VIRT(DDR_PFE_TO_PHYS(addr)), data -+ + offset, size); -+ } -+ -+ break; -+ -+ case SHT_NOBITS: -+ memset(DDR_PHYS_TO_VIRT(DDR_PFE_TO_PHYS(addr)), 0, size); -+ -+ break; -+ -+ default: -+ pr_err("%s: unsupported section type(%x)\n", __func__, -+ type); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* Loads an elf section into pe lmem -+ * Data needs to be at least 32bit aligned, NOBITS sections are correctly -+ * initialized to 0 -+ * -+ * @param[in] id PE identification (CLASS0_ID,..., CLASS5_ID) -+ * @param[in] data pointer to the elf firmware -+ * @param[in] shdr pointer to the elf section header -+ * -+ */ -+static int pe_load_pe_lmem_section(int id, const void *data, -+ struct elf32_shdr *shdr) -+{ -+ u32 offset = be32_to_cpu(shdr->sh_offset); -+ u32 addr = be32_to_cpu(shdr->sh_addr); -+ u32 size = be32_to_cpu(shdr->sh_size); -+ u32 type = be32_to_cpu(shdr->sh_type); -+ -+ if (id > CLASS_MAX_ID) { -+ pr_err( -+ "%s: unsupported pe-lmem section type(%x) for PE(%d)\n", -+ __func__, type, id); -+ return -EINVAL; -+ } -+ -+ if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) { -+ pr_err( -+ "%s: load address(%x) and elf file address(%lx) don't have the same alignment\n", -+ __func__, addr, (unsigned long)data + offset); -+ -+ return -EINVAL; -+ } -+ -+ if (addr & 0x3) { -+ pr_err("%s: load address(%x) is not 32bit aligned\n", -+ __func__, addr); -+ return -EINVAL; -+ } -+ -+ switch (type) { -+ case SHT_PROGBITS: -+ class_pe_lmem_memcpy_to32(addr, data + offset, size); -+ break; -+ -+ case SHT_NOBITS: -+ class_pe_lmem_memset(addr, 0, size); -+ break; -+ -+ default: -+ pr_err("%s: unsupported section type(%x)\n", __func__, -+ type); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* Loads an elf section into a PE -+ * For now only supports loading a section to dmem (all PE's), pmem (class and -+ * tmu PE's), -+ * DDDR (util PE code) -+ * -+ * @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, -+ * ..., UTIL_ID) -+ * @param[in] data pointer to the elf firmware -+ * @param[in] shdr pointer to the elf section header -+ * -+ */ -+int pe_load_elf_section(int id, const void *data, struct elf32_shdr *shdr, -+ struct device *dev) { -+ u32 addr = be32_to_cpu(shdr->sh_addr); -+ u32 size = be32_to_cpu(shdr->sh_size); -+ -+ if (IS_DMEM(addr, size)) -+ return pe_load_dmem_section(id, data, shdr); -+ else if (IS_PMEM(addr, size)) -+ return pe_load_pmem_section(id, data, shdr); -+ else if (IS_PFE_LMEM(addr, size)) -+ return 0; -+ else if (IS_PHYS_DDR(addr, size)) -+ return pe_load_ddr_section(id, data, shdr, dev); -+ else if (IS_PE_LMEM(addr, size)) -+ return pe_load_pe_lmem_section(id, data, shdr); -+ -+ pr_err("%s: unsupported memory range(%x)\n", __func__, -+ addr); -+ return 0; -+} -+ -+/**************************** BMU ***************************/ -+ -+/* Initializes a BMU block. -+ * @param[in] base BMU block base address -+ * @param[in] cfg BMU configuration -+ */ -+void bmu_init(void *base, struct BMU_CFG *cfg) -+{ -+ bmu_disable(base); -+ -+ bmu_set_config(base, cfg); -+ -+ bmu_reset(base); -+} -+ -+/* Resets a BMU block. -+ * @param[in] base BMU block base address -+ */ -+void bmu_reset(void *base) -+{ -+ writel(CORE_SW_RESET, base + BMU_CTRL); -+ -+ /* Wait for self clear */ -+ while (readl(base + BMU_CTRL) & CORE_SW_RESET) -+ ; -+} -+ -+/* Enabled a BMU block. -+ * @param[in] base BMU block base address -+ */ -+void bmu_enable(void *base) -+{ -+ writel(CORE_ENABLE, base + BMU_CTRL); -+} -+ -+/* Disables a BMU block. -+ * @param[in] base BMU block base address -+ */ -+void bmu_disable(void *base) -+{ -+ writel(CORE_DISABLE, base + BMU_CTRL); -+} -+ -+/* Sets the configuration of a BMU block. -+ * @param[in] base BMU block base address -+ * @param[in] cfg BMU configuration -+ */ -+void bmu_set_config(void *base, struct BMU_CFG *cfg) -+{ -+ writel(cfg->baseaddr, base + BMU_UCAST_BASE_ADDR); -+ writel(cfg->count & 0xffff, base + BMU_UCAST_CONFIG); -+ writel(cfg->size & 0xffff, base + BMU_BUF_SIZE); -+ -+ /* Interrupts are never used */ -+ writel(cfg->low_watermark, base + BMU_LOW_WATERMARK); -+ writel(cfg->high_watermark, base + BMU_HIGH_WATERMARK); -+ writel(0x0, base + BMU_INT_ENABLE); -+} -+ -+/**************************** MTIP GEMAC ***************************/ -+ -+/* Enable Rx Checksum Engine. With this enabled, Frame with bad IP, -+ * TCP or UDP checksums are discarded -+ * -+ * @param[in] base GEMAC base address. -+ */ -+void gemac_enable_rx_checksum_offload(void *base) -+{ -+ /*Do not find configuration to do this */ -+} -+ -+/* Disable Rx Checksum Engine. -+ * -+ * @param[in] base GEMAC base address. -+ */ -+void gemac_disable_rx_checksum_offload(void *base) -+{ -+ /*Do not find configuration to do this */ -+} -+ -+/* GEMAC set speed. -+ * @param[in] base GEMAC base address -+ * @param[in] speed GEMAC speed (10, 100 or 1000 Mbps) -+ */ -+void gemac_set_speed(void *base, enum mac_speed gem_speed) -+{ -+ u32 ecr = readl(base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_SPEED; -+ u32 rcr = readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_RMII_10T; -+ -+ switch (gem_speed) { -+ case SPEED_10M: -+ rcr |= EMAC_RCNTRL_RMII_10T; -+ break; -+ -+ case SPEED_1000M: -+ ecr |= EMAC_ECNTRL_SPEED; -+ break; -+ -+ case SPEED_100M: -+ default: -+ /*It is in 100M mode */ -+ break; -+ } -+ writel(ecr, (base + EMAC_ECNTRL_REG)); -+ writel(rcr, (base + EMAC_RCNTRL_REG)); -+} -+ -+/* GEMAC set duplex. -+ * @param[in] base GEMAC base address -+ * @param[in] duplex GEMAC duplex mode (Full, Half) -+ */ -+void gemac_set_duplex(void *base, int duplex) -+{ -+ if (duplex == DUPLEX_HALF) { -+ writel(readl(base + EMAC_TCNTRL_REG) & ~EMAC_TCNTRL_FDEN, base -+ + EMAC_TCNTRL_REG); -+ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_DRT, (base -+ + EMAC_RCNTRL_REG)); -+ } else{ -+ writel(readl(base + EMAC_TCNTRL_REG) | EMAC_TCNTRL_FDEN, base -+ + EMAC_TCNTRL_REG); -+ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_DRT, (base -+ + EMAC_RCNTRL_REG)); -+ } -+} -+ -+/* GEMAC set mode. -+ * @param[in] base GEMAC base address -+ * @param[in] mode GEMAC operation mode (MII, RMII, RGMII, SGMII) -+ */ -+void gemac_set_mode(void *base, int mode) -+{ -+ u32 val = readl(base + EMAC_RCNTRL_REG); -+ -+ /*Remove loopbank*/ -+ val &= ~EMAC_RCNTRL_LOOP; -+ -+ /* Enable flow control and MII mode.PFE firmware always expects -+ CRC should be forwarded by MAC to validate CRC in software.*/ -+ val |= (EMAC_RCNTRL_FCE | EMAC_RCNTRL_MII_MODE); -+ -+ writel(val, base + EMAC_RCNTRL_REG); -+} -+ -+/* GEMAC enable function. -+ * @param[in] base GEMAC base address -+ */ -+void gemac_enable(void *base) -+{ -+ writel(readl(base + EMAC_ECNTRL_REG) | EMAC_ECNTRL_ETHER_EN, base + -+ EMAC_ECNTRL_REG); -+} -+ -+/* GEMAC disable function. -+ * @param[in] base GEMAC base address -+ */ -+void gemac_disable(void *base) -+{ -+ writel(readl(base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_ETHER_EN, base + -+ EMAC_ECNTRL_REG); -+} -+ -+/* GEMAC TX disable function. -+ * @param[in] base GEMAC base address -+ */ -+void gemac_tx_disable(void *base) -+{ -+ writel(readl(base + EMAC_TCNTRL_REG) | EMAC_TCNTRL_GTS, base + -+ EMAC_TCNTRL_REG); -+} -+ -+void gemac_tx_enable(void *base) -+{ -+ writel(readl(base + EMAC_TCNTRL_REG) & ~EMAC_TCNTRL_GTS, base + -+ EMAC_TCNTRL_REG); -+} -+ -+/* Sets the hash register of the MAC. -+ * This register is used for matching unicast and multicast frames. -+ * -+ * @param[in] base GEMAC base address. -+ * @param[in] hash 64-bit hash to be configured. -+ */ -+void gemac_set_hash(void *base, struct pfe_mac_addr *hash) -+{ -+ writel(hash->bottom, base + EMAC_GALR); -+ writel(hash->top, base + EMAC_GAUR); -+} -+ -+void gemac_set_laddrN(void *base, struct pfe_mac_addr *address, -+ unsigned int entry_index) -+{ -+ if ((entry_index < 1) || (entry_index > EMAC_SPEC_ADDR_MAX)) -+ return; -+ -+ entry_index = entry_index - 1; -+ if (entry_index < 1) { -+ writel(htonl(address->bottom), base + EMAC_PHY_ADDR_LOW); -+ writel((htonl(address->top) | 0x8808), base + -+ EMAC_PHY_ADDR_HIGH); -+ } else { -+ writel(htonl(address->bottom), base + ((entry_index - 1) * 8) -+ + EMAC_SMAC_0_0); -+ writel((htonl(address->top) | 0x8808), base + ((entry_index - -+ 1) * 8) + EMAC_SMAC_0_1); -+ } -+} -+ -+void gemac_clear_laddrN(void *base, unsigned int entry_index) -+{ -+ if ((entry_index < 1) || (entry_index > EMAC_SPEC_ADDR_MAX)) -+ return; -+ -+ entry_index = entry_index - 1; -+ if (entry_index < 1) { -+ writel(0, base + EMAC_PHY_ADDR_LOW); -+ writel(0, base + EMAC_PHY_ADDR_HIGH); -+ } else { -+ writel(0, base + ((entry_index - 1) * 8) + EMAC_SMAC_0_0); -+ writel(0, base + ((entry_index - 1) * 8) + EMAC_SMAC_0_1); -+ } -+} -+ -+/* Set the loopback mode of the MAC. This can be either no loopback for -+ * normal operation, local loopback through MAC internal loopback module or PHY -+ * loopback for external loopback through a PHY. This asserts the external -+ * loop pin. -+ * -+ * @param[in] base GEMAC base address. -+ * @param[in] gem_loop Loopback mode to be enabled. LB_LOCAL - MAC -+ * Loopback, -+ * LB_EXT - PHY Loopback. -+ */ -+void gemac_set_loop(void *base, enum mac_loop gem_loop) -+{ -+ pr_info("%s()\n", __func__); -+ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_LOOP, (base + -+ EMAC_RCNTRL_REG)); -+} -+ -+/* GEMAC allow frames -+ * @param[in] base GEMAC base address -+ */ -+void gemac_enable_copy_all(void *base) -+{ -+ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_PROM, (base + -+ EMAC_RCNTRL_REG)); -+} -+ -+/* GEMAC do not allow frames -+ * @param[in] base GEMAC base address -+ */ -+void gemac_disable_copy_all(void *base) -+{ -+ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_PROM, (base + -+ EMAC_RCNTRL_REG)); -+} -+ -+/* GEMAC allow broadcast function. -+ * @param[in] base GEMAC base address -+ */ -+void gemac_allow_broadcast(void *base) -+{ -+ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_BC_REJ, base + -+ EMAC_RCNTRL_REG); -+} -+ -+/* GEMAC no broadcast function. -+ * @param[in] base GEMAC base address -+ */ -+void gemac_no_broadcast(void *base) -+{ -+ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_BC_REJ, base + -+ EMAC_RCNTRL_REG); -+} -+ -+/* GEMAC enable 1536 rx function. -+ * @param[in] base GEMAC base address -+ */ -+void gemac_enable_1536_rx(void *base) -+{ -+ /* Set 1536 as Maximum frame length */ -+ writel((readl(base + EMAC_RCNTRL_REG) & PFE_RCR_MAX_FL_MASK) -+ | (1536 << 16), base + EMAC_RCNTRL_REG); -+} -+ -+/* GEMAC set rx Max frame length. -+ * @param[in] base GEMAC base address -+ * @param[in] mtu new mtu -+ */ -+void gemac_set_rx_max_fl(void *base, int mtu) -+{ -+ /* Set mtu as Maximum frame length */ -+ writel((readl(base + EMAC_RCNTRL_REG) & PFE_RCR_MAX_FL_MASK) -+ | (mtu << 16), base + EMAC_RCNTRL_REG); -+} -+ -+/* GEMAC enable stacked vlan function. -+ * @param[in] base GEMAC base address -+ */ -+void gemac_enable_stacked_vlan(void *base) -+{ -+ /* MTIP doesn't support stacked vlan */ -+} -+ -+/* GEMAC enable pause rx function. -+ * @param[in] base GEMAC base address -+ */ -+void gemac_enable_pause_rx(void *base) -+{ -+ writel(readl(base + EMAC_RCNTRL_REG) | EMAC_RCNTRL_FCE, -+ base + EMAC_RCNTRL_REG); -+} -+ -+/* GEMAC disable pause rx function. -+ * @param[in] base GEMAC base address -+ */ -+void gemac_disable_pause_rx(void *base) -+{ -+ writel(readl(base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_FCE, -+ base + EMAC_RCNTRL_REG); -+} -+ -+/* GEMAC enable pause tx function. -+ * @param[in] base GEMAC base address -+ */ -+static void __maybe_unused gemac_enable_pause_tx(void *base) -+{ -+ writel(EMAC_RX_SECTION_EMPTY_V, base + EMAC_RX_SECTION_EMPTY); -+} -+ -+/* GEMAC disable pause tx function. -+ * @param[in] base GEMAC base address -+ */ -+static void __maybe_unused gemac_disable_pause_tx(void *base) -+{ -+ writel(0x0, base + EMAC_RX_SECTION_EMPTY); -+} -+ -+/* GEMAC wol configuration -+ * @param[in] base GEMAC base address -+ * @param[in] wol_conf WoL register configuration -+ */ -+void gemac_set_wol(void *base, u32 wol_conf) -+{ -+ u32 val = readl(base + EMAC_ECNTRL_REG); -+ -+ if (wol_conf) -+ val |= (EMAC_ECNTRL_MAGIC_ENA | EMAC_ECNTRL_SLEEP); -+ else -+ val &= ~(EMAC_ECNTRL_MAGIC_ENA | EMAC_ECNTRL_SLEEP); -+ writel(val, base + EMAC_ECNTRL_REG); -+} -+ -+/* Sets Gemac bus width to 64bit -+ * @param[in] base GEMAC base address -+ * @param[in] width gemac bus width to be set possible values are 32/64/128 -+ */ -+void gemac_set_bus_width(void *base, int width) -+{ -+} -+ -+/* Sets Gemac configuration. -+ * @param[in] base GEMAC base address -+ * @param[in] cfg GEMAC configuration -+ */ -+void gemac_set_config(void *base, struct gemac_cfg *cfg) -+{ -+ /*GEMAC config taken from VLSI */ -+ writel(0x00000004, base + EMAC_TFWR_STR_FWD); -+ writel(0x00000005, base + EMAC_RX_SECTION_FULL); -+ -+ if (pfe_errata_a010897) -+ writel(0x0000076c, base + EMAC_TRUNC_FL); -+ else -+ writel(0x00003fff, base + EMAC_TRUNC_FL); -+ -+ writel(0x00000030, base + EMAC_TX_SECTION_EMPTY); -+ writel(0x00000000, base + EMAC_MIB_CTRL_STS_REG); -+ -+ gemac_set_mode(base, cfg->mode); -+ -+ gemac_set_speed(base, cfg->speed); -+ -+ gemac_set_duplex(base, cfg->duplex); -+} -+ -+/**************************** GPI ***************************/ -+ -+/* Initializes a GPI block. -+ * @param[in] base GPI base address -+ * @param[in] cfg GPI configuration -+ */ -+void gpi_init(void *base, struct gpi_cfg *cfg) -+{ -+ gpi_reset(base); -+ -+ gpi_disable(base); -+ -+ gpi_set_config(base, cfg); -+} -+ -+/* Resets a GPI block. -+ * @param[in] base GPI base address -+ */ -+void gpi_reset(void *base) -+{ -+ writel(CORE_SW_RESET, base + GPI_CTRL); -+} -+ -+/* Enables a GPI block. -+ * @param[in] base GPI base address -+ */ -+void gpi_enable(void *base) -+{ -+ writel(CORE_ENABLE, base + GPI_CTRL); -+} -+ -+/* Disables a GPI block. -+ * @param[in] base GPI base address -+ */ -+void gpi_disable(void *base) -+{ -+ writel(CORE_DISABLE, base + GPI_CTRL); -+} -+ -+/* Sets the configuration of a GPI block. -+ * @param[in] base GPI base address -+ * @param[in] cfg GPI configuration -+ */ -+void gpi_set_config(void *base, struct gpi_cfg *cfg) -+{ -+ writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_ALLOC_CTRL), base -+ + GPI_LMEM_ALLOC_ADDR); -+ writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_FREE_CTRL), base -+ + GPI_LMEM_FREE_ADDR); -+ writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_ALLOC_CTRL), base -+ + GPI_DDR_ALLOC_ADDR); -+ writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), base -+ + GPI_DDR_FREE_ADDR); -+ writel(CBUS_VIRT_TO_PFE(CLASS_INQ_PKTPTR), base + GPI_CLASS_ADDR); -+ writel(DDR_HDR_SIZE, base + GPI_DDR_DATA_OFFSET); -+ writel(LMEM_HDR_SIZE, base + GPI_LMEM_DATA_OFFSET); -+ writel(0, base + GPI_LMEM_SEC_BUF_DATA_OFFSET); -+ writel(0, base + GPI_DDR_SEC_BUF_DATA_OFFSET); -+ writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, base + GPI_HDR_SIZE); -+ writel((DDR_BUF_SIZE << 16) | LMEM_BUF_SIZE, base + GPI_BUF_SIZE); -+ -+ writel(((cfg->lmem_rtry_cnt << 16) | (GPI_DDR_BUF_EN << 1) | -+ GPI_LMEM_BUF_EN), base + GPI_RX_CONFIG); -+ writel(cfg->tmlf_txthres, base + GPI_TMLF_TX); -+ writel(cfg->aseq_len, base + GPI_DTX_ASEQ); -+ writel(1, base + GPI_TOE_CHKSUM_EN); -+ -+ if (cfg->mtip_pause_reg) { -+ writel(cfg->mtip_pause_reg, base + GPI_CSR_MTIP_PAUSE_REG); -+ writel(EGPI_PAUSE_TIME, base + GPI_TX_PAUSE_TIME); -+ } -+} -+ -+/**************************** CLASSIFIER ***************************/ -+ -+/* Initializes CLASSIFIER block. -+ * @param[in] cfg CLASSIFIER configuration -+ */ -+void class_init(struct class_cfg *cfg) -+{ -+ class_reset(); -+ -+ class_disable(); -+ -+ class_set_config(cfg); -+} -+ -+/* Resets CLASSIFIER block. -+ * -+ */ -+void class_reset(void) -+{ -+ writel(CORE_SW_RESET, CLASS_TX_CTRL); -+} -+ -+/* Enables all CLASS-PE's cores. -+ * -+ */ -+void class_enable(void) -+{ -+ writel(CORE_ENABLE, CLASS_TX_CTRL); -+} -+ -+/* Disables all CLASS-PE's cores. -+ * -+ */ -+void class_disable(void) -+{ -+ writel(CORE_DISABLE, CLASS_TX_CTRL); -+} -+ -+/* -+ * Sets the configuration of the CLASSIFIER block. -+ * @param[in] cfg CLASSIFIER configuration -+ */ -+void class_set_config(struct class_cfg *cfg) -+{ -+ u32 val; -+ -+ /* Initialize route table */ -+ if (!cfg->resume) -+ memset(DDR_PHYS_TO_VIRT(cfg->route_table_baseaddr), 0, (1 << -+ cfg->route_table_hash_bits) * CLASS_ROUTE_SIZE); -+ -+#if !defined(LS1012A_PFE_RESET_WA) -+ writel(cfg->pe_sys_clk_ratio, CLASS_PE_SYS_CLK_RATIO); -+#endif -+ -+ writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, CLASS_HDR_SIZE); -+ writel(LMEM_BUF_SIZE, CLASS_LMEM_BUF_SIZE); -+ writel(CLASS_ROUTE_ENTRY_SIZE(CLASS_ROUTE_SIZE) | -+ CLASS_ROUTE_HASH_SIZE(cfg->route_table_hash_bits), -+ CLASS_ROUTE_HASH_ENTRY_SIZE); -+ writel(HIF_PKT_CLASS_EN | HIF_PKT_OFFSET(sizeof(struct hif_hdr)), -+ CLASS_HIF_PARSE); -+ -+ val = HASH_CRC_PORT_IP | QB2BUS_LE; -+ -+#if defined(CONFIG_IP_ALIGNED) -+ val |= IP_ALIGNED; -+#endif -+ -+ /* -+ * Class PE packet steering will only work if TOE mode, bridge fetch or -+ * route fetch are enabled (see class/qb_fet.v). Route fetch would -+ * trigger additional memory copies (likely from DDR because of hash -+ * table size, which cannot be reduced because PE software still -+ * relies on hash value computed in HW), so when not in TOE mode we -+ * simply enable HW bridge fetch even though we don't use it. -+ */ -+ if (cfg->toe_mode) -+ val |= CLASS_TOE; -+ else -+ val |= HW_BRIDGE_FETCH; -+ -+ writel(val, CLASS_ROUTE_MULTI); -+ -+ writel(DDR_PHYS_TO_PFE(cfg->route_table_baseaddr), -+ CLASS_ROUTE_TABLE_BASE); -+ writel(CLASS_PE0_RO_DM_ADDR0_VAL, CLASS_PE0_RO_DM_ADDR0); -+ writel(CLASS_PE0_RO_DM_ADDR1_VAL, CLASS_PE0_RO_DM_ADDR1); -+ writel(CLASS_PE0_QB_DM_ADDR0_VAL, CLASS_PE0_QB_DM_ADDR0); -+ writel(CLASS_PE0_QB_DM_ADDR1_VAL, CLASS_PE0_QB_DM_ADDR1); -+ writel(CBUS_VIRT_TO_PFE(TMU_PHY_INQ_PKTPTR), CLASS_TM_INQ_ADDR); -+ -+ writel(23, CLASS_AFULL_THRES); -+ writel(23, CLASS_TSQ_FIFO_THRES); -+ -+ writel(24, CLASS_MAX_BUF_CNT); -+ writel(24, CLASS_TSQ_MAX_CNT); -+} -+ -+/**************************** TMU ***************************/ -+ -+void tmu_reset(void) -+{ -+ writel(SW_RESET, TMU_CTRL); -+} -+ -+/* Initializes TMU block. -+ * @param[in] cfg TMU configuration -+ */ -+void tmu_init(struct tmu_cfg *cfg) -+{ -+ int q, phyno; -+ -+ tmu_disable(0xF); -+ mdelay(10); -+ -+#if !defined(LS1012A_PFE_RESET_WA) -+ /* keep in soft reset */ -+ writel(SW_RESET, TMU_CTRL); -+#endif -+ writel(0x3, TMU_SYS_GENERIC_CONTROL); -+ writel(750, TMU_INQ_WATERMARK); -+ writel(CBUS_VIRT_TO_PFE(EGPI1_BASE_ADDR + -+ GPI_INQ_PKTPTR), TMU_PHY0_INQ_ADDR); -+ writel(CBUS_VIRT_TO_PFE(EGPI2_BASE_ADDR + -+ GPI_INQ_PKTPTR), TMU_PHY1_INQ_ADDR); -+ writel(CBUS_VIRT_TO_PFE(HGPI_BASE_ADDR + -+ GPI_INQ_PKTPTR), TMU_PHY3_INQ_ADDR); -+ writel(CBUS_VIRT_TO_PFE(HIF_NOCPY_RX_INQ0_PKTPTR), TMU_PHY4_INQ_ADDR); -+ writel(CBUS_VIRT_TO_PFE(UTIL_INQ_PKTPTR), TMU_PHY5_INQ_ADDR); -+ writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), -+ TMU_BMU_INQ_ADDR); -+ -+ writel(0x3FF, TMU_TDQ0_SCH_CTRL); /* -+ * enabling all 10 -+ * schedulers [9:0] of each TDQ -+ */ -+ writel(0x3FF, TMU_TDQ1_SCH_CTRL); -+ writel(0x3FF, TMU_TDQ3_SCH_CTRL); -+ -+#if !defined(LS1012A_PFE_RESET_WA) -+ writel(cfg->pe_sys_clk_ratio, TMU_PE_SYS_CLK_RATIO); -+#endif -+ -+#if !defined(LS1012A_PFE_RESET_WA) -+ writel(DDR_PHYS_TO_PFE(cfg->llm_base_addr), TMU_LLM_BASE_ADDR); -+ /* Extra packet pointers will be stored from this address onwards */ -+ -+ writel(cfg->llm_queue_len, TMU_LLM_QUE_LEN); -+ writel(5, TMU_TDQ_IIFG_CFG); -+ writel(DDR_BUF_SIZE, TMU_BMU_BUF_SIZE); -+ -+ writel(0x0, TMU_CTRL); -+ -+ /* MEM init */ -+ pr_info("%s: mem init\n", __func__); -+ writel(MEM_INIT, TMU_CTRL); -+ -+ while (!(readl(TMU_CTRL) & MEM_INIT_DONE)) -+ ; -+ -+ /* LLM init */ -+ pr_info("%s: lmem init\n", __func__); -+ writel(LLM_INIT, TMU_CTRL); -+ -+ while (!(readl(TMU_CTRL) & LLM_INIT_DONE)) -+ ; -+#endif -+ /* set up each queue for tail drop */ -+ for (phyno = 0; phyno < 4; phyno++) { -+ if (phyno == 2) -+ continue; -+ for (q = 0; q < 16; q++) { -+ u32 qdepth; -+ -+ writel((phyno << 8) | q, TMU_TEQ_CTRL); -+ writel(1 << 22, TMU_TEQ_QCFG); /*Enable tail drop */ -+ -+ if (phyno == 3) -+ qdepth = DEFAULT_TMU3_QDEPTH; -+ else -+ qdepth = (q == 0) ? DEFAULT_Q0_QDEPTH : -+ DEFAULT_MAX_QDEPTH; -+ -+ /* LOG: 68855 */ -+ /* -+ * The following is a workaround for the reordered -+ * packet and BMU2 buffer leakage issue. -+ */ -+ if (CHIP_REVISION() == 0) -+ qdepth = 31; -+ -+ writel(qdepth << 18, TMU_TEQ_HW_PROB_CFG2); -+ writel(qdepth >> 14, TMU_TEQ_HW_PROB_CFG3); -+ } -+ } -+ -+#ifdef CFG_LRO -+ /* Set TMU-3 queue 5 (LRO) in no-drop mode */ -+ writel((3 << 8) | TMU_QUEUE_LRO, TMU_TEQ_CTRL); -+ writel(0, TMU_TEQ_QCFG); -+#endif -+ -+ writel(0x05, TMU_TEQ_DISABLE_DROPCHK); -+ -+ writel(0x0, TMU_CTRL); -+} -+ -+/* Enables TMU-PE cores. -+ * @param[in] pe_mask TMU PE mask -+ */ -+void tmu_enable(u32 pe_mask) -+{ -+ writel(readl(TMU_TX_CTRL) | (pe_mask & 0xF), TMU_TX_CTRL); -+} -+ -+/* Disables TMU cores. -+ * @param[in] pe_mask TMU PE mask -+ */ -+void tmu_disable(u32 pe_mask) -+{ -+ writel(readl(TMU_TX_CTRL) & ~(pe_mask & 0xF), TMU_TX_CTRL); -+} -+ -+/* This will return the tmu queue status -+ * @param[in] if_id gem interface id or TMU index -+ * @return returns the bit mask of busy queues, zero means all -+ * queues are empty -+ */ -+u32 tmu_qstatus(u32 if_id) -+{ -+ return cpu_to_be32(pe_dmem_read(TMU0_ID + if_id, TMU_DM_PESTATUS + -+ offsetof(struct pe_status, tmu_qstatus), 4)); -+} -+ -+u32 tmu_pkts_processed(u32 if_id) -+{ -+ return cpu_to_be32(pe_dmem_read(TMU0_ID + if_id, TMU_DM_PESTATUS + -+ offsetof(struct pe_status, rx), 4)); -+} -+ -+/**************************** UTIL ***************************/ -+ -+/* Resets UTIL block. -+ */ -+void util_reset(void) -+{ -+ writel(CORE_SW_RESET, UTIL_TX_CTRL); -+} -+ -+/* Initializes UTIL block. -+ * @param[in] cfg UTIL configuration -+ */ -+void util_init(struct util_cfg *cfg) -+{ -+ writel(cfg->pe_sys_clk_ratio, UTIL_PE_SYS_CLK_RATIO); -+} -+ -+/* Enables UTIL-PE core. -+ * -+ */ -+void util_enable(void) -+{ -+ writel(CORE_ENABLE, UTIL_TX_CTRL); -+} -+ -+/* Disables UTIL-PE core. -+ * -+ */ -+void util_disable(void) -+{ -+ writel(CORE_DISABLE, UTIL_TX_CTRL); -+} -+ -+/**************************** HIF ***************************/ -+/* Initializes HIF copy block. -+ * -+ */ -+void hif_init(void) -+{ -+ /*Initialize HIF registers*/ -+ writel((HIF_RX_POLL_CTRL_CYCLE << 16) | HIF_TX_POLL_CTRL_CYCLE, -+ HIF_POLL_CTRL); -+} -+ -+/* Enable hif tx DMA and interrupt -+ * -+ */ -+void hif_tx_enable(void) -+{ -+ writel(HIF_CTRL_DMA_EN, HIF_TX_CTRL); -+ writel((readl(HIF_INT_ENABLE) | HIF_INT_EN | HIF_TXPKT_INT_EN), -+ HIF_INT_ENABLE); -+} -+ -+/* Disable hif tx DMA and interrupt -+ * -+ */ -+void hif_tx_disable(void) -+{ -+ u32 hif_int; -+ -+ writel(0, HIF_TX_CTRL); -+ -+ hif_int = readl(HIF_INT_ENABLE); -+ hif_int &= HIF_TXPKT_INT_EN; -+ writel(hif_int, HIF_INT_ENABLE); -+} -+ -+/* Enable hif rx DMA and interrupt -+ * -+ */ -+void hif_rx_enable(void) -+{ -+ hif_rx_dma_start(); -+ writel((readl(HIF_INT_ENABLE) | HIF_INT_EN | HIF_RXPKT_INT_EN), -+ HIF_INT_ENABLE); -+} -+ -+/* Disable hif rx DMA and interrupt -+ * -+ */ -+void hif_rx_disable(void) -+{ -+ u32 hif_int; -+ -+ writel(0, HIF_RX_CTRL); -+ -+ hif_int = readl(HIF_INT_ENABLE); -+ hif_int &= HIF_RXPKT_INT_EN; -+ writel(hif_int, HIF_INT_ENABLE); -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_hif.c -@@ -0,0 +1,1063 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "pfe_mod.h" -+ -+#define HIF_INT_MASK (HIF_INT | HIF_RXPKT_INT | HIF_TXPKT_INT) -+ -+unsigned char napi_first_batch; -+ -+static void pfe_tx_do_cleanup(unsigned long data); -+ -+static int pfe_hif_alloc_descr(struct pfe_hif *hif) -+{ -+ void *addr; -+ dma_addr_t dma_addr; -+ int err = 0; -+ -+ pr_info("%s\n", __func__); -+ addr = dma_alloc_coherent(pfe->dev, -+ HIF_RX_DESC_NT * sizeof(struct hif_desc) + -+ HIF_TX_DESC_NT * sizeof(struct hif_desc), -+ &dma_addr, GFP_KERNEL); -+ -+ if (!addr) { -+ pr_err("%s: Could not allocate buffer descriptors!\n" -+ , __func__); -+ err = -ENOMEM; -+ goto err0; -+ } -+ -+ hif->descr_baseaddr_p = dma_addr; -+ hif->descr_baseaddr_v = addr; -+ hif->rx_ring_size = HIF_RX_DESC_NT; -+ hif->tx_ring_size = HIF_TX_DESC_NT; -+ -+ return 0; -+ -+err0: -+ return err; -+} -+ -+#if defined(LS1012A_PFE_RESET_WA) -+static void pfe_hif_disable_rx_desc(struct pfe_hif *hif) -+{ -+ int ii; -+ struct hif_desc *desc = hif->rx_base; -+ -+ /*Mark all descriptors as LAST_BD */ -+ for (ii = 0; ii < hif->rx_ring_size; ii++) { -+ desc->ctrl |= BD_CTRL_LAST_BD; -+ desc++; -+ } -+} -+ -+struct class_rx_hdr_t { -+ u32 next_ptr; /* ptr to the start of the first DDR buffer */ -+ u16 length; /* total packet length */ -+ u16 phyno; /* input physical port number */ -+ u32 status; /* gemac status bits */ -+ u32 status2; /* reserved for software usage */ -+}; -+ -+/* STATUS_BAD_FRAME_ERR is set for all errors (including checksums if enabled) -+ * except overflow -+ */ -+#define STATUS_BAD_FRAME_ERR BIT(16) -+#define STATUS_LENGTH_ERR BIT(17) -+#define STATUS_CRC_ERR BIT(18) -+#define STATUS_TOO_SHORT_ERR BIT(19) -+#define STATUS_TOO_LONG_ERR BIT(20) -+#define STATUS_CODE_ERR BIT(21) -+#define STATUS_MC_HASH_MATCH BIT(22) -+#define STATUS_CUMULATIVE_ARC_HIT BIT(23) -+#define STATUS_UNICAST_HASH_MATCH BIT(24) -+#define STATUS_IP_CHECKSUM_CORRECT BIT(25) -+#define STATUS_TCP_CHECKSUM_CORRECT BIT(26) -+#define STATUS_UDP_CHECKSUM_CORRECT BIT(27) -+#define STATUS_OVERFLOW_ERR BIT(28) /* GPI error */ -+#define MIN_PKT_SIZE 64 -+ -+static inline void copy_to_lmem(u32 *dst, u32 *src, int len) -+{ -+ int i; -+ -+ for (i = 0; i < len; i += sizeof(u32)) { -+ *dst = htonl(*src); -+ dst++; src++; -+ } -+} -+ -+static void send_dummy_pkt_to_hif(void) -+{ -+ void *lmem_ptr, *ddr_ptr, *lmem_virt_addr; -+ u32 physaddr; -+ struct class_rx_hdr_t local_hdr; -+ static u32 dummy_pkt[] = { -+ 0x33221100, 0x2b785544, 0xd73093cb, 0x01000608, -+ 0x04060008, 0x2b780200, 0xd73093cb, 0x0a01a8c0, -+ 0x33221100, 0xa8c05544, 0x00000301, 0x00000000, -+ 0x00000000, 0x00000000, 0x00000000, 0xbe86c51f }; -+ -+ ddr_ptr = (void *)((u64)readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL)); -+ if (!ddr_ptr) -+ return; -+ -+ lmem_ptr = (void *)((u64)readl(BMU1_BASE_ADDR + BMU_ALLOC_CTRL)); -+ if (!lmem_ptr) -+ return; -+ -+ pr_info("Sending a dummy pkt to HIF %p %p\n", ddr_ptr, lmem_ptr); -+ physaddr = (u32)DDR_VIRT_TO_PFE(ddr_ptr); -+ -+ lmem_virt_addr = (void *)CBUS_PFE_TO_VIRT((unsigned long int)lmem_ptr); -+ -+ local_hdr.phyno = htons(0); /* RX_PHY_0 */ -+ local_hdr.length = htons(MIN_PKT_SIZE); -+ -+ local_hdr.next_ptr = htonl((u32)physaddr); -+ /*Mark checksum is correct */ -+ local_hdr.status = htonl((STATUS_IP_CHECKSUM_CORRECT | -+ STATUS_UDP_CHECKSUM_CORRECT | -+ STATUS_TCP_CHECKSUM_CORRECT | -+ STATUS_UNICAST_HASH_MATCH | -+ STATUS_CUMULATIVE_ARC_HIT)); -+ local_hdr.status2 = 0; -+ -+ copy_to_lmem((u32 *)lmem_virt_addr, (u32 *)&local_hdr, -+ sizeof(local_hdr)); -+ -+ copy_to_lmem((u32 *)(lmem_virt_addr + LMEM_HDR_SIZE), (u32 *)dummy_pkt, -+ 0x40); -+ -+ writel((unsigned long int)lmem_ptr, CLASS_INQ_PKTPTR); -+} -+ -+void pfe_hif_rx_idle(struct pfe_hif *hif) -+{ -+ int hif_stop_loop = 10; -+ u32 rx_status; -+ -+ pfe_hif_disable_rx_desc(hif); -+ pr_info("Bringing hif to idle state..."); -+ writel(0, HIF_INT_ENABLE); -+ /*If HIF Rx BDP is busy send a dummy packet */ -+ do { -+ rx_status = readl(HIF_RX_STATUS); -+ if (rx_status & BDP_CSR_RX_DMA_ACTV) -+ send_dummy_pkt_to_hif(); -+ -+ usleep_range(100, 150); -+ } while (--hif_stop_loop); -+ -+ if (readl(HIF_RX_STATUS) & BDP_CSR_RX_DMA_ACTV) -+ pr_info("Failed\n"); -+ else -+ pr_info("Done\n"); -+} -+#endif -+ -+static void pfe_hif_free_descr(struct pfe_hif *hif) -+{ -+ pr_info("%s\n", __func__); -+ -+ dma_free_coherent(pfe->dev, -+ hif->rx_ring_size * sizeof(struct hif_desc) + -+ hif->tx_ring_size * sizeof(struct hif_desc), -+ hif->descr_baseaddr_v, hif->descr_baseaddr_p); -+} -+ -+static void __maybe_unused pfe_hif_desc_dump(struct pfe_hif *hif) -+{ -+ struct hif_desc *desc; -+ unsigned long desc_p; -+ int ii = 0; -+ -+ pr_info("%s\n", __func__); -+ -+ desc = hif->rx_base; -+ desc_p = (u32)((u64)desc - (u64)hif->descr_baseaddr_v + -+ hif->descr_baseaddr_p); -+ -+ pr_info("HIF Rx desc base %p physical %x\n", desc, (u32)desc_p); -+ for (ii = 0; ii < hif->rx_ring_size; ii++) { -+ pr_info("status: %08x, ctrl: %08x, data: %08x, next: %x\n", -+ readl(&desc->status), readl(&desc->ctrl), -+ readl(&desc->data), readl(&desc->next)); -+ desc++; -+ } -+ -+ desc = hif->tx_base; -+ desc_p = ((u64)desc - (u64)hif->descr_baseaddr_v + -+ hif->descr_baseaddr_p); -+ -+ pr_info("HIF Tx desc base %p physical %x\n", desc, (u32)desc_p); -+ for (ii = 0; ii < hif->tx_ring_size; ii++) { -+ pr_info("status: %08x, ctrl: %08x, data: %08x, next: %x\n", -+ readl(&desc->status), readl(&desc->ctrl), -+ readl(&desc->data), readl(&desc->next)); -+ desc++; -+ } -+} -+ -+/* pfe_hif_release_buffers */ -+static void pfe_hif_release_buffers(struct pfe_hif *hif) -+{ -+ struct hif_desc *desc; -+ int i = 0; -+ -+ hif->rx_base = hif->descr_baseaddr_v; -+ -+ pr_info("%s\n", __func__); -+ -+ /*Free Rx buffers */ -+ desc = hif->rx_base; -+ for (i = 0; i < hif->rx_ring_size; i++) { -+ if (readl(&desc->data)) { -+ if ((i < hif->shm->rx_buf_pool_cnt) && -+ (!hif->shm->rx_buf_pool[i])) { -+ /* -+ * dma_unmap_single(hif->dev, desc->data, -+ * hif->rx_buf_len[i], DMA_FROM_DEVICE); -+ */ -+ dma_unmap_single(hif->dev, -+ DDR_PFE_TO_PHYS( -+ readl(&desc->data)), -+ hif->rx_buf_len[i], -+ DMA_FROM_DEVICE); -+ hif->shm->rx_buf_pool[i] = hif->rx_buf_addr[i]; -+ } else { -+ pr_err("%s: buffer pool already full\n" -+ , __func__); -+ } -+ } -+ -+ writel(0, &desc->data); -+ writel(0, &desc->status); -+ writel(0, &desc->ctrl); -+ desc++; -+ } -+} -+ -+/* -+ * pfe_hif_init_buffers -+ * This function initializes the HIF Rx/Tx ring descriptors and -+ * initialize Rx queue with buffers. -+ */ -+static int pfe_hif_init_buffers(struct pfe_hif *hif) -+{ -+ struct hif_desc *desc, *first_desc_p; -+ u32 data; -+ int i = 0; -+ -+ pr_info("%s\n", __func__); -+ -+ /* Check enough Rx buffers available in the shared memory */ -+ if (hif->shm->rx_buf_pool_cnt < hif->rx_ring_size) -+ return -ENOMEM; -+ -+ hif->rx_base = hif->descr_baseaddr_v; -+ memset(hif->rx_base, 0, hif->rx_ring_size * sizeof(struct hif_desc)); -+ -+ /*Initialize Rx descriptors */ -+ desc = hif->rx_base; -+ first_desc_p = (struct hif_desc *)hif->descr_baseaddr_p; -+ -+ for (i = 0; i < hif->rx_ring_size; i++) { -+ /* Initialize Rx buffers from the shared memory */ -+ -+ data = (u32)dma_map_single(hif->dev, hif->shm->rx_buf_pool[i], -+ pfe_pkt_size, DMA_FROM_DEVICE); -+ hif->rx_buf_addr[i] = hif->shm->rx_buf_pool[i]; -+ hif->rx_buf_len[i] = pfe_pkt_size; -+ hif->shm->rx_buf_pool[i] = NULL; -+ -+ if (likely(dma_mapping_error(hif->dev, data) == 0)) { -+ writel(DDR_PHYS_TO_PFE(data), &desc->data); -+ } else { -+ pr_err("%s : low on mem\n", __func__); -+ -+ goto err; -+ } -+ -+ writel(0, &desc->status); -+ -+ /* -+ * Ensure everything else is written to DDR before -+ * writing bd->ctrl -+ */ -+ wmb(); -+ -+ writel((BD_CTRL_PKT_INT_EN | BD_CTRL_LIFM -+ | BD_CTRL_DIR | BD_CTRL_DESC_EN -+ | BD_BUF_LEN(pfe_pkt_size)), &desc->ctrl); -+ -+ /* Chain descriptors */ -+ writel((u32)DDR_PHYS_TO_PFE(first_desc_p + i + 1), &desc->next); -+ desc++; -+ } -+ -+ /* Overwrite last descriptor to chain it to first one*/ -+ desc--; -+ writel((u32)DDR_PHYS_TO_PFE(first_desc_p), &desc->next); -+ -+ hif->rxtoclean_index = 0; -+ -+ /*Initialize Rx buffer descriptor ring base address */ -+ writel(DDR_PHYS_TO_PFE(hif->descr_baseaddr_p), HIF_RX_BDP_ADDR); -+ -+ hif->tx_base = hif->rx_base + hif->rx_ring_size; -+ first_desc_p = (struct hif_desc *)hif->descr_baseaddr_p + -+ hif->rx_ring_size; -+ memset(hif->tx_base, 0, hif->tx_ring_size * sizeof(struct hif_desc)); -+ -+ /*Initialize tx descriptors */ -+ desc = hif->tx_base; -+ -+ for (i = 0; i < hif->tx_ring_size; i++) { -+ /* Chain descriptors */ -+ writel((u32)DDR_PHYS_TO_PFE(first_desc_p + i + 1), &desc->next); -+ writel(0, &desc->ctrl); -+ desc++; -+ } -+ -+ /* Overwrite last descriptor to chain it to first one */ -+ desc--; -+ writel((u32)DDR_PHYS_TO_PFE(first_desc_p), &desc->next); -+ hif->txavail = hif->tx_ring_size; -+ hif->txtosend = 0; -+ hif->txtoclean = 0; -+ hif->txtoflush = 0; -+ -+ /*Initialize Tx buffer descriptor ring base address */ -+ writel((u32)DDR_PHYS_TO_PFE(first_desc_p), HIF_TX_BDP_ADDR); -+ -+ return 0; -+ -+err: -+ pfe_hif_release_buffers(hif); -+ return -ENOMEM; -+} -+ -+/* -+ * pfe_hif_client_register -+ * -+ * This function used to register a client driver with the HIF driver. -+ * -+ * Return value: -+ * 0 - on Successful registration -+ */ -+static int pfe_hif_client_register(struct pfe_hif *hif, u32 client_id, -+ struct hif_client_shm *client_shm) -+{ -+ struct hif_client *client = &hif->client[client_id]; -+ u32 i, cnt; -+ struct rx_queue_desc *rx_qbase; -+ struct tx_queue_desc *tx_qbase; -+ struct hif_rx_queue *rx_queue; -+ struct hif_tx_queue *tx_queue; -+ int err = 0; -+ -+ pr_info("%s\n", __func__); -+ -+ spin_lock_bh(&hif->tx_lock); -+ -+ if (test_bit(client_id, &hif->shm->g_client_status[0])) { -+ pr_err("%s: client %d already registered\n", -+ __func__, client_id); -+ err = -1; -+ goto unlock; -+ } -+ -+ memset(client, 0, sizeof(struct hif_client)); -+ -+ /* Initialize client Rx queues baseaddr, size */ -+ -+ cnt = CLIENT_CTRL_RX_Q_CNT(client_shm->ctrl); -+ /* Check if client is requesting for more queues than supported */ -+ if (cnt > HIF_CLIENT_QUEUES_MAX) -+ cnt = HIF_CLIENT_QUEUES_MAX; -+ -+ client->rx_qn = cnt; -+ rx_qbase = (struct rx_queue_desc *)client_shm->rx_qbase; -+ for (i = 0; i < cnt; i++) { -+ rx_queue = &client->rx_q[i]; -+ rx_queue->base = rx_qbase + i * client_shm->rx_qsize; -+ rx_queue->size = client_shm->rx_qsize; -+ rx_queue->write_idx = 0; -+ } -+ -+ /* Initialize client Tx queues baseaddr, size */ -+ cnt = CLIENT_CTRL_TX_Q_CNT(client_shm->ctrl); -+ -+ /* Check if client is requesting for more queues than supported */ -+ if (cnt > HIF_CLIENT_QUEUES_MAX) -+ cnt = HIF_CLIENT_QUEUES_MAX; -+ -+ client->tx_qn = cnt; -+ tx_qbase = (struct tx_queue_desc *)client_shm->tx_qbase; -+ for (i = 0; i < cnt; i++) { -+ tx_queue = &client->tx_q[i]; -+ tx_queue->base = tx_qbase + i * client_shm->tx_qsize; -+ tx_queue->size = client_shm->tx_qsize; -+ tx_queue->ack_idx = 0; -+ } -+ -+ set_bit(client_id, &hif->shm->g_client_status[0]); -+ -+unlock: -+ spin_unlock_bh(&hif->tx_lock); -+ -+ return err; -+} -+ -+/* -+ * pfe_hif_client_unregister -+ * -+ * This function used to unregister a client from the HIF driver. -+ * -+ */ -+static void pfe_hif_client_unregister(struct pfe_hif *hif, u32 client_id) -+{ -+ pr_info("%s\n", __func__); -+ -+ /* -+ * Mark client as no longer available (which prevents further packet -+ * receive for this client) -+ */ -+ spin_lock_bh(&hif->tx_lock); -+ -+ if (!test_bit(client_id, &hif->shm->g_client_status[0])) { -+ pr_err("%s: client %d not registered\n", __func__, -+ client_id); -+ -+ spin_unlock_bh(&hif->tx_lock); -+ return; -+ } -+ -+ clear_bit(client_id, &hif->shm->g_client_status[0]); -+ -+ spin_unlock_bh(&hif->tx_lock); -+} -+ -+/* -+ * client_put_rxpacket- -+ * This functions puts the Rx pkt in the given client Rx queue. -+ * It actually swap the Rx pkt in the client Rx descriptor buffer -+ * and returns the free buffer from it. -+ * -+ * If the function returns NULL means client Rx queue is full and -+ * packet couldn't send to client queue. -+ */ -+static void *client_put_rxpacket(struct hif_rx_queue *queue, void *pkt, u32 len, -+ u32 flags, u32 client_ctrl, u32 *rem_len) -+{ -+ void *free_pkt = NULL; -+ struct rx_queue_desc *desc = queue->base + queue->write_idx; -+ -+ if (readl(&desc->ctrl) & CL_DESC_OWN) { -+ if (page_mode) { -+ int rem_page_size = PAGE_SIZE - -+ PRESENT_OFST_IN_PAGE(pkt); -+ int cur_pkt_size = ROUND_MIN_RX_SIZE(len + -+ pfe_pkt_headroom); -+ *rem_len = (rem_page_size - cur_pkt_size); -+ if (*rem_len) { -+ free_pkt = pkt + cur_pkt_size; -+ get_page(virt_to_page(free_pkt)); -+ } else { -+ free_pkt = (void -+ *)__get_free_page(GFP_ATOMIC | GFP_DMA_PFE); -+ *rem_len = pfe_pkt_size; -+ } -+ } else { -+ free_pkt = kmalloc(PFE_BUF_SIZE, GFP_ATOMIC | -+ GFP_DMA_PFE); -+ *rem_len = PFE_BUF_SIZE - pfe_pkt_headroom; -+ } -+ -+ if (free_pkt) { -+ desc->data = pkt; -+ desc->client_ctrl = client_ctrl; -+ /* -+ * Ensure everything else is written to DDR before -+ * writing bd->ctrl -+ */ -+ smp_wmb(); -+ writel(CL_DESC_BUF_LEN(len) | flags, &desc->ctrl); -+ queue->write_idx = (queue->write_idx + 1) -+ & (queue->size - 1); -+ -+ free_pkt += pfe_pkt_headroom; -+ } -+ } -+ -+ return free_pkt; -+} -+ -+/* -+ * pfe_hif_rx_process- -+ * This function does pfe hif rx queue processing. -+ * Dequeue packet from Rx queue and send it to corresponding client queue -+ */ -+static int pfe_hif_rx_process(struct pfe_hif *hif, int budget) -+{ -+ struct hif_desc *desc; -+ struct hif_hdr *pkt_hdr; -+ struct __hif_hdr hif_hdr; -+ void *free_buf; -+ int rtc, len, rx_processed = 0; -+ struct __hif_desc local_desc; -+ int flags; -+ unsigned int desc_p; -+ unsigned int buf_size = 0; -+ -+ spin_lock_bh(&hif->lock); -+ -+ rtc = hif->rxtoclean_index; -+ -+ while (rx_processed < budget) { -+ desc = hif->rx_base + rtc; -+ -+ __memcpy12(&local_desc, desc); -+ -+ /* ACK pending Rx interrupt */ -+ if (local_desc.ctrl & BD_CTRL_DESC_EN) { -+ writel(HIF_INT | HIF_RXPKT_INT, HIF_INT_SRC); -+ -+ if (rx_processed == 0) { -+ if (napi_first_batch == 1) { -+ desc_p = hif->descr_baseaddr_p + -+ ((unsigned long int)(desc) - -+ (unsigned long -+ int)hif->descr_baseaddr_v); -+ napi_first_batch = 0; -+ } -+ } -+ -+ __memcpy12(&local_desc, desc); -+ -+ if (local_desc.ctrl & BD_CTRL_DESC_EN) -+ break; -+ } -+ -+ napi_first_batch = 0; -+ -+#ifdef HIF_NAPI_STATS -+ hif->napi_counters[NAPI_DESC_COUNT]++; -+#endif -+ len = BD_BUF_LEN(local_desc.ctrl); -+ /* -+ * dma_unmap_single(hif->dev, DDR_PFE_TO_PHYS(local_desc.data), -+ * hif->rx_buf_len[rtc], DMA_FROM_DEVICE); -+ */ -+ dma_unmap_single(hif->dev, DDR_PFE_TO_PHYS(local_desc.data), -+ hif->rx_buf_len[rtc], DMA_FROM_DEVICE); -+ -+ pkt_hdr = (struct hif_hdr *)hif->rx_buf_addr[rtc]; -+ -+ /* Track last HIF header received */ -+ if (!hif->started) { -+ hif->started = 1; -+ -+ __memcpy8(&hif_hdr, pkt_hdr); -+ -+ hif->qno = hif_hdr.hdr.q_num; -+ hif->client_id = hif_hdr.hdr.client_id; -+ hif->client_ctrl = (hif_hdr.hdr.client_ctrl1 << 16) | -+ hif_hdr.hdr.client_ctrl; -+ flags = CL_DESC_FIRST; -+ -+ } else { -+ flags = 0; -+ } -+ -+ if (local_desc.ctrl & BD_CTRL_LIFM) -+ flags |= CL_DESC_LAST; -+ -+ /* Check for valid client id and still registered */ -+ if ((hif->client_id >= HIF_CLIENTS_MAX) || -+ !(test_bit(hif->client_id, -+ &hif->shm->g_client_status[0]))) { -+ printk_ratelimited("%s: packet with invalid client id %d q_num %d\n", -+ __func__, -+ hif->client_id, -+ hif->qno); -+ -+ free_buf = pkt_hdr; -+ -+ goto pkt_drop; -+ } -+ -+ /* Check to valid queue number */ -+ if (hif->client[hif->client_id].rx_qn <= hif->qno) { -+ pr_info("%s: packet with invalid queue: %d\n" -+ , __func__, hif->qno); -+ hif->qno = 0; -+ } -+ -+ free_buf = -+ client_put_rxpacket(&hif->client[hif->client_id].rx_q[hif->qno], -+ (void *)pkt_hdr, len, flags, -+ hif->client_ctrl, &buf_size); -+ -+ hif_lib_indicate_client(hif->client_id, EVENT_RX_PKT_IND, -+ hif->qno); -+ -+ if (unlikely(!free_buf)) { -+#ifdef HIF_NAPI_STATS -+ hif->napi_counters[NAPI_CLIENT_FULL_COUNT]++; -+#endif -+ /* -+ * If we want to keep in polling mode to retry later, -+ * we need to tell napi that we consumed -+ * the full budget or we will hit a livelock scenario. -+ * The core code keeps this napi instance -+ * at the head of the list and none of the other -+ * instances get to run -+ */ -+ rx_processed = budget; -+ -+ if (flags & CL_DESC_FIRST) -+ hif->started = 0; -+ -+ break; -+ } -+ -+pkt_drop: -+ /*Fill free buffer in the descriptor */ -+ hif->rx_buf_addr[rtc] = free_buf; -+ hif->rx_buf_len[rtc] = min(pfe_pkt_size, buf_size); -+ writel((DDR_PHYS_TO_PFE -+ ((u32)dma_map_single(hif->dev, -+ free_buf, hif->rx_buf_len[rtc], DMA_FROM_DEVICE))), -+ &desc->data); -+ /* -+ * Ensure everything else is written to DDR before -+ * writing bd->ctrl -+ */ -+ wmb(); -+ writel((BD_CTRL_PKT_INT_EN | BD_CTRL_LIFM | BD_CTRL_DIR | -+ BD_CTRL_DESC_EN | BD_BUF_LEN(hif->rx_buf_len[rtc])), -+ &desc->ctrl); -+ -+ rtc = (rtc + 1) & (hif->rx_ring_size - 1); -+ -+ if (local_desc.ctrl & BD_CTRL_LIFM) { -+ if (!(hif->client_ctrl & HIF_CTRL_RX_CONTINUED)) { -+ rx_processed++; -+ -+#ifdef HIF_NAPI_STATS -+ hif->napi_counters[NAPI_PACKET_COUNT]++; -+#endif -+ } -+ hif->started = 0; -+ } -+ } -+ -+ hif->rxtoclean_index = rtc; -+ spin_unlock_bh(&hif->lock); -+ -+ /* we made some progress, re-start rx dma in case it stopped */ -+ hif_rx_dma_start(); -+ -+ return rx_processed; -+} -+ -+/* -+ * client_ack_txpacket- -+ * This function ack the Tx packet in the give client Tx queue by resetting -+ * ownership bit in the descriptor. -+ */ -+static int client_ack_txpacket(struct pfe_hif *hif, unsigned int client_id, -+ unsigned int q_no) -+{ -+ struct hif_tx_queue *queue = &hif->client[client_id].tx_q[q_no]; -+ struct tx_queue_desc *desc = queue->base + queue->ack_idx; -+ -+ if (readl(&desc->ctrl) & CL_DESC_OWN) { -+ writel((readl(&desc->ctrl) & ~CL_DESC_OWN), &desc->ctrl); -+ queue->ack_idx = (queue->ack_idx + 1) & (queue->size - 1); -+ -+ return 0; -+ -+ } else { -+ /*This should not happen */ -+ pr_err("%s: %d %d %d %d %d %p %d\n", __func__, -+ hif->txtosend, hif->txtoclean, hif->txavail, -+ client_id, q_no, queue, queue->ack_idx); -+ WARN(1, "%s: doesn't own this descriptor", __func__); -+ return 1; -+ } -+} -+ -+void __hif_tx_done_process(struct pfe_hif *hif, int count) -+{ -+ struct hif_desc *desc; -+ struct hif_desc_sw *desc_sw; -+ int ttc, tx_avl; -+ int pkts_done[HIF_CLIENTS_MAX] = {0, 0}; -+ -+ ttc = hif->txtoclean; -+ tx_avl = hif->txavail; -+ -+ while ((tx_avl < hif->tx_ring_size) && count--) { -+ desc = hif->tx_base + ttc; -+ -+ if (readl(&desc->ctrl) & BD_CTRL_DESC_EN) -+ break; -+ -+ desc_sw = &hif->tx_sw_queue[ttc]; -+ -+ if (desc_sw->data) { -+ /* -+ * dmap_unmap_single(hif->dev, desc_sw->data, -+ * desc_sw->len, DMA_TO_DEVICE); -+ */ -+ dma_unmap_single(hif->dev, desc_sw->data, -+ desc_sw->len, DMA_TO_DEVICE); -+ } -+ -+ if (desc_sw->client_id >= HIF_CLIENTS_MAX) { -+ pr_err("Invalid cl id %d\n", desc_sw->client_id); -+ break; -+ } -+ -+ pkts_done[desc_sw->client_id]++; -+ -+ client_ack_txpacket(hif, desc_sw->client_id, desc_sw->q_no); -+ -+ ttc = (ttc + 1) & (hif->tx_ring_size - 1); -+ tx_avl++; -+ } -+ -+ if (pkts_done[0]) -+ hif_lib_indicate_client(0, EVENT_TXDONE_IND, 0); -+ if (pkts_done[1]) -+ hif_lib_indicate_client(1, EVENT_TXDONE_IND, 0); -+ -+ hif->txtoclean = ttc; -+ hif->txavail = tx_avl; -+ -+ if (!count) { -+ tasklet_schedule(&hif->tx_cleanup_tasklet); -+ } else { -+ /*Enable Tx done interrupt */ -+ writel(readl_relaxed(HIF_INT_ENABLE) | HIF_TXPKT_INT, -+ HIF_INT_ENABLE); -+ } -+} -+ -+static void pfe_tx_do_cleanup(unsigned long data) -+{ -+ struct pfe_hif *hif = (struct pfe_hif *)data; -+ -+ writel(HIF_INT | HIF_TXPKT_INT, HIF_INT_SRC); -+ -+ hif_tx_done_process(hif, 64); -+} -+ -+/* -+ * __hif_xmit_pkt - -+ * This function puts one packet in the HIF Tx queue -+ */ -+void __hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int -+ q_no, void *data, u32 len, unsigned int flags) -+{ -+ struct hif_desc *desc; -+ struct hif_desc_sw *desc_sw; -+ -+ desc = hif->tx_base + hif->txtosend; -+ desc_sw = &hif->tx_sw_queue[hif->txtosend]; -+ -+ desc_sw->len = len; -+ desc_sw->client_id = client_id; -+ desc_sw->q_no = q_no; -+ desc_sw->flags = flags; -+ -+ if (flags & HIF_DONT_DMA_MAP) { -+ desc_sw->data = 0; -+ writel((u32)DDR_PHYS_TO_PFE(data), &desc->data); -+ } else { -+ desc_sw->data = dma_map_single(hif->dev, data, len, -+ DMA_TO_DEVICE); -+ writel((u32)DDR_PHYS_TO_PFE(desc_sw->data), &desc->data); -+ } -+ -+ hif->txtosend = (hif->txtosend + 1) & (hif->tx_ring_size - 1); -+ hif->txavail--; -+ -+ if ((!((flags & HIF_DATA_VALID) && (flags & -+ HIF_LAST_BUFFER)))) -+ goto skip_tx; -+ -+ /* -+ * Ensure everything else is written to DDR before -+ * writing bd->ctrl -+ */ -+ wmb(); -+ -+ do { -+ desc_sw = &hif->tx_sw_queue[hif->txtoflush]; -+ desc = hif->tx_base + hif->txtoflush; -+ -+ if (desc_sw->flags & HIF_LAST_BUFFER) { -+ writel((BD_CTRL_LIFM | -+ BD_CTRL_BRFETCH_DISABLE | BD_CTRL_RTFETCH_DISABLE -+ | BD_CTRL_PARSE_DISABLE | BD_CTRL_DESC_EN | -+ BD_CTRL_PKT_INT_EN | BD_BUF_LEN(desc_sw->len)), -+ &desc->ctrl); -+ } else { -+ writel((BD_CTRL_DESC_EN | -+ BD_BUF_LEN(desc_sw->len)), &desc->ctrl); -+ } -+ hif->txtoflush = (hif->txtoflush + 1) & (hif->tx_ring_size - 1); -+ } -+ while (hif->txtoflush != hif->txtosend) -+ ; -+ -+skip_tx: -+ return; -+} -+ -+static irqreturn_t wol_isr(int irq, void *dev_id) -+{ -+ pr_info("WoL\n"); -+ gemac_set_wol(EMAC1_BASE_ADDR, 0); -+ gemac_set_wol(EMAC2_BASE_ADDR, 0); -+ return IRQ_HANDLED; -+} -+ -+/* -+ * hif_isr- -+ * This ISR routine processes Rx/Tx done interrupts from the HIF hardware block -+ */ -+static irqreturn_t hif_isr(int irq, void *dev_id) -+{ -+ struct pfe_hif *hif = (struct pfe_hif *)dev_id; -+ int int_status; -+ int int_enable_mask; -+ -+ /*Read hif interrupt source register */ -+ int_status = readl_relaxed(HIF_INT_SRC); -+ int_enable_mask = readl_relaxed(HIF_INT_ENABLE); -+ -+ if ((int_status & HIF_INT) == 0) -+ return IRQ_NONE; -+ -+ int_status &= ~(HIF_INT); -+ -+ if (int_status & HIF_RXPKT_INT) { -+ int_status &= ~(HIF_RXPKT_INT); -+ int_enable_mask &= ~(HIF_RXPKT_INT); -+ -+ napi_first_batch = 1; -+ -+ if (napi_schedule_prep(&hif->napi)) { -+#ifdef HIF_NAPI_STATS -+ hif->napi_counters[NAPI_SCHED_COUNT]++; -+#endif -+ __napi_schedule(&hif->napi); -+ } -+ } -+ -+ if (int_status & HIF_TXPKT_INT) { -+ int_status &= ~(HIF_TXPKT_INT); -+ int_enable_mask &= ~(HIF_TXPKT_INT); -+ /*Schedule tx cleanup tassklet */ -+ tasklet_schedule(&hif->tx_cleanup_tasklet); -+ } -+ -+ /*Disable interrupts, they will be enabled after they are serviced */ -+ writel_relaxed(int_enable_mask, HIF_INT_ENABLE); -+ -+ if (int_status) { -+ pr_info("%s : Invalid interrupt : %d\n", __func__, -+ int_status); -+ writel(int_status, HIF_INT_SRC); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+void hif_process_client_req(struct pfe_hif *hif, int req, int data1, int data2) -+{ -+ unsigned int client_id = data1; -+ -+ if (client_id >= HIF_CLIENTS_MAX) { -+ pr_err("%s: client id %d out of bounds\n", __func__, -+ client_id); -+ return; -+ } -+ -+ switch (req) { -+ case REQUEST_CL_REGISTER: -+ /* Request for register a client */ -+ pr_info("%s: register client_id %d\n", -+ __func__, client_id); -+ pfe_hif_client_register(hif, client_id, (struct -+ hif_client_shm *)&hif->shm->client[client_id]); -+ break; -+ -+ case REQUEST_CL_UNREGISTER: -+ pr_info("%s: unregister client_id %d\n", -+ __func__, client_id); -+ -+ /* Request for unregister a client */ -+ pfe_hif_client_unregister(hif, client_id); -+ -+ break; -+ -+ default: -+ pr_err("%s: unsupported request %d\n", -+ __func__, req); -+ break; -+ } -+ -+ /* -+ * Process client Tx queues -+ * Currently we don't have checking for tx pending -+ */ -+} -+ -+/* -+ * pfe_hif_rx_poll -+ * This function is NAPI poll function to process HIF Rx queue. -+ */ -+static int pfe_hif_rx_poll(struct napi_struct *napi, int budget) -+{ -+ struct pfe_hif *hif = container_of(napi, struct pfe_hif, napi); -+ int work_done; -+ -+#ifdef HIF_NAPI_STATS -+ hif->napi_counters[NAPI_POLL_COUNT]++; -+#endif -+ -+ work_done = pfe_hif_rx_process(hif, budget); -+ -+ if (work_done < budget) { -+ napi_complete(napi); -+ writel(readl_relaxed(HIF_INT_ENABLE) | HIF_RXPKT_INT, -+ HIF_INT_ENABLE); -+ } -+#ifdef HIF_NAPI_STATS -+ else -+ hif->napi_counters[NAPI_FULL_BUDGET_COUNT]++; -+#endif -+ -+ return work_done; -+} -+ -+/* -+ * pfe_hif_init -+ * This function initializes the baseaddresses and irq, etc. -+ */ -+int pfe_hif_init(struct pfe *pfe) -+{ -+ struct pfe_hif *hif = &pfe->hif; -+ int err; -+ -+ pr_info("%s\n", __func__); -+ -+ hif->dev = pfe->dev; -+ hif->irq = pfe->hif_irq; -+ -+ err = pfe_hif_alloc_descr(hif); -+ if (err) -+ goto err0; -+ -+ if (pfe_hif_init_buffers(hif)) { -+ pr_err("%s: Could not initialize buffer descriptors\n" -+ , __func__); -+ err = -ENOMEM; -+ goto err1; -+ } -+ -+ /* Initialize NAPI for Rx processing */ -+ init_dummy_netdev(&hif->dummy_dev); -+ netif_napi_add(&hif->dummy_dev, &hif->napi, pfe_hif_rx_poll); -+ napi_enable(&hif->napi); -+ -+ spin_lock_init(&hif->tx_lock); -+ spin_lock_init(&hif->lock); -+ -+ hif_init(); -+ hif_rx_enable(); -+ hif_tx_enable(); -+ -+ /* Disable tx done interrupt */ -+ writel(HIF_INT_MASK, HIF_INT_ENABLE); -+ -+ gpi_enable(HGPI_BASE_ADDR); -+ -+ err = request_irq(hif->irq, hif_isr, 0, "pfe_hif", hif); -+ if (err) { -+ pr_err("%s: failed to get the hif IRQ = %d\n", -+ __func__, hif->irq); -+ goto err1; -+ } -+ -+ err = request_irq(pfe->wol_irq, wol_isr, 0, "pfe_wol", pfe); -+ if (err) { -+ pr_err("%s: failed to get the wol IRQ = %d\n", -+ __func__, pfe->wol_irq); -+ goto err1; -+ } -+ -+ tasklet_init(&hif->tx_cleanup_tasklet, -+ (void(*)(unsigned long))pfe_tx_do_cleanup, -+ (unsigned long)hif); -+ -+ return 0; -+err1: -+ pfe_hif_free_descr(hif); -+err0: -+ return err; -+} -+ -+/* pfe_hif_exit- */ -+void pfe_hif_exit(struct pfe *pfe) -+{ -+ struct pfe_hif *hif = &pfe->hif; -+ -+ pr_info("%s\n", __func__); -+ -+ tasklet_kill(&hif->tx_cleanup_tasklet); -+ -+ spin_lock_bh(&hif->lock); -+ hif->shm->g_client_status[0] = 0; -+ /* Make sure all clients are disabled*/ -+ hif->shm->g_client_status[1] = 0; -+ -+ spin_unlock_bh(&hif->lock); -+ -+ /*Disable Rx/Tx */ -+ gpi_disable(HGPI_BASE_ADDR); -+ hif_rx_disable(); -+ hif_tx_disable(); -+ -+ napi_disable(&hif->napi); -+ netif_napi_del(&hif->napi); -+ -+ free_irq(pfe->wol_irq, pfe); -+ free_irq(hif->irq, hif); -+ -+ pfe_hif_release_buffers(hif); -+ pfe_hif_free_descr(hif); -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_hif.h -@@ -0,0 +1,199 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#ifndef _PFE_HIF_H_ -+#define _PFE_HIF_H_ -+ -+#include -+ -+#define HIF_NAPI_STATS -+ -+#define HIF_CLIENT_QUEUES_MAX 16 -+#define HIF_RX_POLL_WEIGHT 64 -+ -+#define HIF_RX_PKT_MIN_SIZE 0x800 /* 2KB */ -+#define HIF_RX_PKT_MIN_SIZE_MASK ~(HIF_RX_PKT_MIN_SIZE - 1) -+#define ROUND_MIN_RX_SIZE(_sz) (((_sz) + (HIF_RX_PKT_MIN_SIZE - 1)) \ -+ & HIF_RX_PKT_MIN_SIZE_MASK) -+#define PRESENT_OFST_IN_PAGE(_buf) (((unsigned long int)(_buf) & (PAGE_SIZE \ -+ - 1)) & HIF_RX_PKT_MIN_SIZE_MASK) -+ -+enum { -+ NAPI_SCHED_COUNT = 0, -+ NAPI_POLL_COUNT, -+ NAPI_PACKET_COUNT, -+ NAPI_DESC_COUNT, -+ NAPI_FULL_BUDGET_COUNT, -+ NAPI_CLIENT_FULL_COUNT, -+ NAPI_MAX_COUNT -+}; -+ -+/* -+ * HIF_TX_DESC_NT value should be always greter than 4, -+ * Otherwise HIF_TX_POLL_MARK will become zero. -+ */ -+#define HIF_RX_DESC_NT 256 -+#define HIF_TX_DESC_NT 2048 -+ -+#define HIF_FIRST_BUFFER BIT(0) -+#define HIF_LAST_BUFFER BIT(1) -+#define HIF_DONT_DMA_MAP BIT(2) -+#define HIF_DATA_VALID BIT(3) -+#define HIF_TSO BIT(4) -+ -+enum { -+ PFE_CL_GEM0 = 0, -+ PFE_CL_GEM1, -+ HIF_CLIENTS_MAX -+}; -+ -+/*structure to store client queue info */ -+struct hif_rx_queue { -+ struct rx_queue_desc *base; -+ u32 size; -+ u32 write_idx; -+}; -+ -+struct hif_tx_queue { -+ struct tx_queue_desc *base; -+ u32 size; -+ u32 ack_idx; -+}; -+ -+/*Structure to store the client info */ -+struct hif_client { -+ int rx_qn; -+ struct hif_rx_queue rx_q[HIF_CLIENT_QUEUES_MAX]; -+ int tx_qn; -+ struct hif_tx_queue tx_q[HIF_CLIENT_QUEUES_MAX]; -+}; -+ -+/*HIF hardware buffer descriptor */ -+struct hif_desc { -+ u32 ctrl; -+ u32 status; -+ u32 data; -+ u32 next; -+}; -+ -+struct __hif_desc { -+ u32 ctrl; -+ u32 status; -+ u32 data; -+}; -+ -+struct hif_desc_sw { -+ dma_addr_t data; -+ u16 len; -+ u8 client_id; -+ u8 q_no; -+ u16 flags; -+}; -+ -+struct hif_hdr { -+ u8 client_id; -+ u8 q_num; -+ u16 client_ctrl; -+ u16 client_ctrl1; -+}; -+ -+struct __hif_hdr { -+ union { -+ struct hif_hdr hdr; -+ u32 word[2]; -+ }; -+}; -+ -+struct hif_ipsec_hdr { -+ u16 sa_handle[2]; -+} __packed; -+ -+/* HIF_CTRL_TX... defines */ -+#define HIF_CTRL_TX_CHECKSUM BIT(2) -+ -+/* HIF_CTRL_RX... defines */ -+#define HIF_CTRL_RX_OFFSET_OFST (24) -+#define HIF_CTRL_RX_CHECKSUMMED BIT(2) -+#define HIF_CTRL_RX_CONTINUED BIT(1) -+ -+struct pfe_hif { -+ /* To store registered clients in hif layer */ -+ struct hif_client client[HIF_CLIENTS_MAX]; -+ struct hif_shm *shm; -+ int irq; -+ -+ void *descr_baseaddr_v; -+ unsigned long descr_baseaddr_p; -+ -+ struct hif_desc *rx_base; -+ u32 rx_ring_size; -+ u32 rxtoclean_index; -+ void *rx_buf_addr[HIF_RX_DESC_NT]; -+ int rx_buf_len[HIF_RX_DESC_NT]; -+ unsigned int qno; -+ unsigned int client_id; -+ unsigned int client_ctrl; -+ unsigned int started; -+ -+ struct hif_desc *tx_base; -+ u32 tx_ring_size; -+ u32 txtosend; -+ u32 txtoclean; -+ u32 txavail; -+ u32 txtoflush; -+ struct hif_desc_sw tx_sw_queue[HIF_TX_DESC_NT]; -+ -+/* tx_lock synchronizes hif packet tx as well as pfe_hif structure access */ -+ spinlock_t tx_lock; -+/* lock synchronizes hif rx queue processing */ -+ spinlock_t lock; -+ struct net_device dummy_dev; -+ struct napi_struct napi; -+ struct device *dev; -+ -+#ifdef HIF_NAPI_STATS -+ unsigned int napi_counters[NAPI_MAX_COUNT]; -+#endif -+ struct tasklet_struct tx_cleanup_tasklet; -+}; -+ -+void __hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int -+ q_no, void *data, u32 len, unsigned int flags); -+int hif_xmit_pkt(struct pfe_hif *hif, unsigned int client_id, unsigned int q_no, -+ void *data, unsigned int len); -+void __hif_tx_done_process(struct pfe_hif *hif, int count); -+void hif_process_client_req(struct pfe_hif *hif, int req, int data1, int -+ data2); -+int pfe_hif_init(struct pfe *pfe); -+void pfe_hif_exit(struct pfe *pfe); -+void pfe_hif_rx_idle(struct pfe_hif *hif); -+static inline void hif_tx_done_process(struct pfe_hif *hif, int count) -+{ -+ spin_lock_bh(&hif->tx_lock); -+ __hif_tx_done_process(hif, count); -+ spin_unlock_bh(&hif->tx_lock); -+} -+ -+static inline void hif_tx_lock(struct pfe_hif *hif) -+{ -+ spin_lock_bh(&hif->tx_lock); -+} -+ -+static inline void hif_tx_unlock(struct pfe_hif *hif) -+{ -+ spin_unlock_bh(&hif->tx_lock); -+} -+ -+static inline int __hif_tx_avail(struct pfe_hif *hif) -+{ -+ return hif->txavail; -+} -+ -+#define __memcpy8(dst, src) memcpy(dst, src, 8) -+#define __memcpy12(dst, src) memcpy(dst, src, 12) -+#define __memcpy(dst, src, len) memcpy(dst, src, len) -+ -+#endif /* _PFE_HIF_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_hif_lib.c -@@ -0,0 +1,628 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "pfe_mod.h" -+#include "pfe_hif.h" -+#include "pfe_hif_lib.h" -+ -+unsigned int lro_mode; -+unsigned int page_mode; -+unsigned int tx_qos = 1; -+module_param(tx_qos, uint, 0444); -+MODULE_PARM_DESC(tx_qos, "0: disable ,\n" -+ "1: enable (default), guarantee no packet drop at TMU level\n"); -+unsigned int pfe_pkt_size; -+unsigned int pfe_pkt_headroom; -+unsigned int emac_txq_cnt; -+ -+/* -+ * @pfe_hal_lib.c. -+ * Common functions used by HIF client drivers -+ */ -+ -+/*HIF shared memory Global variable */ -+struct hif_shm ghif_shm; -+ -+/* Cleanup the HIF shared memory, release HIF rx_buffer_pool. -+ * This function should be called after pfe_hif_exit -+ * -+ * @param[in] hif_shm Shared memory address location in DDR -+ */ -+static void pfe_hif_shm_clean(struct hif_shm *hif_shm) -+{ -+ int i; -+ void *pkt; -+ -+ for (i = 0; i < hif_shm->rx_buf_pool_cnt; i++) { -+ pkt = hif_shm->rx_buf_pool[i]; -+ if (pkt) { -+ hif_shm->rx_buf_pool[i] = NULL; -+ pkt -= pfe_pkt_headroom; -+ -+ if (page_mode) -+ put_page(virt_to_page(pkt)); -+ else -+ kfree(pkt); -+ } -+ } -+} -+ -+/* Initialize shared memory used between HIF driver and clients, -+ * allocate rx_buffer_pool required for HIF Rx descriptors. -+ * This function should be called before initializing HIF driver. -+ * -+ * @param[in] hif_shm Shared memory address location in DDR -+ * @rerurn 0 - on succes, <0 on fail to initialize -+ */ -+static int pfe_hif_shm_init(struct hif_shm *hif_shm) -+{ -+ int i; -+ void *pkt; -+ -+ memset(hif_shm, 0, sizeof(struct hif_shm)); -+ hif_shm->rx_buf_pool_cnt = HIF_RX_DESC_NT; -+ -+ for (i = 0; i < hif_shm->rx_buf_pool_cnt; i++) { -+ if (page_mode) { -+ pkt = (void *)__get_free_page(GFP_KERNEL | -+ GFP_DMA_PFE); -+ } else { -+ pkt = kmalloc(PFE_BUF_SIZE, GFP_KERNEL | GFP_DMA_PFE); -+ } -+ -+ if (pkt) -+ hif_shm->rx_buf_pool[i] = pkt + pfe_pkt_headroom; -+ else -+ goto err0; -+ } -+ -+ return 0; -+ -+err0: -+ pr_err("%s Low memory\n", __func__); -+ pfe_hif_shm_clean(hif_shm); -+ return -ENOMEM; -+} -+ -+/*This function sends indication to HIF driver -+ * -+ * @param[in] hif hif context -+ */ -+static void hif_lib_indicate_hif(struct pfe_hif *hif, int req, int data1, int -+ data2) -+{ -+ hif_process_client_req(hif, req, data1, data2); -+} -+ -+void hif_lib_indicate_client(int client_id, int event_type, int qno) -+{ -+ struct hif_client_s *client = pfe->hif_client[client_id]; -+ -+ if (!client || (event_type >= HIF_EVENT_MAX) || (qno >= -+ HIF_CLIENT_QUEUES_MAX)) -+ return; -+ -+ if (!test_and_set_bit(qno, &client->queue_mask[event_type])) -+ client->event_handler(client->priv, event_type, qno); -+} -+ -+/*This function releases Rx queue descriptors memory and pre-filled buffers -+ * -+ * @param[in] client hif_client context -+ */ -+static void hif_lib_client_release_rx_buffers(struct hif_client_s *client) -+{ -+ struct rx_queue_desc *desc; -+ int qno, ii; -+ void *buf; -+ -+ for (qno = 0; qno < client->rx_qn; qno++) { -+ desc = client->rx_q[qno].base; -+ -+ for (ii = 0; ii < client->rx_q[qno].size; ii++) { -+ buf = (void *)desc->data; -+ if (buf) { -+ buf -= pfe_pkt_headroom; -+ -+ if (page_mode) -+ free_page((unsigned long)buf); -+ else -+ kfree(buf); -+ -+ desc->ctrl = 0; -+ } -+ -+ desc++; -+ } -+ } -+ -+ kfree(client->rx_qbase); -+} -+ -+/*This function allocates memory for the rxq descriptors and pre-fill rx queues -+ * with buffers. -+ * @param[in] client client context -+ * @param[in] q_size size of the rxQ, all queues are of same size -+ */ -+static int hif_lib_client_init_rx_buffers(struct hif_client_s *client, int -+ q_size) -+{ -+ struct rx_queue_desc *desc; -+ struct hif_client_rx_queue *queue; -+ int ii, qno; -+ -+ /*Allocate memory for the client queues */ -+ client->rx_qbase = kzalloc(client->rx_qn * q_size * sizeof(struct -+ rx_queue_desc), GFP_KERNEL); -+ if (!client->rx_qbase) -+ goto err; -+ -+ for (qno = 0; qno < client->rx_qn; qno++) { -+ queue = &client->rx_q[qno]; -+ -+ queue->base = client->rx_qbase + qno * q_size * sizeof(struct -+ rx_queue_desc); -+ queue->size = q_size; -+ queue->read_idx = 0; -+ queue->write_idx = 0; -+ -+ pr_debug("rx queue: %d, base: %p, size: %d\n", qno, -+ queue->base, queue->size); -+ } -+ -+ for (qno = 0; qno < client->rx_qn; qno++) { -+ queue = &client->rx_q[qno]; -+ desc = queue->base; -+ -+ for (ii = 0; ii < queue->size; ii++) { -+ desc->ctrl = CL_DESC_BUF_LEN(pfe_pkt_size) | -+ CL_DESC_OWN; -+ desc++; -+ } -+ } -+ -+ return 0; -+ -+err: -+ return 1; -+} -+ -+ -+static void hif_lib_client_cleanup_tx_queue(struct hif_client_tx_queue *queue) -+{ -+ pr_debug("%s\n", __func__); -+ -+ /* -+ * Check if there are any pending packets. Client must flush the tx -+ * queues before unregistering, by calling by calling -+ * hif_lib_tx_get_next_complete() -+ * -+ * Hif no longer calls since we are no longer registered -+ */ -+ if (queue->tx_pending) -+ pr_err("%s: pending transmit packets\n", __func__); -+} -+ -+static void hif_lib_client_release_tx_buffers(struct hif_client_s *client) -+{ -+ int qno; -+ -+ pr_debug("%s\n", __func__); -+ -+ for (qno = 0; qno < client->tx_qn; qno++) -+ hif_lib_client_cleanup_tx_queue(&client->tx_q[qno]); -+ -+ kfree(client->tx_qbase); -+} -+ -+static int hif_lib_client_init_tx_buffers(struct hif_client_s *client, int -+ q_size) -+{ -+ struct hif_client_tx_queue *queue; -+ int qno; -+ -+ client->tx_qbase = kzalloc(client->tx_qn * q_size * sizeof(struct -+ tx_queue_desc), GFP_KERNEL); -+ if (!client->tx_qbase) -+ return 1; -+ -+ for (qno = 0; qno < client->tx_qn; qno++) { -+ queue = &client->tx_q[qno]; -+ -+ queue->base = client->tx_qbase + qno * q_size * sizeof(struct -+ tx_queue_desc); -+ queue->size = q_size; -+ queue->read_idx = 0; -+ queue->write_idx = 0; -+ queue->tx_pending = 0; -+ queue->nocpy_flag = 0; -+ queue->prev_tmu_tx_pkts = 0; -+ queue->done_tmu_tx_pkts = 0; -+ -+ pr_debug("tx queue: %d, base: %p, size: %d\n", qno, -+ queue->base, queue->size); -+ } -+ -+ return 0; -+} -+ -+static int hif_lib_event_dummy(void *priv, int event_type, int qno) -+{ -+ return 0; -+} -+ -+int hif_lib_client_register(struct hif_client_s *client) -+{ -+ struct hif_shm *hif_shm; -+ struct hif_client_shm *client_shm; -+ int err, i; -+ /* int loop_cnt = 0; */ -+ -+ pr_debug("%s\n", __func__); -+ -+ /*Allocate memory before spin_lock*/ -+ if (hif_lib_client_init_rx_buffers(client, client->rx_qsize)) { -+ err = -ENOMEM; -+ goto err_rx; -+ } -+ -+ if (hif_lib_client_init_tx_buffers(client, client->tx_qsize)) { -+ err = -ENOMEM; -+ goto err_tx; -+ } -+ -+ spin_lock_bh(&pfe->hif.lock); -+ if (!(client->pfe) || (client->id >= HIF_CLIENTS_MAX) || -+ (pfe->hif_client[client->id])) { -+ err = -EINVAL; -+ goto err; -+ } -+ -+ hif_shm = client->pfe->hif.shm; -+ -+ if (!client->event_handler) -+ client->event_handler = hif_lib_event_dummy; -+ -+ /*Initialize client specific shared memory */ -+ client_shm = (struct hif_client_shm *)&hif_shm->client[client->id]; -+ client_shm->rx_qbase = (unsigned long int)client->rx_qbase; -+ client_shm->rx_qsize = client->rx_qsize; -+ client_shm->tx_qbase = (unsigned long int)client->tx_qbase; -+ client_shm->tx_qsize = client->tx_qsize; -+ client_shm->ctrl = (client->tx_qn << CLIENT_CTRL_TX_Q_CNT_OFST) | -+ (client->rx_qn << CLIENT_CTRL_RX_Q_CNT_OFST); -+ /* spin_lock_init(&client->rx_lock); */ -+ -+ for (i = 0; i < HIF_EVENT_MAX; i++) { -+ client->queue_mask[i] = 0; /* -+ * By default all events are -+ * unmasked -+ */ -+ } -+ -+ /*Indicate to HIF driver*/ -+ hif_lib_indicate_hif(&pfe->hif, REQUEST_CL_REGISTER, client->id, 0); -+ -+ pr_debug("%s: client: %p, client_id: %d, tx_qsize: %d, rx_qsize: %d\n", -+ __func__, client, client->id, client->tx_qsize, -+ client->rx_qsize); -+ -+ client->cpu_id = -1; -+ -+ pfe->hif_client[client->id] = client; -+ spin_unlock_bh(&pfe->hif.lock); -+ -+ return 0; -+ -+err: -+ spin_unlock_bh(&pfe->hif.lock); -+ hif_lib_client_release_tx_buffers(client); -+ -+err_tx: -+ hif_lib_client_release_rx_buffers(client); -+ -+err_rx: -+ return err; -+} -+ -+int hif_lib_client_unregister(struct hif_client_s *client) -+{ -+ struct pfe *pfe = client->pfe; -+ u32 client_id = client->id; -+ -+ pr_info( -+ "%s : client: %p, client_id: %d, txQ_depth: %d, rxQ_depth: %d\n" -+ , __func__, client, client->id, client->tx_qsize, -+ client->rx_qsize); -+ -+ spin_lock_bh(&pfe->hif.lock); -+ hif_lib_indicate_hif(&pfe->hif, REQUEST_CL_UNREGISTER, client->id, 0); -+ -+ hif_lib_client_release_tx_buffers(client); -+ hif_lib_client_release_rx_buffers(client); -+ pfe->hif_client[client_id] = NULL; -+ spin_unlock_bh(&pfe->hif.lock); -+ -+ return 0; -+} -+ -+int hif_lib_event_handler_start(struct hif_client_s *client, int event, -+ int qno) -+{ -+ struct hif_client_rx_queue *queue = &client->rx_q[qno]; -+ struct rx_queue_desc *desc = queue->base + queue->read_idx; -+ -+ if ((event >= HIF_EVENT_MAX) || (qno >= HIF_CLIENT_QUEUES_MAX)) { -+ pr_debug("%s: Unsupported event : %d queue number : %d\n", -+ __func__, event, qno); -+ return -1; -+ } -+ -+ test_and_clear_bit(qno, &client->queue_mask[event]); -+ -+ switch (event) { -+ case EVENT_RX_PKT_IND: -+ if (!(desc->ctrl & CL_DESC_OWN)) -+ hif_lib_indicate_client(client->id, -+ EVENT_RX_PKT_IND, qno); -+ break; -+ -+ case EVENT_HIGH_RX_WM: -+ case EVENT_TXDONE_IND: -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+ * This function gets one packet from the specified client queue -+ * It also refill the rx buffer -+ */ -+void *hif_lib_receive_pkt(struct hif_client_s *client, int qno, int *len, int -+ *ofst, unsigned int *rx_ctrl, -+ unsigned int *desc_ctrl, void **priv_data) -+{ -+ struct hif_client_rx_queue *queue = &client->rx_q[qno]; -+ struct rx_queue_desc *desc; -+ void *pkt = NULL; -+ -+ /* -+ * Following lock is to protect rx queue access from, -+ * hif_lib_event_handler_start. -+ * In general below lock is not required, because hif_lib_xmit_pkt and -+ * hif_lib_event_handler_start are called from napi poll and which is -+ * not re-entrant. But if some client use in different way this lock is -+ * required. -+ */ -+ /*spin_lock_irqsave(&client->rx_lock, flags); */ -+ desc = queue->base + queue->read_idx; -+ if (!(desc->ctrl & CL_DESC_OWN)) { -+ pkt = desc->data - pfe_pkt_headroom; -+ -+ *rx_ctrl = desc->client_ctrl; -+ *desc_ctrl = desc->ctrl; -+ -+ if (desc->ctrl & CL_DESC_FIRST) { -+ u16 size = *rx_ctrl >> HIF_CTRL_RX_OFFSET_OFST; -+ -+ if (size) { -+ size += PFE_PARSE_INFO_SIZE; -+ *len = CL_DESC_BUF_LEN(desc->ctrl) - -+ PFE_PKT_HEADER_SZ - size; -+ *ofst = pfe_pkt_headroom + PFE_PKT_HEADER_SZ -+ + size; -+ *priv_data = desc->data + PFE_PKT_HEADER_SZ; -+ } else { -+ *len = CL_DESC_BUF_LEN(desc->ctrl) - -+ PFE_PKT_HEADER_SZ - PFE_PARSE_INFO_SIZE; -+ *ofst = pfe_pkt_headroom -+ + PFE_PKT_HEADER_SZ -+ + PFE_PARSE_INFO_SIZE; -+ *priv_data = NULL; -+ } -+ -+ } else { -+ *len = CL_DESC_BUF_LEN(desc->ctrl); -+ *ofst = pfe_pkt_headroom; -+ } -+ -+ /* -+ * Needed so we don't free a buffer/page -+ * twice on module_exit -+ */ -+ desc->data = NULL; -+ -+ /* -+ * Ensure everything else is written to DDR before -+ * writing bd->ctrl -+ */ -+ smp_wmb(); -+ -+ desc->ctrl = CL_DESC_BUF_LEN(pfe_pkt_size) | CL_DESC_OWN; -+ queue->read_idx = (queue->read_idx + 1) & (queue->size - 1); -+ } -+ -+ /*spin_unlock_irqrestore(&client->rx_lock, flags); */ -+ return pkt; -+} -+ -+static inline void hif_hdr_write(struct hif_hdr *pkt_hdr, unsigned int -+ client_id, unsigned int qno, -+ u32 client_ctrl) -+{ -+ /* Optimize the write since the destinaton may be non-cacheable */ -+ if (!((unsigned long)pkt_hdr & 0x3)) { -+ ((u32 *)pkt_hdr)[0] = (client_ctrl << 16) | (qno << 8) | -+ client_id; -+ } else { -+ ((u16 *)pkt_hdr)[0] = (qno << 8) | (client_id & 0xFF); -+ ((u16 *)pkt_hdr)[1] = (client_ctrl & 0xFFFF); -+ } -+} -+ -+/*This function puts the given packet in the specific client queue */ -+void __hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void -+ *data, unsigned int len, u32 client_ctrl, -+ unsigned int flags, void *client_data) -+{ -+ struct hif_client_tx_queue *queue = &client->tx_q[qno]; -+ struct tx_queue_desc *desc = queue->base + queue->write_idx; -+ -+ /* First buffer */ -+ if (flags & HIF_FIRST_BUFFER) { -+ data -= sizeof(struct hif_hdr); -+ len += sizeof(struct hif_hdr); -+ -+ hif_hdr_write(data, client->id, qno, client_ctrl); -+ } -+ -+ desc->data = client_data; -+ desc->ctrl = CL_DESC_OWN | CL_DESC_FLAGS(flags); -+ -+ __hif_xmit_pkt(&pfe->hif, client->id, qno, data, len, flags); -+ -+ queue->write_idx = (queue->write_idx + 1) & (queue->size - 1); -+ queue->tx_pending++; -+ queue->jiffies_last_packet = jiffies; -+} -+ -+void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno, -+ unsigned int *flags, int count) -+{ -+ struct hif_client_tx_queue *queue = &client->tx_q[qno]; -+ struct tx_queue_desc *desc = queue->base + queue->read_idx; -+ -+ pr_debug("%s: qno : %d rd_indx: %d pending:%d\n", __func__, qno, -+ queue->read_idx, queue->tx_pending); -+ -+ if (!queue->tx_pending) -+ return NULL; -+ -+ if (queue->nocpy_flag && !queue->done_tmu_tx_pkts) { -+ u32 tmu_tx_pkts = be32_to_cpu(pe_dmem_read(TMU0_ID + -+ client->id, TMU_DM_TX_TRANS, 4)); -+ -+ if (queue->prev_tmu_tx_pkts > tmu_tx_pkts) -+ queue->done_tmu_tx_pkts = UINT_MAX - -+ queue->prev_tmu_tx_pkts + tmu_tx_pkts; -+ else -+ queue->done_tmu_tx_pkts = tmu_tx_pkts - -+ queue->prev_tmu_tx_pkts; -+ -+ queue->prev_tmu_tx_pkts = tmu_tx_pkts; -+ -+ if (!queue->done_tmu_tx_pkts) -+ return NULL; -+ } -+ -+ if (desc->ctrl & CL_DESC_OWN) -+ return NULL; -+ -+ queue->read_idx = (queue->read_idx + 1) & (queue->size - 1); -+ queue->tx_pending--; -+ -+ *flags = CL_DESC_GET_FLAGS(desc->ctrl); -+ -+ if (queue->done_tmu_tx_pkts && (*flags & HIF_LAST_BUFFER)) -+ queue->done_tmu_tx_pkts--; -+ -+ return desc->data; -+} -+ -+static void hif_lib_tmu_credit_init(struct pfe *pfe) -+{ -+ int i, q; -+ -+ for (i = 0; i < NUM_GEMAC_SUPPORT; i++) -+ for (q = 0; q < emac_txq_cnt; q++) { -+ pfe->tmu_credit.tx_credit_max[i][q] = (q == 0) ? -+ DEFAULT_Q0_QDEPTH : DEFAULT_MAX_QDEPTH; -+ pfe->tmu_credit.tx_credit[i][q] = -+ pfe->tmu_credit.tx_credit_max[i][q]; -+ } -+} -+ -+/* __hif_lib_update_credit -+ * -+ * @param[in] client hif client context -+ * @param[in] queue queue number in match with TMU -+ */ -+void __hif_lib_update_credit(struct hif_client_s *client, unsigned int queue) -+{ -+ unsigned int tmu_tx_packets, tmp; -+ -+ if (tx_qos) { -+ tmu_tx_packets = be32_to_cpu(pe_dmem_read(TMU0_ID + -+ client->id, (TMU_DM_TX_TRANS + (queue * 4)), 4)); -+ -+ /* tx_packets counter overflowed */ -+ if (tmu_tx_packets > -+ pfe->tmu_credit.tx_packets[client->id][queue]) { -+ tmp = UINT_MAX - tmu_tx_packets + -+ pfe->tmu_credit.tx_packets[client->id][queue]; -+ -+ pfe->tmu_credit.tx_credit[client->id][queue] = -+ pfe->tmu_credit.tx_credit_max[client->id][queue] - tmp; -+ } else { -+ /* TMU tx <= pfe_eth tx, normal case or both OF since -+ * last time -+ */ -+ pfe->tmu_credit.tx_credit[client->id][queue] = -+ pfe->tmu_credit.tx_credit_max[client->id][queue] - -+ (pfe->tmu_credit.tx_packets[client->id][queue] - -+ tmu_tx_packets); -+ } -+ } -+} -+ -+int pfe_hif_lib_init(struct pfe *pfe) -+{ -+ int rc; -+ -+ pr_info("%s\n", __func__); -+ -+ if (lro_mode) { -+ page_mode = 1; -+ pfe_pkt_size = min(PAGE_SIZE, MAX_PFE_PKT_SIZE); -+ pfe_pkt_headroom = 0; -+ } else { -+ page_mode = 0; -+ pfe_pkt_size = PFE_PKT_SIZE; -+ pfe_pkt_headroom = PFE_PKT_HEADROOM; -+ } -+ -+ if (tx_qos) -+ emac_txq_cnt = EMAC_TXQ_CNT / 2; -+ else -+ emac_txq_cnt = EMAC_TXQ_CNT; -+ -+ hif_lib_tmu_credit_init(pfe); -+ pfe->hif.shm = &ghif_shm; -+ rc = pfe_hif_shm_init(pfe->hif.shm); -+ -+ return rc; -+} -+ -+void pfe_hif_lib_exit(struct pfe *pfe) -+{ -+ pr_info("%s\n", __func__); -+ -+ pfe_hif_shm_clean(pfe->hif.shm); -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_hif_lib.h -@@ -0,0 +1,229 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#ifndef _PFE_HIF_LIB_H_ -+#define _PFE_HIF_LIB_H_ -+ -+#include "pfe_hif.h" -+ -+#define HIF_CL_REQ_TIMEOUT 10 -+#define GFP_DMA_PFE 0 -+#define PFE_PARSE_INFO_SIZE 16 -+ -+enum { -+ REQUEST_CL_REGISTER = 0, -+ REQUEST_CL_UNREGISTER, -+ HIF_REQUEST_MAX -+}; -+ -+enum { -+ /* Event to indicate that client rx queue is reached water mark level */ -+ EVENT_HIGH_RX_WM = 0, -+ /* Event to indicate that, packet received for client */ -+ EVENT_RX_PKT_IND, -+ /* Event to indicate that, packet tx done for client */ -+ EVENT_TXDONE_IND, -+ HIF_EVENT_MAX -+}; -+ -+/*structure to store client queue info */ -+ -+/*structure to store client queue info */ -+struct hif_client_rx_queue { -+ struct rx_queue_desc *base; -+ u32 size; -+ u32 read_idx; -+ u32 write_idx; -+}; -+ -+struct hif_client_tx_queue { -+ struct tx_queue_desc *base; -+ u32 size; -+ u32 read_idx; -+ u32 write_idx; -+ u32 tx_pending; -+ unsigned long jiffies_last_packet; -+ u32 nocpy_flag; -+ u32 prev_tmu_tx_pkts; -+ u32 done_tmu_tx_pkts; -+}; -+ -+struct hif_client_s { -+ int id; -+ int tx_qn; -+ int rx_qn; -+ void *rx_qbase; -+ void *tx_qbase; -+ int tx_qsize; -+ int rx_qsize; -+ int cpu_id; -+ struct hif_client_tx_queue tx_q[HIF_CLIENT_QUEUES_MAX]; -+ struct hif_client_rx_queue rx_q[HIF_CLIENT_QUEUES_MAX]; -+ int (*event_handler)(void *priv, int event, int data); -+ unsigned long queue_mask[HIF_EVENT_MAX]; -+ struct pfe *pfe; -+ void *priv; -+}; -+ -+/* -+ * Client specific shared memory -+ * It contains number of Rx/Tx queues, base addresses and queue sizes -+ */ -+struct hif_client_shm { -+ u32 ctrl; /*0-7: number of Rx queues, 8-15: number of tx queues */ -+ unsigned long rx_qbase; /*Rx queue base address */ -+ u32 rx_qsize; /*each Rx queue size, all Rx queues are of same size */ -+ unsigned long tx_qbase; /* Tx queue base address */ -+ u32 tx_qsize; /*each Tx queue size, all Tx queues are of same size */ -+}; -+ -+/*Client shared memory ctrl bit description */ -+#define CLIENT_CTRL_RX_Q_CNT_OFST 0 -+#define CLIENT_CTRL_TX_Q_CNT_OFST 8 -+#define CLIENT_CTRL_RX_Q_CNT(ctrl) (((ctrl) >> CLIENT_CTRL_RX_Q_CNT_OFST) \ -+ & 0xFF) -+#define CLIENT_CTRL_TX_Q_CNT(ctrl) (((ctrl) >> CLIENT_CTRL_TX_Q_CNT_OFST) \ -+ & 0xFF) -+ -+/* -+ * Shared memory used to communicate between HIF driver and host/client drivers -+ * Before starting the hif driver rx_buf_pool ans rx_buf_pool_cnt should be -+ * initialized with host buffers and buffers count in the pool. -+ * rx_buf_pool_cnt should be >= HIF_RX_DESC_NT. -+ * -+ */ -+struct hif_shm { -+ u32 rx_buf_pool_cnt; /*Number of rx buffers available*/ -+ /*Rx buffers required to initialize HIF rx descriptors */ -+ void *rx_buf_pool[HIF_RX_DESC_NT]; -+ unsigned long g_client_status[2]; /*Global client status bit mask */ -+ /* Client specific shared memory */ -+ struct hif_client_shm client[HIF_CLIENTS_MAX]; -+}; -+ -+#define CL_DESC_OWN BIT(31) -+/* This sets owner ship to HIF driver */ -+#define CL_DESC_LAST BIT(30) -+/* This indicates last packet for multi buffers handling */ -+#define CL_DESC_FIRST BIT(29) -+/* This indicates first packet for multi buffers handling */ -+ -+#define CL_DESC_BUF_LEN(x) ((x) & 0xFFFF) -+#define CL_DESC_FLAGS(x) (((x) & 0xF) << 16) -+#define CL_DESC_GET_FLAGS(x) (((x) >> 16) & 0xF) -+ -+struct rx_queue_desc { -+ void *data; -+ u32 ctrl; /*0-15bit len, 16-20bit flags, 31bit owner*/ -+ u32 client_ctrl; -+}; -+ -+struct tx_queue_desc { -+ void *data; -+ u32 ctrl; /*0-15bit len, 16-20bit flags, 31bit owner*/ -+}; -+ -+/* HIF Rx is not working properly for 2-byte aligned buffers and -+ * ip_header should be 4byte aligned for better iperformance. -+ * "ip_header = 64 + 6(hif_header) + 14 (MAC Header)" will be 4byte aligned. -+ */ -+#define PFE_PKT_HEADER_SZ sizeof(struct hif_hdr) -+/* must be big enough for headroom, pkt size and skb shared info */ -+#define PFE_BUF_SIZE 2048 -+#define PFE_PKT_HEADROOM 128 -+ -+#define SKB_SHARED_INFO_SIZE SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) -+#define PFE_PKT_SIZE (PFE_BUF_SIZE - PFE_PKT_HEADROOM \ -+ - SKB_SHARED_INFO_SIZE) -+#define MAX_L2_HDR_SIZE 14 /* Not correct for VLAN/PPPoE */ -+#define MAX_L3_HDR_SIZE 20 /* Not correct for IPv6 */ -+#define MAX_L4_HDR_SIZE 60 /* TCP with maximum options */ -+#define MAX_HDR_SIZE (MAX_L2_HDR_SIZE + MAX_L3_HDR_SIZE \ -+ + MAX_L4_HDR_SIZE) -+/* Used in page mode to clamp packet size to the maximum supported by the hif -+ *hw interface (<16KiB) -+ */ -+#define MAX_PFE_PKT_SIZE 16380UL -+ -+extern unsigned int pfe_pkt_size; -+extern unsigned int pfe_pkt_headroom; -+extern unsigned int page_mode; -+extern unsigned int lro_mode; -+extern unsigned int tx_qos; -+extern unsigned int emac_txq_cnt; -+ -+int pfe_hif_lib_init(struct pfe *pfe); -+void pfe_hif_lib_exit(struct pfe *pfe); -+int hif_lib_client_register(struct hif_client_s *client); -+int hif_lib_client_unregister(struct hif_client_s *client); -+void __hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void -+ *data, unsigned int len, u32 client_ctrl, -+ unsigned int flags, void *client_data); -+int hif_lib_xmit_pkt(struct hif_client_s *client, unsigned int qno, void *data, -+ unsigned int len, u32 client_ctrl, void *client_data); -+void hif_lib_indicate_client(int cl_id, int event, int data); -+int hif_lib_event_handler_start(struct hif_client_s *client, int event, int -+ data); -+int hif_lib_tmu_queue_start(struct hif_client_s *client, int qno); -+int hif_lib_tmu_queue_stop(struct hif_client_s *client, int qno); -+void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno, -+ unsigned int *flags, int count); -+void *hif_lib_receive_pkt(struct hif_client_s *client, int qno, int *len, int -+ *ofst, unsigned int *rx_ctrl, -+ unsigned int *desc_ctrl, void **priv_data); -+void __hif_lib_update_credit(struct hif_client_s *client, unsigned int queue); -+void hif_lib_set_rx_cpu_affinity(struct hif_client_s *client, int cpu_id); -+void hif_lib_set_tx_queue_nocpy(struct hif_client_s *client, int qno, int -+ enable); -+static inline int hif_lib_tx_avail(struct hif_client_s *client, unsigned int -+ qno) -+{ -+ struct hif_client_tx_queue *queue = &client->tx_q[qno]; -+ -+ return (queue->size - queue->tx_pending); -+} -+ -+static inline int hif_lib_get_tx_wr_index(struct hif_client_s *client, unsigned -+ int qno) -+{ -+ struct hif_client_tx_queue *queue = &client->tx_q[qno]; -+ -+ return queue->write_idx; -+} -+ -+static inline int hif_lib_tx_pending(struct hif_client_s *client, unsigned int -+ qno) -+{ -+ struct hif_client_tx_queue *queue = &client->tx_q[qno]; -+ -+ return queue->tx_pending; -+} -+ -+#define hif_lib_tx_credit_avail(pfe, id, qno) \ -+ ((pfe)->tmu_credit.tx_credit[id][qno]) -+ -+#define hif_lib_tx_credit_max(pfe, id, qno) \ -+ ((pfe)->tmu_credit.tx_credit_max[id][qno]) -+ -+/* -+ * Test comment -+ */ -+#define hif_lib_tx_credit_use(pfe, id, qno, credit) \ -+ ({ typeof(pfe) pfe_ = pfe; \ -+ typeof(id) id_ = id; \ -+ typeof(qno) qno_ = qno; \ -+ typeof(credit) credit_ = credit; \ -+ do { \ -+ if (tx_qos) { \ -+ (pfe_)->tmu_credit.tx_credit[id_][qno_]\ -+ -= credit_; \ -+ (pfe_)->tmu_credit.tx_packets[id_][qno_]\ -+ += credit_; \ -+ } \ -+ } while (0); \ -+ }) -+ -+#endif /* _PFE_HIF_LIB_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_hw.c -@@ -0,0 +1,164 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#include "pfe_mod.h" -+#include "pfe_hw.h" -+ -+/* Functions to handle most of pfe hw register initialization */ -+int pfe_hw_init(struct pfe *pfe, int resume) -+{ -+ struct class_cfg class_cfg = { -+ .pe_sys_clk_ratio = PE_SYS_CLK_RATIO, -+ .route_table_baseaddr = pfe->ddr_phys_baseaddr + -+ ROUTE_TABLE_BASEADDR, -+ .route_table_hash_bits = ROUTE_TABLE_HASH_BITS, -+ }; -+ -+ struct tmu_cfg tmu_cfg = { -+ .pe_sys_clk_ratio = PE_SYS_CLK_RATIO, -+ .llm_base_addr = pfe->ddr_phys_baseaddr + TMU_LLM_BASEADDR, -+ .llm_queue_len = TMU_LLM_QUEUE_LEN, -+ }; -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ struct util_cfg util_cfg = { -+ .pe_sys_clk_ratio = PE_SYS_CLK_RATIO, -+ }; -+#endif -+ -+ struct BMU_CFG bmu1_cfg = { -+ .baseaddr = CBUS_VIRT_TO_PFE(LMEM_BASE_ADDR + -+ BMU1_LMEM_BASEADDR), -+ .count = BMU1_BUF_COUNT, -+ .size = BMU1_BUF_SIZE, -+ .low_watermark = 10, -+ .high_watermark = 15, -+ }; -+ -+ struct BMU_CFG bmu2_cfg = { -+ .baseaddr = DDR_PHYS_TO_PFE(pfe->ddr_phys_baseaddr + -+ BMU2_DDR_BASEADDR), -+ .count = BMU2_BUF_COUNT, -+ .size = BMU2_BUF_SIZE, -+ .low_watermark = 250, -+ .high_watermark = 253, -+ }; -+ -+ struct gpi_cfg egpi1_cfg = { -+ .lmem_rtry_cnt = EGPI1_LMEM_RTRY_CNT, -+ .tmlf_txthres = EGPI1_TMLF_TXTHRES, -+ .aseq_len = EGPI1_ASEQ_LEN, -+ .mtip_pause_reg = CBUS_VIRT_TO_PFE(EMAC1_BASE_ADDR + -+ EMAC_TCNTRL_REG), -+ }; -+ -+ struct gpi_cfg egpi2_cfg = { -+ .lmem_rtry_cnt = EGPI2_LMEM_RTRY_CNT, -+ .tmlf_txthres = EGPI2_TMLF_TXTHRES, -+ .aseq_len = EGPI2_ASEQ_LEN, -+ .mtip_pause_reg = CBUS_VIRT_TO_PFE(EMAC2_BASE_ADDR + -+ EMAC_TCNTRL_REG), -+ }; -+ -+ struct gpi_cfg hgpi_cfg = { -+ .lmem_rtry_cnt = HGPI_LMEM_RTRY_CNT, -+ .tmlf_txthres = HGPI_TMLF_TXTHRES, -+ .aseq_len = HGPI_ASEQ_LEN, -+ .mtip_pause_reg = 0, -+ }; -+ -+ pr_info("%s\n", __func__); -+ -+#if !defined(LS1012A_PFE_RESET_WA) -+ /* LS1012A needs this to make PE work correctly */ -+ writel(0x3, CLASS_PE_SYS_CLK_RATIO); -+ writel(0x3, TMU_PE_SYS_CLK_RATIO); -+ writel(0x3, UTIL_PE_SYS_CLK_RATIO); -+ usleep_range(10, 20); -+#endif -+ -+ pr_info("CLASS version: %x\n", readl(CLASS_VERSION)); -+ pr_info("TMU version: %x\n", readl(TMU_VERSION)); -+ -+ pr_info("BMU1 version: %x\n", readl(BMU1_BASE_ADDR + -+ BMU_VERSION)); -+ pr_info("BMU2 version: %x\n", readl(BMU2_BASE_ADDR + -+ BMU_VERSION)); -+ -+ pr_info("EGPI1 version: %x\n", readl(EGPI1_BASE_ADDR + -+ GPI_VERSION)); -+ pr_info("EGPI2 version: %x\n", readl(EGPI2_BASE_ADDR + -+ GPI_VERSION)); -+ pr_info("HGPI version: %x\n", readl(HGPI_BASE_ADDR + -+ GPI_VERSION)); -+ -+ pr_info("HIF version: %x\n", readl(HIF_VERSION)); -+ pr_info("HIF NOPCY version: %x\n", readl(HIF_NOCPY_VERSION)); -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ pr_info("UTIL version: %x\n", readl(UTIL_VERSION)); -+#endif -+ while (!(readl(TMU_CTRL) & ECC_MEM_INIT_DONE)) -+ ; -+ -+ hif_rx_disable(); -+ hif_tx_disable(); -+ -+ bmu_init(BMU1_BASE_ADDR, &bmu1_cfg); -+ -+ pr_info("bmu_init(1) done\n"); -+ -+ bmu_init(BMU2_BASE_ADDR, &bmu2_cfg); -+ -+ pr_info("bmu_init(2) done\n"); -+ -+ class_cfg.resume = resume ? 1 : 0; -+ -+ class_init(&class_cfg); -+ -+ pr_info("class_init() done\n"); -+ -+ tmu_init(&tmu_cfg); -+ -+ pr_info("tmu_init() done\n"); -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ util_init(&util_cfg); -+ -+ pr_info("util_init() done\n"); -+#endif -+ gpi_init(EGPI1_BASE_ADDR, &egpi1_cfg); -+ -+ pr_info("gpi_init(1) done\n"); -+ -+ gpi_init(EGPI2_BASE_ADDR, &egpi2_cfg); -+ -+ pr_info("gpi_init(2) done\n"); -+ -+ gpi_init(HGPI_BASE_ADDR, &hgpi_cfg); -+ -+ pr_info("gpi_init(hif) done\n"); -+ -+ bmu_enable(BMU1_BASE_ADDR); -+ -+ pr_info("bmu_enable(1) done\n"); -+ -+ bmu_enable(BMU2_BASE_ADDR); -+ -+ pr_info("bmu_enable(2) done\n"); -+ -+ return 0; -+} -+ -+void pfe_hw_exit(struct pfe *pfe) -+{ -+ pr_info("%s\n", __func__); -+ -+ bmu_disable(BMU1_BASE_ADDR); -+ bmu_reset(BMU1_BASE_ADDR); -+ -+ bmu_disable(BMU2_BASE_ADDR); -+ bmu_reset(BMU2_BASE_ADDR); -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_hw.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#ifndef _PFE_HW_H_ -+#define _PFE_HW_H_ -+ -+#define PE_SYS_CLK_RATIO 1 /* SYS/AXI = 250MHz, HFE = 500MHz */ -+ -+int pfe_hw_init(struct pfe *pfe, int resume); -+void pfe_hw_exit(struct pfe *pfe); -+ -+#endif /* _PFE_HW_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c -@@ -0,0 +1,381 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "pfe_mod.h" -+ -+extern bool pfe_use_old_dts_phy; -+struct ls1012a_pfe_platform_data pfe_platform_data; -+ -+static int pfe_get_gemac_if_properties(struct device_node *gem, -+ int port, -+ struct ls1012a_pfe_platform_data *pdata) -+{ -+ struct device_node *phy_node = NULL; -+ int size; -+ int phy_id = 0; -+ const u32 *addr; -+ int err; -+ -+ addr = of_get_property(gem, "reg", &size); -+ if (addr) -+ port = be32_to_cpup(addr); -+ else -+ goto err; -+ -+ pdata->ls1012a_eth_pdata[port].gem_id = port; -+ -+ err = of_get_mac_address(gem, pdata->ls1012a_eth_pdata[port].mac_addr); -+ -+ phy_node = of_parse_phandle(gem, "phy-handle", 0); -+ pdata->ls1012a_eth_pdata[port].phy_node = phy_node; -+ if (phy_node) { -+ pfe_use_old_dts_phy = false; -+ goto process_phynode; -+ } else if (of_phy_is_fixed_link(gem)) { -+ pfe_use_old_dts_phy = false; -+ if (of_phy_register_fixed_link(gem) < 0) { -+ pr_err("broken fixed-link specification\n"); -+ goto err; -+ } -+ phy_node = of_node_get(gem); -+ pdata->ls1012a_eth_pdata[port].phy_node = phy_node; -+ } else if (of_get_property(gem, "fsl,pfe-phy-if-flags", &size)) { -+ pfe_use_old_dts_phy = true; -+ /* Use old dts properties for phy handling */ -+ addr = of_get_property(gem, "fsl,pfe-phy-if-flags", &size); -+ pdata->ls1012a_eth_pdata[port].phy_flags = be32_to_cpup(addr); -+ -+ addr = of_get_property(gem, "fsl,gemac-phy-id", &size); -+ if (!addr) { -+ pr_err("%s:%d Invalid gemac-phy-id....\n", __func__, -+ __LINE__); -+ } else { -+ phy_id = be32_to_cpup(addr); -+ pdata->ls1012a_eth_pdata[port].phy_id = phy_id; -+ pdata->ls1012a_mdio_pdata[0].phy_mask &= ~(1 << phy_id); -+ } -+ -+ /* If PHY is enabled, read mdio properties */ -+ if (pdata->ls1012a_eth_pdata[port].phy_flags & GEMAC_NO_PHY) -+ goto done; -+ -+ } else { -+ pr_info("%s: No PHY or fixed-link\n", __func__); -+ return 0; -+ } -+ -+process_phynode: -+ err = of_get_phy_mode(gem, &pdata->ls1012a_eth_pdata[port].mii_config); -+ if (err) -+ pr_err("%s:%d Incorrect Phy mode....\n", __func__, -+ __LINE__); -+ -+ addr = of_get_property(gem, "fsl,mdio-mux-val", &size); -+ if (!addr) { -+ pr_err("%s: Invalid mdio-mux-val....\n", __func__); -+ } else { -+ phy_id = be32_to_cpup(addr); -+ pdata->ls1012a_eth_pdata[port].mdio_muxval = phy_id; -+ } -+ -+ if (pdata->ls1012a_eth_pdata[port].phy_id < 32) -+ pfe->mdio_muxval[pdata->ls1012a_eth_pdata[port].phy_id] = -+ pdata->ls1012a_eth_pdata[port].mdio_muxval; -+ -+ -+ pdata->ls1012a_mdio_pdata[port].irq[0] = PHY_POLL; -+ -+done: -+ return 0; -+ -+err: -+ return -1; -+} -+ -+/* -+ * -+ * pfe_platform_probe - -+ * -+ * -+ */ -+static int pfe_platform_probe(struct platform_device *pdev) -+{ -+ struct resource res; -+ int ii = 0, rc, interface_count = 0, size = 0; -+ const u32 *prop; -+ struct device_node *np, *gem = NULL; -+ struct clk *pfe_clk; -+ -+ np = pdev->dev.of_node; -+ -+ if (!np) { -+ pr_err("Invalid device node\n"); -+ return -EINVAL; -+ } -+ -+ pfe = kzalloc(sizeof(*pfe), GFP_KERNEL); -+ if (!pfe) { -+ rc = -ENOMEM; -+ goto err_alloc; -+ } -+ -+ platform_set_drvdata(pdev, pfe); -+ -+ if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) { -+ rc = -ENOMEM; -+ pr_err("unable to configure DMA mask.\n"); -+ goto err_ddr; -+ } -+ -+ if (of_address_to_resource(np, 1, &res)) { -+ rc = -ENOMEM; -+ pr_err("failed to get ddr resource\n"); -+ goto err_ddr; -+ } -+ -+ pfe->ddr_phys_baseaddr = res.start; -+ pfe->ddr_size = resource_size(&res); -+ -+ pfe->ddr_baseaddr = memremap(res.start, resource_size(&res), -+ MEMREMAP_WB); -+ if (!pfe->ddr_baseaddr) { -+ pr_err("memremap() ddr failed\n"); -+ rc = -ENOMEM; -+ goto err_ddr; -+ } -+ -+ pfe->scfg = -+ syscon_regmap_lookup_by_phandle(pdev->dev.of_node, -+ "fsl,pfe-scfg"); -+ if (IS_ERR(pfe->scfg)) { -+ dev_err(&pdev->dev, "No syscfg phandle specified\n"); -+ return PTR_ERR(pfe->scfg); -+ } -+ -+ pfe->cbus_baseaddr = of_iomap(np, 0); -+ if (!pfe->cbus_baseaddr) { -+ rc = -ENOMEM; -+ pr_err("failed to get axi resource\n"); -+ goto err_axi; -+ } -+ -+ pfe->hif_irq = platform_get_irq(pdev, 0); -+ if (pfe->hif_irq < 0) { -+ pr_err("platform_get_irq for hif failed\n"); -+ rc = pfe->hif_irq; -+ goto err_hif_irq; -+ } -+ -+ pfe->wol_irq = platform_get_irq(pdev, 2); -+ if (pfe->wol_irq < 0) { -+ pr_err("platform_get_irq for WoL failed\n"); -+ rc = pfe->wol_irq; -+ goto err_hif_irq; -+ } -+ -+ /* Read interface count */ -+ prop = of_get_property(np, "fsl,pfe-num-interfaces", &size); -+ if (!prop) { -+ pr_err("Failed to read number of interfaces\n"); -+ rc = -ENXIO; -+ goto err_prop; -+ } -+ -+ interface_count = be32_to_cpup(prop); -+ if (interface_count <= 0) { -+ pr_err("No ethernet interface count : %d\n", -+ interface_count); -+ rc = -ENXIO; -+ goto err_prop; -+ } -+ -+ pfe_platform_data.ls1012a_mdio_pdata[0].phy_mask = 0xffffffff; -+ -+ while ((gem = of_get_next_child(np, gem))) { -+ if (of_find_property(gem, "reg", &size)) { -+ pfe_get_gemac_if_properties(gem, ii, -+ &pfe_platform_data); -+ ii++; -+ } -+ } -+ -+ if (interface_count != ii) -+ pr_info("missing some of gemac interface properties.\n"); -+ -+ pfe->dev = &pdev->dev; -+ -+ pfe->dev->platform_data = &pfe_platform_data; -+ -+ /* declare WoL capabilities */ -+ device_init_wakeup(&pdev->dev, true); -+ -+ /* find the clocks */ -+ pfe_clk = devm_clk_get(pfe->dev, "pfe"); -+ if (IS_ERR(pfe_clk)) -+ return PTR_ERR(pfe_clk); -+ -+ /* PFE clock is (platform clock / 2) */ -+ /* save sys_clk value as KHz */ -+ pfe->ctrl.sys_clk = clk_get_rate(pfe_clk) / (2 * 1000); -+ -+ rc = pfe_probe(pfe); -+ if (rc < 0) -+ goto err_probe; -+ -+ return 0; -+ -+err_probe: -+err_prop: -+err_hif_irq: -+ iounmap(pfe->cbus_baseaddr); -+ -+err_axi: -+ memunmap(pfe->ddr_baseaddr); -+ -+err_ddr: -+ platform_set_drvdata(pdev, NULL); -+ -+ kfree(pfe); -+ -+err_alloc: -+ return rc; -+} -+ -+/* -+ * pfe_platform_remove - -+ */ -+static void pfe_platform_remove(struct platform_device *pdev) -+{ -+ struct pfe *pfe = platform_get_drvdata(pdev); -+ int rc; -+ -+ pr_info("%s\n", __func__); -+ -+ rc = pfe_remove(pfe); -+ -+ iounmap(pfe->cbus_baseaddr); -+ -+ memunmap(pfe->ddr_baseaddr); -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ kfree(pfe); -+} -+ -+#ifdef CONFIG_PM -+#ifdef CONFIG_PM_SLEEP -+static int pfe_platform_suspend(struct device *dev) -+{ -+ struct pfe *pfe = platform_get_drvdata(to_platform_device(dev)); -+ struct net_device *netdev; -+ int i; -+ -+ pfe->wake = 0; -+ -+ for (i = 0; i < (NUM_GEMAC_SUPPORT); i++) { -+ netdev = pfe->eth.eth_priv[i]->ndev; -+ -+ netif_device_detach(netdev); -+ -+ if (netif_running(netdev)) -+ if (pfe_eth_suspend(netdev)) -+ pfe->wake = 1; -+ } -+ -+ /* Shutdown PFE only if we're not waking up the system */ -+ if (!pfe->wake) { -+#if defined(LS1012A_PFE_RESET_WA) -+ pfe_hif_rx_idle(&pfe->hif); -+#endif -+ pfe_ctrl_suspend(&pfe->ctrl); -+ pfe_firmware_exit(pfe); -+ -+ pfe_hif_exit(pfe); -+ pfe_hif_lib_exit(pfe); -+ -+ pfe_hw_exit(pfe); -+ } -+ -+ return 0; -+} -+ -+static int pfe_platform_resume(struct device *dev) -+{ -+ struct pfe *pfe = platform_get_drvdata(to_platform_device(dev)); -+ struct net_device *netdev; -+ int i; -+ -+ if (!pfe->wake) { -+ pfe_hw_init(pfe, 1); -+ pfe_hif_lib_init(pfe); -+ pfe_hif_init(pfe); -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ util_enable(); -+#endif -+ tmu_enable(0xf); -+ class_enable(); -+ pfe_ctrl_resume(&pfe->ctrl); -+ } -+ -+ for (i = 0; i < (NUM_GEMAC_SUPPORT); i++) { -+ netdev = pfe->eth.eth_priv[i]->ndev; -+ -+ if (pfe->mdio.mdio_priv[i]->mii_bus) -+ pfe_eth_mdio_reset(pfe->mdio.mdio_priv[i]->mii_bus); -+ -+ if (netif_running(netdev)) -+ pfe_eth_resume(netdev); -+ -+ netif_device_attach(netdev); -+ } -+ return 0; -+} -+#else -+#define pfe_platform_suspend NULL -+#define pfe_platform_resume NULL -+#endif -+ -+static const struct dev_pm_ops pfe_platform_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(pfe_platform_suspend, pfe_platform_resume) -+}; -+#endif -+ -+static const struct of_device_id pfe_match[] = { -+ { -+ .compatible = "fsl,pfe", -+ }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, pfe_match); -+ -+static struct platform_driver pfe_platform_driver = { -+ .probe = pfe_platform_probe, -+ .remove = pfe_platform_remove, -+ .driver = { -+ .name = "pfe", -+ .of_match_table = pfe_match, -+#ifdef CONFIG_PM -+ .pm = &pfe_platform_pm_ops, -+#endif -+ }, -+}; -+ -+module_platform_driver(pfe_platform_driver); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("PFE Ethernet driver"); -+MODULE_AUTHOR("NXP DNCPE"); ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_mod.c -@@ -0,0 +1,158 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#include -+#include "pfe_mod.h" -+#include "pfe_cdev.h" -+ -+unsigned int us; -+module_param(us, uint, 0444); -+MODULE_PARM_DESC(us, "0: module enabled for kernel networking (DEFAULT)\n" -+ "1: module enabled for userspace networking\n"); -+struct pfe *pfe; -+ -+/* -+ * pfe_probe - -+ */ -+int pfe_probe(struct pfe *pfe) -+{ -+ int rc; -+ -+ if (pfe->ddr_size < DDR_MAX_SIZE) { -+ pr_err("%s: required DDR memory (%x) above platform ddr memory (%x)\n", -+ __func__, (unsigned int)DDR_MAX_SIZE, pfe->ddr_size); -+ rc = -ENOMEM; -+ goto err_hw; -+ } -+ -+ if (((int)(pfe->ddr_phys_baseaddr + BMU2_DDR_BASEADDR) & -+ (8 * SZ_1M - 1)) != 0) { -+ pr_err("%s: BMU2 base address (0x%x) must be aligned on 8MB boundary\n", -+ __func__, (int)pfe->ddr_phys_baseaddr + -+ BMU2_DDR_BASEADDR); -+ rc = -ENOMEM; -+ goto err_hw; -+ } -+ -+ pr_info("cbus_baseaddr: %lx, ddr_baseaddr: %lx, ddr_phys_baseaddr: %lx, ddr_size: %x\n", -+ (unsigned long)pfe->cbus_baseaddr, -+ (unsigned long)pfe->ddr_baseaddr, -+ pfe->ddr_phys_baseaddr, pfe->ddr_size); -+ -+ pfe_lib_init(pfe->cbus_baseaddr, pfe->ddr_baseaddr, -+ pfe->ddr_phys_baseaddr, pfe->ddr_size); -+ -+ rc = pfe_hw_init(pfe, 0); -+ if (rc < 0) -+ goto err_hw; -+ -+ if (us) -+ goto firmware_init; -+ -+ rc = pfe_hif_lib_init(pfe); -+ if (rc < 0) -+ goto err_hif_lib; -+ -+ rc = pfe_hif_init(pfe); -+ if (rc < 0) -+ goto err_hif; -+ -+firmware_init: -+ rc = pfe_firmware_init(pfe); -+ if (rc < 0) -+ goto err_firmware; -+ -+ rc = pfe_ctrl_init(pfe); -+ if (rc < 0) -+ goto err_ctrl; -+ -+ rc = pfe_eth_init(pfe); -+ if (rc < 0) -+ goto err_eth; -+ -+ rc = pfe_sysfs_init(pfe); -+ if (rc < 0) -+ goto err_sysfs; -+ -+ rc = pfe_debugfs_init(pfe); -+ if (rc < 0) -+ goto err_debugfs; -+ -+ if (us) { -+ /* Creating a character device */ -+ rc = pfe_cdev_init(); -+ if (rc < 0) -+ goto err_cdev; -+ } -+ -+ return 0; -+ -+err_cdev: -+ pfe_debugfs_exit(pfe); -+ -+err_debugfs: -+ pfe_sysfs_exit(pfe); -+ -+err_sysfs: -+ pfe_eth_exit(pfe); -+ -+err_eth: -+ pfe_ctrl_exit(pfe); -+ -+err_ctrl: -+ pfe_firmware_exit(pfe); -+ -+err_firmware: -+ if (us) -+ goto err_hif_lib; -+ -+ pfe_hif_exit(pfe); -+ -+err_hif: -+ pfe_hif_lib_exit(pfe); -+ -+err_hif_lib: -+ pfe_hw_exit(pfe); -+ -+err_hw: -+ return rc; -+} -+ -+/* -+ * pfe_remove - -+ */ -+int pfe_remove(struct pfe *pfe) -+{ -+ pr_info("%s\n", __func__); -+ -+ if (us) -+ pfe_cdev_exit(); -+ -+ pfe_debugfs_exit(pfe); -+ -+ pfe_sysfs_exit(pfe); -+ -+ pfe_eth_exit(pfe); -+ -+ pfe_ctrl_exit(pfe); -+ -+#if defined(LS1012A_PFE_RESET_WA) -+ pfe_hif_rx_idle(&pfe->hif); -+#endif -+ pfe_firmware_exit(pfe); -+ -+ if (us) -+ goto hw_exit; -+ -+ pfe_hif_exit(pfe); -+ -+ pfe_hif_lib_exit(pfe); -+ -+hw_exit: -+ pfe_hw_exit(pfe); -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_mod.h -@@ -0,0 +1,103 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#ifndef _PFE_MOD_H_ -+#define _PFE_MOD_H_ -+ -+#include -+#include -+ -+extern unsigned int us; -+ -+struct pfe; -+ -+#include "pfe_hw.h" -+#include "pfe_firmware.h" -+#include "pfe_ctrl.h" -+#include "pfe_hif.h" -+#include "pfe_hif_lib.h" -+#include "pfe_eth.h" -+#include "pfe_sysfs.h" -+#include "pfe_perfmon.h" -+#include "pfe_debugfs.h" -+ -+#define PHYID_MAX_VAL 32 -+ -+struct pfe_tmu_credit { -+ /* Number of allowed TX packet in-flight, matches TMU queue size */ -+ unsigned int tx_credit[NUM_GEMAC_SUPPORT][EMAC_TXQ_CNT]; -+ unsigned int tx_credit_max[NUM_GEMAC_SUPPORT][EMAC_TXQ_CNT]; -+ unsigned int tx_packets[NUM_GEMAC_SUPPORT][EMAC_TXQ_CNT]; -+}; -+ -+struct pfe { -+ struct regmap *scfg; -+ unsigned long ddr_phys_baseaddr; -+ void *ddr_baseaddr; -+ unsigned int ddr_size; -+ void *cbus_baseaddr; -+ void *apb_baseaddr; -+ unsigned long iram_phys_baseaddr; -+ void *iram_baseaddr; -+ unsigned long ipsec_phys_baseaddr; -+ void *ipsec_baseaddr; -+ int hif_irq; -+ int wol_irq; -+ int hif_client_irq; -+ struct device *dev; -+ struct dentry *dentry; -+ struct pfe_ctrl ctrl; -+ struct pfe_hif hif; -+ struct pfe_eth eth; -+ struct pfe_mdio mdio; -+ struct hif_client_s *hif_client[HIF_CLIENTS_MAX]; -+#if defined(CFG_DIAGS) -+ struct pfe_diags diags; -+#endif -+ struct pfe_tmu_credit tmu_credit; -+ struct pfe_cpumon cpumon; -+ struct pfe_memmon memmon; -+ int wake; -+ int mdio_muxval[PHYID_MAX_VAL]; -+ struct clk *hfe_clock; -+}; -+ -+extern struct pfe *pfe; -+ -+int pfe_probe(struct pfe *pfe); -+int pfe_remove(struct pfe *pfe); -+ -+/* DDR Mapping in reserved memory*/ -+#define ROUTE_TABLE_BASEADDR 0 -+#define ROUTE_TABLE_HASH_BITS 15 /* 32K entries */ -+#define ROUTE_TABLE_SIZE ((1 << ROUTE_TABLE_HASH_BITS) \ -+ * CLASS_ROUTE_SIZE) -+#define BMU2_DDR_BASEADDR (ROUTE_TABLE_BASEADDR + ROUTE_TABLE_SIZE) -+#define BMU2_BUF_COUNT (4096 - 256) -+/* This is to get a total DDR size of 12MiB */ -+#define BMU2_DDR_SIZE (DDR_BUF_SIZE * BMU2_BUF_COUNT) -+#define UTIL_CODE_BASEADDR (BMU2_DDR_BASEADDR + BMU2_DDR_SIZE) -+#define UTIL_CODE_SIZE (128 * SZ_1K) -+#define UTIL_DDR_DATA_BASEADDR (UTIL_CODE_BASEADDR + UTIL_CODE_SIZE) -+#define UTIL_DDR_DATA_SIZE (64 * SZ_1K) -+#define CLASS_DDR_DATA_BASEADDR (UTIL_DDR_DATA_BASEADDR + UTIL_DDR_DATA_SIZE) -+#define CLASS_DDR_DATA_SIZE (32 * SZ_1K) -+#define TMU_DDR_DATA_BASEADDR (CLASS_DDR_DATA_BASEADDR + CLASS_DDR_DATA_SIZE) -+#define TMU_DDR_DATA_SIZE (32 * SZ_1K) -+#define TMU_LLM_BASEADDR (TMU_DDR_DATA_BASEADDR + TMU_DDR_DATA_SIZE) -+#define TMU_LLM_QUEUE_LEN (8 * 512) -+/* Must be power of two and at least 16 * 8 = 128 bytes */ -+#define TMU_LLM_SIZE (4 * 16 * TMU_LLM_QUEUE_LEN) -+/* (4 TMU's x 16 queues x queue_len) */ -+ -+#define DDR_MAX_SIZE (TMU_LLM_BASEADDR + TMU_LLM_SIZE) -+ -+/* LMEM Mapping */ -+#define BMU1_LMEM_BASEADDR 0 -+#define BMU1_BUF_COUNT 256 -+#define BMU1_LMEM_SIZE (LMEM_BUF_SIZE * BMU1_BUF_COUNT) -+ -+#endif /* _PFE_MOD_H */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_perfmon.h -@@ -0,0 +1,26 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#ifndef _PFE_PERFMON_H_ -+#define _PFE_PERFMON_H_ -+ -+#include "pfe/pfe.h" -+ -+#define CT_CPUMON_INTERVAL (1 * TIMER_TICKS_PER_SEC) -+ -+struct pfe_cpumon { -+ u32 cpu_usage_pct[MAX_PE]; -+ u32 class_usage_pct; -+}; -+ -+struct pfe_memmon { -+ u32 kernel_memory_allocated; -+}; -+ -+int pfe_perfmon_init(struct pfe *pfe); -+void pfe_perfmon_exit(struct pfe *pfe); -+ -+#endif /* _PFE_PERFMON_H_ */ ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_sysfs.c -@@ -0,0 +1,840 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#include -+#include -+ -+#include "pfe_mod.h" -+ -+#define PE_EXCEPTION_DUMP_ADDRESS 0x1fa8 -+#define NUM_QUEUES 16 -+ -+static char register_name[20][5] = { -+ "EPC", "ECAS", "EID", "ED", -+ "r0", "r1", "r2", "r3", -+ "r4", "r5", "r6", "r7", -+ "r8", "r9", "r10", "r11", -+ "r12", "r13", "r14", "r15", -+}; -+ -+static char exception_name[14][20] = { -+ "Reset", -+ "HardwareFailure", -+ "NMI", -+ "InstBreakpoint", -+ "DataBreakpoint", -+ "Unsupported", -+ "PrivilegeViolation", -+ "InstBusError", -+ "DataBusError", -+ "AlignmentError", -+ "ArithmeticError", -+ "SystemCall", -+ "MemoryManagement", -+ "Interrupt", -+}; -+ -+static unsigned long class_do_clear; -+static unsigned long tmu_do_clear; -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+static unsigned long util_do_clear; -+#endif -+ -+static ssize_t display_pe_status(char *buf, int id, u32 dmem_addr, unsigned long -+ do_clear) -+{ -+ ssize_t len = 0; -+ u32 val; -+ char statebuf[5]; -+ struct pfe_cpumon *cpumon = &pfe->cpumon; -+ u32 debug_indicator; -+ u32 debug[20]; -+ -+ if (id < CLASS0_ID || id >= MAX_PE) -+ return len; -+ -+ *(u32 *)statebuf = pe_dmem_read(id, dmem_addr, 4); -+ dmem_addr += 4; -+ -+ statebuf[4] = '\0'; -+ len += sprintf(buf + len, "state=%4s ", statebuf); -+ -+ val = pe_dmem_read(id, dmem_addr, 4); -+ dmem_addr += 4; -+ len += sprintf(buf + len, "ctr=%08x ", cpu_to_be32(val)); -+ -+ val = pe_dmem_read(id, dmem_addr, 4); -+ if (do_clear && val) -+ pe_dmem_write(id, 0, dmem_addr, 4); -+ dmem_addr += 4; -+ len += sprintf(buf + len, "rx=%u ", cpu_to_be32(val)); -+ -+ val = pe_dmem_read(id, dmem_addr, 4); -+ if (do_clear && val) -+ pe_dmem_write(id, 0, dmem_addr, 4); -+ dmem_addr += 4; -+ if (id >= TMU0_ID && id <= TMU_MAX_ID) -+ len += sprintf(buf + len, "qstatus=%x", cpu_to_be32(val)); -+ else -+ len += sprintf(buf + len, "tx=%u", cpu_to_be32(val)); -+ -+ val = pe_dmem_read(id, dmem_addr, 4); -+ if (do_clear && val) -+ pe_dmem_write(id, 0, dmem_addr, 4); -+ dmem_addr += 4; -+ if (val) -+ len += sprintf(buf + len, " drop=%u", cpu_to_be32(val)); -+ -+ len += sprintf(buf + len, " load=%d%%", cpumon->cpu_usage_pct[id]); -+ -+ len += sprintf(buf + len, "\n"); -+ -+ debug_indicator = pe_dmem_read(id, dmem_addr, 4); -+ dmem_addr += 4; -+ if (!strncmp((char *)&debug_indicator, "DBUG", 4)) { -+ int j, last = 0; -+ -+ for (j = 0; j < 16; j++) { -+ debug[j] = pe_dmem_read(id, dmem_addr, 4); -+ if (debug[j]) { -+ if (do_clear) -+ pe_dmem_write(id, 0, dmem_addr, 4); -+ last = j + 1; -+ } -+ dmem_addr += 4; -+ } -+ for (j = 0; j < last; j++) { -+ len += sprintf(buf + len, "%08x%s", -+ cpu_to_be32(debug[j]), -+ (j & 0x7) == 0x7 || j == last - 1 ? "\n" : " "); -+ } -+ } -+ -+ if (!strncmp(statebuf, "DEAD", 4)) { -+ u32 i, dump = PE_EXCEPTION_DUMP_ADDRESS; -+ -+ len += sprintf(buf + len, "Exception details:\n"); -+ for (i = 0; i < 20; i++) { -+ debug[i] = pe_dmem_read(id, dump, 4); -+ dump += 4; -+ if (i == 2) -+ len += sprintf(buf + len, "%4s = %08x (=%s) ", -+ register_name[i], cpu_to_be32(debug[i]), -+ exception_name[min((u32) -+ cpu_to_be32(debug[i]), (u32)13)]); -+ else -+ len += sprintf(buf + len, "%4s = %08x%s", -+ register_name[i], cpu_to_be32(debug[i]), -+ (i & 0x3) == 0x3 || i == 19 ? "\n" : " "); -+ } -+ } -+ -+ return len; -+} -+ -+static ssize_t class_phy_stats(char *buf, int phy) -+{ -+ ssize_t len = 0; -+ int off1 = phy * 0x28; -+ int off2 = phy * 0x10; -+ -+ if (phy == 3) -+ off1 = CLASS_PHY4_RX_PKTS - CLASS_PHY1_RX_PKTS; -+ -+ len += sprintf(buf + len, "phy: %d\n", phy); -+ len += sprintf(buf + len, -+ " rx: %10u, tx: %10u, intf: %10u, ipv4: %10u, ipv6: %10u\n", -+ readl(CLASS_PHY1_RX_PKTS + off1), -+ readl(CLASS_PHY1_TX_PKTS + off1), -+ readl(CLASS_PHY1_INTF_MATCH_PKTS + off1), -+ readl(CLASS_PHY1_V4_PKTS + off1), -+ readl(CLASS_PHY1_V6_PKTS + off1)); -+ -+ len += sprintf(buf + len, -+ " icmp: %10u, igmp: %10u, tcp: %10u, udp: %10u\n", -+ readl(CLASS_PHY1_ICMP_PKTS + off2), -+ readl(CLASS_PHY1_IGMP_PKTS + off2), -+ readl(CLASS_PHY1_TCP_PKTS + off2), -+ readl(CLASS_PHY1_UDP_PKTS + off2)); -+ -+ len += sprintf(buf + len, " err\n"); -+ len += sprintf(buf + len, -+ " lp: %10u, intf: %10u, l3: %10u, chcksum: %10u, ttl: %10u\n", -+ readl(CLASS_PHY1_LP_FAIL_PKTS + off1), -+ readl(CLASS_PHY1_INTF_FAIL_PKTS + off1), -+ readl(CLASS_PHY1_L3_FAIL_PKTS + off1), -+ readl(CLASS_PHY1_CHKSUM_ERR_PKTS + off1), -+ readl(CLASS_PHY1_TTL_ERR_PKTS + off1)); -+ -+ return len; -+} -+ -+/* qm_read_drop_stat -+ * This function is used to read the drop statistics from the TMU -+ * hw drop counter. Since the hw counter is always cleared afer -+ * reading, this function maintains the previous drop count, and -+ * adds the new value to it. That value can be retrieved by -+ * passing a pointer to it with the total_drops arg. -+ * -+ * @param tmu TMU number (0 - 3) -+ * @param queue queue number (0 - 15) -+ * @param total_drops pointer to location to store total drops (or NULL) -+ * @param do_reset if TRUE, clear total drops after updating -+ */ -+u32 qm_read_drop_stat(u32 tmu, u32 queue, u32 *total_drops, int do_reset) -+{ -+ static u32 qtotal[TMU_MAX_ID + 1][NUM_QUEUES]; -+ u32 val; -+ -+ writel((tmu << 8) | queue, TMU_TEQ_CTRL); -+ writel((tmu << 8) | queue, TMU_LLM_CTRL); -+ val = readl(TMU_TEQ_DROP_STAT); -+ qtotal[tmu][queue] += val; -+ if (total_drops) -+ *total_drops = qtotal[tmu][queue]; -+ if (do_reset) -+ qtotal[tmu][queue] = 0; -+ return val; -+} -+ -+static ssize_t tmu_queue_stats(char *buf, int tmu, int queue) -+{ -+ ssize_t len = 0; -+ u32 drops; -+ -+ len += sprintf(buf + len, "%d-%02d, ", tmu, queue); -+ -+ drops = qm_read_drop_stat(tmu, queue, NULL, 0); -+ -+ /* Select queue */ -+ writel((tmu << 8) | queue, TMU_TEQ_CTRL); -+ writel((tmu << 8) | queue, TMU_LLM_CTRL); -+ -+ len += sprintf(buf + len, -+ "(teq) drop: %10u, tx: %10u (llm) head: %08x, tail: %08x, drop: %10u\n", -+ drops, readl(TMU_TEQ_TRANS_STAT), -+ readl(TMU_LLM_QUE_HEADPTR), readl(TMU_LLM_QUE_TAILPTR), -+ readl(TMU_LLM_QUE_DROPCNT)); -+ -+ return len; -+} -+ -+static ssize_t tmu_queues(char *buf, int tmu) -+{ -+ ssize_t len = 0; -+ int queue; -+ -+ for (queue = 0; queue < 16; queue++) -+ len += tmu_queue_stats(buf + len, tmu, queue); -+ -+ return len; -+} -+ -+static ssize_t block_version(char *buf, void *addr) -+{ -+ ssize_t len = 0; -+ u32 val; -+ -+ val = readl(addr); -+ len += sprintf(buf + len, "revision: %x, version: %x, id: %x\n", -+ (val >> 24) & 0xff, (val >> 16) & 0xff, val & 0xffff); -+ -+ return len; -+} -+ -+static ssize_t bmu(char *buf, int id, void *base) -+{ -+ ssize_t len = 0; -+ -+ len += sprintf(buf + len, "%s: %d\n ", __func__, id); -+ -+ len += block_version(buf + len, base + BMU_VERSION); -+ -+ len += sprintf(buf + len, " buf size: %x\n", (1 << readl(base + -+ BMU_BUF_SIZE))); -+ len += sprintf(buf + len, " buf count: %x\n", readl(base + -+ BMU_BUF_CNT)); -+ len += sprintf(buf + len, " buf rem: %x\n", readl(base + -+ BMU_REM_BUF_CNT)); -+ len += sprintf(buf + len, " buf curr: %x\n", readl(base + -+ BMU_CURR_BUF_CNT)); -+ len += sprintf(buf + len, " free err: %x\n", readl(base + -+ BMU_FREE_ERR_ADDR)); -+ -+ return len; -+} -+ -+static ssize_t gpi(char *buf, int id, void *base) -+{ -+ ssize_t len = 0; -+ u32 val; -+ -+ len += sprintf(buf + len, "%s%d:\n ", __func__, id); -+ len += block_version(buf + len, base + GPI_VERSION); -+ -+ len += sprintf(buf + len, " tx under stick: %x\n", readl(base + -+ GPI_FIFO_STATUS)); -+ val = readl(base + GPI_FIFO_DEBUG); -+ len += sprintf(buf + len, " tx pkts: %x\n", (val >> 23) & -+ 0x3f); -+ len += sprintf(buf + len, " rx pkts: %x\n", (val >> 18) & -+ 0x3f); -+ len += sprintf(buf + len, " tx bytes: %x\n", (val >> 9) & -+ 0x1ff); -+ len += sprintf(buf + len, " rx bytes: %x\n", (val >> 0) & -+ 0x1ff); -+ len += sprintf(buf + len, " overrun: %x\n", readl(base + -+ GPI_OVERRUN_DROPCNT)); -+ -+ return len; -+} -+ -+static ssize_t pfe_set_class(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ class_do_clear = kstrtoul(buf, 0, 0); -+ return count; -+} -+ -+static ssize_t pfe_show_class(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ ssize_t len = 0; -+ int id; -+ u32 val; -+ struct pfe_cpumon *cpumon = &pfe->cpumon; -+ -+ len += block_version(buf + len, CLASS_VERSION); -+ -+ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { -+ len += sprintf(buf + len, "%d: ", id - CLASS0_ID); -+ -+ val = readl(CLASS_PE0_DEBUG + id * 4); -+ len += sprintf(buf + len, "pc=1%04x ", val & 0xffff); -+ -+ len += display_pe_status(buf + len, id, CLASS_DM_PESTATUS, -+ class_do_clear); -+ } -+ len += sprintf(buf + len, "aggregate load=%d%%\n\n", -+ cpumon->class_usage_pct); -+ -+ len += sprintf(buf + len, "pe status: 0x%x\n", -+ readl(CLASS_PE_STATUS)); -+ len += sprintf(buf + len, "max buf cnt: 0x%x afull thres: 0x%x\n", -+ readl(CLASS_MAX_BUF_CNT), readl(CLASS_AFULL_THRES)); -+ len += sprintf(buf + len, "tsq max cnt: 0x%x tsq fifo thres: 0x%x\n", -+ readl(CLASS_TSQ_MAX_CNT), readl(CLASS_TSQ_FIFO_THRES)); -+ len += sprintf(buf + len, "state: 0x%x\n", readl(CLASS_STATE)); -+ -+ len += class_phy_stats(buf + len, 0); -+ len += class_phy_stats(buf + len, 1); -+ len += class_phy_stats(buf + len, 2); -+ len += class_phy_stats(buf + len, 3); -+ -+ return len; -+} -+ -+static ssize_t pfe_set_tmu(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ tmu_do_clear = kstrtoul(buf, 0, 0); -+ return count; -+} -+ -+static ssize_t pfe_show_tmu(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ ssize_t len = 0; -+ int id; -+ u32 val; -+ -+ len += block_version(buf + len, TMU_VERSION); -+ -+ for (id = TMU0_ID; id <= TMU_MAX_ID; id++) { -+ if (id == TMU2_ID) -+ continue; -+ len += sprintf(buf + len, "%d: ", id - TMU0_ID); -+ -+ len += display_pe_status(buf + len, id, TMU_DM_PESTATUS, -+ tmu_do_clear); -+ } -+ -+ len += sprintf(buf + len, "pe status: %x\n", readl(TMU_PE_STATUS)); -+ len += sprintf(buf + len, "inq fifo cnt: %x\n", -+ readl(TMU_PHY_INQ_FIFO_CNT)); -+ val = readl(TMU_INQ_STAT); -+ len += sprintf(buf + len, "inq wr ptr: %x\n", val & 0x3ff); -+ len += sprintf(buf + len, "inq rd ptr: %x\n", val >> 10); -+ -+ return len; -+} -+ -+static unsigned long drops_do_clear; -+static u32 class_drop_counter[CLASS_NUM_DROP_COUNTERS]; -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+static u32 util_drop_counter[UTIL_NUM_DROP_COUNTERS]; -+#endif -+ -+char *class_drop_description[CLASS_NUM_DROP_COUNTERS] = { -+ "ICC", -+ "Host Pkt Error", -+ "Rx Error", -+ "IPsec Outbound", -+ "IPsec Inbound", -+ "EXPT IPsec Error", -+ "Reassembly", -+ "Fragmenter", -+ "NAT-T", -+ "Socket", -+ "Multicast", -+ "NAT-PT", -+ "Tx Disabled", -+}; -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+char *util_drop_description[UTIL_NUM_DROP_COUNTERS] = { -+ "IPsec Outbound", -+ "IPsec Inbound", -+ "IPsec Rate Limiter", -+ "Fragmenter", -+ "Socket", -+ "Tx Disabled", -+ "Rx Error", -+}; -+#endif -+ -+static ssize_t pfe_set_drops(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ drops_do_clear = kstrtoul(buf, 0, 0); -+ return count; -+} -+ -+static u32 tmu_drops[4][16]; -+static ssize_t pfe_show_drops(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ ssize_t len = 0; -+ int id, dropnum; -+ int tmu, queue; -+ u32 val; -+ u32 dmem_addr; -+ int num_class_drops = 0, num_tmu_drops = 0, num_util_drops = 0; -+ struct pfe_ctrl *ctrl = &pfe->ctrl; -+ -+ memset(class_drop_counter, 0, sizeof(class_drop_counter)); -+ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { -+ if (drops_do_clear) -+ pe_sync_stop(ctrl, (1 << id)); -+ for (dropnum = 0; dropnum < CLASS_NUM_DROP_COUNTERS; -+ dropnum++) { -+ dmem_addr = CLASS_DM_DROP_CNTR; -+ val = be32_to_cpu(pe_dmem_read(id, dmem_addr, 4)); -+ class_drop_counter[dropnum] += val; -+ num_class_drops += val; -+ if (drops_do_clear) -+ pe_dmem_write(id, 0, dmem_addr, 4); -+ } -+ if (drops_do_clear) -+ pe_start(ctrl, (1 << id)); -+ } -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ if (drops_do_clear) -+ pe_sync_stop(ctrl, (1 << UTIL_ID)); -+ for (dropnum = 0; dropnum < UTIL_NUM_DROP_COUNTERS; dropnum++) { -+ dmem_addr = UTIL_DM_DROP_CNTR; -+ val = be32_to_cpu(pe_dmem_read(UTIL_ID, dmem_addr, 4)); -+ util_drop_counter[dropnum] = val; -+ num_util_drops += val; -+ if (drops_do_clear) -+ pe_dmem_write(UTIL_ID, 0, dmem_addr, 4); -+ } -+ if (drops_do_clear) -+ pe_start(ctrl, (1 << UTIL_ID)); -+#endif -+ for (tmu = 0; tmu < 4; tmu++) { -+ for (queue = 0; queue < 16; queue++) { -+ qm_read_drop_stat(tmu, queue, &tmu_drops[tmu][queue], -+ drops_do_clear); -+ num_tmu_drops += tmu_drops[tmu][queue]; -+ } -+ } -+ -+ if (num_class_drops == 0 && num_util_drops == 0 && num_tmu_drops == 0) -+ len += sprintf(buf + len, "No PE drops\n\n"); -+ -+ if (num_class_drops > 0) { -+ len += sprintf(buf + len, "Class PE drops --\n"); -+ for (dropnum = 0; dropnum < CLASS_NUM_DROP_COUNTERS; -+ dropnum++) { -+ if (class_drop_counter[dropnum] > 0) -+ len += sprintf(buf + len, " %s: %d\n", -+ class_drop_description[dropnum], -+ class_drop_counter[dropnum]); -+ } -+ len += sprintf(buf + len, "\n"); -+ } -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ if (num_util_drops > 0) { -+ len += sprintf(buf + len, "Util PE drops --\n"); -+ for (dropnum = 0; dropnum < UTIL_NUM_DROP_COUNTERS; dropnum++) { -+ if (util_drop_counter[dropnum] > 0) -+ len += sprintf(buf + len, " %s: %d\n", -+ util_drop_description[dropnum], -+ util_drop_counter[dropnum]); -+ } -+ len += sprintf(buf + len, "\n"); -+ } -+#endif -+ if (num_tmu_drops > 0) { -+ len += sprintf(buf + len, "TMU drops --\n"); -+ for (tmu = 0; tmu < 4; tmu++) { -+ for (queue = 0; queue < 16; queue++) { -+ if (tmu_drops[tmu][queue] > 0) -+ len += sprintf(buf + len, -+ " TMU%d-Q%d: %d\n" -+ , tmu, queue, tmu_drops[tmu][queue]); -+ } -+ } -+ len += sprintf(buf + len, "\n"); -+ } -+ -+ return len; -+} -+ -+static ssize_t pfe_show_tmu0_queues(struct device *dev, struct device_attribute -+ *attr, char *buf) -+{ -+ return tmu_queues(buf, 0); -+} -+ -+static ssize_t pfe_show_tmu1_queues(struct device *dev, struct device_attribute -+ *attr, char *buf) -+{ -+ return tmu_queues(buf, 1); -+} -+ -+static ssize_t pfe_show_tmu2_queues(struct device *dev, struct device_attribute -+ *attr, char *buf) -+{ -+ return tmu_queues(buf, 2); -+} -+ -+static ssize_t pfe_show_tmu3_queues(struct device *dev, struct device_attribute -+ *attr, char *buf) -+{ -+ return tmu_queues(buf, 3); -+} -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+static ssize_t pfe_set_util(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ util_do_clear = kstrtoul(buf, NULL, 0); -+ return count; -+} -+ -+static ssize_t pfe_show_util(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ ssize_t len = 0; -+ struct pfe_ctrl *ctrl = &pfe->ctrl; -+ -+ len += block_version(buf + len, UTIL_VERSION); -+ -+ pe_sync_stop(ctrl, (1 << UTIL_ID)); -+ len += display_pe_status(buf + len, UTIL_ID, UTIL_DM_PESTATUS, -+ util_do_clear); -+ pe_start(ctrl, (1 << UTIL_ID)); -+ -+ len += sprintf(buf + len, "pe status: %x\n", readl(UTIL_PE_STATUS)); -+ len += sprintf(buf + len, "max buf cnt: %x\n", -+ readl(UTIL_MAX_BUF_CNT)); -+ len += sprintf(buf + len, "tsq max cnt: %x\n", -+ readl(UTIL_TSQ_MAX_CNT)); -+ -+ return len; -+} -+#endif -+ -+static ssize_t pfe_show_bmu(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ ssize_t len = 0; -+ -+ len += bmu(buf + len, 1, BMU1_BASE_ADDR); -+ len += bmu(buf + len, 2, BMU2_BASE_ADDR); -+ -+ return len; -+} -+ -+static ssize_t pfe_show_hif(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ ssize_t len = 0; -+ -+ len += sprintf(buf + len, "hif:\n "); -+ len += block_version(buf + len, HIF_VERSION); -+ -+ len += sprintf(buf + len, " tx curr bd: %x\n", -+ readl(HIF_TX_CURR_BD_ADDR)); -+ len += sprintf(buf + len, " tx status: %x\n", -+ readl(HIF_TX_STATUS)); -+ len += sprintf(buf + len, " tx dma status: %x\n", -+ readl(HIF_TX_DMA_STATUS)); -+ -+ len += sprintf(buf + len, " rx curr bd: %x\n", -+ readl(HIF_RX_CURR_BD_ADDR)); -+ len += sprintf(buf + len, " rx status: %x\n", -+ readl(HIF_RX_STATUS)); -+ len += sprintf(buf + len, " rx dma status: %x\n", -+ readl(HIF_RX_DMA_STATUS)); -+ -+ len += sprintf(buf + len, "hif nocopy:\n "); -+ len += block_version(buf + len, HIF_NOCPY_VERSION); -+ -+ len += sprintf(buf + len, " tx curr bd: %x\n", -+ readl(HIF_NOCPY_TX_CURR_BD_ADDR)); -+ len += sprintf(buf + len, " tx status: %x\n", -+ readl(HIF_NOCPY_TX_STATUS)); -+ len += sprintf(buf + len, " tx dma status: %x\n", -+ readl(HIF_NOCPY_TX_DMA_STATUS)); -+ -+ len += sprintf(buf + len, " rx curr bd: %x\n", -+ readl(HIF_NOCPY_RX_CURR_BD_ADDR)); -+ len += sprintf(buf + len, " rx status: %x\n", -+ readl(HIF_NOCPY_RX_STATUS)); -+ len += sprintf(buf + len, " rx dma status: %x\n", -+ readl(HIF_NOCPY_RX_DMA_STATUS)); -+ -+ return len; -+} -+ -+static ssize_t pfe_show_gpi(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ ssize_t len = 0; -+ -+ len += gpi(buf + len, 0, EGPI1_BASE_ADDR); -+ len += gpi(buf + len, 1, EGPI2_BASE_ADDR); -+ len += gpi(buf + len, 3, HGPI_BASE_ADDR); -+ -+ return len; -+} -+ -+static ssize_t pfe_show_pfemem(struct device *dev, struct device_attribute -+ *attr, char *buf) -+{ -+ ssize_t len = 0; -+ struct pfe_memmon *memmon = &pfe->memmon; -+ -+ len += sprintf(buf + len, "Kernel Memory: %d Bytes (%d KB)\n", -+ memmon->kernel_memory_allocated, -+ (memmon->kernel_memory_allocated + 1023) / 1024); -+ -+ return len; -+} -+ -+static ssize_t pfe_show_crc_revalidated(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ u64 crc_validated = 0; -+ ssize_t len = 0; -+ int id, phyid; -+ -+ len += sprintf(buf + len, "FCS re-validated by PFE:\n"); -+ -+ for (phyid = 0; phyid < 2; phyid++) { -+ crc_validated = 0; -+ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++) { -+ crc_validated += be32_to_cpu(pe_dmem_read(id, -+ CLASS_DM_CRC_VALIDATED + (phyid * 4), 4)); -+ } -+ len += sprintf(buf + len, "MAC %d:\n count:%10llu\n", -+ phyid, crc_validated); -+ } -+ -+ return len; -+} -+ -+#ifdef HIF_NAPI_STATS -+static ssize_t pfe_show_hif_napi_stats(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct pfe *pfe = platform_get_drvdata(pdev); -+ ssize_t len = 0; -+ -+ len += sprintf(buf + len, "sched: %u\n", -+ pfe->hif.napi_counters[NAPI_SCHED_COUNT]); -+ len += sprintf(buf + len, "poll: %u\n", -+ pfe->hif.napi_counters[NAPI_POLL_COUNT]); -+ len += sprintf(buf + len, "packet: %u\n", -+ pfe->hif.napi_counters[NAPI_PACKET_COUNT]); -+ len += sprintf(buf + len, "budget: %u\n", -+ pfe->hif.napi_counters[NAPI_FULL_BUDGET_COUNT]); -+ len += sprintf(buf + len, "desc: %u\n", -+ pfe->hif.napi_counters[NAPI_DESC_COUNT]); -+ len += sprintf(buf + len, "full: %u\n", -+ pfe->hif.napi_counters[NAPI_CLIENT_FULL_COUNT]); -+ -+ return len; -+} -+ -+static ssize_t pfe_set_hif_napi_stats(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct pfe *pfe = platform_get_drvdata(pdev); -+ -+ memset(pfe->hif.napi_counters, 0, sizeof(pfe->hif.napi_counters)); -+ -+ return count; -+} -+ -+static DEVICE_ATTR(hif_napi_stats, 0644, pfe_show_hif_napi_stats, -+ pfe_set_hif_napi_stats); -+#endif -+ -+static DEVICE_ATTR(class, 0644, pfe_show_class, pfe_set_class); -+static DEVICE_ATTR(tmu, 0644, pfe_show_tmu, pfe_set_tmu); -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+static DEVICE_ATTR(util, 0644, pfe_show_util, pfe_set_util); -+#endif -+static DEVICE_ATTR(bmu, 0444, pfe_show_bmu, NULL); -+static DEVICE_ATTR(hif, 0444, pfe_show_hif, NULL); -+static DEVICE_ATTR(gpi, 0444, pfe_show_gpi, NULL); -+static DEVICE_ATTR(drops, 0644, pfe_show_drops, pfe_set_drops); -+static DEVICE_ATTR(tmu0_queues, 0444, pfe_show_tmu0_queues, NULL); -+static DEVICE_ATTR(tmu1_queues, 0444, pfe_show_tmu1_queues, NULL); -+static DEVICE_ATTR(tmu2_queues, 0444, pfe_show_tmu2_queues, NULL); -+static DEVICE_ATTR(tmu3_queues, 0444, pfe_show_tmu3_queues, NULL); -+static DEVICE_ATTR(pfemem, 0444, pfe_show_pfemem, NULL); -+static DEVICE_ATTR(fcs_revalidated, 0444, pfe_show_crc_revalidated, NULL); -+ -+int pfe_sysfs_init(struct pfe *pfe) -+{ -+ if (device_create_file(pfe->dev, &dev_attr_class)) -+ goto err_class; -+ -+ if (device_create_file(pfe->dev, &dev_attr_tmu)) -+ goto err_tmu; -+ -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ if (device_create_file(pfe->dev, &dev_attr_util)) -+ goto err_util; -+#endif -+ -+ if (device_create_file(pfe->dev, &dev_attr_bmu)) -+ goto err_bmu; -+ -+ if (device_create_file(pfe->dev, &dev_attr_hif)) -+ goto err_hif; -+ -+ if (device_create_file(pfe->dev, &dev_attr_gpi)) -+ goto err_gpi; -+ -+ if (device_create_file(pfe->dev, &dev_attr_drops)) -+ goto err_drops; -+ -+ if (device_create_file(pfe->dev, &dev_attr_tmu0_queues)) -+ goto err_tmu0_queues; -+ -+ if (device_create_file(pfe->dev, &dev_attr_tmu1_queues)) -+ goto err_tmu1_queues; -+ -+ if (device_create_file(pfe->dev, &dev_attr_tmu2_queues)) -+ goto err_tmu2_queues; -+ -+ if (device_create_file(pfe->dev, &dev_attr_tmu3_queues)) -+ goto err_tmu3_queues; -+ -+ if (device_create_file(pfe->dev, &dev_attr_pfemem)) -+ goto err_pfemem; -+ -+ if (device_create_file(pfe->dev, &dev_attr_fcs_revalidated)) -+ goto err_crc_revalidated; -+ -+#ifdef HIF_NAPI_STATS -+ if (device_create_file(pfe->dev, &dev_attr_hif_napi_stats)) -+ goto err_hif_napi_stats; -+#endif -+ -+ return 0; -+ -+#ifdef HIF_NAPI_STATS -+err_hif_napi_stats: -+ device_remove_file(pfe->dev, &dev_attr_fcs_revalidated); -+#endif -+ -+err_crc_revalidated: -+ device_remove_file(pfe->dev, &dev_attr_pfemem); -+ -+err_pfemem: -+ device_remove_file(pfe->dev, &dev_attr_tmu3_queues); -+ -+err_tmu3_queues: -+ device_remove_file(pfe->dev, &dev_attr_tmu2_queues); -+ -+err_tmu2_queues: -+ device_remove_file(pfe->dev, &dev_attr_tmu1_queues); -+ -+err_tmu1_queues: -+ device_remove_file(pfe->dev, &dev_attr_tmu0_queues); -+ -+err_tmu0_queues: -+ device_remove_file(pfe->dev, &dev_attr_drops); -+ -+err_drops: -+ device_remove_file(pfe->dev, &dev_attr_gpi); -+ -+err_gpi: -+ device_remove_file(pfe->dev, &dev_attr_hif); -+ -+err_hif: -+ device_remove_file(pfe->dev, &dev_attr_bmu); -+ -+err_bmu: -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ device_remove_file(pfe->dev, &dev_attr_util); -+ -+err_util: -+#endif -+ device_remove_file(pfe->dev, &dev_attr_tmu); -+ -+err_tmu: -+ device_remove_file(pfe->dev, &dev_attr_class); -+ -+err_class: -+ return -1; -+} -+ -+void pfe_sysfs_exit(struct pfe *pfe) -+{ -+#ifdef HIF_NAPI_STATS -+ device_remove_file(pfe->dev, &dev_attr_hif_napi_stats); -+#endif -+ device_remove_file(pfe->dev, &dev_attr_fcs_revalidated); -+ device_remove_file(pfe->dev, &dev_attr_pfemem); -+ device_remove_file(pfe->dev, &dev_attr_tmu3_queues); -+ device_remove_file(pfe->dev, &dev_attr_tmu2_queues); -+ device_remove_file(pfe->dev, &dev_attr_tmu1_queues); -+ device_remove_file(pfe->dev, &dev_attr_tmu0_queues); -+ device_remove_file(pfe->dev, &dev_attr_drops); -+ device_remove_file(pfe->dev, &dev_attr_gpi); -+ device_remove_file(pfe->dev, &dev_attr_hif); -+ device_remove_file(pfe->dev, &dev_attr_bmu); -+#if !defined(CONFIG_FSL_PPFE_UTIL_DISABLED) -+ device_remove_file(pfe->dev, &dev_attr_util); -+#endif -+ device_remove_file(pfe->dev, &dev_attr_tmu); -+ device_remove_file(pfe->dev, &dev_attr_class); -+} ---- /dev/null -+++ b/drivers/staging/fsl_ppfe/pfe_sysfs.h -@@ -0,0 +1,17 @@ -+/* SPDX-License-Identifier: GPL-2.0+ */ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP -+ */ -+ -+#ifndef _PFE_SYSFS_H_ -+#define _PFE_SYSFS_H_ -+ -+#include -+ -+u32 qm_read_drop_stat(u32 tmu, u32 queue, u32 *total_drops, int do_reset); -+ -+int pfe_sysfs_init(struct pfe *pfe); -+void pfe_sysfs_exit(struct pfe *pfe); -+ -+#endif /* _PFE_SYSFS_H_ */ diff --git a/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch deleted file mode 100644 index dc63c7e3dd..0000000000 --- a/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 5677c6ef5f4096f3149a4e8cfd1438bc9eb2e8a4 Mon Sep 17 00:00:00 2001 -From: Bhaskar Upadhaya -Date: Wed, 29 Nov 2017 15:27:57 +0530 -Subject: [PATCH] phy: Add 2.5G SGMII interface mode - -Add 2.5G SGMII interface mode(PHY_INTERFACE_MODE_2500SGMII) -in existing phy_interface list - -Signed-off-by: Bhaskar Upadhaya ---- - Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 + - drivers/net/phy/phy-core.c | 1 + - drivers/net/phy/phylink.c | 2 ++ - include/linux/phy.h | 3 +++ - 4 files changed, 7 insertions(+) - ---- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml -+++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml -@@ -65,6 +65,7 @@ properties: - - mii - - gmii - - sgmii -+ - sgmii-2500 - - psgmii - - qsgmii - - qusgmii ---- a/drivers/net/phy/phy-core.c -+++ b/drivers/net/phy/phy-core.c -@@ -138,6 +138,7 @@ int phy_interface_num_ports(phy_interfac - case PHY_INTERFACE_MODE_RXAUI: - case PHY_INTERFACE_MODE_XAUI: - case PHY_INTERFACE_MODE_1000BASEKX: -+ case PHY_INTERFACE_MODE_2500SGMII: - return 1; - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -250,6 +250,7 @@ static int phylink_interface_max_speed(p - case PHY_INTERFACE_MODE_GMII: - return SPEED_1000; - -+ case PHY_INTERFACE_MODE_2500SGMII: - case PHY_INTERFACE_MODE_2500BASEX: - case PHY_INTERFACE_MODE_10G_QXGMII: - return SPEED_2500; -@@ -564,6 +565,7 @@ static unsigned long phylink_get_capabil - break; - - case PHY_INTERFACE_MODE_2500BASEX: -+ case PHY_INTERFACE_MODE_2500SGMII: - caps |= MAC_2500FD; - break; - ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -170,6 +170,7 @@ typedef enum { - PHY_INTERFACE_MODE_QUSGMII, - PHY_INTERFACE_MODE_1000BASEKX, - PHY_INTERFACE_MODE_10G_QXGMII, -+ PHY_INTERFACE_MODE_2500SGMII, - PHY_INTERFACE_MODE_MAX, - } phy_interface_t; - -@@ -245,6 +246,8 @@ static inline const char *phy_modes(phy_ - return "gmii"; - case PHY_INTERFACE_MODE_SGMII: - return "sgmii"; -+ case PHY_INTERFACE_MODE_2500SGMII: -+ return "sgmii-2500"; - case PHY_INTERFACE_MODE_TBI: - return "tbi"; - case PHY_INTERFACE_MODE_REVMII: diff --git a/target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch b/target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch deleted file mode 100644 index 2d724bb582..0000000000 --- a/target/linux/layerscape/patches-6.12/703-layerscape-6.12-fix-compilation-warning-for-fsl-ppfe-.patch +++ /dev/null @@ -1,239 +0,0 @@ -From 1dc3a2e216d99adc2df022ab37eab32f61d80e0e Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 8 May 2023 19:26:48 +0200 -Subject: [PATCH] layerscape: 6.1: fix compilation warning for fsl ppfe driver - -Rework some desc dump and dummy pkt function to fix compilation warning. -Fix compilation warning: -drivers/staging/fsl_ppfe/pfe_hif.c: In function 'send_dummy_pkt_to_hif': -drivers/staging/fsl_ppfe/pfe_hif.c:118:19: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] - 118 | ddr_ptr = (void *)((u64)readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL)); - | ^ -drivers/staging/fsl_ppfe/pfe_hif.c:122:20: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] - 122 | lmem_ptr = (void *)((u64)readl(BMU1_BASE_ADDR + BMU_ALLOC_CTRL)); - | ^ -drivers/staging/fsl_ppfe/pfe_hif.c: In function 'pfe_hif_desc_dump': -drivers/staging/fsl_ppfe/pfe_hif.c:195:24: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] - 195 | desc_p = (u32)((u64)desc - (u64)hif->descr_baseaddr_v + - | ^ -drivers/staging/fsl_ppfe/pfe_hif.c:195:36: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] - 195 | desc_p = (u32)((u64)desc - (u64)hif->descr_baseaddr_v + - | ^ -drivers/staging/fsl_ppfe/pfe_hif.c:207:19: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] - 207 | desc_p = ((u64)desc - (u64)hif->descr_baseaddr_v + - | ^ -drivers/staging/fsl_ppfe/pfe_hif.c:207:31: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast] - 207 | desc_p = ((u64)desc - (u64)hif->descr_baseaddr_v + - | ^ -cc1: all warnings being treated as errors - -In file included from ./include/linux/kernel.h:19, - from ./include/linux/list.h:9, - from ./include/linux/wait.h:7, - from ./include/linux/eventfd.h:13, - from drivers/staging/fsl_ppfe/pfe_cdev.c:11: -drivers/staging/fsl_ppfe/pfe_cdev.c: In function 'pfe_cdev_read': -./include/linux/kern_levels.h:5:25: error: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'int' [-Werror=format=] - 5 | #define KERN_SOH "\001" /* ASCII Start Of Header */ - | ^~~~~~ -./include/linux/printk.h:422:25: note: in definition of macro 'printk_index_wrap' - 422 | _p_func(_fmt, ##__VA_ARGS__); \ - | ^~~~ -./include/linux/printk.h:132:17: note: in expansion of macro 'printk' - 132 | printk(fmt, ##__VA_ARGS__); \ - | ^~~~~~ -./include/linux/printk.h:580:9: note: in expansion of macro 'no_printk' - 580 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) - | ^~~~~~~~~ -./include/linux/kern_levels.h:15:25: note: in expansion of macro 'KERN_SOH' - 15 | #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */ - | ^~~~~~~~ -./include/linux/printk.h:580:19: note: in expansion of macro 'KERN_DEBUG' - 580 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) - | ^~~~~~~~~~ -drivers/staging/fsl_ppfe/pfe_cdev.c:42:17: note: in expansion of macro 'pr_debug' - 42 | pr_debug("%u %lu", link_states[ret].phy_id, - | ^~~~~~~~ -./include/linux/kern_levels.h:5:25: error: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'size_t' {aka 'unsigned int'} [-Werror=format=] - 5 | #define KERN_SOH "\001" /* ASCII Start Of Header */ - | ^~~~~~ -./include/linux/printk.h:422:25: note: in definition of macro 'printk_index_wrap' - 422 | _p_func(_fmt, ##__VA_ARGS__); \ - | ^~~~ -./include/linux/printk.h:493:9: note: in expansion of macro 'printk' - 493 | printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) - | ^~~~~~ -./include/linux/kern_levels.h:11:25: note: in expansion of macro 'KERN_SOH' - 11 | #define KERN_ERR KERN_SOH "3" /* error conditions */ - | ^~~~~~~~ -./include/linux/printk.h:493:16: note: in expansion of macro 'KERN_ERR' - 493 | printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) - | ^~~~~~~~ -drivers/staging/fsl_ppfe/pfe_cdev.c:50:17: note: in expansion of macro 'pr_err' - 50 | pr_err("Failed to send (%d)bytes of (%lu) requested.\n", - | ^~~~~~ -./include/linux/kern_levels.h:5:25: error: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'unsigned int' [-Werror=format=] - 5 | #define KERN_SOH "\001" /* ASCII Start Of Header */ - | ^~~~~~ -./include/linux/printk.h:422:25: note: in definition of macro 'printk_index_wrap' - 422 | _p_func(_fmt, ##__VA_ARGS__); \ - | ^~~~ -./include/linux/printk.h:132:17: note: in expansion of macro 'printk' - 132 | printk(fmt, ##__VA_ARGS__); \ - | ^~~~~~ -./include/linux/printk.h:580:9: note: in expansion of macro 'no_printk' - 580 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) - | ^~~~~~~~~ -./include/linux/kern_levels.h:15:25: note: in expansion of macro 'KERN_SOH' - 15 | #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */ - | ^~~~~~~~ -./include/linux/printk.h:580:19: note: in expansion of macro 'KERN_DEBUG' - 580 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) - | ^~~~~~~~~~ -drivers/staging/fsl_ppfe/pfe_cdev.c:57:9: note: in expansion of macro 'pr_debug' - 57 | pr_debug("Read of (%lu) bytes performed.\n", sizeof(link_states)); - | ^~~~~~~~ -cc1: all warnings being treated as errors - -In file included from ./include/uapi/linux/posix_types.h:5, - from ./include/uapi/linux/types.h:14, - from ./include/linux/types.h:6, - from ./include/linux/list.h:5, - from ./include/linux/module.h:12, - from drivers/staging/fsl_ppfe/pfe_sysfs.c:7: -drivers/staging/fsl_ppfe/pfe_sysfs.c: In function 'pfe_set_util': -./include/linux/stddef.h:8:14: error: passing argument 2 of 'kstrtoul' makes integer from pointer without a cast [-Werror=int-conversion] - 8 | #define NULL ((void *)0) - | ^~~~~~~~~~~ - | | - | void * -drivers/staging/fsl_ppfe/pfe_sysfs.c:538:39: note: in expansion of macro 'NULL' - 538 | util_do_clear = kstrtoul(buf, NULL, 0); - | ^~~~ -In file included from ./include/linux/kernel.h:13, - from ./include/linux/list.h:9: -./include/linux/kstrtox.h:30:69: note: expected 'unsigned int' but argument is of type 'void *' - 30 | static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res) - | ~~~~~~~~~~~~~^~~~ -cc1: all warnings being treated as errors - -With UTIL compiled on, fix compilation warning: -drivers/staging/fsl_ppfe/pfe_hal.c: In function 'pe_load_ddr_section': -drivers/staging/fsl_ppfe/pfe_hal.c:617:19: error: 'else' without a previous 'if' - 617 | } else { - | ^~~~ -drivers/staging/fsl_ppfe/pfe_hal.c:622:17: error: break statement not within loop or switch - 622 | break; - | ^~~~~ -drivers/staging/fsl_ppfe/pfe_hal.c:624:9: error: case label not within a switch statement - 624 | case SHT_NOBITS: - | ^~~~ -drivers/staging/fsl_ppfe/pfe_hal.c:627:17: error: break statement not within loop or switch - 627 | break; - | ^~~~~ -drivers/staging/fsl_ppfe/pfe_hal.c:629:9: error: 'default' label not within a switch statement - 629 | default: - | ^~~~~~~ -drivers/staging/fsl_ppfe/pfe_hal.c: At top level: -drivers/staging/fsl_ppfe/pfe_hal.c:635:9: error: expected identifier or '(' before 'return' - 635 | return 0; - | ^~~~~~ -drivers/staging/fsl_ppfe/pfe_hal.c:636:1: error: expected identifier or '(' before '}' token - 636 | } - -Signed-off-by: Christian Marangi -Signed-off-by: Pawel Dembicki ---- - drivers/staging/fsl_ppfe/pfe_cdev.c | 6 +++--- - drivers/staging/fsl_ppfe/pfe_hif.c | 14 +++++++------- - drivers/staging/fsl_ppfe/pfe_sysfs.c | 2 +- - 3 files changed, 11 insertions(+), 11 deletions(-) - ---- a/drivers/staging/fsl_ppfe/pfe_cdev.c -+++ b/drivers/staging/fsl_ppfe/pfe_cdev.c -@@ -34,7 +34,7 @@ static ssize_t pfe_cdev_read(struct file - { - int ret = 0; - -- pr_info("PFE CDEV attempt copying (%lu) size of user.\n", -+ pr_info("PFE CDEV attempt copying (%zu) size of user.\n", - sizeof(link_states)); - - pr_debug("Dump link_state on screen before copy_to_user\n"); -@@ -47,14 +47,14 @@ static ssize_t pfe_cdev_read(struct file - /* Copy to user the value in buffer sized len */ - ret = copy_to_user(buf, &link_states, sizeof(link_states)); - if (ret != 0) { -- pr_err("Failed to send (%d)bytes of (%lu) requested.\n", -+ pr_err("Failed to send (%d)bytes of (%zu) requested.\n", - ret, len); - return -EFAULT; - } - - /* offset set back to 0 as there is contextual reading offset */ - *off = 0; -- pr_debug("Read of (%lu) bytes performed.\n", sizeof(link_states)); -+ pr_debug("Read of (%zu) bytes performed.\n", sizeof(link_states)); - - return sizeof(link_states); - } ---- a/drivers/staging/fsl_ppfe/pfe_hif.c -+++ b/drivers/staging/fsl_ppfe/pfe_hif.c -@@ -115,11 +115,11 @@ static void send_dummy_pkt_to_hif(void) - 0x33221100, 0xa8c05544, 0x00000301, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xbe86c51f }; - -- ddr_ptr = (void *)((u64)readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL)); -+ ddr_ptr = (void *)((uintptr_t)readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL)); - if (!ddr_ptr) - return; - -- lmem_ptr = (void *)((u64)readl(BMU1_BASE_ADDR + BMU_ALLOC_CTRL)); -+ lmem_ptr = (void *)((uintptr_t)readl(BMU1_BASE_ADDR + BMU_ALLOC_CTRL)); - if (!lmem_ptr) - return; - -@@ -186,16 +186,16 @@ static void pfe_hif_free_descr(struct pf - static void __maybe_unused pfe_hif_desc_dump(struct pfe_hif *hif) - { - struct hif_desc *desc; -- unsigned long desc_p; -+ u64 desc_p; - int ii = 0; - - pr_info("%s\n", __func__); - - desc = hif->rx_base; -- desc_p = (u32)((u64)desc - (u64)hif->descr_baseaddr_v + -+ desc_p = ((void *)desc - hif->descr_baseaddr_v + - hif->descr_baseaddr_p); - -- pr_info("HIF Rx desc base %p physical %x\n", desc, (u32)desc_p); -+ pr_info("HIF Rx desc base %p physical %llx\n", desc, desc_p); - for (ii = 0; ii < hif->rx_ring_size; ii++) { - pr_info("status: %08x, ctrl: %08x, data: %08x, next: %x\n", - readl(&desc->status), readl(&desc->ctrl), -@@ -204,10 +204,10 @@ static void __maybe_unused pfe_hif_desc_ - } - - desc = hif->tx_base; -- desc_p = ((u64)desc - (u64)hif->descr_baseaddr_v + -+ desc_p = ((void *)desc - hif->descr_baseaddr_v + - hif->descr_baseaddr_p); - -- pr_info("HIF Tx desc base %p physical %x\n", desc, (u32)desc_p); -+ pr_info("HIF Tx desc base %p physical %llx\n", desc, desc_p); - for (ii = 0; ii < hif->tx_ring_size; ii++) { - pr_info("status: %08x, ctrl: %08x, data: %08x, next: %x\n", - readl(&desc->status), readl(&desc->ctrl), ---- a/drivers/staging/fsl_ppfe/pfe_sysfs.c -+++ b/drivers/staging/fsl_ppfe/pfe_sysfs.c -@@ -535,7 +535,7 @@ static ssize_t pfe_show_tmu3_queues(stru - static ssize_t pfe_set_util(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) - { -- util_do_clear = kstrtoul(buf, NULL, 0); -+ util_do_clear = kstrtoul(buf, 0, 0); - return count; - } - diff --git a/target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch b/target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch deleted file mode 100644 index 99a0dec0a8..0000000000 --- a/target/linux/layerscape/patches-6.12/900-layerscape-dts-ls1012a-frdm-add-GPIO-hog-for-PHY-res.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 3efb7aeefef62886be0dde83f6340d1a1bfcb5f6 Mon Sep 17 00:00:00 2001 -From: Pawel Dembicki -Date: Fri, 31 Oct 2025 22:46:05 +0100 -Subject: [PATCH] layerscape: dts: ls1012a-frdm: add GPIO hog for PHY reset - -On LS1012A-FRDM both PHY reset pins are tied to GPIO1_23 (active-low). -Older kernels preserved the U-Boot-configured level, but since 6.12 the -pin may default to an undefined state early in boot, leaving the PHYs in -reset and breaking detection. - -Add a GPIO hog on gpio1[23], configured as output-high, to keep the -reset line deasserted from early boot. - -Signed-off-by: Pawel Dembicki ---- - arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts | 9 +++++++++ - 1 file changed, 9 insertions(+) - ---- a/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts -+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts -@@ -87,6 +87,15 @@ - status = "okay"; - }; - -+&gpio0 { -+ phy-reset-hog { -+ gpio-hog; -+ gpios = <23 1>; -+ output-low; -+ line-name = "phy-reset"; -+ }; -+}; -+ - &i2c0 { - status = "okay"; - From 7dd477918368b013f241ae9e0b0bda15f2a0f83a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 26 Jun 2026 19:00:36 +0200 Subject: [PATCH 186/228] wifi-scripts: fix disabled vif tracking using wrong dictionary key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wdev_update_disabled_vifs() indexed the disabled_vifs map with the wdev object instead of the vif name. The map is read back via disabled_vifs[vif.name], so disabled vifs were never matched, and coercing the wdev object into a string key triggered an infinite escaping loop in ucv_to_string_json_encoded() during state output, causing OOM on reboot. Suggested-by: Shayne Chen (陳軒丞) Reported-by: Michael-cy Lee (李峻宇) Signed-off-by: Felix Fietkau --- .../config/wifi-scripts/files/lib/netifd/wireless-device.uc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/network/config/wifi-scripts/files/lib/netifd/wireless-device.uc b/package/network/config/wifi-scripts/files/lib/netifd/wireless-device.uc index 768a421480..f55fc31189 100644 --- a/package/network/config/wifi-scripts/files/lib/netifd/wireless-device.uc +++ b/package/network/config/wifi-scripts/files/lib/netifd/wireless-device.uc @@ -353,7 +353,7 @@ function wdev_update_disabled_vifs(wdev) let name = vif.name; if (enabled == false) - disabled[wdev] = true; + disabled[name] = true; else if (ifindex != cache[name]) changed = true; From f6a6f764dfabc98ad094cb7d45dca0d767c1f6b8 Mon Sep 17 00:00:00 2001 From: Shiji Yang Date: Sat, 27 Jun 2026 00:56:02 +0800 Subject: [PATCH 187/228] toolchain: binutils: fix default version selection Fixes: 82f26df15c56 ("toolchain: binutils: change default to 2.46") Signed-off-by: Shiji Yang Link: https://github.com/openwrt/openwrt/pull/23952 Signed-off-by: Jonas Jelonek --- toolchain/binutils/Config.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolchain/binutils/Config.in b/toolchain/binutils/Config.in index 7cad4d6c06..29ae2e4aa8 100644 --- a/toolchain/binutils/Config.in +++ b/toolchain/binutils/Config.in @@ -2,7 +2,7 @@ choice prompt "Binutils Version" if TOOLCHAINOPTS - default BINUTILS_USE_VERSION_2_44 + default BINUTILS_USE_VERSION_2_46 help Select the version of binutils you wish to use. From 6b16b96e433e7d30abd6cf3bed2eeffe658dacc7 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Fri, 26 Jun 2026 09:32:34 +0000 Subject: [PATCH 188/228] realtek: dsa: rtl93xx: allow to adjust LED_CLK The LED_GLB_CTRL register has a field to select the clock used for LED output, either for serial LED output or for the external auxiliary MDIO to connect a RTL8231. While the default value for the period time of 400ns is the correct one for most applications, some special devices require a dedicated setting, e.g. UniFi switches with Etherlighting. Support the generic DT property "clock-frequency" within the LED node, and read + apply during LED configuration. In case the property isn't specified, no change is applied to keep previous behavior. In case an unsupported value is supplied, the default is used as a fallback Link: https://github.com/openwrt/openwrt/pull/23944 Signed-off-by: Jonas Jelonek --- .../drivers/net/dsa/rtl83xx/rtl930x.c | 33 ++++++++++++++++++ .../drivers/net/dsa/rtl83xx/rtl931x.c | 34 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c index 1c83510d9e..84e00cf86b 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c @@ -24,6 +24,11 @@ #define RTL930X_VLAN_PORT_TAG_STS_CTRL_IGR_P_ITAG_KEEP_MASK GENMASK(0, 0) #define RTL930X_LED_GLB_ACTIVE_LOW BIT(22) +#define RTL930X_LED_CLK_SEL_MASK GENMASK(17, 16) +#define RTL930X_LED_CLK_SEL_800NS 0 +#define RTL930X_LED_CLK_SEL_400NS 1 +#define RTL930X_LED_CLK_SEL_200NS 2 +#define RTL930X_LED_CLK_SEL_100NS 3 #define RTL930X_LED_SETX_0_CTRL(x) (RTL930X_LED_SET0_0_CTRL - (x * 8)) #define RTL930X_LED_SETX_1_CTRL(x) (RTL930X_LED_SETX_0_CTRL(x) - 4) @@ -2612,7 +2617,9 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) struct device *dev = priv->dev; u8 leds_in_set[4] = {}; u32 led_mode = 1; + u32 clk_freq; u32 pm = 0; + int ret; node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds"); if (!node) { @@ -2620,6 +2627,32 @@ static void rtl930x_led_init(struct rtl838x_switch_priv *priv) return; } + ret = of_property_read_u32(node, "clock-frequency", &clk_freq); + if (!ret) { + u8 clk_sel; + + switch (clk_freq) { + case 10000000: + clk_sel = RTL930X_LED_CLK_SEL_100NS; + break; + case 5000000: + clk_sel = RTL930X_LED_CLK_SEL_200NS; + break; + case 1250000: + clk_sel = RTL930X_LED_CLK_SEL_800NS; + break; + default: + dev_warn(dev, "invalid LED clock frequency, falling back to default\n"); + fallthrough; + case 2500000: + clk_sel = RTL930X_LED_CLK_SEL_400NS; + break; + } + + sw_w32_mask(RTL930X_LED_CLK_SEL_MASK, + FIELD_PREP(RTL930X_LED_CLK_SEL_MASK, clk_sel), RTL930X_LED_GLB_CTRL); + } + for (int set = 0; set < 4; set++) { char set_name[16] = {0}; u32 set_config[4]; diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c index d10517c27e..e992c45c22 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl931x.c @@ -25,6 +25,12 @@ #define RTL931X_VLAN_PORT_TAG_ITPID_IDX_MASK GENMASK(2, 1) #define RTL931X_VLAN_PORT_TAG_ITPID_KEEP_MASK GENMASK(0, 0) +#define RTL931X_LED_CLK_SEL_MASK GENMASK(16, 15) +#define RTL931X_LED_CLK_SEL_800NS 0 +#define RTL931X_LED_CLK_SEL_400NS 1 +#define RTL931X_LED_CLK_SEL_200NS 2 +#define RTL931X_LED_CLK_SEL_100NS 3 + /* Definition of the RTL931X-specific template field IDs as used in the PIE */ enum template_field_id { TEMPLATE_FIELD_SPM0 = 1, @@ -1603,6 +1609,8 @@ static void rtldsa_931x_led_init(struct rtl838x_switch_priv *priv) struct device *dev = priv->dev; struct device_node *node; u8 leds_in_set[4] = {}; + u32 clk_freq; + int ret; node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300-leds"); if (!node) { @@ -1610,6 +1618,32 @@ static void rtldsa_931x_led_init(struct rtl838x_switch_priv *priv) return; } + ret = of_property_read_u32(node, "clock-frequency", &clk_freq); + if (!ret) { + u8 clk_sel; + + switch (clk_freq) { + case 10000000: + clk_sel = RTL931X_LED_CLK_SEL_100NS; + break; + case 5000000: + clk_sel = RTL931X_LED_CLK_SEL_200NS; + break; + case 1250000: + clk_sel = RTL931X_LED_CLK_SEL_800NS; + break; + default: + dev_warn(dev, "invalid LED clock frequency, falling back to default\n"); + fallthrough; + case 2500000: + clk_sel = RTL931X_LED_CLK_SEL_400NS; + break; + } + + sw_w32_mask(RTL931X_LED_CLK_SEL_MASK, + FIELD_PREP(RTL931X_LED_CLK_SEL_MASK, clk_sel), RTL931X_LED_GLB_CTRL); + } + for (int set = 0; set < 4; set++) { char set_name[16] = {0}; u32 set_config[4]; From aea3d6cee16c98b5a799a3a6f24fd2282a6de3a7 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 27 Jun 2026 00:51:21 +0200 Subject: [PATCH 189/228] rtl8812au-ct: fix compilation with GCC 15 GCC 15 enables -Wheader-guard and the kernel module build treats warnings as errors, so the mismatched include guards in three driver headers break the build: include/rtl8812a_sreset.h:20: error: header guard '_RTL88812A_SRESET_H_' followed by '#define' of a different macro [-Werror=header-guard] Add a patch making each '#ifndef' match its '#define'. rtl8192e_sreset.h was a copy/paste of the rtl8812a guard, so it gets its own '_RTL8192E_SRESET_H_' name instead of duplicating '_RTL8812A_SRESET_H_'. Assisted-by: Claude:claude-opus-4-8 Link: https://github.com/openwrt/openwrt/pull/23957 Signed-off-by: Hauke Mehrtens --- .../012-fix-mismatched-include-guards.patch | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 package/kernel/rtl8812au-ct/patches/012-fix-mismatched-include-guards.patch diff --git a/package/kernel/rtl8812au-ct/patches/012-fix-mismatched-include-guards.patch b/package/kernel/rtl8812au-ct/patches/012-fix-mismatched-include-guards.patch new file mode 100644 index 0000000000..efcc854c14 --- /dev/null +++ b/package/kernel/rtl8812au-ct/patches/012-fix-mismatched-include-guards.patch @@ -0,0 +1,58 @@ +From 4cfefb927313c389f76adff88f863abefbb040ec Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 27 Jun 2026 00:48:52 +0200 +Subject: [PATCH] Fix mismatched include guards + +GCC 15 enables -Wheader-guard and the kernel module build treats it as +an error, so the mismatched include guards in these headers break the +build: + + include/rtl8812a_sreset.h:20: error: header guard + '_RTL88812A_SRESET_H_' followed by '#define' of a different macro + [-Werror=header-guard] + +Make each '#ifndef' match its '#define'. rtl8192e_sreset.h was a +copy/paste of the rtl8812a guard, so give it its own +'_RTL8192E_SRESET_H_' name instead of duplicating '_RTL8812A_SRESET_H_'. + +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Hauke Mehrtens +--- + include/custom_gpio.h | 2 +- + include/rtl8192e_sreset.h | 4 ++-- + include/rtl8812a_sreset.h | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/include/custom_gpio.h ++++ b/include/custom_gpio.h +@@ -1,5 +1,5 @@ + #ifndef __CUSTOM_GPIO_H__ +-#define __CUSTOM_GPIO_H___ ++#define __CUSTOM_GPIO_H__ + + #include + #include +--- a/include/rtl8192e_sreset.h ++++ b/include/rtl8192e_sreset.h +@@ -17,8 +17,8 @@ + * + * + ******************************************************************************/ +-#ifndef _RTL88812A_SRESET_H_ +-#define _RTL8812A_SRESET_H_ ++#ifndef _RTL8192E_SRESET_H_ ++#define _RTL8192E_SRESET_H_ + + #include + +--- a/include/rtl8812a_sreset.h ++++ b/include/rtl8812a_sreset.h +@@ -17,7 +17,7 @@ + * + * + ******************************************************************************/ +-#ifndef _RTL88812A_SRESET_H_ ++#ifndef _RTL8812A_SRESET_H_ + #define _RTL8812A_SRESET_H_ + + #include From 4a5642413be47e5f43d161a2a087ca6f45c9706b Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 27 Jun 2026 00:42:11 +0200 Subject: [PATCH 190/228] thc-ipv6: fix compilation with GCC 15 GCC 15 defaults to C23, where an empty parameter list "()" means "(void)" instead of an unspecified argument list. This broke thc-ipv6 in two ways: - thc-ipv6.h declared thc_open_ipv6() with an empty argument list, so its prototype became "int(void)" and conflicted with the actual definition "int thc_open_ipv6(char *interface)" and all of its callers: thc-ipv6-lib.c:127:36: error: too many arguments to function 'thc_open_ipv6'; expected 0, have 1 thc-ipv6-lib.c:2555:5: error: conflicting types for 'thc_open_ipv6'; have 'int(char *)' - The alarming() SIGALRM handlers in detect_sniffer6.c and thcping6.c were declared with "()", so their type became "void (*)(void)" and no longer matched the "void (*)(int)" expected by signal(): detect_sniffer6.c:140:19: error: passing argument 2 of 'signal' from incompatible pointer type [-Wincompatible-pointer-types] Add patches giving the prototype and the signal handlers their proper signatures. Assisted-by: Claude:claude-opus-4-8 Link: https://github.com/openwrt/openwrt/pull/23956 Signed-off-by: Hauke Mehrtens --- .../102-fix-thc_open_ipv6-prototype.patch | 37 +++++++++++++ .../103-fix-signal-handler-prototypes.patch | 55 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 package/network/ipv6/thc-ipv6/patches/102-fix-thc_open_ipv6-prototype.patch create mode 100644 package/network/ipv6/thc-ipv6/patches/103-fix-signal-handler-prototypes.patch diff --git a/package/network/ipv6/thc-ipv6/patches/102-fix-thc_open_ipv6-prototype.patch b/package/network/ipv6/thc-ipv6/patches/102-fix-thc_open_ipv6-prototype.patch new file mode 100644 index 0000000000..25446e22a1 --- /dev/null +++ b/package/network/ipv6/thc-ipv6/patches/102-fix-thc_open_ipv6-prototype.patch @@ -0,0 +1,37 @@ +From 0f6e30c03a093bba52f16570635b9f778925f2d7 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 27 Jun 2026 00:34:23 +0200 +Subject: [PATCH] Fix thc_open_ipv6() prototype for GCC 15 / C23 + +GCC 15 defaults to C23, where an empty parameter list "()" means +"(void)" instead of an unspecified argument list. thc-ipv6.h declared + + extern int thc_open_ipv6(); + +so the prototype became "int(void)" and clashed with the actual +definition "int thc_open_ipv6(char *interface)" and all of its callers: + + thc-ipv6-lib.c:127: error: too many arguments to function + 'thc_open_ipv6'; expected 0, have 1 + thc-ipv6-lib.c:2555: error: conflicting types for 'thc_open_ipv6'; + have 'int(char *)' + +Give the prototype its real signature. + +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Hauke Mehrtens +--- + thc-ipv6.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/thc-ipv6.h ++++ b/thc-ipv6.h +@@ -208,7 +208,7 @@ extern int thc_generate_pkt(char *interf + int *pkt_len); + extern int thc_send_pkt(char *interface, unsigned char *pkt, int *pkt_len); + extern unsigned char *thc_destroy_packet(unsigned char *pkt); +-extern int thc_open_ipv6(); ++extern int thc_open_ipv6(char *interface); + extern int thc_is_dst_local(char *interface, unsigned char *dst); + extern int checksum_pseudo_header(unsigned char *src, unsigned char *dst, + unsigned char type, unsigned char *data, diff --git a/package/network/ipv6/thc-ipv6/patches/103-fix-signal-handler-prototypes.patch b/package/network/ipv6/thc-ipv6/patches/103-fix-signal-handler-prototypes.patch new file mode 100644 index 0000000000..e70fbe9298 --- /dev/null +++ b/package/network/ipv6/thc-ipv6/patches/103-fix-signal-handler-prototypes.patch @@ -0,0 +1,55 @@ +From 1e48ae83dddaca892d78025fdd1d3fe6652c8522 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens +Date: Sat, 27 Jun 2026 02:24:41 +0200 +Subject: [PATCH] Fix signal handler prototypes for GCC 15 / C23 + +GCC 15 defaults to C23, where an empty parameter list "()" means +"(void)" instead of an unspecified argument list. The alarming() SIGALRM +handlers in detect_sniffer6.c and thcping6.c were declared with "()", so +their type became "void (*)(void)" and no longer matched the +"void (*)(int)" expected by signal(): + + detect_sniffer6.c:140:19: error: passing argument 2 of 'signal' from + incompatible pointer type [-Wincompatible-pointer-types] + +Give them the proper signal handler signature. Also pass an argument to +the direct alarming() call in detect_sniffer6.c. + +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Hauke Mehrtens +--- + detect_sniffer6.c | 4 ++-- + thcping6.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/detect_sniffer6.c ++++ b/detect_sniffer6.c +@@ -27,7 +27,7 @@ void help(char *prg) { + exit(-1); + } + +-void alarming() { ++void alarming(int sig) { + if (found == 0) + printf("No packets received, no vulnerable system seems to be sniffing.\n"); + else +@@ -63,7 +63,7 @@ void check_packets(u_char *pingdata, con + printf(" Sniffing host detected: %s\n", thc_ipv62notation(ptr + 8)); + memcpy(doubles[found], thc_ipv62notation(ptr + 8), 16); + found++; +- if (oneonly) alarming(); ++ if (oneonly) alarming(0); + } + } + } +--- a/thcping6.c ++++ b/thcping6.c +@@ -89,7 +89,7 @@ void help(char *prg, int help) { + exit(-1); + } + +-void alarming() { ++void alarming(int sig) { + if (done == 0) printf("No packet received, terminating.\n"); + exit(resp_type); + } From 0161349c1b48ac060c4a1beab00501ee59627dd5 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 20 Jun 2026 20:47:14 +0200 Subject: [PATCH 191/228] ead: fix compilation with GCC 15 GCC 15 defaults to C23, where an empty parameter list "()" means "(void)" instead of an unspecified argument list. This broke two spots in the bundled tinysrp sources: - The interrupt() signal handler in t_truerand.c was declared with "()", so its type became "void (*)(void)" and no longer matched the "void (*)(int)" expected by signal(): t_truerand.c:100:32: error: passing argument 2 of 'signal' from incompatible pointer type [-Wincompatible-pointer-types] Give it the proper signal handler signature instead. - The pre-ANSI fallback in t_defines.h declared strchr(), strrchr() and strtok() with "()". ead.c is compiled without -DHAVE_CONFIG_H, so STDC_HEADERS is undefined and that legacy branch is taken, where the zero-argument prototypes now conflict with the declarations in the standard headers: tinysrp/t_defines.h:90:30: error: conflicting types for 'strtok'; have 'char *(void)' Drop the dead K&R branch and include and unconditionally; the library's own objects already take this path via config.h. Assisted-by: Claude:claude-opus-4-8 Link: https://github.com/openwrt/openwrt/pull/23955 Signed-off-by: Hauke Mehrtens --- package/network/services/ead/src/tinysrp/t_defines.h | 11 ----------- package/network/services/ead/src/tinysrp/t_truerand.c | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/package/network/services/ead/src/tinysrp/t_defines.h b/package/network/services/ead/src/tinysrp/t_defines.h index 4128093f60..1a8e4034d1 100644 --- a/package/network/services/ead/src/tinysrp/t_defines.h +++ b/package/network/services/ead/src/tinysrp/t_defines.h @@ -79,19 +79,8 @@ #endif #endif -#if STDC_HEADERS #include #include -#else /* not STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr rindex -#endif -char *strchr(), *strrchr(), *strtok(); -#ifndef HAVE_MEMCPY -#define memcpy(d, s, n) bcopy((s), (d), (n)) -#endif -#endif /* not STDC_HEADERS */ #include diff --git a/package/network/services/ead/src/tinysrp/t_truerand.c b/package/network/services/ead/src/tinysrp/t_truerand.c index fa0d6ce603..f46a1e1857 100644 --- a/package/network/services/ead/src/tinysrp/t_truerand.c +++ b/package/network/services/ead/src/tinysrp/t_truerand.c @@ -86,7 +86,7 @@ tick() } static void -interrupt() +interrupt(int sig) { if (count) { #ifdef OLD_TRUERAND From 97424f9c860593ad524aff84a2f982b97abfed5f Mon Sep 17 00:00:00 2001 From: Konstantin Demin Date: Sat, 13 Jun 2026 18:12:13 +0300 Subject: [PATCH 192/228] toolchain: gcc: update GCC 15 to 15.3.0 Release Notes: https://gcc.gnu.org/gcc-15/changes.html Removed upstreamed: toolchain/gcc/patches-15.x/004-libcody-Make-it-buildable-by-C-11-to-C-26.patch [1] [1] https://github.com/gcc-mirror/gcc/commit/1f0224e8ddb3d3d0bf4c7a11769b193a4df5cc37 Signed-off-by: Konstantin Demin Link: https://github.com/openwrt/openwrt/pull/23771 Signed-off-by: Hauke Mehrtens --- toolchain/gcc/Config.version | 2 +- toolchain/gcc/common.mk | 4 +- ...dy-Make-it-buildable-by-C-11-to-C-26.patch | 250 ------------------ .../gcc/patches-15.x/820-libgcc_pic.patch | 6 +- .../gcc/patches-15.x/910-mbsd_multi.patch | 2 +- 5 files changed, 7 insertions(+), 257 deletions(-) delete mode 100644 toolchain/gcc/patches-15.x/004-libcody-Make-it-buildable-by-C-11-to-C-26.patch diff --git a/toolchain/gcc/Config.version b/toolchain/gcc/Config.version index 104ff8a9d2..d933661522 100644 --- a/toolchain/gcc/Config.version +++ b/toolchain/gcc/Config.version @@ -10,7 +10,7 @@ config GCC_VERSION string default EXTERNAL_GCC_VERSION if EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN default "13.4.0" if GCC_VERSION_13 - default "15.2.0" if GCC_VERSION_15 + default "15.3.0" if GCC_VERSION_15 default "14.3.0" config GCC_USE_DEFAULT_VERSION diff --git a/toolchain/gcc/common.mk b/toolchain/gcc/common.mk index c122810d0b..10bc7070bf 100644 --- a/toolchain/gcc/common.mk +++ b/toolchain/gcc/common.mk @@ -38,8 +38,8 @@ ifeq ($(PKG_VERSION),14.3.0) PKG_HASH:=e0dc77297625631ac8e50fa92fffefe899a4eb702592da5c32ef04e2293aca3a endif -ifeq ($(PKG_VERSION),15.2.0) - PKG_HASH:=438fd996826b0c82485a29da03a72d71d6e3541a83ec702df4271f6fe025d24e +ifeq ($(PKG_VERSION),15.3.0) + PKG_HASH:=fa59c1beef8995f27c4d71c1df227587189315d3e6faff1bb4306e61b0c530eb endif PATCH_DIR=../patches-$(GCC_MAJOR_VERSION).x diff --git a/toolchain/gcc/patches-15.x/004-libcody-Make-it-buildable-by-C-11-to-C-26.patch b/toolchain/gcc/patches-15.x/004-libcody-Make-it-buildable-by-C-11-to-C-26.patch deleted file mode 100644 index db25be919a..0000000000 --- a/toolchain/gcc/patches-15.x/004-libcody-Make-it-buildable-by-C-11-to-C-26.patch +++ /dev/null @@ -1,250 +0,0 @@ -From daa3e1ead791bc58208043cfc4595ba1a78cdd34 Mon Sep 17 00:00:00 2001 -From: Jakub Jelinek -Date: Fri, 21 Nov 2025 16:25:58 +0100 -Subject: [PATCH] libcody: Make it buildable by C++11 to C++26 - -The following builds with -std=c++11 and c++14 and c++17 and c++20 and c++23 -and c++26. - -I see the u8 string literals are mixed e.g. with strerror, so in --fexec-charset=IBM1047 there will still be garbage, so am not 100% sure if -the u8 literals everywhere are worth it either. - -2025-11-21 Jakub Jelinek - - * cody.hh (S2C): For __cpp_char8_t >= 201811 use char8_t instead of - char in argument type. - (MessageBuffer::Space): Revert 2025-11-15 change. - (MessageBuffer::Append): For __cpp_char8_t >= 201811 add overload - with char8_t const * type of first argument. - (Packet::Packet): Similarly for first argument. - * client.cc (CommunicationError, Client::ProcessResponse, - Client::Connect, ConnectResponse, PathnameResponse, OKResponse, - IncludeTranslateResponse): Cast u8 string literals to (const char *) - where needed. - * server.cc (Server::ProcessRequests, ConnectRequest): Likewise. - -(cherry picked from commit 07a767c7a50d1daae8ef7d4aba73fe53ad40c0b7) ---- - libcody/client.cc | 36 +++++++++++++++++++----------------- - libcody/cody.hh | 22 ++++++++++++++++++++++ - libcody/server.cc | 28 ++++++++++++++-------------- - 3 files changed, 55 insertions(+), 31 deletions(-) - ---- a/libcody/client.cc -+++ b/libcody/client.cc -@@ -97,7 +97,7 @@ int Client::CommunicateWithServer () - - static Packet CommunicationError (int err) - { -- std::string e {u8"communication error:"}; -+ std::string e {(const char *) u8"communication error:"}; - e.append (strerror (err)); - - return Packet (Client::PC_ERROR, std::move (e)); -@@ -110,33 +110,34 @@ Packet Client::ProcessResponse (std::vec - { - if (e == EINVAL) - { -- std::string msg (u8"malformed string '"); -+ std::string msg ((const char *) u8"malformed string '"); - msg.append (words[0]); -- msg.append (u8"'"); -+ msg.append ((const char *) u8"'"); - return Packet (Client::PC_ERROR, std::move (msg)); - } - else -- return Packet (Client::PC_ERROR, u8"missing response"); -+ return Packet (Client::PC_ERROR, (const char *) u8"missing response"); - } - - Assert (!words.empty ()); -- if (words[0] == u8"ERROR") -+ if (words[0] == (const char *) u8"ERROR") - return Packet (Client::PC_ERROR, -- words.size () == 2 ? words[1]: u8"malformed error response"); -+ words.size () == 2 ? words[1] -+ : (const char *) u8"malformed error response"); - - if (isLast && !read.IsAtEnd ()) - return Packet (Client::PC_ERROR, -- std::string (u8"unexpected extra response")); -+ std::string ((const char *) u8"unexpected extra response")); - - Assert (code < Detail::RC_HWM); - Packet result (responseTable[code] (words)); - result.SetRequest (code); - if (result.GetCode () == Client::PC_ERROR && result.GetString ().empty ()) - { -- std::string msg {u8"malformed response '"}; -+ std::string msg {(const char *) u8"malformed response '"}; - - read.LexedLine (msg); -- msg.append (u8"'"); -+ msg.append ((const char *) u8"'"); - result.GetString () = std::move (msg); - } - else if (result.GetCode () == Client::PC_CONNECT) -@@ -199,7 +200,7 @@ Packet Client::Connect (char const *agen - size_t alen, size_t ilen) - { - write.BeginLine (); -- write.AppendWord (u8"HELLO"); -+ write.AppendWord ((const char *) u8"HELLO"); - write.AppendInteger (Version); - write.AppendWord (agent, true, alen); - write.AppendWord (ident, true, ilen); -@@ -211,7 +212,8 @@ Packet Client::Connect (char const *agen - // HELLO $version $agent [$flags] - Packet ConnectResponse (std::vector &words) - { -- if (words[0] == u8"HELLO" && (words.size () == 3 || words.size () == 4)) -+ if (words[0] == (const char *) u8"HELLO" -+ && (words.size () == 3 || words.size () == 4)) - { - char *eptr; - unsigned long val = strtoul (words[1].c_str (), &eptr, 10); -@@ -247,7 +249,7 @@ Packet Client::ModuleRepo () - // PATHNAME $dir | ERROR - Packet PathnameResponse (std::vector &words) - { -- if (words[0] == u8"PATHNAME" && words.size () == 2) -+ if (words[0] == (const char *) u8"PATHNAME" && words.size () == 2) - return Packet (Client::PC_PATHNAME, std::move (words[1])); - - return Packet (Client::PC_ERROR, u8""); -@@ -256,7 +258,7 @@ Packet PathnameResponse (std::vector &words) - { -- if (words[0] == u8"OK") -+ if (words[0] == (const char *) u8"OK") - return Packet (Client::PC_OK); - else - return Packet (Client::PC_ERROR, -@@ -319,11 +321,11 @@ Packet Client::IncludeTranslate (char co - // PATHNAME $cmifile - Packet IncludeTranslateResponse (std::vector &words) - { -- if (words[0] == u8"BOOL" && words.size () == 2) -+ if (words[0] == (const char *) u8"BOOL" && words.size () == 2) - { -- if (words[1] == u8"FALSE") -- return Packet (Client::PC_BOOL, 0); -- else if (words[1] == u8"TRUE") -+ if (words[1] == (const char *) u8"FALSE") -+ return Packet (Client::PC_BOOL); -+ else if (words[1] == (const char *) u8"TRUE") - return Packet (Client::PC_BOOL, 1); - else - return Packet (Client::PC_ERROR, u8""); ---- a/libcody/cody.hh -+++ b/libcody/cody.hh -@@ -47,12 +47,21 @@ namespace Detail { - - // C++11 doesn't have utf8 character literals :( - -+#if __cpp_char8_t >= 201811 -+template -+constexpr char S2C (char8_t const (&s)[I]) -+{ -+ static_assert (I == 2, "only single octet strings may be converted"); -+ return s[0]; -+} -+#else - template - constexpr char S2C (char const (&s)[I]) - { - static_assert (I == 2, "only single octet strings may be converted"); - return s[0]; - } -+#endif - - /// Internal buffering class. Used to concatenate outgoing messages - /// and Lex incoming ones. -@@ -123,6 +132,13 @@ public: - Space (); - Append (str, maybe_quote, len); - } -+#if __cpp_char8_t >= 201811 -+ void AppendWord (char8_t const *str, bool maybe_quote = false, -+ size_t len = ~size_t (0)) -+ { -+ AppendWord ((const char *) str, maybe_quote, len); -+ } -+#endif - /// Add a word as with AppendWord - /// @param str the string to append - /// @param maybe_quote string might need quoting, as for Append -@@ -264,6 +280,12 @@ public: - : string (s), cat (STRING), code (c) - { - } -+#if __cpp_char8_t >= 201811 -+ Packet (unsigned c, const char8_t *s) -+ : string ((const char *) s), cat (STRING), code (c) -+ { -+ } -+#endif - Packet (unsigned c, std::vector &&v) - : vector (std::move (v)), cat (VECTOR), code (c) - { ---- a/libcody/server.cc -+++ b/libcody/server.cc -@@ -36,12 +36,12 @@ static RequestPair - const requestTable[Detail::RC_HWM] = - { - // Same order as enum RequestCode -- RequestPair {u8"HELLO", nullptr}, -- RequestPair {u8"MODULE-REPO", ModuleRepoRequest}, -- RequestPair {u8"MODULE-EXPORT", ModuleExportRequest}, -- RequestPair {u8"MODULE-IMPORT", ModuleImportRequest}, -- RequestPair {u8"MODULE-COMPILED", ModuleCompiledRequest}, -- RequestPair {u8"INCLUDE-TRANSLATE", IncludeTranslateRequest}, -+ RequestPair {(const char *) u8"HELLO", nullptr}, -+ RequestPair {(const char *) u8"MODULE-REPO", ModuleRepoRequest}, -+ RequestPair {(const char *) u8"MODULE-EXPORT", ModuleExportRequest}, -+ RequestPair {(const char *) u8"MODULE-IMPORT", ModuleImportRequest}, -+ RequestPair {(const char *) u8"MODULE-COMPILED", ModuleCompiledRequest}, -+ RequestPair {(const char *) u8"INCLUDE-TRANSLATE", IncludeTranslateRequest}, - }; - } - -@@ -135,21 +135,21 @@ void Server::ProcessRequests (void) - std::string msg; - - if (err > 0) -- msg = u8"error processing '"; -+ msg = (const char *) u8"error processing '"; - else if (ix >= Detail::RC_HWM) -- msg = u8"unrecognized '"; -+ msg = (const char *) u8"unrecognized '"; - else if (IsConnected () && ix == Detail::RC_CONNECT) -- msg = u8"already connected '"; -+ msg = (const char *) u8"already connected '"; - else if (!IsConnected () && ix != Detail::RC_CONNECT) -- msg = u8"not connected '"; -+ msg = (const char *) u8"not connected '"; - else -- msg = u8"malformed '"; -+ msg = (const char *) u8"malformed '"; - - read.LexedLine (msg); -- msg.append (u8"'"); -+ msg.append ((const char *) u8"'"); - if (err > 0) - { -- msg.append (u8" "); -+ msg.append ((const char *) u8" "); - msg.append (strerror (err)); - } - resolver->ErrorResponse (this, std::move (msg)); -@@ -176,7 +176,7 @@ Resolver *ConnectRequest (Server *s, Res - return nullptr; - - if (words.size () == 3) -- words.emplace_back (u8""); -+ words.emplace_back ((const char *) u8""); - unsigned version = ParseUnsigned (words[1]); - if (version == ~0u) - return nullptr; diff --git a/toolchain/gcc/patches-15.x/820-libgcc_pic.patch b/toolchain/gcc/patches-15.x/820-libgcc_pic.patch index f9691e599f..20f1bac45a 100644 --- a/toolchain/gcc/patches-15.x/820-libgcc_pic.patch +++ b/toolchain/gcc/patches-15.x/820-libgcc_pic.patch @@ -8,7 +8,7 @@ Date: Mon Oct 19 23:26:09 2009 +0000 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in -@@ -944,11 +944,12 @@ $(libgcov-driver-objects): %$(objext): $ +@@ -945,11 +945,12 @@ $(libgcov-driver-objects): %$(objext): $ # Static libraries. libgcc.a: $(libgcc-objects) @@ -22,7 +22,7 @@ Date: Mon Oct 19 23:26:09 2009 +0000 -rm -f $@ objects="$(objects)"; \ -@@ -972,7 +973,7 @@ all: libunwind.a +@@ -973,7 +974,7 @@ all: libunwind.a endif ifeq ($(enable_shared),yes) @@ -31,7 +31,7 @@ Date: Mon Oct 19 23:26:09 2009 +0000 ifneq ($(LIBUNWIND),) all: libunwind$(SHLIB_EXT) libgcc_s$(SHLIB_EXT): libunwind$(SHLIB_EXT) -@@ -1181,6 +1182,10 @@ install-shared: +@@ -1182,6 +1183,10 @@ install-shared: chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a $(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a diff --git a/toolchain/gcc/patches-15.x/910-mbsd_multi.patch b/toolchain/gcc/patches-15.x/910-mbsd_multi.patch index 4b29ac01cc..3603b95b40 100644 --- a/toolchain/gcc/patches-15.x/910-mbsd_multi.patch +++ b/toolchain/gcc/patches-15.x/910-mbsd_multi.patch @@ -114,7 +114,7 @@ Date: Tue Jul 31 00:52:27 2007 +0000 ; On SVR4 targets, it also controls whether or not to emit a --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi -@@ -10897,6 +10897,17 @@ This option is only supported for C and +@@ -10901,6 +10901,17 @@ This option is only supported for C and This warning is upgraded to an error by @option{-pedantic-errors}. From 91fa75d7f4ad6627c7f86c1f9e944f169265f734 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Wed, 24 Jun 2026 19:46:25 +0200 Subject: [PATCH 193/228] airoha: an7581: fix GPS support on Gemtek W1700k This commit removes unnecessary pinctrl nodes for the PHY LEDs. The LEDs are controlled directly via GPIO pins. Alternate function of gpio33/34 is CTS/RTS for UART2. It looks like this pinctrl is somehow conflicting with HSUART. This is likely an errata in the early silicon revision. HSUART is connected to GPS. The comment incorrectly states that the PHY driver doesn't attach. The driver attaches correctly, the only drawback is a warning in the log. Warning: [ 10.463371] mdio_bus mt7530-0: Failed to setup PHY LED pinctrl [ 10.494230] mdio_bus mt7530-0: Failed to setup PHY LED pinctrl [ 10.926028] mt7530-mmio 1fb58000.switch: configuring for fixed/internal link mode [ 10.933640] mt7530-mmio 1fb58000.switch lan3 (uninitialized): PHY [mt7530-0:09] driver [Airoha AN7581 PHY] (irq=50) [ 10.944890] mt7530-mmio 1fb58000.switch lan4 (uninitialized): PHY [mt7530-0:0a] driver [Airoha AN7581 PHY] (irq=51) GPS test: root@OpenWrt:~# minicom -D /dev/ttyS2 -b 460800 ... $GNGGA,000106.012,,,,,0,0,,,M,,M,,*52 $GNGLL,,,,,000106.012,V,N*60 $GNGSA,A,1,,,,,,,,,,,,,,,,1*1D $GNGSA,A,1,,,,,,,,,,,,,,,,2*1E $GNGSA,A,1,,,,,,,,,,,,,,,,3*1F $GNGSA,A,1,,,,,,,,,,,,,,,,4*18 $GPGSV,1,1,00,1*64 ... Fixes: 99307582dea2 ("airoha: add support for Gemtek W1700K") Signed-off-by: Aleksander Jan Bajkowski Link: https://github.com/openwrt/openwrt/pull/23936 Signed-off-by: Jonas Jelonek --- target/linux/airoha/dts/an7581-w1700k-ubi.dts | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/target/linux/airoha/dts/an7581-w1700k-ubi.dts b/target/linux/airoha/dts/an7581-w1700k-ubi.dts index 4aa281c79d..d306f8f8e6 100644 --- a/target/linux/airoha/dts/an7581-w1700k-ubi.dts +++ b/target/linux/airoha/dts/an7581-w1700k-ubi.dts @@ -123,25 +123,6 @@ }; }; - /* W1700K does not use the built-in LED controller. Instead, it uses GPIO. - * The driver fails to probe without gswpX_led0_pins defined, so put a dummy - * here. - */ - - gswp1_led0_pins: gswp1-led0-pins { - mux { - function = "phy1_led0"; - pins = "gpio33"; - }; - }; - - gswp2_led0_pins: gswp2-led0-pins { - mux { - function = "phy2_led0"; - pins = "gpio34"; - }; - }; - uart2_pins: uart2-pins { mux { function = "uart"; @@ -387,8 +368,6 @@ &gsw_phy1 { status = "okay"; interrupts = <1>; - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gswp1_led0_pins>; }; &gsw_port1 { @@ -399,8 +378,6 @@ &gsw_phy2 { status = "okay"; interrupts = <2>; - pinctrl-names = "gbe-led"; - pinctrl-0 = <&gswp2_led0_pins>; }; &gsw_port2 { From dcbb2f58dc9d5c772fb0c5230bddde087e84c7a0 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 19 Jun 2026 15:45:29 -0700 Subject: [PATCH 194/228] irq-ath79-intc: use of_irq_get Modern version of irq_of_map_and_parse() that does not require irq_dispose_mapping() to be called. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23884 Signed-off-by: Jonas Jelonek --- .../ath79/files/drivers/irqchip/irq-ath79-intc.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index 565c2a5fde..ed29eb1eed 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -19,7 +19,7 @@ #define ATH79_MAX_INTC_CASCADE 3 struct ath79_intc { - u32 irq; + int irq; u32 num_irqs; u32 enable_mask; u32 int_status; @@ -139,25 +139,29 @@ static int __init ath79_intc_of_init( intc->irq_wb_chan[irq] = args.args[0]; } - intc->irq = irq_of_parse_and_map(node, 0); + intc->irq = of_irq_get(node, 0); + if (intc->irq < 0) { + pr_err("Failed to get INTC IRQ\n"); + err = intc->irq; + goto err; + } + if (!intc->irq) { pr_err("Failed to get INTC IRQ\n"); - err = -EINVAL; + err = -ENODEV; goto err; } domain = irq_domain_create_linear(of_fwnode_handle(node), cnt, &ath79_irq_domain_ops, intc); if (!domain) { err = -EINVAL; - goto err_irq; + goto err; } irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); return 0; -err_irq: - irq_dispose_mapping(intc->irq); err: kfree(intc); return err; From 8ff69df2e0f308a47746deae5a0fe987dcca4757 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 19 Jun 2026 15:34:01 -0700 Subject: [PATCH 195/228] irq-ath79-intc: move irq_chip to private struct For whatever reason, the static array change is causing massive dmesg spam. Revert it for now. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23884 Signed-off-by: Jonas Jelonek --- .../ath79/files/drivers/irqchip/irq-ath79-intc.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c index ed29eb1eed..d517980b37 100644 --- a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -25,6 +25,7 @@ struct ath79_intc { u32 int_status; u32 irq_mask[ATH79_MAX_INTC_CASCADE]; u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; + struct irq_chip chip; }; static void ath79_intc_irq_handler(struct irq_desc *desc) @@ -68,15 +69,12 @@ static void ath79_intc_irq_disable(struct irq_data *d) disable_irq(intc->irq); } -static const struct irq_chip ath79_intc_irq_chip = { - .name = "INTC", - .irq_enable = ath79_intc_irq_enable, - .irq_disable = ath79_intc_irq_disable, -}; - static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) { - irq_set_chip_and_handler(irq, &ath79_intc_irq_chip, handle_level_irq); + struct ath79_intc *intc = d->host_data; + + irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); + return 0; } @@ -102,6 +100,10 @@ static int __init ath79_intc_of_init( if (!intc) return -ENOMEM; + intc->chip = dummy_irq_chip; + intc->chip.name = "INTC"; + intc->chip.irq_disable = ath79_intc_irq_disable; + intc->chip.irq_enable = ath79_intc_irq_enable; intc->num_irqs = cnt; if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { From f1a41ccb3da088080e0ed3274884138c6f25cc62 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 27 Jun 2026 16:12:46 +0200 Subject: [PATCH 196/228] odhcp6c: update to Git HEAD (2026-06-27) 10a52220aec9 config: drop misleading const from option-parsing input strings Signed-off-by: Hauke Mehrtens --- package/network/ipv6/odhcp6c/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/ipv6/odhcp6c/Makefile b/package/network/ipv6/odhcp6c/Makefile index 99fa036860..eddb1858d0 100644 --- a/package/network/ipv6/odhcp6c/Makefile +++ b/package/network/ipv6/odhcp6c/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/odhcp6c.git -PKG_SOURCE_DATE:=2026-06-20 -PKG_SOURCE_VERSION:=07d324ee7222c0e15b9975281f18236fdccc11bd -PKG_MIRROR_HASH:=f26733017c82f5397bae026c56df8e1225dfaa8cdbea3cf7b3f9192cfa9ba719 +PKG_SOURCE_DATE:=2026-06-27 +PKG_SOURCE_VERSION:=10a52220aec9d45803518d8cc4d63e552484ed61 +PKG_MIRROR_HASH:=2194569b6899febaa70070e19b9849737952e2f96edf02d3bd504c6e76160ce4 PKG_MAINTAINER:=Álvaro Fernández Rojas PKG_LICENSE:=GPL-2.0 From cdf91585086e61a243db36fa61d155dcc2a515d3 Mon Sep 17 00:00:00 2001 From: Carsten Schuette Date: Sat, 6 Jun 2026 08:10:02 +0200 Subject: [PATCH 197/228] dtc: update to 1.8.1 Changelog: https://git.kernel.org/pub/scm/utils/dtc/dtc.git/tag/?h=v1.8.1 https://git.kernel.org/pub/scm/utils/dtc/dtc.git/tag/?h=v1.8.0 This also fixes #23671 Signed-off-by: Carsten Schuette Link: https://github.com/openwrt/openwrt/pull/23677 Signed-off-by: Hauke Mehrtens --- package/utils/dtc/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/utils/dtc/Makefile b/package/utils/dtc/Makefile index 9a03662afa..c6db139c23 100644 --- a/package/utils/dtc/Makefile +++ b/package/utils/dtc/Makefile @@ -5,11 +5,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dtc -PKG_VERSION:=1.7.2 +PKG_VERSION:=1.8.1 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_HASH:=f200e5ebd7afd20d4b3804a3085af0870fcf3c194f8d7f0f6985cf8bbb4ac0f4 +PKG_HASH:=454e5cce748ce957c91e7f45e66da2cff5100ddb52155d7a909c43cbeaf1bcb0 PKG_SOURCE_URL:=@KERNEL/software/utils/dtc PKG_MAINTAINER:=Yousong Zhou @@ -93,7 +93,7 @@ MESON_ARGS += \ -Dyaml=disabled \ -Dvalgrind=disabled \ -Dpython=disabled \ - -Dstatic-build=$(if $(CONFIG_DTC_STATIC_BUILD),true,false) + $(if $(CONFIG_DTC_STATIC_BUILD),--prefer-static) define Build/InstallDev $(INSTALL_DIR) $(1)/usr/lib From f5d928e52a5f8c3d236dc0602fb407a2d3ec0285 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 27 Jun 2026 17:29:48 +0200 Subject: [PATCH 198/228] umdns: update to Git HEAD (2026-06-27) dbee55098c2e Change domain variable to const char* for gcc 15 compatibility Signed-off-by: Hauke Mehrtens --- package/network/services/umdns/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/services/umdns/Makefile b/package/network/services/umdns/Makefile index 40ee5ed492..d317fac304 100644 --- a/package/network/services/umdns/Makefile +++ b/package/network/services/umdns/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_URL=$(PROJECT_GIT)/project/mdnsd.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2026-06-16 -PKG_SOURCE_VERSION:=1b5e7bf1cec775b89f1a6068dc0b9df3593b5986 -PKG_MIRROR_HASH:=7d9ec860af2b8217f65cd4af92a61be1925ad171dee9b536c4914cc0080e3303 +PKG_SOURCE_DATE:=2026-06-27 +PKG_SOURCE_VERSION:=dbee55098c2e7a0a76feec414a11d76838572918 +PKG_MIRROR_HASH:=726e7874f7399fd286d81479ff00cb1cdd231cf3a25b8f89e4a9a1c45bb670bc PKG_MAINTAINER:=John Crispin PKG_LICENSE:=LGPL-2.1 From 313ad4789bc9b22e2739686b451131a30e67d3f2 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 28 Jun 2026 00:46:48 +0200 Subject: [PATCH 199/228] odhcpd: update to Git HEAD (2026-06-28) 68f382690bfa statefiles: escape client hostnames in the lease state file Signed-off-by: Hauke Mehrtens --- package/network/services/odhcpd/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/network/services/odhcpd/Makefile b/package/network/services/odhcpd/Makefile index cd8b8cea7a..d2d3759c92 100644 --- a/package/network/services/odhcpd/Makefile +++ b/package/network/services/odhcpd/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/odhcpd.git -PKG_MIRROR_HASH:=2d6504c0ee35cecc6b91d1603152bbe37b41a5a09217a90bd539e7c6371e011a -PKG_SOURCE_DATE:=2026-06-18 -PKG_SOURCE_VERSION:=03dacc23356b5789842b9d1bba0200fd005e35f3 +PKG_MIRROR_HASH:=0080feb1757c95b7a844f82728abc6d9c89b792c8170efcb73b04e728c547665 +PKG_SOURCE_DATE:=2026-06-28 +PKG_SOURCE_VERSION:=68f382690bfaec56d5b1f31c3c31c48bcb642e3a PKG_MAINTAINER:=Álvaro Fernández Rojas PKG_LICENSE:=GPL-2.0 From 5bffee2b4a97bfcaafa4337fde207df8cdc67e48 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Fri, 26 Jun 2026 18:28:29 +0200 Subject: [PATCH 200/228] realtek: l3: move routes to l3 structure Make routes an attribute of the new layer 3 control structure. Link: https://github.com/openwrt/openwrt/pull/23963 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 19 ++++++++++++------- .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 1 + .../drivers/net/dsa/rtl83xx/rtl-otto.h | 1 - 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index db3caadb8b..68daeffd4e 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -157,11 +157,12 @@ static int otto_l3_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac, /* Updates an L3 next hop entry in the ROUTING table */ static int otto_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_addr, u64 mac) { - struct otto_l3_route *r; + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; struct rhlist_head *tmp, *list; + struct otto_l3_route *r; rcu_read_lock(); - list = rhltable_lookup(&priv->routes, &ip_addr, otto_l3_route_ht_params); + list = rhltable_lookup(&ctrl->routes, &ip_addr, otto_l3_route_ht_params); if (!list) { rcu_read_unlock(); return -ENOENT; @@ -264,9 +265,10 @@ static int otto_l3_port_ipv4_resolve(struct rtl838x_switch_priv *priv, static void otto_l3_route_remove(struct rtl838x_switch_priv *priv, struct otto_l3_route *r) { + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; int id; - if (rhltable_remove(&priv->routes, &r->linkage, otto_l3_route_ht_params)) + if (rhltable_remove(&ctrl->routes, &r->linkage, otto_l3_route_ht_params)) dev_warn(priv->dev, "Could not remove route\n"); if (r->is_host_route) { @@ -291,6 +293,7 @@ static void otto_l3_route_remove(struct rtl838x_switch_priv *priv, struct otto_l static struct otto_l3_route *otto_l3_host_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) { + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; struct otto_l3_route *r; int idx = 0, err; @@ -314,7 +317,7 @@ static struct otto_l3_route *otto_l3_host_route_alloc(struct rtl838x_switch_priv r->pr.id = -1; /* We still need to allocate a rule in HW */ r->is_host_route = true; - err = rhltable_insert(&priv->routes, &r->linkage, otto_l3_route_ht_params); + err = rhltable_insert(&ctrl->routes, &r->linkage, otto_l3_route_ht_params); if (err) { pr_err("Could not insert new rule\n"); mutex_unlock(&priv->reg_mutex); @@ -335,6 +338,7 @@ out_free: static struct otto_l3_route *otto_l3_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) { + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; struct otto_l3_route *r; int idx = 0, err; @@ -354,7 +358,7 @@ static struct otto_l3_route *otto_l3_route_alloc(struct rtl838x_switch_priv *pri r->pr.id = -1; /* We still need to allocate a rule in HW */ r->is_host_route = false; - err = rhltable_insert(&priv->routes, &r->linkage, otto_l3_route_ht_params); + err = rhltable_insert(&ctrl->routes, &r->linkage, otto_l3_route_ht_params); if (err) { pr_err("Could not insert new rule\n"); mutex_unlock(&priv->reg_mutex); @@ -476,6 +480,7 @@ static int otto_l3_fib_del_v4(struct rtl838x_switch_priv *priv, struct fib_entry_notifier_info *info) { struct fib_nh *nh = fib_info_nh(info->fi, 0); + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; struct rhlist_head *tmp, *list; struct otto_l3_route *route; @@ -483,7 +488,7 @@ static int otto_l3_fib_del_v4(struct rtl838x_switch_priv *priv, return 0; rcu_read_lock(); - list = rhltable_lookup(&priv->routes, &nh->fib_nh_gw4, otto_l3_route_ht_params); + list = rhltable_lookup(&ctrl->routes, &nh->fib_nh_gw4, otto_l3_route_ht_params); if (!list) { rcu_read_unlock(); dev_err(priv->dev, "no such gateway: %pI4\n", &nh->fib_nh_gw4); @@ -715,7 +720,7 @@ int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv) ctrl->priv = priv; /* Initialize hash table for L3 routing */ - rhltable_init(&priv->routes, &otto_l3_route_ht_params); + rhltable_init(&ctrl->routes, &otto_l3_route_ht_params); /* * Register netevent notifier callback to catch notifications about neighboring changes diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index d61087dfff..fb6d47cdb6 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -9,6 +9,7 @@ struct otto_l3_ctrl { struct rtl838x_switch_priv *priv; struct notifier_block fib_nb; struct notifier_block ne_nb; + struct rhltable routes; }; struct otto_l3_route_attr { diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index 832f047562..8b5b5bff62 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -1510,7 +1510,6 @@ struct rtl838x_switch_priv { unsigned long pie_use_bm[MAX_PIE_ENTRIES >> 5]; unsigned long octet_cntr_use_bm[MAX_COUNTERS >> 5]; unsigned long packet_cntr_use_bm[MAX_COUNTERS >> 4]; - struct rhltable routes; unsigned long route_use_bm[MAX_ROUTES >> 5]; unsigned long host_route_use_bm[MAX_HOST_ROUTES >> 5]; struct rtl838x_l3_intf *interfaces[MAX_INTERFACES]; From 1f0b80a53c60f9f72d65ac94046d8d8379cf452e Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Fri, 26 Jun 2026 18:36:25 +0200 Subject: [PATCH 201/228] realtek: l3: replace priv with ctrl in work structures Use layer 3 control structure as attribute in work structures. Link: https://github.com/openwrt/openwrt/pull/23963 Signed-off-by: Markus Stockhausen --- .../realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index 68daeffd4e..18d8ac0a23 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -16,19 +16,19 @@ struct otto_l3_net_event_work { struct work_struct work; - struct rtl838x_switch_priv *priv; + struct otto_l3_ctrl *ctrl; u64 mac; u32 gw_addr; }; struct otto_l3_fib_event_work { struct work_struct work; + struct otto_l3_ctrl *ctrl; union { struct fib_entry_notifier_info fen_info; struct fib6_entry_notifier_info fen6_info; struct fib_rule_notifier_info fr_info; }; - struct rtl838x_switch_priv *priv; bool is_fib6; unsigned long event; }; @@ -529,7 +529,7 @@ static void otto_l3_fib_event_work_do(struct work_struct *work) { struct otto_l3_fib_event_work *fib_work = container_of(work, struct otto_l3_fib_event_work, work); - struct rtl838x_switch_priv *priv = fib_work->priv; + struct rtl838x_switch_priv *priv = fib_work->ctrl->priv; struct fib_rule *rule; int err; @@ -591,7 +591,7 @@ static int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event return NOTIFY_BAD; INIT_WORK(&fib_work->work, otto_l3_fib_event_work_do); - fib_work->priv = priv; + fib_work->ctrl = ctrl; fib_work->event = event; fib_work->is_fib6 = false; @@ -642,7 +642,7 @@ static void otto_l3_net_event_work_do(struct work_struct *work) { struct otto_l3_net_event_work *net_work = container_of(work, struct otto_l3_net_event_work, work); - struct rtl838x_switch_priv *priv = net_work->priv; + struct rtl838x_switch_priv *priv = net_work->ctrl->priv; otto_l3_nexthop_update(priv, net_work->gw_addr, net_work->mac); @@ -678,7 +678,7 @@ static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long return NOTIFY_BAD; INIT_WORK(&net_work->work, otto_l3_net_event_work_do); - net_work->priv = priv; + net_work->ctrl = ctrl; net_work->mac = ether_addr_to_u64(n->ha); net_work->gw_addr = *(__be32 *)n->primary_key; From dc753e2d326b7ec95cb016cc1be5ce660a846384 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Fri, 26 Jun 2026 18:48:09 +0200 Subject: [PATCH 202/228] realtek: l3: convert otto_l3_walk_data to control structure Use new control structure in walk data. Link: https://github.com/openwrt/openwrt/pull/23963 Signed-off-by: Markus Stockhausen --- .../realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index 18d8ac0a23..de9659db21 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -34,14 +34,14 @@ struct otto_l3_fib_event_work { }; struct otto_l3_walk_data { - struct rtl838x_switch_priv *priv; + struct otto_l3_ctrl *ctrl; int port; }; static int otto_l3_port_lower_walk(struct net_device *lower, struct netdev_nested_priv *_priv) { struct otto_l3_walk_data *data = (struct otto_l3_walk_data *)_priv->data; - struct rtl838x_switch_priv *priv = data->priv; + struct rtl838x_switch_priv *priv = data->ctrl->priv; int ret = 0; int index; @@ -55,12 +55,12 @@ static int otto_l3_port_lower_walk(struct net_device *lower, struct netdev_neste return ret; } -static int otto_l3_port_dev_lower_find(struct net_device *dev, struct rtl838x_switch_priv *priv) +static int otto_l3_port_dev_lower_find(struct net_device *dev, struct otto_l3_ctrl *ctrl) { struct otto_l3_walk_data data; struct netdev_nested_priv _priv; - data.priv = priv; + data.ctrl = ctrl; data.port = 0; _priv.data = (void *)&data; @@ -407,13 +407,14 @@ static int otto_l3_fib_add_v4(struct rtl838x_switch_priv *priv, struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; struct fib_nh *nh = fib_info_nh(info->fi, 0); + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; struct otto_l3_route *route; int port; if (otto_l3_fib_check_v4(priv, info, FIB_EVENT_ENTRY_ADD)) return 0; - port = otto_l3_port_dev_lower_find(ndev, priv); + port = otto_l3_port_dev_lower_find(ndev, ctrl); if (port < 0) { dev_err(priv->dev, "lower interface %s not found\n", ndev->name); return -ENODEV; @@ -667,7 +668,7 @@ static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long if (n->tbl != &arp_tbl) return NOTIFY_DONE; dev = n->dev; - port = otto_l3_port_dev_lower_find(dev, priv); + port = otto_l3_port_dev_lower_find(dev, ctrl); if (port < 0 || !(n->nud_state & NUD_VALID)) { pr_debug("%s: Neigbour invalid, not updating\n", __func__); return NOTIFY_DONE; From 885345b26896f2fdc9d49b6a75f057ddc4a67bb3 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sat, 27 Jun 2026 08:51:20 +0200 Subject: [PATCH 203/228] realtek: l3: convert to device based logging Make device logging consistent. For this - add a device attribute to the new layer 3 control structure - convert pr_...() logging to dev_...() logging. Link: https://github.com/openwrt/openwrt/pull/23963 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 94 +++++++++++-------- .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 1 + 2 files changed, 54 insertions(+), 41 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index de9659db21..db63e26dc2 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -42,13 +42,14 @@ static int otto_l3_port_lower_walk(struct net_device *lower, struct netdev_neste { struct otto_l3_walk_data *data = (struct otto_l3_walk_data *)_priv->data; struct rtl838x_switch_priv *priv = data->ctrl->priv; + struct otto_l3_ctrl *ctrl = data->ctrl; int ret = 0; int index; index = rtl83xx_port_is_under(lower, priv); data->port = index; if (index >= 0) { - pr_debug("Found DSA-port, index %d\n", index); + dev_dbg(ctrl->dev, "Found DSA-port, index %d\n", index); ret = 1; } @@ -74,8 +75,9 @@ static int otto_l3_port_dev_lower_find(struct net_device *dev, struct otto_l3_ct */ static int otto_l3_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac) { - int free_mac = -1; + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; struct rtl93xx_rt_mac m; + int free_mac = -1; mutex_lock(&priv->reg_mutex); for (int i = 0; i < MAX_ROUTER_MACS; i++) { @@ -91,7 +93,7 @@ static int otto_l3_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac) } if (free_mac < 0) { - pr_err("No free router MACs, cannot offload\n"); + dev_err(ctrl->dev, "No free router MACs, cannot offload\n"); mutex_unlock(&priv->reg_mutex); return -1; } @@ -114,8 +116,9 @@ static int otto_l3_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac) static int otto_l3_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac, int vlan) { - int free_mac = -1; + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; struct rtl838x_l3_intf intf; + int free_mac = -1; u64 m; mutex_lock(&priv->reg_mutex); @@ -132,7 +135,7 @@ static int otto_l3_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac, } if (free_mac < 0) { - pr_err("No free egress interface, cannot offload\n"); + dev_err(ctrl->dev, "No free egress interface, cannot offload\n"); return -1; } @@ -169,12 +172,13 @@ static int otto_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_ad } rhl_for_each_entry_rcu(r, tmp, list, linkage) { - pr_debug("%s: Setting up fwding: ip %pI4, GW mac %016llx\n", - __func__, &ip_addr, mac); + dev_dbg(ctrl->dev, "%s: Setting up fwding: ip %pI4, GW mac %016llx\n", + __func__, &ip_addr, mac); /* Reads the ROUTING table entry associated with the route */ priv->r->route_read(r->id, r); - pr_debug("Route with id %d to %pI4 / %d\n", r->id, &r->dst_ip, r->prefix_len); + dev_dbg(ctrl->dev, "Route with id %d to %pI4 / %d\n", + r->id, &r->dst_ip, r->prefix_len); r->nh.mac = r->nh.gw = mac; r->nh.port = priv->r->port_ignore; @@ -199,7 +203,7 @@ static int otto_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_ad if (r->is_host_route) { int slot = priv->r->find_l3_slot(r, false); - pr_info("%s: Got slot for route: %d\n", __func__, slot); + dev_info(ctrl->dev, "Got slot for route: %d\n", slot); priv->r->host_route_write(slot, r); } else { priv->r->route_write(r->id, r); @@ -214,7 +218,8 @@ static int otto_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_ad if (r->pr.id < 0) { r->pr.packet_cntr = rtl83xx_packet_cntr_alloc(priv); if (r->pr.packet_cntr >= 0) { - pr_info("Using packet counter %d\n", r->pr.packet_cntr); + dev_info(ctrl->dev, "Using packet counter %d\n", + r->pr.packet_cntr); r->pr.log_sel = true; r->pr.log_data = r->pr.packet_cntr; } @@ -222,7 +227,7 @@ static int otto_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_ad } else { int pkts = priv->r->packet_cntr_read(r->pr.packet_cntr); - pr_debug("%s: total packets: %d\n", __func__, pkts); + dev_dbg(ctrl->dev, "total packets: %d\n", pkts); priv->r->pie_rule_write(priv, r->pr.id, &r->pr); } @@ -236,6 +241,7 @@ static int otto_l3_port_ipv4_resolve(struct rtl838x_switch_priv *priv, struct net_device *dev, __be32 ip_addr) { struct neighbour *n = neigh_lookup(&arp_tbl, &ip_addr, dev); + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; int err = 0; u64 mac; @@ -251,10 +257,10 @@ static int otto_l3_port_ipv4_resolve(struct rtl838x_switch_priv *priv, */ if (n->nud_state & NUD_VALID) { mac = ether_addr_to_u64(n->ha); - pr_info("%s: resolved mac: %016llx\n", __func__, mac); + dev_info(ctrl->dev, "resolved mac: %016llx\n", mac); otto_l3_nexthop_update(priv, ip_addr, mac); } else { - pr_info("%s: need to wait\n", __func__); + dev_info(ctrl->dev, "need to wait\n"); neigh_event_send(n, NULL); } @@ -269,11 +275,11 @@ static void otto_l3_route_remove(struct rtl838x_switch_priv *priv, struct otto_l int id; if (rhltable_remove(&ctrl->routes, &r->linkage, otto_l3_route_ht_params)) - dev_warn(priv->dev, "Could not remove route\n"); + dev_warn(ctrl->dev, "Could not remove route\n"); if (r->is_host_route) { id = priv->r->find_l3_slot(r, false); - pr_debug("%s: Got id for host route: %d\n", __func__, id); + dev_dbg(ctrl->dev, "Got id for host route: %d\n", id); r->attr.valid = false; priv->r->host_route_write(id, r); clear_bit(r->id - MAX_ROUTES, priv->host_route_use_bm); @@ -281,7 +287,7 @@ static void otto_l3_route_remove(struct rtl838x_switch_priv *priv, struct otto_l /* If there is a HW representation of the route, delete it */ if (priv->r->route_lookup_hw) { id = priv->r->route_lookup_hw(r); - pr_info("%s: Got id for prefix route: %d\n", __func__, id); + dev_info(ctrl->dev, "Got id for prefix route: %d\n", id); r->attr.valid = false; priv->r->route_write(id, r); } @@ -300,7 +306,7 @@ static struct otto_l3_route *otto_l3_host_route_alloc(struct rtl838x_switch_priv mutex_lock(&priv->reg_mutex); idx = find_first_zero_bit(priv->host_route_use_bm, MAX_HOST_ROUTES); - pr_debug("%s id: %d, ip %pI4\n", __func__, idx, &ip); + dev_dbg(ctrl->dev, "id: %d, ip %pI4\n", idx, &ip); r = kzalloc(sizeof(*r), GFP_KERNEL); if (!r) { @@ -319,7 +325,7 @@ static struct otto_l3_route *otto_l3_host_route_alloc(struct rtl838x_switch_priv err = rhltable_insert(&ctrl->routes, &r->linkage, otto_l3_route_ht_params); if (err) { - pr_err("Could not insert new rule\n"); + dev_err(ctrl->dev, "Could not insert new rule\n"); mutex_unlock(&priv->reg_mutex); goto out_free; } @@ -345,7 +351,7 @@ static struct otto_l3_route *otto_l3_route_alloc(struct rtl838x_switch_priv *pri mutex_lock(&priv->reg_mutex); idx = find_first_zero_bit(priv->route_use_bm, MAX_ROUTES); - pr_debug("%s id: %d, ip %pI4\n", __func__, idx, &ip); + dev_dbg(ctrl->dev, "id: %d, ip %pI4\n", idx, &ip); r = kzalloc(sizeof(*r), GFP_KERNEL); if (!r) { @@ -360,7 +366,7 @@ static struct otto_l3_route *otto_l3_route_alloc(struct rtl838x_switch_priv *pri err = rhltable_insert(&ctrl->routes, &r->linkage, otto_l3_route_ht_params); if (err) { - pr_err("Could not insert new rule\n"); + dev_err(ctrl->dev, "Could not insert new rule\n"); mutex_unlock(&priv->reg_mutex); goto out_free; } @@ -384,17 +390,18 @@ static int otto_l3_fib_check_v4(struct rtl838x_switch_priv *priv, struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; struct fib_nh *nh = fib_info_nh(info->fi, 0); + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; char gw_message[32] = ""; if (nh->fib_nh_gw4) snprintf(gw_message, sizeof(gw_message), "via %pI4 ", &nh->fib_nh_gw4); - dev_info(priv->dev, "%s IPv4 route %pI4/%d %s(VLAN %d, MAC %pM)\n", + dev_info(ctrl->dev, "%s IPv4 route %pI4/%d %s(VLAN %d, MAC %pM)\n", event == FIB_EVENT_ENTRY_ADD ? "add" : "delete", &info->dst, info->dst_len, gw_message, vlan, ndev->dev_addr); if ((info->type == RTN_BROADCAST) || ipv4_is_loopback(info->dst) || !info->dst) { - dev_warn(priv->dev, "skip loopback/broadcast addresses and default routes\n"); + dev_warn(ctrl->dev, "skip loopback/broadcast addresses and default routes\n"); return -EINVAL; } @@ -416,7 +423,7 @@ static int otto_l3_fib_add_v4(struct rtl838x_switch_priv *priv, port = otto_l3_port_dev_lower_find(ndev, ctrl); if (port < 0) { - dev_err(priv->dev, "lower interface %s not found\n", ndev->name); + dev_err(ctrl->dev, "lower interface %s not found\n", ndev->name); return -ENODEV; } @@ -427,9 +434,10 @@ static int otto_l3_fib_add_v4(struct rtl838x_switch_priv *priv, route = otto_l3_route_alloc(priv, nh->fib_nh_gw4); if (route) - dev_info(priv->dev, "route hashtable extended for gw %pI4\n", &nh->fib_nh_gw4); + dev_info(ctrl->dev, "route hashtable extended for gw %pI4\n", &nh->fib_nh_gw4); else { - dev_err(priv->dev, "could not extend route hashtable for gw %pI4\n", &nh->fib_nh_gw4); + dev_err(ctrl->dev, "could not extend route hashtable for gw %pI4\n", + &nh->fib_nh_gw4); return -ENOSPC; } @@ -440,7 +448,7 @@ static int otto_l3_fib_add_v4(struct rtl838x_switch_priv *priv, if (priv->r->set_l3_router_mac) { u64 mac = ether_addr_to_u64(ndev->dev_addr); - pr_debug("Local route and router MAC %pM\n", ndev->dev_addr); + dev_dbg(ctrl->dev, "Local route and router MAC %pM\n", ndev->dev_addr); if (otto_l3_alloc_router_mac(priv, mac)) goto out_free_rt; @@ -459,7 +467,7 @@ static int otto_l3_fib_add_v4(struct rtl838x_switch_priv *priv, route->attr.type = 0; slot = priv->r->find_l3_slot(route, false); - pr_debug("%s: Got slot for route: %d\n", __func__, slot); + dev_dbg(ctrl->dev, "Got slot for route: %d\n", slot); priv->r->host_route_write(slot, route); } } @@ -492,12 +500,12 @@ static int otto_l3_fib_del_v4(struct rtl838x_switch_priv *priv, list = rhltable_lookup(&ctrl->routes, &nh->fib_nh_gw4, otto_l3_route_ht_params); if (!list) { rcu_read_unlock(); - dev_err(priv->dev, "no such gateway: %pI4\n", &nh->fib_nh_gw4); + dev_err(ctrl->dev, "no such gateway: %pI4\n", &nh->fib_nh_gw4); return -ENOENT; } rhl_for_each_entry_rcu(route, tmp, list, linkage) { if (route->dst_ip == info->dst && route->prefix_len == info->dst_len) { - dev_info(priv->dev, "found a route with id %d, nh-id %d\n", + dev_info(ctrl->dev, "found a route with id %d, nh-id %d\n", route->id, route->nh.id); break; } @@ -506,7 +514,7 @@ static int otto_l3_fib_del_v4(struct rtl838x_switch_priv *priv, rtl83xx_l2_nexthop_rm(priv, &route->nh); - dev_info(priv->dev, "releasing packet counter %d\n", route->pr.packet_cntr); + dev_info(ctrl->dev, "releasing packet counter %d\n", route->pr.packet_cntr); set_bit(route->pr.packet_cntr, priv->packet_cntr_use_bm); priv->r->pie_rule_rm(priv, &route->pr); @@ -520,7 +528,9 @@ static int otto_l3_fib_del_v4(struct rtl838x_switch_priv *priv, static int otto_l3_fib_add_v6(struct rtl838x_switch_priv *priv, struct fib6_entry_notifier_info *info) { - pr_debug("In %s\n", __func__); + struct otto_l3_ctrl *ctrl = priv->l3_ctrl; + + dev_dbg(ctrl->dev, "In %s\n", __func__); /* nh->fib_nh_flags |= RTNH_F_OFFLOAD; */ return 0; @@ -531,12 +541,13 @@ static void otto_l3_fib_event_work_do(struct work_struct *work) struct otto_l3_fib_event_work *fib_work = container_of(work, struct otto_l3_fib_event_work, work); struct rtl838x_switch_priv *priv = fib_work->ctrl->priv; + struct otto_l3_ctrl *ctrl = fib_work->ctrl; struct fib_rule *rule; int err; /* Protect internal structures from changes */ rtnl_lock(); - pr_debug("%s: doing work, event %ld\n", __func__, fib_work->event); + dev_dbg(ctrl->dev, "doing work, event %ld\n", fib_work->event); switch (fib_work->event) { case FIB_EVENT_ENTRY_ADD: case FIB_EVENT_ENTRY_REPLACE: @@ -546,14 +557,14 @@ static void otto_l3_fib_event_work_do(struct work_struct *work) else err = otto_l3_fib_add_v4(priv, &fib_work->fen_info); if (err) - dev_err(priv->dev, "fib_add() failed\n"); + dev_err(ctrl->dev, "fib_add() failed\n"); fib_info_put(fib_work->fen_info.fi); break; case FIB_EVENT_ENTRY_DEL: err = otto_l3_fib_del_v4(priv, &fib_work->fen_info); if (err) - dev_err(priv->dev, "fib_del() failed\n"); + dev_err(ctrl->dev, "fib_del() failed\n"); fib_info_put(fib_work->fen_info.fi); break; @@ -561,7 +572,7 @@ static void otto_l3_fib_event_work_do(struct work_struct *work) case FIB_EVENT_RULE_DEL: rule = fib_work->fr_info.rule; if (!fib4_rule_default(rule)) - pr_err("%s: FIB4 default rule failed\n", __func__); + dev_err(ctrl->dev, "FIB4 default rule failed\n"); fib_rule_put(rule); break; } @@ -601,7 +612,7 @@ static int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_APPEND: case FIB_EVENT_ENTRY_DEL: - pr_debug("%s: FIB_ENTRY ADD/DEL, event %ld\n", __func__, event); + dev_dbg(ctrl->dev, "FIB_ENTRY ADD/DEL, event %ld\n", event); if (info->family == AF_INET) { struct fib_entry_notifier_info *fen_info = ptr; @@ -620,7 +631,7 @@ static int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event } else if (info->family == AF_INET6) { //struct fib6_entry_notifier_info *fen6_info = ptr; - pr_warn("%s: FIB_RULE ADD/DEL for IPv6 not supported\n", __func__); + dev_warn(ctrl->dev, "FIB_RULE ADD/DEL for IPv6 not supported\n"); kfree(fib_work); return NOTIFY_DONE; } @@ -628,7 +639,7 @@ static int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event case FIB_EVENT_RULE_ADD: case FIB_EVENT_RULE_DEL: - pr_debug("%s: FIB_RULE ADD/DEL, event: %ld\n", __func__, event); + dev_dbg(ctrl->dev, "FIB_RULE ADD/DEL, event: %ld\n", event); memcpy(&fib_work->fr_info, ptr, sizeof(fib_work->fr_info)); fib_rule_get(fib_work->fr_info.rule); break; @@ -670,7 +681,7 @@ static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long dev = n->dev; port = otto_l3_port_dev_lower_find(dev, ctrl); if (port < 0 || !(n->nud_state & NUD_VALID)) { - pr_debug("%s: Neigbour invalid, not updating\n", __func__); + dev_dbg(ctrl->dev, "Neigbour invalid, not updating\n"); return NOTIFY_DONE; } @@ -684,8 +695,8 @@ static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long net_work->mac = ether_addr_to_u64(n->ha); net_work->gw_addr = *(__be32 *)n->primary_key; - pr_debug("%s: updating neighbour on port %d, mac %016llx\n", - __func__, port, net_work->mac); + dev_dbg(ctrl->dev, "updating neighbour on port %d, mac %016llx\n", + port, net_work->mac); queue_work(priv->wq, &net_work->work); if (err) netdev_warn(dev, "failed to handle neigh update (err %d)\n", err); @@ -719,6 +730,7 @@ int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv) return -ENOMEM; priv->l3_ctrl = ctrl; ctrl->priv = priv; + ctrl->dev = priv->dev; /* Initialize hash table for L3 routing */ rhltable_init(&ctrl->routes, &otto_l3_route_ht_params); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index fb6d47cdb6..8894075c0f 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -6,6 +6,7 @@ #include "rtl-otto.h" struct otto_l3_ctrl { + struct device *dev; struct rtl838x_switch_priv *priv; struct notifier_block fib_nb; struct notifier_block ne_nb; From fa45a65423824493ba3592f353cea4fb57c1d7b4 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sat, 27 Jun 2026 09:05:11 +0200 Subject: [PATCH 204/228] realtek: l3: convert function signatures from priv to ctrl Get rid of the priv pointer in the function signatures. Hand over the new layer 3 control structure instead. Link: https://github.com/openwrt/openwrt/pull/23963 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 77 ++++++++----------- 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index db63e26dc2..86b407d820 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -73,9 +73,9 @@ static int otto_l3_port_dev_lower_find(struct net_device *dev, struct otto_l3_ct /* On the RTL93xx, an L3 termination endpoint MAC address on which the router waits * for packets to be routed needs to be allocated. */ -static int otto_l3_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac) +static int otto_l3_alloc_router_mac(struct otto_l3_ctrl *ctrl, u64 mac) { - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; + struct rtl838x_switch_priv *priv = ctrl->priv; struct rtl93xx_rt_mac m; int free_mac = -1; @@ -114,9 +114,9 @@ static int otto_l3_alloc_router_mac(struct rtl838x_switch_priv *priv, u64 mac) return 0; } -static int otto_l3_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac, int vlan) +static int otto_l3_alloc_egress_intf(struct otto_l3_ctrl *ctrl, u64 mac, int vlan) { - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; + struct rtl838x_switch_priv *priv = ctrl->priv; struct rtl838x_l3_intf intf; int free_mac = -1; u64 m; @@ -158,9 +158,9 @@ static int otto_l3_alloc_egress_intf(struct rtl838x_switch_priv *priv, u64 mac, } /* Updates an L3 next hop entry in the ROUTING table */ -static int otto_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_addr, u64 mac) +static int otto_l3_nexthop_update(struct otto_l3_ctrl *ctrl, __be32 ip_addr, u64 mac) { - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; + struct rtl838x_switch_priv *priv = ctrl->priv; struct rhlist_head *tmp, *list; struct otto_l3_route *r; @@ -237,11 +237,10 @@ static int otto_l3_nexthop_update(struct rtl838x_switch_priv *priv, __be32 ip_ad return 0; } -static int otto_l3_port_ipv4_resolve(struct rtl838x_switch_priv *priv, +static int otto_l3_port_ipv4_resolve(struct otto_l3_ctrl *ctrl, struct net_device *dev, __be32 ip_addr) { struct neighbour *n = neigh_lookup(&arp_tbl, &ip_addr, dev); - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; int err = 0; u64 mac; @@ -258,7 +257,7 @@ static int otto_l3_port_ipv4_resolve(struct rtl838x_switch_priv *priv, if (n->nud_state & NUD_VALID) { mac = ether_addr_to_u64(n->ha); dev_info(ctrl->dev, "resolved mac: %016llx\n", mac); - otto_l3_nexthop_update(priv, ip_addr, mac); + otto_l3_nexthop_update(ctrl, ip_addr, mac); } else { dev_info(ctrl->dev, "need to wait\n"); neigh_event_send(n, NULL); @@ -269,9 +268,9 @@ static int otto_l3_port_ipv4_resolve(struct rtl838x_switch_priv *priv, return err; } -static void otto_l3_route_remove(struct rtl838x_switch_priv *priv, struct otto_l3_route *r) +static void otto_l3_route_remove(struct otto_l3_ctrl *ctrl, struct otto_l3_route *r) { - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; + struct rtl838x_switch_priv *priv = ctrl->priv; int id; if (rhltable_remove(&ctrl->routes, &r->linkage, otto_l3_route_ht_params)) @@ -297,9 +296,9 @@ static void otto_l3_route_remove(struct rtl838x_switch_priv *priv, struct otto_l kfree(r); } -static struct otto_l3_route *otto_l3_host_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) +static struct otto_l3_route *otto_l3_host_route_alloc(struct otto_l3_ctrl *ctrl, u32 ip) { - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; + struct rtl838x_switch_priv *priv = ctrl->priv; struct otto_l3_route *r; int idx = 0, err; @@ -342,9 +341,9 @@ out_free: return NULL; } -static struct otto_l3_route *otto_l3_route_alloc(struct rtl838x_switch_priv *priv, u32 ip) +static struct otto_l3_route *otto_l3_route_alloc(struct otto_l3_ctrl *ctrl, u32 ip) { - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; + struct rtl838x_switch_priv *priv = ctrl->priv; struct otto_l3_route *r; int idx = 0, err; @@ -383,14 +382,13 @@ out_free: return NULL; } -static int otto_l3_fib_check_v4(struct rtl838x_switch_priv *priv, - struct fib_entry_notifier_info *info, - enum fib_event_type event) +static int otto_l3_fib_check_v4(struct otto_l3_ctrl *ctrl, + struct fib_entry_notifier_info *info, + enum fib_event_type event) { struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; struct fib_nh *nh = fib_info_nh(info->fi, 0); - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; char gw_message[32] = ""; if (nh->fib_nh_gw4) @@ -408,17 +406,16 @@ static int otto_l3_fib_check_v4(struct rtl838x_switch_priv *priv, return 0; } -static int otto_l3_fib_add_v4(struct rtl838x_switch_priv *priv, - struct fib_entry_notifier_info *info) +static int otto_l3_fib_add_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifier_info *info) { struct net_device *ndev = fib_info_nh(info->fi, 0)->fib_nh_dev; int vlan = is_vlan_dev(ndev) ? vlan_dev_vlan_id(ndev) : 0; + struct rtl838x_switch_priv *priv = ctrl->priv; struct fib_nh *nh = fib_info_nh(info->fi, 0); - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; struct otto_l3_route *route; int port; - if (otto_l3_fib_check_v4(priv, info, FIB_EVENT_ENTRY_ADD)) + if (otto_l3_fib_check_v4(ctrl, info, FIB_EVENT_ENTRY_ADD)) return 0; port = otto_l3_port_dev_lower_find(ndev, ctrl); @@ -429,9 +426,9 @@ static int otto_l3_fib_add_v4(struct rtl838x_switch_priv *priv, /* Allocate route or host-route entry (if hardware supports this) */ if (info->dst_len == 32 && priv->r->host_route_write) - route = otto_l3_host_route_alloc(priv, nh->fib_nh_gw4); + route = otto_l3_host_route_alloc(ctrl, nh->fib_nh_gw4); else - route = otto_l3_route_alloc(priv, nh->fib_nh_gw4); + route = otto_l3_route_alloc(ctrl, nh->fib_nh_gw4); if (route) dev_info(ctrl->dev, "route hashtable extended for gw %pI4\n", &nh->fib_nh_gw4); @@ -449,11 +446,11 @@ static int otto_l3_fib_add_v4(struct rtl838x_switch_priv *priv, u64 mac = ether_addr_to_u64(ndev->dev_addr); dev_dbg(ctrl->dev, "Local route and router MAC %pM\n", ndev->dev_addr); - if (otto_l3_alloc_router_mac(priv, mac)) + if (otto_l3_alloc_router_mac(ctrl, mac)) goto out_free_rt; /* vid = 0: Do not care about VID */ - route->nh.if_id = otto_l3_alloc_egress_intf(priv, mac, vlan); + route->nh.if_id = otto_l3_alloc_egress_intf(ctrl, mac, vlan); if (route->nh.if_id < 0) goto out_free_rmac; @@ -474,7 +471,7 @@ static int otto_l3_fib_add_v4(struct rtl838x_switch_priv *priv, /* We need to resolve the mac address of the GW */ if (nh->fib_nh_gw4) - otto_l3_port_ipv4_resolve(priv, ndev, nh->fib_nh_gw4); + otto_l3_port_ipv4_resolve(ctrl, ndev, nh->fib_nh_gw4); nh->fib_nh_flags |= RTNH_F_OFFLOAD; @@ -485,15 +482,14 @@ out_free_rt: return 0; } -static int otto_l3_fib_del_v4(struct rtl838x_switch_priv *priv, - struct fib_entry_notifier_info *info) +static int otto_l3_fib_del_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifier_info *info) { + struct rtl838x_switch_priv *priv = ctrl->priv; struct fib_nh *nh = fib_info_nh(info->fi, 0); - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; struct rhlist_head *tmp, *list; struct otto_l3_route *route; - if (otto_l3_fib_check_v4(priv, info, FIB_EVENT_ENTRY_DEL)) + if (otto_l3_fib_check_v4(ctrl, info, FIB_EVENT_ENTRY_DEL)) return 0; rcu_read_lock(); @@ -518,18 +514,15 @@ static int otto_l3_fib_del_v4(struct rtl838x_switch_priv *priv, set_bit(route->pr.packet_cntr, priv->packet_cntr_use_bm); priv->r->pie_rule_rm(priv, &route->pr); - otto_l3_route_remove(priv, route); + otto_l3_route_remove(ctrl, route); nh->fib_nh_flags &= ~RTNH_F_OFFLOAD; return 0; } -static int otto_l3_fib_add_v6(struct rtl838x_switch_priv *priv, - struct fib6_entry_notifier_info *info) +static int otto_l3_fib_add_v6(struct otto_l3_ctrl *ctrl, struct fib6_entry_notifier_info *info) { - struct otto_l3_ctrl *ctrl = priv->l3_ctrl; - dev_dbg(ctrl->dev, "In %s\n", __func__); /* nh->fib_nh_flags |= RTNH_F_OFFLOAD; */ @@ -540,7 +533,6 @@ static void otto_l3_fib_event_work_do(struct work_struct *work) { struct otto_l3_fib_event_work *fib_work = container_of(work, struct otto_l3_fib_event_work, work); - struct rtl838x_switch_priv *priv = fib_work->ctrl->priv; struct otto_l3_ctrl *ctrl = fib_work->ctrl; struct fib_rule *rule; int err; @@ -553,16 +545,16 @@ static void otto_l3_fib_event_work_do(struct work_struct *work) case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_APPEND: if (fib_work->is_fib6) - err = otto_l3_fib_add_v6(priv, &fib_work->fen6_info); + err = otto_l3_fib_add_v6(ctrl, &fib_work->fen6_info); else - err = otto_l3_fib_add_v4(priv, &fib_work->fen_info); + err = otto_l3_fib_add_v4(ctrl, &fib_work->fen_info); if (err) dev_err(ctrl->dev, "fib_add() failed\n"); fib_info_put(fib_work->fen_info.fi); break; case FIB_EVENT_ENTRY_DEL: - err = otto_l3_fib_del_v4(priv, &fib_work->fen_info); + err = otto_l3_fib_del_v4(ctrl, &fib_work->fen_info); if (err) dev_err(ctrl->dev, "fib_del() failed\n"); @@ -654,9 +646,8 @@ static void otto_l3_net_event_work_do(struct work_struct *work) { struct otto_l3_net_event_work *net_work = container_of(work, struct otto_l3_net_event_work, work); - struct rtl838x_switch_priv *priv = net_work->ctrl->priv; - otto_l3_nexthop_update(priv, net_work->gw_addr, net_work->mac); + otto_l3_nexthop_update(net_work->ctrl, net_work->gw_addr, net_work->mac); kfree(net_work); } From c6df98aecbcc61f91d7de7a164048f79dca89be5 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sat, 27 Jun 2026 13:48:59 +0200 Subject: [PATCH 205/228] realtek: l3: add device specific configuration All the layer 3 device specific functions and attributes currently live in the DSA driver. Add a configuration structure to the layer 3 code. For now provide and fill a dummy value. It will be replaced with meaningful data with the next patches. Link: https://github.com/openwrt/openwrt/pull/23963 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 31 +++++++++++++++++++ .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 5 +++ 2 files changed, 36 insertions(+) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index 86b407d820..305d9e8beb 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -697,6 +698,30 @@ static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long return NOTIFY_DONE; } +const struct otto_l3_config otto_l3_838x_cfg = { + ._dummy = 8380, +}; + +const struct otto_l3_config otto_l3_839x_cfg = { + ._dummy = 8390, +}; + +const struct otto_l3_config otto_l3_930x_cfg = { + ._dummy = 9300, +}; + +const struct otto_l3_config otto_l3_931x_cfg = { + ._dummy = 9310, +}; + +static const struct of_device_id otto_l3_of_ids[] = { + { .compatible = "realtek,rtl8380-switch", .data = &otto_l3_838x_cfg, }, + { .compatible = "realtek,rtl8392-switch", .data = &otto_l3_839x_cfg, }, + { .compatible = "realtek,rtl9301-switch", .data = &otto_l3_930x_cfg, }, + { .compatible = "realtek,rtl9311-switch", .data = &otto_l3_931x_cfg, }, + { /* sentinel */ } +}; + void otto_l3_remove(struct rtl838x_switch_priv *priv) { struct otto_l3_ctrl *ctrl = priv->l3_ctrl; @@ -713,6 +738,7 @@ void otto_l3_remove(struct rtl838x_switch_priv *priv) int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv) { + const struct of_device_id *match; struct otto_l3_ctrl *ctrl; int err; @@ -723,6 +749,11 @@ int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv) ctrl->priv = priv; ctrl->dev = priv->dev; + match = of_match_node(otto_l3_of_ids, dev->of_node); + if (!match) + return dev_err_probe(dev, -EINVAL, "No compatible configuration found\n"); + ctrl->cfg = match->data; + /* Initialize hash table for L3 routing */ rhltable_init(&ctrl->routes, &otto_l3_route_ht_params); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index 8894075c0f..4ab71dea98 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -5,7 +5,12 @@ #include "rtl-otto.h" +struct otto_l3_config { + int _dummy; +}; + struct otto_l3_ctrl { + const struct otto_l3_config *cfg; struct device *dev; struct rtl838x_switch_priv *priv; struct notifier_block fib_nb; From a74b29731ca7ab41ec584324d21a7711c1ec10fe Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sat, 27 Jun 2026 16:22:26 +0200 Subject: [PATCH 206/228] realtek: l3: move route read/write into new structure Reading and writing routes is part of the layer 3 code. Move it to where it belongs. While we are here convert pr_...() logging to dev_...() logging. Link: https://github.com/openwrt/openwrt/pull/23963 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 241 +++++++++++++++++- .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 3 +- .../drivers/net/dsa/rtl83xx/rtl-otto.h | 2 - .../drivers/net/dsa/rtl83xx/rtl838x.c | 31 --- .../drivers/net/dsa/rtl83xx/rtl839x.c | 38 --- .../drivers/net/dsa/rtl83xx/rtl930x.c | 155 ----------- 6 files changed, 236 insertions(+), 234 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index 305d9e8beb..8270a765cd 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -39,6 +39,229 @@ struct otto_l3_walk_data { int port; }; +static void otto_l3_838x_route_read(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); + + rtl_table_read(r, idx); + + /* The table has a size of 2 registers */ + rt->nh.gw = sw_r32(rtl_table_data(r, 0)); + rt->nh.gw <<= 32; + rt->nh.gw |= sw_r32(rtl_table_data(r, 1)); + + rtl_table_release(r); +} + +static void otto_l3_838x_route_write(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); + + sw_w32(rt->nh.gw >> 32, rtl_table_data(r, 0)); + sw_w32(rt->nh.gw, rtl_table_data(r, 1)); + rtl_table_write(r, idx); + + rtl_table_release(r); +} + +static void otto_l3_839x_route_read(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 2); + u64 v; + + rtl_table_read(r, idx); + + /* The table has a size of 2 registers */ + v = sw_r32(rtl_table_data(r, 0)); + v <<= 32; + v |= sw_r32(rtl_table_data(r, 1)); + rt->switch_mac_id = (v >> 12) & 0xf; + rt->nh.gw = v >> 16; + + rtl_table_release(r); +} + +static void otto_l3_839x_route_write(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 2); + u32 v; + + sw_w32(rt->nh.gw >> 16, rtl_table_data(r, 0)); + v = rt->nh.gw << 16; + v |= rt->switch_mac_id << 12; + sw_w32(v, rtl_table_data(r, 1)); + rtl_table_write(r, idx); + + rtl_table_release(r); +} + +/* Read a prefix route entry from the L3_PREFIX_ROUTE_IPUC table + * We currently only support IPv4 and IPv6 unicast route + */ +__maybe_unused +static void otto_l3_930x_route_read(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 2); + bool host_route, default_route; + struct in6_addr ip6_m; + u32 v, ip4_m; + + dev_dbg(ctrl->dev, "%s\n", __func__); + + rtl_table_read(r, idx); + /* The table has a size of 11 registers */ + rt->attr.valid = !!(sw_r32(rtl_table_data(r, 0)) & BIT(31)); + if (!rt->attr.valid) + goto out; + + rt->attr.type = (sw_r32(rtl_table_data(r, 0)) >> 29) & 0x3; + + v = sw_r32(rtl_table_data(r, 10)); + host_route = !!(v & BIT(21)); + default_route = !!(v & BIT(20)); + rt->prefix_len = -1; + dev_dbg(ctrl->dev, "host route %d, default_route %d\n", host_route, default_route); + + switch (rt->attr.type) { + case 0: /* IPv4 Unicast route */ + rt->dst_ip = sw_r32(rtl_table_data(r, 4)); + ip4_m = sw_r32(rtl_table_data(r, 9)); + dev_dbg(ctrl->dev, "Read ip4 mask: %08x\n", ip4_m); + rt->prefix_len = host_route ? 32 : -1; + rt->prefix_len = (rt->prefix_len < 0 && default_route) ? 0 : -1; + if (rt->prefix_len < 0) + rt->prefix_len = inet_mask_len(ip4_m); + break; + case 2: /* IPv6 Unicast route */ + ipv6_addr_set(&rt->dst_ip6, + sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), + sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4))); + ipv6_addr_set(&ip6_m, + sw_r32(rtl_table_data(r, 6)), sw_r32(rtl_table_data(r, 7)), + sw_r32(rtl_table_data(r, 8)), sw_r32(rtl_table_data(r, 9))); + rt->prefix_len = host_route ? 128 : 0; + rt->prefix_len = (rt->prefix_len < 0 && default_route) ? 0 : -1; + if (rt->prefix_len < 0) + rt->prefix_len = find_last_bit((unsigned long *)&ip6_m.s6_addr32, + 128); + break; + case 1: /* IPv4 Multicast route */ + case 3: /* IPv6 Multicast route */ + dev_warn(ctrl->dev, "route type not supported\n"); + goto out; + } + + rt->attr.hit = !!(v & BIT(22)); + rt->attr.action = (v >> 18) & 3; + rt->nh.id = (v >> 7) & 0x7ff; + rt->attr.ttl_dec = !!(v & BIT(6)); + rt->attr.ttl_check = !!(v & BIT(5)); + rt->attr.dst_null = !!(v & BIT(4)); + rt->attr.qos_as = !!(v & BIT(3)); + rt->attr.qos_prio = v & 0x7; + dev_dbg(ctrl->dev, "index %d is valid: %d\n", idx, rt->attr.valid); + dev_dbg(ctrl->dev, "next_hop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", + rt->nh.id, rt->attr.hit, rt->attr.action, + rt->attr.ttl_dec, rt->attr.ttl_check, rt->attr.dst_null); + dev_dbg(ctrl->dev, "GW: %pI4, prefix_len: %d\n", &rt->dst_ip, rt->prefix_len); +out: + rtl_table_release(r); +} + +__maybe_unused +static void otto_l3_930x_net6_mask(int prefix_len, struct in6_addr *ip6_m) +{ + int o, b; + /* Define network mask */ + o = prefix_len >> 3; + b = prefix_len & 0x7; + memset(ip6_m->s6_addr, 0xff, o); + ip6_m->s6_addr[o] |= b ? 0xff00 >> b : 0x00; +} + +/* Write a prefix route into the routing table CAM at position idx + * Currently only IPv4 and IPv6 unicast routes are supported + */ +__maybe_unused +static void otto_l3_930x_route_write(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt) +{ + /* Access L3_PREFIX_ROUTE_IPUC table (2) via register RTL9300_TBL_1 */ + /* The table has a size of 11 registers (20 for MC) */ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 2); + struct in6_addr ip6_m; + u32 v, ip4_m; + + dev_dbg(ctrl->dev, "%s\n", __func__); + dev_dbg(ctrl->dev, "index %d is valid: %d\n", idx, rt->attr.valid); + dev_dbg(ctrl->dev, "nexthop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", + rt->nh.id, rt->attr.hit, rt->attr.action, + rt->attr.ttl_dec, rt->attr.ttl_check, rt->attr.dst_null); + dev_dbg(ctrl->dev, "GW: %pI4, prefix_len: %d\n", &rt->dst_ip, rt->prefix_len); + + v = rt->attr.valid ? BIT(31) : 0; + v |= (rt->attr.type & 0x3) << 29; + sw_w32(v, rtl_table_data(r, 0)); + + v = rt->attr.hit ? BIT(22) : 0; + v |= (rt->attr.action & 0x3) << 18; + v |= (rt->nh.id & 0x7ff) << 7; + v |= rt->attr.ttl_dec ? BIT(6) : 0; + v |= rt->attr.ttl_check ? BIT(5) : 0; + v |= rt->attr.dst_null ? BIT(6) : 0; + v |= rt->attr.qos_as ? BIT(6) : 0; + v |= rt->attr.qos_prio & 0x7; + v |= rt->prefix_len == 0 ? BIT(20) : 0; /* set default route bit */ + + /* set bit mask for entry type always to 0x3 */ + sw_w32(0x3 << 29, rtl_table_data(r, 5)); + + switch (rt->attr.type) { + case 0: /* IPv4 Unicast route */ + sw_w32(0, rtl_table_data(r, 1)); + sw_w32(0, rtl_table_data(r, 2)); + sw_w32(0, rtl_table_data(r, 3)); + sw_w32(rt->dst_ip, rtl_table_data(r, 4)); + + v |= rt->prefix_len == 32 ? BIT(21) : 0; /* set host-route bit */ + ip4_m = inet_make_mask(rt->prefix_len); + sw_w32(0, rtl_table_data(r, 6)); + sw_w32(0, rtl_table_data(r, 7)); + sw_w32(0, rtl_table_data(r, 8)); + sw_w32(ip4_m, rtl_table_data(r, 9)); + break; + case 2: /* IPv6 Unicast route */ + sw_w32(rt->dst_ip6.s6_addr32[0], rtl_table_data(r, 1)); + sw_w32(rt->dst_ip6.s6_addr32[1], rtl_table_data(r, 2)); + sw_w32(rt->dst_ip6.s6_addr32[2], rtl_table_data(r, 3)); + sw_w32(rt->dst_ip6.s6_addr32[3], rtl_table_data(r, 4)); + + v |= rt->prefix_len == 128 ? BIT(21) : 0; /* set host-route bit */ + + otto_l3_930x_net6_mask(rt->prefix_len, &ip6_m); + + sw_w32(ip6_m.s6_addr32[0], rtl_table_data(r, 6)); + sw_w32(ip6_m.s6_addr32[1], rtl_table_data(r, 7)); + sw_w32(ip6_m.s6_addr32[2], rtl_table_data(r, 8)); + sw_w32(ip6_m.s6_addr32[3], rtl_table_data(r, 9)); + break; + case 1: /* IPv4 Multicast route */ + case 3: /* IPv6 Multicast route */ + dev_warn(ctrl->dev, "route type not supported\n"); + rtl_table_release(r); + return; + } + sw_w32(v, rtl_table_data(r, 10)); + + dev_dbg(ctrl->dev, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", + sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), + sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)), + sw_r32(rtl_table_data(r, 6)), sw_r32(rtl_table_data(r, 7)), sw_r32(rtl_table_data(r, 8)), + sw_r32(rtl_table_data(r, 9)), sw_r32(rtl_table_data(r, 10))); + + rtl_table_write(r, idx); + rtl_table_release(r); +} + static int otto_l3_port_lower_walk(struct net_device *lower, struct netdev_nested_priv *_priv) { struct otto_l3_walk_data *data = (struct otto_l3_walk_data *)_priv->data; @@ -177,7 +400,7 @@ static int otto_l3_nexthop_update(struct otto_l3_ctrl *ctrl, __be32 ip_addr, u64 __func__, &ip_addr, mac); /* Reads the ROUTING table entry associated with the route */ - priv->r->route_read(r->id, r); + ctrl->cfg->route_read(ctrl, r->id, r); dev_dbg(ctrl->dev, "Route with id %d to %pI4 / %d\n", r->id, &r->dst_ip, r->prefix_len); @@ -207,7 +430,7 @@ static int otto_l3_nexthop_update(struct otto_l3_ctrl *ctrl, __be32 ip_addr, u64 dev_info(ctrl->dev, "Got slot for route: %d\n", slot); priv->r->host_route_write(slot, r); } else { - priv->r->route_write(r->id, r); + ctrl->cfg->route_write(ctrl, r->id, r); r->pr.fwd_sel = true; r->pr.fwd_data = r->nh.l2_id; r->pr.fwd_act = PIE_ACT_ROUTE_UC; @@ -289,7 +512,7 @@ static void otto_l3_route_remove(struct otto_l3_ctrl *ctrl, struct otto_l3_route id = priv->r->route_lookup_hw(r); dev_info(ctrl->dev, "Got id for prefix route: %d\n", id); r->attr.valid = false; - priv->r->route_write(id, r); + ctrl->cfg->route_write(ctrl, id, r); } clear_bit(r->id, priv->route_use_bm); } @@ -699,19 +922,23 @@ static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long } const struct otto_l3_config otto_l3_838x_cfg = { - ._dummy = 8380, + .route_read = otto_l3_838x_route_read, + .route_write = otto_l3_838x_route_write, }; const struct otto_l3_config otto_l3_839x_cfg = { - ._dummy = 8390, + .route_read = otto_l3_839x_route_read, + .route_write = otto_l3_839x_route_write, }; const struct otto_l3_config otto_l3_930x_cfg = { - ._dummy = 9300, +#ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD + .route_read = otto_l3_930x_route_read, + .route_write = otto_l3_930x_route_write, +#endif }; const struct otto_l3_config otto_l3_931x_cfg = { - ._dummy = 9310, }; static const struct of_device_id otto_l3_of_ids[] = { diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index 4ab71dea98..e92cc47fba 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -6,7 +6,8 @@ #include "rtl-otto.h" struct otto_l3_config { - int _dummy; + void (*route_read)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt); + void (*route_write)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt); }; struct otto_l3_ctrl { diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index 8b5b5bff62..6cd5b9aa2c 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -1437,8 +1437,6 @@ struct rtldsa_config { void (*l2_learning_setup)(void); u32 (*packet_cntr_read)(int counter); void (*packet_cntr_clear)(int counter); - void (*route_read)(int idx, struct otto_l3_route *rt); - void (*route_write)(int idx, struct otto_l3_route *rt); void (*host_route_write)(int idx, struct otto_l3_route *rt); int (*l3_setup)(struct rtl838x_switch_priv *priv); void (*set_l3_nexthop)(int idx, u16 dmac_id, u16 interface); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c index ae193e2537..3dd1cc6f13 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl838x.c @@ -1628,35 +1628,6 @@ static void rtl838x_packet_cntr_clear(int counter) rtl_table_release(r); } -static void rtl838x_route_read(int idx, struct otto_l3_route *rt) -{ - /* Read ROUTING table (2) via register RTL8380_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); - - pr_debug("In %s, id %d\n", __func__, idx); - rtl_table_read(r, idx); - - /* The table has a size of 2 registers */ - rt->nh.gw = sw_r32(rtl_table_data(r, 0)); - rt->nh.gw <<= 32; - rt->nh.gw |= sw_r32(rtl_table_data(r, 1)); - - rtl_table_release(r); -} - -static void rtl838x_route_write(int idx, struct otto_l3_route *rt) -{ - /* Access ROUTING table (2) via register RTL8380_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL8380_TBL_1, 2); - - pr_debug("In %s, id %d, gw: %016llx\n", __func__, idx, rt->nh.gw); - sw_w32(rt->nh.gw >> 32, rtl_table_data(r, 0)); - sw_w32(rt->nh.gw, rtl_table_data(r, 1)); - rtl_table_write(r, idx); - - rtl_table_release(r); -} - static int rtl838x_l3_setup(struct rtl838x_switch_priv *priv) { /* Nothing to be done */ @@ -1876,8 +1847,6 @@ const struct rtldsa_config rtldsa_838x_cfg = { .l2_learning_setup = rtl838x_l2_learning_setup, .packet_cntr_read = rtl838x_packet_cntr_read, .packet_cntr_clear = rtl838x_packet_cntr_clear, - .route_read = rtl838x_route_read, - .route_write = rtl838x_route_write, .l3_setup = rtl838x_l3_setup, .set_receive_management_action = rtl838x_set_receive_management_action, .qos_init = rtldsa_838x_qos_init, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c index 9e9d11a544..857201be29 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl839x.c @@ -1533,42 +1533,6 @@ static void rtl839x_packet_cntr_clear(int counter) rtl_table_release(r); } -static void rtl839x_route_read(int idx, struct otto_l3_route *rt) -{ - u64 v; - /* Read ROUTING table (2) via register RTL8390_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 2); - - pr_debug("In %s\n", __func__); - rtl_table_read(r, idx); - - /* The table has a size of 2 registers */ - v = sw_r32(rtl_table_data(r, 0)); - v <<= 32; - v |= sw_r32(rtl_table_data(r, 1)); - rt->switch_mac_id = (v >> 12) & 0xf; - rt->nh.gw = v >> 16; - - rtl_table_release(r); -} - -static void rtl839x_route_write(int idx, struct otto_l3_route *rt) -{ - u32 v; - - /* Read ROUTING table (2) via register RTL8390_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL8390_TBL_1, 2); - - pr_debug("In %s\n", __func__); - sw_w32(rt->nh.gw >> 16, rtl_table_data(r, 0)); - v = rt->nh.gw << 16; - v |= rt->switch_mac_id << 12; - sw_w32(v, rtl_table_data(r, 1)); - rtl_table_write(r, idx); - - rtl_table_release(r); -} - /* Configure the switch's own MAC addresses used when routing packets */ static void rtl839x_setup_port_macs(struct rtl838x_switch_priv *priv) { @@ -1792,8 +1756,6 @@ const struct rtldsa_config rtldsa_839x_cfg = { .l2_learning_setup = rtl839x_l2_learning_setup, .packet_cntr_read = rtl839x_packet_cntr_read, .packet_cntr_clear = rtl839x_packet_cntr_clear, - .route_read = rtl839x_route_read, - .route_write = rtl839x_route_write, .l3_setup = rtl839x_l3_setup, .set_receive_management_action = rtl839x_set_receive_management_action, .qos_init = rtldsa_839x_qos_init, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c index 84e00cf86b..de0cef88b4 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c @@ -1265,78 +1265,6 @@ static u32 rtl930x_l3_hash4(u32 ip, int algorithm, bool move_dip) // return hash; // } -/* Read a prefix route entry from the L3_PREFIX_ROUTE_IPUC table - * We currently only support IPv4 and IPv6 unicast route - */ -static void rtl930x_route_read(int idx, struct otto_l3_route *rt) -{ - u32 v, ip4_m; - bool host_route, default_route; - struct in6_addr ip6_m; - - /* Read L3_PREFIX_ROUTE_IPUC table (2) via register RTL9300_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 2); - - rtl_table_read(r, idx); - /* The table has a size of 11 registers */ - rt->attr.valid = !!(sw_r32(rtl_table_data(r, 0)) & BIT(31)); - if (!rt->attr.valid) - goto out; - - rt->attr.type = (sw_r32(rtl_table_data(r, 0)) >> 29) & 0x3; - - v = sw_r32(rtl_table_data(r, 10)); - host_route = !!(v & BIT(21)); - default_route = !!(v & BIT(20)); - rt->prefix_len = -1; - pr_debug("%s: host route %d, default_route %d\n", __func__, host_route, default_route); - - switch (rt->attr.type) { - case 0: /* IPv4 Unicast route */ - rt->dst_ip = sw_r32(rtl_table_data(r, 4)); - ip4_m = sw_r32(rtl_table_data(r, 9)); - pr_debug("%s: Read ip4 mask: %08x\n", __func__, ip4_m); - rt->prefix_len = host_route ? 32 : -1; - rt->prefix_len = (rt->prefix_len < 0 && default_route) ? 0 : -1; - if (rt->prefix_len < 0) - rt->prefix_len = inet_mask_len(ip4_m); - break; - case 2: /* IPv6 Unicast route */ - ipv6_addr_set(&rt->dst_ip6, - sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), - sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4))); - ipv6_addr_set(&ip6_m, - sw_r32(rtl_table_data(r, 6)), sw_r32(rtl_table_data(r, 7)), - sw_r32(rtl_table_data(r, 8)), sw_r32(rtl_table_data(r, 9))); - rt->prefix_len = host_route ? 128 : 0; - rt->prefix_len = (rt->prefix_len < 0 && default_route) ? 0 : -1; - if (rt->prefix_len < 0) - rt->prefix_len = find_last_bit((unsigned long *)&ip6_m.s6_addr32, - 128); - break; - case 1: /* IPv4 Multicast route */ - case 3: /* IPv6 Multicast route */ - pr_warn("%s: route type not supported\n", __func__); - goto out; - } - - rt->attr.hit = !!(v & BIT(22)); - rt->attr.action = (v >> 18) & 3; - rt->nh.id = (v >> 7) & 0x7ff; - rt->attr.ttl_dec = !!(v & BIT(6)); - rt->attr.ttl_check = !!(v & BIT(5)); - rt->attr.dst_null = !!(v & BIT(4)); - rt->attr.qos_as = !!(v & BIT(3)); - rt->attr.qos_prio = v & 0x7; - pr_debug("%s: index %d is valid: %d\n", __func__, idx, rt->attr.valid); - pr_debug("%s: next_hop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", - __func__, rt->nh.id, rt->attr.hit, rt->attr.action, - rt->attr.ttl_dec, rt->attr.ttl_check, rt->attr.dst_null); - pr_debug("%s: GW: %pI4, prefix_len: %d\n", __func__, &rt->dst_ip, rt->prefix_len); -out: - rtl_table_release(r); -} - static void rtl930x_net6_mask(int prefix_len, struct in6_addr *ip6_m) { int o, b; @@ -1532,87 +1460,6 @@ static int rtl930x_find_l3_slot(struct otto_l3_route *rt, bool must_exist) return -1; } -/* Write a prefix route into the routing table CAM at position idx - * Currently only IPv4 and IPv6 unicast routes are supported - */ -static void rtl930x_route_write(int idx, struct otto_l3_route *rt) -{ - u32 v, ip4_m; - struct in6_addr ip6_m; - /* Access L3_PREFIX_ROUTE_IPUC table (2) via register RTL9300_TBL_1 */ - /* The table has a size of 11 registers (20 for MC) */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 2); - - pr_debug("%s: index %d is valid: %d\n", __func__, idx, rt->attr.valid); - pr_debug("%s: nexthop: %d, hit: %d, action :%d, ttl_dec %d, ttl_check %d, dst_null %d\n", - __func__, rt->nh.id, rt->attr.hit, rt->attr.action, - rt->attr.ttl_dec, rt->attr.ttl_check, rt->attr.dst_null); - pr_debug("%s: GW: %pI4, prefix_len: %d\n", __func__, &rt->dst_ip, rt->prefix_len); - - v = rt->attr.valid ? BIT(31) : 0; - v |= (rt->attr.type & 0x3) << 29; - sw_w32(v, rtl_table_data(r, 0)); - - v = rt->attr.hit ? BIT(22) : 0; - v |= (rt->attr.action & 0x3) << 18; - v |= (rt->nh.id & 0x7ff) << 7; - v |= rt->attr.ttl_dec ? BIT(6) : 0; - v |= rt->attr.ttl_check ? BIT(5) : 0; - v |= rt->attr.dst_null ? BIT(6) : 0; - v |= rt->attr.qos_as ? BIT(6) : 0; - v |= rt->attr.qos_prio & 0x7; - v |= rt->prefix_len == 0 ? BIT(20) : 0; /* set default route bit */ - - /* set bit mask for entry type always to 0x3 */ - sw_w32(0x3 << 29, rtl_table_data(r, 5)); - - switch (rt->attr.type) { - case 0: /* IPv4 Unicast route */ - sw_w32(0, rtl_table_data(r, 1)); - sw_w32(0, rtl_table_data(r, 2)); - sw_w32(0, rtl_table_data(r, 3)); - sw_w32(rt->dst_ip, rtl_table_data(r, 4)); - - v |= rt->prefix_len == 32 ? BIT(21) : 0; /* set host-route bit */ - ip4_m = inet_make_mask(rt->prefix_len); - sw_w32(0, rtl_table_data(r, 6)); - sw_w32(0, rtl_table_data(r, 7)); - sw_w32(0, rtl_table_data(r, 8)); - sw_w32(ip4_m, rtl_table_data(r, 9)); - break; - case 2: /* IPv6 Unicast route */ - sw_w32(rt->dst_ip6.s6_addr32[0], rtl_table_data(r, 1)); - sw_w32(rt->dst_ip6.s6_addr32[1], rtl_table_data(r, 2)); - sw_w32(rt->dst_ip6.s6_addr32[2], rtl_table_data(r, 3)); - sw_w32(rt->dst_ip6.s6_addr32[3], rtl_table_data(r, 4)); - - v |= rt->prefix_len == 128 ? BIT(21) : 0; /* set host-route bit */ - - rtl930x_net6_mask(rt->prefix_len, &ip6_m); - - sw_w32(ip6_m.s6_addr32[0], rtl_table_data(r, 6)); - sw_w32(ip6_m.s6_addr32[1], rtl_table_data(r, 7)); - sw_w32(ip6_m.s6_addr32[2], rtl_table_data(r, 8)); - sw_w32(ip6_m.s6_addr32[3], rtl_table_data(r, 9)); - break; - case 1: /* IPv4 Multicast route */ - case 3: /* IPv6 Multicast route */ - pr_warn("%s: route type not supported\n", __func__); - rtl_table_release(r); - return; - } - sw_w32(v, rtl_table_data(r, 10)); - - pr_debug("%s: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", __func__, - sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), - sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)), - sw_r32(rtl_table_data(r, 6)), sw_r32(rtl_table_data(r, 7)), sw_r32(rtl_table_data(r, 8)), - sw_r32(rtl_table_data(r, 9)), sw_r32(rtl_table_data(r, 10))); - - rtl_table_write(r, idx); - rtl_table_release(r); -} - /* Get the destination MAC and L3 egress interface ID of a nexthop entry from * the SoC's L3_NEXTHOP table */ @@ -2893,8 +2740,6 @@ const struct rtldsa_config rtldsa_930x_cfg = { .packet_cntr_read = rtl930x_packet_cntr_read, .packet_cntr_clear = rtl930x_packet_cntr_clear, #ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD - .route_read = rtl930x_route_read, - .route_write = rtl930x_route_write, .host_route_write = rtl930x_host_route_write, .l3_setup = rtl930x_l3_setup, .set_l3_nexthop = rtl930x_set_l3_nexthop, From b440cd00d119229d6ba19bef1de810a39e8963d0 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sat, 27 Jun 2026 21:16:32 +0200 Subject: [PATCH 207/228] realtek: l3: move nexthop helper to new struture Another two layer 3 functions that do not belong into the DSA space. Move them over to the L3 configuration structure. Link: https://github.com/openwrt/openwrt/pull/23963 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 49 ++++++++++++++++++- .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 2 + .../drivers/net/dsa/rtl83xx/rtl-otto.h | 2 - .../drivers/net/dsa/rtl83xx/rtl930x.c | 41 ---------------- 4 files changed, 49 insertions(+), 45 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index 8270a765cd..9083ffe0b2 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -95,6 +95,49 @@ static void otto_l3_839x_route_write(struct otto_l3_ctrl *ctrl, int idx, struct rtl_table_release(r); } + +/* Destination MAC and L3 egress interface ID of a nexthop entry from the SoC's L3_NEXTHOP table */ +__maybe_unused +static void otto_l3_930x_get_nexthop(struct otto_l3_ctrl *ctrl, + int idx, u16 *dmac_id, u16 *interface) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 3); + u32 v; + + rtl_table_read(r, idx); + /* The table has a size of 1 register */ + v = sw_r32(rtl_table_data(r, 0)); + rtl_table_release(r); + + *dmac_id = (v >> 7) & 0x7fff; + *interface = v & 0x7f; +} + +/* + * Set the destination MAC and L3 egress interface ID for a nexthop entry in the SoC's L3_NEXTHOP + * table. The nexthop entry is identified by idx. dmac_id is the reference to the L2 entry in the + * L2 forwarding table, special values are + * 0x7ffe: TRAP2CPU + * 0x7ffd: TRAP2MASTERCPU + * 0x7fff: DMAC_ID_DROP + */ +__maybe_unused +static void otto_l3_930x_set_nexthop(struct otto_l3_ctrl *ctrl, + int idx, u16 dmac_id, u16 interface) +{ + /* Access L3_NEXTHOP table (3) via register RTL9300_TBL_1 */ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 3); + + dev_dbg(ctrl->dev, "Writing to L3_NEXTHOP table, index %d, dmac_id %d, interface %d\n", + idx, dmac_id, interface); + sw_w32(((dmac_id & 0x7fff) << 7) | (interface & 0x7f), rtl_table_data(r, 0)); + + dev_dbg(ctrl->dev, "value at index 0: %08x\n", sw_r32(rtl_table_data(r, 0))); + rtl_table_write(r, idx); + rtl_table_release(r); +} + + /* Read a prefix route entry from the L3_PREFIX_ROUTE_IPUC table * We currently only support IPv4 and IPv6 unicast route */ @@ -436,8 +479,8 @@ static int otto_l3_nexthop_update(struct otto_l3_ctrl *ctrl, __be32 ip_addr, u64 r->pr.fwd_act = PIE_ACT_ROUTE_UC; } - if (priv->r->set_l3_nexthop) - priv->r->set_l3_nexthop(r->nh.id, r->nh.l2_id, r->nh.if_id); + if (ctrl->cfg->set_nexthop) + ctrl->cfg->set_nexthop(ctrl, r->nh.id, r->nh.l2_id, r->nh.if_id); if (r->pr.id < 0) { r->pr.packet_cntr = rtl83xx_packet_cntr_alloc(priv); @@ -933,6 +976,8 @@ const struct otto_l3_config otto_l3_839x_cfg = { const struct otto_l3_config otto_l3_930x_cfg = { #ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD + .get_nexthop = otto_l3_930x_get_nexthop, + .set_nexthop = otto_l3_930x_set_nexthop, .route_read = otto_l3_930x_route_read, .route_write = otto_l3_930x_route_write, #endif diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index e92cc47fba..6c8d0e730b 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -6,6 +6,8 @@ #include "rtl-otto.h" struct otto_l3_config { + void (*get_nexthop)(struct otto_l3_ctrl *ctrl, int idx, u16 *dmac_id, u16 *interface); + void (*set_nexthop)(struct otto_l3_ctrl *ctrl, int idx, u16 dmac_id, u16 interface); void (*route_read)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt); void (*route_write)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt); }; diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index 6cd5b9aa2c..36a6641b8b 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -1439,8 +1439,6 @@ struct rtldsa_config { void (*packet_cntr_clear)(int counter); void (*host_route_write)(int idx, struct otto_l3_route *rt); int (*l3_setup)(struct rtl838x_switch_priv *priv); - void (*set_l3_nexthop)(int idx, u16 dmac_id, u16 interface); - void (*get_l3_nexthop)(int idx, u16 *dmac_id, u16 *interface); u64 (*get_l3_egress_mac)(u32 idx); void (*set_l3_egress_mac)(u32 idx, u64 mac); int (*find_l3_slot)(struct otto_l3_route *rt, bool must_exist); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c index de0cef88b4..fd11e3adfe 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c @@ -1460,24 +1460,6 @@ static int rtl930x_find_l3_slot(struct otto_l3_route *rt, bool must_exist) return -1; } -/* Get the destination MAC and L3 egress interface ID of a nexthop entry from - * the SoC's L3_NEXTHOP table - */ -static void rtl930x_get_l3_nexthop(int idx, u16 *dmac_id, u16 *interface) -{ - u32 v; - /* Read L3_NEXTHOP table (3) via register RTL9300_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 3); - - rtl_table_read(r, idx); - /* The table has a size of 1 register */ - v = sw_r32(rtl_table_data(r, 0)); - rtl_table_release(r); - - *dmac_id = (v >> 7) & 0x7fff; - *interface = v & 0x7f; -} - // Currently not used // static int rtl930x_l3_mtu_del(struct rtl838x_switch_priv *priv, int mtu) // { @@ -1562,27 +1544,6 @@ static void rtl930x_get_l3_nexthop(int idx, u16 *dmac_id, u16 *interface) // } // } -/* Set the destination MAC and L3 egress interface ID for a nexthop entry in the SoC's - * L3_NEXTHOP table. The nexthop entry is identified by idx. - * dmac_id is the reference to the L2 entry in the L2 forwarding table, special values are - * 0x7ffe: TRAP2CPU - * 0x7ffd: TRAP2MASTERCPU - * 0x7fff: DMAC_ID_DROP - */ -static void rtl930x_set_l3_nexthop(int idx, u16 dmac_id, u16 interface) -{ - /* Access L3_NEXTHOP table (3) via register RTL9300_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 3); - - pr_debug("%s: Writing to L3_NEXTHOP table, index %d, dmac_id %d, interface %d\n", - __func__, idx, dmac_id, interface); - sw_w32(((dmac_id & 0x7fff) << 7) | (interface & 0x7f), rtl_table_data(r, 0)); - - pr_debug("%s: %08x\n", __func__, sw_r32(rtl_table_data(r, 0))); - rtl_table_write(r, idx); - rtl_table_release(r); -} - #endif /* CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD */ static void rtl930x_pie_lookup_enable(struct rtl838x_switch_priv *priv, int index) @@ -2742,8 +2703,6 @@ const struct rtldsa_config rtldsa_930x_cfg = { #ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD .host_route_write = rtl930x_host_route_write, .l3_setup = rtl930x_l3_setup, - .set_l3_nexthop = rtl930x_set_l3_nexthop, - .get_l3_nexthop = rtl930x_get_l3_nexthop, .get_l3_egress_mac = rtl930x_get_l3_egress_mac, .set_l3_egress_mac = rtl930x_set_l3_egress_mac, .find_l3_slot = rtl930x_find_l3_slot, From 0738b151eb30bbf6f166dab45cc40c60aef882db Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sat, 27 Jun 2026 21:39:23 +0200 Subject: [PATCH 208/228] realtek: l3: move route_lookup_hw over to layer 3 structure Another layer 3 function that needs a new home. As always convert the code to dev_...() logging. Link: https://github.com/openwrt/openwrt/pull/23963 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 51 ++++++++++++++++- .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 1 + .../drivers/net/dsa/rtl83xx/rtl-otto.h | 1 - .../drivers/net/dsa/rtl83xx/rtl930x.c | 55 ------------------- 4 files changed, 50 insertions(+), 58 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index 9083ffe0b2..f6b9d0f10a 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -222,6 +222,52 @@ static void otto_l3_930x_net6_mask(int prefix_len, struct in6_addr *ip6_m) ip6_m->s6_addr[o] |= b ? 0xff00 >> b : 0x00; } +/* + * Look up the index of a prefix route in the routing table CAM for unicast IPv4/6 routes + * using hardware offload. + */ +__maybe_unused +static int otto_l3_930x_route_lookup_hw(struct otto_l3_ctrl *ctrl, struct otto_l3_route *rt) +{ + struct in6_addr ip6_m; + u32 ip4_m, v; + + if (rt->attr.type == 1 || rt->attr.type == 3) /* Hardware only supports UC routes */ + return -1; + + sw_w32_mask(0x3 << 19, rt->attr.type, RTL930X_L3_HW_LU_KEY_CTRL); + if (rt->attr.type) { /* IPv6 */ + otto_l3_930x_net6_mask(rt->prefix_len, &ip6_m); + for (int i = 0; i < 4; i++) + sw_w32(rt->dst_ip6.s6_addr32[0] & ip6_m.s6_addr32[0], + RTL930X_L3_HW_LU_KEY_IP_CTRL + (i << 2)); + } else { /* IPv4 */ + ip4_m = inet_make_mask(rt->prefix_len); + sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL); + sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 4); + sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 8); + v = rt->dst_ip & ip4_m; + dev_dbg(ctrl->dev, "searching for %pI4\n", &v); + sw_w32(v, RTL930X_L3_HW_LU_KEY_IP_CTRL + 12); + } + + /* Execute CAM lookup in SoC */ + sw_w32(BIT(15), RTL930X_L3_HW_LU_CTRL); + + /* Wait until execute bit clears and result is ready */ + do { + v = sw_r32(RTL930X_L3_HW_LU_CTRL); + } while (v & BIT(15)); + + dev_dbg(ctrl->dev, "found: %d, index: %d\n", !!(v & BIT(14)), v & 0x1ff); + + /* Test if search successful (BIT 14 set) */ + if (v & BIT(14)) + return v & 0x1ff; + + return -1; +} + /* Write a prefix route into the routing table CAM at position idx * Currently only IPv4 and IPv6 unicast routes are supported */ @@ -551,8 +597,8 @@ static void otto_l3_route_remove(struct otto_l3_ctrl *ctrl, struct otto_l3_route clear_bit(r->id - MAX_ROUTES, priv->host_route_use_bm); } else { /* If there is a HW representation of the route, delete it */ - if (priv->r->route_lookup_hw) { - id = priv->r->route_lookup_hw(r); + if (ctrl->cfg->route_lookup_hw) { + id = ctrl->cfg->route_lookup_hw(ctrl, r); dev_info(ctrl->dev, "Got id for prefix route: %d\n", id); r->attr.valid = false; ctrl->cfg->route_write(ctrl, id, r); @@ -978,6 +1024,7 @@ const struct otto_l3_config otto_l3_930x_cfg = { #ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD .get_nexthop = otto_l3_930x_get_nexthop, .set_nexthop = otto_l3_930x_set_nexthop, + .route_lookup_hw = otto_l3_930x_route_lookup_hw, .route_read = otto_l3_930x_route_read, .route_write = otto_l3_930x_route_write, #endif diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index 6c8d0e730b..78c2c4d5bd 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -8,6 +8,7 @@ struct otto_l3_config { void (*get_nexthop)(struct otto_l3_ctrl *ctrl, int idx, u16 *dmac_id, u16 *interface); void (*set_nexthop)(struct otto_l3_ctrl *ctrl, int idx, u16 dmac_id, u16 interface); + int (*route_lookup_hw)(struct otto_l3_ctrl *ctrl, struct otto_l3_route *rt); void (*route_read)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt); void (*route_write)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_route *rt); }; diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index 36a6641b8b..02732b241e 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -1442,7 +1442,6 @@ struct rtldsa_config { u64 (*get_l3_egress_mac)(u32 idx); void (*set_l3_egress_mac)(u32 idx, u64 mac); int (*find_l3_slot)(struct otto_l3_route *rt, bool must_exist); - int (*route_lookup_hw)(struct otto_l3_route *rt); void (*get_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m); void (*set_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m); void (*set_l3_egress_intf)(int idx, struct rtl838x_l3_intf *intf); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c index fd11e3adfe..2e09d091f6 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c @@ -1265,16 +1265,6 @@ static u32 rtl930x_l3_hash4(u32 ip, int algorithm, bool move_dip) // return hash; // } -static void rtl930x_net6_mask(int prefix_len, struct in6_addr *ip6_m) -{ - int o, b; - /* Define network mask */ - o = prefix_len >> 3; - b = prefix_len & 0x7; - memset(ip6_m->s6_addr, 0xff, o); - ip6_m->s6_addr[o] |= b ? 0xff00 >> b : 0x00; -} - /* Read a host route entry from the table using its index * We currently only support IPv4 and IPv6 unicast route */ @@ -1382,50 +1372,6 @@ out: rtl_table_release(r); } -/* Look up the index of a prefix route in the routing table CAM for unicast IPv4/6 routes - * using hardware offload. - */ -static int rtl930x_route_lookup_hw(struct otto_l3_route *rt) -{ - u32 ip4_m, v; - struct in6_addr ip6_m; - - if (rt->attr.type == 1 || rt->attr.type == 3) /* Hardware only supports UC routes */ - return -1; - - sw_w32_mask(0x3 << 19, rt->attr.type, RTL930X_L3_HW_LU_KEY_CTRL); - if (rt->attr.type) { /* IPv6 */ - rtl930x_net6_mask(rt->prefix_len, &ip6_m); - for (int i = 0; i < 4; i++) - sw_w32(rt->dst_ip6.s6_addr32[0] & ip6_m.s6_addr32[0], - RTL930X_L3_HW_LU_KEY_IP_CTRL + (i << 2)); - } else { /* IPv4 */ - ip4_m = inet_make_mask(rt->prefix_len); - sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL); - sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 4); - sw_w32(0, RTL930X_L3_HW_LU_KEY_IP_CTRL + 8); - v = rt->dst_ip & ip4_m; - pr_debug("%s: searching for %pI4\n", __func__, &v); - sw_w32(v, RTL930X_L3_HW_LU_KEY_IP_CTRL + 12); - } - - /* Execute CAM lookup in SoC */ - sw_w32(BIT(15), RTL930X_L3_HW_LU_CTRL); - - /* Wait until execute bit clears and result is ready */ - do { - v = sw_r32(RTL930X_L3_HW_LU_CTRL); - } while (v & BIT(15)); - - pr_debug("%s: found: %d, index: %d\n", __func__, !!(v & BIT(14)), v & 0x1ff); - - /* Test if search successful (BIT 14 set) */ - if (v & BIT(14)) - return v & 0x1ff; - - return -1; -} - static int rtl930x_find_l3_slot(struct otto_l3_route *rt, bool must_exist) { int slot_width, algorithm, addr, idx; @@ -2706,7 +2652,6 @@ const struct rtldsa_config rtldsa_930x_cfg = { .get_l3_egress_mac = rtl930x_get_l3_egress_mac, .set_l3_egress_mac = rtl930x_set_l3_egress_mac, .find_l3_slot = rtl930x_find_l3_slot, - .route_lookup_hw = rtl930x_route_lookup_hw, .get_l3_router_mac = rtl930x_get_l3_router_mac, .set_l3_router_mac = rtl930x_set_l3_router_mac, .set_l3_egress_intf = rtl930x_set_l3_egress_intf, From 23e5161399b8fb98a0a440858f73f30aad0340d5 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sat, 27 Jun 2026 22:05:52 +0200 Subject: [PATCH 209/228] realtek: l3: move router MAC helpers to layer 3 ecosystem The router MAC helpers and their structures belong to layer 3. Move them over to the new source file. Link: https://github.com/openwrt/openwrt/pull/23963 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 84 ++++++++++++++++++- .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 22 +++++ .../drivers/net/dsa/rtl83xx/rtl-otto.h | 21 ----- .../drivers/net/dsa/rtl83xx/rtl930x.c | 75 ----------------- 4 files changed, 102 insertions(+), 100 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index f6b9d0f10a..1d8390da3c 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -95,6 +95,80 @@ static void otto_l3_839x_route_write(struct otto_l3_ctrl *ctrl, int idx, struct rtl_table_release(r); } +/* + * Reads a MAC entry for L3 termination as entry point for routing from the hardware table. + * idx is the index into the L3_ROUTER_MAC table + */ +__maybe_unused +static void otto_l3_930x_get_router_mac(struct otto_l3_ctrl *ctrl, + u32 idx, struct otto_l3_router_mac *m) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0); + u32 v, w; + + rtl_table_read(r, idx); + /* The table has a size of 7 registers, 64 entries */ + v = sw_r32(rtl_table_data(r, 0)); + w = sw_r32(rtl_table_data(r, 3)); + m->valid = !!(v & BIT(20)); + if (!m->valid) + goto out; + + m->p_type = !!(v & BIT(19)); + m->p_id = (v >> 13) & 0x3f; /* trunk id of port */ + m->vid = v & 0xfff; + m->vid_mask = w & 0xfff; + m->action = sw_r32(rtl_table_data(r, 6)) & 0x7; + m->mac_mask = ((((u64)sw_r32(rtl_table_data(r, 5))) << 32) & 0xffffffffffffULL) | + (sw_r32(rtl_table_data(r, 4))); + m->mac = ((((u64)sw_r32(rtl_table_data(r, 1))) << 32) & 0xffffffffffffULL) | + (sw_r32(rtl_table_data(r, 2))); + /* Bits L3_INTF and BMSK_L3_INTF are 0 */ + +out: + rtl_table_release(r); +} + +/* + * Writes a MAC entry for L3 termination as entry point for routing into the hardware table + * idx is the index into the L3_ROUTER_MAC table + */ +__maybe_unused +static void otto_l3_930x_set_router_mac(struct otto_l3_ctrl *ctrl, + u32 idx, struct otto_l3_router_mac *m) +{ + struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0); + u32 v, w; + + /* The table has a size of 7 registers, 64 entries */ + v = BIT(20); /* mac entry valid, port type is 0: individual */ + v |= (m->p_id & 0x3f) << 13; + v |= (m->vid & 0xfff); /* Set the interface_id to the vlan id */ + + w = m->vid_mask; + w |= (m->p_id_mask & 0x3f) << 13; + + sw_w32(v, rtl_table_data(r, 0)); + sw_w32(w, rtl_table_data(r, 3)); + + /* Set MAC address, L3_INTF (bit 12 in register 1) needs to be 0 */ + sw_w32((u32)(m->mac), rtl_table_data(r, 2)); + sw_w32(m->mac >> 32, rtl_table_data(r, 1)); + + /* Set MAC address mask, BMSK_L3_INTF (bit 12 in register 5) needs to be 0 */ + sw_w32((u32)(m->mac_mask >> 32), rtl_table_data(r, 4)); + sw_w32((u32)m->mac_mask, rtl_table_data(r, 5)); + + sw_w32(m->action & 0x7, rtl_table_data(r, 6)); + + dev_dbg(ctrl->dev, "writing index %d: %08x %08x %08x %08x %08x %08x %08x\n", idx, + sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), + sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)), + sw_r32(rtl_table_data(r, 6)) + ); + rtl_table_write(r, idx); + rtl_table_release(r); +} /* Destination MAC and L3 egress interface ID of a nexthop entry from the SoC's L3_NEXTHOP table */ __maybe_unused @@ -389,12 +463,12 @@ static int otto_l3_port_dev_lower_find(struct net_device *dev, struct otto_l3_ct static int otto_l3_alloc_router_mac(struct otto_l3_ctrl *ctrl, u64 mac) { struct rtl838x_switch_priv *priv = ctrl->priv; - struct rtl93xx_rt_mac m; + struct otto_l3_router_mac m; int free_mac = -1; mutex_lock(&priv->reg_mutex); for (int i = 0; i < MAX_ROUTER_MACS; i++) { - priv->r->get_l3_router_mac(i, &m); + ctrl->cfg->get_router_mac(ctrl, i, &m); if (free_mac < 0 && !m.valid) { free_mac = i; continue; @@ -420,7 +494,7 @@ static int otto_l3_alloc_router_mac(struct otto_l3_ctrl *ctrl, u64 mac) m.vid_mask = 0; /* ... so mask needs to be 0 */ m.mac_mask = 0xffffffffffffULL; /* We want an exact match of the interface MAC */ m.action = L3_FORWARD; /* Route the packet */ - priv->r->set_l3_router_mac(free_mac, &m); + ctrl->cfg->set_router_mac(ctrl, free_mac, &m); mutex_unlock(&priv->reg_mutex); @@ -755,7 +829,7 @@ static int otto_l3_fib_add_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifi route->prefix_len = info->dst_len; route->nh.rvid = vlan; - if (priv->r->set_l3_router_mac) { + if (ctrl->cfg->set_router_mac) { u64 mac = ether_addr_to_u64(ndev->dev_addr); dev_dbg(ctrl->dev, "Local route and router MAC %pM\n", ndev->dev_addr); @@ -1022,6 +1096,8 @@ const struct otto_l3_config otto_l3_839x_cfg = { const struct otto_l3_config otto_l3_930x_cfg = { #ifdef CONFIG_NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD + .get_router_mac = otto_l3_930x_get_router_mac, + .set_router_mac = otto_l3_930x_set_router_mac, .get_nexthop = otto_l3_930x_get_nexthop, .set_nexthop = otto_l3_930x_set_nexthop, .route_lookup_hw = otto_l3_930x_route_lookup_hw, diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index 78c2c4d5bd..1440b7c0ed 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -5,7 +5,29 @@ #include "rtl-otto.h" +/* An entry in the RTL93XX SoC's ROUTER_MAC tables setting up a termination point + * for the L3 routing system. Packets arriving and matching an entry in this table + * will be considered for routing. + * Mask fields state whether the corresponding data fields matter for matching + */ +struct otto_l3_router_mac { + bool valid; /* Valid or not */ + bool p_type; /* Individual (0) or trunk (1) port */ + bool p_mask; /* Whether the port type is used */ + u8 p_id; + u8 p_id_mask; /* Mask for the port */ + u8 action; /* Routing action performed: 0: FORWARD, 1: DROP, 2: TRAP2CPU */ + /* 3: COPY2CPU, 4: TRAP2MASTERCPU, 5: COPY2MASTERCPU, 6: HARDDROP */ + u16 vid; + u16 vid_mask; + u64 mac; /* MAC address used as source MAC in the routed packet */ + u64 mac_mask; +}; + + struct otto_l3_config { + void (*get_router_mac)(struct otto_l3_ctrl *ctrl, u32 idx, struct otto_l3_router_mac *m); + void (*set_router_mac)(struct otto_l3_ctrl *ctrl, u32 idx, struct otto_l3_router_mac *m); void (*get_nexthop)(struct otto_l3_ctrl *ctrl, int idx, u16 *dmac_id, u16 *interface); void (*set_nexthop)(struct otto_l3_ctrl *ctrl, int idx, u16 dmac_id, u16 interface); int (*route_lookup_hw)(struct otto_l3_ctrl *ctrl, struct otto_l3_route *rt); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h index 02732b241e..393ad060cb 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl-otto.h @@ -1285,25 +1285,6 @@ struct rtl838x_l3_intf { u8 ip6_pbr_icmp_redirect; }; -/* An entry in the RTL93XX SoC's ROUTER_MAC tables setting up a termination point - * for the L3 routing system. Packets arriving and matching an entry in this table - * will be considered for routing. - * Mask fields state whether the corresponding data fields matter for matching - */ -struct rtl93xx_rt_mac { - bool valid; /* Valid or not */ - bool p_type; /* Individual (0) or trunk (1) port */ - bool p_mask; /* Whether the port type is used */ - u8 p_id; - u8 p_id_mask; /* Mask for the port */ - u8 action; /* Routing action performed: 0: FORWARD, 1: DROP, 2: TRAP2CPU */ - /* 3: COPY2CPU, 4: TRAP2MASTERCPU, 5: COPY2MASTERCPU, 6: HARDDROP */ - u16 vid; - u16 vid_mask; - u64 mac; /* MAC address used as source MAC in the routed packet */ - u64 mac_mask; -}; - struct rtl838x_switch_priv; struct rtl83xx_flow { @@ -1442,8 +1423,6 @@ struct rtldsa_config { u64 (*get_l3_egress_mac)(u32 idx); void (*set_l3_egress_mac)(u32 idx, u64 mac); int (*find_l3_slot)(struct otto_l3_route *rt, bool must_exist); - void (*get_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m); - void (*set_l3_router_mac)(u32 idx, struct rtl93xx_rt_mac *m); void (*set_l3_egress_intf)(int idx, struct rtl838x_l3_intf *intf); void (*set_receive_management_action)(int port, rma_ctrl_t type, action_type_t action); void (*led_init)(struct rtl838x_switch_priv *priv); diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c index 2e09d091f6..a2acd1bf27 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/rtl930x.c @@ -2054,79 +2054,6 @@ static void rtl930x_set_l3_egress_intf(int idx, struct rtl838x_l3_intf *intf) rtl_table_release(r); } -/* Reads a MAC entry for L3 termination as entry point for routing - * from the hardware table - * idx is the index into the L3_ROUTER_MAC table - */ -static void rtl930x_get_l3_router_mac(u32 idx, struct rtl93xx_rt_mac *m) -{ - u32 v, w; - /* Read L3_ROUTER_MAC table (0) via register RTL9300_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0); - - rtl_table_read(r, idx); - /* The table has a size of 7 registers, 64 entries */ - v = sw_r32(rtl_table_data(r, 0)); - w = sw_r32(rtl_table_data(r, 3)); - m->valid = !!(v & BIT(20)); - if (!m->valid) - goto out; - - m->p_type = !!(v & BIT(19)); - m->p_id = (v >> 13) & 0x3f; /* trunk id of port */ - m->vid = v & 0xfff; - m->vid_mask = w & 0xfff; - m->action = sw_r32(rtl_table_data(r, 6)) & 0x7; - m->mac_mask = ((((u64)sw_r32(rtl_table_data(r, 5))) << 32) & 0xffffffffffffULL) | - (sw_r32(rtl_table_data(r, 4))); - m->mac = ((((u64)sw_r32(rtl_table_data(r, 1))) << 32) & 0xffffffffffffULL) | - (sw_r32(rtl_table_data(r, 2))); - /* Bits L3_INTF and BMSK_L3_INTF are 0 */ - -out: - rtl_table_release(r); -} - -/* Writes a MAC entry for L3 termination as entry point for routing - * into the hardware table - * idx is the index into the L3_ROUTER_MAC table - */ -static void rtl930x_set_l3_router_mac(u32 idx, struct rtl93xx_rt_mac *m) -{ - u32 v, w; - /* Read L3_ROUTER_MAC table (0) via register RTL9300_TBL_1 */ - struct table_reg *r = rtl_table_get(RTL9300_TBL_1, 0); - - /* The table has a size of 7 registers, 64 entries */ - v = BIT(20); /* mac entry valid, port type is 0: individual */ - v |= (m->p_id & 0x3f) << 13; - v |= (m->vid & 0xfff); /* Set the interface_id to the vlan id */ - - w = m->vid_mask; - w |= (m->p_id_mask & 0x3f) << 13; - - sw_w32(v, rtl_table_data(r, 0)); - sw_w32(w, rtl_table_data(r, 3)); - - /* Set MAC address, L3_INTF (bit 12 in register 1) needs to be 0 */ - sw_w32((u32)(m->mac), rtl_table_data(r, 2)); - sw_w32(m->mac >> 32, rtl_table_data(r, 1)); - - /* Set MAC address mask, BMSK_L3_INTF (bit 12 in register 5) needs to be 0 */ - sw_w32((u32)(m->mac_mask >> 32), rtl_table_data(r, 4)); - sw_w32((u32)m->mac_mask, rtl_table_data(r, 5)); - - sw_w32(m->action & 0x7, rtl_table_data(r, 6)); - - pr_debug("%s writing index %d: %08x %08x %08x %08x %08x %08x %08x\n", __func__, idx, - sw_r32(rtl_table_data(r, 0)), sw_r32(rtl_table_data(r, 1)), sw_r32(rtl_table_data(r, 2)), - sw_r32(rtl_table_data(r, 3)), sw_r32(rtl_table_data(r, 4)), sw_r32(rtl_table_data(r, 5)), - sw_r32(rtl_table_data(r, 6)) - ); - rtl_table_write(r, idx); - rtl_table_release(r); -} - /* Get the Destination-MAC of an L3 egress interface or the Source MAC for routed packets * from the SoC's L3_EGR_INTF_MAC table * Indexes 0-2047 are DMACs, 2048+ are SMACs @@ -2652,8 +2579,6 @@ const struct rtldsa_config rtldsa_930x_cfg = { .get_l3_egress_mac = rtl930x_get_l3_egress_mac, .set_l3_egress_mac = rtl930x_set_l3_egress_mac, .find_l3_slot = rtl930x_find_l3_slot, - .get_l3_router_mac = rtl930x_get_l3_router_mac, - .set_l3_router_mac = rtl930x_set_l3_router_mac, .set_l3_egress_intf = rtl930x_set_l3_egress_intf, #endif .led_init = rtl930x_led_init, From 6e9fd1c3ba6bf486a044ed9d640a77dd50b6cbc2 Mon Sep 17 00:00:00 2001 From: John Audia Date: Thu, 21 May 2026 08:53:52 -0400 Subject: [PATCH 210/228] elfutils: update to 0.195 Patches rebased: - 003-libintl-compatibility.patch - 005-build_only_libs.patch - 006-Fix-build-on-aarch64-musl.patch - 101-no-fts.patch Patches removed due being upstreamed: - 007-add-libeu-symbols-to-libelf.patch - 008-fix-autoconf-ENABLE_IMA_VERIFICATION.patch - 009-fix-null-dereference-with-lto.patch - 102-fix-potential-deref-of-null-error.patch Note that this release is needed in order to build against GCC 16.1 https://github.com/openwrt/openwrt/pull/23194 Release notes from 0.192 to 0.195: https://inbox.sourceware.org/elfutils-devel/CAJDtP-RjuT13zehLgSvz9TnwQZ1VYPOS=q_kuut5a2g+KLamgw@mail.gmail.com/T/ https://inbox.sourceware.org/elfutils-devel/CAJDtP-S0rYAOZQeDZvMtPkQztgK9RboWtYwpqNLCNGNdaSGn-A@mail.gmail.com/T/ https://inbox.sourceware.org/elfutils-devel/CAJDtP-Qok4ViNzvrr28WgkCCqrFH0iAZStiD8C7nbpDhrPzLWA@mail.gmail.com/T/ Signed-off-by: John Audia Link: https://github.com/openwrt/openwrt/pull/23468 Signed-off-by: Hauke Mehrtens --- package/libs/elfutils/Makefile | 6 +- .../patches/003-libintl-compatibility.patch | 2 +- .../patches/005-build_only_libs.patch | 8 +- .../006-Fix-build-on-aarch64-musl.patch | 2 +- .../007-add-libeu-symbols-to-libelf.patch | 31 --- ...fix-autoconf-ENABLE_IMA_VERIFICATION.patch | 24 --- .../009-fix-null-dereference-with-lto.patch | 193 ------------------ .../libs/elfutils/patches/101-no-fts.patch | 2 +- ...02-fix-potential-deref-of-null-error.patch | 55 ----- 9 files changed, 10 insertions(+), 313 deletions(-) delete mode 100644 package/libs/elfutils/patches/007-add-libeu-symbols-to-libelf.patch delete mode 100644 package/libs/elfutils/patches/008-fix-autoconf-ENABLE_IMA_VERIFICATION.patch delete mode 100644 package/libs/elfutils/patches/009-fix-null-dereference-with-lto.patch delete mode 100644 package/libs/elfutils/patches/102-fix-potential-deref-of-null-error.patch diff --git a/package/libs/elfutils/Makefile b/package/libs/elfutils/Makefile index 4507a01089..030392b54e 100644 --- a/package/libs/elfutils/Makefile +++ b/package/libs/elfutils/Makefile @@ -7,13 +7,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=elfutils -PKG_VERSION:=0.192 -PKG_RELEASE:=2 +PKG_VERSION:=0.195 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://sourceware.org/$(PKG_NAME)/ftp/$(PKG_VERSION) \ https://mirrors.kernel.org/sourceware/$(PKG_NAME)/$(PKG_VERSION) -PKG_HASH:=616099beae24aba11f9b63d86ca6cc8d566d968b802391334c91df54eab416b4 +PKG_HASH:=37629fdf7f1f3dc2818e138fca2b8094177d6c2d0f701d3bb650a561218dc026 PKG_MAINTAINER:=Luiz Angelo Daros de Luca PKG_LICENSE:=GPL-2.0-or-later LGPL-3.0-or-later diff --git a/package/libs/elfutils/patches/003-libintl-compatibility.patch b/package/libs/elfutils/patches/003-libintl-compatibility.patch index eda9f2204a..655f8f3cfe 100644 --- a/package/libs/elfutils/patches/003-libintl-compatibility.patch +++ b/package/libs/elfutils/patches/003-libintl-compatibility.patch @@ -11,7 +11,7 @@ Requires.private: zlib @LIBZSTD@ --- a/configure.ac +++ b/configure.ac -@@ -728,6 +728,9 @@ dnl AM_GNU_GETTEXT_REQUIRE_VERSION suppo +@@ -788,6 +788,9 @@ dnl AM_GNU_GETTEXT_REQUIRE_VERSION suppo AM_GNU_GETTEXT_VERSION([0.19.6]) AM_GNU_GETTEXT_REQUIRE_VERSION([0.19.6]) diff --git a/package/libs/elfutils/patches/005-build_only_libs.patch b/package/libs/elfutils/patches/005-build_only_libs.patch index 177ac659e6..2d68b3e7a5 100644 --- a/package/libs/elfutils/patches/005-build_only_libs.patch +++ b/package/libs/elfutils/patches/005-build_only_libs.patch @@ -1,11 +1,11 @@ --- a/Makefile.am +++ b/Makefile.am -@@ -27,7 +27,7 @@ AM_MAKEFLAGS = --no-print-directory +@@ -29,7 +29,7 @@ AM_MAKEFLAGS = --no-print-directory pkginclude_HEADERS = version.h - SUBDIRS = config lib libelf libcpu backends libebl libdwelf libdwfl libdw \ -- libasm debuginfod src po doc tests -+ libasm + SUBDIRS = config lib libelf libcpu backends libebl libdwelf libdwfl \ +- libdwfl_stacktrace libdw libasm debuginfod src po doc tests ++ libdwfl_stacktrace libdw libasm EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING SECURITY \ COPYING COPYING-GPLV2 COPYING-LGPLV3 CONDUCT diff --git a/package/libs/elfutils/patches/006-Fix-build-on-aarch64-musl.patch b/package/libs/elfutils/patches/006-Fix-build-on-aarch64-musl.patch index a7786ed2c0..bd387e7a66 100644 --- a/package/libs/elfutils/patches/006-Fix-build-on-aarch64-musl.patch +++ b/package/libs/elfutils/patches/006-Fix-build-on-aarch64-musl.patch @@ -33,7 +33,7 @@ Signed-off-by: Hongxu Jia # include # include # include -@@ -94,7 +94,7 @@ aarch64_set_initial_registers_tid (pid_t +@@ -115,7 +115,7 @@ aarch64_set_initial_registers_tid (pid_t Dwarf_Word dwarf_fregs[32]; for (int r = 0; r < 32; r++) diff --git a/package/libs/elfutils/patches/007-add-libeu-symbols-to-libelf.patch b/package/libs/elfutils/patches/007-add-libeu-symbols-to-libelf.patch deleted file mode 100644 index 23489b5625..0000000000 --- a/package/libs/elfutils/patches/007-add-libeu-symbols-to-libelf.patch +++ /dev/null @@ -1,31 +0,0 @@ -From f5d6e088f84dd05278c4698a21cbf1ff4569978d Mon Sep 17 00:00:00 2001 -From: Mark Wielaard -Date: Tue, 22 Oct 2024 15:03:42 +0200 -Subject: [PATCH] libelf: Add libeu objects to libelf.a static archive - -libelf might use some symbols from libeu.a, specifically the eu-search -wrappers. But we don't ship libeu.a separately. So include the libeu -objects in the libelf.a archive to facilitate static linking. - - * libelf/Makefile.am (libeu_objects): New variable. - (libelf_a_LIBADD): New, add libeu_objects. - -https://sourceware.org/bugzilla/show_bug.cgi?id=32293 - -Signed-off-by: Mark Wielaard ---- - libelf/Makefile.am | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/libelf/Makefile.am -+++ b/libelf/Makefile.am -@@ -122,6 +122,9 @@ libelf.so: $(srcdir)/libelf.map $(libelf - @$(textrel_check) - $(AM_V_at)ln -fs $@ $@.$(VERSION) - -+libeu_objects = $(shell $(AR) t ../lib/libeu.a) -+libelf_a_LIBADD = $(addprefix ../lib/,$(libeu_objects)) -+ - install: install-am libelf.so - $(mkinstalldirs) $(DESTDIR)$(libdir) - $(INSTALL_PROGRAM) libelf.so $(DESTDIR)$(libdir)/libelf-$(PACKAGE_VERSION).so diff --git a/package/libs/elfutils/patches/008-fix-autoconf-ENABLE_IMA_VERIFICATION.patch b/package/libs/elfutils/patches/008-fix-autoconf-ENABLE_IMA_VERIFICATION.patch deleted file mode 100644 index e5732d2b08..0000000000 --- a/package/libs/elfutils/patches/008-fix-autoconf-ENABLE_IMA_VERIFICATION.patch +++ /dev/null @@ -1,24 +0,0 @@ -From f3c664d069d81a4872a1ec8241ee709f37c53e9c Mon Sep 17 00:00:00 2001 -From: Aaron Merey -Date: Tue, 29 Oct 2024 14:16:57 -0400 -Subject: [PATCH] configure.ac: Fix ENABLE_IMA_VERIFICATION conditional - -Fix test statement for ENABLE_IMA_VERIFICATION always evalutating to -false due to a missing 'x'. - -Signed-off-by: Aaron Merey ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/configure.ac -+++ b/configure.ac -@@ -895,7 +895,7 @@ AS_IF([test "x$enable_debuginfod" != "xn - AM_CONDITIONAL([DEBUGINFOD],[test "x$enable_debuginfod" = "xyes"]) - AS_IF([test "x$enable_debuginfod_ima_verification" = "xyes"],AC_DEFINE([ENABLE_IMA_VERIFICATION],[1],[Build IMA verification])) - AS_IF([test "x$have_libarchive" = "xyes"],AC_DEFINE([HAVE_LIBARCHIVE],[1],[Define to 1 if libarchive is available])) --AM_CONDITIONAL([ENABLE_IMA_VERIFICATION],[test "$enable_debuginfod_ima_verification" = "xyes"]) -+AM_CONDITIONAL([ENABLE_IMA_VERIFICATION],[test "x$enable_debuginfod_ima_verification" = "xyes"]) - AM_CONDITIONAL([OLD_LIBMICROHTTPD],[test "x$old_libmicrohttpd" = "xyes"]) - - dnl for /etc/profile.d/elfutils.{csh,sh} diff --git a/package/libs/elfutils/patches/009-fix-null-dereference-with-lto.patch b/package/libs/elfutils/patches/009-fix-null-dereference-with-lto.patch deleted file mode 100644 index 1179a1e1a0..0000000000 --- a/package/libs/elfutils/patches/009-fix-null-dereference-with-lto.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 8707194a9f2f0b13e53041b03ebfdbdbd2942e43 Mon Sep 17 00:00:00 2001 -From: Mark Wielaard -Date: Tue, 5 Nov 2024 23:31:14 +0100 -Subject: [PATCH 1/1] libelf: Only fetch shdr once in elf_compress[_gnu] - -Some compilers assume the second call to elf[32|64]_getshdr can fail -and produce error: potential null pointer dereference. Just store the -result of the first call and reuse (when not NULL). - - * libelf/elf_compress.c (elf_compress): Store getshdr result in - a shdr union var. - * libelf/elf_compress_gnu.c (): Likewise - -https://sourceware.org/bugzilla/show_bug.cgi?id=32311 - -Signed-off-by: Mark Wielaard ---- - libelf/elf_compress.c | 55 +++++++++++++++++++++------------------ - libelf/elf_compress_gnu.c | 45 ++++++++++++++------------------ - 2 files changed, 48 insertions(+), 52 deletions(-) - ---- a/libelf/elf_compress.c -+++ b/libelf/elf_compress.c -@@ -584,25 +584,30 @@ elf_compress (Elf_Scn *scn, int type, un - Elf64_Xword sh_flags; - Elf64_Word sh_type; - Elf64_Xword sh_addralign; -+ union shdr -+ { -+ Elf32_Shdr *s32; -+ Elf64_Shdr *s64; -+ } shdr; - if (elfclass == ELFCLASS32) - { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- if (shdr == NULL) -+ shdr.s32 = elf32_getshdr (scn); -+ if (shdr.s32 == NULL) - return -1; - -- sh_flags = shdr->sh_flags; -- sh_type = shdr->sh_type; -- sh_addralign = shdr->sh_addralign; -+ sh_flags = shdr.s32->sh_flags; -+ sh_type = shdr.s32->sh_type; -+ sh_addralign = shdr.s32->sh_addralign; - } - else - { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- if (shdr == NULL) -+ shdr.s64 = elf64_getshdr (scn); -+ if (shdr.s64 == NULL) - return -1; - -- sh_flags = shdr->sh_flags; -- sh_type = shdr->sh_type; -- sh_addralign = shdr->sh_addralign; -+ sh_flags = shdr.s64->sh_flags; -+ sh_type = shdr.s64->sh_type; -+ sh_addralign = shdr.s64->sh_addralign; - } - - if ((sh_flags & SHF_ALLOC) != 0) -@@ -679,17 +684,17 @@ elf_compress (Elf_Scn *scn, int type, un - correctly and ignored when SHF_COMPRESSED is set. */ - if (elfclass == ELFCLASS32) - { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- shdr->sh_size = new_size; -- shdr->sh_addralign = __libelf_type_align (ELFCLASS32, ELF_T_CHDR); -- shdr->sh_flags |= SHF_COMPRESSED; -+ shdr.s32->sh_size = new_size; -+ shdr.s32->sh_addralign = __libelf_type_align (ELFCLASS32, -+ ELF_T_CHDR); -+ shdr.s32->sh_flags |= SHF_COMPRESSED; - } - else - { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- shdr->sh_size = new_size; -- shdr->sh_addralign = __libelf_type_align (ELFCLASS64, ELF_T_CHDR); -- shdr->sh_flags |= SHF_COMPRESSED; -+ shdr.s64->sh_size = new_size; -+ shdr.s64->sh_addralign = __libelf_type_align (ELFCLASS64, -+ ELF_T_CHDR); -+ shdr.s64->sh_flags |= SHF_COMPRESSED; - } - - __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_CHDR); -@@ -731,17 +736,15 @@ elf_compress (Elf_Scn *scn, int type, un - correctly and ignored when SHF_COMPRESSED is set. */ - if (elfclass == ELFCLASS32) - { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- shdr->sh_size = scn->zdata_size; -- shdr->sh_addralign = scn->zdata_align; -- shdr->sh_flags &= ~SHF_COMPRESSED; -+ shdr.s32->sh_size = scn->zdata_size; -+ shdr.s32->sh_addralign = scn->zdata_align; -+ shdr.s32->sh_flags &= ~SHF_COMPRESSED; - } - else - { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- shdr->sh_size = scn->zdata_size; -- shdr->sh_addralign = scn->zdata_align; -- shdr->sh_flags &= ~SHF_COMPRESSED; -+ shdr.s64->sh_size = scn->zdata_size; -+ shdr.s64->sh_addralign = scn->zdata_align; -+ shdr.s64->sh_flags &= ~SHF_COMPRESSED; - } - - __libelf_reset_rawdata (scn, scn->zdata_base, ---- a/libelf/elf_compress_gnu.c -+++ b/libelf/elf_compress_gnu.c -@@ -59,25 +59,30 @@ elf_compress_gnu (Elf_Scn *scn, int infl - Elf64_Xword sh_flags; - Elf64_Word sh_type; - Elf64_Xword sh_addralign; -+ union shdr -+ { -+ Elf32_Shdr *s32; -+ Elf64_Shdr *s64; -+ } shdr; - if (elfclass == ELFCLASS32) - { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- if (shdr == NULL) -+ shdr.s32 = elf32_getshdr (scn); -+ if (shdr.s32 == NULL) - return -1; - -- sh_flags = shdr->sh_flags; -- sh_type = shdr->sh_type; -- sh_addralign = shdr->sh_addralign; -+ sh_flags = shdr.s32->sh_flags; -+ sh_type = shdr.s32->sh_type; -+ sh_addralign = shdr.s32->sh_addralign; - } - else - { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- if (shdr == NULL) -+ shdr.s64 = elf64_getshdr (scn); -+ if (shdr.s64 == NULL) - return -1; - -- sh_flags = shdr->sh_flags; -- sh_type = shdr->sh_type; -- sh_addralign = shdr->sh_addralign; -+ sh_flags = shdr.s64->sh_flags; -+ sh_type = shdr.s64->sh_type; -+ sh_addralign = shdr.s64->sh_addralign; - } - - /* Allocated sections, or sections that are already are compressed -@@ -122,15 +127,9 @@ elf_compress_gnu (Elf_Scn *scn, int infl - sh_flags won't have a SHF_COMPRESSED hint in the GNU format. - Just adjust the sh_size. */ - if (elfclass == ELFCLASS32) -- { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- shdr->sh_size = new_size; -- } -+ shdr.s32->sh_size = new_size; - else -- { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- shdr->sh_size = new_size; -- } -+ shdr.s64->sh_size = new_size; - - __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_BYTE); - -@@ -187,15 +186,9 @@ elf_compress_gnu (Elf_Scn *scn, int infl - sh_flags won't have a SHF_COMPRESSED hint in the GNU format. - Just adjust the sh_size. */ - if (elfclass == ELFCLASS32) -- { -- Elf32_Shdr *shdr = elf32_getshdr (scn); -- shdr->sh_size = size; -- } -+ shdr.s32->sh_size = size; - else -- { -- Elf64_Shdr *shdr = elf64_getshdr (scn); -- shdr->sh_size = size; -- } -+ shdr.s64->sh_size = size; - - __libelf_reset_rawdata (scn, buf_out, size, sh_addralign, - __libelf_data_type (&ehdr, sh_type, diff --git a/package/libs/elfutils/patches/101-no-fts.patch b/package/libs/elfutils/patches/101-no-fts.patch index 29a6c4b36c..3483ef203e 100644 --- a/package/libs/elfutils/patches/101-no-fts.patch +++ b/package/libs/elfutils/patches/101-no-fts.patch @@ -72,7 +72,7 @@ struct parse_opt *opt = state->hook; --- a/libdwfl/Makefile.am +++ b/libdwfl/Makefile.am -@@ -50,7 +50,7 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_en +@@ -51,7 +51,7 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_en argp-std.c find-debuginfo.c \ dwfl_build_id_find_elf.c \ dwfl_build_id_find_debuginfo.c \ diff --git a/package/libs/elfutils/patches/102-fix-potential-deref-of-null-error.patch b/package/libs/elfutils/patches/102-fix-potential-deref-of-null-error.patch deleted file mode 100644 index 6710e4ef9c..0000000000 --- a/package/libs/elfutils/patches/102-fix-potential-deref-of-null-error.patch +++ /dev/null @@ -1,55 +0,0 @@ -strip.c: Pointer `arhdr` created at strip.c:2741 and then dereferenced without NULL-check. -The same situation for the `arhdr` pointer at the objdump.c:313 and -the `h` pointer at the readelf.c:13545. - -Triggers found by static analyzer Svace. - -Signed-off-by: Maks Mishin ---- - src/objdump.c | 5 +++++ - src/readelf.c | 5 +++++ - src/strip.c | 5 +++++ - 3 files changed, 15 insertions(+) - ---- a/src/objdump.c -+++ b/src/objdump.c -@@ -311,6 +311,11 @@ handle_ar (int fd, Elf *elf, const char - { - /* The the header for this element. */ - Elf_Arhdr *arhdr = elf_getarhdr (subelf); -+ if (arhdr == NULL) -+ { -+ printf ("cannot get arhdr: %s\n", elf_errmsg (-1)); -+ exit (1); -+ } - - /* Skip over the index entries. */ - if (strcmp (arhdr->ar_name, "/") != 0 ---- a/src/readelf.c -+++ b/src/readelf.c -@@ -13543,6 +13543,11 @@ dump_archive_index (Elf *elf, const char - as_off, fname, elf_errmsg (-1)); - - const Elf_Arhdr *h = elf_getarhdr (subelf); -+ if (h == NULL) -+ { -+ printf ("cannot get arhdr: %s\n", elf_errmsg (-1)); -+ exit (1); -+ } - - printf (_("Archive member '%s' contains:\n"), h->ar_name); - ---- a/src/strip.c -+++ b/src/strip.c -@@ -2739,6 +2739,11 @@ handle_ar (int fd, Elf *elf, const char - { - /* The the header for this element. */ - Elf_Arhdr *arhdr = elf_getarhdr (subelf); -+ if (arhdr == NULL) -+ { -+ printf ("cannot get arhdr: %s\n", elf_errmsg (-1)); -+ exit (1); -+ } - - if (elf_kind (subelf) == ELF_K_ELF) - result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL); From b882cd76eceb29072cae11d40d5d0f6133ec7042 Mon Sep 17 00:00:00 2001 From: John Audia Date: Sat, 27 Jun 2026 14:17:02 -0400 Subject: [PATCH 211/228] linux-firmware: update 20260622 % git log --no-merges --pretty=oneline --abbrev-commit 20260519...20260622 0798ed4d1dcd nxp: add firmware for IW61x WiFi device 431c5ea014f9 mediatek MT7922: update bluetooth firmware to 20260605203811 2d7053937558 mediatek MT7925: update bluetooth firmware to 20260605184935 bd1c66cfef5f linux-firmware: update firmware for MT7925 WiFi device 1a2f6aca3c9c linux-firmware: update firmware for MT7922 WiFi device f0fcc1d248cb amdgpu: DMCUB updates for various ASICs 85780e744984 qcom: add LPAICP firmware for shikra platform aa2c4a6cee7f qcom: Add qdsp6sw firmware for shikra platform ddaa2620f48f linux-firmware: update firmware for MT7986 17485a680e53 linux-firmware: update firmware for MT7981 17ca86eb15f6 linux-firmware: update firmware for MT7996 1cccfa6b8073 linux-firmware: update firmware for MT7992 f8cd3f6faae7 linux-firmware: update firmware for MT7990 10bf07f6404f qcom: Update ADSP firmware for Kaanapali platform c5774bd79997 qcom: update ADSP firmware for glymur platform dd571d3fe15f qcom: update CDSP firmware for glymur platform 3dcf6778d29c QCA: Add bluetooth firmware nvm files for USI/NFA725B aba75bb237b6 linux-firmware: Add firmware file for Intel BlazarIW 4a32fece257f linux-firmware: Update firmware file for Intel BlazarU core 7bf0edbf74a2 linux-firmware: Update firmware file for Intel BlazarI core 431e7f03d2c7 linux-firmware: Update firmware file for Intel Scorpius core 6ed5e5aa4a02 qcom: update ADSP firmware for qcs615 platform 8df26c69bbe9 cirrus: cs42l45: Update CS42L45 SDCA codec firmware for Dell laptops ce8c0b7174fc rtl_bt: Update RTL8852A BT USB firmware to 0x244F_91B6 861ddef6ec1c realtek: rt1321: Update the patch code to v1.10 2d2d180a1cc0 amdgpu: DMCUB updates for various ASICs ca254b03dc5b QCA: Update Bluetooth WCN3950 firmware 1.3.0-00108 to 1.3.0-00184 acb740a9bfaf qcom: update CDSP firmware for shikra platform 71f496945eb7 qcom: Update ADSP firmware for Glymur platform 1e6faaf837ae Remove any files with unknown licenses 7ad9f3aaa96b AGENTS.md, README: address second round of MR review acda46b96b76 README: document AI assisted contribution convention 57ab6873b2fd AGENTS.md: clarify areas raised in MR review 45fb99aef1cd Add AGENTS.md for AI coding agents e930d3975f23 LICENSES: update GPL-2.0 text and references 430c892e7460 LICENSES: rename GPL-3 to GPL-3.0-only 847ba27f6c18 LICENSES: rename Apache-2 to Apache-2.0 1221848f2376 Move firmware licenses to a LICENSES/ directory 72a012ee810d qcom: update ADSP firmware for sm8750 platform 5118abf637cb QCA: Update Bluetooth WCN6856 firmware 2.1.0-00666 to 2.1.0-00669 f7feff550c56 qcom: Update DSP firmware for qcs8300 platform 3bfa40aaa331 qcom: Update DSP firmware for sa8775p platform 4d575d919be3 amdgpu: Update DMCUB fw for DCN314 47bffda9bb89 amdgpu: revert yellow carp VCN firmware 268bb3d259a0 amdgpu: revert vangogh VCN firmware 8d5b020868c6 amdgpu: revert sienna cichlid VCN firmware 640aa1db8e7f amdgpu: revert navy flounder VCN firmware 4ade9cf51e4d amdgpu: revert dimgrey cavefish VCN firmware f1ea993bb900 amdgpu: revert beige_goby VCN firmware 2110f8af357d qcom: update CDSP firmware for x1e80100 platform e108a9ab7a94 cirrus: cs35l56: Add firmware for Cirrus Amps for a Dell laptop 5670228453b1 linux-firmware: Add RCA firmware files for tas257x projects a329a4c520af intel_vpu: Update NPU firmware 075a812eca30 cirrus: cs35l63: Add Cirrus CS35L63 firmware mappings for various Dell laptops d33a9c6d7661 cirrus: cs35l56: Update firmware for Cirrus Amps for a couple of Lenovo laptops 1a794cdf93cd cirrus: cs35l56: Add firmware for Cirrus Amps for a Lenovo laptop 282d83cf7a32 QCA: Add BCS calibration binary for QCC2072 5ce19c7bb06f QCA: Update Bluetooth firmware for QCC2072 UART interface c8c796dcdd3b amdgpu: DMCUB updates for various ASICs 4f6efdd350e4 rtl_nic: add firmware rtl8261c.bin for RTL8261c 831ea4af30e1 cirrus: cs35l56: Add Cirrus CS35L56 firmware mappings for two Dell laptops 830ba56b93d3 i915: Xe3LPD DMC v2.36 563b533d4f56 i915: Xe3LPD_3002 DMC v2.31 9357f2b5010a i915: Xe3p_LPD DMC v2.37 df472a73b917 cirrus: cs35l56: Add firmware for Cirrus Amps for some Lenovo laptops 542ad48830f6 cirrus: cs42l45: Update CS42L45 SDCA codec firmware for Lenovo laptops dd7b12f0d458 cirrus: cs42l45: Add CS42L45 SDCA codec firmware for Lenovo laptops ef77d60eebba qcom: Add gpu firmwares for Shikra chipset 72a09795db65 cirrus: cs35l56: Update firmware for Cirrus Amps for some Dell laptops f97831a28950 rtw89: 8852b: update fw to v0.29.29.18 d0bf0bc94f2d rtw89: 8852bt: update fw to v0.29.122.2 d531e213dea8 amdgpu: Update gc 11.0.1 microcode Signed-off-by: John Audia Link: https://github.com/openwrt/openwrt/pull/23974 Signed-off-by: Hauke Mehrtens --- package/firmware/linux-firmware/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/firmware/linux-firmware/Makefile b/package/firmware/linux-firmware/Makefile index 74b23de710..61fce656b6 100644 --- a/package/firmware/linux-firmware/Makefile +++ b/package/firmware/linux-firmware/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=linux-firmware -PKG_VERSION:=20260519 +PKG_VERSION:=20260622 PKG_RELEASE:=1 PKG_SOURCE_URL:=@KERNEL/linux/kernel/firmware PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_HASH:=b14e7197a290a7e5569f5ef790cde289bddc47e32126f2eb262a8e677fc39727 +PKG_HASH:=2b9d8a358e76eb766588609135e53fa548b902c551daae33ee32f26f25e60dbb PKG_MAINTAINER:=Felix Fietkau From 3c26b9fd64b53e57294fd29adc0dfe8f211bfa2b Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 28 Jun 2026 16:48:13 +0200 Subject: [PATCH 212/228] ubus: update to Git HEAD (2026-06-28) 24864e7840b3 ubusd_id: use GRND_INSECURE to avoid blocking boot on getrandom() Fixes: https://github.com/openwrt/ubus/issues/21 Signed-off-by: Hauke Mehrtens --- package/system/ubus/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/system/ubus/Makefile b/package/system/ubus/Makefile index 936a2984fa..3b31d346ca 100644 --- a/package/system/ubus/Makefile +++ b/package/system/ubus/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/ubus.git -PKG_SOURCE_DATE:=2026-05-23 -PKG_SOURCE_VERSION:=795b32bb96b611493f423666236e9c1e49e0736c -PKG_MIRROR_HASH:=7fdc7c111b21277603448f20b15ebbf3adeab6e3f51fb99f216587f3b5998fbd +PKG_SOURCE_DATE:=2026-06-28 +PKG_SOURCE_VERSION:=24864e7840b3a02a9ef76284a373f6b2f00b8a9b +PKG_MIRROR_HASH:=33072c12e6d9a1fd59e3774f029575df61393b5a465486726609ff59314b8a84 PKG_ABI_VERSION:=$(call abi_version_str,$(PKG_SOURCE_DATE)) CMAKE_INSTALL:=1 From 0d892f17c92ad3693d438282188a2d99b9dadeee Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 14 Jun 2026 12:50:20 -0700 Subject: [PATCH 213/228] fs: rpsec: add missing modules for CRYPTO_KRB5 Upstream selects these for CRYPTO_KRB5. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23794 Signed-off-by: Jonas Jelonek --- package/kernel/linux/modules/fs.mk | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/package/kernel/linux/modules/fs.mk b/package/kernel/linux/modules/fs.mk index 59e7b99634..ff132aa712 100644 --- a/package/kernel/linux/modules/fs.mk +++ b/package/kernel/linux/modules/fs.mk @@ -491,14 +491,15 @@ define KernelPackage/fs-nfs-common-rpcsec TITLE:=NFS Secure RPC DEPENDS:= \ +kmod-fs-nfs-common \ - +kmod-crypto-des \ - +kmod-crypto-cbc \ - +kmod-crypto-cts \ - +kmod-crypto-md5 \ - +kmod-crypto-sha1 \ + +kmod-crypto-manager \ + +kmod-crypto-authenc \ +kmod-crypto-hmac \ - +kmod-crypto-ecb \ - +kmod-crypto-arc4 + +kmod-crypto-cmac \ + +kmod-crypto-sha1 \ + +kmod-crypto-sha256 \ + +kmod-crypto-sha512 \ + +kmod-crypto-cbc \ + +kmod-crypto-cts KCONFIG:= \ CONFIG_SUNRPC_GSS \ CONFIG_RPCSEC_GSS_KRB5 From beb880855c3f5011b2a9cf5428061d7ce62a74ff Mon Sep 17 00:00:00 2001 From: Mieczyslaw Nalewaj Date: Sat, 27 Jun 2026 17:13:09 +0200 Subject: [PATCH 214/228] rtl8367b: fix RTL8367S-VB vlan mc memory handling The RTL8367S-VB (Family D) uses a software-emulated VLAN MC table (emu_vlanmc) since it lacks hardware support for the VLAN MC registers used by earlier chips. - Add missing NULL check after kzalloc() in rtl8367b_init_regs() to prevent NULL pointer dereference on allocation failure. - Add missing kfree(smi->emu_vlanmc) in rtl8367b_remove() to prevent memory leak on driver unload. Signed-off-by: Mieczyslaw Nalewaj Link: https://github.com/openwrt/openwrt/pull/23970 Signed-off-by: Jonas Jelonek --- target/linux/generic/files/drivers/net/phy/rtl8367b.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/target/linux/generic/files/drivers/net/phy/rtl8367b.c b/target/linux/generic/files/drivers/net/phy/rtl8367b.c index d3dc6af39a..850392cc7c 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8367b.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8367b.c @@ -565,7 +565,11 @@ static int rtl8367b_init_regs(struct rtl8366_smi *smi) count = ARRAY_SIZE(rtl8367c_initvals); if ((smi->rtl8367b_chip == RTL8367B_CHIP_RTL8367S_VB) && (smi->emu_vlanmc == NULL)) { smi->emu_vlanmc = kzalloc(sizeof(struct rtl8366_vlan_mc) * smi->num_vlan_mc, GFP_KERNEL); - dev_info(smi->parent, "alloc vlan mc emulator"); + if (!smi->emu_vlanmc) { + dev_err(smi->parent, "failed to allocate vlan mc emulator\n"); + return -ENOMEM; + } + dev_info(smi->parent, "alloc vlan mc emulator\n"); } break; default: @@ -1586,6 +1590,7 @@ static void rtl8367b_remove(struct platform_device *pdev) rtl8367b_switch_cleanup(smi); platform_set_drvdata(pdev, NULL); rtl8366_smi_cleanup(smi); + kfree(smi->emu_vlanmc); kfree(smi); } } From 27ca0a3eefbfa09834681c06400ca06aa9f258d1 Mon Sep 17 00:00:00 2001 From: John Audia Date: Sat, 27 Jun 2026 10:56:56 -0400 Subject: [PATCH 215/228] kernel: bump 6.18 to 6.18.37 Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.18.37 All patches automatically rebased via update_kernel.sh Build system: x86/64 Build-tested: x86/64-glibc Run-tested: x86/64-glibc Signed-off-by: John Audia Link: https://github.com/openwrt/openwrt/pull/23971 Signed-off-by: Hauke Mehrtens --- .../generic/hack-6.18/721-net-add-packet-mangeling.patch | 2 +- target/linux/generic/kernel-6.18 | 4 ++-- .../patches-6.18/0403-pwm-fix-period-calculation.patch | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/target/linux/generic/hack-6.18/721-net-add-packet-mangeling.patch b/target/linux/generic/hack-6.18/721-net-add-packet-mangeling.patch index 0db4849715..3c19fe1782 100644 --- a/target/linux/generic/hack-6.18/721-net-add-packet-mangeling.patch +++ b/target/linux/generic/hack-6.18/721-net-add-packet-mangeling.patch @@ -97,7 +97,7 @@ Signed-off-by: Felix Fietkau help --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -3870,6 +3870,11 @@ static int xmit_one(struct sk_buff *skb, +@@ -3871,6 +3871,11 @@ static int xmit_one(struct sk_buff *skb, if (dev_nit_active_rcu(dev)) dev_queue_xmit_nit(skb, dev); diff --git a/target/linux/generic/kernel-6.18 b/target/linux/generic/kernel-6.18 index 1efcc0734e..efbfe51433 100644 --- a/target/linux/generic/kernel-6.18 +++ b/target/linux/generic/kernel-6.18 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.18 = .36 -LINUX_KERNEL_HASH-6.18.36 = fbab86c9f471c81075b280cca30bd85d790c060063a1245859b6344b07c9c44e +LINUX_VERSION-6.18 = .37 +LINUX_KERNEL_HASH-6.18.37 = a83cd200e6646db52866b8309e9137b9e9048b613cbda10ced2b811aae125255 diff --git a/target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch b/target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch index 78bce5fa11..2606b767fc 100644 --- a/target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch +++ b/target/linux/qualcommbe/patches-6.18/0403-pwm-fix-period-calculation.patch @@ -41,8 +41,6 @@ Signed-off-by: Kenneth Kasilag drivers/pwm/pwm-ipq.c | 122 ++++++++++++++---- 1 file changed, 108 insertions(+), 14 deletions(-) -diff --git a/drivers/pwm/pwm-ipq.c b/drivers/pwm/pwm-ipq.c -index 3619091b546d12..0b616def6ae4cd 100644 --- a/drivers/pwm/pwm-ipq.c +++ b/drivers/pwm/pwm-ipq.c @@ -89,10 +89,10 @@ static int ipq_pwm_apply(struct pwm_chip @@ -164,3 +162,4 @@ index 3619091b546d12..0b616def6ae4cd 100644 + hi_div = (u64)hi_dur * (pre_div + 1); state->duty_cycle = DIV64_U64_ROUND_UP(hi_div * NSEC_PER_SEC, ipq_chip->clk_rate); + From c1ba308aa63ea1fd57dbe916a0550660510085b1 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 20 Jun 2026 14:40:59 -0700 Subject: [PATCH 216/228] lantiq: vrx518_ep: use module_pci_driver macro Use = {} to get rid of the memset so that init is just pci_register_driver with extra prints. Assisted-by: Opencode:Big-Pickle Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23976 Signed-off-by: Jonas Jelonek --- package/kernel/lantiq/vrx518_ep/src/ep.c | 35 ++---------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/package/kernel/lantiq/vrx518_ep/src/ep.c b/package/kernel/lantiq/vrx518_ep/src/ep.c index 40fc9d3629..ab350b672d 100644 --- a/package/kernel/lantiq/vrx518_ep/src/ep.c +++ b/package/kernel/lantiq/vrx518_ep/src/ep.c @@ -52,13 +52,8 @@ module_param(pcie_switch_exist, bool, 0644); MODULE_PARM_DESC(pcie_switch_exist, "pcie switch existed or not"); static const char dc_ep_driver_name[] = "vrx518"; -static const char dc_ep_driver_version[] = DRV_VERSION; -static const char dc_ep_driver_string[] = - "Intel(R) SmartPHY DSL(VRX518) PCIe EP/ACA Driver"; -static const char dc_ep_copyright[] = - "Copyright (c) 2016 Intel Corporation."; -static struct dc_ep_info g_dc_ep_info; +static struct dc_ep_info g_dc_ep_info = {}; static DEFINE_SPINLOCK(dc_ep_lock); static inline void reset_assert_device(struct dc_ep_dev *dev, u32 bits) @@ -729,7 +724,7 @@ static const struct pci_device_id dc_ep_id_table[] = { MODULE_DEVICE_TABLE(pci, dc_ep_id_table); static struct pci_driver dc_ep_driver = { - .name = (char *)dc_ep_driver_name, + .name = dc_ep_driver_name, .id_table = dc_ep_id_table, .probe = dc_ep_probe, .remove = dc_ep_remove, @@ -738,31 +733,7 @@ static struct pci_driver dc_ep_driver = { /* AER is controlled by RC */ }; -static int __init dc_ep_init(void) -{ - pr_info("%s - version %s\n", - dc_ep_driver_string, dc_ep_driver_version); - - pr_info("%s\n", dc_ep_copyright); - memset(&g_dc_ep_info, 0, sizeof(struct dc_ep_info)); - - if (pci_register_driver(&dc_ep_driver) < 0) { - pr_err("%s: No devices found, driver not installed.\n", - __func__); - return -ENODEV; - } - return 0; -} -module_init(dc_ep_init); - -static void __exit dc_ep_exit(void) -{ - pci_unregister_driver(&dc_ep_driver); - - pr_info("%s: %s driver unloaded\n", __func__, - dc_ep_driver_name); -} -module_exit(dc_ep_exit); +module_pci_driver(dc_ep_driver); MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) SmartPHY PCIe EP/ACA Driver"); From f33b49d0a7df7d6e92fb670cdbe2a789a0590a06 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sat, 27 Jun 2026 13:54:02 +0000 Subject: [PATCH 217/228] realtek: pcs: rtl930x: reduce calibration code nesting The calibration code is deeply nested with multiple function using numeric nesting. Though it tries to follow the SDK pattern, this makes it just unnecessarily complex and confusing. Dissolve some of this unneeded nesting, together with some minor cleanup here and there. Link: https://github.com/openwrt/openwrt/pull/23983 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 142 +++++------------- 1 file changed, 41 insertions(+), 101 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 68bcd26667..8f0902e8fb 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -2491,34 +2491,27 @@ static void rtpcs_930x_sds_do_rx_calibration_1(struct rtpcs_serdes *sds, /* --- 1.1.5 */ } -static void rtpcs_930x_sds_do_rx_calibration_2_1(struct rtpcs_serdes *sds) -{ - /* 1.2.1 ForegroundOffsetCal_Manual --- */ - - /* Gray config endis to 1 */ - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x02, 2, 2, 0x01); - - /* ForegroundOffsetCal_Manual(auto mode) */ - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 14, 14, 0x00); - - /* --- 1.2.1 */ -} - -static void rtpcs_930x_sds_do_rx_calibration_2_2(struct rtpcs_serdes *sds) -{ - /* Force Rx-Run = 0 */ - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 8, 8, 0x0); - - rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); -} - -static void rtpcs_930x_sds_do_rx_calibration_2_3(struct rtpcs_serdes *sds) +static void rtpcs_930x_sds_do_rx_calibration_2(struct rtpcs_serdes *sds) { struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); u32 fgcal_binary, fgcal_gray; u32 offset_range; - /* 1.2.3 Foreground Calibration --- */ + rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); + + /* ForegroundOffsetCal_Manual */ + + /* Gray config endis to 1 */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x02, 2, 2, 0x01); + + /* ForegroundOffsetCal_Manual(auto mode) */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 14, 14, 0x00); + + /* Force Rx-Run = 0 */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 8, 8, 0x0); + rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); + + /* Foreground Calibration --- */ for (int run = 0; run < 10; run++) { /* REG_DBGO_SEL */ @@ -2547,36 +2540,16 @@ static void rtpcs_930x_sds_do_rx_calibration_2_3(struct rtpcs_serdes *sds) offset_range++; rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 15, 14, offset_range); - rtpcs_930x_sds_do_rx_calibration_2_2(sds); + + /* Force Rx-Run = 0 */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 8, 8, 0x0); + rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); } - /* --- 1.2.3 */ } -static void rtpcs_930x_sds_do_rx_calibration_2(struct rtpcs_serdes *sds) -{ - rtpcs_930x_sds_rx_reset(sds, RTPCS_SDS_MODE_10GBASER); - rtpcs_930x_sds_do_rx_calibration_2_1(sds); - rtpcs_930x_sds_do_rx_calibration_2_2(sds); - rtpcs_930x_sds_do_rx_calibration_2_3(sds); -} - -static void rtpcs_930x_sds_rxcal_3_1(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - /* 1.3.1 --- */ - if (hw_mode != RTPCS_SDS_MODE_10GBASER && - hw_mode != RTPCS_SDS_MODE_1000BASEX && - hw_mode != RTPCS_SDS_MODE_SGMII) - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xc, 8, 8, 0); - - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x0); - rtpcs_930x_sds_rxcal_leq_manual(sds, false, 0); - - /* --- 1.3.1 */ -} - -static void rtpcs_930x_sds_rxcal_3_2(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) +__always_unused +static void rtpcs_930x_sds_do_rx_calibration_3(struct rtpcs_serdes *sds, + enum rtpcs_sds_mode hw_mode) { u32 sum10 = 0, avg10, int10; int dac_long_cable_offset; @@ -2593,8 +2566,12 @@ static void rtpcs_930x_sds_rxcal_3_2(struct rtpcs_serdes *sds, /* rtl9300_rxCaliConf_phy_myParam */ dac_long_cable_offset = 0; eq_hold_enabled = false; + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xc, 8, 8, 0x0); } + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x0); + rtpcs_930x_sds_rxcal_leq_manual(sds, false, 0); + if (hw_mode != RTPCS_SDS_MODE_10GBASER) pr_warn("%s: LEQ only valid for 10GR!\n", __func__); @@ -2641,79 +2618,41 @@ static void rtpcs_930x_sds_rxcal_3_2(struct rtpcs_serdes *sds, /* --- 1.3.2 */ } -__always_unused -static void rtpcs_930x_sds_do_rx_calibration_3(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) +static void rtpcs_930x_sds_do_rx_calibration_4(struct rtpcs_serdes *sds) { - rtpcs_930x_sds_rxcal_3_1(sds, hw_mode); + u32 tap0_list[4] = {0}; + u32 vth_list[2] = {0}; - if (hw_mode == RTPCS_SDS_MODE_10GBASER || - hw_mode == RTPCS_SDS_MODE_1000BASEX || - hw_mode == RTPCS_SDS_MODE_SGMII) - rtpcs_930x_sds_rxcal_3_2(sds, hw_mode); -} - -static void rtpcs_930x_sds_do_rx_calibration_4_1(struct rtpcs_serdes *sds) -{ - u32 vth_list[2] = {0, 0}; - u32 tap0_list[4] = {0, 0, 0, 0}; - - /* 1.4.1 --- */ + /* run VTH/TAP auto-adapt */ rtpcs_930x_sds_rxcal_vth_manual(sds, false, vth_list); rtpcs_930x_sds_rxcal_tap_manual(sds, 0, false, tap0_list); mdelay(200); - /* --- 1.4.2 */ -} - -static void rtpcs_930x_sds_do_rx_calibration_4_2(struct rtpcs_serdes *sds) -{ - u32 vth_list[2]; - u32 tap_list[4]; - - /* 1.4.2 --- */ - + /* manually set learned VTH */ rtpcs_930x_sds_rxcal_vth_get(sds, vth_list); rtpcs_930x_sds_rxcal_vth_manual(sds, true, vth_list); mdelay(100); - rtpcs_930x_sds_rxcal_tap_get(sds, 0, tap_list); - rtpcs_930x_sds_rxcal_tap_manual(sds, 0, true, tap_list); - - /* --- 1.4.2 */ + /* manually set learned TAP0 */ + rtpcs_930x_sds_rxcal_tap_get(sds, 0, tap0_list); + rtpcs_930x_sds_rxcal_tap_manual(sds, 0, true, tap0_list); } -static void rtpcs_930x_sds_do_rx_calibration_4(struct rtpcs_serdes *sds) -{ - rtpcs_930x_sds_do_rx_calibration_4_1(sds); - rtpcs_930x_sds_do_rx_calibration_4_2(sds); -} - -static void rtpcs_930x_sds_do_rx_calibration_5_2(struct rtpcs_serdes *sds) +static void rtpcs_930x_sds_do_rx_calibration_5(struct rtpcs_serdes *sds) { u32 tap1_list[4] = {0}; u32 tap2_list[4] = {0}; u32 tap3_list[4] = {0}; u32 tap4_list[4] = {0}; - /* 1.5.2 --- */ - + /* dfeTap1_4Enable true */ rtpcs_930x_sds_rxcal_tap_manual(sds, 1, false, tap1_list); rtpcs_930x_sds_rxcal_tap_manual(sds, 2, false, tap2_list); rtpcs_930x_sds_rxcal_tap_manual(sds, 3, false, tap3_list); rtpcs_930x_sds_rxcal_tap_manual(sds, 4, false, tap4_list); mdelay(30); - - /* --- 1.5.2 */ -} - -static void rtpcs_930x_sds_do_rx_calibration_5(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) -{ - if (hw_mode == RTPCS_SDS_MODE_10GBASER) /* dfeTap1_4Enable true */ - rtpcs_930x_sds_do_rx_calibration_5_2(sds); } static void rtpcs_930x_sds_do_rx_calibration_dfe_disable(struct rtpcs_serdes *sds) @@ -2739,18 +2678,19 @@ static void rtpcs_930x_sds_do_rx_calibration(struct rtpcs_serdes *sds, rtpcs_930x_sds_do_rx_calibration_1(sds, hw_mode); rtpcs_930x_sds_do_rx_calibration_2(sds); rtpcs_930x_sds_do_rx_calibration_4(sds); - rtpcs_930x_sds_do_rx_calibration_5(sds, hw_mode); - mdelay(20); /* Do this only for 10GR mode */ if (hw_mode == RTPCS_SDS_MODE_10GBASER) { + rtpcs_930x_sds_do_rx_calibration_5(sds); + mdelay(20); + latch_sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_0, 1, 2, 2); mdelay(1); latch_sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_0, 1, 2, 2); if (latch_sts) { rtpcs_930x_sds_do_rx_calibration_dfe_disable(sds); rtpcs_930x_sds_do_rx_calibration_4(sds); - rtpcs_930x_sds_do_rx_calibration_5(sds, hw_mode); + rtpcs_930x_sds_do_rx_calibration_5(sds); } } } From d5615c1df68cdf3ee35ede1202ff0e22261dd4b7 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sat, 27 Jun 2026 17:25:02 +0000 Subject: [PATCH 218/228] realtek: pcs: rtl930x: give some calibration functions meaningful names Adapted from the SDK, the calibration functions are just named after their sequential logic and with a numbering scheme. This doesn't help understanding what the code is doing. Instead, give some of them meaningful names where possible, revealing kind of a logical structure. Link: https://github.com/openwrt/openwrt/pull/23983 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 8f0902e8fb..9f03e6bd5c 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -2491,7 +2491,7 @@ static void rtpcs_930x_sds_do_rx_calibration_1(struct rtpcs_serdes *sds, /* --- 1.1.5 */ } -static void rtpcs_930x_sds_do_rx_calibration_2(struct rtpcs_serdes *sds) +static void rtpcs_930x_sds_rxcal_fgcal(struct rtpcs_serdes *sds) { struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); u32 fgcal_binary, fgcal_gray; @@ -2618,7 +2618,7 @@ static void rtpcs_930x_sds_do_rx_calibration_3(struct rtpcs_serdes *sds, /* --- 1.3.2 */ } -static void rtpcs_930x_sds_do_rx_calibration_4(struct rtpcs_serdes *sds) +static void rtpcs_930x_sds_rxcal_vth_tap0_adapt_lock(struct rtpcs_serdes *sds) { u32 tap0_list[4] = {0}; u32 vth_list[2] = {0}; @@ -2639,7 +2639,7 @@ static void rtpcs_930x_sds_do_rx_calibration_4(struct rtpcs_serdes *sds) rtpcs_930x_sds_rxcal_tap_manual(sds, 0, true, tap0_list); } -static void rtpcs_930x_sds_do_rx_calibration_5(struct rtpcs_serdes *sds) +static void rtpcs_930x_sds_rxcal_dfe_taps_adapt(struct rtpcs_serdes *sds) { u32 tap1_list[4] = {0}; u32 tap2_list[4] = {0}; @@ -2655,7 +2655,7 @@ static void rtpcs_930x_sds_do_rx_calibration_5(struct rtpcs_serdes *sds) mdelay(30); } -static void rtpcs_930x_sds_do_rx_calibration_dfe_disable(struct rtpcs_serdes *sds) +static void rtpcs_930x_sds_rxcal_dfe_disable(struct rtpcs_serdes *sds) { u32 tap1_list[4] = {0}; u32 tap2_list[4] = {0}; @@ -2676,21 +2676,21 @@ static void rtpcs_930x_sds_do_rx_calibration(struct rtpcs_serdes *sds, u32 latch_sts; rtpcs_930x_sds_do_rx_calibration_1(sds, hw_mode); - rtpcs_930x_sds_do_rx_calibration_2(sds); - rtpcs_930x_sds_do_rx_calibration_4(sds); + rtpcs_930x_sds_rxcal_fgcal(sds); + rtpcs_930x_sds_rxcal_vth_tap0_adapt_lock(sds); /* Do this only for 10GR mode */ if (hw_mode == RTPCS_SDS_MODE_10GBASER) { - rtpcs_930x_sds_do_rx_calibration_5(sds); + rtpcs_930x_sds_rxcal_dfe_taps_adapt(sds); mdelay(20); latch_sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_0, 1, 2, 2); mdelay(1); latch_sts = rtpcs_sds_read_bits(sds, PAGE_TGR_STD_0, 1, 2, 2); if (latch_sts) { - rtpcs_930x_sds_do_rx_calibration_dfe_disable(sds); - rtpcs_930x_sds_do_rx_calibration_4(sds); - rtpcs_930x_sds_do_rx_calibration_5(sds); + rtpcs_930x_sds_rxcal_dfe_disable(sds); + rtpcs_930x_sds_rxcal_vth_tap0_adapt_lock(sds); + rtpcs_930x_sds_rxcal_dfe_taps_adapt(sds); } } } From 8dd1c280aec92e67caa07a9031cbcfa85c8cbcad Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sat, 27 Jun 2026 17:50:12 +0000 Subject: [PATCH 219/228] realtek: pcs: store active media type in SerDes state Track the resolved media type in struct rtpcs_serdes alongside hw_mode, storing it as soon as rtpcs_sds_select_media() resolves it so all subsequent ops (set_hw_mode, activate, post_config) can access it. This is unused for now and will be used only in dead code in next patches. Though, this dead code is going to be used with subsequent patches. Link: https://github.com/openwrt/openwrt/pull/23983 Signed-off-by: Jonas Jelonek --- target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 9f03e6bd5c..49b93cdc21 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -294,6 +294,7 @@ struct rtpcs_serdes { s16 link_port[RTPCS_MAX_LINKS_PER_SDS]; enum rtpcs_sds_mode hw_mode; + enum rtpcs_sds_media media; u8 id; u8 num_of_links; bool first_start; @@ -4011,6 +4012,8 @@ static int rtpcs_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, if (ret < 0) return ret; + sds->media = sds_media; + ret = sds->ops->config_media(sds, sds_media, hw_mode); if (ret < 0) return ret; From 393d5b01fba4dbefcaed95c1938cc2b6c47e2dfb Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sat, 27 Jun 2026 19:23:05 +0000 Subject: [PATCH 220/228] realtek: pcs: rtl930x: fix LEQ calibration to use media type Replace the mode-based approximation in the LEQ adapt+lock step with proper media-based logic using the newly stored sds->media field. Those adjustments are based on SDK code and digging through some basics of signal conditioning. PCB connections route through an external PHY (PHY-attached); that PHY handles its own equalization so the SerDes LEQ is left in free-running auto-adapt with no correction offset. DAC and fiber SFP connect directly to the SerDes without an intermediate PHY and require a calibrated lock. Replace the SDK's dacLongCableOffset/eqHoldEnable variable pair with a single direct_serdes bool and encode the full per-media LEQ correction into one switch: fiber +3 (direct SerDes, no cable), DAC short +4 (base 3 + 1), DAC long +6 (base 3 + 3). Fix the MAXHOLD_EN bit (0x17[7]) and the 0x0c[8] write to be gated on direct_serdes; both were previously conditioned on PCB which is the PHY-attached case and thus wrong. Fix the LEQ lock to apply to all direct SerDes connections (DAC + fiber), not just PCB. Also drop the spurious dead-code branch that was an artifact of the original transplanting. No behavioral change because this particular function of calibration is not used right now but will be in the future. Link: https://github.com/openwrt/openwrt/pull/23983 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 91 +++++++++---------- 1 file changed, 41 insertions(+), 50 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 49b93cdc21..5ca0def0c3 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -2549,74 +2549,65 @@ static void rtpcs_930x_sds_rxcal_fgcal(struct rtpcs_serdes *sds) } __always_unused -static void rtpcs_930x_sds_do_rx_calibration_3(struct rtpcs_serdes *sds, - enum rtpcs_sds_mode hw_mode) +static void rtpcs_930x_sds_rxcal_leq_adapt_lock(struct rtpcs_serdes *sds) { - u32 sum10 = 0, avg10, int10; - int dac_long_cable_offset; - bool eq_hold_enabled; + /* + * SDK dacLongCableOffset / eqHoldEnable from rtl9300_rxCaliConf_serdes/phy_myParam. + * These distinguish direct SerDes connections (DAC, fiber SFP — no external PHY in + * the signal path) from PHY-attached ports (PCB traces to an external PHY). On + * PHY-attached ports the PHY handles its own equalization, so the SerDes LEQ is left + * in auto-adapt and no correction offset is needed. + */ + bool direct_serdes = sds->media == RTPCS_SDS_MEDIA_FIBER || + sds->media == RTPCS_SDS_MEDIA_DAC_SHORT || + sds->media == RTPCS_SDS_MEDIA_DAC_LONG; + u32 sum10 = 0, avg10; int i; - if (hw_mode == RTPCS_SDS_MODE_10GBASER || - hw_mode == RTPCS_SDS_MODE_1000BASEX || - hw_mode == RTPCS_SDS_MODE_SGMII) { - /* rtl9300_rxCaliConf_serdes_myParam */ - dac_long_cable_offset = 3; - eq_hold_enabled = true; - } else { - /* rtl9300_rxCaliConf_phy_myParam */ - dac_long_cable_offset = 0; - eq_hold_enabled = false; + /* 1.3.1: release LEQ auto-adapt, let it settle from zero */ + if (!direct_serdes) rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xc, 8, 8, 0x0); - } - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x0); rtpcs_930x_sds_rxcal_leq_manual(sds, false, 0); - if (hw_mode != RTPCS_SDS_MODE_10GBASER) - pr_warn("%s: LEQ only valid for 10GR!\n", __func__); - - /* 1.3.2 --- */ - + /* 1.3.2: sample the auto-adapted LEQ value 10 times over ~100ms */ for (i = 0; i < 10; i++) { sum10 += rtpcs_930x_sds_rxcal_leq_read(sds); mdelay(10); } + /* rounded average of where auto-adapt settled */ avg10 = (sum10 / 10) + (((sum10 % 10) >= 5) ? 1 : 0); - int10 = sum10 / 10; - pr_info("sum10:%u, avg10:%u, int10:%u", sum10, avg10, int10); + /* + * Empirical correction based on media type. + * Direct SerDes connections get a base offset of +3; DAC cables add further + * correction for their attenuation. PHY-attached (PCB) needs none. + */ + switch (sds->media) { + case RTPCS_SDS_MEDIA_FIBER: + avg10 += 3; + break; + case RTPCS_SDS_MEDIA_DAC_SHORT: + avg10 += 4; /* base 3 + 1 for short DAC */ + break; + case RTPCS_SDS_MEDIA_DAC_LONG: + avg10 += 6; /* base 3 + 3 for long DAC */ + break; + default: + break; + } - if (hw_mode == RTPCS_SDS_MODE_10GBASER || - hw_mode == RTPCS_SDS_MODE_1000BASEX || - hw_mode == RTPCS_SDS_MODE_SGMII) { - if (dac_long_cable_offset) { - rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, - dac_long_cable_offset); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, - eq_hold_enabled); - if (hw_mode == RTPCS_SDS_MODE_10GBASER) - rtpcs_930x_sds_rxcal_leq_manual(sds, - true, avg10); - } else { - if (sum10 >= 5) { - rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, 3); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x1); - if (hw_mode == RTPCS_SDS_MODE_10GBASER) - rtpcs_930x_sds_rxcal_leq_manual(sds, true, avg10); - } else { - rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, 0); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x1); - if (hw_mode == RTPCS_SDS_MODE_10GBASER) - rtpcs_930x_sds_rxcal_leq_manual(sds, true, avg10); - } - } + pr_info("sum10:%u, avg10:%u", sum10, avg10); + + /* lock LEQ at corrected value for direct SerDes; PHY-attached stays in auto-adapt */ + if (direct_serdes) { + rtpcs_930x_sds_rxcal_leq_offset_manual(sds, 1, 0); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x17, 7, 7, 0x1); + rtpcs_930x_sds_rxcal_leq_manual(sds, true, avg10); } pr_info("SDS %u LEQ = %u", sds->id, rtpcs_930x_sds_rxcal_leq_read(sds)); - - /* --- 1.3.2 */ } static void rtpcs_930x_sds_rxcal_vth_tap0_adapt_lock(struct rtpcs_serdes *sds) From 8b0ce8e4e33f7ff53a244fb11aa06d39f22586be Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Sun, 28 Jun 2026 09:55:18 +0000 Subject: [PATCH 221/228] realtek: pcs: rtl930x: simplify DCVS/VTH/TAP calibration helpers Reduce repetition in dcvs_manual, dcvs_get, vth_manual and tap_manual by hoisting the per-channel enable bit write out of per-case branches and encoding per-channel register/bit mappings as lookup tables where the pattern is uniform across channels. This also fixes two bugs in dcvs_get that were hidden in the switch: - DCVS1 read never populated dcvs_sign_out; it wrote the sign bit read (0x14[4:4]) into dcvs_coef_bin and then immediately overwrote it with the coefficient read, leaving the sign always zero for that channel. - DCVS3 assigned the manual bit read directly to a bool without the !! normalisation applied to all other cases. Link: https://github.com/openwrt/openwrt/pull/23983 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 277 +++++++----------- 1 file changed, 105 insertions(+), 172 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 5ca0def0c3..2b84354fa4 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -2034,67 +2034,51 @@ static void rtpcs_930x_sds_tx_config(struct rtpcs_serdes *sds, __always_unused static void rtpcs_930x_sds_rxcal_dcvs_manual(struct rtpcs_serdes *sds, - u32 dcvs_id, bool manual, u32 dvcs_list[]) + u32 dcvs_id, bool manual, u32 dcvs_list[]) { - if (manual) { - switch (dcvs_id) { - case 0: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 14, 14, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 5, 5, dvcs_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 4, 0, dvcs_list[1]); - break; - case 1: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 13, 13, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 15, 15, dvcs_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 14, 11, dvcs_list[1]); - break; - case 2: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 12, 12, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 10, 10, dvcs_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 9, 6, dvcs_list[1]); - break; - case 3: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 11, 11, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 5, 5, dvcs_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 4, 1, dvcs_list[1]); - break; - case 4: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 15, 15, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 10, 10, dvcs_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 9, 6, dvcs_list[1]); - break; - case 5: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x02, 11, 11, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 4, 4, dvcs_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 3, 0, dvcs_list[1]); - break; - default: - break; - } - } else { - switch (dcvs_id) { - case 0: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 14, 14, 0x0); - break; - case 1: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 13, 13, 0x0); - break; - case 2: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 12, 12, 0x0); - break; - case 3: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1e, 11, 11, 0x0); - break; - case 4: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x01, 15, 15, 0x0); - break; - case 5: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x02, 11, 11, 0x0); - break; - default: - break; - } + u8 reg[6] = { 0x1e, 0x1e, 0x1e, 0x1e, 0x01, 0x02 }; + u8 bit[6] = { 14, 13, 12, 11, 15, 11 }; + + if (dcvs_id > 5) + return; + + /* set DCVS auto/manual */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, reg[dcvs_id], bit[dcvs_id], bit[dcvs_id], + manual ? 0x1 : 0x0); + + if (!manual) { + /* give auto mode some time */ mdelay(1); + return; + } + + switch (dcvs_id) { + case 0: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 5, 5, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 4, 0, dcvs_list[1]); + break; + case 1: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 15, 15, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 14, 11, dcvs_list[1]); + break; + case 2: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 10, 10, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 9, 6, dcvs_list[1]); + break; + case 3: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 5, 5, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x1d, 4, 1, dcvs_list[1]); + break; + case 4: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 10, 10, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 9, 6, dcvs_list[1]); + break; + case 5: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 4, 4, dcvs_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x11, 3, 0, dcvs_list[1]); + break; + default: + break; } } @@ -2102,10 +2086,17 @@ __always_unused static void rtpcs_930x_sds_rxcal_dcvs_get(struct rtpcs_serdes *sds, u32 dcvs_id, u32 dcvs_list[]) { - struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); + u8 manual_reg[6] = { 0x1e, 0x1e, 0x1e, 0x1e, 0x01, 0x02 }; + u8 coeff_sel[6] = { 0x22, 0x23, 0x24, 0x25, 0x2c, 0x2d }; + u8 manual_bit[6] = { 14, 13, 12, 11, 15, 11 }; u32 dcvs_sign_out = 0, dcvs_coef_bin = 0; + struct rtpcs_serdes *even_sds; bool dcvs_manual; + if (dcvs_id > 5) + return; + + even_sds = rtpcs_sds_get_even(sds); if (sds == even_sds) rtpcs_sds_write(sds, PAGE_WDIG, 0x2, 0x2f); else @@ -2114,69 +2105,14 @@ static void rtpcs_930x_sds_rxcal_dcvs_get(struct rtpcs_serdes *sds, rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x15, 9, 9, 0x1); /* REG0_RX_EN_TEST */ rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x06, 11, 6, 0x20); /* REG0_RX_DEBUG_SEL */ - switch (dcvs_id) { - case 0: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x22); - mdelay(1); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, coeff_sel[dcvs_id]); + mdelay(1); - /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x1e, 14, 14); - break; - - case 1: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x23); - mdelay(1); - - /* ##DCVS0 Read Out */ - dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x1e, 13, 13); - break; - - case 2: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x24); - mdelay(1); - - /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x1e, 12, 12); - break; - case 3: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x25); - mdelay(1); - - /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); - dcvs_manual = rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x1e, 11, 11); - break; - - case 4: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x2c); - mdelay(1); - - /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); - dcvs_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x01, 15, 15); - break; - - case 5: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x0c, 5, 0, 0x2d); - mdelay(1); - - /* ##DCVS0 Read Out */ - dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); - dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); - dcvs_manual = rtpcs_sds_read_bits(sds, PAGE_ANA_10G, 0x02, 11, 11); - break; - - default: - break; - } + /* ## DCVSX Read Out */ + dcvs_sign_out = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 4, 4); + dcvs_coef_bin = rtpcs_sds_read_bits(sds, PAGE_WDIG, 0x14, 3, 0); + dcvs_manual = !!rtpcs_sds_read_bits(sds, PAGE_ANA_10G, manual_reg[dcvs_id], + manual_bit[dcvs_id], manual_bit[dcvs_id]); pr_info("%s: DCVS %u sign = %s, manual = %u, even coefficient = %u\n", __func__, dcvs_id, dcvs_sign_out ? "-" : "+", dcvs_manual, dcvs_coef_bin); @@ -2258,14 +2194,14 @@ static u32 rtpcs_930x_sds_rxcal_leq_read(struct rtpcs_serdes *sds) static void rtpcs_930x_sds_rxcal_vth_manual(struct rtpcs_serdes *sds, bool manual, u32 vth_list[]) { + /* REG0_LOAD_IN_INIT, [13:13] = VTH */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 13, 13, manual ? 0x1 : 0x0); + if (manual) { - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 13, 13, 0x1); rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 5, 3, vth_list[0]); rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x13, 2, 0, vth_list[1]); - } else { - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, 13, 13, 0x0); + } else mdelay(10); - } } static void rtpcs_930x_sds_rxcal_vth_get(struct rtpcs_serdes *sds, @@ -2293,53 +2229,50 @@ static void rtpcs_930x_sds_rxcal_vth_get(struct rtpcs_serdes *sds, static void rtpcs_930x_sds_rxcal_tap_manual(struct rtpcs_serdes *sds, int tap_id, bool manual, u32 tap_list[]) { - if (manual) { - switch (tap_id) { - case 0: - /* ##REG0_LOAD_IN_INIT[0]=1; REG0_TAP0_INIT[5:0]=Tap0_Value */ - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, - tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 4, 0, tap_list[1]); - break; - case 1: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, - tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x07, 6, 6, tap_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 11, 6, tap_list[1]); - rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x07, 5, 5, tap_list[2]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x12, 5, 0, tap_list[3]); - break; - case 2: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, - tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 4, 0, tap_list[1]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 11, 11, tap_list[2]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 10, 6, tap_list[3]); - break; - case 3: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, - tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 4, 0, tap_list[1]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 5, 5, tap_list[2]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 4, 0, tap_list[3]); - break; - case 4: - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, - tap_id + 7, 0x1); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 5, 5, tap_list[0]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 4, 0, tap_list[1]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 11, 11, tap_list[2]); - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 10, 6, tap_list[3]); - break; - default: - break; - } - } else { - rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0f, tap_id + 7, tap_id + 7, 0x0); + if (tap_id > 4) + return; + + /* ##REG0_LOAD_IN_INIT[0], [11:7] = TAP0-TAP4 */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0xf, tap_id + 7, tap_id + 7, + manual ? 0x1 : 0x0); + + if (!manual) { mdelay(10); + return; + } + + switch (tap_id) { + case 0: + /* ##REG0_TAP0_INIT[5:0]=Tap0_Value */ + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x03, 4, 0, tap_list[1]); + break; + case 1: + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x07, 6, 6, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 11, 6, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_COM, 0x07, 5, 5, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x12, 5, 0, tap_list[3]); + break; + case 2: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x09, 4, 0, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 11, 11, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 10, 6, tap_list[3]); + break; + case 3: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x0a, 4, 0, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 5, 5, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 4, 0, tap_list[3]); + break; + case 4: + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 5, 5, tap_list[0]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G_EXT, 0x01, 4, 0, tap_list[1]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 11, 11, tap_list[2]); + rtpcs_sds_write_bits(sds, PAGE_ANA_10G, 0x06, 10, 6, tap_list[3]); + break; + default: + break; } } From 3a7595dcde9454e6a33c943a6acfbcf6a6931ef7 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Sun, 28 Jun 2026 22:24:29 +0200 Subject: [PATCH 222/228] realtek: pcs: simplify gray code to binary conversion Gray conversion is b[i] = g[i] XOR g[i+1] XOR ... XOR g[n-1] Make the code a 3 liner. For more details see [1]. [1] https://en.wikipedia.org/wiki/Gray_code#Converting_to_and_from_Gray_code Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/23984 Signed-off-by: Jonas Jelonek --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index 2b84354fa4..bb6b1c8219 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -2144,31 +2144,15 @@ static void rtpcs_930x_sds_rxcal_leq_offset_manual(struct rtpcs_serdes *sds, } } -#define GRAY_BITS 5 static u32 rtpcs_930x_sds_rxcal_gray_to_binary(u32 gray_code) { - int i, j, m; - u32 g[GRAY_BITS]; - u32 c[GRAY_BITS]; - u32 leq_binary = 0; + u32 binary = gray_code; - for (i = 0; i < GRAY_BITS; i++) - g[i] = (gray_code & BIT(i)) >> i; + gray_code &= 0x1f; /* only lower 5 bits */ + while (gray_code >>= 1) + binary ^= gray_code; - m = GRAY_BITS - 1; - - c[m] = g[m]; - - for (i = 0; i < m; i++) { - c[i] = g[i]; - for (j = i + 1; j < GRAY_BITS; j++) - c[i] = c[i] ^ g[j]; - } - - for (i = 0; i < GRAY_BITS; i++) - leq_binary += c[i] << i; - - return leq_binary; + return binary; } static u32 rtpcs_930x_sds_rxcal_leq_read(struct rtpcs_serdes *sds) From f79e66d99698660838b9619024c42c2a7ce19ac9 Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sat, 23 May 2026 17:02:19 +0300 Subject: [PATCH 223/228] airoha: an7581: enable mtd virtual concat support This is required for upcoming Nokia XG-040G-MD support. Signed-off-by: Mikhail Zhilkin Link: https://github.com/openwrt/openwrt/pull/23569 Signed-off-by: Hauke Mehrtens --- target/linux/airoha/an7581/config-6.18 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/airoha/an7581/config-6.18 b/target/linux/airoha/an7581/config-6.18 index b08771357f..59f7325212 100644 --- a/target/linux/airoha/an7581/config-6.18 +++ b/target/linux/airoha/an7581/config-6.18 @@ -212,6 +212,7 @@ CONFIG_MTD_UBI_BEB_LIMIT=20 CONFIG_MTD_UBI_BLOCK=y CONFIG_MTD_UBI_NVMEM=y CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_VIRT_CONCAT=y CONFIG_MTK_NET_PHYLIB=y CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_NEED_DMA_MAP_STATE=y From 989ae157e03d8ae298a28cf96ee2e3808704b79d Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sat, 6 Jun 2026 14:52:30 +0300 Subject: [PATCH 224/228] uboot-airoha: fix sorting This commit fixes sorting in Makefile. Signed-off-by: Mikhail Zhilkin Link: https://github.com/openwrt/openwrt/pull/23569 Signed-off-by: Hauke Mehrtens --- package/boot/uboot-airoha/Makefile | 50 +++++++++++++++--------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/package/boot/uboot-airoha/Makefile b/package/boot/uboot-airoha/Makefile index 52b95c68ed..6f2e02c064 100644 --- a/package/boot/uboot-airoha/Makefile +++ b/package/boot/uboot-airoha/Makefile @@ -16,14 +16,22 @@ define U-Boot/Default LZMA_COMPRESS:=1 endef -define U-Boot/en7523_rfb - NAME:=EN7523 Reference Board - UBOOT_CONFIG:=en7523_evb - BUILD_DEVICES:=airoha_en7523-evb - BUILD_SUBTARGET:=en7523 +define U-Boot/an7581_gemtek_w1700k + NAME:=Gemtek W1700K (UBI) + UBOOT_CONFIG:=an7581_w1700k + BUILD_DEVICES:=gemtek_w1700k-ubi + BUILD_SUBTARGET:=an7581 + UBOOT_IMAGE:=u-boot.bin +endef + +define U-Boot/an7581_nokia_valyrian + NAME:=Nokia Valyrian + UBOOT_CONFIG:=an7581_nokia_valyrian + BUILD_DEVICES:=nokia_valyrian + BUILD_SUBTARGET:=an7581 UBOOT_IMAGE:=u-boot.fip - BL2_IMAGE:=en7523-bl2.bin - BL31_IMAGE:=en7523-bl31.bin + BL2_IMAGE:=an7581-bl2.bin + BL31_IMAGE:=an7581-bl31.bin endef define U-Boot/an7581_rfb @@ -46,30 +54,22 @@ define U-Boot/an7583_rfb BL31_IMAGE:=an7583-bl31.bin endef -define U-Boot/an7581_gemtek_w1700k - NAME:=Gemtek W1700K (UBI) - UBOOT_CONFIG:=an7581_w1700k - BUILD_DEVICES:=gemtek_w1700k-ubi - BUILD_SUBTARGET:=an7581 - UBOOT_IMAGE:=u-boot.bin -endef - -define U-Boot/an7581_nokia_valyrian - NAME:=Nokia Valyrian - UBOOT_CONFIG:=an7581_nokia_valyrian - BUILD_DEVICES:=nokia_valyrian - BUILD_SUBTARGET:=an7581 +define U-Boot/en7523_rfb + NAME:=EN7523 Reference Board + UBOOT_CONFIG:=en7523_evb + BUILD_DEVICES:=airoha_en7523-evb + BUILD_SUBTARGET:=en7523 UBOOT_IMAGE:=u-boot.fip - BL2_IMAGE:=an7581-bl2.bin - BL31_IMAGE:=an7581-bl31.bin + BL2_IMAGE:=en7523-bl2.bin + BL31_IMAGE:=en7523-bl31.bin endef UBOOT_TARGETS := \ - en7523_rfb \ + an7581_gemtek_w1700k \ + an7581_nokia_valyrian \ an7581_rfb \ an7583_rfb \ - an7581_gemtek_w1700k \ - an7581_nokia_valyrian + en7523_rfb UBOOT_CUSTOMIZE_CONFIG := \ --disable TOOLS_KWBIMAGE \ From 77ed809ce390ce2759e747e29accccfc01c7571d Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sat, 6 Jun 2026 14:59:51 +0300 Subject: [PATCH 225/228] uboot-airoha: add custom title support The patch was copied from mediatek target. Signed-off-by: Mikhail Zhilkin Link: https://github.com/openwrt/openwrt/pull/23569 Signed-off-by: Hauke Mehrtens --- .../200-cmd-bootmenu-custom-title.patch | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 package/boot/uboot-airoha/patches/200-cmd-bootmenu-custom-title.patch diff --git a/package/boot/uboot-airoha/patches/200-cmd-bootmenu-custom-title.patch b/package/boot/uboot-airoha/patches/200-cmd-bootmenu-custom-title.patch new file mode 100644 index 0000000000..3a66aa298a --- /dev/null +++ b/package/boot/uboot-airoha/patches/200-cmd-bootmenu-custom-title.patch @@ -0,0 +1,33 @@ +--- a/cmd/bootmenu.c ++++ b/cmd/bootmenu.c +@@ -482,7 +482,11 @@ static void menu_display_statusline(stru + printf(ANSI_CURSOR_POSITION, 1, 1); + puts(ANSI_CLEAR_LINE); + printf(ANSI_CURSOR_POSITION, 2, 3); +- puts("*** U-Boot Boot Menu ***"); ++ if (menu->mtitle) ++ puts(menu->mtitle); ++ else ++ puts(" *** U-Boot Boot Menu ***"); ++ + puts(ANSI_CLEAR_LINE_TO_END); + printf(ANSI_CURSOR_POSITION, 3, 1); + puts(ANSI_CLEAR_LINE); +@@ -573,6 +577,7 @@ static enum bootmenu_ret bootmenu_show(i + return BOOTMENU_RET_FAIL; + } + ++ bootmenu->mtitle = env_get("bootmenu_title"); + for (iter = bootmenu->first; iter; iter = iter->next) { + if (menu_item_add(menu, iter->key, iter) != 1) + goto cleanup; +--- a/include/menu.h ++++ b/include/menu.h +@@ -43,6 +43,7 @@ struct bootmenu_data { + int last_active; /* last active menu entry */ + int count; /* total count of menu entries */ + struct bootmenu_entry *first; /* first menu entry */ ++ char *mtitle; /* custom menu title */ + }; + + /** enum bootmenu_key - keys that can be returned by the bootmenu */ From 0d807a16b1d97734076971682da498f5118dacf8 Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sat, 6 Jun 2026 16:43:36 +0300 Subject: [PATCH 226/228] uboot-airoha: add readmem command This command is required to read and set device MAC address. The patch was copied from mediatek target. Signed-off-by: Mikhail Zhilkin Link: https://github.com/openwrt/openwrt/pull/23569 Signed-off-by: Hauke Mehrtens --- .../patches/201-cmd-env-readmem.patch | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 package/boot/uboot-airoha/patches/201-cmd-env-readmem.patch diff --git a/package/boot/uboot-airoha/patches/201-cmd-env-readmem.patch b/package/boot/uboot-airoha/patches/201-cmd-env-readmem.patch new file mode 100644 index 0000000000..14a4ba112a --- /dev/null +++ b/package/boot/uboot-airoha/patches/201-cmd-env-readmem.patch @@ -0,0 +1,116 @@ +--- a/cmd/Kconfig ++++ b/cmd/Kconfig +@@ -717,6 +717,12 @@ config CMD_ENV_EXISTS + Check if a variable is defined in the environment for use in + shell scripting. + ++config CMD_ENV_READMEM ++ bool "env readmem" ++ default y ++ help ++ Store memory content into environment variable. ++ + config CMD_ENV_CALLBACK + bool "env callbacks - print callbacks and their associated variables" + help +--- a/cmd/nvedit.c ++++ b/cmd/nvedit.c +@@ -273,6 +273,60 @@ static int do_env_ask(struct cmd_tbl *cm + } + #endif + ++#if defined(CONFIG_CMD_ENV_READMEM) ++int do_env_readmem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) ++{ ++ char varstr[CONFIG_SYS_CBSIZE]; ++ const void *buf; ++ char *local_args[4]; ++ ulong addr, bytes = 6; ++ int hexdump = 0; ++ ++ /* ++ * Check the syntax: ++ * ++ * readmem [-b] name address [size] ++ */ ++ if (argc < 3) ++ return CMD_RET_USAGE; ++ ++ local_args[0] = argv[0]; ++ ++ if (!strncmp(argv[1], "-b", 3)) ++ hexdump = 1; ++ ++ local_args[1] = argv[hexdump + 1]; ++ local_args[2] = varstr; ++ local_args[3] = NULL; ++ ++ addr = simple_strtoul(argv[hexdump + 2], NULL, 16); ++ ++ if (!hexdump) ++ bytes = simple_strtoul(argv[hexdump + 3], NULL, 16); ++ ++ if (bytes < 1) ++ return 1; ++ ++ if ((hexdump * 3) * bytes >= CONFIG_SYS_CBSIZE) ++ return 1; ++ ++ buf = map_sysmem(addr, bytes); ++ if (!buf) ++ return 1; ++ ++ if (hexdump) { ++ sprintf(varstr, "%pM", buf); ++ } else { ++ memcpy(varstr, buf, bytes); ++ varstr[bytes] = '\0'; ++ } ++ unmap_sysmem(buf); ++ ++ /* Continue calling setenv code */ ++ return env_do_env_set(flag, 3, local_args, H_INTERACTIVE); ++} ++#endif ++ + #if defined(CONFIG_CMD_ENV_CALLBACK) + static int print_static_binding(const char *var_name, const char *callback_name, + void *priv) +@@ -1095,6 +1149,9 @@ static struct cmd_tbl cmd_env_sub[] = { + U_BOOT_CMD_MKENT(load, 1, 0, do_env_load, "", ""), + #endif + U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_env_print, "", ""), ++#if defined(CONFIG_CMD_ENV_READMEM) ++ U_BOOT_CMD_MKENT(readmem, CONFIG_SYS_MAXARGS, 3, do_env_readmem, "", ""), ++#endif + #if defined(CONFIG_CMD_RUN) + U_BOOT_CMD_MKENT(run, CONFIG_SYS_MAXARGS, 1, do_run, "", ""), + #endif +@@ -1179,6 +1236,9 @@ U_BOOT_LONGHELP(env, + #if defined(CONFIG_CMD_NVEDIT_EFI) + "env print -e [-guid guid] [-n] [name ...] - print UEFI environment\n" + #endif ++#if defined(CONFIG_CMD_ENV_READMEM) ++ "env readmem [-b] name address size - read variable from memory\n" ++#endif + #if defined(CONFIG_CMD_RUN) + "env run var [...] - run commands in an environment variable\n" + #endif +@@ -1287,6 +1347,17 @@ U_BOOT_CMD( + ); + #endif + ++#if defined(CONFIG_CMD_ENV_READMEM) ++U_BOOT_CMD_COMPLETE( ++ readmem, CONFIG_SYS_MAXARGS, 3, do_env_readmem, ++ "get environment variable from memory address", ++ "[-b] name address size\n" ++ " - store memory address to env variable\n" ++ " \"-b\": read binary ethaddr", ++ var_complete ++); ++#endif ++ + #if defined(CONFIG_CMD_RUN) + U_BOOT_CMD_COMPLETE( + run, CONFIG_SYS_MAXARGS, 1, do_run, From 0277c8601ee48a687d1d27eddfc7175ea7f6874d Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sat, 6 Jun 2026 15:08:36 +0300 Subject: [PATCH 227/228] uboot-airoha: add support for Nokia XG-040G-MD Add support for Nokia XG-040G-MD. Known issues ------------ 1. Reset button is currently doesn't work and cannot be used to start tftp recovery: Button 'reset' not found (err=-19) LED 'green:power' not found (err=-19) Signed-off-by: Mikhail Zhilkin Link: https://github.com/openwrt/openwrt/pull/23569 Signed-off-by: Hauke Mehrtens --- package/boot/uboot-airoha/Makefile | 11 + .../patches/401-add-nokia-xg-040g-md.patch | 295 ++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 package/boot/uboot-airoha/patches/401-add-nokia-xg-040g-md.patch diff --git a/package/boot/uboot-airoha/Makefile b/package/boot/uboot-airoha/Makefile index 6f2e02c064..129081268c 100644 --- a/package/boot/uboot-airoha/Makefile +++ b/package/boot/uboot-airoha/Makefile @@ -34,6 +34,16 @@ define U-Boot/an7581_nokia_valyrian BL31_IMAGE:=an7581-bl31.bin endef +define U-Boot/an7581_nokia_xg-040g-md + NAME:=Nokia XG-040G-MD + UBOOT_CONFIG:=an7581_nokia_xg-040g-md + BUILD_DEVICES:=nokia_xg-040g-md-ubi + BUILD_SUBTARGET:=an7581 + UBOOT_IMAGE:=u-boot.fip + BL2_IMAGE:=an7581-bl2.bin + BL31_IMAGE:=an7581-bl31.bin +endef + define U-Boot/an7581_rfb NAME:=AN7581 Reference Board UBOOT_CONFIG:=an7581_evb @@ -67,6 +77,7 @@ endef UBOOT_TARGETS := \ an7581_gemtek_w1700k \ an7581_nokia_valyrian \ + an7581_nokia_xg-040g-md \ an7581_rfb \ an7583_rfb \ en7523_rfb diff --git a/package/boot/uboot-airoha/patches/401-add-nokia-xg-040g-md.patch b/package/boot/uboot-airoha/patches/401-add-nokia-xg-040g-md.patch new file mode 100644 index 0000000000..be59a76086 --- /dev/null +++ b/package/boot/uboot-airoha/patches/401-add-nokia-xg-040g-md.patch @@ -0,0 +1,295 @@ +--- /dev/null ++++ b/configs/an7581_nokia_xg-040g-md_defconfig +@@ -0,0 +1,134 @@ ++CONFIG_ARM=y ++CONFIG_ARCH_AIROHA=y ++CONFIG_POSITION_INDEPENDENT=y ++CONFIG_BOOTDELAY=3 ++CONFIG_AUTOBOOT_KEYED=y ++CONFIG_AUTOBOOT_MENU_SHOW=y ++CONFIG_TARGET_AN7581=y ++CONFIG_TEXT_BASE=0x81e00000 ++CONFIG_SYS_MALLOC_F_LEN=0x4000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_DM_GPIO=y ++CONFIG_DEFAULT_DEVICE_TREE="airoha/an7581-nokia-xg-040g-md" ++CONFIG_SYS_LOAD_ADDR=0x81800000 ++CONFIG_BUILD_TARGET="u-boot.bin" ++# CONFIG_EFI_LOADER is not set ++CONFIG_FIT=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_DEFAULT_FDT_FILE="airoha/an7581-nokia-xg-040g-md.dtb" ++CONFIG_LOGLEVEL=9 ++CONFIG_LOG=y ++CONFIG_SYS_PBSIZE=1049 ++CONFIG_SYS_CONSOLE_IS_IN_ENV=y ++# CONFIG_DISPLAY_BOARDINFO is not set ++CONFIG_HUSH_PARSER=y ++CONFIG_SYS_PROMPT="AN7581> " ++CONFIG_SYS_MAXARGS=8 ++CONFIG_CMD_CPU=y ++CONFIG_CMD_LICENSE=y ++CONFIG_CMD_BOOTMENU=y ++CONFIG_CMD_ASKENV=y ++CONFIG_CMD_ERASEENV=y ++CONFIG_CMD_ENV_FLAGS=y ++CONFIG_CMD_RNG=y ++CONFIG_CMD_STRINGS=y ++CONFIG_CMD_DM=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_MTD=y ++CONFIG_CMD_MTD_MARKBAD=y ++CONFIG_CMD_MTD_NAND_READ_TEST=y ++CONFIG_CMD_MTD_NAND_WRITE_TEST=y ++CONFIG_CMD_PART=y ++CONFIG_CMD_TFTPSRV=y ++CONFIG_CMD_RARP=y ++CONFIG_CMD_CDP=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_LINK_LOCAL=y ++CONFIG_CMD_DHCP=y ++CONFIG_CMD_DNS=y ++CONFIG_CMD_PING=y ++CONFIG_CMD_PXE=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_UUID=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_SMC=y ++CONFIG_CMD_UBI=y ++CONFIG_CMD_UBI_RENAME=y ++CONFIG_OF_EMBED=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_UBI=y ++CONFIG_ENV_REDUNDANT=y ++CONFIG_ENV_UBI_PART="ubi" ++CONFIG_ENV_UBI_VOLUME="ubootenv" ++CONFIG_ENV_UBI_VOLUME_REDUND="ubootenv2" ++CONFIG_ENV_RELOC_GD_ENV_ADDR=y ++CONFIG_ENV_USE_DEFAULT_ENV_TEXT_FILE=y ++CONFIG_ENV_DEFAULT_ENV_TEXT_FILE="defenvs/an7581_nokia_xg-040g-md_env" ++CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y ++# CONFIG_ENV_IS_IN_MTD is not set ++# CONFIG_MMC is not set ++CONFIG_MTD=y ++CONFIG_DM_MTD=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_MODULE=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++# CONFIG_MTD_UBI_FASTMAP is not set ++CONFIG_UBI_BLOCK=y ++# CONFIG_UBIFS_SILENCE_MSG is not set ++# CONFIG_UBIFS_SILENCE_DEBUG_DUMP is not set ++CONFIG_VERSION_VARIABLE=y ++CONFIG_NETCONSOLE=y ++CONFIG_USE_IPADDR=y ++CONFIG_IPADDR="192.168.1.1" ++CONFIG_USE_SERVERIP=y ++CONFIG_SERVERIP="192.168.1.254" ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_BUTTON=y ++CONFIG_BUTTON_GPIO=y ++CONFIG_OF_UPSTREAM=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_SYS_RX_ETH_BUFFER=8 ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_CLK=y ++CONFIG_DMA=y ++CONFIG_GPIO_HOG=y ++CONFIG_LED=y ++CONFIG_LED_BLINK=y ++CONFIG_LED_GPIO=y ++CONFIG_SPI_FLASH=y ++CONFIG_SPI_FLASH_EON=y ++CONFIG_SPI_FLASH_GIGADEVICE=y ++CONFIG_SPI_FLASH_ISSI=y ++CONFIG_SPI_FLASH_MACRONIX=y ++CONFIG_SPI_FLASH_SPANSION=y ++CONFIG_SPI_FLASH_STMICRO=y ++CONFIG_SPI_FLASH_WINBOND=y ++CONFIG_SPI_FLASH_MTD=y ++CONFIG_AIROHA_ETH=y ++CONFIG_DM_MDIO=y ++CONFIG_CMD_MII=y ++CONFIG_CMD_MDIO=y ++CONFIG_PCS_AIROHA_AN7581=y ++CONFIG_PHY=y ++CONFIG_PINCTRL=y ++CONFIG_PINCONF=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_RAM=y ++CONFIG_DM_SERIAL=y ++CONFIG_SYS_NS16550=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_AIROHA_SNFI_SPI=y ++CONFIG_SHA512=y ++CONFIG_USE_DEFAULT_ENV_FILE=y ++CONFIG_DEFAULT_ENV_FILE="defenvs/an7581_nokia_xg-040g-md_env" ++CONFIG_PCS_AIROHA_AN7581=y ++CONFIG_PHY_AIROHA_EN8811=y ++CONFIG_PHY_ANEG_TIMEOUT=10000 ++CONFIG_PHY_ETHERNET_ID=y +--- /dev/null ++++ b/defenvs/an7581_nokia_xg-040g-md_env +@@ -0,0 +1,53 @@ ++ipaddr=192.168.1.1 ++serverip=192.168.1.254 ++loadaddr=0x90000000 ++console=earlycon=uart8250,mmio32,0x11002000 console=ttyS0 ++bootcmd=run check_buttons ; run boot_ubi ++bootconf=config-1 ++bootdelay=0 ++bootfile=openwrt-airoha-an7581-nokia_xg-040g-md-ubi-initramfs-recovery.itb ++bootfile_bl2=openwrt-airoha-an7581-nokia_xg-040g-md-ubi-preloader.bin ++bootfile_fip=openwrt-airoha-an7581-nokia_xg-040g-md-ubi-bl31-uboot.fip ++bootfile_upg=openwrt-airoha-an7581-nokia_xg-040g-md-ubi-squashfs-sysupgrade.itb ++bootled_status=green:power ++bootmenu_confirm_return=askenv - Press ENTER to return to menu ; bootmenu 60 ++bootmenu_default=0 ++bootmenu_delay=0 ++bootmenu_title= ( ( ( OpenWrt ) ) ) ++bootmenu_0=Initialize environment.=run _firstboot ++bootmenu_0d=Run default boot command.=run boot_default ++bootmenu_1=Boot system via TFTP=run boot_tftp ; run bootmenu_confirm_return ++bootmenu_2=Boot production system from NAND=run boot_production ; run bootmenu_confirm_return ++bootmenu_3=Load production system via TFTP then write to NAND=setenv noboot 1 ; setenv replacevol 1 ; run boot_tftp_production ; setenv noboot ; setenv replacevol ; run bootmenu_confirm_return ++bootmenu_4=Load BL31+U-Boot FIP via TFTP then write to NAND=run boot_tftp_write_fip ; run bootmenu_confirm_return ++bootmenu_5=Load BL2 preloader via TFTP then write to NAND=run boot_tftp_write_bl2 ; run bootmenu_confirm_return ++bootmenu_6=Reboot=reset ++bootmenu_7=Reset all settings to factory defaults=run reset_factory ; reset ++boot_first=if button reset ; then led $bootled_status on ; run boot_default ; fi ; bootmenu ++boot_default=run bootcmd ; run boot_tftp_forever ++boot_production=led $bootled_status on ; run ubi_read_production && bootm $loadaddr#$bootconf ; led $bootled_status off ++boot_ubi=run boot_production ; run boot_tftp_forever ++boot_tftp_forever=led $bootled_status on ; while true ; do run boot_tftp ; sleep 1 ; done ++boot_tftp_production=tftpboot $loadaddr $bootfile_upg && env exists replacevol && iminfo $loadaddr && run ubi_write_production ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp_recovery=tftpboot $loadaddr $bootfile && env exists replacevol && iminfo $loadaddr && run ubi_write_recovery ; if env exists noboot ; then else bootm $loadaddr#$bootconf ; fi ++boot_tftp=tftpboot $loadaddr $bootfile && bootm $loadaddr#$bootconf ++boot_tftp_write_bl2=mw.b $loadaddr 0xff 0x800 ; setexpr loadaddr_bl2 $loadaddr + 0x800 ; tftpboot $loadaddr_bl2 $bootfile_bl2 && run mtd_write_bl2 ++boot_tftp_write_fip=tftpboot $loadaddr $bootfile_fip && run ubi_write_fip && run reset_factory ++preboot=led $bootled_status on ++check_buttons=if button reset ; then run boot_tftp ; fi ++ethaddr_factory=ubi read 0x90000000 ri && env readmem -b ethaddr 0x9000003e 0x6 ; setenv ethaddr_factory ++part_default=production ++reset_factory=ubi part ubi ; mw $loadaddr 0x0 0x800 ; ubi write $loadaddr ubootenv 0x800 ; ubi write $loadaddr ubootenv2 0x800 ++mtd_write_bl2=mtd erase bl2 && mtd write bl2 $loadaddr ++ubi_create_board_data=ubi check bosa || ubi create bosa 0x40000 || run ubi_format ; ubi check ri || ubi create ri 0x40000 || run ubi_format ++ubi_create_env=ubi check ubootenv || ubi create ubootenv 0x1f000 dynamic || run ubi_format ; ubi check ubootenv2 || ubi create ubootenv2 0x1f000 dynamic || run ubi_format ++ubi_format=ubi detach ; mtd erase ubi && ubi part ubi ; reset ++ubi_prepare_rootfs=if ubi check rootfs_data ; then else if env exists rootfs_data_max ; then ubi create rootfs_data $rootfs_data_max dynamic || ubi create rootfs_data - dynamic ; else ubi create rootfs_data - dynamic ; fi ; fi ++ubi_read_production=ubi read $loadaddr fit && iminfo $loadaddr && run ubi_prepare_rootfs ++ubi_remove_rootfs=ubi check rootfs_data && ubi remove rootfs_data ++ubi_write_fip=run ubi_remove_rootfs ; ubi check fip && ubi remove fip ; ubi create fip 0x100000 static && ubi write $loadaddr fip $filesize ++ubi_write_production=ubi check fit && ubi remove fit ; run ubi_remove_rootfs ; ubi create fit $filesize dynamic && ubi write $loadaddr fit $filesize ++_init_env=setenv _init_env ; run ubi_create_env ; saveenv ; saveenv ; run ubi_create_board_data ++_firstboot=setenv _firstboot ; run ethaddr_factory ; run _switch_to_menu ; run _init_env ; run boot_first ++_switch_to_menu=setenv _switch_to_menu ; setenv bootdelay 3 ; setenv bootmenu_delay 3 ; setenv bootmenu_0 $bootmenu_0d ; setenv bootmenu_0d ; run _bootmenu_update_title ++_bootmenu_update_title=setenv _bootmenu_update_title ; setenv bootmenu_title "$bootmenu_title $ver" +--- /dev/null ++++ b/dts/upstream/src/arm64/airoha/an7581-nokia-xg-040g-md.dts +@@ -0,0 +1,99 @@ ++// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++/dts-v1/; ++ ++#include ++#include ++#include ++#include "en7581.dtsi" ++ ++/ { ++ model = "Nokia XG-040G-MD"; ++ compatible = "nokia,xg-040g-md", ++ "airoha,an7581", ++ "airoha,en7581"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200 earlycon"; ++ stdout-path = "serial0:115200n8"; ++ linux,usable-memory-range = <0x0 0x80200000 0x0 0x1fe00000>; ++ }; ++ ++ memory@80000000 { ++ device_type = "memory"; ++ reg = <0x0 0x80000000 0x0 0x20000000>; ++ }; ++ ++ keys { ++ compatible = "gpio-keys"; ++ ++ button-0 { ++ label = "reset"; ++ linux,code = ; ++ gpios = <&en7581_pinctrl 0 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-0 { ++ label = "green:power"; ++ gpios = <&en7581_pinctrl 17 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led-1 { ++ label = "green:wan"; ++ gpios = <&en7581_pinctrl 18 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led-2 { ++ label = "red:wan"; ++ gpios = <&en7581_pinctrl 19 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led-3 { ++ label = "green:wan-online"; ++ gpios = <&en7581_pinctrl 20 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led-4 { ++ label = "green:usb-2"; ++ gpios = <&en7581_pinctrl 34 GPIO_ACTIVE_LOW>; ++ }; ++ ++ led-5 { ++ label = "green:usb-1"; ++ gpios = <&en7581_pinctrl 35 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&snfi { ++ status = "okay"; ++}; ++ ++&spi_nand { ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "bl2"; ++ reg = <0x0 0x20000>; ++ }; ++ ++ partition@20000 { ++ label = "ubi"; ++ reg = <0x20000 0xffe0000>; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ status = "okay"; ++}; ++ ++ð { ++ status = "okay"; ++}; From a6ecb09985fa7c14bae1c1bad7d42495737bc0ba Mon Sep 17 00:00:00 2001 From: Mikhail Zhilkin Date: Sat, 23 May 2026 17:42:33 +0300 Subject: [PATCH 228/228] airoha: add support for Nokia XG-040G-MD This commit adds support for Nokia XG-040G-MD XG-PON ONU. Specification ------------- - SoC : Airoha AN7581DT Quad-core ARM Cortex-A53 1.2 GHz - RAM : 512 MiB DDR4 (ESMT M16U4G16256A-QLB) - Flash : SPI-NAND 256 MiB (SkyHigh ML02G300WHI00) - WLAN : - - Ethernet : 1x 2500 Mbps (LAN1, Airoha EN8811HN) 3x 10/100/1000 Mbps (LAN2-LAN4, Airoha AN7581 SoC switch) - XG-PON : ECONET EN7572AN, SLIC: MaxLinear PEF32001VSV12 - USB : 1x USB 3.0 (with power control via gpio) 1x USB 2.0 (with power control via gpio) - Buttons : Reset - LEDs : 1x Power (green, gpio-controlled) 1x WAN (green, gpio-controlled) 1x WAN (red, gpio-controlled) 4x LAN (green, gpio-controlled) 2x USB (green) - Power : 12 VDC, 1 A Unsupported functions and limitations ------------------------------------- 1. XG-PON won't be available after installing OpenWrt. Installation (stock layout, UART) --------------------------------- 1. Attach UART and run picocom: picocom -b 115200 --send-cmd "sb -vv" /dev/ttyUSB0 2. Interrupt boot process by pressing Enter key to enter u-boot Username: telecomadmin Password: nE7jA%5m 3. Start download firmware via ymodem protocol (via UART): loady 0x85000000 4. Press Ctrl + A then Ctrl + S in the picocom terminal (if you are using a different terminal, please refer to the documentation) to start upload OpenWrt initramfs image using ymodem protocol. Enter local path to the OpenWrt initramfs image and press Enter. 5. Load OpenWrt initramfs image from the memory: bootm 0x85000000 5. Sysupgrade with OpenWrt sysupgrade image Alternative for the p.3-4. Load and boot OpenWrt initramfs from tftp IP 192.168.1.254: tftpboot 0x85000000 192.168.1.254:openwrt-initramfs-uImage.itb bootm 0x85000000 I was unable to download the file without errors, the bootloader network driver is very unstable. Perhaps you will be more fortunate. Backup and installation (stock layout, without UART) ---------------------------------------------------- 1. Unplug Fiber 2. Make ONU Reset 3. Navigate: http://192.168.1.1 Username: CMCCAdmin Password: aDm8H%MdA 4. Go to Apps -> Home Storage -> FTP and check Enable FTP 5. Go to Apps -> Home Storage -> SAMBA Sharing and check Enable Samba 6. Visit the following URL to open Telnet: http://192.168.1.1/system.cgi?telnet 7. Telnet account login: Username: user Password: 8. Get root privileges: su user_ftp Password: 9. Copy 'squashfs-factory-kernel.bin', 'squashfs-factory-rootfs.bin' and 'OpenWrt.mtd2.u-boot-env.bin' (backup of 'u-boot-env' partition from the another Nokia XG-040G-MD with OpenWrt installed) 9. Attach USB flash drive and check the new dir in /mnt: ls /mnt 10. Change current dir to the flash drive (change D to your flash drive label): cd /mnt/D 11. Make backup: for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; \ do cat /dev/mtd$i | gzip -9 > mtd$i.bin.gz; done 12. Check image sizes: ls -l | awk '{if(NR>1) {$5=sprintf("0x%x", $5); print}}' 13. Write images: mtd_debug erase /dev/mtd0 0x60000 0x20000 mtd_debug write /dev/mtd0 0x60000 0x20000 OpenWrt.mtd2.u-boot-env.bin mtd_debug erase /dev/mtd14 0x0 0x2880000 mtd_debug write /dev/mtd14 0x0 0x3e6cfc squashfs-factory-kernel.bin mtd_debug erase /dev/mtd11 0x0 0x80e0000 mtd_debug write /dev/mtd11 0x0 0x440000 squashfs-factory-rootfs.bin 0x3e6cfc - size of your 'squashfs-factory-kernel.bin' 0x440000 - size of your 'squashfs-factory-rootfs.bin' 14. Reboot: reboot Recovery (stock layout) ----------------------- The same as described in Installation (UART). Return to stock (stock layout) ------------------------------ 1. Follow the steps 1-5 of the Installation (UART) 2. Once in OpenWrt upload you backup to the /tmp dir of the router: scp -O mtd16.bin.gz root@192.168.1.1:/tmp 5. Connect to the router using ssh and install kmod-mtd-rw: apk update && apk add kmod-mtd-rw insmod mtd-rw i_want_a_brick=1 6. Unlock bootloader: mtd unlock bootloader 7. Restore stock: zcat /tmp/mtd16.bin.gz | mtd write - all_flash 8. Reboot: reboot Notes (OpenWrt U-Boot layout) ----------------------------- 1. Only devices with SkyHigh ML02G300WHI00 spi-nand are supported. Driver for FudanMicro FM25G02B is absent in current U-Boot. 2. A simple installation without serial console is also possible using a fork of @dangowrt's UBI Installer Link: https://github.com/dangowrt/owrt-ubi-installer Installation / recovery (OpenWrt U-Boot layout) ----------------------------------------------- 1. Make sure that you have 'bosa' and 'ri' partitions mtd backups before you start 2. Place OpenWrt images on the tftp server (IP: 192.168.1.254): openwrt-airoha-an7581-nokia_xg-040g-md-ubi-bl31-uboot.fip openwrt-airoha-an7581-nokia_xg-040g-md-ubi-initramfs-recovery.itb openwrt-airoha-an7581-nokia_xg-040g-md-ubi-preloader.bin 3. Attach serial console and start terminal with XMODEM support: picocom -b 115200 --send-cmd "sx -vvX" /dev/ttyUSB0 4. Push reset button and power on the router 5. Press 'x', then 'Ctrl + A' and 'Ctrl + S' 6. Paste full path to the bl2 image: 'openwrt-airoha-an7581-nokia_xg-040g-md-ubi-preloader.bin' 7. Wait until the file is downloaded and the following prompt appears: Press x to load BL31 + U-Boot FIP 8. Press 'x', then 'Ctrl + A' and 'Ctrl + S' 9. Paste full path to the fip image: 'openwrt-airoha-an7581-nokia_xg-040g-md-ubi-bl31-uboot.fip' 10. Wait until the file is downloaded, u-boot will prepare ubi partition automatically 11. Wait for U-Boot menu 12. Run 'Load BL31+U-Boot FIP via TFTP then write to NAND' 13. Run 'Load BL2 preloader via TFTP then write to NAND' 14. Run 'Boot system via TFTP' 15. Once in OpenWrt perform standard sysupgrade 16. Once in OpenWrt upload 'bosa' and 'ri' partitions mtd backups to the /tmp dir using scp protocol 17. Check ID of the UBI volumes: ubinfo -d 0 -N bosa | grep "Volume ID" ubinfo -d 0 -N ri | grep "Volume ID" 18. Write backups according to the volume ID: ubiupdatevol /dev/ubi0_2 /tmp/bosa.bin ubiupdatevol /dev/ubi0_3 /tmp/ri.bin 19. Reboot: reboot Stock layout ------------ +-------+------------+---------+---------+ | mtd | label | start | size | +-------+------------+---------+---------+ | mtd0 | bootloader | 0 | 80000 | | mtd1 | romfile | 80000 | 40000 | | mtd14 | nsb_master | c0000 | 2880000 | | mtd15 | nsb_slave | 2940000 | 2880000 | | mtd6 | bosa | 51c0000 | 40000 | | mtd7 | ri | 5200000 | 40000 | | mtd8 | flag | 5240000 | 40000 | | mtd9 | flagback | 5280000 | 40000 | | mtd10 | config | 52c0000 | a00000 | | mtd11 | data | 5cc0000 | 80e0000 | | mtd12 | oopsfs | dda0000 | 400000 | | mtd13 | log | e1a0000 | a00000 | +-------+------------+---------+---------+ USB power control ----------------- Disable (both ports): echo disabled > /sys/devices/platform/usb-power/state Enable (both ports): echo enabled > /sys/devices/platform/usb-power/state UART ---- A view from the back side of the PCB: ------------------------ | GND RX TX | X X X Connection parameters: 115200, 8N1, 3.3V MAC addresses ------------- +---------+-------------------+-----------+ | | MAC | Algorithm | +---------+-------------------+-----------+ | LAN | 04:xx:xx:xx:xx:0d | label | | WAN | 04:xx:xx:xx:xx:0e | label + 1 | +---------+-------------------+-----------+ The LAN MAC (hex) was found in 'ri', 0x3e Signed-off-by: Mikhail Zhilkin Link: https://github.com/openwrt/openwrt/pull/23569 Signed-off-by: Hauke Mehrtens --- .../uboot-envtools/files/airoha_an7581 | 6 +- .../an7581/base-files/etc/board.d/02_network | 4 + .../an7581/base-files/lib/upgrade/platform.sh | 44 ++- .../dts/an7581-nokia_xg-040g-md-common.dtsi | 350 ++++++++++++++++++ .../dts/an7581-nokia_xg-040g-md-ubi.dts | 84 +++++ .../airoha/dts/an7581-nokia_xg-040g-md.dts | 152 ++++++++ target/linux/airoha/image/an7581.mk | 46 +++ 7 files changed, 681 insertions(+), 5 deletions(-) create mode 100644 target/linux/airoha/dts/an7581-nokia_xg-040g-md-common.dtsi create mode 100644 target/linux/airoha/dts/an7581-nokia_xg-040g-md-ubi.dts create mode 100644 target/linux/airoha/dts/an7581-nokia_xg-040g-md.dts diff --git a/package/boot/uboot-tools/uboot-envtools/files/airoha_an7581 b/package/boot/uboot-tools/uboot-envtools/files/airoha_an7581 index 29e6c39886..c0a5c9fb44 100644 --- a/package/boot/uboot-tools/uboot-envtools/files/airoha_an7581 +++ b/package/boot/uboot-tools/uboot-envtools/files/airoha_an7581 @@ -12,9 +12,13 @@ touch /etc/config/ubootenv board=$(board_name) case "$board" in -gemtek,w1700k-ubi) +gemtek,w1700k-ubi|\ +nokia,xg-040g-md-ubi) ubootenv_add_ubi_default ;; +nokia,xg-040g-md) + ubootenv_add_mtd "u-boot-env" "0x1c000" "0x4000" "0x4000" + ;; esac config_load ubootenv diff --git a/target/linux/airoha/an7581/base-files/etc/board.d/02_network b/target/linux/airoha/an7581/base-files/etc/board.d/02_network index 267873f022..107ca37046 100644 --- a/target/linux/airoha/an7581/base-files/etc/board.d/02_network +++ b/target/linux/airoha/an7581/base-files/etc/board.d/02_network @@ -20,6 +20,10 @@ an7581_setup_interfaces() nokia,valyrian) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 10g" "wan" ;; + nokia,xg-040g-md |\ + nokia,xg-040g-md-ubi) + ucidef_set_interface_lan "lan1 lan2 lan3 lan4" + ;; *) echo "Unsupported hardware. Network interfaces not initialized" ;; diff --git a/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh b/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh index 767f499faa..8584b84e0c 100644 --- a/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh +++ b/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh @@ -1,11 +1,39 @@ -REQUIRE_IMAGE_METADATA=1 RAMFS_COPY_BIN='fitblk fit_check_sign' +REQUIRE_IMAGE_METADATA=1 + +nokia_initial_setup() +{ + [ "$(rootfs_type)" = "tmpfs" ] || return 0 + + fw_setenv bootcmd "flash read 0xc0000 0x800000 0x85000000; bootm 0x85000000" +} + +platform_check_image() { + local board=$(board_name) + + [ "$#" -gt 1 ] && return 1 + + case "$board" in + nokia,xg-040g-md) + nand_do_platform_check "$board" "$1" + return $? + ;; + nokia,xg-040g-md-ubi) + fit_check_image "$1" + return $? + ;; + esac + + return 0 +} + platform_do_upgrade() { local board=$(board_name) case "$board" in - gemtek,w1700k-ubi) + gemtek,w1700k-ubi|\ + nokia,xg-040g-md-ubi) fit_do_upgrade "$1" ;; *) @@ -14,6 +42,14 @@ platform_do_upgrade() { esac } -platform_check_image() { - return 0 +platform_pre_upgrade() { + local board=$(board_name) + + case "$board" in + nokia,xg-040g-md) + nokia_initial_setup + ;; + *) + ;; + esac } diff --git a/target/linux/airoha/dts/an7581-nokia_xg-040g-md-common.dtsi b/target/linux/airoha/dts/an7581-nokia_xg-040g-md-common.dtsi new file mode 100644 index 0000000000..aecddc73da --- /dev/null +++ b/target/linux/airoha/dts/an7581-nokia_xg-040g-md-common.dtsi @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +/dts-v1/; +#include +#include +#include +#include "an7581.dtsi" + +/ { + aliases { + label-mac-device = &gdm1; + + led-boot = &led_power_green; + led-failsafe = &led_power_green; + led-running = &led_power_green; + led-upgrade = &led_power_green; + + serial0 = &uart1; + }; + + chosen { + bootargs = "console=ttyS0,115200 earlycon"; + stdout-path = "serial0:115200n8"; + linux,usable-memory-range = + <0x0 0x80200000 0x0 0x1fe00000>; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-0 { + label = "reset"; + linux,code = ; + gpios = <&en7581_pinctrl 0 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power_green: led-0 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&en7581_pinctrl 17 GPIO_ACTIVE_LOW>; + panic-indicator; + }; + + led-1 { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&en7581_pinctrl 18 GPIO_ACTIVE_LOW>; + }; + + led-2 { + color = ; + function = LED_FUNCTION_WAN; + gpios = <&en7581_pinctrl 19 GPIO_ACTIVE_LOW>; + }; + + led-3 { + color = ; + function = LED_FUNCTION_WAN_ONLINE; + gpios = <&en7581_pinctrl 20 GPIO_ACTIVE_LOW>; + }; + + led-4 { + color = ; + function = LED_FUNCTION_USB; + function-enumerator = <2>; + gpios = <&en7581_pinctrl 34 GPIO_ACTIVE_LOW>; + linux,default-trigger = "usbport"; + trigger-sources = <&usb_port2>; + }; + + led-5 { + color = ; + function = LED_FUNCTION_USB; + function-enumerator = <1>; + gpios = <&en7581_pinctrl 35 GPIO_ACTIVE_LOW>; + linux,default-trigger = "usbport"; + trigger-sources = <&usb_port1>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x20000000>; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "fixed-3.3V"; + }; + + reg_usb_5v: regulator-usb-5v { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&en7581_pinctrl 24 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + regulator-max-microvolt = <5000000>; + regulator-min-microvolt = <5000000>; + regulator-name = "usb-5v"; + }; + + /* + * Controls both USB ports at once + */ + usb-power { + compatible = "regulator-output"; + vout-supply = <®_usb_5v>; + }; +}; + +&en7581_pinctrl { + gpio-ranges = <&en7581_pinctrl 0 13 47>; + + mdio_pins: mdio-pins { + mux { + function = "mdio"; + groups = "mdio"; + }; + + conf { + pins = "gpio2"; + output-high; + }; + }; + + gswp2_led0_pins: gswp2-led0-pins { + mux { + function = "phy2_led0"; + pins = "gpio44"; + }; + }; + + gswp3_led0_pins: gswp3-led0-pins { + mux { + function = "phy3_led0"; + pins = "gpio45"; + }; + }; + + gswp4_led0_pins: gswp4-led0-pins { + mux { + function = "phy4_led0"; + pins = "gpio46"; + }; + }; +}; + +ð { + status = "okay"; +}; + +ð_pcs { + status = "okay"; +}; + +&i2c0 { + status = "okay"; +}; + +&mdio { + /* Airoha EN8811 2.5Gbps phy */ + en8811: ethernet-phy@f { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0xf>; + + reset-gpios = <&en7581_pinctrl 31 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <20000>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led-0 { + reg = <0>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + default-state = "keep"; + }; + }; + }; +}; + +&npu { + status = "okay"; +}; + +&pon_pcs { + status = "okay"; +}; + +&snfi { + status = "okay"; +}; + +/* + * SkyHigh ML02G300WHI00 + */ +&spi_nand { + /* + * ECC must be aligned with bootloader to prevent read errors. + * Stock fw also uses NAND_ECC_NONE. + */ + nand-ecc-mode = "none"; + nand-ecc-step-size = <2048>; + nand-ecc-strength = <0>; + + partitions: partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&gdm1 { + status = "okay"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_3e (0)>; +}; + +&switch { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; +}; + +&gsw_port2 { + status = "okay"; + + label = "lan2"; +}; + +&gsw_phy2 { + status = "okay"; + + interrupts = <2>; + + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp2_led0_pins>; +}; + +&gsw_phy2_led0 { + status = "okay"; + + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + active-low; +}; + +&gsw_port3 { + status = "okay"; + + label = "lan3"; +}; + +&gsw_phy3 { + status = "okay"; + + interrupts = <3>; + + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp3_led0_pins>; +}; + +&gsw_phy3_led0 { + status = "okay"; + + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <3>; + active-low; +}; + +&gsw_port4 { + status = "okay"; + + label = "lan4"; +}; + +&gsw_phy4 { + status = "okay"; + + interrupts = <4>; + + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp4_led0_pins>; +}; + +&gsw_phy4_led0 { + status = "okay"; + + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <4>; + active-low; +}; + +&gdm4 { + status = "okay"; + + openwrt,netdev-name = "lan1"; + + phy-handle = <&en8811>; + phy-mode = "2500base-x"; + + nvmem-cell-names = "mac-address"; + nvmem-cells = <&macaddr_factory_3e (0)>; +}; + +&usb0 { + status = "okay"; + + vusb33-supply = <®_3p3v>; + + #address-cells = <1>; + #size-cells = <0>; + + usb_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; +}; + +&usb1 { + status = "okay"; + + mediatek,u3p-dis-msk = <0x1>; + phys = <&usb1_phy PHY_TYPE_USB2>; + vusb33-supply = <®_3p3v>; + + #address-cells = <1>; + #size-cells = <0>; + + usb_port2: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; +}; diff --git a/target/linux/airoha/dts/an7581-nokia_xg-040g-md-ubi.dts b/target/linux/airoha/dts/an7581-nokia_xg-040g-md-ubi.dts new file mode 100644 index 0000000000..b61f613e7a --- /dev/null +++ b/target/linux/airoha/dts/an7581-nokia_xg-040g-md-ubi.dts @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +#include "an7581-nokia_xg-040g-md-common.dtsi" + +/ { + model = "Nokia XG-040G-MD (UBI)"; + compatible = "nokia,xg-040g-md-ubi", "airoha,an7581", + "airoha,en7581"; + + chosen { + rootdisk = <&ubi_fit>; + }; +}; + +&partitions { + partition@0_all { + label = "all_flash"; + reg = <0x0 0x10000000>; + read-only; + }; + + partition@0 { + label = "bl2"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@20000 { + label = "ubi"; + reg = <0x20000 0xffe0000>; + compatible = "linux,ubi"; + + volumes { + ubi-volume-bosa { + volname = "bosa"; + }; + + ubi-volume-factory { + volname = "ri"; + + nvmem-layout { + compatible = "fixed-layout"; + + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_3e: macaddr@3e { + compatible = "mac-base"; + reg = <0x3e 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + ubi_fit: ubi-volume-fit { + volname = "fit"; + }; + + ubi-volume-fip { + volname = "fip"; + }; + + ubi_env: ubi-volume-ubootenv { + volname = "ubootenv"; + }; + + ubi_env2: ubi-volume-ubootenv2 { + volname = "ubootenv2"; + }; + }; + }; +}; + +&ubi_env { + nvmem-layout { + compatible = "u-boot,env-redundant-bool-layout"; + }; +}; + +&ubi_env2 { + nvmem-layout { + compatible = "u-boot,env-redundant-bool-layout"; + }; +}; diff --git a/target/linux/airoha/dts/an7581-nokia_xg-040g-md.dts b/target/linux/airoha/dts/an7581-nokia_xg-040g-md.dts new file mode 100644 index 0000000000..5676c78ab6 --- /dev/null +++ b/target/linux/airoha/dts/an7581-nokia_xg-040g-md.dts @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +#include "an7581-nokia_xg-040g-md-common.dtsi" + +/ { + model = "Nokia XG-040G-MD"; + compatible = "nokia,xg-040g-md", "airoha,an7581", "airoha,en7581"; + + virtual_flash { + compatible = "mtd-concat"; + devices = <&ubi4 &ubi1 &ubi2 &ubi3 &ubi5 &ubi6>; + + partitions { + compatible = "fixed-partitions"; + + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ubi"; + reg = <0x0 0x0>; + }; + }; + }; +}; + +&partitions { + partition@0_all { + label = "all_flash"; + reg = <0x0 0xeba0000>; + read-only; + }; + + partition@0 { + label = "bootloader"; + reg = <0x0 0x80000>; + read-only; + }; + + partition@60000 { + label = "u-boot-env"; + reg = <0x60000 0x20000>; + }; + + partition@80000 { + label = "romfile"; + reg = <0x80000 0x40000>; + read-only; + }; + + partition@c0000 { + label = "nsb_1"; + reg = <0xc0000 0x2880000>; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel"; + reg = <0x0 0x800000>; + }; + + ubi1: partition@800000 { + label = "rootfs_1"; + reg = <0x800000 0x2080000>; + }; + }; + + ubi2: partition@2940000 { + label = "nsb_2"; + reg = <0x2940000 0x2880000>; + }; + + partition@51c0000 { + label = "bosa"; + reg = <0x51c0000 0x40000>; + read-only; + }; + + partition@5200000 { + label = "ri"; + reg = <0x5200000 0x40000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_3e: macaddr@3e { + compatible = "mac-base"; + reg = <0x3e 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@5240000 { + label = "flag"; + reg = <0x5240000 0x40000>; + read-only; + }; + + partition@5280000 { + label = "flagback"; + reg = <0x5280000 0x40000>; + read-only; + }; + + ubi3: partition@52c0000 { + label = "config"; + reg = <0x52c0000 0xa00000>; + }; + + ubi4: partition@5cc0000 { + label = "data"; + reg = <0x5cc0000 0x80e0000>; + }; + + ubi5: partition@dda0000 { + label = "oopsfs"; + reg = <0xdda0000 0x400000>; + }; + + partition@e1a0000 { + label = "log"; + reg = <0xe1a0000 0xa00000>; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + ubi6: partition@0 { + label = "log_truncated"; + reg = <0x0 0x9c0000>; + }; + + /* + * Must be excluded from ubi. Otherwise the data + * will be broken after U-Boot 'bootflag swap' + * command call. This command writes bootflag at + * 0xeb60000 (boot_flag_addr). + */ + partition@9c0000 { + label = "bootflag"; + reg = <0x9c0000 0x40000>; + read-only; + }; + }; +}; diff --git a/target/linux/airoha/image/an7581.mk b/target/linux/airoha/image/an7581.mk index 7323eba0da..cc94c7de53 100644 --- a/target/linux/airoha/image/an7581.mk +++ b/target/linux/airoha/image/an7581.mk @@ -134,3 +134,49 @@ define Device/nokia_valyrian ARTIFACTS := preloader.bin bl31-uboot.fip endef TARGET_DEVICES += nokia_valyrian + +define Device/nokia_xg-040g-md-common + $(call Device/FitImageLzma) + DEVICE_VENDOR := Nokia + DEVICE_MODEL := XG-040G-MD + BLOCKSIZE := 128k + PAGESIZE := 2048 + UBINIZE_OPTS := -E 5 + DEVICE_PACKAGES := kmod-gpio-button-hotplug kmod-leds-gpio \ + kmod-phy-airoha-en8811h kmod-regulator-userspace-consumer \ + kmod-usb-ledtrig-usbport kmod-usb3 +endef + +define Device/nokia_xg-040g-md + $(call Device/nokia_xg-040g-md-common) + DEVICE_DTS := an7581-nokia_xg-040g-md + DEVICE_DTS_CONFIG := config@1 + IMAGE_SIZE := 131968k + KERNEL_SIZE := 8192k + IMAGES += factory-kernel.bin factory-rootfs.bin + IMAGE/factory-kernel.bin := append-kernel + IMAGE/factory-rootfs.bin := append-ubi | check-size + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += nokia_xg-040g-md + +define Device/nokia_xg-040g-md-ubi + $(call Device/nokia_xg-040g-md-common) + DEVICE_VARIANT := (UBI) + DEVICE_DTS := an7581-nokia_xg-040g-md-ubi + UBOOTENV_IN_UBI := 1 + KERNEL_IN_UBI := 1 + KERNEL := kernel-bin | gzip + KERNEL_INITRAMFS := kernel-bin | lzma | \ + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | pad-to 128k + KERNEL_INITRAMFS_SUFFIX := -recovery.itb + IMAGES := sysupgrade.itb + IMAGE/sysupgrade.itb := append-kernel | \ + fit gzip $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb external-static-with-rootfs | \ + append-metadata + DEVICE_PACKAGES += fitblk + ARTIFACT/bl31-uboot.fip := an7581-bl31-uboot nokia_xg-040g-md + ARTIFACT/preloader.bin := an7581-preloader nokia_xg-040g-md + ARTIFACTS := bl31-uboot.fip preloader.bin +endef +TARGET_DEVICES += nokia_xg-040g-md-ubi