From fdce970dbb47a6f91b08bdac21a098e77926549f Mon Sep 17 00:00:00 2001 From: Erik Karlsson Date: Wed, 6 Sep 2023 12:33:17 +0200 Subject: [PATCH 01/24] procd: create /dev/fd symlink This is needed for ksh/bash style process substitution such as <(command) and >(command) which was introduced in ash as of busybox version 1.34.0 to work. Signed-off-by: Erik Karlsson --- package/system/procd/Makefile | 2 +- package/system/procd/files/hotplug.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package/system/procd/Makefile b/package/system/procd/Makefile index d0576c1259..7c829260d5 100644 --- a/package/system/procd/Makefile +++ b/package/system/procd/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=procd -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/procd.git diff --git a/package/system/procd/files/hotplug.json b/package/system/procd/files/hotplug.json index b930b307a4..9fecddae6b 100644 --- a/package/system/procd/files/hotplug.json +++ b/package/system/procd/files/hotplug.json @@ -11,6 +11,7 @@ [ "eq", "DEVNAME", "null" ], [ [ "makedev", "/dev/%DEVNAME%", "0666" ], + [ "exec", "/bin/ln", "-s", "/proc/self/fd", "/dev/fd" ], [ "exec", "/bin/ln", "-s", "/proc/self/fd/0", "/dev/stdin" ], [ "exec", "/bin/ln", "-s", "/proc/self/fd/1", "/dev/stdout" ], [ "exec", "/bin/ln", "-s", "/proc/self/fd/2", "/dev/stderr" ], From 863444f9cb3908880eaaa15a99808f7f802881b4 Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Sat, 16 Sep 2023 17:52:57 +0200 Subject: [PATCH 02/24] sunxi: use kernel 6.1 as default Signed-off-by: Zoltan HERPAI --- target/linux/sunxi/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/linux/sunxi/Makefile b/target/linux/sunxi/Makefile index 750a1b7658..acca20f123 100644 --- a/target/linux/sunxi/Makefile +++ b/target/linux/sunxi/Makefile @@ -10,8 +10,7 @@ BOARDNAME:=Allwinner A1x/A20/A3x/H3/H5/R40 FEATURES:=fpu usb ext4 display rootfs-part rtc squashfs SUBTARGETS:=cortexa8 cortexa7 cortexa53 -KERNEL_PATCHVER:=5.15 -KERNEL_TESTING_PATCHVER:=6.1 +KERNEL_PATCHVER:=6.1 KERNELNAME:=zImage dtbs From 10eea40f7b367b8a3b0e8a406cbb34e1d1488e41 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sat, 16 Sep 2023 11:26:35 +0200 Subject: [PATCH 03/24] mac80211: ath11k: drop upstreamed patches Commit ed3725e15a154ebebf44e0c34806c57525483f92 ("wifi: ath11k: Fix qmi_msg_handler data structure initialization") has been present upstream since 6.1.2 but it seems Quilt refreshed it wrongly so it appeared like a completely different patch. Commit 7c15430822e71e90203d87e6d0cfe83fa058b0dc ("wifi: ath11k: allow system suspend to survive ath11k") has been present upstream since 6.1.16 but somehow quilt still happily applied it. So, drop both of them. Signed-off-by: Robert Marko --- ...qmi_msg_handler-data-structure-initi.patch | 33 -------------- ...low-system-suspend-to-survive-ath11k.patch | 43 ------------------- 2 files changed, 76 deletions(-) delete mode 100644 package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch delete mode 100644 package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch diff --git a/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch b/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch deleted file mode 100644 index a334973663..0000000000 --- a/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch +++ /dev/null @@ -1,33 +0,0 @@ -From ed3725e15a154ebebf44e0c34806c57525483f92 Mon Sep 17 00:00:00 2001 -From: Rahul Bhattacharjee -Date: Fri, 21 Oct 2022 14:31:26 +0530 -Subject: [PATCH] wifi: ath11k: Fix qmi_msg_handler data structure - initialization - -qmi_msg_handler is required to be null terminated by QMI module. -There might be a case where a handler for a msg id is not present in the -handlers array which can lead to infinite loop while searching the handler -and therefore out of bound access in qmi_invoke_handler(). -Hence update the initialization in qmi_msg_handler data structure. - -Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 - -Signed-off-by: Rahul Bhattacharjee -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221021090126.28626-1-quic_rbhattac@quicinc.com ---- - drivers/net/wireless/ath/ath11k/qmi.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/net/wireless/ath/ath11k/qmi.c -+++ b/drivers/net/wireless/ath/ath11k/qmi.c -@@ -1702,6 +1702,9 @@ static const struct qmi_elem_info qmi_wl - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - }, -+ -+ /* end of list */ -+ {}, - }; - - static int ath11k_qmi_host_cap_send(struct ath11k_base *ab) diff --git a/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch b/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch deleted file mode 100644 index fa680954e6..0000000000 --- a/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 7c15430822e71e90203d87e6d0cfe83fa058b0dc Mon Sep 17 00:00:00 2001 -From: Len Brown -Date: Wed, 1 Feb 2023 12:32:01 -0600 -Subject: [PATCH] wifi: ath11k: allow system suspend to survive ath11k - -When ath11k runs into internal errors upon suspend, -it returns an error code to pci_pm_suspend, which -aborts the entire system suspend. - -The driver should not abort system suspend, but should -keep its internal errors to itself, and allow the system -to suspend. Otherwise, a user can suspend a laptop -by closing the lid and sealing it into a case, assuming -that is will suspend, rather than heating up and draining -the battery when in transit. - -In practice, the ath11k device seems to have plenty of transient -errors, and subsequent suspend cycles after this failure -often succeed. - -https://bugzilla.kernel.org/show_bug.cgi?id=216968 - -Fixes: d1b0c33850d29 ("ath11k: implement suspend for QCA6390 PCI devices") - -Signed-off-by: Len Brown -Cc: stable@vger.kernel.org -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20230201183201.14431-1-len.brown@intel.com ---- - drivers/net/wireless/ath/ath11k/pci.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/wireless/ath/ath11k/pci.c -+++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -998,7 +998,7 @@ static __maybe_unused int ath11k_pci_pm_ - if (ret) - ath11k_warn(ab, "failed to resume core: %d\n", ret); - -- return ret; -+ return 0; - } - - static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops, From b33bfcf9fab2044b032b86597d2d0fe62c70ca37 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sat, 16 Sep 2023 12:02:50 +0200 Subject: [PATCH 04/24] mac80211: ath11k: sync with ath-next Synchronize the ath11k backports with the current ath-next tree. All of the changes are various bugfixes, there is no new major feature. Signed-off-by: Robert Marko --- ...band-selection-for-ppdu-received-in-.patch | 37 ++ ...lify-ath11k_mac_validate_vht_he_fixe.patch | 38 +++ ...-Split-coldboot-calibration-hw_param.patch | 180 ++++++++++ ...coldboot-calibration-support-for-QCN.patch | 176 ++++++++++ ...k-Remove-cal_done-check-during-probe.patch | 33 ++ ...t-drop-tx_status-when-peer-cannot-be.patch | 53 +++ ...nup-mac80211-references-on-failure-d.patch | 51 +++ ...Consistently-use-ath11k_vif_to_arvif.patch | 316 ++++++++++++++++++ ...ifi-ath11k-Fix-a-few-spelling-errors.patch | 50 +++ ...lify-the-code-with-module_platform_d.patch | 36 ++ ...x-Wvoid-pointer-to-enum-cast-warning.patch | 29 ++ ...fi-ath11k-Remove-unused-declarations.patch | 44 +++ ...add-a-warning-message-for-MHI_CB_EE_.patch | 34 ++ ...-references-from-rsvd2-to-info-field.patch | 75 +++++ ...-tid-bitmap-is-0-in-peer-rx-mu-stats.patch | 100 ++++++ ...i-ath11k-use-unique-QRTR-instance-ID.patch | 4 +- ...ci-fix-compilation-in-5.16-and-older.patch | 2 +- ...ble-coldboot-calibration-for-IPQ8074.patch | 12 +- ...upport-setting-FW-memory-mode-via-DT.patch | 7 +- 19 files changed, 1266 insertions(+), 11 deletions(-) create mode 100644 package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-fix-band-selection-for-ppdu-received-in-.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-simplify-ath11k_mac_validate_vht_he_fixe.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0003-wifi-ath11k-Split-coldboot-calibration-hw_param.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0004-wifi-ath11k-Add-coldboot-calibration-support-for-QCN.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Remove-cal_done-check-during-probe.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0006-wifi-ath11k-Don-t-drop-tx_status-when-peer-cannot-be.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-Cleanup-mac80211-references-on-failure-d.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-Consistently-use-ath11k_vif_to_arvif.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0009-wifi-ath11k-Fix-a-few-spelling-errors.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-simplify-the-code-with-module_platform_d.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-Wvoid-pointer-to-enum-cast-warning.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Remove-unused-declarations.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-mhi-add-a-warning-message-for-MHI_CB_EE_.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0014-wifi-ath11k-move-references-from-rsvd2-to-info-field.patch create mode 100644 package/kernel/mac80211/patches/ath11k/0015-wifi-ath11k-fix-tid-bitmap-is-0-in-peer-rx-mu-stats.patch diff --git a/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-fix-band-selection-for-ppdu-received-in-.patch b/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-fix-band-selection-for-ppdu-received-in-.patch new file mode 100644 index 0000000000..e6f9ac9e4c --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-fix-band-selection-for-ppdu-received-in-.patch @@ -0,0 +1,37 @@ +From 72c8caf904aed2caed5d6e75233294b6159ddb5d Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 26 Jul 2023 10:16:24 +0530 +Subject: [PATCH 1/5] wifi: ath11k: fix band selection for ppdu received in + channel 177 of 5 GHz + +5 GHz band channel 177 support was added with the commit e5e94d10c856 ("wifi: +ath11k: add channel 177 into 5 GHz channel list"). However, during processing +for the received ppdu in ath11k_dp_rx_h_ppdu(), channel number is checked only +till 173. This leads to driver code checking for channel and then fetching the +band from it which is extra effort since firmware has already given the channel +number in the metadata. + +Fix this issue by checking the channel number till 177 since we support +it now. + +Found via code review. Compile tested only. + +Fixes: e5e94d10c856 ("wifi: ath11k: add channel 177 into 5 GHz channel list") +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230726044624.20507-1-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -2408,7 +2408,7 @@ static void ath11k_dp_rx_h_ppdu(struct a + rx_status->freq = center_freq; + } else if (channel_num >= 1 && channel_num <= 14) { + rx_status->band = NL80211_BAND_2GHZ; +- } else if (channel_num >= 36 && channel_num <= 173) { ++ } else if (channel_num >= 36 && channel_num <= 177) { + rx_status->band = NL80211_BAND_5GHZ; + } else { + spin_lock_bh(&ar->data_lock); diff --git a/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-simplify-ath11k_mac_validate_vht_he_fixe.patch b/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-simplify-ath11k_mac_validate_vht_he_fixe.patch new file mode 100644 index 0000000000..2bdde1c72f --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-simplify-ath11k_mac_validate_vht_he_fixe.patch @@ -0,0 +1,38 @@ +From 6f092c98dcfa1e4cf37d45f9b8e4d4a3cbeb79d4 Mon Sep 17 00:00:00 2001 +From: Dmitry Antipov +Date: Wed, 26 Jul 2023 12:21:02 +0300 +Subject: [PATCH 2/5] wifi: ath11k: simplify + ath11k_mac_validate_vht_he_fixed_rate_settings() + +In ath11k_mac_validate_vht_he_fixed_rate_settings() ar->ab->peers +list is not altered so list_for_each_entry() should be safe. + +Compile tested only. + +Signed-off-by: Dmitry Antipov +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230726092113.78794-1-dmantipov@yandex.ru +--- + drivers/net/wireless/ath/ath11k/mac.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -8255,7 +8255,7 @@ ath11k_mac_validate_vht_he_fixed_rate_se + const struct cfg80211_bitrate_mask *mask) + { + bool he_fixed_rate = false, vht_fixed_rate = false; +- struct ath11k_peer *peer, *tmp; ++ struct ath11k_peer *peer; + const u16 *vht_mcs_mask, *he_mcs_mask; + struct ieee80211_link_sta *deflink; + u8 vht_nss, he_nss; +@@ -8278,7 +8278,7 @@ ath11k_mac_validate_vht_he_fixed_rate_se + + rcu_read_lock(); + spin_lock_bh(&ar->ab->base_lock); +- list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) { ++ list_for_each_entry(peer, &ar->ab->peers, list) { + if (peer->sta) { + deflink = &peer->sta->deflink; + diff --git a/package/kernel/mac80211/patches/ath11k/0003-wifi-ath11k-Split-coldboot-calibration-hw_param.patch b/package/kernel/mac80211/patches/ath11k/0003-wifi-ath11k-Split-coldboot-calibration-hw_param.patch new file mode 100644 index 0000000000..f8c7c937ea --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0003-wifi-ath11k-Split-coldboot-calibration-hw_param.patch @@ -0,0 +1,180 @@ +From 011e5a3052a22d3758d17442bf0c04c68bf79bea Mon Sep 17 00:00:00 2001 +From: Seevalamuthu Mariappan +Date: Wed, 26 Jul 2023 19:40:30 +0530 +Subject: [PATCH 3/5] wifi: ath11k: Split coldboot calibration hw_param + +QCN9074 enables coldboot calibration only in Factory Test Mode (FTM). +Hence, split cold_boot_calib to two hw_params for mission and FTM +mode. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Seevalamuthu Mariappan +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230726141032.3061-2-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 3 +-- + drivers/net/wireless/ath/ath11k/core.c | 36 ++++++++++++++++++++------ + drivers/net/wireless/ath/ath11k/core.h | 1 + + drivers/net/wireless/ath/ath11k/hw.h | 3 ++- + drivers/net/wireless/ath/ath11k/qmi.c | 6 ++--- + 5 files changed, 35 insertions(+), 14 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -422,8 +422,7 @@ static int ath11k_ahb_fwreset_from_cold_ + { + int timeout; + +- if (ath11k_cold_boot_cal == 0 || ab->qmi.cal_done || +- ab->hw_params.cold_boot_calib == 0 || ++ if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || + ab->hw_params.cbcal_restart_fw == 0) + return 0; + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -86,7 +86,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = false, + .idle_ps = false, + .supports_sta_ps = false, +- .cold_boot_calib = true, ++ .coldboot_cal_mm = true, ++ .coldboot_cal_ftm = true, + .cbcal_restart_fw = true, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -167,7 +168,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = false, + .idle_ps = false, + .supports_sta_ps = false, +- .cold_boot_calib = true, ++ .coldboot_cal_mm = true, ++ .coldboot_cal_ftm = true, + .cbcal_restart_fw = true, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -248,7 +250,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = true, + .idle_ps = true, + .supports_sta_ps = true, +- .cold_boot_calib = false, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = false, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -332,7 +335,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = false, + .idle_ps = false, + .supports_sta_ps = false, +- .cold_boot_calib = false, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = false, + .fw_mem_mode = 2, + .num_vdevs = 8, +@@ -413,7 +417,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = true, + .idle_ps = true, + .supports_sta_ps = true, +- .cold_boot_calib = false, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = false, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -495,7 +500,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = true, + .idle_ps = true, + .supports_sta_ps = true, +- .cold_boot_calib = false, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, + .cbcal_restart_fw = false, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -578,7 +584,8 @@ static const struct ath11k_hw_params ath + .supports_shadow_regs = true, + .idle_ps = true, + .supports_sta_ps = true, +- .cold_boot_calib = true, ++ .coldboot_cal_mm = true, ++ .coldboot_cal_ftm = true, + .cbcal_restart_fw = false, + .fw_mem_mode = 0, + .num_vdevs = 16 + 1, +@@ -667,7 +674,8 @@ static const struct ath11k_hw_params ath + .supports_suspend = false, + .hal_params = &ath11k_hw_hal_params_ipq8074, + .single_pdev_only = false, +- .cold_boot_calib = true, ++ .coldboot_cal_mm = true, ++ .coldboot_cal_ftm = true, + .cbcal_restart_fw = true, + .fix_l1ss = true, + .supports_dynamic_smps_6ghz = false, +@@ -749,6 +757,18 @@ void ath11k_fw_stats_free(struct ath11k_ + ath11k_fw_stats_bcn_free(&stats->bcn); + } + ++bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab) ++{ ++ if (!ath11k_cold_boot_cal) ++ return false; ++ ++ if (ath11k_ftm_mode) ++ return ab->hw_params.coldboot_cal_ftm; ++ ++ else ++ return ab->hw_params.coldboot_cal_mm; ++} ++ + int ath11k_core_suspend(struct ath11k_base *ab) + { + int ret; +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1186,6 +1186,7 @@ void ath11k_core_halt(struct ath11k *ar) + int ath11k_core_resume(struct ath11k_base *ab); + int ath11k_core_suspend(struct ath11k_base *ab); + void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab); ++bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab); + + const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, + const char *filename); +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -187,7 +187,8 @@ struct ath11k_hw_params { + bool supports_shadow_regs; + bool idle_ps; + bool supports_sta_ps; +- bool cold_boot_calib; ++ bool coldboot_cal_mm; ++ bool coldboot_cal_ftm; + bool cbcal_restart_fw; + int fw_mem_mode; + u32 num_vdevs; +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2079,7 +2079,7 @@ static int ath11k_qmi_assign_target_mem_ + return -EINVAL; + } + +- if (ath11k_cold_boot_cal && ab->hw_params.cold_boot_calib) { ++ if (ath11k_core_coldboot_cal_support(ab)) { + if (hremote_node) { + ab->qmi.target_mem[idx].paddr = + res.start + host_ddr_sz; +@@ -3209,8 +3209,8 @@ static void ath11k_qmi_driver_event_work + break; + } + +- if (ath11k_cold_boot_cal && ab->qmi.cal_done == 0 && +- ab->hw_params.cold_boot_calib) { ++ if (ab->qmi.cal_done == 0 && ++ ath11k_core_coldboot_cal_support(ab)) { + ath11k_qmi_process_coldboot_calibration(ab); + } else { + clear_bit(ATH11K_FLAG_CRASH_FLUSH, diff --git a/package/kernel/mac80211/patches/ath11k/0004-wifi-ath11k-Add-coldboot-calibration-support-for-QCN.patch b/package/kernel/mac80211/patches/ath11k/0004-wifi-ath11k-Add-coldboot-calibration-support-for-QCN.patch new file mode 100644 index 0000000000..9d51c1c3ea --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0004-wifi-ath11k-Add-coldboot-calibration-support-for-QCN.patch @@ -0,0 +1,176 @@ +From bdfc967bf5fcd762473a01d39edb81f1165ba290 Mon Sep 17 00:00:00 2001 +From: Anilkumar Kolli +Date: Wed, 26 Jul 2023 19:40:31 +0530 +Subject: [PATCH 4/5] wifi: ath11k: Add coldboot calibration support for + QCN9074 + +QCN9074 supports 6 GHz, which has increased number of channels +compared to 5 GHz/2 GHz. So, to support coldboot calibration in +QCN9074 ATH11K_COLD_BOOT_FW_RESET_DELAY extended to 60 seconds. To +avoid code redundancy, fwreset_from_cold_boot moved to QMI and made +common for both ahb and pci. Coldboot calibration is enabled only in +FTM mode for QCN9074. QCN9074 requires firmware restart after coldboot, +hence enable cbcal_restart_fw in hw_params. + +This support can be enabled/disabled using hw params for different +hardware. Currently it is not enabled for QCA6390. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Anilkumar Kolli +Signed-off-by: Seevalamuthu Mariappan +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230726141032.3061-3-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 28 ++------------------------ + drivers/net/wireless/ath/ath11k/core.c | 4 ++-- + drivers/net/wireless/ath/ath11k/pci.c | 2 ++ + drivers/net/wireless/ath/ath11k/qmi.c | 28 ++++++++++++++++++++++++++ + drivers/net/wireless/ath/ath11k/qmi.h | 3 ++- + 5 files changed, 36 insertions(+), 29 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -14,6 +14,7 @@ + #include "ahb.h" + #include "debug.h" + #include "hif.h" ++#include "qmi.h" + #include + #include "pcic.h" + #include +@@ -418,31 +419,6 @@ static void ath11k_ahb_power_down(struct + rproc_shutdown(ab_ahb->tgt_rproc); + } + +-static int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab) +-{ +- int timeout; +- +- if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || +- ab->hw_params.cbcal_restart_fw == 0) +- return 0; +- +- ath11k_dbg(ab, ATH11K_DBG_AHB, "wait for cold boot done\n"); +- timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, +- (ab->qmi.cal_done == 1), +- ATH11K_COLD_BOOT_FW_RESET_DELAY); +- if (timeout <= 0) { +- ath11k_cold_boot_cal = 0; +- ath11k_warn(ab, "Coldboot Calibration failed timed out\n"); +- } +- +- /* reset the firmware */ +- ath11k_ahb_power_down(ab); +- ath11k_ahb_power_up(ab); +- +- ath11k_dbg(ab, ATH11K_DBG_AHB, "exited from cold boot mode\n"); +- return 0; +-} +- + static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab) + { + struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; +@@ -1225,7 +1201,7 @@ static int ath11k_ahb_probe(struct platf + goto err_ce_free; + } + +- ath11k_ahb_fwreset_from_cold_boot(ab); ++ ath11k_qmi_fwreset_from_cold_boot(ab); + + return 0; + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -336,8 +336,8 @@ static const struct ath11k_hw_params ath + .idle_ps = false, + .supports_sta_ps = false, + .coldboot_cal_mm = false, +- .coldboot_cal_ftm = false, +- .cbcal_restart_fw = false, ++ .coldboot_cal_ftm = true, ++ .cbcal_restart_fw = true, + .fw_mem_mode = 2, + .num_vdevs = 8, + .num_peers = 128, +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -15,6 +15,7 @@ + #include "mhi.h" + #include "debug.h" + #include "pcic.h" ++#include "qmi.h" + + #define ATH11K_PCI_BAR_NUM 0 + #define ATH11K_PCI_DMA_MASK 32 +@@ -897,6 +898,7 @@ unsupported_wcn6855_soc: + ath11k_err(ab, "failed to init core: %d\n", ret); + goto err_irq_affinity_cleanup; + } ++ ath11k_qmi_fwreset_from_cold_boot(ab); + return 0; + + err_irq_affinity_cleanup: +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -9,6 +9,7 @@ + #include "qmi.h" + #include "core.h" + #include "debug.h" ++#include "hif.h" + #include + #include + #include +@@ -2839,6 +2840,33 @@ int ath11k_qmi_firmware_start(struct ath + return 0; + } + ++int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab) ++{ ++ int timeout; ++ ++ if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || ++ ab->hw_params.cbcal_restart_fw == 0) ++ return 0; ++ ++ ath11k_dbg(ab, ATH11K_DBG_QMI, "wait for cold boot done\n"); ++ ++ timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, ++ (ab->qmi.cal_done == 1), ++ ATH11K_COLD_BOOT_FW_RESET_DELAY); ++ ++ if (timeout <= 0) { ++ ath11k_warn(ab, "Coldboot Calibration timed out\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* reset the firmware */ ++ ath11k_hif_power_down(ab); ++ ath11k_hif_power_up(ab); ++ ath11k_dbg(ab, ATH11K_DBG_QMI, "exit wait for cold boot done\n"); ++ return 0; ++} ++EXPORT_SYMBOL(ath11k_qmi_fwreset_from_cold_boot); ++ + static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab) + { + int timeout; +--- a/drivers/net/wireless/ath/ath11k/qmi.h ++++ b/drivers/net/wireless/ath/ath11k/qmi.h +@@ -37,7 +37,7 @@ + + #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 + #define ATH11K_FIRMWARE_MODE_OFF 4 +-#define ATH11K_COLD_BOOT_FW_RESET_DELAY (40 * HZ) ++#define ATH11K_COLD_BOOT_FW_RESET_DELAY (60 * HZ) + + #define ATH11K_QMI_DEVICE_BAR_SIZE 0x200000 + +@@ -519,5 +519,6 @@ void ath11k_qmi_msg_recv_work(struct wor + void ath11k_qmi_deinit_service(struct ath11k_base *ab); + int ath11k_qmi_init_service(struct ath11k_base *ab); + void ath11k_qmi_free_resource(struct ath11k_base *ab); ++int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab); + + #endif diff --git a/package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Remove-cal_done-check-during-probe.patch b/package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Remove-cal_done-check-during-probe.patch new file mode 100644 index 0000000000..884fd58d75 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Remove-cal_done-check-during-probe.patch @@ -0,0 +1,33 @@ +From 13329d0cb7212b058bd8451a99d215a8f97645ea Mon Sep 17 00:00:00 2001 +From: Seevalamuthu Mariappan +Date: Wed, 26 Jul 2023 19:40:32 +0530 +Subject: [PATCH 5/5] wifi: ath11k: Remove cal_done check during probe + +In some race conditions, calibration done QMI message is received even +before host wait starts for calibration to be done. +Due to this, resetting firmware was not performed after calibration. + +Hence, remove cal_done check in ath11k_qmi_fwreset_from_cold_boot() +as this is called only from probe. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Seevalamuthu Mariappan +Signed-off-by: Raj Kumar Bhagat +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230726141032.3061-4-quic_rajkbhag@quicinc.com +--- + drivers/net/wireless/ath/ath11k/qmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -2844,7 +2844,7 @@ int ath11k_qmi_fwreset_from_cold_boot(st + { + int timeout; + +- if (!ath11k_core_coldboot_cal_support(ab) || ab->qmi.cal_done || ++ if (!ath11k_core_coldboot_cal_support(ab) || + ab->hw_params.cbcal_restart_fw == 0) + return 0; + diff --git a/package/kernel/mac80211/patches/ath11k/0006-wifi-ath11k-Don-t-drop-tx_status-when-peer-cannot-be.patch b/package/kernel/mac80211/patches/ath11k/0006-wifi-ath11k-Don-t-drop-tx_status-when-peer-cannot-be.patch new file mode 100644 index 0000000000..e404a7849e --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0006-wifi-ath11k-Don-t-drop-tx_status-when-peer-cannot-be.patch @@ -0,0 +1,53 @@ +From 400ece6c7f346b0a30867bd00b03b5b2563d4357 Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +Date: Tue, 22 Aug 2023 16:42:24 +0300 +Subject: [PATCH] wifi: ath11k: Don't drop tx_status when peer cannot be found + +When a station idles for a long time, hostapd will try to send a QoS Null +frame to the station as "poll". NL80211_CMD_PROBE_CLIENT is used for this +purpose. And the skb will be added to ack_status_frame - waiting for a +completion via ieee80211_report_ack_skb(). + +But when the peer was already removed before the tx_complete arrives, the +peer will be missing. And when using dev_kfree_skb_any (instead of going +through mac80211), the entry will stay inside ack_status_frames. This IDR +will therefore run full after 8K request were generated for such clients. +At this point, the access point will then just stall and not allow any new +clients because idr_alloc() for ack_status_frame will fail. + +ieee80211_free_txskb() on the other hand will (when required) call +ieee80211_report_ack_skb() and make sure that (when required) remove the +entry from the ack_status_frame. + +Tested-on: IPQ6018 hw1.0 WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Fixes: 6257c702264c ("wifi: ath11k: fix tx status reporting in encap offload mode") +Fixes: 94739d45c388 ("ath11k: switch to using ieee80211_tx_status_ext()") +Cc: stable@vger.kernel.org +Signed-off-by: Sven Eckelmann +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230802-ath11k-ack_status_leak-v2-1-c0af729d6229@narfation.org +--- + drivers/net/wireless/ath/ath11k/dp_tx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -369,7 +369,7 @@ ath11k_dp_tx_htt_tx_complete_buf(struct + "dp_tx: failed to find the peer with peer_id %d\n", + ts->peer_id); + spin_unlock_bh(&ab->base_lock); +- dev_kfree_skb_any(msdu); ++ ieee80211_free_txskb(ar->hw, msdu); + return; + } + spin_unlock_bh(&ab->base_lock); +@@ -624,7 +624,7 @@ static void ath11k_dp_tx_complete_msdu(s + "dp_tx: failed to find the peer with peer_id %d\n", + ts->peer_id); + spin_unlock_bh(&ab->base_lock); +- dev_kfree_skb_any(msdu); ++ ieee80211_free_txskb(ar->hw, msdu); + return; + } + arsta = (struct ath11k_sta *)peer->sta->drv_priv; diff --git a/package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-Cleanup-mac80211-references-on-failure-d.patch b/package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-Cleanup-mac80211-references-on-failure-d.patch new file mode 100644 index 0000000000..ae9cd05dd6 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-Cleanup-mac80211-references-on-failure-d.patch @@ -0,0 +1,51 @@ +From 29d15589f084d71a4ea8c544039c5839db0236e2 Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +Date: Tue, 22 Aug 2023 16:42:24 +0300 +Subject: [PATCH] wifi: ath11k: Cleanup mac80211 references on failure during + tx_complete + +When a function is using functions from mac80211 to free an skb then it +should do it consistently and not switch to the generic dev_kfree_skb_any +(or similar functions). Otherwise (like in the error handlers), mac80211 +will will not be aware of the freed skb and thus not clean up related +information in its internal data structures. + +Not doing so lead in the past to filled up structure which then prevented +new clients to connect. + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Fixes: 6257c702264c ("wifi: ath11k: fix tx status reporting in encap offload mode") +Cc: stable@vger.kernel.org +Signed-off-by: Sven Eckelmann +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230802-ath11k-ack_status_leak-v2-2-c0af729d6229@narfation.org +--- + drivers/net/wireless/ath/ath11k/dp_tx.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -344,7 +344,7 @@ ath11k_dp_tx_htt_tx_complete_buf(struct + dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + + if (!skb_cb->vif) { +- dev_kfree_skb_any(msdu); ++ ieee80211_free_txskb(ar->hw, msdu); + return; + } + +@@ -566,12 +566,12 @@ static void ath11k_dp_tx_complete_msdu(s + dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + + if (unlikely(!rcu_access_pointer(ab->pdevs_active[ar->pdev_idx]))) { +- dev_kfree_skb_any(msdu); ++ ieee80211_free_txskb(ar->hw, msdu); + return; + } + + if (unlikely(!skb_cb->vif)) { +- dev_kfree_skb_any(msdu); ++ ieee80211_free_txskb(ar->hw, msdu); + return; + } + diff --git a/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-Consistently-use-ath11k_vif_to_arvif.patch b/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-Consistently-use-ath11k_vif_to_arvif.patch new file mode 100644 index 0000000000..cc54b89441 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-Consistently-use-ath11k_vif_to_arvif.patch @@ -0,0 +1,316 @@ +From 9476cda44c136089f14f8951ae5197d63e91735c Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Mon, 21 Aug 2023 07:13:36 -0700 +Subject: [PATCH] wifi: ath11k: Consistently use ath11k_vif_to_arvif() + +Helper function ath11k_vif_to_arvif() exists to retrieve a struct +ath11k_vif from a struct ieee80211_vif. However, in multiple places +this logic is open-coded with inline typecasting. Since the +typecasting prevents the compiler from type-checking the source and +destination, update the driver to consistently use the helper +function. + +No functional changes, compile tested only. + +Signed-off-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230821-ath11k_vif_to_arvif-v1-1-fa2c3b60b5cf@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 64 +++++++++++----------- + drivers/net/wireless/ath/ath11k/testmode.c | 2 +- + 2 files changed, 33 insertions(+), 33 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -566,7 +566,7 @@ static void ath11k_get_arvif_iter(void * + struct ieee80211_vif *vif) + { + struct ath11k_vif_iter *arvif_iter = data; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + + if (arvif->vdev_id == arvif_iter->vdev_id) + arvif_iter->arvif = arvif; +@@ -1464,7 +1464,7 @@ static int ath11k_mac_setup_bcn_tmpl_ema + u32 params = 0; + u8 i = 0; + +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ tx_arvif = ath11k_vif_to_arvif(arvif->vif->mbssid_tx_vif); + + beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw, + tx_arvif->vif, 0); +@@ -1520,8 +1520,8 @@ static int ath11k_mac_setup_bcn_tmpl_mbs + struct sk_buff *bcn; + int ret; + +- if (arvif->vif->mbssid_tx_vif) { +- tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; ++ if (vif->mbssid_tx_vif) { ++ tx_arvif = ath11k_vif_to_arvif(vif->mbssid_tx_vif); + if (tx_arvif != arvif) { + ar = tx_arvif->ar; + ab = ar->ab; +@@ -1562,7 +1562,7 @@ static int ath11k_mac_setup_bcn_tmpl(str + * non-transmitting interfaces, and results in a crash if sent. + */ + if (vif->mbssid_tx_vif && +- arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up) ++ arvif != ath11k_vif_to_arvif(vif->mbssid_tx_vif) && arvif->is_up) + return 0; + + if (vif->bss_conf.ema_ap && vif->mbssid_tx_vif) +@@ -1626,7 +1626,7 @@ static void ath11k_control_beaconing(str + ether_addr_copy(arvif->bssid, info->bssid); + + if (arvif->vif->mbssid_tx_vif) +- tx_arvif = (struct ath11k_vif *)arvif->vif->mbssid_tx_vif->drv_priv; ++ tx_arvif = ath11k_vif_to_arvif(arvif->vif->mbssid_tx_vif); + + ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, + arvif->bssid, +@@ -1649,7 +1649,7 @@ static void ath11k_mac_handle_beacon_ite + { + struct sk_buff *skb = data; + struct ieee80211_mgmt *mgmt = (void *)skb->data; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + + if (vif->type != NL80211_IFTYPE_STATION) + return; +@@ -1672,7 +1672,7 @@ static void ath11k_mac_handle_beacon_mis + struct ieee80211_vif *vif) + { + u32 *vdev_id = data; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct ath11k *ar = arvif->ar; + struct ieee80211_hw *hw = ar->hw; + +@@ -1718,7 +1718,7 @@ static void ath11k_peer_assoc_h_basic(st + struct ieee80211_sta *sta, + struct peer_assoc_params *arg) + { +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + u32 aid; + + lockdep_assert_held(&ar->conf_mutex); +@@ -1746,7 +1746,7 @@ static void ath11k_peer_assoc_h_crypto(s + struct ieee80211_bss_conf *info = &vif->bss_conf; + struct cfg80211_chan_def def; + struct cfg80211_bss *bss; +- struct ath11k_vif *arvif = (struct ath11k_vif *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + const u8 *rsnie = NULL; + const u8 *wpaie = NULL; + +@@ -1804,7 +1804,7 @@ static void ath11k_peer_assoc_h_rates(st + struct ieee80211_sta *sta, + struct peer_assoc_params *arg) + { +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates; + struct cfg80211_chan_def def; + const struct ieee80211_supported_band *sband; +@@ -1867,7 +1867,7 @@ static void ath11k_peer_assoc_h_ht(struc + struct peer_assoc_params *arg) + { + const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct cfg80211_chan_def def; + enum nl80211_band band; + const u8 *ht_mcs_mask; +@@ -2064,7 +2064,7 @@ static void ath11k_peer_assoc_h_vht(stru + struct peer_assoc_params *arg) + { + const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct cfg80211_chan_def def; + enum nl80211_band band; + u16 *vht_mcs_mask; +@@ -2261,7 +2261,7 @@ static void ath11k_peer_assoc_h_he(struc + struct ieee80211_sta *sta, + struct peer_assoc_params *arg) + { +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct cfg80211_chan_def def; + const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap; + enum nl80211_band band; +@@ -2584,7 +2584,7 @@ static void ath11k_peer_assoc_h_qos(stru + struct ieee80211_sta *sta, + struct peer_assoc_params *arg) + { +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + + switch (arvif->vdev_type) { + case WMI_VDEV_TYPE_AP: +@@ -2747,7 +2747,7 @@ static void ath11k_peer_assoc_h_phymode( + struct ieee80211_sta *sta, + struct peer_assoc_params *arg) + { +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct cfg80211_chan_def def; + enum nl80211_band band; + const u8 *ht_mcs_mask; +@@ -2933,7 +2933,7 @@ static bool ath11k_mac_vif_recalc_sta_he + struct ieee80211_vif *vif, + struct ieee80211_sta_he_cap *he_cap) + { +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct ieee80211_he_cap_elem he_cap_elem = {0}; + struct ieee80211_sta_he_cap *cap_band = NULL; + struct cfg80211_chan_def def; +@@ -2995,7 +2995,7 @@ static void ath11k_bss_assoc(struct ieee + struct ieee80211_bss_conf *bss_conf) + { + struct ath11k *ar = hw->priv; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct peer_assoc_params peer_arg; + struct ieee80211_sta *ap_sta; + struct ath11k_peer *peer; +@@ -3111,7 +3111,7 @@ static void ath11k_bss_disassoc(struct i + struct ieee80211_vif *vif) + { + struct ath11k *ar = hw->priv; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + int ret; + + lockdep_assert_held(&ar->conf_mutex); +@@ -3160,7 +3160,7 @@ static void ath11k_recalculate_mgmt_rate + struct ieee80211_vif *vif, + struct cfg80211_chan_def *def) + { +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + const struct ieee80211_supported_band *sband; + u8 basic_rate_idx; + int hw_rate_code; +@@ -4632,7 +4632,7 @@ static int ath11k_station_disassoc(struc + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) + { +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + int ret = 0; + + lockdep_assert_held(&ar->conf_mutex); +@@ -5160,7 +5160,7 @@ static int ath11k_mac_op_sta_set_txpwr(s + struct ieee80211_sta *sta) + { + struct ath11k *ar = hw->priv; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + int ret = 0; + s16 txpwr; + +@@ -5210,7 +5210,7 @@ static void ath11k_mac_op_sta_rc_update( + { + struct ath11k *ar = hw->priv; + struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct ath11k_peer *peer; + u32 bw, smps; + +@@ -5337,7 +5337,7 @@ static int ath11k_mac_op_conf_tx(struct + const struct ieee80211_tx_queue_params *params) + { + struct ath11k *ar = hw->priv; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct wmi_wmm_params_arg *p = NULL; + int ret; + +@@ -6455,7 +6455,7 @@ static int ath11k_mac_setup_vdev_params_ + return 0; + } + +- tx_arvif = (void *)tx_vif->drv_priv; ++ tx_arvif = ath11k_vif_to_arvif(tx_vif); + + if (arvif->vif->bss_conf.nontransmitted) { + if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) +@@ -7408,7 +7408,7 @@ ath11k_mac_update_vif_chan(struct ath11k + /* TODO: Update ar->rx_channel */ + + for (i = 0; i < n_vifs; i++) { +- arvif = (void *)vifs[i].vif->drv_priv; ++ arvif = ath11k_vif_to_arvif(vifs[i].vif); + + if (WARN_ON(!arvif->is_started)) + continue; +@@ -7450,7 +7450,7 @@ ath11k_mac_update_vif_chan(struct ath11k + + mbssid_tx_vif = arvif->vif->mbssid_tx_vif; + if (mbssid_tx_vif) +- tx_arvif = (struct ath11k_vif *)mbssid_tx_vif->drv_priv; ++ tx_arvif = ath11k_vif_to_arvif(mbssid_tx_vif); + + ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, + arvif->bssid, +@@ -7546,7 +7546,7 @@ static int ath11k_start_vdev_delay(struc + { + struct ath11k *ar = hw->priv; + struct ath11k_base *ab = ar->ab; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + int ret; + + if (WARN_ON(arvif->is_started)) +@@ -7596,7 +7596,7 @@ ath11k_mac_op_assign_vif_chanctx(struct + { + struct ath11k *ar = hw->priv; + struct ath11k_base *ab = ar->ab; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + int ret; + struct peer_create_params param; + +@@ -7686,7 +7686,7 @@ ath11k_mac_op_unassign_vif_chanctx(struc + { + struct ath11k *ar = hw->priv; + struct ath11k_base *ab = ar->ab; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct ath11k_peer *peer; + int ret; + +@@ -8307,7 +8307,7 @@ ath11k_mac_op_set_bitrate_mask(struct ie + struct ieee80211_vif *vif, + const struct cfg80211_bitrate_mask *mask) + { +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct cfg80211_chan_def def; + struct ath11k_pdev_cap *cap; + struct ath11k *ar = arvif->ar; +@@ -8904,7 +8904,7 @@ static int ath11k_mac_op_remain_on_chann + enum ieee80211_roc_type type) + { + struct ath11k *ar = hw->priv; +- struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct scan_req_params arg; + int ret; + u32 scan_time_msec; +--- a/drivers/net/wireless/ath/ath11k/testmode.c ++++ b/drivers/net/wireless/ath/ath11k/testmode.c +@@ -350,7 +350,7 @@ static int ath11k_tm_cmd_wmi(struct ath1 + if (ar->ab->fw_mode != ATH11K_FIRMWARE_MODE_FTM && + (tag == WMI_TAG_VDEV_SET_PARAM_CMD || tag == WMI_TAG_UNIT_TEST_CMD)) { + if (vif) { +- arvif = (struct ath11k_vif *)vif->drv_priv; ++ arvif = ath11k_vif_to_arvif(vif); + *ptr = arvif->vdev_id; + } else { + ret = -EINVAL; diff --git a/package/kernel/mac80211/patches/ath11k/0009-wifi-ath11k-Fix-a-few-spelling-errors.patch b/package/kernel/mac80211/patches/ath11k/0009-wifi-ath11k-Fix-a-few-spelling-errors.patch new file mode 100644 index 0000000000..b093f3e342 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0009-wifi-ath11k-Fix-a-few-spelling-errors.patch @@ -0,0 +1,50 @@ +From d68a283bfc39aeed2a51c67804e014bf4b35c7e1 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Tue, 22 Aug 2023 07:50:49 -0700 +Subject: [PATCH] wifi: ath11k: Fix a few spelling errors + +Fix a few issues flagged by 'codespell'. + +Signed-off-by: Jeff Johnson +Acked-by: Randy Dunlap +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230822-ath_spelling-v1-2-8e2698759564@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp.h | 2 +- + drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +- + drivers/net/wireless/ath/ath11k/dp_tx.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/dp.h ++++ b/drivers/net/wireless/ath/ath11k/dp.h +@@ -635,7 +635,7 @@ enum htt_ppdu_stats_tag_type { + * b'24 - status_swap: 1 is to swap status TLV + * b'25 - pkt_swap: 1 is to swap packet TLV + * b'26:31 - rsvd1: reserved for future use +- * dword1 - b'0:16 - ring_buffer_size: size of bufferes referenced by rx ring, ++ * dword1 - b'0:16 - ring_buffer_size: size of buffers referenced by rx ring, + * in byte units. + * Valid only for HW_TO_SW_RING and SW_TO_HW_RING + * - b'16:31 - rsvd2: Reserved for future use +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -3423,7 +3423,7 @@ static int ath11k_dp_rx_h_defrag_reo_rei + ath11k_hal_rx_buf_addr_info_set(msdu0, paddr, cookie, + ab->hw_params.hal_params->rx_buf_rbm); + +- /* Fill mpdu details into reo entrace ring */ ++ /* Fill mpdu details into reo entrance ring */ + srng = &ab->hal.srng_list[ab->dp.reo_reinject_ring.ring_id]; + + spin_lock_bh(&srng->lock); +--- a/drivers/net/wireless/ath/ath11k/dp_tx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c +@@ -238,7 +238,7 @@ tcl_ring_sel: + spin_unlock_bh(&tcl_ring->lock); + ret = -ENOMEM; + +- /* Checking for available tcl descritors in another ring in ++ /* Checking for available tcl descriptors in another ring in + * case of failure due to full tcl ring now, is better than + * checking this ring earlier for each pkt tx. + * Restart ring selection if some rings are not checked yet. diff --git a/package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-simplify-the-code-with-module_platform_d.patch b/package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-simplify-the-code-with-module_platform_d.patch new file mode 100644 index 0000000000..19873339b2 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-simplify-the-code-with-module_platform_d.patch @@ -0,0 +1,36 @@ +From 749a660b39030bfbacc366cd8670df2ee0e878b2 Mon Sep 17 00:00:00 2001 +From: Yang Yingliang +Date: Fri, 4 Aug 2023 17:12:55 +0800 +Subject: [PATCH] wifi: ath11k: simplify the code with module_platform_driver + +The init/exit() of driver only calls platform_driver_register/unregister, +it can be simpilfied with module_platform_driver. + +Signed-off-by: Yang Yingliang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230804091255.1347178-1-yangyingliang@huawei.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 12 +----------- + 1 file changed, 1 insertion(+), 11 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -1306,17 +1306,7 @@ static struct platform_driver ath11k_ahb + .shutdown = ath11k_ahb_shutdown, + }; + +-static int ath11k_ahb_init(void) +-{ +- return platform_driver_register(&ath11k_ahb_driver); +-} +-module_init(ath11k_ahb_init); +- +-static void ath11k_ahb_exit(void) +-{ +- platform_driver_unregister(&ath11k_ahb_driver); +-} +-module_exit(ath11k_ahb_exit); ++module_platform_driver(ath11k_ahb_driver); + + MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN AHB devices"); + MODULE_LICENSE("Dual BSD/GPL"); diff --git a/package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-Wvoid-pointer-to-enum-cast-warning.patch b/package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-Wvoid-pointer-to-enum-cast-warning.patch new file mode 100644 index 0000000000..f42b021375 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-Wvoid-pointer-to-enum-cast-warning.patch @@ -0,0 +1,29 @@ +From 6763ef191d672ff3c2db0622652d49b0c0a60c4a Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Thu, 10 Aug 2023 11:12:23 +0200 +Subject: [PATCH] wifi: ath11k: fix Wvoid-pointer-to-enum-cast warning + +'hw_rev' is an enum, thus cast of pointer on 64-bit compile test with W=1 +causes: + + h11k/ahb.c:1124:11: error: cast to smaller integer type 'enum ath11k_hw_rev' from 'const void *' [-Werror,-Wvoid-pointer-to-enum-cast] + +Signed-off-by: Krzysztof Kozlowski +Acked-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230810091224.70088-1-krzysztof.kozlowski@linaro.org +--- + drivers/net/wireless/ath/ath11k/ahb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -1096,7 +1096,7 @@ static int ath11k_ahb_probe(struct platf + return -EINVAL; + } + +- hw_rev = (enum ath11k_hw_rev)of_id->data; ++ hw_rev = (uintptr_t)of_id->data; + + switch (hw_rev) { + case ATH11K_HW_IPQ8074: diff --git a/package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Remove-unused-declarations.patch b/package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Remove-unused-declarations.patch new file mode 100644 index 0000000000..c318bbc321 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Remove-unused-declarations.patch @@ -0,0 +1,44 @@ +From adb0b206709f4f2f1256a1ea20619ab98e99f2e7 Mon Sep 17 00:00:00 2001 +From: Yue Haibing +Date: Fri, 11 Aug 2023 18:44:13 +0800 +Subject: [PATCH] wifi: ath11k: Remove unused declarations + +Commit 2c3960c2253d ("ath11k: setup ce tasklet for control path") +declared but never implemented ath11k_ce_map_service_to_pipe(). +Commit e3396b8bddd2 ("ath11k: ce: support different CE configurations") +declared but never implemented ath11k_ce_attr_attach(). +Commit d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +declared but never implemented ath11k_qmi_event_work()/ath11k_qmi_msg_recv_work(). + +Signed-off-by: Yue Haibing +Acked-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230811104413.33668-1-yuehaibing@huawei.com +--- + drivers/net/wireless/ath/ath11k/ce.h | 3 --- + drivers/net/wireless/ath/ath11k/qmi.h | 2 -- + 2 files changed, 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/ce.h ++++ b/drivers/net/wireless/ath/ath11k/ce.h +@@ -203,9 +203,6 @@ int ath11k_ce_alloc_pipes(struct ath11k_ + void ath11k_ce_free_pipes(struct ath11k_base *ab); + int ath11k_ce_get_attr_flags(struct ath11k_base *ab, int ce_id); + void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id); +-int ath11k_ce_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, +- u8 *ul_pipe, u8 *dl_pipe); +-int ath11k_ce_attr_attach(struct ath11k_base *ab); + void ath11k_ce_get_shadow_config(struct ath11k_base *ab, + u32 **shadow_cfg, u32 *shadow_cfg_len); + void ath11k_ce_stop_shadow_timers(struct ath11k_base *ab); +--- a/drivers/net/wireless/ath/ath11k/qmi.h ++++ b/drivers/net/wireless/ath/ath11k/qmi.h +@@ -514,8 +514,6 @@ struct qmi_wlanfw_wlan_ini_resp_msg_v01 + int ath11k_qmi_firmware_start(struct ath11k_base *ab, + u32 mode); + void ath11k_qmi_firmware_stop(struct ath11k_base *ab); +-void ath11k_qmi_event_work(struct work_struct *work); +-void ath11k_qmi_msg_recv_work(struct work_struct *work); + void ath11k_qmi_deinit_service(struct ath11k_base *ab); + int ath11k_qmi_init_service(struct ath11k_base *ab); + void ath11k_qmi_free_resource(struct ath11k_base *ab); diff --git a/package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-mhi-add-a-warning-message-for-MHI_CB_EE_.patch b/package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-mhi-add-a-warning-message-for-MHI_CB_EE_.patch new file mode 100644 index 0000000000..e1286c9537 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-mhi-add-a-warning-message-for-MHI_CB_EE_.patch @@ -0,0 +1,34 @@ +From 4a93b554cf9fa64faa7cf164c0d32fc3ce67108b Mon Sep 17 00:00:00 2001 +From: Arowa Suliman +Date: Sat, 26 Aug 2023 08:42:42 +0300 +Subject: [PATCH] wifi: ath11k: mhi: add a warning message for MHI_CB_EE_RDDM + crash + +Currently, the ath11k driver does not print a crash signature when a +MHI_CB_EE_RDDM crash happens. Checked by triggering a simulated crash using the +command and checking dmesg for logs: + +echo assert > /sys/kernel/debug/ath11k/../simulate_fw_crash + +Add a warning when firmware crash MHI_CB_EE_RDDM happens. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23 + +Signed-off-by: Arowa Suliman +Reviewed-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230714001126.463127-1-arowa@chromium.org +--- + drivers/net/wireless/ath/ath11k/mhi.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/ath/ath11k/mhi.c ++++ b/drivers/net/wireless/ath/ath11k/mhi.c +@@ -333,6 +333,7 @@ static void ath11k_mhi_op_status_cb(stru + ath11k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n"); + break; + case MHI_CB_EE_RDDM: ++ ath11k_warn(ab, "firmware crashed: MHI_CB_EE_RDDM\n"); + if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags))) + queue_work(ab->workqueue_aux, &ab->reset_work); + break; diff --git a/package/kernel/mac80211/patches/ath11k/0014-wifi-ath11k-move-references-from-rsvd2-to-info-field.patch b/package/kernel/mac80211/patches/ath11k/0014-wifi-ath11k-move-references-from-rsvd2-to-info-field.patch new file mode 100644 index 0000000000..731a763e17 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0014-wifi-ath11k-move-references-from-rsvd2-to-info-field.patch @@ -0,0 +1,75 @@ +From 5bd2ced044bb95029d5c44cf7d23ced73e0fc05b Mon Sep 17 00:00:00 2001 +From: Muna Sinada +Date: Sat, 26 Aug 2023 08:42:46 +0300 +Subject: [PATCH] wifi: ath11k: move references from rsvd2 to info fields + +Remove references to reserved fields and add new info fields for +struct hal_rx_ppdu_end_user_stats. Reserved fields should not be +accessed, therefore existing references to it are to be changed to +referencing specific info fields. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-00356-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Muna Sinada +Acked-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1692827868-15667-1-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/hal_rx.c | 10 +++++----- + drivers/net/wireless/ath/ath11k/hal_rx.h | 11 ++++++++--- + 2 files changed, 13 insertions(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/hal_rx.c ++++ b/drivers/net/wireless/ath/ath11k/hal_rx.c +@@ -814,7 +814,7 @@ ath11k_hal_rx_handle_ofdma_info(void *rx + + rx_user_status->ul_ofdma_user_v0_word0 = __le32_to_cpu(ppdu_end_user->info6); + +- rx_user_status->ul_ofdma_user_v0_word1 = __le32_to_cpu(ppdu_end_user->rsvd2[10]); ++ rx_user_status->ul_ofdma_user_v0_word1 = __le32_to_cpu(ppdu_end_user->info9); + } + + static inline void +@@ -825,11 +825,11 @@ ath11k_hal_rx_populate_byte_count(void * + (struct hal_rx_ppdu_end_user_stats *)rx_tlv; + + rx_user_status->mpdu_ok_byte_count = +- FIELD_GET(HAL_RX_PPDU_END_USER_STATS_RSVD2_6_MPDU_OK_BYTE_COUNT, +- __le32_to_cpu(ppdu_end_user->rsvd2[6])); ++ FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_OK_BYTE_COUNT, ++ __le32_to_cpu(ppdu_end_user->info7)); + rx_user_status->mpdu_err_byte_count = +- FIELD_GET(HAL_RX_PPDU_END_USER_STATS_RSVD2_8_MPDU_ERR_BYTE_COUNT, +- __le32_to_cpu(ppdu_end_user->rsvd2[8])); ++ FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO9_MPDU_ERR_BYTE_COUNT, ++ __le32_to_cpu(ppdu_end_user->info8)); + } + + static inline void +--- a/drivers/net/wireless/ath/ath11k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath11k/hal_rx.h +@@ -222,8 +222,8 @@ struct hal_rx_ppdu_start { + #define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP GENMASK(15, 0) + #define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_EOSP_BITMAP GENMASK(31, 16) + +-#define HAL_RX_PPDU_END_USER_STATS_RSVD2_6_MPDU_OK_BYTE_COUNT GENMASK(24, 0) +-#define HAL_RX_PPDU_END_USER_STATS_RSVD2_8_MPDU_ERR_BYTE_COUNT GENMASK(24, 0) ++#define HAL_RX_PPDU_END_USER_STATS_INFO7_MPDU_OK_BYTE_COUNT GENMASK(24, 0) ++#define HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_ERR_BYTE_COUNT GENMASK(24, 0) + + struct hal_rx_ppdu_end_user_stats { + __le32 rsvd0[2]; +@@ -236,7 +236,12 @@ struct hal_rx_ppdu_end_user_stats { + __le32 info4; + __le32 info5; + __le32 info6; +- __le32 rsvd2[11]; ++ __le32 rsvd2[5]; ++ __le32 info7; ++ __le32 rsvd3; ++ __le32 info8; ++ __le32 rsvd3[2]; ++ __le32 info9; + } __packed; + + struct hal_rx_ppdu_end_user_stats_ext { diff --git a/package/kernel/mac80211/patches/ath11k/0015-wifi-ath11k-fix-tid-bitmap-is-0-in-peer-rx-mu-stats.patch b/package/kernel/mac80211/patches/ath11k/0015-wifi-ath11k-fix-tid-bitmap-is-0-in-peer-rx-mu-stats.patch new file mode 100644 index 0000000000..3edc3fc956 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0015-wifi-ath11k-fix-tid-bitmap-is-0-in-peer-rx-mu-stats.patch @@ -0,0 +1,100 @@ +From 7791487cd16cafd018cba0bf73789111a9f16843 Mon Sep 17 00:00:00 2001 +From: Muna Sinada +Date: Sat, 26 Aug 2023 08:42:46 +0300 +Subject: [PATCH] wifi: ath11k: fix tid bitmap is 0 in peer rx mu stats + +Correct parsing of reading offset for rx tid 16 bit bitmap. Incorrect +offset caused peer rx mu stats tid bitmap to always be zero. This +correction is in the software context and does not affect the +firmware interface. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-00356-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Muna Sinada +Acked-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1692827868-15667-2-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/hal_rx.c | 10 +++++----- + drivers/net/wireless/ath/ath11k/hal_rx.h | 17 +++++++++-------- + 2 files changed, 14 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/hal_rx.c ++++ b/drivers/net/wireless/ath/ath11k/hal_rx.c +@@ -814,7 +814,7 @@ ath11k_hal_rx_handle_ofdma_info(void *rx + + rx_user_status->ul_ofdma_user_v0_word0 = __le32_to_cpu(ppdu_end_user->info6); + +- rx_user_status->ul_ofdma_user_v0_word1 = __le32_to_cpu(ppdu_end_user->info9); ++ rx_user_status->ul_ofdma_user_v0_word1 = __le32_to_cpu(ppdu_end_user->info10); + } + + static inline void +@@ -826,10 +826,10 @@ ath11k_hal_rx_populate_byte_count(void * + + rx_user_status->mpdu_ok_byte_count = + FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_OK_BYTE_COUNT, +- __le32_to_cpu(ppdu_end_user->info7)); ++ __le32_to_cpu(ppdu_end_user->info8)); + rx_user_status->mpdu_err_byte_count = + FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO9_MPDU_ERR_BYTE_COUNT, +- __le32_to_cpu(ppdu_end_user->info8)); ++ __le32_to_cpu(ppdu_end_user->info9)); + } + + static inline void +@@ -903,8 +903,8 @@ ath11k_hal_rx_parse_mon_status_tlv(struc + FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO2_AST_INDEX, + __le32_to_cpu(eu_stats->info2)); + ppdu_info->tid = +- ffs(FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP, +- __le32_to_cpu(eu_stats->info6))) - 1; ++ ffs(FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO7_TID_BITMAP, ++ __le32_to_cpu(eu_stats->info7))) - 1; + ppdu_info->tcp_msdu_count = + FIELD_GET(HAL_RX_PPDU_END_USER_STATS_INFO4_TCP_MSDU_CNT, + __le32_to_cpu(eu_stats->info4)); +--- a/drivers/net/wireless/ath/ath11k/hal_rx.h ++++ b/drivers/net/wireless/ath/ath11k/hal_rx.h +@@ -149,7 +149,7 @@ struct hal_rx_mon_ppdu_info { + u8 beamformed; + u8 rssi_comb; + u8 rssi_chain_pri20[HAL_RX_MAX_NSS]; +- u8 tid; ++ u16 tid; + u16 ht_flags; + u16 vht_flags; + u16 he_flags; +@@ -219,11 +219,11 @@ struct hal_rx_ppdu_start { + #define HAL_RX_PPDU_END_USER_STATS_INFO5_OTHER_MSDU_CNT GENMASK(15, 0) + #define HAL_RX_PPDU_END_USER_STATS_INFO5_TCP_ACK_MSDU_CNT GENMASK(31, 16) + +-#define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_BITMAP GENMASK(15, 0) +-#define HAL_RX_PPDU_END_USER_STATS_INFO6_TID_EOSP_BITMAP GENMASK(31, 16) ++#define HAL_RX_PPDU_END_USER_STATS_INFO7_TID_BITMAP GENMASK(15, 0) ++#define HAL_RX_PPDU_END_USER_STATS_INFO7_TID_EOSP_BITMAP GENMASK(31, 16) + +-#define HAL_RX_PPDU_END_USER_STATS_INFO7_MPDU_OK_BYTE_COUNT GENMASK(24, 0) +-#define HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_ERR_BYTE_COUNT GENMASK(24, 0) ++#define HAL_RX_PPDU_END_USER_STATS_INFO8_MPDU_OK_BYTE_COUNT GENMASK(24, 0) ++#define HAL_RX_PPDU_END_USER_STATS_INFO9_MPDU_ERR_BYTE_COUNT GENMASK(24, 0) + + struct hal_rx_ppdu_end_user_stats { + __le32 rsvd0[2]; +@@ -236,12 +236,13 @@ struct hal_rx_ppdu_end_user_stats { + __le32 info4; + __le32 info5; + __le32 info6; +- __le32 rsvd2[5]; + __le32 info7; +- __le32 rsvd3; ++ __le32 rsvd2[4]; + __le32 info8; +- __le32 rsvd3[2]; ++ __le32 rsvd3; + __le32 info9; ++ __le32 rsvd4[2]; ++ __le32 info10; + } __packed; + + struct hal_rx_ppdu_end_user_stats_ext { diff --git a/package/kernel/mac80211/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch b/package/kernel/mac80211/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch index 39d5a61d5a..30472b3229 100644 --- a/package/kernel/mac80211/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch +++ b/package/kernel/mac80211/patches/ath11k/100-wifi-ath11k-use-unique-QRTR-instance-ID.patch @@ -93,7 +93,7 @@ Signed-off-by: Robert Marko default: return "UNKNOWN"; } -@@ -336,27 +366,14 @@ static void ath11k_mhi_op_status_cb(stru +@@ -337,27 +367,14 @@ static void ath11k_mhi_op_status_cb(stru if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags))) queue_work(ab->workqueue_aux, &ab->reset_work); break; @@ -138,7 +138,7 @@ Signed-off-by: Robert Marko int ath11k_mhi_register(struct ath11k_pci *ar_pci); --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -370,13 +370,20 @@ static void ath11k_pci_sw_reset(struct a +@@ -371,13 +371,20 @@ static void ath11k_pci_sw_reset(struct a static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab) { struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; diff --git a/package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch b/package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch index 7215656389..9a0ca80090 100644 --- a/package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch +++ b/package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch @@ -15,7 +15,7 @@ Signed-off-by: Robert Marko --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c -@@ -458,7 +458,11 @@ static int ath11k_pci_alloc_msi(struct a +@@ -459,7 +459,11 @@ static int ath11k_pci_alloc_msi(struct a pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO, &ab->pci.msi.addr_lo); diff --git a/package/kernel/mac80211/patches/ath11k/902-ath11k-Disable-coldboot-calibration-for-IPQ8074.patch b/package/kernel/mac80211/patches/ath11k/902-ath11k-Disable-coldboot-calibration-for-IPQ8074.patch index 5454fa75e4..cff62eea90 100644 --- a/package/kernel/mac80211/patches/ath11k/902-ath11k-Disable-coldboot-calibration-for-IPQ8074.patch +++ b/package/kernel/mac80211/patches/ath11k/902-ath11k-Disable-coldboot-calibration-for-IPQ8074.patch @@ -8,17 +8,19 @@ so until that is resolved disabled it to allow using the radio. Signed-off-by: Robert Marko --- - drivers/net/wireless/ath/ath11k/core.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + drivers/net/wireless/ath/ath11k/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c -@@ -86,7 +86,7 @@ static const struct ath11k_hw_params ath +@@ -86,8 +86,8 @@ static const struct ath11k_hw_params ath .supports_shadow_regs = false, .idle_ps = false, .supports_sta_ps = false, -- .cold_boot_calib = true, -+ .cold_boot_calib = false, +- .coldboot_cal_mm = true, +- .coldboot_cal_ftm = true, ++ .coldboot_cal_mm = false, ++ .coldboot_cal_ftm = false, .cbcal_restart_fw = true, .fw_mem_mode = 0, .num_vdevs = 16 + 1, diff --git a/package/kernel/mac80211/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch b/package/kernel/mac80211/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch index ca77748fd2..aacbb34839 100644 --- a/package/kernel/mac80211/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch +++ b/package/kernel/mac80211/patches/ath11k/903-ath11k-support-setting-FW-memory-mode-via-DT.patch @@ -31,7 +31,7 @@ Signed-off-by: Robert Marko { .hw_rev = ATH11K_HW_IPQ8074, .name = "ipq8074 hw2.0", -@@ -1954,7 +1954,8 @@ static void ath11k_core_reset(struct wor +@@ -1974,7 +1974,8 @@ static void ath11k_core_reset(struct wor static int ath11k_init_hw_params(struct ath11k_base *ab) { const struct ath11k_hw_params *hw_params = NULL; @@ -41,7 +41,7 @@ Signed-off-by: Robert Marko for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) { hw_params = &ath11k_hw_params[i]; -@@ -1970,7 +1971,30 @@ static int ath11k_init_hw_params(struct +@@ -1990,7 +1991,31 @@ static int ath11k_init_hw_params(struct ab->hw_params = *hw_params; @@ -62,7 +62,8 @@ Signed-off-by: Robert Marko + ab->hw_params.fw_mem_mode = 2; + ab->hw_params.num_vdevs = 8; + ab->hw_params.num_peers = 128; -+ ab->hw_params.cold_boot_calib = false; ++ ab->hw_params.coldboot_cal_mm = false; ++ ab->hw_params.coldboot_cal_ftm = false; + } else + ath11k_info(ab, "Unsupported FW memory mode: %u\n", fw_mem_mode); + } From d2ce3a61aa1cbc53988eb640cbab48e20fbfb1aa Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 31 Aug 2023 21:10:23 +0200 Subject: [PATCH 05/24] ath79: fix packetloss on some WLR-7100 On some WLR-7100 routers, significant packet loss was observed. This is fixed by configuring a delay on the GMAC0 RXD and RXDV lines. The values used in this commit are copied from the values used by the stock firmare (based on register dumping). Out of four test routers, the problem was consistently observed on two. It is unclear what the relevant difference is exactly (the two working routers were v1 001 with AR1022 and v1 002 with AR9342, the two broken routers were both v1 002 with AR1022). All PCB routing also seems identical, so maybe there is some stray capacitance on some of these that adds just enough delay or so... With this change, the packet loss disappears on the broken routers, without introducing new packet loss on the previously working routers. Note that the PHY *also* has delays enabled (through `qca,ar8327-initvals`) on both RX and TX lines, but apparently that is not enough, or it is not effective (registers have been verified to be written). For detailed discussion of this issue and debug history, see https://forum.openwrt.org/t/sitecom-wlr-7100-development-progress/79641 Signed-off-by: Matthijs Kooijman --- target/linux/ath79/dts/ar1022_sitecom_wlr-7100.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/ath79/dts/ar1022_sitecom_wlr-7100.dts b/target/linux/ath79/dts/ar1022_sitecom_wlr-7100.dts index d008dd5ec8..e2ccef105d 100644 --- a/target/linux/ath79/dts/ar1022_sitecom_wlr-7100.dts +++ b/target/linux/ath79/dts/ar1022_sitecom_wlr-7100.dts @@ -65,6 +65,8 @@ gmac-config { device = <&gmac>; rgmii-gmac0 = <1>; + rxdv-delay = <3>; + rxd-delay = <3>; }; }; From 9bfbdfa77890b0e77a6bf89e84a42a7fcc0e81ff Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 14 Aug 2023 12:56:49 +0200 Subject: [PATCH 06/24] ipq40xx: move DSA and ethernet driver to 5.15 specific directory As a preparation to move to 6.1, we need to move the DSA and ethernet drivers to a 5.15 specific directory as 6.1 will use the latest patchset that was sent upstream which is too hard to backport to 5.15. Signed-off-by: Robert Marko --- .../{files => files-5.15}/drivers/net/dsa/qca/qca8k-ipq4019.c | 0 .../{files => files-5.15}/drivers/net/dsa/qca/qca8k-ipq4019.h | 0 .../drivers/net/ethernet/qualcomm/ipqess/Makefile | 0 .../drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 0 .../drivers/net/ethernet/qualcomm/ipqess/ipqess.h | 0 .../drivers/net/ethernet/qualcomm/ipqess/ipqess_ethtool.c | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename target/linux/ipq40xx/{files => files-5.15}/drivers/net/dsa/qca/qca8k-ipq4019.c (100%) rename target/linux/ipq40xx/{files => files-5.15}/drivers/net/dsa/qca/qca8k-ipq4019.h (100%) rename target/linux/ipq40xx/{files => files-5.15}/drivers/net/ethernet/qualcomm/ipqess/Makefile (100%) rename target/linux/ipq40xx/{files => files-5.15}/drivers/net/ethernet/qualcomm/ipqess/ipqess.c (100%) rename target/linux/ipq40xx/{files => files-5.15}/drivers/net/ethernet/qualcomm/ipqess/ipqess.h (100%) rename target/linux/ipq40xx/{files => files-5.15}/drivers/net/ethernet/qualcomm/ipqess/ipqess_ethtool.c (100%) diff --git a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c b/target/linux/ipq40xx/files-5.15/drivers/net/dsa/qca/qca8k-ipq4019.c similarity index 100% rename from target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c rename to target/linux/ipq40xx/files-5.15/drivers/net/dsa/qca/qca8k-ipq4019.c diff --git a/target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h b/target/linux/ipq40xx/files-5.15/drivers/net/dsa/qca/qca8k-ipq4019.h similarity index 100% rename from target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h rename to target/linux/ipq40xx/files-5.15/drivers/net/dsa/qca/qca8k-ipq4019.h diff --git a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/Makefile b/target/linux/ipq40xx/files-5.15/drivers/net/ethernet/qualcomm/ipqess/Makefile similarity index 100% rename from target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/Makefile rename to target/linux/ipq40xx/files-5.15/drivers/net/ethernet/qualcomm/ipqess/Makefile diff --git a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.c b/target/linux/ipq40xx/files-5.15/drivers/net/ethernet/qualcomm/ipqess/ipqess.c similarity index 100% rename from target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.c rename to target/linux/ipq40xx/files-5.15/drivers/net/ethernet/qualcomm/ipqess/ipqess.c diff --git a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.h b/target/linux/ipq40xx/files-5.15/drivers/net/ethernet/qualcomm/ipqess/ipqess.h similarity index 100% rename from target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess.h rename to target/linux/ipq40xx/files-5.15/drivers/net/ethernet/qualcomm/ipqess/ipqess.h diff --git a/target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess_ethtool.c b/target/linux/ipq40xx/files-5.15/drivers/net/ethernet/qualcomm/ipqess/ipqess_ethtool.c similarity index 100% rename from target/linux/ipq40xx/files/drivers/net/ethernet/qualcomm/ipqess/ipqess_ethtool.c rename to target/linux/ipq40xx/files-5.15/drivers/net/ethernet/qualcomm/ipqess/ipqess_ethtool.c From 70dfb696c03bcfc1231ebdf16d8ddbae8d7eccf7 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 14 Aug 2023 13:06:27 +0200 Subject: [PATCH 07/24] ipq40xx: update ESS reset patch with pending upstream Use the split version of ESS reset patch that was sent upstream. Signed-off-by: Robert Marko --- ...k-qcom-ipq4019-add-missing-networkin.patch | 27 ++++++++++ ...pq4019-add-missing-networking-resets.patch | 28 ++++++++++ .../300-clk-qcom-ipq4019-add-ess-reset.patch | 52 ------------------- 3 files changed, 55 insertions(+), 52 deletions(-) create mode 100644 target/linux/ipq40xx/patches-5.15/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch create mode 100644 target/linux/ipq40xx/patches-5.15/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch delete mode 100644 target/linux/ipq40xx/patches-5.15/300-clk-qcom-ipq4019-add-ess-reset.patch diff --git a/target/linux/ipq40xx/patches-5.15/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch b/target/linux/ipq40xx/patches-5.15/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch new file mode 100644 index 0000000000..ae59005bba --- /dev/null +++ b/target/linux/ipq40xx/patches-5.15/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch @@ -0,0 +1,27 @@ +From 53cac0823f86c39eb4b00e2c9a7b2483a4182008 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 14 Aug 2023 12:37:58 +0200 +Subject: [PATCH 1/2] dt-bindings: clock: qcom: ipq4019: add missing networking + resets + +Add bindings for the missing networking resets found in IPQ4019 GCC. + +Signed-off-by: Robert Marko +--- + include/dt-bindings/clock/qcom,gcc-ipq4019.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/include/dt-bindings/clock/qcom,gcc-ipq4019.h ++++ b/include/dt-bindings/clock/qcom,gcc-ipq4019.h +@@ -165,5 +165,11 @@ + #define GCC_QDSS_BCR 69 + #define GCC_MPM_BCR 70 + #define GCC_SPDM_BCR 71 ++#define ESS_MAC1_ARES 72 ++#define ESS_MAC2_ARES 73 ++#define ESS_MAC3_ARES 74 ++#define ESS_MAC4_ARES 75 ++#define ESS_MAC5_ARES 76 ++#define ESS_PSGMII_ARES 77 + + #endif diff --git a/target/linux/ipq40xx/patches-5.15/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch b/target/linux/ipq40xx/patches-5.15/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch new file mode 100644 index 0000000000..42a2f341be --- /dev/null +++ b/target/linux/ipq40xx/patches-5.15/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch @@ -0,0 +1,28 @@ +From 6038ba75e2aa8e57d4eaf20a90c8061c43b1117f Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 14 Aug 2023 12:39:04 +0200 +Subject: [PATCH 2/2] clk: qcom: gcc-ipq4019: add missing networking resets + +IPQ4019 has more networking related resets that will be required for future +wired networking support, so lets add them. + +Signed-off-by: Robert Marko +--- + drivers/clk/qcom/gcc-ipq4019.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/clk/qcom/gcc-ipq4019.c ++++ b/drivers/clk/qcom/gcc-ipq4019.c +@@ -1707,6 +1707,12 @@ static const struct qcom_reset_map gcc_i + [GCC_TCSR_BCR] = {0x22000, 0}, + [GCC_MPM_BCR] = {0x24000, 0}, + [GCC_SPDM_BCR] = {0x25000, 0}, ++ [ESS_MAC1_ARES] = {0x1200C, 0}, ++ [ESS_MAC2_ARES] = {0x1200C, 1}, ++ [ESS_MAC3_ARES] = {0x1200C, 2}, ++ [ESS_MAC4_ARES] = {0x1200C, 3}, ++ [ESS_MAC5_ARES] = {0x1200C, 4}, ++ [ESS_PSGMII_ARES] = {0x1200C, 5}, + }; + + static const struct regmap_config gcc_ipq4019_regmap_config = { diff --git a/target/linux/ipq40xx/patches-5.15/300-clk-qcom-ipq4019-add-ess-reset.patch b/target/linux/ipq40xx/patches-5.15/300-clk-qcom-ipq4019-add-ess-reset.patch deleted file mode 100644 index eb015251a1..0000000000 --- a/target/linux/ipq40xx/patches-5.15/300-clk-qcom-ipq4019-add-ess-reset.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 480c1f7648fc586db12d6003c717c23667a4fcf0 Mon Sep 17 00:00:00 2001 -From: Ram Chandra Jangir -Date: Tue, 28 Mar 2017 22:35:33 +0530 -Subject: [PATCH] clk: qcom: ipq4019: add ess reset - -Added the ESS reset in IPQ4019 GCC. - -Signed-off-by: Ram Chandra Jangir ---- - drivers/clk/qcom/gcc-ipq4019.c | 11 +++++++++++ - include/dt-bindings/clock/qcom,gcc-ipq4019.h | 11 +++++++++++ - 2 files changed, 22 insertions(+) - ---- a/drivers/clk/qcom/gcc-ipq4019.c -+++ b/drivers/clk/qcom/gcc-ipq4019.c -@@ -1735,6 +1735,17 @@ static const struct qcom_reset_map gcc_i - [GCC_TCSR_BCR] = {0x22000, 0}, - [GCC_MPM_BCR] = {0x24000, 0}, - [GCC_SPDM_BCR] = {0x25000, 0}, -+ [ESS_MAC1_ARES] = {0x1200C, 0}, -+ [ESS_MAC2_ARES] = {0x1200C, 1}, -+ [ESS_MAC3_ARES] = {0x1200C, 2}, -+ [ESS_MAC4_ARES] = {0x1200C, 3}, -+ [ESS_MAC5_ARES] = {0x1200C, 4}, -+ [ESS_PSGMII_ARES] = {0x1200C, 5}, -+ [ESS_MAC1_CLK_DIS] = {0x1200C, 8}, -+ [ESS_MAC2_CLK_DIS] = {0x1200C, 9}, -+ [ESS_MAC3_CLK_DIS] = {0x1200C, 10}, -+ [ESS_MAC4_CLK_DIS] = {0x1200C, 11}, -+ [ESS_MAC5_CLK_DIS] = {0x1200C, 12}, - }; - - static const struct regmap_config gcc_ipq4019_regmap_config = { ---- a/include/dt-bindings/clock/qcom,gcc-ipq4019.h -+++ b/include/dt-bindings/clock/qcom,gcc-ipq4019.h -@@ -165,5 +165,16 @@ - #define GCC_QDSS_BCR 69 - #define GCC_MPM_BCR 70 - #define GCC_SPDM_BCR 71 -+#define ESS_MAC1_ARES 72 -+#define ESS_MAC2_ARES 73 -+#define ESS_MAC3_ARES 74 -+#define ESS_MAC4_ARES 75 -+#define ESS_MAC5_ARES 76 -+#define ESS_PSGMII_ARES 77 -+#define ESS_MAC1_CLK_DIS 78 -+#define ESS_MAC2_CLK_DIS 79 -+#define ESS_MAC3_CLK_DIS 80 -+#define ESS_MAC4_CLK_DIS 81 -+#define ESS_MAC5_CLK_DIS 82 - - #endif From bd242a42a6142c4c7c5cf69ac836a31276e86155 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 14 Aug 2023 13:16:12 +0200 Subject: [PATCH 08/24] ipq40xx: copy 5.15 patches and config to 6.1 Copy the 5.15 patches and config as a base for 6.1 support. Signed-off-by: Robert Marko --- target/linux/ipq40xx/config-6.1 | 508 ++++++++++++++++++ ...k-qcom-ipq4019-add-missing-networkin.patch | 27 + ...pq4019-add-missing-networking-resets.patch | 28 + .../104-clk-fix-apss-cpu-overclocking.patch | 115 ++++ ...-compressed-add-appended-DTB-section.patch | 48 ++ ...d-set-ipq40xx-watchdog-to-allow-boot.patch | 66 +++ ...msm-use-sdhci_set_clock-instead-of-s.patch | 24 + ...m-comment-unused-sdhci_msm_set_clock.patch | 108 ++++ ...are-qcom-scm-Add-SDI-disable-support.patch | 60 +++ ...-qcom-scm-disable-SDI-on-Google-WiFi.patch | 34 ++ ...e-qcom-scm-fix-SCM-cold-boot-address.patch | 138 +++++ ...-add-support-for-Toshiba-TC58NVG0S3H.patch | 29 + ...pecific-data-to-struct-skb_shared_in.patch | 43 ++ ...019-add-shinfo-based-tagging-driver-.patch | 187 +++++++ ...ethernet-qualcomm-add-IPQESS-support.patch | 43 ++ ...4019-add-ethernet-controller-DT-node.patch | 81 +++ ...phy-define-PSGMII-PHY-interface-mode.patch | 69 +++ ...comm-IPQ4019-built-in-switch-support.patch | 57 ++ .../706-arm-dts-ipq4019-add-switch-node.patch | 98 ++++ .../707-dt-bindings-net-add-QCA807x-PHY.patch | 61 +++ ...8-net-phy-Add-Qualcom-QCA807x-driver.patch | 50 ++ ...9-arm-dts-ipq4019-QCA807x-properties.patch | 61 +++ .../850-soc-add-qualcomm-syscon.patch | 180 +++++++ ...qcom_scm-Clear-download-bit-during-r.patch | 27 + .../patches-6.1/998-lantiq-atm-hacks.patch | 43 ++ .../999-atm-mpoa-intel-dsl-phy-support.patch | 137 +++++ 26 files changed, 2322 insertions(+) create mode 100644 target/linux/ipq40xx/config-6.1 create mode 100644 target/linux/ipq40xx/patches-6.1/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch create mode 100644 target/linux/ipq40xx/patches-6.1/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch create mode 100644 target/linux/ipq40xx/patches-6.1/104-clk-fix-apss-cpu-overclocking.patch create mode 100644 target/linux/ipq40xx/patches-6.1/301-arm-compressed-add-appended-DTB-section.patch create mode 100644 target/linux/ipq40xx/patches-6.1/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch create mode 100644 target/linux/ipq40xx/patches-6.1/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch create mode 100644 target/linux/ipq40xx/patches-6.1/401-mmc-sdhci-msm-comment-unused-sdhci_msm_set_clock.patch create mode 100644 target/linux/ipq40xx/patches-6.1/420-firmware-qcom-scm-Add-SDI-disable-support.patch create mode 100644 target/linux/ipq40xx/patches-6.1/421-firmware-qcom-scm-disable-SDI-on-Google-WiFi.patch create mode 100644 target/linux/ipq40xx/patches-6.1/422-firmware-qcom-scm-fix-SCM-cold-boot-address.patch create mode 100644 target/linux/ipq40xx/patches-6.1/444-mtd-nand-rawnand-add-support-for-Toshiba-TC58NVG0S3H.patch create mode 100644 target/linux/ipq40xx/patches-6.1/700-skbuff-add-DSA-specific-data-to-struct-skb_shared_in.patch create mode 100644 target/linux/ipq40xx/patches-6.1/701-net-dsa-tag_ipq4019-add-shinfo-based-tagging-driver-.patch create mode 100644 target/linux/ipq40xx/patches-6.1/702-net-ethernet-qualcomm-add-IPQESS-support.patch create mode 100644 target/linux/ipq40xx/patches-6.1/703-arm-dts-ipq4019-add-ethernet-controller-DT-node.patch create mode 100644 target/linux/ipq40xx/patches-6.1/704-net-phy-define-PSGMII-PHY-interface-mode.patch create mode 100644 target/linux/ipq40xx/patches-6.1/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch create mode 100644 target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch create mode 100644 target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch create mode 100644 target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch create mode 100644 target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch create mode 100644 target/linux/ipq40xx/patches-6.1/850-soc-add-qualcomm-syscon.patch create mode 100644 target/linux/ipq40xx/patches-6.1/910-Revert-firmware-qcom_scm-Clear-download-bit-during-r.patch create mode 100644 target/linux/ipq40xx/patches-6.1/998-lantiq-atm-hacks.patch create mode 100644 target/linux/ipq40xx/patches-6.1/999-atm-mpoa-intel-dsl-phy-support.patch diff --git a/target/linux/ipq40xx/config-6.1 b/target/linux/ipq40xx/config-6.1 new file mode 100644 index 0000000000..0acc013a81 --- /dev/null +++ b/target/linux/ipq40xx/config-6.1 @@ -0,0 +1,508 @@ +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_APQ_GCC_8084 is not set +# CONFIG_APQ_MMCC_8084 is not set +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_IPQ40XX=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +# CONFIG_ARCH_MDM9615 is not set +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_ARCH_MSM8960 is not set +# CONFIG_ARCH_MSM8974 is not set +# CONFIG_ARCH_MSM8X60 is not set +CONFIG_ARCH_MULTIPLATFORM=y +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ATAG_DTB_COMPAT is not set +CONFIG_ARM_CPUIDLE=y +# CONFIG_ARM_CPU_TOPOLOGY is not set +CONFIG_ARM_CRYPTO=y +CONFIG_ARM_GIC=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +# CONFIG_ARM_QCOM_CPUFREQ_HW is not set +# CONFIG_ARM_QCOM_CPUFREQ_NVMEM is not set +# CONFIG_ARM_QCOM_SPM_CPUIDLE is not set +# CONFIG_ARM_SMMU is not set +CONFIG_ARM_THUMB=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_AT803X_PHY=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BCH=y +CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BOUNCE=y +# CONFIG_CACHE_L2X0 is not set +CONFIG_CLKSRC_QCOM=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE_PARTITION=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_QCOM=y +CONFIG_COMPAT_32BIT_TIME=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_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=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_CRC32_SARWATE is not set +CONFIG_CRC32_SLICEBY8=y +CONFIG_CRC8=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_BS=y +CONFIG_CRYPTO_BLAKE2S_ARM=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEV_QCE=y +# CONFIG_CRYPTO_DEV_QCE_ENABLE_AEAD is not set +# CONFIG_CRYPTO_DEV_QCE_ENABLE_ALL is not set +# CONFIG_CRYPTO_DEV_QCE_ENABLE_SHA is not set +CONFIG_CRYPTO_DEV_QCE_ENABLE_SKCIPHER=y +CONFIG_CRYPTO_DEV_QCE_SKCIPHER=y +CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN=512 +CONFIG_CRYPTO_DEV_QCOM_RNG=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_DES=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA256_ARM=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SIMD=y +CONFIG_CRYPTO_XTS=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +CONFIG_DEBUG_MISC=y +CONFIG_DMADEVICES=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS=y +CONFIG_DMA_REMAP=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DTC=y +CONFIG_DT_IDLE_STATES=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EEPROM_AT24=y +CONFIG_EXTCON=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=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_MSI_IRQ_DOMAIN=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_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_74X164=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_WATCHDOG=y +CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y +CONFIG_GRO_CELLS=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAVE_SMP=y +CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_OPTEE=y +CONFIG_HZ_FIXED=0 +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_INITRAMFS_SOURCE="" +# 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_IPQ_APSS_PLL is not set +CONFIG_IPQ_GCC_4019=y +# CONFIG_IPQ_GCC_6018 is not set +# CONFIG_IPQ_GCC_806X is not set +# CONFIG_IPQ_GCC_8074 is not set +# CONFIG_IPQ_LCC_806X 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_WORK=y +CONFIG_KMAP_LOCAL=y +CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y +# CONFIG_KPSS_XCC is not set +# CONFIG_KRAITCC is not set +CONFIG_LEDS_LP5523=y +CONFIG_LEDS_LP5562=y +CONFIG_LEDS_LP55XX_COMMON=y +CONFIG_LEDS_TLC591XX=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MDIO_GPIO=y +CONFIG_MDIO_IPQ4019=y +# CONFIG_MDM_GCC_9615 is not set +# CONFIG_MDM_LCC_9615 is not set +CONFIG_MEMFD_CREATE=y +# CONFIG_MFD_HI6421_SPMI is not set +# CONFIG_MFD_QCOM_RPM is not set +# CONFIG_MFD_SPMI_PMIC is not set +CONFIG_MFD_SYSCON=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_MSM=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MODULES_USE_ELF_REL=y +# CONFIG_MSM_GCC_8660 is not set +# CONFIG_MSM_GCC_8916 is not set +# CONFIG_MSM_GCC_8939 is not set +# CONFIG_MSM_GCC_8960 is not set +# CONFIG_MSM_GCC_8974 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_LCC_8960 is not set +# CONFIG_MSM_MMCC_8960 is not set +# CONFIG_MSM_MMCC_8974 is not set +# CONFIG_MSM_MMCC_8996 is not set +# CONFIG_MSM_MMCC_8998 is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_SW_BCH=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_QCOM=y +# CONFIG_MTD_QCOMSMEM_PARTS is not set +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_SPLIT_WRGG_FW=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_NEON=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_QCA8K_IPQ4019=y +CONFIG_NET_DSA_TAG_IPQ4019=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SWITCHDEV=y +CONFIG_NLS=y +CONFIG_NO_HZ=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_QCOM_QFPROM=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_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OPTEE=y +CONFIG_OPTEE_SHM_NUM_PRIV_PAGES=1 +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_QCOM=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +# CONFIG_PHY_QCOM_APQ8064_SATA is not set +CONFIG_PHY_QCOM_IPQ4019_USB=y +# CONFIG_PHY_QCOM_IPQ806X_SATA is not set +# CONFIG_PHY_QCOM_IPQ806X_USB is not set +# CONFIG_PHY_QCOM_PCIE2 is not set +# CONFIG_PHY_QCOM_QMP is not set +# CONFIG_PHY_QCOM_QUSB2 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_APQ8064 is not set +# CONFIG_PINCTRL_APQ8084 is not set +CONFIG_PINCTRL_IPQ4019=y +# CONFIG_PINCTRL_IPQ6018 is not set +# CONFIG_PINCTRL_IPQ8064 is not set +# CONFIG_PINCTRL_IPQ8074 is not set +# CONFIG_PINCTRL_MDM9615 is not set +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_MSM8226 is not set +# CONFIG_PINCTRL_MSM8660 is not set +# CONFIG_PINCTRL_MSM8916 is not set +# CONFIG_PINCTRL_MSM8960 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_QCOM_SPMI_PMIC is not set +# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set +# CONFIG_PINCTRL_QCS404 is not set +# CONFIG_PINCTRL_SC7180 is not set +# CONFIG_PINCTRL_SDM660 is not set +# CONFIG_PINCTRL_SDM845 is not set +# CONFIG_PINCTRL_SM8150 is not set +# CONFIG_PINCTRL_SM8250 is not set +CONFIG_PM_OPP=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO_RESTART=y +CONFIG_POWER_RESET_MSM=y +CONFIG_POWER_SUPPLY=y +CONFIG_PPS=y +CONFIG_PRINTK_TIME=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_QCA807X_PHY=y +CONFIG_QCOM_A53PLL=y +# CONFIG_QCOM_ADM is not set +CONFIG_QCOM_BAM_DMA=y +# CONFIG_QCOM_COMMAND_DB is not set +# CONFIG_QCOM_CPR is not set +# CONFIG_QCOM_EBI2 is not set +# CONFIG_QCOM_GENI_SE is not set +# CONFIG_QCOM_GSBI is not set +# CONFIG_QCOM_HFPLL is not set +# CONFIG_QCOM_IOMMU is not set +CONFIG_QCOM_IPQ4019_ESS_EDMA=y +# CONFIG_QCOM_LLCC is not set +# CONFIG_QCOM_OCMEM is not set +# CONFIG_QCOM_PDC is not set +# CONFIG_QCOM_RMTFS_MEM is not set +# CONFIG_QCOM_RPMH is not set +CONFIG_QCOM_SCM=y +# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set +CONFIG_QCOM_SMEM=y +# CONFIG_QCOM_SMSM is not set +# CONFIG_QCOM_SOCINFO is not set +CONFIG_QCOM_TCSR=y +# CONFIG_QCOM_TSENS 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_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_QCOM_LABIBB is not set +# CONFIG_REGULATOR_QCOM_SPMI is not set +# CONFIG_REGULATOR_QCOM_USB_VBUS is not set +CONFIG_REGULATOR_VCTRL=y +CONFIG_REGULATOR_VQMMC_IPQ4019=y +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_QCOM_AOSS is not set +# CONFIG_RESET_QCOM_PDC is not set +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTC_MC146818_LIB=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +# CONFIG_SC_DISPCC_7180 is not set +# CONFIG_SC_GCC_7180 is not set +# CONFIG_SC_GPUCC_7180 is not set +# CONFIG_SC_LPASS_CORECC_7180 is not set +# CONFIG_SC_MSS_7180 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_SERIAL_8250_FSL=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SGL_ALLOC=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +# CONFIG_SM_GCC_8150 is not set +# CONFIG_SM_GCC_8250 is not set +# CONFIG_SM_GPUCC_8150 is not set +# CONFIG_SM_GPUCC_8250 is not set +# CONFIG_SM_VIDEOCC_8150 is not set +# CONFIG_SM_VIDEOCC_8250 is not set +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_QUP=y +CONFIG_SPMI=y +# CONFIG_SPMI_HISI3670 is not set +CONFIG_SPMI_MSM_PMIC_ARB=y +# CONFIG_SPMI_PMIC_CLKDIV is not set +CONFIG_SRCU=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_TEE=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_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_UEVENT_HELPER_PATH="" +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_UNWINDER_ARM=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/target/linux/ipq40xx/patches-6.1/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch b/target/linux/ipq40xx/patches-6.1/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch new file mode 100644 index 0000000000..ae59005bba --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch @@ -0,0 +1,27 @@ +From 53cac0823f86c39eb4b00e2c9a7b2483a4182008 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 14 Aug 2023 12:37:58 +0200 +Subject: [PATCH 1/2] dt-bindings: clock: qcom: ipq4019: add missing networking + resets + +Add bindings for the missing networking resets found in IPQ4019 GCC. + +Signed-off-by: Robert Marko +--- + include/dt-bindings/clock/qcom,gcc-ipq4019.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/include/dt-bindings/clock/qcom,gcc-ipq4019.h ++++ b/include/dt-bindings/clock/qcom,gcc-ipq4019.h +@@ -165,5 +165,11 @@ + #define GCC_QDSS_BCR 69 + #define GCC_MPM_BCR 70 + #define GCC_SPDM_BCR 71 ++#define ESS_MAC1_ARES 72 ++#define ESS_MAC2_ARES 73 ++#define ESS_MAC3_ARES 74 ++#define ESS_MAC4_ARES 75 ++#define ESS_MAC5_ARES 76 ++#define ESS_PSGMII_ARES 77 + + #endif diff --git a/target/linux/ipq40xx/patches-6.1/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch b/target/linux/ipq40xx/patches-6.1/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch new file mode 100644 index 0000000000..42a2f341be --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch @@ -0,0 +1,28 @@ +From 6038ba75e2aa8e57d4eaf20a90c8061c43b1117f Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 14 Aug 2023 12:39:04 +0200 +Subject: [PATCH 2/2] clk: qcom: gcc-ipq4019: add missing networking resets + +IPQ4019 has more networking related resets that will be required for future +wired networking support, so lets add them. + +Signed-off-by: Robert Marko +--- + drivers/clk/qcom/gcc-ipq4019.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/clk/qcom/gcc-ipq4019.c ++++ b/drivers/clk/qcom/gcc-ipq4019.c +@@ -1707,6 +1707,12 @@ static const struct qcom_reset_map gcc_i + [GCC_TCSR_BCR] = {0x22000, 0}, + [GCC_MPM_BCR] = {0x24000, 0}, + [GCC_SPDM_BCR] = {0x25000, 0}, ++ [ESS_MAC1_ARES] = {0x1200C, 0}, ++ [ESS_MAC2_ARES] = {0x1200C, 1}, ++ [ESS_MAC3_ARES] = {0x1200C, 2}, ++ [ESS_MAC4_ARES] = {0x1200C, 3}, ++ [ESS_MAC5_ARES] = {0x1200C, 4}, ++ [ESS_PSGMII_ARES] = {0x1200C, 5}, + }; + + static const struct regmap_config gcc_ipq4019_regmap_config = { diff --git a/target/linux/ipq40xx/patches-6.1/104-clk-fix-apss-cpu-overclocking.patch b/target/linux/ipq40xx/patches-6.1/104-clk-fix-apss-cpu-overclocking.patch new file mode 100644 index 0000000000..2de03f7ae0 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/104-clk-fix-apss-cpu-overclocking.patch @@ -0,0 +1,115 @@ +From f2b87dc1028b710ec8ce25808b9d21f92b376184 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sun, 11 Mar 2018 14:41:31 +0100 +Subject: [PATCH 2/2] clk: fix apss cpu overclocking + +There's an interaction issue between the clk changes:" +clk: qcom: ipq4019: Add the apss cpu pll divider clock node +clk: qcom: ipq4019: remove fixed clocks and add pll clocks +" and the cpufreq-dt. + +cpufreq-dt is now spamming the kernel-log with the following: + +[ 1099.190658] cpu cpu0: dev_pm_opp_set_rate: failed to find current OPP +for freq 761142857 (-34) + +This only happens on certain devices like the Compex WPJ428 +and AVM FritzBox!4040. However, other devices like the Asus +RT-AC58U and Meraki MR33 work just fine. + +The issue stem from the fact that all higher CPU-Clocks +are achieved by switching the clock-parent to the P_DDRPLLAPSS +(ddrpllapss). Which is set by Qualcomm's proprietary bootcode +as part of the DDR calibration. + +For example, the FB4040 uses 256 MiB Nanya NT5CC128M16IP clocked +at round 533 MHz (ddrpllsdcc = 190285714 Hz). + +whereas the 128 MiB Nanya NT5CC64M16GP-DI in the ASUS RT-AC58U is +clocked at a slightly higher 537 MHz ( ddrpllsdcc = 192000000 Hz). + +This patch attempts to fix the issue by modifying +clk_cpu_div_round_rate(), clk_cpu_div_set_rate(), clk_cpu_div_recalc_rate() +to use a new qcom_find_freq_close() function, which returns the closest +matching frequency, instead of the next higher. This way, the SoC in +the FB4040 (with its max clock speed of 710.4 MHz) will no longer +try to overclock to 761 MHz. + +Fixes: d83dcacea18 ("clk: qcom: ipq4019: Add the apss cpu pll divider clock node") +Signed-off-by: Christian Lamparter +Signed-off-by: John Crispin +--- + drivers/clk/qcom/gcc-ipq4019.c | 34 +++++++++++++++++++++++++++++++--- + 1 file changed, 31 insertions(+), 3 deletions(-) + +--- a/drivers/clk/qcom/gcc-ipq4019.c ++++ b/drivers/clk/qcom/gcc-ipq4019.c +@@ -1243,6 +1243,29 @@ static const struct clk_fepll_vco gcc_fe + .reg = 0x2f020, + }; + ++ ++const struct freq_tbl *qcom_find_freq_close(const struct freq_tbl *f, ++ unsigned long rate) ++{ ++ const struct freq_tbl *last = NULL; ++ ++ for ( ; f->freq; f++) { ++ if (rate == f->freq) ++ return f; ++ ++ if (f->freq > rate) { ++ if (!last || ++ (f->freq - rate) < (rate - last->freq)) ++ return f; ++ else ++ return last; ++ } ++ last = f; ++ } ++ ++ return last; ++} ++ + /* + * Round rate function for APSS CPU PLL Clock divider. + * It looks up the frequency table and returns the next higher frequency +@@ -1255,7 +1278,7 @@ static long clk_cpu_div_round_rate(struc + struct clk_hw *p_hw; + const struct freq_tbl *f; + +- f = qcom_find_freq(pll->freq_tbl, rate); ++ f = qcom_find_freq_close(pll->freq_tbl, rate); + if (!f) + return -EINVAL; + +@@ -1277,7 +1300,7 @@ static int clk_cpu_div_set_rate(struct c + const struct freq_tbl *f; + u32 mask; + +- f = qcom_find_freq(pll->freq_tbl, rate); ++ f = qcom_find_freq_close(pll->freq_tbl, rate); + if (!f) + return -EINVAL; + +@@ -1304,6 +1327,7 @@ static unsigned long + clk_cpu_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { ++ const struct freq_tbl *f; + struct clk_fepll *pll = to_clk_fepll(hw); + u32 cdiv, pre_div; + u64 rate; +@@ -1324,7 +1348,11 @@ clk_cpu_div_recalc_rate(struct clk_hw *h + rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2; + do_div(rate, pre_div); + +- return rate; ++ f = qcom_find_freq_close(pll->freq_tbl, rate); ++ if (!f) ++ return rate; ++ ++ return f->freq; + }; + + static const struct clk_ops clk_regmap_cpu_div_ops = { diff --git a/target/linux/ipq40xx/patches-6.1/301-arm-compressed-add-appended-DTB-section.patch b/target/linux/ipq40xx/patches-6.1/301-arm-compressed-add-appended-DTB-section.patch new file mode 100644 index 0000000000..0448574e7e --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/301-arm-compressed-add-appended-DTB-section.patch @@ -0,0 +1,48 @@ +From 0843a61d6913bdac8889eb048ed89f7903059787 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 30 Oct 2020 13:36:31 +0100 +Subject: [PATCH] arm: compressed: add appended DTB section + +This adds a appended_dtb section to the ARM decompressor +linker script. + +This allows using the existing ARM zImage appended DTB support for +appending a DTB to the raw ELF kernel. + +Its size is set to 1MB max to match the zImage appended DTB size limit. + +To use it to pass the DTB to the kernel, objcopy is used: + +objcopy --set-section-flags=.appended_dtb=alloc,contents \ + --update-section=.appended_dtb=.dtb vmlinux + +This is based off the following patch: +https://github.com/openwrt/openwrt/commit/c063e27e02a9dcac0e7f5877fb154e58fa3e1a69 + +Signed-off-by: Robert Marko +--- + arch/arm/boot/compressed/vmlinux.lds.S | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/compressed/vmlinux.lds.S ++++ b/arch/arm/boot/compressed/vmlinux.lds.S +@@ -103,6 +103,13 @@ SECTIONS + + _edata = .; + ++ .appended_dtb : { ++ /* leave space for appended DTB */ ++ . += 0x100000; ++ } ++ ++ _edata_dtb = .; ++ + /* + * The image_end section appears after any additional loadable sections + * that the linker may decide to insert in the binary image. Having +@@ -140,4 +147,4 @@ SECTIONS + + ARM_ASSERTS + } +-ASSERT(_edata_real == _edata, "error: zImage file size is incorrect"); ++ASSERT(_edata_real == _edata_dtb, "error: zImage file size is incorrect"); diff --git a/target/linux/ipq40xx/patches-6.1/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch b/target/linux/ipq40xx/patches-6.1/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch new file mode 100644 index 0000000000..51891c1f22 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch @@ -0,0 +1,66 @@ +From 11d6a6128a5a07c429941afc202b6e62a19771be Mon Sep 17 00:00:00 2001 +From: John Thomson +Date: Fri, 23 Oct 2020 19:42:36 +1000 +Subject: [PATCH 2/2] arm: compressed: set ipq40xx watchdog to allow boot + +For IPQ40XX systems where the SoC watchdog is activated before linux, +the watchdog timer may be too small for linux to finish uncompress, +boot, and watchdog management start. +If the watchdog is enabled, set the timeout for it to 30 seconds. +The functionality and offsets were copied from: +drivers/watchdog/qcom-wdt.c qcom_wdt_set_timeout & qcom_wdt_start +The watchdog memory address was taken from: +arch/arm/boot/dts/qcom-ipq4019.dtsi + +This was required on Mikrotik IPQ40XX consumer hardware using Mikrotik's +RouterBoot bootloader. + +Signed-off-by: John Thomson +--- + arch/arm/boot/compressed/head.S | 35 +++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -624,6 +624,41 @@ not_relocated: mov r0, #0 + bic r4, r4, #1 + blne cache_on + ++/* Set the Qualcom IPQ40xx watchdog timeout to 30 seconds ++ * if it is enabled, so that there is time for kernel ++ * to decompress, boot, and take over the watchdog. ++ * data and functionality from drivers/watchdog/qcom-wdt.c ++ * address from arch/arm/boot/dts/qcom-ipq4019.dtsi ++ */ ++#ifdef CONFIG_ARCH_IPQ40XX ++watchdog_set: ++ /* offsets: ++ * 0x04 reset (=1 resets countdown) ++ * 0x08 enable (=0 disables) ++ * 0x0c status (=1 when SoC was reset by watchdog) ++ * 0x10 bark (=timeout warning in ticks) ++ * 0x14 bite (=timeout reset in ticks) ++ * clock rate is 1<<15 hertz ++ */ ++ .equ watchdog, 0x0b017000 @Store watchdog base address ++ movw r0, #:lower16:watchdog ++ movt r0, #:upper16:watchdog ++ ldr r1, [r0, #0x08] @Get enabled? ++ cmp r1, #1 @If not enabled, do not change ++ bne watchdog_finished ++ mov r1, #0 ++ str r1, [r0, #0x08] @Disable the watchdog ++ mov r1, #1 ++ str r1, [r0, #0x04] @Pet the watchdog ++ mov r1, #30 @30 seconds timeout ++ lsl r1, r1, #15 @converted to ticks ++ str r1, [r0, #0x10] @Set the bark timeout ++ str r1, [r0, #0x14] @Set the bite timeout ++ mov r1, #1 ++ str r1, [r0, #0x08] @Enable the watchdog ++watchdog_finished: ++#endif /* CONFIG_ARCH_IPQ40XX */ ++ + /* + * The C runtime environment should now be setup sufficiently. + * Set up some pointers, and start decompressing. diff --git a/target/linux/ipq40xx/patches-6.1/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch b/target/linux/ipq40xx/patches-6.1/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch new file mode 100644 index 0000000000..3a3be91709 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch @@ -0,0 +1,24 @@ +From f63ea127643a605da97090ce585fdd7c2d17fa42 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 14 Dec 2020 13:35:35 +0100 +Subject: [PATCH] mmc: sdhci-msm: use sdhci_set_clock + +When using sdhci_msm_set_clock clock setting will fail, so lets +use the generic sdhci_set_clock. + +Signed-off-by: Robert Marko +--- + drivers/mmc/host/sdhci-msm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mmc/host/sdhci-msm.c ++++ b/drivers/mmc/host/sdhci-msm.c +@@ -2447,7 +2447,7 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_mat + + static const struct sdhci_ops sdhci_msm_ops = { + .reset = sdhci_msm_reset, +- .set_clock = sdhci_msm_set_clock, ++ .set_clock = sdhci_set_clock, + .get_min_clock = sdhci_msm_get_min_clock, + .get_max_clock = sdhci_msm_get_max_clock, + .set_bus_width = sdhci_set_bus_width, diff --git a/target/linux/ipq40xx/patches-6.1/401-mmc-sdhci-msm-comment-unused-sdhci_msm_set_clock.patch b/target/linux/ipq40xx/patches-6.1/401-mmc-sdhci-msm-comment-unused-sdhci_msm_set_clock.patch new file mode 100644 index 0000000000..b297600171 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/401-mmc-sdhci-msm-comment-unused-sdhci_msm_set_clock.patch @@ -0,0 +1,108 @@ +From 28edd829133766eb3cefaf2e49d3ee701968061b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 9 May 2023 01:57:17 +0200 +Subject: [PATCH] mmc: sdhci-msm: comment unused sdhci_msm_set_clock + +comment unused sdhci_msm_set_clock and __sdhci_msm_set_clock as due to some +current problem, we are forced to use sdhci_set_clock. + +Signed-off-by: Christian Marangi +--- + drivers/mmc/host/sdhci-msm.c | 86 ++++++++++++++++++------------------ + 1 file changed, 43 insertions(+), 43 deletions(-) + +--- a/drivers/mmc/host/sdhci-msm.c ++++ b/drivers/mmc/host/sdhci-msm.c +@@ -1751,49 +1751,49 @@ static unsigned int sdhci_msm_get_min_cl + return SDHCI_MSM_MIN_CLOCK; + } + +-/* +- * __sdhci_msm_set_clock - sdhci_msm clock control. +- * +- * Description: +- * MSM controller does not use internal divider and +- * instead directly control the GCC clock as per +- * HW recommendation. +- **/ +-static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) +-{ +- u16 clk; +- +- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); +- +- if (clock == 0) +- return; +- +- /* +- * MSM controller do not use clock divider. +- * Thus read SDHCI_CLOCK_CONTROL and only enable +- * clock with no divider value programmed. +- */ +- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); +- sdhci_enable_clk(host, clk); +-} +- +-/* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */ +-static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) +-{ +- struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +- struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); +- +- if (!clock) { +- host->mmc->actual_clock = msm_host->clk_rate = 0; +- goto out; +- } +- +- sdhci_msm_hc_select_mode(host); +- +- msm_set_clock_rate_for_bus_mode(host, clock); +-out: +- __sdhci_msm_set_clock(host, clock); +-} ++// /* ++// * __sdhci_msm_set_clock - sdhci_msm clock control. ++// * ++// * Description: ++// * MSM controller does not use internal divider and ++// * instead directly control the GCC clock as per ++// * HW recommendation. ++// **/ ++// static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) ++// { ++// u16 clk; ++ ++// sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); ++ ++// if (clock == 0) ++// return; ++ ++// /* ++// * MSM controller do not use clock divider. ++// * Thus read SDHCI_CLOCK_CONTROL and only enable ++// * clock with no divider value programmed. ++// */ ++// clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); ++// sdhci_enable_clk(host, clk); ++// } ++ ++// /* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */ ++// static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) ++// { ++// struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++// struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); ++ ++// if (!clock) { ++// host->mmc->actual_clock = msm_host->clk_rate = 0; ++// goto out; ++// } ++ ++// sdhci_msm_hc_select_mode(host); ++ ++// msm_set_clock_rate_for_bus_mode(host, clock); ++// out: ++// __sdhci_msm_set_clock(host, clock); ++// } + + /*****************************************************************************\ + * * diff --git a/target/linux/ipq40xx/patches-6.1/420-firmware-qcom-scm-Add-SDI-disable-support.patch b/target/linux/ipq40xx/patches-6.1/420-firmware-qcom-scm-Add-SDI-disable-support.patch new file mode 100644 index 0000000000..e4ee745ff1 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/420-firmware-qcom-scm-Add-SDI-disable-support.patch @@ -0,0 +1,60 @@ +From b514bc3c0a5a57bc83843dc66c72788b9c9435ac Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 18 May 2023 16:02:23 +0200 +Subject: [PATCH 1/3] firmware: qcom: scm: Add SDI disable support + +Some SoC-s like IPQ5018 require SDI(Secure Debug Image) to be disabled +before trying to reboot, otherwise board will just hang after reboot has +been issued via PSCI. + +So, provide a call to SCM that allows disabling it. + +Signed-off-by: Robert Marko +Acked-by: Mukesh Ojha +--- + drivers/firmware/qcom_scm.c | 23 +++++++++++++++++++++++ + drivers/firmware/qcom_scm.h | 1 + + 2 files changed, 24 insertions(+) + +--- a/drivers/firmware/qcom_scm.c ++++ b/drivers/firmware/qcom_scm.c +@@ -389,6 +389,29 @@ int qcom_scm_set_remote_state(u32 state, + } + EXPORT_SYMBOL(qcom_scm_set_remote_state); + ++static int qcom_scm_disable_sdi(void) ++{ ++ int ret; ++ struct qcom_scm_desc desc = { ++ .svc = QCOM_SCM_SVC_BOOT, ++ .cmd = QCOM_SCM_BOOT_SDI_CONFIG, ++ .args[0] = 1, /* Disable watchdog debug */ ++ .args[1] = 0, /* Disable SDI */ ++ .arginfo = QCOM_SCM_ARGS(2), ++ .owner = ARM_SMCCC_OWNER_SIP, ++ }; ++ struct qcom_scm_res res; ++ ++ ret = qcom_scm_clk_enable(); ++ if (ret) ++ return ret; ++ ret = qcom_scm_call(__scm->dev, &desc, &res); ++ ++ qcom_scm_clk_disable(); ++ ++ return ret ? : res.result[0]; ++} ++ + static int __qcom_scm_set_dload_mode(struct device *dev, bool enable) + { + struct qcom_scm_desc desc = { +--- a/drivers/firmware/qcom_scm.h ++++ b/drivers/firmware/qcom_scm.h +@@ -77,6 +77,7 @@ extern int scm_legacy_call(struct device + #define QCOM_SCM_SVC_BOOT 0x01 + #define QCOM_SCM_BOOT_SET_ADDR 0x01 + #define QCOM_SCM_BOOT_TERMINATE_PC 0x02 ++#define QCOM_SCM_BOOT_SDI_CONFIG 0x09 + #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 + #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a + #define QCOM_SCM_FLUSH_FLAG_MASK 0x3 diff --git a/target/linux/ipq40xx/patches-6.1/421-firmware-qcom-scm-disable-SDI-on-Google-WiFi.patch b/target/linux/ipq40xx/patches-6.1/421-firmware-qcom-scm-disable-SDI-on-Google-WiFi.patch new file mode 100644 index 0000000000..98f02934a9 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/421-firmware-qcom-scm-disable-SDI-on-Google-WiFi.patch @@ -0,0 +1,34 @@ +From a658ad57c2b9d46eb5395c7bb8cf83b8e0f289e7 Mon Sep 17 00:00:00 2001 +From: Brian Norris +Date: Fri, 28 Jul 2023 12:02:19 +0200 +Subject: [PATCH 2/3] firmware: qcom: scm: disable SDI on Google WiFi + +Google WiFi seems to have SDI (Secure Debug Image) enabled by default which +prevents normal reboot from working causing the board to just hang after +reboot is called. + +So lets disable SDI during SCM probe on Google WiFi boards in order to +avoid a state where WDT will kick in and then the board will just hang +in the debug mode. + +Signed-off-by: Brian Norris +--- + drivers/firmware/qcom_scm.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/firmware/qcom_scm.c ++++ b/drivers/firmware/qcom_scm.c +@@ -1337,6 +1337,13 @@ static int qcom_scm_probe(struct platfor + if (download_mode) + qcom_scm_set_download_mode(true); + ++ /* ++ * Factory firmware leaves SDI (a debug interface), which prevents ++ * clean reboot. ++ */ ++ if (of_machine_is_compatible("google,wifi")) ++ qcom_scm_disable_sdi(); ++ + return 0; + } + diff --git a/target/linux/ipq40xx/patches-6.1/422-firmware-qcom-scm-fix-SCM-cold-boot-address.patch b/target/linux/ipq40xx/patches-6.1/422-firmware-qcom-scm-fix-SCM-cold-boot-address.patch new file mode 100644 index 0000000000..a31ea69e89 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/422-firmware-qcom-scm-fix-SCM-cold-boot-address.patch @@ -0,0 +1,138 @@ +From aaa675f07e781e248fcf169ce9a917b48bc2cc9b Mon Sep 17 00:00:00 2001 +From: Brian Norris +Date: Fri, 28 Jul 2023 12:06:23 +0200 +Subject: [PATCH 3/3] firmware: qcom: scm: fix SCM cold boot address + +This effectively reverts upstream Linux commit 13e77747800e ("firmware: +qcom: scm: Use atomic SCM for cold boot"), because Google WiFi boot +firmwares don't support the atomic variant. + +This fixes SMP support for Google WiFi. + +Signed-off-by: Brian Norris +--- + drivers/firmware/qcom_scm-legacy.c | 62 +++++++++++++++++++++++++----- + drivers/firmware/qcom_scm.c | 11 ++++++ + 2 files changed, 63 insertions(+), 10 deletions(-) + +--- a/drivers/firmware/qcom_scm-legacy.c ++++ b/drivers/firmware/qcom_scm-legacy.c +@@ -13,6 +13,9 @@ + #include + #include + ++#include ++#include ++ + #include "qcom_scm.h" + + static DEFINE_MUTEX(qcom_scm_lock); +@@ -117,6 +120,25 @@ static void __scm_legacy_do(const struct + } while (res->a0 == QCOM_SCM_INTERRUPTED); + } + ++static void qcom_scm_inv_range(unsigned long start, unsigned long end) ++{ ++ u32 cacheline_size, ctr; ++ ++ asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr)); ++ cacheline_size = 4 << ((ctr >> 16) & 0xf); ++ ++ start = round_down(start, cacheline_size); ++ end = round_up(end, cacheline_size); ++ outer_inv_range(start, end); ++ while (start < end) { ++ asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) ++ : "memory"); ++ start += cacheline_size; ++ } ++ dsb(); ++ isb(); ++} ++ + /** + * scm_legacy_call() - Sends a command to the SCM and waits for the command to + * finish processing. +@@ -160,10 +182,16 @@ int scm_legacy_call(struct device *dev, + + rsp = scm_legacy_command_to_response(cmd); + +- cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE); +- if (dma_mapping_error(dev, cmd_phys)) { +- kfree(cmd); +- return -ENOMEM; ++ if (dev) { ++ cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE); ++ if (dma_mapping_error(dev, cmd_phys)) { ++ kfree(cmd); ++ return -ENOMEM; ++ } ++ } else { ++ cmd_phys = virt_to_phys(cmd); ++ __cpuc_flush_dcache_area(cmd, alloc_len); ++ outer_flush_range(cmd_phys, cmd_phys + alloc_len); + } + + smc.args[0] = 1; +@@ -179,13 +207,26 @@ int scm_legacy_call(struct device *dev, + goto out; + + do { +- dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len, +- sizeof(*rsp), DMA_FROM_DEVICE); ++ if (dev) { ++ dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + ++ cmd_len, sizeof(*rsp), ++ DMA_FROM_DEVICE); ++ } else { ++ unsigned long start = (uintptr_t)cmd + sizeof(*cmd) + ++ cmd_len; ++ qcom_scm_inv_range(start, start + sizeof(*rsp)); ++ } + } while (!rsp->is_complete); + +- dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len + +- le32_to_cpu(rsp->buf_offset), +- resp_len, DMA_FROM_DEVICE); ++ if (dev) { ++ dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len + ++ le32_to_cpu(rsp->buf_offset), ++ resp_len, DMA_FROM_DEVICE); ++ } else { ++ unsigned long start = (uintptr_t)cmd + sizeof(*cmd) + cmd_len + ++ le32_to_cpu(rsp->buf_offset); ++ qcom_scm_inv_range(start, start + resp_len); ++ } + + if (res) { + res_buf = scm_legacy_get_response_buffer(rsp); +@@ -193,7 +234,8 @@ int scm_legacy_call(struct device *dev, + res->result[i] = le32_to_cpu(res_buf[i]); + } + out: +- dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE); ++ if (dev) ++ dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE); + kfree(cmd); + return ret; + } +--- a/drivers/firmware/qcom_scm.c ++++ b/drivers/firmware/qcom_scm.c +@@ -344,6 +344,17 @@ int qcom_scm_set_cold_boot_addr(void *en + desc.args[0] = flags; + desc.args[1] = virt_to_phys(entry); + ++ /* ++ * Factory firmware doesn't support the atomic variant. Non-atomic SCMs ++ * require ugly DMA invalidation support that was dropped upstream a ++ * while ago. For more info, see: ++ * ++ * [RFC] qcom_scm: IPQ4019 firmware does not support atomic API? ++ * https://lore.kernel.org/linux-arm-msm/20200913201608.GA3162100@bDebian/ ++ */ ++ if (of_machine_is_compatible("google,wifi")) ++ return qcom_scm_call(__scm ? __scm->dev : NULL, &desc, NULL); ++ + return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL); + } + EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); diff --git a/target/linux/ipq40xx/patches-6.1/444-mtd-nand-rawnand-add-support-for-Toshiba-TC58NVG0S3H.patch b/target/linux/ipq40xx/patches-6.1/444-mtd-nand-rawnand-add-support-for-Toshiba-TC58NVG0S3H.patch new file mode 100644 index 0000000000..91919b2894 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/444-mtd-nand-rawnand-add-support-for-Toshiba-TC58NVG0S3H.patch @@ -0,0 +1,29 @@ +From 35ca7e3e6ccd120d694a3425f37fc6374ad2e11e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Andreas=20B=C3=B6hler?= +Date: Wed, 20 Apr 2022 12:08:38 +0200 +Subject: [PATCH] mtd: rawnand: add support for Toshiba TC58NVG0S3HTA00 + NAND flash +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The Toshiba TC58NVG0S3HTA00 is detected with 64 byte OOB while the flash +has 128 bytes OOB. This adds a static NAND ID entry to correct this. + +Tested on FRITZ!Box 7530 flashed with OpenWrt. + +Signed-off-by: Andreas Böhler +(changed id_len to 8, added comment about possible counterfeits) +--- +--- a/drivers/mtd/nand/raw/nand_ids.c ++++ b/drivers/mtd/nand/raw/nand_ids.c +@@ -29,6 +29,9 @@ struct nand_flash_dev nand_flash_ids[] = + {"TC58NVG0S3E 1G 3.3V 8-bit", + { .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} }, + SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512), }, ++ {"TC58NVG0S3HTA00 1G 3.3V 8-bit", /* possibly counterfeit chip - see commit */ ++ { .id = {0x98, 0xf1, 0x80, 0x15} }, /* should be more bytes */ ++ SZ_2K, SZ_128, SZ_128K, 0, 8, 128, NAND_ECC_INFO(8, SZ_512), }, + {"TC58NVG2S0F 4G 3.3V 8-bit", + { .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} }, + SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) }, diff --git a/target/linux/ipq40xx/patches-6.1/700-skbuff-add-DSA-specific-data-to-struct-skb_shared_in.patch b/target/linux/ipq40xx/patches-6.1/700-skbuff-add-DSA-specific-data-to-struct-skb_shared_in.patch new file mode 100644 index 0000000000..385364c076 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/700-skbuff-add-DSA-specific-data-to-struct-skb_shared_in.patch @@ -0,0 +1,43 @@ +From da75807ac41175e9db8c95f7a172b4133763b744 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Mon, 11 Jan 2021 17:49:36 +0100 +Subject: [PATCH] skbuff: add DSA specific data to struct skb_shared_info + +All of the already existing DSA tagging protocol drivers +are storing the tagging data directly into the skb. In most +cases that is the only way to send the required information +to the underlying ethernet switch. + +However on certain platforms (like the Qualcomm IPQ40xx +SoCs) the built-in ethernet switch is connected directly +to an ethernet MAC, and the tagging information must be +sent out-of-band which is done directly via the hardware +TX descriptors of the ethernet MAC. + +In such cases, putting the information into the skb causes +unneccesary overhead, because the ethernet driver must +remove that before sending the ethernet frame towards to +the hardware. + +This change adds two new DSA specific fields to struct +skb_shared_info which makes it possible to send the +tagging information via skb->shinfo. With this approach, +the twofold modifications of the skb data can be avoided. + +Signed-off-by: Gabor Juhos +--- + include/linux/skbuff.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -564,6 +564,9 @@ struct skb_shared_info { + unsigned int gso_type; + u32 tskey; + ++ unsigned int dsa_tag_proto; ++ unsigned char dsa_tag_data[8]; ++ + /* + * Warning : all fields before dataref are cleared in __alloc_skb() + */ diff --git a/target/linux/ipq40xx/patches-6.1/701-net-dsa-tag_ipq4019-add-shinfo-based-tagging-driver-.patch b/target/linux/ipq40xx/patches-6.1/701-net-dsa-tag_ipq4019-add-shinfo-based-tagging-driver-.patch new file mode 100644 index 0000000000..74079d68a1 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/701-net-dsa-tag_ipq4019-add-shinfo-based-tagging-driver-.patch @@ -0,0 +1,187 @@ +From 29a0c2fae991cab142575c92276c0afdeb260ebe Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Thu, 28 Oct 2021 21:44:52 +0200 +Subject: [PATCH] net: dsa: tag_ipq4019: add shinfo based tagging driver for + IPQ40xx + +This change adds a tagging protocol driver for the built-in +ethernet switch of the Qualcomm Atheros IPQ4019 SoCs. + +In comparison to the existing tagging protocols this hardware +requires a slightly different approach because the switch does +not use in-band tags. + +On the receive path, the source port information is embedded +into the RX descriptors of the ethernet MAC hardware. Similarly, +the destination port mask must be sent via the TX descriptors +of the ethernet MAC when a packet is sent towards the switch. + +In order to support this special requirements, this patch +adds a new tagging protocol driver. + +The driver extracts the source port information directly +from the 'receive return descriptor' of the ethernet MAC. +It is possible because that descriptor is part of the skb +received from the ethernet driver. + +Unfortunatley, it is not possible to put the destination +port information directly to the TX descriptors, because +those are handled internally by the driver of the ethernet +hardware. + +To overcome this limitation, this tagging driver uses the +DSA specific fields in skb->shinfo to send the destination +port information to the ethernet driver. + +A similar tagging driver is exist but that uses skb +extensions which causes unnecessary overhead. + +Signed-off-by: Gabor Juhos +--- + include/linux/dsa/ipq4019.h | 11 ++++++ + include/net/dsa.h | 2 + + net/dsa/Kconfig | 6 +++ + net/dsa/Makefile | 1 + + net/dsa/tag_ipq4019.c | 79 +++++++++++++++++++++++++++++++++++++ + 5 files changed, 99 insertions(+) + create mode 100644 include/linux/dsa/ipq4019.h + create mode 100644 net/dsa/tag_ipq4019.c + +--- /dev/null ++++ b/include/linux/dsa/ipq4019.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#ifndef DSA_IPQ40XX_H ++#define DSA_IPQ40XX_H ++ ++struct ipq40xx_dsa_tag_data { ++ u8 from_cpu; ++ u8 dp; ++}; ++ ++#endif /* DSA_IPQ40XX_H */ +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -51,6 +51,7 @@ struct phylink_link_state; + #define DSA_TAG_PROTO_SEVILLE_VALUE 21 + #define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22 + #define DSA_TAG_PROTO_SJA1110_VALUE 23 ++#define DSA_TAG_PROTO_IPQ4019_VALUE 24 + + enum dsa_tag_protocol { + DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, +@@ -77,6 +78,7 @@ enum dsa_tag_protocol { + DSA_TAG_PROTO_OCELOT_8021Q = DSA_TAG_PROTO_OCELOT_8021Q_VALUE, + DSA_TAG_PROTO_SEVILLE = DSA_TAG_PROTO_SEVILLE_VALUE, + DSA_TAG_PROTO_SJA1110 = DSA_TAG_PROTO_SJA1110_VALUE, ++ DSA_TAG_PROTO_IPQ4019 = DSA_TAG_PROTO_IPQ4019_VALUE, + }; + + struct dsa_switch; +--- a/net/dsa/Kconfig ++++ b/net/dsa/Kconfig +@@ -57,6 +57,12 @@ config NET_DSA_TAG_HELLCREEK + Say Y or M if you want to enable support for tagging frames + for the Hirschmann Hellcreek TSN switches. + ++config NET_DSA_TAG_IPQ4019 ++ tristate "Tag driver for Qualcomm Atheros IPQ4019 SoC built-in switch" ++ help ++ Say Y or M if you want to enable support for tagging frames for ++ the built-in switch of the Qualcomm Atheros IPQ4019 SoC-s. ++ + config NET_DSA_TAG_GSWIP + tristate "Tag driver for Lantiq / Intel GSWIP switches" + help +--- a/net/dsa/Makefile ++++ b/net/dsa/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_NET_DSA_TAG_AR9331) += tag_ + obj-$(CONFIG_NET_DSA_TAG_BRCM_COMMON) += tag_brcm.o + obj-$(CONFIG_NET_DSA_TAG_DSA_COMMON) += tag_dsa.o + obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o ++obj-$(CONFIG_NET_DSA_TAG_IPQ4019) += tag_ipq4019.o + obj-$(CONFIG_NET_DSA_TAG_HELLCREEK) += tag_hellcreek.o + obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o + obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o +--- /dev/null ++++ b/net/dsa/tag_ipq4019.c +@@ -0,0 +1,78 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++ ++/* Copyright (c) 2021, Gabor Juhos */ ++ ++#include ++#include ++ ++#include "dsa_priv.h" ++ ++/* Receive Return Descriptor */ ++struct edma_rrd { ++ u16 rrd0; ++ u16 rrd1; ++ u16 rrd2; ++ u16 rrd3; ++ u16 rrd4; ++ u16 rrd5; ++ u16 rrd6; ++ u16 rrd7; ++} __packed; ++ ++#define EDMA_RRD_SIZE sizeof(struct edma_rrd) ++ ++#define EDMA_RRD1_PORT_ID_MASK GENMASK(14, 12) ++ ++static struct sk_buff *ipq4019_sh_tag_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct dsa_port *dp = dsa_slave_to_port(dev); ++ struct ipq40xx_dsa_tag_data *tag_data; ++ ++ BUILD_BUG_ON(sizeof_field(struct skb_shared_info, dsa_tag_data) < ++ sizeof(struct ipq40xx_dsa_tag_data)); ++ ++ skb_shinfo(skb)->dsa_tag_proto = DSA_TAG_PROTO_IPQ4019; ++ tag_data = (struct ipq40xx_dsa_tag_data *)skb_shinfo(skb)->dsa_tag_data; ++ ++ tag_data->from_cpu = 1; ++ /* set the destination port information */ ++ tag_data->dp = BIT(dp->index); ++ ++ return skb; ++} ++ ++static struct sk_buff *ipq4019_sh_tag_rcv(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct edma_rrd *rrd; ++ int offset; ++ int port; ++ ++ offset = EDMA_RRD_SIZE + ETH_HLEN; ++ if (unlikely(skb_headroom(skb) < offset)) ++ return NULL; ++ ++ rrd = (struct edma_rrd *)(skb->data - offset); ++ port = FIELD_GET(EDMA_RRD1_PORT_ID_MASK, rrd->rrd1); ++ ++ skb->dev = dsa_master_find_slave(dev, 0, port); ++ if (!skb->dev) ++ return NULL; ++ ++ return skb; ++} ++ ++const struct dsa_device_ops ipq4019_sh_tag_dsa_ops = { ++ .name = "ipq4019-sh", ++ .proto = DSA_TAG_PROTO_IPQ4019, ++ .xmit = ipq4019_sh_tag_xmit, ++ .rcv = ipq4019_sh_tag_rcv, ++}; ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("DSA tag driver for the IPQ4019 SoC built-in ethernet switch"); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_IPQ4019); ++ ++module_dsa_tag_driver(ipq4019_sh_tag_dsa_ops); diff --git a/target/linux/ipq40xx/patches-6.1/702-net-ethernet-qualcomm-add-IPQESS-support.patch b/target/linux/ipq40xx/patches-6.1/702-net-ethernet-qualcomm-add-IPQESS-support.patch new file mode 100644 index 0000000000..72e9345118 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/702-net-ethernet-qualcomm-add-IPQESS-support.patch @@ -0,0 +1,43 @@ +From 4f488235f498db43f2412116dea6e02c7fb20216 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 1 Nov 2021 12:36:51 +0100 +Subject: [PATCH] net: ethernet: qualcomm: add IPQESS support + +Allow compiling the IPQESS driver that supports the +Qualcomm IPQ40xx SoC built-in ethernet controller. + +Signed-off-by: Robert Marko +--- + drivers/net/ethernet/qualcomm/Kconfig | 11 +++++++++++ + drivers/net/ethernet/qualcomm/Makefile | 1 + + 2 files changed, 12 insertions(+) + +--- a/drivers/net/ethernet/qualcomm/Kconfig ++++ b/drivers/net/ethernet/qualcomm/Kconfig +@@ -60,6 +60,17 @@ config QCOM_EMAC + low power, Receive-Side Scaling (RSS), and IEEE 1588-2008 + Precision Clock Synchronization Protocol. + ++config QCOM_IPQ4019_ESS_EDMA ++ tristate "Qualcomm Atheros IPQ4019 ESS EDMA support" ++ depends on OF ++ select PHYLINK ++ help ++ This driver supports the Qualcomm Atheros IPQ40xx built-in ++ ESS EDMA ethernet controller. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ipqess. ++ + source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" + + endif # NET_VENDOR_QUALCOMM +--- a/drivers/net/ethernet/qualcomm/Makefile ++++ b/drivers/net/ethernet/qualcomm/Makefile +@@ -10,5 +10,6 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o + qcauart-objs := qca_uart.o + + obj-y += emac/ ++obj-y += ipqess/ + + obj-$(CONFIG_RMNET) += rmnet/ diff --git a/target/linux/ipq40xx/patches-6.1/703-arm-dts-ipq4019-add-ethernet-controller-DT-node.patch b/target/linux/ipq40xx/patches-6.1/703-arm-dts-ipq4019-add-ethernet-controller-DT-node.patch new file mode 100644 index 0000000000..68fb4eb4ce --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/703-arm-dts-ipq4019-add-ethernet-controller-DT-node.patch @@ -0,0 +1,81 @@ +From 44327d7098d4f32c24ec8c528e5aff6e030956bc Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 20 Oct 2021 13:21:45 +0200 +Subject: [PATCH] arm: dts: ipq4019: add ethernet controller DT node + +Since IPQ40xx SoC built-in ethernet controller now has a driver, +add its DT node so it can be used. + +Signed-off-by: Robert Marko +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 48 +++++++++++++++++++++++++++++ + 1 file changed, 48 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -38,6 +38,7 @@ + spi1 = &blsp1_spi2; + i2c0 = &blsp1_i2c3; + i2c1 = &blsp1_i2c4; ++ ethernet0 = &gmac; + }; + + cpus { +@@ -589,6 +590,57 @@ + status = "disabled"; + }; + ++ gmac: ethernet@c080000 { ++ compatible = "qcom,ipq4019-ess-edma"; ++ reg = <0xc080000 0x8000>; ++ resets = <&gcc ESS_RESET>; ++ reset-names = "ess_rst"; ++ clocks = <&gcc GCC_ESS_CLK>; ++ clock-names = "ess_clk"; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ ++ status = "disabled"; ++ ++ phy-mode = "internal"; ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ pause; ++ asym-pause; ++ }; ++ }; ++ + mdio: mdio@90000 { + #address-cells = <1>; + #size-cells = <0>; diff --git a/target/linux/ipq40xx/patches-6.1/704-net-phy-define-PSGMII-PHY-interface-mode.patch b/target/linux/ipq40xx/patches-6.1/704-net-phy-define-PSGMII-PHY-interface-mode.patch new file mode 100644 index 0000000000..7fbf38a7e3 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/704-net-phy-define-PSGMII-PHY-interface-mode.patch @@ -0,0 +1,69 @@ +From 157ac9f52fd9b9a22cf12f7755a905fb34ef72f7 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Fri, 25 Dec 2020 08:02:47 +0100 +Subject: [PATCH] net: phy: define PSGMII PHY interface mode + +The PSGMII interface is similar to QSGMII. The main difference +is that the PSGMII interface combines five SGMII lines into a +single link while in QSGMII only four lines are combined. + +Similarly to the QSGMII, this interface mode might also needs +special handling within the MAC driver. + +Add definitions for the PHY layer to allow to express this type +of connection between the MAC and PHY. + +Signed-off-by: Gabor Juhos +--- + Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 + + drivers/net/phy/phylink.c | 2 ++ + include/linux/phy.h | 3 +++ + 3 files changed, 6 insertions(+) + +--- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml ++++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml +@@ -64,6 +64,7 @@ properties: + - mii + - gmii + - sgmii ++ - psgmii + - qsgmii + - tbi + - rev-mii +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -366,6 +366,7 @@ void phylink_get_linkmodes(unsigned long + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_GMII: +@@ -629,6 +630,7 @@ static int phylink_parse_mode(struct phy + + switch (pl->link_config.interface) { + case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + phylink_set(pl->supported, 10baseT_Half); + phylink_set(pl->supported, 10baseT_Full); +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -139,6 +139,7 @@ typedef enum { + PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_XLGMII, + PHY_INTERFACE_MODE_MOCA, ++ PHY_INTERFACE_MODE_PSGMII, + PHY_INTERFACE_MODE_QSGMII, + PHY_INTERFACE_MODE_TRGMII, + PHY_INTERFACE_MODE_100BASEX, +@@ -244,6 +245,8 @@ static inline const char *phy_modes(phy_ + return "xlgmii"; + case PHY_INTERFACE_MODE_MOCA: + return "moca"; ++ case PHY_INTERFACE_MODE_PSGMII: ++ return "psgmii"; + case PHY_INTERFACE_MODE_QSGMII: + return "qsgmii"; + case PHY_INTERFACE_MODE_TRGMII: diff --git a/target/linux/ipq40xx/patches-6.1/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch b/target/linux/ipq40xx/patches-6.1/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch new file mode 100644 index 0000000000..13b169e576 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch @@ -0,0 +1,57 @@ +From b5f71652b85a85ea53162e9e2b760b84fd0d254f Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 1 Nov 2021 18:10:28 +0100 +Subject: [PATCH] net: dsa: add Qualcomm IPQ4019 built-in switch support + +Qualcomm IPQ40xx SoC-s have a variant of QCA8337N switch built-in. + +It shares most of the stuff with its external counterpart, however it is +modified for the SoC. +Namely, it doesn't have second CPU port (Port 6), so it has 6 ports +instead of 7. +It also has no built-in PHY-s but rather requires external PSGMII based +companion PHY-s (QCA8072 and QCA8075) for which it first needs to carry +out calibration before using them. +PSGMII has a SoC built-in PHY that is used to connect to the PHY-s which +unfortunately requires some magic values as the datasheet doesnt document +the bits that are being set or the register at all. + +Since its built-in it is MMIO like other peripherals and doesn't have its +own MDIO bus but depends on the SoC provided one. + +CPU connection is at Port 0 and it uses some kind of a internal connection +and no traditional RGMII/SGMII. +It also doesn't use in-band tagging like other qca8k switches so a shinfo +based tagger is used. + +Signed-off-by: Robert Marko +--- + drivers/net/dsa/qca/Kconfig | 9 +++++++++ + drivers/net/dsa/qca/Makefile | 1 + + 2 files changed, 10 insertions(+) + +--- a/drivers/net/dsa/qca/Kconfig ++++ b/drivers/net/dsa/qca/Kconfig +@@ -23,3 +23,13 @@ config NET_DSA_QCA8K_LEDS_SUPPORT + help + This enabled support for LEDs present on the Qualcomm Atheros + QCA8K Ethernet switch chips. ++ ++config NET_DSA_QCA8K_IPQ4019 ++ tristate "Qualcomm Atheros IPQ4019 built-in Ethernet switch support" ++ depends on HAS_IOMEM && NET_DSA ++ select NET_DSA_TAG_IPQ4019 ++ select REGMAP ++ help ++ This enables support for the Qualcomm Atheros IPQ4019 SoC built-in ++ Ethernet switch. ++ +--- a/drivers/net/dsa/qca/Makefile ++++ b/drivers/net/dsa/qca/Makefile +@@ -1,5 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o ++obj-$(CONFIG_NET_DSA_QCA8K_IPQ4019) += qca8k-ipq4019.o + obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o + qca8k-y += qca8k-common.o qca8k-8xxx.o + ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT diff --git a/target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch b/target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch new file mode 100644 index 0000000000..a231c7331b --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch @@ -0,0 +1,98 @@ +From ebb62523990a27b3a25e422fa575619f7f725a20 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 1 Nov 2021 18:15:04 +0100 +Subject: [PATCH] arm: dts: ipq4019: add switch node + +Since the built-in IPQ40xx switch now has a driver, add the required node +for it to work. + +Signed-off-by: Robert Marko +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 78 +++++++++++++++++++++++++++++ + 1 file changed, 78 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -590,6 +590,82 @@ + status = "disabled"; + }; + ++ switch: switch@c000000 { ++ compatible = "qca,ipq4019-qca8337n"; ++ reg = <0xc000000 0x80000>, <0x98000 0x800>; ++ reg-names = "base", "psgmii_phy"; ++ resets = <&gcc ESS_PSGMII_ARES>; ++ reset-names = "psgmii_rst"; ++ mdio = <&mdio>; ++ psgmii-ethphy = <&psgmiiphy>; ++ ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { /* MAC0 */ ++ reg = <0>; ++ label = "cpu"; ++ ethernet = <&gmac>; ++ phy-mode = "internal"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ pause; ++ asym-pause; ++ }; ++ }; ++ ++ swport1: port@1 { /* MAC1 */ ++ reg = <1>; ++ label = "lan1"; ++ phy-handle = <ðphy0>; ++ phy-mode = "psgmii"; ++ ++ status = "disabled"; ++ }; ++ ++ swport2: port@2 { /* MAC2 */ ++ reg = <2>; ++ label = "lan2"; ++ phy-handle = <ðphy1>; ++ phy-mode = "psgmii"; ++ ++ status = "disabled"; ++ }; ++ ++ swport3: port@3 { /* MAC3 */ ++ reg = <3>; ++ label = "lan3"; ++ phy-handle = <ðphy2>; ++ phy-mode = "psgmii"; ++ ++ status = "disabled"; ++ }; ++ ++ swport4: port@4 { /* MAC4 */ ++ reg = <4>; ++ label = "lan4"; ++ phy-handle = <ðphy3>; ++ phy-mode = "psgmii"; ++ ++ status = "disabled"; ++ }; ++ ++ swport5: port@5 { /* MAC5 */ ++ reg = <5>; ++ label = "wan"; ++ phy-handle = <ðphy4>; ++ phy-mode = "psgmii"; ++ ++ status = "disabled"; ++ }; ++ }; ++ }; ++ + gmac: ethernet@c080000 { + compatible = "qcom,ipq4019-ess-edma"; + reg = <0xc080000 0x8000>; diff --git a/target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch b/target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch new file mode 100644 index 0000000000..dfb8d692ab --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch @@ -0,0 +1,61 @@ +From c66863c1ba8995b61e6d727d78a241c734f5bb57 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 1 Oct 2020 15:05:35 +0200 +Subject: [PATCH] dt-bindings: net: add QCA807x PHY + +Add DT bindings for Qualcomm QCA807x PHY series. + +Signed-off-by: Robert Marko +--- + include/dt-bindings/net/qcom-qca807x.h | 45 ++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + create mode 100644 include/dt-bindings/net/qcom-qca807x.h + +--- /dev/null ++++ b/include/dt-bindings/net/qcom-qca807x.h +@@ -0,0 +1,45 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Device Tree constants for the Qualcomm QCA807X PHYs ++ */ ++ ++#ifndef _DT_BINDINGS_QCOM_QCA807X_H ++#define _DT_BINDINGS_QCOM_QCA807X_H ++ ++#define PSGMII_QSGMII_TX_DRIVER_140MV 0 ++#define PSGMII_QSGMII_TX_DRIVER_160MV 1 ++#define PSGMII_QSGMII_TX_DRIVER_180MV 2 ++#define PSGMII_QSGMII_TX_DRIVER_200MV 3 ++#define PSGMII_QSGMII_TX_DRIVER_220MV 4 ++#define PSGMII_QSGMII_TX_DRIVER_240MV 5 ++#define PSGMII_QSGMII_TX_DRIVER_260MV 6 ++#define PSGMII_QSGMII_TX_DRIVER_280MV 7 ++#define PSGMII_QSGMII_TX_DRIVER_300MV 8 ++#define PSGMII_QSGMII_TX_DRIVER_320MV 9 ++#define PSGMII_QSGMII_TX_DRIVER_400MV 10 ++#define PSGMII_QSGMII_TX_DRIVER_500MV 11 ++/* Default value */ ++#define PSGMII_QSGMII_TX_DRIVER_600MV 12 ++ ++/* Full amplitude, full bias current */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_BIAS 0 ++/* Amplitude follow DSP (amplitude is adjusted based on cable length), half bias current */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_HALF_BIAS 1 ++/* Full amplitude, bias current follow DSP (bias current is adjusted based on cable length) */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_DSP_BIAS 2 ++/* Both amplitude and bias current follow DSP */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_BIAS 3 ++/* Full amplitude, half bias current */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_HALF_BIAS 4 ++/* Amplitude follow DSP setting; 1/4 bias current when cable<10m, ++ * otherwise half bias current ++ */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_QUARTER_BIAS 5 ++/* Full amplitude; same bias current setting with “010” and “011”, ++ * but half more bias is reduced when cable <10m ++ */ ++#define QCA807X_CONTROL_DAC_FULL_VOLT_HALF_BIAS_SHORT 6 ++/* Amplitude follow DSP; same bias current setting with “110”, default value */ ++#define QCA807X_CONTROL_DAC_DSP_VOLT_HALF_BIAS_SHORT 7 ++ ++#endif diff --git a/target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch b/target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch new file mode 100644 index 0000000000..6a92a103d6 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch @@ -0,0 +1,50 @@ +From f825cdc8bfde7616a14e2163f16303a8973031d2 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 7 Oct 2020 17:38:48 +0200 +Subject: [PATCH] net: phy: Add Qualcom QCA807x driver + +This adds driver for the Qualcomm QCA8072 and QCA8075 PHY-s. + +They are 2 or 5 port IEEE 802.3 clause 22 compliant 10BASE-Te, 100BASE-TX and 1000BASE-T PHY-s. + +They feature 2 SerDes, one for PSGMII or QSGMII connection with MAC, while second one is SGMII for connection to MAC or fiber. + +Both models have a combo port that supports 1000BASE-X and 100BASE-FX fiber. + +Each PHY inside of QCA807x series has 4 digitally controlled output only pins that natively drive LED-s. +But some vendors used these to driver generic LED-s controlled by userspace, +so lets enable registering each PHY as GPIO controller and add driver for it. + +These are commonly used in Qualcomm IPQ40xx, IPQ60xx and IPQ807x boards. + +Signed-off-by: Robert Marko +--- + drivers/net/phy/Kconfig | 6 ++++++ + drivers/net/phy/Makefile | 1 + + 2 files changed, 7 insertions(+) + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -347,6 +347,12 @@ config AT803X_PHY + Currently supports the AR8030, AR8031, AR8033, AR8035 and internal + QCA8337(Internal qca8k PHY) model + ++config QCA807X_PHY ++ tristate "Qualcomm QCA807X PHYs" ++ depends on OF_MDIO ++ help ++ Currently supports the QCA8072 and QCA8075 models. ++ + config QSEMI_PHY + tristate "Quality Semiconductor PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -92,6 +92,7 @@ obj-$(CONFIG_NATIONAL_PHY) += national.o + obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja11xx.o + obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o + obj-$(CONFIG_QSEMI_PHY) += qsemi.o ++obj-$(CONFIG_QCA807X_PHY) += qca807x.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o + obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch b/target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch new file mode 100644 index 0000000000..cc4b44b393 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch @@ -0,0 +1,61 @@ +From e0fa88eaa3c176b71e563da68949ac2ab45aaa61 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Fri, 2 Oct 2020 10:43:26 +0200 +Subject: [PATCH] arm: dts: ipq4019: QCA807x properties + +This adds necessary DT properties for QCA807x PHY-s to IPQ4019 DTSI. + +Signed-off-by: Robert Marko +--- + arch/arm/boot/dts/qcom-ipq4019.dtsi | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi ++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + / { + #address-cells = <1>; +@@ -726,22 +727,38 @@ + + ethphy0: ethernet-phy@0 { + reg = <0>; ++ ++ qcom,control-dac = ; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; ++ ++ qcom,control-dac = ; + }; + + ethphy2: ethernet-phy@2 { + reg = <2>; ++ ++ qcom,control-dac = ; + }; + + ethphy3: ethernet-phy@3 { + reg = <3>; ++ ++ qcom,control-dac = ; + }; + + ethphy4: ethernet-phy@4 { + reg = <4>; ++ ++ qcom,control-dac = ; ++ }; ++ ++ psgmiiphy: psgmii-phy@5 { ++ reg = <5>; ++ ++ qcom,tx-driver-strength = ; + }; + }; + diff --git a/target/linux/ipq40xx/patches-6.1/850-soc-add-qualcomm-syscon.patch b/target/linux/ipq40xx/patches-6.1/850-soc-add-qualcomm-syscon.patch new file mode 100644 index 0000000000..9b44a4c885 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/850-soc-add-qualcomm-syscon.patch @@ -0,0 +1,180 @@ +From: Christian Lamparter +Subject: SoC: add qualcomm syscon +--- a/drivers/soc/qcom/Makefile ++++ b/drivers/soc/qcom/Makefile +@@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o + obj-$(CONFIG_QCOM_SMSM) += smsm.o + obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o + obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o ++obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o + obj-$(CONFIG_QCOM_APR) += apr.o + obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o + obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -192,6 +192,13 @@ config QCOM_SOCINFO + Say yes here to support the Qualcomm socinfo driver, providing + information about the SoC to user space. + ++config QCOM_TCSR ++ tristate "QCOM Top Control and Status Registers" ++ depends on ARCH_QCOM ++ help ++ Say y here to enable TCSR support. The TCSR provides control ++ functions for various peripherals. ++ + config QCOM_WCNSS_CTRL + tristate "Qualcomm WCNSS control driver" + depends on ARCH_QCOM || COMPILE_TEST +--- /dev/null ++++ b/drivers/soc/qcom/qcom_tcsr.c +@@ -0,0 +1,98 @@ ++/* ++ * Copyright (c) 2014, The Linux foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License rev 2 and ++ * only rev 2 as published by the free Software foundation. ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TCSR_USB_PORT_SEL 0xb0 ++#define TCSR_USB_HSPHY_CONFIG 0xC ++ ++#define TCSR_ESS_INTERFACE_SEL_OFFSET 0x0 ++#define TCSR_ESS_INTERFACE_SEL_MASK 0xf ++ ++#define TCSR_WIFI0_GLB_CFG_OFFSET 0x0 ++#define TCSR_WIFI1_GLB_CFG_OFFSET 0x4 ++#define TCSR_PNOC_SNOC_MEMTYPE_M0_M2 0x4 ++ ++static int tcsr_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ const struct device_node *node = pdev->dev.of_node; ++ void __iomem *base; ++ u32 val; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ if (!of_property_read_u32(node, "qcom,usb-ctrl-select", &val)) { ++ dev_err(&pdev->dev, "setting usb port select = %d\n", val); ++ writel(val, base + TCSR_USB_PORT_SEL); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,usb-hsphy-mode-select", &val)) { ++ dev_info(&pdev->dev, "setting usb hs phy mode select = %x\n", val); ++ writel(val, base + TCSR_USB_HSPHY_CONFIG); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,ess-interface-select", &val)) { ++ u32 tmp = 0; ++ dev_info(&pdev->dev, "setting ess interface select = %x\n", val); ++ tmp = readl(base + TCSR_ESS_INTERFACE_SEL_OFFSET); ++ tmp = tmp & (~TCSR_ESS_INTERFACE_SEL_MASK); ++ tmp = tmp | (val&TCSR_ESS_INTERFACE_SEL_MASK); ++ writel(tmp, base + TCSR_ESS_INTERFACE_SEL_OFFSET); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,wifi_glb_cfg", &val)) { ++ dev_info(&pdev->dev, "setting wifi_glb_cfg = %x\n", val); ++ writel(val, base + TCSR_WIFI0_GLB_CFG_OFFSET); ++ writel(val, base + TCSR_WIFI1_GLB_CFG_OFFSET); ++ } ++ ++ if (!of_property_read_u32(node, "qcom,wifi_noc_memtype_m0_m2", &val)) { ++ dev_info(&pdev->dev, ++ "setting wifi_noc_memtype_m0_m2 = %x\n", val); ++ writel(val, base + TCSR_PNOC_SNOC_MEMTYPE_M0_M2); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id tcsr_dt_match[] = { ++ { .compatible = "qcom,tcsr", }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, tcsr_dt_match); ++ ++static struct platform_driver tcsr_driver = { ++ .driver = { ++ .name = "tcsr", ++ .owner = THIS_MODULE, ++ .of_match_table = tcsr_dt_match, ++ }, ++ .probe = tcsr_probe, ++}; ++ ++module_platform_driver(tcsr_driver); ++ ++MODULE_AUTHOR("Andy Gross "); ++MODULE_DESCRIPTION("QCOM TCSR driver"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/include/dt-bindings/soc/qcom,tcsr.h +@@ -0,0 +1,48 @@ ++/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * 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. ++ */ ++#ifndef __DT_BINDINGS_QCOM_TCSR_H ++#define __DT_BINDINGS_QCOM_TCSR_H ++ ++#define TCSR_USB_SELECT_USB3_P0 0x1 ++#define TCSR_USB_SELECT_USB3_P1 0x2 ++#define TCSR_USB_SELECT_USB3_DUAL 0x3 ++ ++/* IPQ40xx HS PHY Mode Select */ ++#define TCSR_USB_HSPHY_HOST_MODE 0x00E700E7 ++#define TCSR_USB_HSPHY_DEVICE_MODE 0x00C700E7 ++ ++/* IPQ40xx ess interface mode select */ ++#define TCSR_ESS_PSGMII 0 ++#define TCSR_ESS_PSGMII_RGMII5 1 ++#define TCSR_ESS_PSGMII_RMII0 2 ++#define TCSR_ESS_PSGMII_RMII1 4 ++#define TCSR_ESS_PSGMII_RMII0_RMII1 6 ++#define TCSR_ESS_PSGMII_RGMII4 9 ++ ++/* ++ * IPQ40xx WiFi Global Config ++ * Bit 30:AXID_EN ++ * Enable AXI master bus Axid translating to confirm all txn submitted by order ++ * Bit 24: Use locally generated socslv_wxi_bvalid ++ * 1: use locally generate socslv_wxi_bvalid for performance. ++ * 0: use SNOC socslv_wxi_bvalid. ++ */ ++#define TCSR_WIFI_GLB_CFG 0x41000000 ++ ++/* IPQ40xx MEM_TYPE_SEL_M0_M2 Select Bit 26:24 - 2 NORMAL */ ++#define TCSR_WIFI_NOC_MEMTYPE_M0_M2 0x02222222 ++ ++/* TCSR A/B REG */ ++#define IPQ806X_TCSR_REG_A_ADM_CRCI_MUX_SEL 0 ++#define IPQ806X_TCSR_REG_B_ADM_CRCI_MUX_SEL 1 ++ ++#endif diff --git a/target/linux/ipq40xx/patches-6.1/910-Revert-firmware-qcom_scm-Clear-download-bit-during-r.patch b/target/linux/ipq40xx/patches-6.1/910-Revert-firmware-qcom_scm-Clear-download-bit-during-r.patch new file mode 100644 index 0000000000..b5b89b26f1 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/910-Revert-firmware-qcom_scm-Clear-download-bit-during-r.patch @@ -0,0 +1,27 @@ +From c668fd2c4d9ad4a510fd214a2da83bd9b67a2508 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sun, 13 Aug 2023 18:13:08 +0200 +Subject: [PATCH] Revert "firmware: qcom_scm: Clear download bit during reboot" + +This reverts commit a3ea89b5978dbcd0fa55f675c5a1e04611093709. + +It is breaking reboot on IPQ4019 boards, so revert until a proper fix +is found. + +Signed-off-by: Robert Marko +--- + drivers/firmware/qcom_scm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/firmware/qcom_scm.c ++++ b/drivers/firmware/qcom_scm.c +@@ -1361,7 +1361,8 @@ static int qcom_scm_probe(struct platfor + static void qcom_scm_shutdown(struct platform_device *pdev) + { + /* Clean shutdown, disable download mode to allow normal restart */ +- qcom_scm_set_download_mode(false); ++ if (download_mode) ++ qcom_scm_set_download_mode(false); + } + + static const struct of_device_id qcom_scm_dt_match[] = { diff --git a/target/linux/ipq40xx/patches-6.1/998-lantiq-atm-hacks.patch b/target/linux/ipq40xx/patches-6.1/998-lantiq-atm-hacks.patch new file mode 100644 index 0000000000..c15a4b3ae3 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/998-lantiq-atm-hacks.patch @@ -0,0 +1,43 @@ +From: John Crispin +Date: Fri, 3 Aug 2012 10:27:25 +0200 +Subject: [PATCH 04/36] MIPS: lantiq: add atm hack + +Signed-off-by: John Crispin +--- a/include/uapi/linux/atm.h ++++ b/include/uapi/linux/atm.h +@@ -131,8 +131,14 @@ + #define ATM_ABR 4 + #define ATM_ANYCLASS 5 /* compatible with everything */ + ++#define ATM_VBR_NRT ATM_VBR ++#define ATM_VBR_RT 6 ++#define ATM_UBR_PLUS 7 ++#define ATM_GFR 8 ++ + #define ATM_MAX_PCR -1 /* maximum available PCR */ + ++ + struct atm_trafprm { + unsigned char traffic_class; /* traffic class (ATM_UBR, ...) */ + int max_pcr; /* maximum PCR in cells per second */ +@@ -155,6 +161,9 @@ struct atm_trafprm { + unsigned int adtf :10; /* ACR Decrease Time Factor (10-bit) */ + unsigned int cdf :3; /* Cutoff Decrease Factor (3-bit) */ + unsigned int spare :9; /* spare bits */ ++ int scr; /* sustained rate in cells per second */ ++ int mbs; /* maximum burst size (MBS) in cells */ ++ int cdv; /* Cell delay variation */ + }; + + struct atm_qos { +--- a/net/atm/proc.c ++++ b/net/atm/proc.c +@@ -141,7 +141,7 @@ static void *vcc_seq_next(struct seq_fil + static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc) + { + static const char *const class_name[] = { +- "off", "UBR", "CBR", "VBR", "ABR"}; ++ "off","UBR","CBR","NTR-VBR","ABR","ANY","RT-VBR","UBR+","GFR"}; + static const char *const aal_name[] = { + "---", "1", "2", "3/4", /* 0- 3 */ + "???", "5", "???", "???", /* 4- 7 */ diff --git a/target/linux/ipq40xx/patches-6.1/999-atm-mpoa-intel-dsl-phy-support.patch b/target/linux/ipq40xx/patches-6.1/999-atm-mpoa-intel-dsl-phy-support.patch new file mode 100644 index 0000000000..b774fc39d8 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/999-atm-mpoa-intel-dsl-phy-support.patch @@ -0,0 +1,137 @@ +From: Subhra Banerjee +Date: Fri, 31 Aug 2018 12:01:19 +0530 +Subject: [PATCH] UGW_SW-29163: ATM oam support + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -2952,6 +2952,22 @@ char *ppp_dev_name(struct ppp_channel *c + return name; + } + ++/* ++ * Return the PPP device interface pointer ++ */ ++struct net_device *ppp_device(struct ppp_channel *chan) ++{ ++ struct channel *pch = chan->ppp; ++ struct net_device *dev = NULL; ++ ++ if (pch) { ++ read_lock_bh(&pch->upl); ++ if (pch->ppp && pch->ppp->dev) ++ dev = pch->ppp->dev; ++ read_unlock_bh(&pch->upl); ++ } ++ return dev; ++} + + /* + * Disconnect a channel from the generic layer. +@@ -3598,6 +3614,7 @@ EXPORT_SYMBOL(ppp_unregister_channel); + EXPORT_SYMBOL(ppp_channel_index); + EXPORT_SYMBOL(ppp_unit_number); + EXPORT_SYMBOL(ppp_dev_name); ++EXPORT_SYMBOL(ppp_device); + EXPORT_SYMBOL(ppp_input); + EXPORT_SYMBOL(ppp_input_error); + EXPORT_SYMBOL(ppp_output_wakeup); +--- a/include/linux/ppp_channel.h ++++ b/include/linux/ppp_channel.h +@@ -74,6 +74,9 @@ extern int ppp_unit_number(struct ppp_ch + /* Get the device name associated with a channel, or NULL if none */ + extern char *ppp_dev_name(struct ppp_channel *); + ++/* Get the device pointer associated with a channel, or NULL if none */ ++extern struct net_device *ppp_device(struct ppp_channel *); ++ + /* + * SMP locking notes: + * The channel code must ensure that when it calls ppp_unregister_channel, +--- a/net/atm/Kconfig ++++ b/net/atm/Kconfig +@@ -56,6 +56,12 @@ config ATM_MPOA + subnetwork boundaries. These shortcut connections bypass routers + enhancing overall network performance. + ++config ATM_MPOA_INTEL_DSL_PHY_SUPPORT ++ bool "Intel DSL Phy MPOA support" ++ depends on ATM && INET && ATM_MPOA!=n ++ help ++ Add support for Intel DSL Phy ATM MPOA ++ + config ATM_BR2684 + tristate "RFC1483/2684 Bridged protocols" + depends on ATM && INET +--- a/net/atm/br2684.c ++++ b/net/atm/br2684.c +@@ -596,6 +596,11 @@ static int br2684_regvcc(struct atm_vcc + atmvcc->push = br2684_push; + atmvcc->pop = br2684_pop; + atmvcc->release_cb = br2684_release_cb; ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++ if (atm_hook_mpoa_setup) /* IPoA or EoA w/o FCS */ ++ atm_hook_mpoa_setup(atmvcc, brdev->payload == p_routed ? 3 : 0, ++ brvcc->encaps == BR2684_ENCAPS_LLC ? 1 : 0, net_dev); ++#endif + atmvcc->owner = THIS_MODULE; + + /* initialize netdev carrier state */ +--- a/net/atm/common.c ++++ b/net/atm/common.c +@@ -137,6 +137,11 @@ static struct proto vcc_proto = { + .release_cb = vcc_release_cb, + }; + ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++void (*atm_hook_mpoa_setup)(struct atm_vcc *, int, int, struct net_device *) = NULL; ++EXPORT_SYMBOL(atm_hook_mpoa_setup); ++#endif ++ + int vcc_create(struct net *net, struct socket *sock, int protocol, int family, int kern) + { + struct sock *sk; +--- a/net/atm/common.h ++++ b/net/atm/common.h +@@ -53,4 +53,6 @@ int svc_change_qos(struct atm_vcc *vcc,s + + void atm_dev_release_vccs(struct atm_dev *dev); + ++extern void (*atm_hook_mpoa_setup)(struct atm_vcc *, int, int, struct net_device *); ++ + #endif +--- a/net/atm/mpc.c ++++ b/net/atm/mpc.c +@@ -31,6 +31,7 @@ + /* Modular too */ + #include + ++#include "common.h" + #include "lec.h" + #include "mpc.h" + #include "resources.h" +@@ -645,6 +646,10 @@ static int atm_mpoa_vcc_attach(struct at + vcc->proto_data = mpc->dev; + vcc->push = mpc_push; + ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++ if (atm_hook_mpoa_setup) /* IPoA, LLC */ ++ atm_hook_mpoa_setup(vcc, 3, 1, mpc->dev); ++#endif + return 0; + } + +--- a/net/atm/pppoatm.c ++++ b/net/atm/pppoatm.c +@@ -422,6 +422,12 @@ static int pppoatm_assign_vcc(struct atm + atmvcc->user_back = pvcc; + atmvcc->push = pppoatm_push; + atmvcc->pop = pppoatm_pop; ++#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT) ++ if (atm_hook_mpoa_setup) /* PPPoA */ ++ atm_hook_mpoa_setup(atmvcc, 2, ++ pvcc->encaps == e_llc ? 1 : 0, ++ ppp_device(&pvcc->chan)); ++#endif + atmvcc->release_cb = pppoatm_release_cb; + __module_get(THIS_MODULE); + atmvcc->owner = THIS_MODULE; From 3d6d8bcd8fd13bc72a4670f9f209528f9b6d1a93 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 14 Aug 2023 18:42:18 +0200 Subject: [PATCH 09/24] ipq40xx: qca807x: adapt for 6.1 Kernel 6.1 has changed format of sfp_parse_support(), so lets adapt to those changes so it works on newer kernels as well. Signed-off-by: Robert Marko --- target/linux/ipq40xx/files/drivers/net/phy/qca807x.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c index 23b0ca74f7..abfc11e121 100644 --- a/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c +++ b/target/linux/ipq40xx/files/drivers/net/phy/qca807x.c @@ -644,8 +644,13 @@ static int qca807x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, }; phy_interface_t iface; int ret; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0) + DECLARE_PHY_INTERFACE_MASK(interfaces); + sfp_parse_support(phydev->sfp_bus, id, support, interfaces); +#else sfp_parse_support(phydev->sfp_bus, id, support); +#endif iface = sfp_select_interface(phydev->sfp_bus, support); dev_info(&phydev->mdio.dev, "%s SFP module inserted\n", phy_modes(iface)); From 4c010932a5fa12b150dfcde773f291e6f906ec60 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 14 Aug 2023 18:45:59 +0200 Subject: [PATCH 10/24] ipq40xx: 6.1: adapt and refresh patches Adapt and refresh patches to apply. DSA and ethernet driver patches are dropped as they will be replaced with the latest version that was sent upstream. Signed-off-by: Robert Marko --- ...d-set-ipq40xx-watchdog-to-allow-boot.patch | 2 +- ...msm-use-sdhci_set_clock-instead-of-s.patch | 2 +- ...are-qcom-scm-Add-SDI-disable-support.patch | 4 +- ...-qcom-scm-disable-SDI-on-Google-WiFi.patch | 2 +- ...e-qcom-scm-fix-SCM-cold-boot-address.patch | 10 +- ...pecific-data-to-struct-skb_shared_in.patch | 43 ---- ...019-add-shinfo-based-tagging-driver-.patch | 187 ------------------ ...ethernet-qualcomm-add-IPQESS-support.patch | 43 ---- ...phy-define-PSGMII-PHY-interface-mode.patch | 69 ------- ...comm-IPQ4019-built-in-switch-support.patch | 57 ------ .../706-arm-dts-ipq4019-add-switch-node.patch | 8 +- .../707-dt-bindings-net-add-QCA807x-PHY.patch | 2 +- ...8-net-phy-Add-Qualcom-QCA807x-driver.patch | 21 +- ...9-arm-dts-ipq4019-QCA807x-properties.patch | 8 +- .../850-soc-add-qualcomm-syscon.patch | 27 ++- ...qcom_scm-Clear-download-bit-during-r.patch | 2 +- .../999-atm-mpoa-intel-dsl-phy-support.patch | 8 +- 17 files changed, 46 insertions(+), 449 deletions(-) delete mode 100644 target/linux/ipq40xx/patches-6.1/700-skbuff-add-DSA-specific-data-to-struct-skb_shared_in.patch delete mode 100644 target/linux/ipq40xx/patches-6.1/701-net-dsa-tag_ipq4019-add-shinfo-based-tagging-driver-.patch delete mode 100644 target/linux/ipq40xx/patches-6.1/702-net-ethernet-qualcomm-add-IPQESS-support.patch delete mode 100644 target/linux/ipq40xx/patches-6.1/704-net-phy-define-PSGMII-PHY-interface-mode.patch delete mode 100644 target/linux/ipq40xx/patches-6.1/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch diff --git a/target/linux/ipq40xx/patches-6.1/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch b/target/linux/ipq40xx/patches-6.1/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch index 51891c1f22..4939c56470 100644 --- a/target/linux/ipq40xx/patches-6.1/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch +++ b/target/linux/ipq40xx/patches-6.1/302-arm-compressed-set-ipq40xx-watchdog-to-allow-boot.patch @@ -22,7 +22,7 @@ Signed-off-by: John Thomson --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S -@@ -624,6 +624,41 @@ not_relocated: mov r0, #0 +@@ -620,6 +620,41 @@ not_relocated: mov r0, #0 bic r4, r4, #1 blne cache_on diff --git a/target/linux/ipq40xx/patches-6.1/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch b/target/linux/ipq40xx/patches-6.1/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch index 3a3be91709..bf36164aed 100644 --- a/target/linux/ipq40xx/patches-6.1/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch +++ b/target/linux/ipq40xx/patches-6.1/400-mmc-sdhci-sdhci-msm-use-sdhci_set_clock-instead-of-s.patch @@ -13,7 +13,7 @@ Signed-off-by: Robert Marko --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c -@@ -2447,7 +2447,7 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_mat +@@ -2451,7 +2451,7 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_mat static const struct sdhci_ops sdhci_msm_ops = { .reset = sdhci_msm_reset, diff --git a/target/linux/ipq40xx/patches-6.1/420-firmware-qcom-scm-Add-SDI-disable-support.patch b/target/linux/ipq40xx/patches-6.1/420-firmware-qcom-scm-Add-SDI-disable-support.patch index e4ee745ff1..732f3c50fb 100644 --- a/target/linux/ipq40xx/patches-6.1/420-firmware-qcom-scm-Add-SDI-disable-support.patch +++ b/target/linux/ipq40xx/patches-6.1/420-firmware-qcom-scm-Add-SDI-disable-support.patch @@ -18,7 +18,7 @@ Acked-by: Mukesh Ojha --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c -@@ -389,6 +389,29 @@ int qcom_scm_set_remote_state(u32 state, +@@ -400,6 +400,29 @@ int qcom_scm_set_remote_state(u32 state, } EXPORT_SYMBOL(qcom_scm_set_remote_state); @@ -56,5 +56,5 @@ Acked-by: Mukesh Ojha #define QCOM_SCM_BOOT_TERMINATE_PC 0x02 +#define QCOM_SCM_BOOT_SDI_CONFIG 0x09 #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 + #define QCOM_SCM_BOOT_SET_ADDR_MC 0x11 #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a - #define QCOM_SCM_FLUSH_FLAG_MASK 0x3 diff --git a/target/linux/ipq40xx/patches-6.1/421-firmware-qcom-scm-disable-SDI-on-Google-WiFi.patch b/target/linux/ipq40xx/patches-6.1/421-firmware-qcom-scm-disable-SDI-on-Google-WiFi.patch index 98f02934a9..ff788c5c56 100644 --- a/target/linux/ipq40xx/patches-6.1/421-firmware-qcom-scm-disable-SDI-on-Google-WiFi.patch +++ b/target/linux/ipq40xx/patches-6.1/421-firmware-qcom-scm-disable-SDI-on-Google-WiFi.patch @@ -18,7 +18,7 @@ Signed-off-by: Brian Norris --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c -@@ -1337,6 +1337,13 @@ static int qcom_scm_probe(struct platfor +@@ -1435,6 +1435,13 @@ static int qcom_scm_probe(struct platfor if (download_mode) qcom_scm_set_download_mode(true); diff --git a/target/linux/ipq40xx/patches-6.1/422-firmware-qcom-scm-fix-SCM-cold-boot-address.patch b/target/linux/ipq40xx/patches-6.1/422-firmware-qcom-scm-fix-SCM-cold-boot-address.patch index a31ea69e89..a92342215e 100644 --- a/target/linux/ipq40xx/patches-6.1/422-firmware-qcom-scm-fix-SCM-cold-boot-address.patch +++ b/target/linux/ipq40xx/patches-6.1/422-firmware-qcom-scm-fix-SCM-cold-boot-address.patch @@ -53,7 +53,7 @@ Signed-off-by: Brian Norris /** * scm_legacy_call() - Sends a command to the SCM and waits for the command to * finish processing. -@@ -160,10 +182,16 @@ int scm_legacy_call(struct device *dev, +@@ -163,10 +185,16 @@ int scm_legacy_call(struct device *dev, rsp = scm_legacy_command_to_response(cmd); @@ -74,7 +74,7 @@ Signed-off-by: Brian Norris } smc.args[0] = 1; -@@ -179,13 +207,26 @@ int scm_legacy_call(struct device *dev, +@@ -182,13 +210,26 @@ int scm_legacy_call(struct device *dev, goto out; do { @@ -106,7 +106,7 @@ Signed-off-by: Brian Norris if (res) { res_buf = scm_legacy_get_response_buffer(rsp); -@@ -193,7 +234,8 @@ int scm_legacy_call(struct device *dev, +@@ -196,7 +237,8 @@ int scm_legacy_call(struct device *dev, res->result[i] = le32_to_cpu(res_buf[i]); } out: @@ -118,7 +118,7 @@ Signed-off-by: Brian Norris } --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c -@@ -344,6 +344,17 @@ int qcom_scm_set_cold_boot_addr(void *en +@@ -305,6 +305,17 @@ static int qcom_scm_set_boot_addr(void * desc.args[0] = flags; desc.args[1] = virt_to_phys(entry); @@ -135,4 +135,4 @@ Signed-off-by: Brian Norris + return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL); } - EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); + diff --git a/target/linux/ipq40xx/patches-6.1/700-skbuff-add-DSA-specific-data-to-struct-skb_shared_in.patch b/target/linux/ipq40xx/patches-6.1/700-skbuff-add-DSA-specific-data-to-struct-skb_shared_in.patch deleted file mode 100644 index 385364c076..0000000000 --- a/target/linux/ipq40xx/patches-6.1/700-skbuff-add-DSA-specific-data-to-struct-skb_shared_in.patch +++ /dev/null @@ -1,43 +0,0 @@ -From da75807ac41175e9db8c95f7a172b4133763b744 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Mon, 11 Jan 2021 17:49:36 +0100 -Subject: [PATCH] skbuff: add DSA specific data to struct skb_shared_info - -All of the already existing DSA tagging protocol drivers -are storing the tagging data directly into the skb. In most -cases that is the only way to send the required information -to the underlying ethernet switch. - -However on certain platforms (like the Qualcomm IPQ40xx -SoCs) the built-in ethernet switch is connected directly -to an ethernet MAC, and the tagging information must be -sent out-of-band which is done directly via the hardware -TX descriptors of the ethernet MAC. - -In such cases, putting the information into the skb causes -unneccesary overhead, because the ethernet driver must -remove that before sending the ethernet frame towards to -the hardware. - -This change adds two new DSA specific fields to struct -skb_shared_info which makes it possible to send the -tagging information via skb->shinfo. With this approach, -the twofold modifications of the skb data can be avoided. - -Signed-off-by: Gabor Juhos ---- - include/linux/skbuff.h | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/include/linux/skbuff.h -+++ b/include/linux/skbuff.h -@@ -564,6 +564,9 @@ struct skb_shared_info { - unsigned int gso_type; - u32 tskey; - -+ unsigned int dsa_tag_proto; -+ unsigned char dsa_tag_data[8]; -+ - /* - * Warning : all fields before dataref are cleared in __alloc_skb() - */ diff --git a/target/linux/ipq40xx/patches-6.1/701-net-dsa-tag_ipq4019-add-shinfo-based-tagging-driver-.patch b/target/linux/ipq40xx/patches-6.1/701-net-dsa-tag_ipq4019-add-shinfo-based-tagging-driver-.patch deleted file mode 100644 index 74079d68a1..0000000000 --- a/target/linux/ipq40xx/patches-6.1/701-net-dsa-tag_ipq4019-add-shinfo-based-tagging-driver-.patch +++ /dev/null @@ -1,187 +0,0 @@ -From 29a0c2fae991cab142575c92276c0afdeb260ebe Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Thu, 28 Oct 2021 21:44:52 +0200 -Subject: [PATCH] net: dsa: tag_ipq4019: add shinfo based tagging driver for - IPQ40xx - -This change adds a tagging protocol driver for the built-in -ethernet switch of the Qualcomm Atheros IPQ4019 SoCs. - -In comparison to the existing tagging protocols this hardware -requires a slightly different approach because the switch does -not use in-band tags. - -On the receive path, the source port information is embedded -into the RX descriptors of the ethernet MAC hardware. Similarly, -the destination port mask must be sent via the TX descriptors -of the ethernet MAC when a packet is sent towards the switch. - -In order to support this special requirements, this patch -adds a new tagging protocol driver. - -The driver extracts the source port information directly -from the 'receive return descriptor' of the ethernet MAC. -It is possible because that descriptor is part of the skb -received from the ethernet driver. - -Unfortunatley, it is not possible to put the destination -port information directly to the TX descriptors, because -those are handled internally by the driver of the ethernet -hardware. - -To overcome this limitation, this tagging driver uses the -DSA specific fields in skb->shinfo to send the destination -port information to the ethernet driver. - -A similar tagging driver is exist but that uses skb -extensions which causes unnecessary overhead. - -Signed-off-by: Gabor Juhos ---- - include/linux/dsa/ipq4019.h | 11 ++++++ - include/net/dsa.h | 2 + - net/dsa/Kconfig | 6 +++ - net/dsa/Makefile | 1 + - net/dsa/tag_ipq4019.c | 79 +++++++++++++++++++++++++++++++++++++ - 5 files changed, 99 insertions(+) - create mode 100644 include/linux/dsa/ipq4019.h - create mode 100644 net/dsa/tag_ipq4019.c - ---- /dev/null -+++ b/include/linux/dsa/ipq4019.h -@@ -0,0 +1,11 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#ifndef DSA_IPQ40XX_H -+#define DSA_IPQ40XX_H -+ -+struct ipq40xx_dsa_tag_data { -+ u8 from_cpu; -+ u8 dp; -+}; -+ -+#endif /* DSA_IPQ40XX_H */ ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -51,6 +51,7 @@ struct phylink_link_state; - #define DSA_TAG_PROTO_SEVILLE_VALUE 21 - #define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22 - #define DSA_TAG_PROTO_SJA1110_VALUE 23 -+#define DSA_TAG_PROTO_IPQ4019_VALUE 24 - - enum dsa_tag_protocol { - DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, -@@ -77,6 +78,7 @@ enum dsa_tag_protocol { - DSA_TAG_PROTO_OCELOT_8021Q = DSA_TAG_PROTO_OCELOT_8021Q_VALUE, - DSA_TAG_PROTO_SEVILLE = DSA_TAG_PROTO_SEVILLE_VALUE, - DSA_TAG_PROTO_SJA1110 = DSA_TAG_PROTO_SJA1110_VALUE, -+ DSA_TAG_PROTO_IPQ4019 = DSA_TAG_PROTO_IPQ4019_VALUE, - }; - - struct dsa_switch; ---- a/net/dsa/Kconfig -+++ b/net/dsa/Kconfig -@@ -57,6 +57,12 @@ config NET_DSA_TAG_HELLCREEK - Say Y or M if you want to enable support for tagging frames - for the Hirschmann Hellcreek TSN switches. - -+config NET_DSA_TAG_IPQ4019 -+ tristate "Tag driver for Qualcomm Atheros IPQ4019 SoC built-in switch" -+ help -+ Say Y or M if you want to enable support for tagging frames for -+ the built-in switch of the Qualcomm Atheros IPQ4019 SoC-s. -+ - config NET_DSA_TAG_GSWIP - tristate "Tag driver for Lantiq / Intel GSWIP switches" - help ---- a/net/dsa/Makefile -+++ b/net/dsa/Makefile -@@ -8,6 +8,7 @@ obj-$(CONFIG_NET_DSA_TAG_AR9331) += tag_ - obj-$(CONFIG_NET_DSA_TAG_BRCM_COMMON) += tag_brcm.o - obj-$(CONFIG_NET_DSA_TAG_DSA_COMMON) += tag_dsa.o - obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o -+obj-$(CONFIG_NET_DSA_TAG_IPQ4019) += tag_ipq4019.o - obj-$(CONFIG_NET_DSA_TAG_HELLCREEK) += tag_hellcreek.o - obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o - obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o ---- /dev/null -+++ b/net/dsa/tag_ipq4019.c -@@ -0,0 +1,78 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ -+/* Copyright (c) 2021, Gabor Juhos */ -+ -+#include -+#include -+ -+#include "dsa_priv.h" -+ -+/* Receive Return Descriptor */ -+struct edma_rrd { -+ u16 rrd0; -+ u16 rrd1; -+ u16 rrd2; -+ u16 rrd3; -+ u16 rrd4; -+ u16 rrd5; -+ u16 rrd6; -+ u16 rrd7; -+} __packed; -+ -+#define EDMA_RRD_SIZE sizeof(struct edma_rrd) -+ -+#define EDMA_RRD1_PORT_ID_MASK GENMASK(14, 12) -+ -+static struct sk_buff *ipq4019_sh_tag_xmit(struct sk_buff *skb, -+ struct net_device *dev) -+{ -+ struct dsa_port *dp = dsa_slave_to_port(dev); -+ struct ipq40xx_dsa_tag_data *tag_data; -+ -+ BUILD_BUG_ON(sizeof_field(struct skb_shared_info, dsa_tag_data) < -+ sizeof(struct ipq40xx_dsa_tag_data)); -+ -+ skb_shinfo(skb)->dsa_tag_proto = DSA_TAG_PROTO_IPQ4019; -+ tag_data = (struct ipq40xx_dsa_tag_data *)skb_shinfo(skb)->dsa_tag_data; -+ -+ tag_data->from_cpu = 1; -+ /* set the destination port information */ -+ tag_data->dp = BIT(dp->index); -+ -+ return skb; -+} -+ -+static struct sk_buff *ipq4019_sh_tag_rcv(struct sk_buff *skb, -+ struct net_device *dev) -+{ -+ struct edma_rrd *rrd; -+ int offset; -+ int port; -+ -+ offset = EDMA_RRD_SIZE + ETH_HLEN; -+ if (unlikely(skb_headroom(skb) < offset)) -+ return NULL; -+ -+ rrd = (struct edma_rrd *)(skb->data - offset); -+ port = FIELD_GET(EDMA_RRD1_PORT_ID_MASK, rrd->rrd1); -+ -+ skb->dev = dsa_master_find_slave(dev, 0, port); -+ if (!skb->dev) -+ return NULL; -+ -+ return skb; -+} -+ -+const struct dsa_device_ops ipq4019_sh_tag_dsa_ops = { -+ .name = "ipq4019-sh", -+ .proto = DSA_TAG_PROTO_IPQ4019, -+ .xmit = ipq4019_sh_tag_xmit, -+ .rcv = ipq4019_sh_tag_rcv, -+}; -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_DESCRIPTION("DSA tag driver for the IPQ4019 SoC built-in ethernet switch"); -+MODULE_AUTHOR("Gabor Juhos "); -+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_IPQ4019); -+ -+module_dsa_tag_driver(ipq4019_sh_tag_dsa_ops); diff --git a/target/linux/ipq40xx/patches-6.1/702-net-ethernet-qualcomm-add-IPQESS-support.patch b/target/linux/ipq40xx/patches-6.1/702-net-ethernet-qualcomm-add-IPQESS-support.patch deleted file mode 100644 index 72e9345118..0000000000 --- a/target/linux/ipq40xx/patches-6.1/702-net-ethernet-qualcomm-add-IPQESS-support.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 4f488235f498db43f2412116dea6e02c7fb20216 Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 1 Nov 2021 12:36:51 +0100 -Subject: [PATCH] net: ethernet: qualcomm: add IPQESS support - -Allow compiling the IPQESS driver that supports the -Qualcomm IPQ40xx SoC built-in ethernet controller. - -Signed-off-by: Robert Marko ---- - drivers/net/ethernet/qualcomm/Kconfig | 11 +++++++++++ - drivers/net/ethernet/qualcomm/Makefile | 1 + - 2 files changed, 12 insertions(+) - ---- a/drivers/net/ethernet/qualcomm/Kconfig -+++ b/drivers/net/ethernet/qualcomm/Kconfig -@@ -60,6 +60,17 @@ config QCOM_EMAC - low power, Receive-Side Scaling (RSS), and IEEE 1588-2008 - Precision Clock Synchronization Protocol. - -+config QCOM_IPQ4019_ESS_EDMA -+ tristate "Qualcomm Atheros IPQ4019 ESS EDMA support" -+ depends on OF -+ select PHYLINK -+ help -+ This driver supports the Qualcomm Atheros IPQ40xx built-in -+ ESS EDMA ethernet controller. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called ipqess. -+ - source "drivers/net/ethernet/qualcomm/rmnet/Kconfig" - - endif # NET_VENDOR_QUALCOMM ---- a/drivers/net/ethernet/qualcomm/Makefile -+++ b/drivers/net/ethernet/qualcomm/Makefile -@@ -10,5 +10,6 @@ obj-$(CONFIG_QCA7000_UART) += qcauart.o - qcauart-objs := qca_uart.o - - obj-y += emac/ -+obj-y += ipqess/ - - obj-$(CONFIG_RMNET) += rmnet/ diff --git a/target/linux/ipq40xx/patches-6.1/704-net-phy-define-PSGMII-PHY-interface-mode.patch b/target/linux/ipq40xx/patches-6.1/704-net-phy-define-PSGMII-PHY-interface-mode.patch deleted file mode 100644 index 7fbf38a7e3..0000000000 --- a/target/linux/ipq40xx/patches-6.1/704-net-phy-define-PSGMII-PHY-interface-mode.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 157ac9f52fd9b9a22cf12f7755a905fb34ef72f7 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Fri, 25 Dec 2020 08:02:47 +0100 -Subject: [PATCH] net: phy: define PSGMII PHY interface mode - -The PSGMII interface is similar to QSGMII. The main difference -is that the PSGMII interface combines five SGMII lines into a -single link while in QSGMII only four lines are combined. - -Similarly to the QSGMII, this interface mode might also needs -special handling within the MAC driver. - -Add definitions for the PHY layer to allow to express this type -of connection between the MAC and PHY. - -Signed-off-by: Gabor Juhos ---- - Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 + - drivers/net/phy/phylink.c | 2 ++ - include/linux/phy.h | 3 +++ - 3 files changed, 6 insertions(+) - ---- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml -+++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml -@@ -64,6 +64,7 @@ properties: - - mii - - gmii - - sgmii -+ - psgmii - - qsgmii - - tbi - - rev-mii ---- a/drivers/net/phy/phylink.c -+++ b/drivers/net/phy/phylink.c -@@ -366,6 +366,7 @@ void phylink_get_linkmodes(unsigned long - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_GMII: -@@ -629,6 +630,7 @@ static int phylink_parse_mode(struct phy - - switch (pl->link_config.interface) { - case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - phylink_set(pl->supported, 10baseT_Half); - phylink_set(pl->supported, 10baseT_Full); ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -139,6 +139,7 @@ typedef enum { - PHY_INTERFACE_MODE_XGMII, - PHY_INTERFACE_MODE_XLGMII, - PHY_INTERFACE_MODE_MOCA, -+ PHY_INTERFACE_MODE_PSGMII, - PHY_INTERFACE_MODE_QSGMII, - PHY_INTERFACE_MODE_TRGMII, - PHY_INTERFACE_MODE_100BASEX, -@@ -244,6 +245,8 @@ static inline const char *phy_modes(phy_ - return "xlgmii"; - case PHY_INTERFACE_MODE_MOCA: - return "moca"; -+ case PHY_INTERFACE_MODE_PSGMII: -+ return "psgmii"; - case PHY_INTERFACE_MODE_QSGMII: - return "qsgmii"; - case PHY_INTERFACE_MODE_TRGMII: diff --git a/target/linux/ipq40xx/patches-6.1/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch b/target/linux/ipq40xx/patches-6.1/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch deleted file mode 100644 index 13b169e576..0000000000 --- a/target/linux/ipq40xx/patches-6.1/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch +++ /dev/null @@ -1,57 +0,0 @@ -From b5f71652b85a85ea53162e9e2b760b84fd0d254f Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Mon, 1 Nov 2021 18:10:28 +0100 -Subject: [PATCH] net: dsa: add Qualcomm IPQ4019 built-in switch support - -Qualcomm IPQ40xx SoC-s have a variant of QCA8337N switch built-in. - -It shares most of the stuff with its external counterpart, however it is -modified for the SoC. -Namely, it doesn't have second CPU port (Port 6), so it has 6 ports -instead of 7. -It also has no built-in PHY-s but rather requires external PSGMII based -companion PHY-s (QCA8072 and QCA8075) for which it first needs to carry -out calibration before using them. -PSGMII has a SoC built-in PHY that is used to connect to the PHY-s which -unfortunately requires some magic values as the datasheet doesnt document -the bits that are being set or the register at all. - -Since its built-in it is MMIO like other peripherals and doesn't have its -own MDIO bus but depends on the SoC provided one. - -CPU connection is at Port 0 and it uses some kind of a internal connection -and no traditional RGMII/SGMII. -It also doesn't use in-band tagging like other qca8k switches so a shinfo -based tagger is used. - -Signed-off-by: Robert Marko ---- - drivers/net/dsa/qca/Kconfig | 9 +++++++++ - drivers/net/dsa/qca/Makefile | 1 + - 2 files changed, 10 insertions(+) - ---- a/drivers/net/dsa/qca/Kconfig -+++ b/drivers/net/dsa/qca/Kconfig -@@ -23,3 +23,13 @@ config NET_DSA_QCA8K_LEDS_SUPPORT - help - This enabled support for LEDs present on the Qualcomm Atheros - QCA8K Ethernet switch chips. -+ -+config NET_DSA_QCA8K_IPQ4019 -+ tristate "Qualcomm Atheros IPQ4019 built-in Ethernet switch support" -+ depends on HAS_IOMEM && NET_DSA -+ select NET_DSA_TAG_IPQ4019 -+ select REGMAP -+ help -+ This enables support for the Qualcomm Atheros IPQ4019 SoC built-in -+ Ethernet switch. -+ ---- a/drivers/net/dsa/qca/Makefile -+++ b/drivers/net/dsa/qca/Makefile -@@ -1,5 +1,6 @@ - # SPDX-License-Identifier: GPL-2.0-only - obj-$(CONFIG_NET_DSA_AR9331) += ar9331.o -+obj-$(CONFIG_NET_DSA_QCA8K_IPQ4019) += qca8k-ipq4019.o - obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o - qca8k-y += qca8k-common.o qca8k-8xxx.o - ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT diff --git a/target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch b/target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch index a231c7331b..b1a6a2bf34 100644 --- a/target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch +++ b/target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch @@ -1,4 +1,4 @@ -From ebb62523990a27b3a25e422fa575619f7f725a20 Mon Sep 17 00:00:00 2001 +From 8cbdb2526c3d7ba2e0c8c771773595f195135f54 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 1 Nov 2021 18:15:04 +0100 Subject: [PATCH] arm: dts: ipq4019: add switch node @@ -8,12 +8,12 @@ for it to work. Signed-off-by: Robert Marko --- - arch/arm/boot/dts/qcom-ipq4019.dtsi | 78 +++++++++++++++++++++++++++++ - 1 file changed, 78 insertions(+) + arch/arm/boot/dts/qcom-ipq4019.dtsi | 76 +++++++++++++++++++++++++++++ + 1 file changed, 76 insertions(+) --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -590,6 +590,82 @@ +@@ -591,6 +591,82 @@ status = "disabled"; }; diff --git a/target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch b/target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch index dfb8d692ab..e026b7550d 100644 --- a/target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch +++ b/target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch @@ -1,4 +1,4 @@ -From c66863c1ba8995b61e6d727d78a241c734f5bb57 Mon Sep 17 00:00:00 2001 +From dfba344da3657ee4d91e7ebd1217e93423d03624 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 1 Oct 2020 15:05:35 +0200 Subject: [PATCH] dt-bindings: net: add QCA807x PHY diff --git a/target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch b/target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch index 6a92a103d6..dd2bb33c55 100644 --- a/target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch +++ b/target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch @@ -1,6 +1,6 @@ -From f825cdc8bfde7616a14e2163f16303a8973031d2 Mon Sep 17 00:00:00 2001 +From 95179775debad6b0bdab241d4a305135fc5e67dc Mon Sep 17 00:00:00 2001 From: Robert Marko -Date: Wed, 7 Oct 2020 17:38:48 +0200 +Date: Fri, 9 Sep 2022 23:44:42 +0200 Subject: [PATCH] net: phy: Add Qualcom QCA807x driver This adds driver for the Qualcomm QCA8072 and QCA8075 PHY-s. @@ -19,32 +19,33 @@ These are commonly used in Qualcomm IPQ40xx, IPQ60xx and IPQ807x boards. Signed-off-by: Robert Marko --- - drivers/net/phy/Kconfig | 6 ++++++ + drivers/net/phy/Kconfig | 7 +++++++ drivers/net/phy/Makefile | 1 + - 2 files changed, 7 insertions(+) + 2 files changed, 8 insertions(+) --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -347,6 +347,12 @@ config AT803X_PHY +@@ -362,6 +362,13 @@ config AT803X_PHY Currently supports the AR8030, AR8031, AR8033, AR8035 and internal QCA8337(Internal qca8k PHY) model +config QCA807X_PHY -+ tristate "Qualcomm QCA807X PHYs" ++ tristate "Qualcomm QCA807x PHYs" + depends on OF_MDIO + help -+ Currently supports the QCA8072 and QCA8075 models. ++ Currently supports the Qualcomm QCA8072, QCA8075 and the PSGMII ++ control PHY. + config QSEMI_PHY tristate "Quality Semiconductor PHYs" help --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -92,6 +92,7 @@ obj-$(CONFIG_NATIONAL_PHY) += national.o +@@ -94,6 +94,7 @@ obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm + obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja11xx.o obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o - obj-$(CONFIG_QSEMI_PHY) += qsemi.o +obj-$(CONFIG_QCA807X_PHY) += qca807x.o + obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_REALTEK_PHY) += realtek.o obj-$(CONFIG_RENESAS_PHY) += uPD60620.o - obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o diff --git a/target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch b/target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch index cc4b44b393..5d8a9bf053 100644 --- a/target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch +++ b/target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch @@ -1,4 +1,4 @@ -From e0fa88eaa3c176b71e563da68949ac2ab45aaa61 Mon Sep 17 00:00:00 2001 +From 03ebcd291974e4ca5d77026111f63309bc708326 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 2 Oct 2020 10:43:26 +0200 Subject: [PATCH] arm: dts: ipq4019: QCA807x properties @@ -7,8 +7,8 @@ This adds necessary DT properties for QCA807x PHY-s to IPQ4019 DTSI. Signed-off-by: Robert Marko --- - arch/arm/boot/dts/qcom-ipq4019.dtsi | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) + arch/arm/boot/dts/qcom-ipq4019.dtsi | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi @@ -20,7 +20,7 @@ Signed-off-by: Robert Marko / { #address-cells = <1>; -@@ -726,22 +727,38 @@ +@@ -724,22 +725,38 @@ ethphy0: ethernet-phy@0 { reg = <0>; diff --git a/target/linux/ipq40xx/patches-6.1/850-soc-add-qualcomm-syscon.patch b/target/linux/ipq40xx/patches-6.1/850-soc-add-qualcomm-syscon.patch index 9b44a4c885..6afb27b178 100644 --- a/target/linux/ipq40xx/patches-6.1/850-soc-add-qualcomm-syscon.patch +++ b/target/linux/ipq40xx/patches-6.1/850-soc-add-qualcomm-syscon.patch @@ -1,20 +1,10 @@ From: Christian Lamparter Subject: SoC: add qualcomm syscon ---- a/drivers/soc/qcom/Makefile -+++ b/drivers/soc/qcom/Makefile -@@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o - obj-$(CONFIG_QCOM_SMSM) += smsm.o - obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o - obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o -+obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o - obj-$(CONFIG_QCOM_APR) += apr.o - obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o - obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig -@@ -192,6 +192,13 @@ config QCOM_SOCINFO - Say yes here to support the Qualcomm socinfo driver, providing - information about the SoC to user space. +@@ -248,4 +248,11 @@ config QCOM_ICC_BWMON + the fixed bandwidth votes from cpufreq (CPU nodes) thus achieve high + memory throughput even with lower CPU frequencies. +config QCOM_TCSR + tristate "QCOM Top Control and Status Registers" @@ -23,9 +13,14 @@ Subject: SoC: add qualcomm syscon + Say y here to enable TCSR support. The TCSR provides control + functions for various peripherals. + - config QCOM_WCNSS_CTRL - tristate "Qualcomm WCNSS control driver" - depends on ARCH_QCOM || COMPILE_TEST + endmenu +--- a/drivers/soc/qcom/Makefile ++++ b/drivers/soc/qcom/Makefile +@@ -29,3 +29,4 @@ obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o + obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o + obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) += kryo-l2-accessors.o + obj-$(CONFIG_QCOM_ICC_BWMON) += icc-bwmon.o ++obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o --- /dev/null +++ b/drivers/soc/qcom/qcom_tcsr.c @@ -0,0 +1,98 @@ diff --git a/target/linux/ipq40xx/patches-6.1/910-Revert-firmware-qcom_scm-Clear-download-bit-during-r.patch b/target/linux/ipq40xx/patches-6.1/910-Revert-firmware-qcom_scm-Clear-download-bit-during-r.patch index b5b89b26f1..f08ff04137 100644 --- a/target/linux/ipq40xx/patches-6.1/910-Revert-firmware-qcom_scm-Clear-download-bit-during-r.patch +++ b/target/linux/ipq40xx/patches-6.1/910-Revert-firmware-qcom_scm-Clear-download-bit-during-r.patch @@ -15,7 +15,7 @@ Signed-off-by: Robert Marko --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c -@@ -1361,7 +1361,8 @@ static int qcom_scm_probe(struct platfor +@@ -1459,7 +1459,8 @@ static int qcom_scm_probe(struct platfor static void qcom_scm_shutdown(struct platform_device *pdev) { /* Clean shutdown, disable download mode to allow normal restart */ diff --git a/target/linux/ipq40xx/patches-6.1/999-atm-mpoa-intel-dsl-phy-support.patch b/target/linux/ipq40xx/patches-6.1/999-atm-mpoa-intel-dsl-phy-support.patch index b774fc39d8..3d5b7afe8c 100644 --- a/target/linux/ipq40xx/patches-6.1/999-atm-mpoa-intel-dsl-phy-support.patch +++ b/target/linux/ipq40xx/patches-6.1/999-atm-mpoa-intel-dsl-phy-support.patch @@ -4,7 +4,7 @@ Subject: [PATCH] UGW_SW-29163: ATM oam support --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c -@@ -2952,6 +2952,22 @@ char *ppp_dev_name(struct ppp_channel *c +@@ -2953,6 +2953,22 @@ char *ppp_dev_name(struct ppp_channel *c return name; } @@ -27,7 +27,7 @@ Subject: [PATCH] UGW_SW-29163: ATM oam support /* * Disconnect a channel from the generic layer. -@@ -3598,6 +3614,7 @@ EXPORT_SYMBOL(ppp_unregister_channel); +@@ -3599,6 +3615,7 @@ EXPORT_SYMBOL(ppp_unregister_channel); EXPORT_SYMBOL(ppp_channel_index); EXPORT_SYMBOL(ppp_unit_number); EXPORT_SYMBOL(ppp_dev_name); @@ -37,7 +37,7 @@ Subject: [PATCH] UGW_SW-29163: ATM oam support EXPORT_SYMBOL(ppp_output_wakeup); --- a/include/linux/ppp_channel.h +++ b/include/linux/ppp_channel.h -@@ -74,6 +74,9 @@ extern int ppp_unit_number(struct ppp_ch +@@ -76,6 +76,9 @@ extern int ppp_unit_number(struct ppp_ch /* Get the device name associated with a channel, or NULL if none */ extern char *ppp_dev_name(struct ppp_channel *); @@ -64,7 +64,7 @@ Subject: [PATCH] UGW_SW-29163: ATM oam support depends on ATM && INET --- a/net/atm/br2684.c +++ b/net/atm/br2684.c -@@ -596,6 +596,11 @@ static int br2684_regvcc(struct atm_vcc +@@ -598,6 +598,11 @@ static int br2684_regvcc(struct atm_vcc atmvcc->push = br2684_push; atmvcc->pop = br2684_pop; atmvcc->release_cb = br2684_release_cb; From cd9c7211241ea605e8713f5b9f0692ec0f7b765b Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 21 Aug 2023 23:42:54 +0200 Subject: [PATCH 11/24] ipq40xx: 6.1: use latest DSA and ethernet patches This pulls-in the latest version of qca8k based IPQ4019 driver as well as the latest version of IPQESS that was sent upstream. Both qca8k and IPQESS have been improved and cleaned up compared to current version of patches. PSGMII PHY mode and missing reset have been upstreamed and will be in the kernel 6.6. Signed-off-by: Robert Marko Signed-off-by: Christian Marangi --- ...-qcom-ipq4019-add-missing-networkin.patch} | 9 +- ...q4019-add-missing-networking-resets.patch} | 8 +- ...-Introduce-PSGMII-PHY-interface-mode.patch | 105 + ...introduce-the-Qualcomm-IPQESS-driver.patch | 2025 +++++++++++++++++ ...dsa-add-out-of-band-tagging-protocol.patch | 238 ++ ...-Add-out-of-band-DSA-tagging-support.patch | 173 ++ ...ess-release-IRQ-s-on-network-device-.patch | 75 + ...qess-enable-threaded-NAPI-by-default.patch | 49 + ...019-Add-description-for-the-IPQESS-.patch} | 41 +- ...-add-IPQ4019-built-in-switch-support.patch | 1132 +++++++++ ...707-arm-dts-ipq4019-add-switch-node.patch} | 2 +- ...708-dt-bindings-net-add-QCA807x-PHY.patch} | 2 +- ...-net-phy-Add-Qualcom-QCA807x-driver.patch} | 4 +- ...-arm-dts-ipq4019-QCA807x-properties.patch} | 2 +- ...ualcomm-ipqess-fix-TX-timeout-errors.patch | 64 + 15 files changed, 3896 insertions(+), 33 deletions(-) rename target/linux/ipq40xx/patches-6.1/{100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch => 001-v6.6-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch} (64%) rename target/linux/ipq40xx/patches-6.1/{101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch => 002-v6.6-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch} (72%) create mode 100644 target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch create mode 100644 target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch create mode 100644 target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch create mode 100644 target/linux/ipq40xx/patches-6.1/702-net-ipqess-Add-out-of-band-DSA-tagging-support.patch create mode 100644 target/linux/ipq40xx/patches-6.1/703-net-qualcomm-ipqess-release-IRQ-s-on-network-device-.patch create mode 100644 target/linux/ipq40xx/patches-6.1/704-net-qualcomm-ipqess-enable-threaded-NAPI-by-default.patch rename target/linux/ipq40xx/patches-6.1/{703-arm-dts-ipq4019-add-ethernet-controller-DT-node.patch => 705-ARM-dts-qcom-ipq4019-Add-description-for-the-IPQESS-.patch} (71%) create mode 100644 target/linux/ipq40xx/patches-6.1/706-net-dsa-qca8k-add-IPQ4019-built-in-switch-support.patch rename target/linux/ipq40xx/patches-6.1/{706-arm-dts-ipq4019-add-switch-node.patch => 707-arm-dts-ipq4019-add-switch-node.patch} (97%) rename target/linux/ipq40xx/patches-6.1/{707-dt-bindings-net-add-QCA807x-PHY.patch => 708-dt-bindings-net-add-QCA807x-PHY.patch} (97%) rename target/linux/ipq40xx/patches-6.1/{708-net-phy-Add-Qualcom-QCA807x-driver.patch => 709-net-phy-Add-Qualcom-QCA807x-driver.patch} (94%) rename target/linux/ipq40xx/patches-6.1/{709-arm-dts-ipq4019-QCA807x-properties.patch => 710-arm-dts-ipq4019-QCA807x-properties.patch} (95%) create mode 100644 target/linux/ipq40xx/patches-6.1/711-net-qualcomm-ipqess-fix-TX-timeout-errors.patch diff --git a/target/linux/ipq40xx/patches-6.1/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch b/target/linux/ipq40xx/patches-6.1/001-v6.6-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch similarity index 64% rename from target/linux/ipq40xx/patches-6.1/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch rename to target/linux/ipq40xx/patches-6.1/001-v6.6-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch index ae59005bba..87feaf79f8 100644 --- a/target/linux/ipq40xx/patches-6.1/100-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch +++ b/target/linux/ipq40xx/patches-6.1/001-v6.6-dt-bindings-clock-qcom-ipq4019-add-missing-networkin.patch @@ -1,12 +1,15 @@ -From 53cac0823f86c39eb4b00e2c9a7b2483a4182008 Mon Sep 17 00:00:00 2001 +From be59072c6eeb7535bf9a339fb9d5a8bfae17ac22 Mon Sep 17 00:00:00 2001 From: Robert Marko -Date: Mon, 14 Aug 2023 12:37:58 +0200 -Subject: [PATCH 1/2] dt-bindings: clock: qcom: ipq4019: add missing networking +Date: Mon, 14 Aug 2023 12:40:23 +0200 +Subject: [PATCH] dt-bindings: clock: qcom: ipq4019: add missing networking resets Add bindings for the missing networking resets found in IPQ4019 GCC. Signed-off-by: Robert Marko +Acked-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20230814104119.96858-1-robert.marko@sartura.hr +Signed-off-by: Bjorn Andersson --- include/dt-bindings/clock/qcom,gcc-ipq4019.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/linux/ipq40xx/patches-6.1/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch b/target/linux/ipq40xx/patches-6.1/002-v6.6-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch similarity index 72% rename from target/linux/ipq40xx/patches-6.1/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch rename to target/linux/ipq40xx/patches-6.1/002-v6.6-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch index 42a2f341be..70b278c803 100644 --- a/target/linux/ipq40xx/patches-6.1/101-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch +++ b/target/linux/ipq40xx/patches-6.1/002-v6.6-clk-qcom-gcc-ipq4019-add-missing-networking-resets.patch @@ -1,12 +1,14 @@ -From 6038ba75e2aa8e57d4eaf20a90c8061c43b1117f Mon Sep 17 00:00:00 2001 +From 20014461691efc9e274c3870357152db7f091820 Mon Sep 17 00:00:00 2001 From: Robert Marko -Date: Mon, 14 Aug 2023 12:39:04 +0200 -Subject: [PATCH 2/2] clk: qcom: gcc-ipq4019: add missing networking resets +Date: Mon, 14 Aug 2023 12:40:24 +0200 +Subject: [PATCH] clk: qcom: gcc-ipq4019: add missing networking resets IPQ4019 has more networking related resets that will be required for future wired networking support, so lets add them. Signed-off-by: Robert Marko +Link: https://lore.kernel.org/r/20230814104119.96858-2-robert.marko@sartura.hr +Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq4019.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch b/target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch new file mode 100644 index 0000000000..189ece1ca7 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/003-v6.6-net-phy-Introduce-PSGMII-PHY-interface-mode.patch @@ -0,0 +1,105 @@ +From 9a0e95e34e9c0a713ddfd48c3a88a20d2bdfd514 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Fri, 11 Aug 2023 13:10:07 +0200 +Subject: [PATCH] net: phy: Introduce PSGMII PHY interface mode + +The PSGMII interface is similar to QSGMII. The main difference +is that the PSGMII interface combines five SGMII lines into a +single link while in QSGMII only four lines are combined. + +Similarly to the QSGMII, this interface mode might also needs +special handling within the MAC driver. + +It is commonly used by Qualcomm with their QCA807x PHY series and +modern WiSoC-s. + +Add definitions for the PHY layer to allow to express this type +of connection between the MAC and PHY. + +Signed-off-by: Gabor Juhos +Signed-off-by: Robert Marko +Signed-off-by: David S. Miller +--- + Documentation/networking/phy.rst | 4 ++++ + drivers/net/phy/phy-core.c | 2 ++ + drivers/net/phy/phylink.c | 3 +++ + include/linux/phy.h | 4 ++++ + 4 files changed, 13 insertions(+) + +--- a/Documentation/networking/phy.rst ++++ b/Documentation/networking/phy.rst +@@ -323,6 +323,10 @@ Some of the interface modes are describe + contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this + interface mode has different autonegotiation and only supports full duplex. + ++``PHY_INTERFACE_MODE_PSGMII`` ++ This is the Penta SGMII mode, it is similar to QSGMII but it combines 5 ++ SGMII lines into a single link compared to 4 on QSGMII. ++ + Pause frames / flow control + =========================== + +--- a/drivers/net/phy/phy-core.c ++++ b/drivers/net/phy/phy-core.c +@@ -140,6 +140,8 @@ int phy_interface_num_ports(phy_interfac + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + return 4; ++ case PHY_INTERFACE_MODE_PSGMII: ++ return 5; + case PHY_INTERFACE_MODE_MAX: + WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode"); + return 0; +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -187,6 +187,7 @@ static int phylink_interface_max_speed(p + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: +@@ -448,6 +449,7 @@ unsigned long phylink_get_capabilities(p + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: +@@ -814,6 +816,7 @@ static int phylink_parse_mode(struct phy + + switch (pl->link_config.interface) { + case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_RGMII: +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -104,6 +104,7 @@ extern const int phy_10gbit_features_arr + * @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface + * @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface + * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax ++ * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII + * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII + * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII + * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX +@@ -141,6 +142,7 @@ typedef enum { + PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_XLGMII, + PHY_INTERFACE_MODE_MOCA, ++ PHY_INTERFACE_MODE_PSGMII, + PHY_INTERFACE_MODE_QSGMII, + PHY_INTERFACE_MODE_TRGMII, + PHY_INTERFACE_MODE_100BASEX, +@@ -248,6 +250,8 @@ static inline const char *phy_modes(phy_ + return "xlgmii"; + case PHY_INTERFACE_MODE_MOCA: + return "moca"; ++ case PHY_INTERFACE_MODE_PSGMII: ++ return "psgmii"; + case PHY_INTERFACE_MODE_QSGMII: + return "qsgmii"; + case PHY_INTERFACE_MODE_TRGMII: diff --git a/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch b/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch new file mode 100644 index 0000000000..254e85c284 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/700-net-ipqess-introduce-the-Qualcomm-IPQESS-driver.patch @@ -0,0 +1,2025 @@ +From 76e25c1f46456416ba5358be8a0677f1ab8196b6 Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Fri, 4 Nov 2022 18:41:48 +0100 +Subject: [PATCH] net: ipqess: introduce the Qualcomm IPQESS driver + +The Qualcomm IPQESS controller is a simple 1G Ethernet controller found +on the IPQ4019 chip. This controller has some specificities, in that the +IPQ4019 platform that includes that controller also has an internal +switch, based on the QCA8K IP. + +It is connected to that switch through an internal link, and doesn't +expose directly any external interface, hence it only supports the +PHY_INTERFACE_MODE_INTERNAL for now. + +It has 16 RX and TX queues, with a very basic RSS fanout configured at +init time. + +Signed-off-by: Maxime Chevallier +--- + MAINTAINERS | 7 + + drivers/net/ethernet/qualcomm/Kconfig | 11 + + drivers/net/ethernet/qualcomm/Makefile | 2 + + drivers/net/ethernet/qualcomm/ipqess/Makefile | 8 + + drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 1246 +++++++++++++++++ + drivers/net/ethernet/qualcomm/ipqess/ipqess.h | 518 +++++++ + .../ethernet/qualcomm/ipqess/ipqess_ethtool.c | 164 +++ + 7 files changed, 1956 insertions(+) + create mode 100644 drivers/net/ethernet/qualcomm/ipqess/Makefile + create mode 100644 drivers/net/ethernet/qualcomm/ipqess/ipqess.c + create mode 100644 drivers/net/ethernet/qualcomm/ipqess/ipqess.h + create mode 100644 drivers/net/ethernet/qualcomm/ipqess/ipqess_ethtool.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -17064,6 +17064,13 @@ L: netdev@vger.kernel.org + S: Maintained + F: drivers/net/ethernet/qualcomm/emac/ + ++QUALCOMM IPQESS ETHERNET DRIVER ++M: Maxime Chevallier ++L: netdev@vger.kernel.org ++S: Maintained ++F: Documentation/devicetree/bindings/net/qcom,ipq4019-ess-edma.yaml ++F: drivers/net/ethernet/qualcomm/ipqess/ ++ + QUALCOMM ETHQOS ETHERNET DRIVER + M: Vinod Koul + R: Bhupesh Sharma +--- a/drivers/net/ethernet/qualcomm/Kconfig ++++ b/drivers/net/ethernet/qualcomm/Kconfig +@@ -60,6 +60,17 @@ config QCOM_EMAC + low power, Receive-Side Scaling (RSS), and IEEE 1588-2008 + Precision Clock Synchronization Protocol. + ++config QCOM_IPQ4019_ESS_EDMA ++ tristate "Qualcomm Atheros IPQ4019 ESS EDMA support" ++ depends on (OF && ARCH_QCOM) || COMPILE_TEST ++ select PHYLINK ++ help ++ This driver supports the Qualcomm Atheros IPQ40xx built-in ++ ESS EDMA ethernet controller. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ipqess. ++ + 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,6 @@ qcauart-objs := qca_uart.o + + obj-y += emac/ + ++obj-$(CONFIG_QCOM_IPQ4019_ESS_EDMA) += ipqess/ ++ + obj-$(CONFIG_RMNET) += rmnet/ +--- /dev/null ++++ b/drivers/net/ethernet/qualcomm/ipqess/Makefile +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# Makefile for the IPQ ESS driver ++# ++ ++obj-$(CONFIG_QCOM_IPQ4019_ESS_EDMA) += ipq_ess.o ++ ++ipq_ess-objs := ipqess.o ipqess_ethtool.o +--- /dev/null ++++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c +@@ -0,0 +1,1246 @@ ++// SPDX-License-Identifier: GPL-2.0 OR ISC ++/* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2017 - 2018, John Crispin ++ * Copyright (c) 2018 - 2019, Christian Lamparter ++ * Copyright (c) 2020 - 2021, Gabor Juhos ++ * Copyright (c) 2021 - 2022, Maxime Chevallier ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ipqess.h" ++ ++#define IPQESS_RRD_SIZE 16 ++#define IPQESS_NEXT_IDX(X, Y) (((X) + 1) & ((Y) - 1)) ++#define IPQESS_TX_DMA_BUF_LEN 0x3fff ++ ++static void ipqess_w32(struct ipqess *ess, u32 reg, u32 val) ++{ ++ writel(val, ess->hw_addr + reg); ++} ++ ++static u32 ipqess_r32(struct ipqess *ess, u16 reg) ++{ ++ return readl(ess->hw_addr + reg); ++} ++ ++static void ipqess_m32(struct ipqess *ess, u32 mask, u32 val, u16 reg) ++{ ++ u32 _val = ipqess_r32(ess, reg); ++ ++ _val &= ~mask; ++ _val |= val; ++ ++ ipqess_w32(ess, reg, _val); ++} ++ ++void ipqess_update_hw_stats(struct ipqess *ess) ++{ ++ u32 *p; ++ u32 stat; ++ int i; ++ ++ lockdep_assert_held(&ess->stats_lock); ++ ++ p = (u32 *)&ess->ipqess_stats; ++ for (i = 0; i < IPQESS_MAX_TX_QUEUE; i++) { ++ stat = ipqess_r32(ess, IPQESS_REG_TX_STAT_PKT_Q(i)); ++ *p += stat; ++ p++; ++ } ++ ++ for (i = 0; i < IPQESS_MAX_TX_QUEUE; i++) { ++ stat = ipqess_r32(ess, IPQESS_REG_TX_STAT_BYTE_Q(i)); ++ *p += stat; ++ p++; ++ } ++ ++ for (i = 0; i < IPQESS_MAX_RX_QUEUE; i++) { ++ stat = ipqess_r32(ess, IPQESS_REG_RX_STAT_PKT_Q(i)); ++ *p += stat; ++ p++; ++ } ++ ++ for (i = 0; i < IPQESS_MAX_RX_QUEUE; i++) { ++ stat = ipqess_r32(ess, IPQESS_REG_RX_STAT_BYTE_Q(i)); ++ *p += stat; ++ p++; ++ } ++} ++ ++static int ipqess_tx_ring_alloc(struct ipqess *ess) ++{ ++ struct device *dev = &ess->pdev->dev; ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ struct ipqess_tx_ring *tx_ring = &ess->tx_ring[i]; ++ size_t size; ++ u32 idx; ++ ++ tx_ring->ess = ess; ++ tx_ring->ring_id = i; ++ tx_ring->idx = i * 4; ++ tx_ring->count = IPQESS_TX_RING_SIZE; ++ tx_ring->nq = netdev_get_tx_queue(ess->netdev, i); ++ ++ size = sizeof(struct ipqess_buf) * IPQESS_TX_RING_SIZE; ++ tx_ring->buf = devm_kzalloc(dev, size, GFP_KERNEL); ++ if (!tx_ring->buf) ++ return -ENOMEM; ++ ++ size = sizeof(struct ipqess_tx_desc) * IPQESS_TX_RING_SIZE; ++ tx_ring->hw_desc = dmam_alloc_coherent(dev, size, &tx_ring->dma, ++ GFP_KERNEL); ++ if (!tx_ring->hw_desc) ++ return -ENOMEM; ++ ++ ipqess_w32(ess, IPQESS_REG_TPD_BASE_ADDR_Q(tx_ring->idx), ++ (u32)tx_ring->dma); ++ ++ idx = ipqess_r32(ess, IPQESS_REG_TPD_IDX_Q(tx_ring->idx)); ++ idx >>= IPQESS_TPD_CONS_IDX_SHIFT; /* need u32 here */ ++ idx &= 0xffff; ++ tx_ring->head = idx; ++ tx_ring->tail = idx; ++ ++ ipqess_m32(ess, IPQESS_TPD_PROD_IDX_MASK << IPQESS_TPD_PROD_IDX_SHIFT, ++ idx, IPQESS_REG_TPD_IDX_Q(tx_ring->idx)); ++ ipqess_w32(ess, IPQESS_REG_TX_SW_CONS_IDX_Q(tx_ring->idx), idx); ++ ipqess_w32(ess, IPQESS_REG_TPD_RING_SIZE, IPQESS_TX_RING_SIZE); ++ } ++ ++ return 0; ++} ++ ++static int ipqess_tx_unmap_and_free(struct device *dev, struct ipqess_buf *buf) ++{ ++ int len = 0; ++ ++ if (buf->flags & IPQESS_DESC_SINGLE) ++ dma_unmap_single(dev, buf->dma, buf->length, DMA_TO_DEVICE); ++ else if (buf->flags & IPQESS_DESC_PAGE) ++ dma_unmap_page(dev, buf->dma, buf->length, DMA_TO_DEVICE); ++ ++ if (buf->flags & IPQESS_DESC_LAST) { ++ len = buf->skb->len; ++ dev_kfree_skb_any(buf->skb); ++ } ++ ++ buf->flags = 0; ++ ++ return len; ++} ++ ++static void ipqess_tx_ring_free(struct ipqess *ess) ++{ ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ int j; ++ ++ if (ess->tx_ring[i].hw_desc) ++ continue; ++ ++ for (j = 0; j < IPQESS_TX_RING_SIZE; j++) { ++ struct ipqess_buf *buf = &ess->tx_ring[i].buf[j]; ++ ++ ipqess_tx_unmap_and_free(&ess->pdev->dev, buf); ++ } ++ ++ ess->tx_ring[i].buf = NULL; ++ } ++} ++ ++static int ipqess_rx_buf_prepare(struct ipqess_buf *buf, ++ struct ipqess_rx_ring *rx_ring) ++{ ++ memset(buf->skb->data, 0, sizeof(struct ipqess_rx_desc)); ++ ++ buf->dma = dma_map_single(rx_ring->ppdev, buf->skb->data, ++ IPQESS_RX_HEAD_BUFF_SIZE, DMA_FROM_DEVICE); ++ if (dma_mapping_error(rx_ring->ppdev, buf->dma)) { ++ dev_kfree_skb_any(buf->skb); ++ buf->skb = NULL; ++ return -EFAULT; ++ } ++ ++ buf->length = IPQESS_RX_HEAD_BUFF_SIZE; ++ rx_ring->hw_desc[rx_ring->head] = (struct ipqess_rx_desc *)buf->dma; ++ rx_ring->head = (rx_ring->head + 1) % IPQESS_RX_RING_SIZE; ++ ++ ipqess_m32(rx_ring->ess, IPQESS_RFD_PROD_IDX_BITS, ++ (rx_ring->head + IPQESS_RX_RING_SIZE - 1) % IPQESS_RX_RING_SIZE, ++ IPQESS_REG_RFD_IDX_Q(rx_ring->idx)); ++ ++ return 0; ++} ++ ++/* locking is handled by the caller */ ++static int ipqess_rx_buf_alloc_napi(struct ipqess_rx_ring *rx_ring) ++{ ++ struct ipqess_buf *buf = &rx_ring->buf[rx_ring->head]; ++ ++ buf->skb = napi_alloc_skb(&rx_ring->napi_rx, IPQESS_RX_HEAD_BUFF_SIZE); ++ if (!buf->skb) ++ return -ENOMEM; ++ ++ return ipqess_rx_buf_prepare(buf, rx_ring); ++} ++ ++static int ipqess_rx_buf_alloc(struct ipqess_rx_ring *rx_ring) ++{ ++ struct ipqess_buf *buf = &rx_ring->buf[rx_ring->head]; ++ ++ buf->skb = netdev_alloc_skb_ip_align(rx_ring->ess->netdev, ++ IPQESS_RX_HEAD_BUFF_SIZE); ++ ++ if (!buf->skb) ++ return -ENOMEM; ++ ++ return ipqess_rx_buf_prepare(buf, rx_ring); ++} ++ ++static void ipqess_refill_work(struct work_struct *work) ++{ ++ struct ipqess_rx_ring_refill *rx_refill = container_of(work, ++ struct ipqess_rx_ring_refill, refill_work); ++ struct ipqess_rx_ring *rx_ring = rx_refill->rx_ring; ++ int refill = 0; ++ ++ /* don't let this loop by accident. */ ++ while (atomic_dec_and_test(&rx_ring->refill_count)) { ++ napi_disable(&rx_ring->napi_rx); ++ if (ipqess_rx_buf_alloc(rx_ring)) { ++ refill++; ++ dev_dbg(rx_ring->ppdev, ++ "Not all buffers were reallocated"); ++ } ++ napi_enable(&rx_ring->napi_rx); ++ } ++ ++ if (atomic_add_return(refill, &rx_ring->refill_count)) ++ schedule_work(&rx_refill->refill_work); ++} ++ ++static int ipqess_rx_ring_alloc(struct ipqess *ess) ++{ ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ int j; ++ ++ ess->rx_ring[i].ess = ess; ++ ess->rx_ring[i].ppdev = &ess->pdev->dev; ++ ess->rx_ring[i].ring_id = i; ++ ess->rx_ring[i].idx = i * 2; ++ ++ ess->rx_ring[i].buf = devm_kzalloc(&ess->pdev->dev, ++ sizeof(struct ipqess_buf) * IPQESS_RX_RING_SIZE, ++ GFP_KERNEL); ++ ++ if (!ess->rx_ring[i].buf) ++ return -ENOMEM; ++ ++ ess->rx_ring[i].hw_desc = ++ dmam_alloc_coherent(&ess->pdev->dev, ++ sizeof(struct ipqess_rx_desc) * IPQESS_RX_RING_SIZE, ++ &ess->rx_ring[i].dma, GFP_KERNEL); ++ ++ if (!ess->rx_ring[i].hw_desc) ++ return -ENOMEM; ++ ++ for (j = 0; j < IPQESS_RX_RING_SIZE; j++) ++ if (ipqess_rx_buf_alloc(&ess->rx_ring[i]) < 0) ++ return -ENOMEM; ++ ++ ess->rx_refill[i].rx_ring = &ess->rx_ring[i]; ++ INIT_WORK(&ess->rx_refill[i].refill_work, ipqess_refill_work); ++ ++ ipqess_w32(ess, IPQESS_REG_RFD_BASE_ADDR_Q(ess->rx_ring[i].idx), ++ (u32)(ess->rx_ring[i].dma)); ++ } ++ ++ ipqess_w32(ess, IPQESS_REG_RX_DESC0, ++ (IPQESS_RX_HEAD_BUFF_SIZE << IPQESS_RX_BUF_SIZE_SHIFT) | ++ (IPQESS_RX_RING_SIZE << IPQESS_RFD_RING_SIZE_SHIFT)); ++ ++ return 0; ++} ++ ++static void ipqess_rx_ring_free(struct ipqess *ess) ++{ ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ int j; ++ ++ cancel_work_sync(&ess->rx_refill[i].refill_work); ++ atomic_set(&ess->rx_ring[i].refill_count, 0); ++ ++ for (j = 0; j < IPQESS_RX_RING_SIZE; j++) { ++ dma_unmap_single(&ess->pdev->dev, ++ ess->rx_ring[i].buf[j].dma, ++ ess->rx_ring[i].buf[j].length, ++ DMA_FROM_DEVICE); ++ dev_kfree_skb_any(ess->rx_ring[i].buf[j].skb); ++ } ++ } ++} ++ ++static struct net_device_stats *ipqess_get_stats(struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ spin_lock(&ess->stats_lock); ++ ipqess_update_hw_stats(ess); ++ spin_unlock(&ess->stats_lock); ++ ++ return &ess->stats; ++} ++ ++static int ipqess_rx_poll(struct ipqess_rx_ring *rx_ring, int budget) ++{ ++ u32 length = 0, num_desc, tail, rx_ring_tail; ++ int done = 0; ++ ++ rx_ring_tail = rx_ring->tail; ++ ++ tail = ipqess_r32(rx_ring->ess, IPQESS_REG_RFD_IDX_Q(rx_ring->idx)); ++ tail >>= IPQESS_RFD_CONS_IDX_SHIFT; ++ tail &= IPQESS_RFD_CONS_IDX_MASK; ++ ++ while (done < budget) { ++ struct ipqess_rx_desc *rd; ++ struct sk_buff *skb; ++ ++ if (rx_ring_tail == tail) ++ break; ++ ++ dma_unmap_single(rx_ring->ppdev, ++ rx_ring->buf[rx_ring_tail].dma, ++ rx_ring->buf[rx_ring_tail].length, ++ DMA_FROM_DEVICE); ++ ++ skb = xchg(&rx_ring->buf[rx_ring_tail].skb, NULL); ++ rd = (struct ipqess_rx_desc *)skb->data; ++ rx_ring_tail = IPQESS_NEXT_IDX(rx_ring_tail, IPQESS_RX_RING_SIZE); ++ ++ /* Check if RRD is valid */ ++ if (!(rd->rrd7 & cpu_to_le16(IPQESS_RRD_DESC_VALID))) { ++ num_desc = 1; ++ dev_kfree_skb_any(skb); ++ goto skip; ++ } ++ ++ num_desc = le16_to_cpu(rd->rrd1) & IPQESS_RRD_NUM_RFD_MASK; ++ length = le16_to_cpu(rd->rrd6) & IPQESS_RRD_PKT_SIZE_MASK; ++ ++ skb_reserve(skb, IPQESS_RRD_SIZE); ++ if (num_desc > 1) { ++ struct sk_buff *skb_prev = NULL; ++ int size_remaining; ++ int i; ++ ++ skb->data_len = 0; ++ skb->tail += (IPQESS_RX_HEAD_BUFF_SIZE - IPQESS_RRD_SIZE); ++ skb->len = length; ++ skb->truesize = length; ++ size_remaining = length - (IPQESS_RX_HEAD_BUFF_SIZE - IPQESS_RRD_SIZE); ++ ++ for (i = 1; i < num_desc; i++) { ++ struct sk_buff *skb_temp = rx_ring->buf[rx_ring_tail].skb; ++ ++ dma_unmap_single(rx_ring->ppdev, ++ rx_ring->buf[rx_ring_tail].dma, ++ rx_ring->buf[rx_ring_tail].length, ++ DMA_FROM_DEVICE); ++ ++ skb_put(skb_temp, min(size_remaining, IPQESS_RX_HEAD_BUFF_SIZE)); ++ if (skb_prev) ++ skb_prev->next = rx_ring->buf[rx_ring_tail].skb; ++ else ++ skb_shinfo(skb)->frag_list = rx_ring->buf[rx_ring_tail].skb; ++ skb_prev = rx_ring->buf[rx_ring_tail].skb; ++ rx_ring->buf[rx_ring_tail].skb->next = NULL; ++ ++ skb->data_len += rx_ring->buf[rx_ring_tail].skb->len; ++ size_remaining -= rx_ring->buf[rx_ring_tail].skb->len; ++ ++ rx_ring_tail = IPQESS_NEXT_IDX(rx_ring_tail, IPQESS_RX_RING_SIZE); ++ } ++ ++ } else { ++ skb_put(skb, length); ++ } ++ ++ skb->dev = rx_ring->ess->netdev; ++ skb->protocol = eth_type_trans(skb, rx_ring->ess->netdev); ++ skb_record_rx_queue(skb, rx_ring->ring_id); ++ ++ if (rd->rrd6 & cpu_to_le16(IPQESS_RRD_CSUM_FAIL_MASK)) ++ skb_checksum_none_assert(skb); ++ else ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ ++ if (rd->rrd7 & cpu_to_le16(IPQESS_RRD_CVLAN)) ++ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ++ le16_to_cpu(rd->rrd4)); ++ else if (rd->rrd1 & cpu_to_le16(IPQESS_RRD_SVLAN)) ++ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), ++ le16_to_cpu(rd->rrd4)); ++ ++ napi_gro_receive(&rx_ring->napi_rx, skb); ++ ++ rx_ring->ess->stats.rx_packets++; ++ rx_ring->ess->stats.rx_bytes += length; ++ ++ done++; ++skip: ++ ++ num_desc += atomic_xchg(&rx_ring->refill_count, 0); ++ while (num_desc) { ++ if (ipqess_rx_buf_alloc_napi(rx_ring)) { ++ num_desc = atomic_add_return(num_desc, ++ &rx_ring->refill_count); ++ if (num_desc >= DIV_ROUND_UP(IPQESS_RX_RING_SIZE * 4, 7)) ++ schedule_work(&rx_ring->ess->rx_refill[rx_ring->ring_id].refill_work); ++ break; ++ } ++ num_desc--; ++ } ++ } ++ ++ ipqess_w32(rx_ring->ess, IPQESS_REG_RX_SW_CONS_IDX_Q(rx_ring->idx), ++ rx_ring_tail); ++ rx_ring->tail = rx_ring_tail; ++ ++ return done; ++} ++ ++static int ipqess_tx_complete(struct ipqess_tx_ring *tx_ring, int budget) ++{ ++ int total = 0, ret; ++ int done = 0; ++ u32 tail; ++ ++ tail = ipqess_r32(tx_ring->ess, IPQESS_REG_TPD_IDX_Q(tx_ring->idx)); ++ tail >>= IPQESS_TPD_CONS_IDX_SHIFT; ++ tail &= IPQESS_TPD_CONS_IDX_MASK; ++ ++ do { ++ ret = ipqess_tx_unmap_and_free(&tx_ring->ess->pdev->dev, ++ &tx_ring->buf[tx_ring->tail]); ++ tx_ring->tail = IPQESS_NEXT_IDX(tx_ring->tail, tx_ring->count); ++ ++ total += ret; ++ } while ((++done < budget) && (tx_ring->tail != tail)); ++ ++ ipqess_w32(tx_ring->ess, IPQESS_REG_TX_SW_CONS_IDX_Q(tx_ring->idx), ++ tx_ring->tail); ++ ++ if (netif_tx_queue_stopped(tx_ring->nq)) { ++ netdev_dbg(tx_ring->ess->netdev, "waking up tx queue %d\n", ++ tx_ring->idx); ++ netif_tx_wake_queue(tx_ring->nq); ++ } ++ ++ netdev_tx_completed_queue(tx_ring->nq, done, total); ++ ++ return done; ++} ++ ++static int ipqess_tx_napi(struct napi_struct *napi, int budget) ++{ ++ struct ipqess_tx_ring *tx_ring = container_of(napi, struct ipqess_tx_ring, ++ napi_tx); ++ int work_done = 0; ++ u32 tx_status; ++ ++ tx_status = ipqess_r32(tx_ring->ess, IPQESS_REG_TX_ISR); ++ tx_status &= BIT(tx_ring->idx); ++ ++ work_done = ipqess_tx_complete(tx_ring, budget); ++ ++ ipqess_w32(tx_ring->ess, IPQESS_REG_TX_ISR, tx_status); ++ ++ if (likely(work_done < budget)) { ++ if (napi_complete_done(napi, work_done)) ++ ipqess_w32(tx_ring->ess, ++ IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx), 0x1); ++ } ++ ++ return work_done; ++} ++ ++static int ipqess_rx_napi(struct napi_struct *napi, int budget) ++{ ++ struct ipqess_rx_ring *rx_ring = container_of(napi, struct ipqess_rx_ring, ++ napi_rx); ++ struct ipqess *ess = rx_ring->ess; ++ u32 rx_mask = BIT(rx_ring->idx); ++ int remaining_budget = budget; ++ int rx_done; ++ u32 status; ++ ++ do { ++ ipqess_w32(ess, IPQESS_REG_RX_ISR, rx_mask); ++ rx_done = ipqess_rx_poll(rx_ring, remaining_budget); ++ remaining_budget -= rx_done; ++ ++ status = ipqess_r32(ess, IPQESS_REG_RX_ISR); ++ } while (remaining_budget > 0 && (status & rx_mask)); ++ ++ if (remaining_budget <= 0) ++ return budget; ++ ++ if (napi_complete_done(napi, budget - remaining_budget)) ++ ipqess_w32(ess, IPQESS_REG_RX_INT_MASK_Q(rx_ring->idx), 0x1); ++ ++ return budget - remaining_budget; ++} ++ ++static irqreturn_t ipqess_interrupt_tx(int irq, void *priv) ++{ ++ struct ipqess_tx_ring *tx_ring = (struct ipqess_tx_ring *)priv; ++ ++ if (likely(napi_schedule_prep(&tx_ring->napi_tx))) { ++ __napi_schedule(&tx_ring->napi_tx); ++ ipqess_w32(tx_ring->ess, IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx), ++ 0x0); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t ipqess_interrupt_rx(int irq, void *priv) ++{ ++ struct ipqess_rx_ring *rx_ring = (struct ipqess_rx_ring *)priv; ++ ++ if (likely(napi_schedule_prep(&rx_ring->napi_rx))) { ++ __napi_schedule(&rx_ring->napi_rx); ++ ipqess_w32(rx_ring->ess, IPQESS_REG_RX_INT_MASK_Q(rx_ring->idx), ++ 0x0); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void ipqess_irq_enable(struct ipqess *ess) ++{ ++ int i; ++ ++ ipqess_w32(ess, IPQESS_REG_RX_ISR, 0xff); ++ ipqess_w32(ess, IPQESS_REG_TX_ISR, 0xffff); ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ ipqess_w32(ess, IPQESS_REG_RX_INT_MASK_Q(ess->rx_ring[i].idx), 1); ++ ipqess_w32(ess, IPQESS_REG_TX_INT_MASK_Q(ess->tx_ring[i].idx), 1); ++ } ++} ++ ++static void ipqess_irq_disable(struct ipqess *ess) ++{ ++ int i; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ ipqess_w32(ess, IPQESS_REG_RX_INT_MASK_Q(ess->rx_ring[i].idx), 0); ++ ipqess_w32(ess, IPQESS_REG_TX_INT_MASK_Q(ess->tx_ring[i].idx), 0); ++ } ++} ++ ++static int __init ipqess_init(struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ struct device_node *of_node = ess->pdev->dev.of_node; ++ int ret; ++ ++ ret = of_get_ethdev_address(of_node, netdev); ++ if (ret) ++ eth_hw_addr_random(netdev); ++ ++ return phylink_of_phy_connect(ess->phylink, of_node, 0); ++} ++ ++static void ipqess_uninit(struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ phylink_disconnect_phy(ess->phylink); ++} ++ ++static int ipqess_open(struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ int i, err; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ int qid; ++ ++ qid = ess->tx_ring[i].idx; ++ err = devm_request_irq(&netdev->dev, ess->tx_irq[qid], ++ ipqess_interrupt_tx, 0, ++ ess->tx_irq_names[qid], ++ &ess->tx_ring[i]); ++ if (err) ++ return err; ++ ++ qid = ess->rx_ring[i].idx; ++ err = devm_request_irq(&netdev->dev, ess->rx_irq[qid], ++ ipqess_interrupt_rx, 0, ++ ess->rx_irq_names[qid], ++ &ess->rx_ring[i]); ++ if (err) ++ return err; ++ ++ napi_enable(&ess->tx_ring[i].napi_tx); ++ napi_enable(&ess->rx_ring[i].napi_rx); ++ } ++ ++ ipqess_irq_enable(ess); ++ phylink_start(ess->phylink); ++ netif_tx_start_all_queues(netdev); ++ ++ return 0; ++} ++ ++static int ipqess_stop(struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ int i; ++ ++ netif_tx_stop_all_queues(netdev); ++ phylink_stop(ess->phylink); ++ ipqess_irq_disable(ess); ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ napi_disable(&ess->tx_ring[i].napi_tx); ++ napi_disable(&ess->rx_ring[i].napi_rx); ++ } ++ ++ return 0; ++} ++ ++static int ipqess_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ return phylink_mii_ioctl(ess->phylink, ifr, cmd); ++} ++ ++static u16 ipqess_tx_desc_available(struct ipqess_tx_ring *tx_ring) ++{ ++ u16 count = 0; ++ ++ if (tx_ring->tail <= tx_ring->head) ++ count = IPQESS_TX_RING_SIZE; ++ ++ count += tx_ring->tail - tx_ring->head - 1; ++ ++ return count; ++} ++ ++static int ipqess_cal_txd_req(struct sk_buff *skb) ++{ ++ int tpds; ++ ++ /* one TPD for the header, and one for each fragments */ ++ tpds = 1 + skb_shinfo(skb)->nr_frags; ++ if (skb_is_gso(skb) && skb_is_gso_v6(skb)) { ++ /* for LSOv2 one extra TPD is needed */ ++ tpds++; ++ } ++ ++ return tpds; ++} ++ ++static struct ipqess_buf *ipqess_get_tx_buffer(struct ipqess_tx_ring *tx_ring, ++ struct ipqess_tx_desc *desc) ++{ ++ return &tx_ring->buf[desc - tx_ring->hw_desc]; ++} ++ ++static struct ipqess_tx_desc *ipqess_tx_desc_next(struct ipqess_tx_ring *tx_ring) ++{ ++ struct ipqess_tx_desc *desc; ++ ++ desc = &tx_ring->hw_desc[tx_ring->head]; ++ tx_ring->head = IPQESS_NEXT_IDX(tx_ring->head, tx_ring->count); ++ ++ return desc; ++} ++ ++static void ipqess_rollback_tx(struct ipqess *eth, ++ struct ipqess_tx_desc *first_desc, int ring_id) ++{ ++ struct ipqess_tx_ring *tx_ring = ð->tx_ring[ring_id]; ++ struct ipqess_tx_desc *desc = NULL; ++ struct ipqess_buf *buf; ++ u16 start_index, index; ++ ++ start_index = first_desc - tx_ring->hw_desc; ++ ++ index = start_index; ++ while (index != tx_ring->head) { ++ desc = &tx_ring->hw_desc[index]; ++ buf = &tx_ring->buf[index]; ++ ipqess_tx_unmap_and_free(ð->pdev->dev, buf); ++ memset(desc, 0, sizeof(*desc)); ++ if (++index == tx_ring->count) ++ index = 0; ++ } ++ tx_ring->head = start_index; ++} ++ ++static int ipqess_tx_map_and_fill(struct ipqess_tx_ring *tx_ring, ++ struct sk_buff *skb) ++{ ++ struct ipqess_tx_desc *desc = NULL, *first_desc = NULL; ++ u32 word1 = 0, word3 = 0, lso_word1 = 0, svlan_tag = 0; ++ struct platform_device *pdev = tx_ring->ess->pdev; ++ struct ipqess_buf *buf = NULL; ++ u16 len; ++ int i; ++ ++ if (skb_is_gso(skb)) { ++ if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { ++ lso_word1 |= IPQESS_TPD_IPV4_EN; ++ ip_hdr(skb)->check = 0; ++ tcp_hdr(skb)->check = ~csum_tcpudp_magic(ip_hdr(skb)->saddr, ++ ip_hdr(skb)->daddr, ++ 0, IPPROTO_TCP, 0); ++ } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { ++ lso_word1 |= IPQESS_TPD_LSO_V2_EN; ++ ipv6_hdr(skb)->payload_len = 0; ++ tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, ++ &ipv6_hdr(skb)->daddr, ++ 0, IPPROTO_TCP, 0); ++ } ++ ++ lso_word1 |= IPQESS_TPD_LSO_EN | ++ ((skb_shinfo(skb)->gso_size & IPQESS_TPD_MSS_MASK) << ++ IPQESS_TPD_MSS_SHIFT) | ++ (skb_transport_offset(skb) << IPQESS_TPD_HDR_SHIFT); ++ } else if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { ++ u8 css, cso; ++ ++ cso = skb_checksum_start_offset(skb); ++ css = cso + skb->csum_offset; ++ ++ word1 |= (IPQESS_TPD_CUSTOM_CSUM_EN); ++ word1 |= (cso >> 1) << IPQESS_TPD_HDR_SHIFT; ++ word1 |= ((css >> 1) << IPQESS_TPD_CUSTOM_CSUM_SHIFT); ++ } ++ ++ if (skb_vlan_tag_present(skb)) { ++ switch (skb->vlan_proto) { ++ case htons(ETH_P_8021Q): ++ word3 |= BIT(IPQESS_TX_INS_CVLAN); ++ word3 |= skb_vlan_tag_get(skb) << IPQESS_TX_CVLAN_TAG_SHIFT; ++ break; ++ case htons(ETH_P_8021AD): ++ word1 |= BIT(IPQESS_TX_INS_SVLAN); ++ svlan_tag = skb_vlan_tag_get(skb); ++ break; ++ default: ++ dev_err(&pdev->dev, "no ctag or stag present\n"); ++ goto vlan_tag_error; ++ } ++ } ++ ++ if (eth_type_vlan(skb->protocol)) ++ word1 |= IPQESS_TPD_VLAN_TAGGED; ++ ++ if (skb->protocol == htons(ETH_P_PPP_SES)) ++ word1 |= IPQESS_TPD_PPPOE_EN; ++ ++ len = skb_headlen(skb); ++ ++ first_desc = ipqess_tx_desc_next(tx_ring); ++ desc = first_desc; ++ if (lso_word1 & IPQESS_TPD_LSO_V2_EN) { ++ desc->addr = cpu_to_le32(skb->len); ++ desc->word1 = cpu_to_le32(word1 | lso_word1); ++ desc->svlan_tag = cpu_to_le16(svlan_tag); ++ desc->word3 = cpu_to_le32(word3); ++ desc = ipqess_tx_desc_next(tx_ring); ++ } ++ ++ buf = ipqess_get_tx_buffer(tx_ring, desc); ++ buf->length = len; ++ buf->dma = dma_map_single(&pdev->dev, skb->data, len, DMA_TO_DEVICE); ++ ++ if (dma_mapping_error(&pdev->dev, buf->dma)) ++ goto dma_error; ++ ++ desc->addr = cpu_to_le32(buf->dma); ++ desc->len = cpu_to_le16(len); ++ ++ buf->flags |= IPQESS_DESC_SINGLE; ++ desc->word1 = cpu_to_le32(word1 | lso_word1); ++ desc->svlan_tag = cpu_to_le16(svlan_tag); ++ desc->word3 = cpu_to_le32(word3); ++ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ ++ len = skb_frag_size(frag); ++ desc = ipqess_tx_desc_next(tx_ring); ++ buf = ipqess_get_tx_buffer(tx_ring, desc); ++ buf->length = len; ++ buf->flags |= IPQESS_DESC_PAGE; ++ buf->dma = skb_frag_dma_map(&pdev->dev, frag, 0, len, ++ DMA_TO_DEVICE); ++ ++ if (dma_mapping_error(&pdev->dev, buf->dma)) ++ goto dma_error; ++ ++ desc->addr = cpu_to_le32(buf->dma); ++ desc->len = cpu_to_le16(len); ++ desc->svlan_tag = cpu_to_le16(svlan_tag); ++ desc->word1 = cpu_to_le32(word1 | lso_word1); ++ desc->word3 = cpu_to_le32(word3); ++ } ++ desc->word1 |= cpu_to_le32(1 << IPQESS_TPD_EOP_SHIFT); ++ buf->skb = skb; ++ buf->flags |= IPQESS_DESC_LAST; ++ ++ return 0; ++ ++dma_error: ++ ipqess_rollback_tx(tx_ring->ess, first_desc, tx_ring->ring_id); ++ dev_err(&pdev->dev, "TX DMA map failed\n"); ++ ++vlan_tag_error: ++ return -ENOMEM; ++} ++ ++static void ipqess_kick_tx(struct ipqess_tx_ring *tx_ring) ++{ ++ /* Ensure that all TPDs has been written completely */ ++ dma_wmb(); ++ ++ /* update software producer index */ ++ ipqess_w32(tx_ring->ess, IPQESS_REG_TPD_IDX_Q(tx_ring->idx), ++ tx_ring->head); ++} ++ ++static netdev_tx_t ipqess_xmit(struct sk_buff *skb, struct net_device *netdev) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ struct ipqess_tx_ring *tx_ring; ++ int avail; ++ int tx_num; ++ int ret; ++ ++ tx_ring = &ess->tx_ring[skb_get_queue_mapping(skb)]; ++ tx_num = ipqess_cal_txd_req(skb); ++ avail = ipqess_tx_desc_available(tx_ring); ++ if (avail < tx_num) { ++ netdev_dbg(netdev, ++ "stopping tx queue %d, avail=%d req=%d im=%x\n", ++ tx_ring->idx, avail, tx_num, ++ ipqess_r32(tx_ring->ess, ++ IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx))); ++ netif_tx_stop_queue(tx_ring->nq); ++ ipqess_w32(tx_ring->ess, IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx), 0x1); ++ ipqess_kick_tx(tx_ring); ++ return NETDEV_TX_BUSY; ++ } ++ ++ ret = ipqess_tx_map_and_fill(tx_ring, skb); ++ if (ret) { ++ dev_kfree_skb_any(skb); ++ ess->stats.tx_errors++; ++ goto err_out; ++ } ++ ++ ess->stats.tx_packets++; ++ ess->stats.tx_bytes += skb->len; ++ netdev_tx_sent_queue(tx_ring->nq, skb->len); ++ ++ if (!netdev_xmit_more() || netif_xmit_stopped(tx_ring->nq)) ++ ipqess_kick_tx(tx_ring); ++ ++err_out: ++ return NETDEV_TX_OK; ++} ++ ++static int ipqess_set_mac_address(struct net_device *netdev, void *p) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ const char *macaddr = netdev->dev_addr; ++ int ret = eth_mac_addr(netdev, p); ++ ++ if (ret) ++ return ret; ++ ++ ipqess_w32(ess, IPQESS_REG_MAC_CTRL1, (macaddr[0] << 8) | macaddr[1]); ++ ipqess_w32(ess, IPQESS_REG_MAC_CTRL0, ++ (macaddr[2] << 24) | (macaddr[3] << 16) | (macaddr[4] << 8) | ++ macaddr[5]); ++ ++ return 0; ++} ++ ++static void ipqess_tx_timeout(struct net_device *netdev, unsigned int txq_id) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ struct ipqess_tx_ring *tr = &ess->tx_ring[txq_id]; ++ ++ netdev_warn(netdev, "TX timeout on queue %d\n", tr->idx); ++} ++ ++static const struct net_device_ops ipqess_axi_netdev_ops = { ++ .ndo_init = ipqess_init, ++ .ndo_uninit = ipqess_uninit, ++ .ndo_open = ipqess_open, ++ .ndo_stop = ipqess_stop, ++ .ndo_do_ioctl = ipqess_do_ioctl, ++ .ndo_start_xmit = ipqess_xmit, ++ .ndo_get_stats = ipqess_get_stats, ++ .ndo_set_mac_address = ipqess_set_mac_address, ++ .ndo_tx_timeout = ipqess_tx_timeout, ++}; ++ ++static void ipqess_hw_stop(struct ipqess *ess) ++{ ++ int i; ++ ++ /* disable all RX queue IRQs */ ++ for (i = 0; i < IPQESS_MAX_RX_QUEUE; i++) ++ ipqess_w32(ess, IPQESS_REG_RX_INT_MASK_Q(i), 0); ++ ++ /* disable all TX queue IRQs */ ++ for (i = 0; i < IPQESS_MAX_TX_QUEUE; i++) ++ ipqess_w32(ess, IPQESS_REG_TX_INT_MASK_Q(i), 0); ++ ++ /* disable all other IRQs */ ++ ipqess_w32(ess, IPQESS_REG_MISC_IMR, 0); ++ ipqess_w32(ess, IPQESS_REG_WOL_IMR, 0); ++ ++ /* clear the IRQ status registers */ ++ ipqess_w32(ess, IPQESS_REG_RX_ISR, 0xff); ++ ipqess_w32(ess, IPQESS_REG_TX_ISR, 0xffff); ++ ipqess_w32(ess, IPQESS_REG_MISC_ISR, 0x1fff); ++ ipqess_w32(ess, IPQESS_REG_WOL_ISR, 0x1); ++ ipqess_w32(ess, IPQESS_REG_WOL_CTRL, 0); ++ ++ /* disable RX and TX queues */ ++ ipqess_m32(ess, IPQESS_RXQ_CTRL_EN_MASK, 0, IPQESS_REG_RXQ_CTRL); ++ ipqess_m32(ess, IPQESS_TXQ_CTRL_TXQ_EN, 0, IPQESS_REG_TXQ_CTRL); ++} ++ ++static int ipqess_hw_init(struct ipqess *ess) ++{ ++ int i, err; ++ u32 tmp; ++ ++ ipqess_hw_stop(ess); ++ ++ ipqess_m32(ess, BIT(IPQESS_INTR_SW_IDX_W_TYP_SHIFT), ++ IPQESS_INTR_SW_IDX_W_TYPE << IPQESS_INTR_SW_IDX_W_TYP_SHIFT, ++ IPQESS_REG_INTR_CTRL); ++ ++ /* enable IRQ delay slot */ ++ ipqess_w32(ess, IPQESS_REG_IRQ_MODRT_TIMER_INIT, ++ (IPQESS_TX_IMT << IPQESS_IRQ_MODRT_TX_TIMER_SHIFT) | ++ (IPQESS_RX_IMT << IPQESS_IRQ_MODRT_RX_TIMER_SHIFT)); ++ ++ /* Set Customer and Service VLAN TPIDs */ ++ ipqess_w32(ess, IPQESS_REG_VLAN_CFG, ++ (ETH_P_8021Q << IPQESS_VLAN_CFG_CVLAN_TPID_SHIFT) | ++ (ETH_P_8021AD << IPQESS_VLAN_CFG_SVLAN_TPID_SHIFT)); ++ ++ /* Configure the TX Queue bursting */ ++ ipqess_w32(ess, IPQESS_REG_TXQ_CTRL, ++ (IPQESS_TPD_BURST << IPQESS_TXQ_NUM_TPD_BURST_SHIFT) | ++ (IPQESS_TXF_BURST << IPQESS_TXQ_TXF_BURST_NUM_SHIFT) | ++ IPQESS_TXQ_CTRL_TPD_BURST_EN); ++ ++ /* Set RSS type */ ++ ipqess_w32(ess, IPQESS_REG_RSS_TYPE, ++ IPQESS_RSS_TYPE_IPV4TCP | IPQESS_RSS_TYPE_IPV6_TCP | ++ IPQESS_RSS_TYPE_IPV4_UDP | IPQESS_RSS_TYPE_IPV6UDP | ++ IPQESS_RSS_TYPE_IPV4 | IPQESS_RSS_TYPE_IPV6); ++ ++ /* Set RFD ring burst and threshold */ ++ ipqess_w32(ess, IPQESS_REG_RX_DESC1, ++ (IPQESS_RFD_BURST << IPQESS_RXQ_RFD_BURST_NUM_SHIFT) | ++ (IPQESS_RFD_THR << IPQESS_RXQ_RFD_PF_THRESH_SHIFT) | ++ (IPQESS_RFD_LTHR << IPQESS_RXQ_RFD_LOW_THRESH_SHIFT)); ++ ++ /* Set Rx FIFO ++ * - threshold to start to DMA data to host ++ */ ++ ipqess_w32(ess, IPQESS_REG_RXQ_CTRL, ++ IPQESS_FIFO_THRESH_128_BYTE | IPQESS_RXQ_CTRL_RMV_VLAN); ++ ++ err = ipqess_rx_ring_alloc(ess); ++ if (err) ++ return err; ++ ++ err = ipqess_tx_ring_alloc(ess); ++ if (err) ++ goto err_rx_ring_free; ++ ++ /* Load all of ring base addresses above into the dma engine */ ++ ipqess_m32(ess, 0, BIT(IPQESS_LOAD_PTR_SHIFT), IPQESS_REG_TX_SRAM_PART); ++ ++ /* Disable TX FIFO low watermark and high watermark */ ++ ipqess_w32(ess, IPQESS_REG_TXF_WATER_MARK, 0); ++ ++ /* Configure RSS indirection table. ++ * 128 hash will be configured in the following ++ * pattern: hash{0,1,2,3} = {Q0,Q2,Q4,Q6} respectively ++ * and so on ++ */ ++ for (i = 0; i < IPQESS_NUM_IDT; i++) ++ ipqess_w32(ess, IPQESS_REG_RSS_IDT(i), IPQESS_RSS_IDT_VALUE); ++ ++ /* Configure load balance mapping table. ++ * 4 table entry will be configured according to the ++ * following pattern: load_balance{0,1,2,3} = {Q0,Q1,Q3,Q4} ++ * respectively. ++ */ ++ ipqess_w32(ess, IPQESS_REG_LB_RING, IPQESS_LB_REG_VALUE); ++ ++ /* Configure Virtual queue for Tx rings */ ++ ipqess_w32(ess, IPQESS_REG_VQ_CTRL0, IPQESS_VQ_REG_VALUE); ++ ipqess_w32(ess, IPQESS_REG_VQ_CTRL1, IPQESS_VQ_REG_VALUE); ++ ++ /* Configure Max AXI Burst write size to 128 bytes*/ ++ ipqess_w32(ess, IPQESS_REG_AXIW_CTRL_MAXWRSIZE, ++ IPQESS_AXIW_MAXWRSIZE_VALUE); ++ ++ /* Enable TX queues */ ++ ipqess_m32(ess, 0, IPQESS_TXQ_CTRL_TXQ_EN, IPQESS_REG_TXQ_CTRL); ++ ++ /* Enable RX queues */ ++ tmp = 0; ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) ++ tmp |= IPQESS_RXQ_CTRL_EN(ess->rx_ring[i].idx); ++ ++ ipqess_m32(ess, IPQESS_RXQ_CTRL_EN_MASK, tmp, IPQESS_REG_RXQ_CTRL); ++ ++ return 0; ++ ++err_rx_ring_free: ++ ++ ipqess_rx_ring_free(ess); ++ return err; ++} ++ ++static void ipqess_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ /* Nothing to do, use fixed Internal mode */ ++} ++ ++static void ipqess_mac_link_down(struct phylink_config *config, ++ unsigned int mode, ++ phy_interface_t interface) ++{ ++ /* Nothing to do, use fixed Internal mode */ ++} ++ ++static void ipqess_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) ++{ ++ /* Nothing to do, use fixed Internal mode */ ++} ++ ++static struct phylink_mac_ops ipqess_phylink_mac_ops = { ++ .validate = phylink_generic_validate, ++ .mac_config = ipqess_mac_config, ++ .mac_link_up = ipqess_mac_link_up, ++ .mac_link_down = ipqess_mac_link_down, ++}; ++ ++static void ipqess_reset(struct ipqess *ess) ++{ ++ reset_control_assert(ess->ess_rst); ++ ++ mdelay(10); ++ ++ reset_control_deassert(ess->ess_rst); ++ ++ /* Waiting for all inner tables to be flushed and reinitialized. ++ * This takes between 5 and 10 ms ++ */ ++ ++ mdelay(10); ++} ++ ++static int ipqess_axi_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct net_device *netdev; ++ phy_interface_t phy_mode; ++ struct ipqess *ess; ++ int i, err = 0; ++ ++ netdev = devm_alloc_etherdev_mqs(&pdev->dev, sizeof(*ess), ++ IPQESS_NETDEV_QUEUES, ++ IPQESS_NETDEV_QUEUES); ++ if (!netdev) ++ return -ENOMEM; ++ ++ ess = netdev_priv(netdev); ++ ess->netdev = netdev; ++ ess->pdev = pdev; ++ spin_lock_init(&ess->stats_lock); ++ SET_NETDEV_DEV(netdev, &pdev->dev); ++ platform_set_drvdata(pdev, netdev); ++ ++ ess->hw_addr = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); ++ if (IS_ERR(ess->hw_addr)) ++ return PTR_ERR(ess->hw_addr); ++ ++ err = of_get_phy_mode(np, &phy_mode); ++ if (err) { ++ dev_err(&pdev->dev, "incorrect phy-mode\n"); ++ return err; ++ } ++ ++ ess->ess_clk = devm_clk_get(&pdev->dev, NULL); ++ if (!IS_ERR(ess->ess_clk)) ++ clk_prepare_enable(ess->ess_clk); ++ ++ ess->ess_rst = devm_reset_control_get(&pdev->dev, NULL); ++ if (IS_ERR(ess->ess_rst)) ++ goto err_clk; ++ ++ ipqess_reset(ess); ++ ++ ess->phylink_config.dev = &netdev->dev; ++ ess->phylink_config.type = PHYLINK_NETDEV; ++ ess->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 | ++ MAC_100 | MAC_1000FD; ++ ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ ess->phylink_config.supported_interfaces); ++ ++ ess->phylink = phylink_create(&ess->phylink_config, ++ of_fwnode_handle(np), phy_mode, ++ &ipqess_phylink_mac_ops); ++ if (IS_ERR(ess->phylink)) { ++ err = PTR_ERR(ess->phylink); ++ goto err_clk; ++ } ++ ++ for (i = 0; i < IPQESS_MAX_TX_QUEUE; i++) { ++ ess->tx_irq[i] = platform_get_irq(pdev, i); ++ scnprintf(ess->tx_irq_names[i], sizeof(ess->tx_irq_names[i]), ++ "%s:txq%d", pdev->name, i); ++ } ++ ++ for (i = 0; i < IPQESS_MAX_RX_QUEUE; i++) { ++ ess->rx_irq[i] = platform_get_irq(pdev, i + IPQESS_MAX_TX_QUEUE); ++ scnprintf(ess->rx_irq_names[i], sizeof(ess->rx_irq_names[i]), ++ "%s:rxq%d", pdev->name, i); ++ } ++ ++ netdev->netdev_ops = &ipqess_axi_netdev_ops; ++ netdev->features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | ++ NETIF_F_HW_VLAN_CTAG_RX | ++ NETIF_F_HW_VLAN_CTAG_TX | ++ NETIF_F_TSO | NETIF_F_GRO | NETIF_F_SG; ++ /* feature change is not supported yet */ ++ netdev->hw_features = 0; ++ netdev->vlan_features = NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_RXCSUM | ++ NETIF_F_TSO | ++ NETIF_F_GRO; ++ netdev->watchdog_timeo = 5 * HZ; ++ netdev->base_addr = (u32)ess->hw_addr; ++ netdev->max_mtu = 9000; ++ netdev->gso_max_segs = IPQESS_TX_RING_SIZE / 2; ++ ++ ipqess_set_ethtool_ops(netdev); ++ ++ err = ipqess_hw_init(ess); ++ if (err) ++ goto err_phylink; ++ ++ for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ netif_napi_add_tx(netdev, &ess->tx_ring[i].napi_tx, ipqess_tx_napi); ++ netif_napi_add(netdev, &ess->rx_ring[i].napi_rx, ipqess_rx_napi); ++ } ++ ++ err = register_netdev(netdev); ++ if (err) ++ goto err_hw_stop; ++ ++ return 0; ++ ++err_hw_stop: ++ ipqess_hw_stop(ess); ++ ++ ipqess_tx_ring_free(ess); ++ ipqess_rx_ring_free(ess); ++err_phylink: ++ phylink_destroy(ess->phylink); ++ ++err_clk: ++ clk_disable_unprepare(ess->ess_clk); ++ ++ return err; ++} ++ ++static int ipqess_axi_remove(struct platform_device *pdev) ++{ ++ const struct net_device *netdev = platform_get_drvdata(pdev); ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ unregister_netdev(ess->netdev); ++ ipqess_hw_stop(ess); ++ ++ ipqess_tx_ring_free(ess); ++ ipqess_rx_ring_free(ess); ++ ++ phylink_destroy(ess->phylink); ++ clk_disable_unprepare(ess->ess_clk); ++ ++ return 0; ++} ++ ++static const struct of_device_id ipqess_of_mtable[] = { ++ {.compatible = "qcom,ipq4019-ess-edma" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, ipqess_of_mtable); ++ ++static struct platform_driver ipqess_axi_driver = { ++ .driver = { ++ .name = "ipqess-edma", ++ .of_match_table = ipqess_of_mtable, ++ }, ++ .probe = ipqess_axi_probe, ++ .remove = ipqess_axi_remove, ++}; ++ ++module_platform_driver(ipqess_axi_driver); ++ ++MODULE_AUTHOR("Qualcomm Atheros Inc"); ++MODULE_AUTHOR("John Crispin "); ++MODULE_AUTHOR("Christian Lamparter "); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_AUTHOR("Maxime Chevallier "); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.h +@@ -0,0 +1,518 @@ ++/* SPDX-License-Identifier: (GPL-2.0 OR ISC) */ ++/* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2017 - 2018, John Crispin ++ * Copyright (c) 2018 - 2019, Christian Lamparter ++ * Copyright (c) 2020 - 2021, Gabor Juhos ++ * Copyright (c) 2021 - 2022, Maxime Chevallier ++ * ++ */ ++ ++#ifndef _IPQESS_H_ ++#define _IPQESS_H_ ++ ++#define IPQESS_NETDEV_QUEUES 4 ++ ++#define IPQESS_TPD_EOP_SHIFT 31 ++ ++#define IPQESS_PORT_ID_SHIFT 12 ++#define IPQESS_PORT_ID_MASK 0x7 ++ ++/* tpd word 3 bit 18-28 */ ++#define IPQESS_TPD_PORT_BITMAP_SHIFT 18 ++ ++#define IPQESS_TPD_FROM_CPU_SHIFT 25 ++ ++#define IPQESS_RX_RING_SIZE 128 ++#define IPQESS_RX_HEAD_BUFF_SIZE 1540 ++#define IPQESS_TX_RING_SIZE 128 ++#define IPQESS_MAX_RX_QUEUE 8 ++#define IPQESS_MAX_TX_QUEUE 16 ++ ++/* Configurations */ ++#define IPQESS_INTR_CLEAR_TYPE 0 ++#define IPQESS_INTR_SW_IDX_W_TYPE 0 ++#define IPQESS_FIFO_THRESH_TYPE 0 ++#define IPQESS_RSS_TYPE 0 ++#define IPQESS_RX_IMT 0x0020 ++#define IPQESS_TX_IMT 0x0050 ++#define IPQESS_TPD_BURST 5 ++#define IPQESS_TXF_BURST 0x100 ++#define IPQESS_RFD_BURST 8 ++#define IPQESS_RFD_THR 16 ++#define IPQESS_RFD_LTHR 0 ++ ++/* Flags used in transmit direction */ ++#define IPQESS_DESC_LAST 0x1 ++#define IPQESS_DESC_SINGLE 0x2 ++#define IPQESS_DESC_PAGE 0x4 ++ ++struct ipqess_statistics { ++ u32 tx_q0_pkt; ++ u32 tx_q1_pkt; ++ u32 tx_q2_pkt; ++ u32 tx_q3_pkt; ++ u32 tx_q4_pkt; ++ u32 tx_q5_pkt; ++ u32 tx_q6_pkt; ++ u32 tx_q7_pkt; ++ u32 tx_q8_pkt; ++ u32 tx_q9_pkt; ++ u32 tx_q10_pkt; ++ u32 tx_q11_pkt; ++ u32 tx_q12_pkt; ++ u32 tx_q13_pkt; ++ u32 tx_q14_pkt; ++ u32 tx_q15_pkt; ++ u32 tx_q0_byte; ++ u32 tx_q1_byte; ++ u32 tx_q2_byte; ++ u32 tx_q3_byte; ++ u32 tx_q4_byte; ++ u32 tx_q5_byte; ++ u32 tx_q6_byte; ++ u32 tx_q7_byte; ++ u32 tx_q8_byte; ++ u32 tx_q9_byte; ++ u32 tx_q10_byte; ++ u32 tx_q11_byte; ++ u32 tx_q12_byte; ++ u32 tx_q13_byte; ++ u32 tx_q14_byte; ++ u32 tx_q15_byte; ++ u32 rx_q0_pkt; ++ u32 rx_q1_pkt; ++ u32 rx_q2_pkt; ++ u32 rx_q3_pkt; ++ u32 rx_q4_pkt; ++ u32 rx_q5_pkt; ++ u32 rx_q6_pkt; ++ u32 rx_q7_pkt; ++ u32 rx_q0_byte; ++ u32 rx_q1_byte; ++ u32 rx_q2_byte; ++ u32 rx_q3_byte; ++ u32 rx_q4_byte; ++ u32 rx_q5_byte; ++ u32 rx_q6_byte; ++ u32 rx_q7_byte; ++ u32 tx_desc_error; ++}; ++ ++struct ipqess_tx_desc { ++ __le16 len; ++ __le16 svlan_tag; ++ __le32 word1; ++ __le32 addr; ++ __le32 word3; ++} __aligned(16) __packed; ++ ++struct ipqess_rx_desc { ++ __le16 rrd0; ++ __le16 rrd1; ++ __le16 rrd2; ++ __le16 rrd3; ++ __le16 rrd4; ++ __le16 rrd5; ++ __le16 rrd6; ++ __le16 rrd7; ++} __aligned(16) __packed; ++ ++struct ipqess_buf { ++ struct sk_buff *skb; ++ dma_addr_t dma; ++ u32 flags; ++ u16 length; ++}; ++ ++struct ipqess_tx_ring { ++ struct napi_struct napi_tx; ++ u32 idx; ++ int ring_id; ++ struct ipqess *ess; ++ struct netdev_queue *nq; ++ struct ipqess_tx_desc *hw_desc; ++ struct ipqess_buf *buf; ++ dma_addr_t dma; ++ u16 count; ++ u16 head; ++ u16 tail; ++}; ++ ++struct ipqess_rx_ring { ++ struct napi_struct napi_rx; ++ u32 idx; ++ int ring_id; ++ struct ipqess *ess; ++ struct device *ppdev; ++ struct ipqess_rx_desc **hw_desc; ++ struct ipqess_buf *buf; ++ dma_addr_t dma; ++ u16 head; ++ u16 tail; ++ atomic_t refill_count; ++}; ++ ++struct ipqess_rx_ring_refill { ++ struct ipqess_rx_ring *rx_ring; ++ struct work_struct refill_work; ++}; ++ ++#define IPQESS_IRQ_NAME_LEN 32 ++ ++struct ipqess { ++ struct net_device *netdev; ++ void __iomem *hw_addr; ++ ++ struct clk *ess_clk; ++ struct reset_control *ess_rst; ++ ++ struct ipqess_rx_ring rx_ring[IPQESS_NETDEV_QUEUES]; ++ ++ struct platform_device *pdev; ++ struct phylink *phylink; ++ struct phylink_config phylink_config; ++ struct ipqess_tx_ring tx_ring[IPQESS_NETDEV_QUEUES]; ++ ++ struct ipqess_statistics ipqess_stats; ++ ++ /* Protects stats */ ++ spinlock_t stats_lock; ++ struct net_device_stats stats; ++ ++ struct ipqess_rx_ring_refill rx_refill[IPQESS_NETDEV_QUEUES]; ++ u32 tx_irq[IPQESS_MAX_TX_QUEUE]; ++ char tx_irq_names[IPQESS_MAX_TX_QUEUE][IPQESS_IRQ_NAME_LEN]; ++ u32 rx_irq[IPQESS_MAX_RX_QUEUE]; ++ char rx_irq_names[IPQESS_MAX_TX_QUEUE][IPQESS_IRQ_NAME_LEN]; ++}; ++ ++void ipqess_set_ethtool_ops(struct net_device *netdev); ++void ipqess_update_hw_stats(struct ipqess *ess); ++ ++/* register definition */ ++#define IPQESS_REG_MAS_CTRL 0x0 ++#define IPQESS_REG_TIMEOUT_CTRL 0x004 ++#define IPQESS_REG_DBG0 0x008 ++#define IPQESS_REG_DBG1 0x00C ++#define IPQESS_REG_SW_CTRL0 0x100 ++#define IPQESS_REG_SW_CTRL1 0x104 ++ ++/* Interrupt Status Register */ ++#define IPQESS_REG_RX_ISR 0x200 ++#define IPQESS_REG_TX_ISR 0x208 ++#define IPQESS_REG_MISC_ISR 0x210 ++#define IPQESS_REG_WOL_ISR 0x218 ++ ++#define IPQESS_MISC_ISR_RX_URG_Q(x) (1 << (x)) ++ ++#define IPQESS_MISC_ISR_AXIR_TIMEOUT 0x00000100 ++#define IPQESS_MISC_ISR_AXIR_ERR 0x00000200 ++#define IPQESS_MISC_ISR_TXF_DEAD 0x00000400 ++#define IPQESS_MISC_ISR_AXIW_ERR 0x00000800 ++#define IPQESS_MISC_ISR_AXIW_TIMEOUT 0x00001000 ++ ++#define IPQESS_WOL_ISR 0x00000001 ++ ++/* Interrupt Mask Register */ ++#define IPQESS_REG_MISC_IMR 0x214 ++#define IPQESS_REG_WOL_IMR 0x218 ++ ++#define IPQESS_RX_IMR_NORMAL_MASK 0x1 ++#define IPQESS_TX_IMR_NORMAL_MASK 0x1 ++#define IPQESS_MISC_IMR_NORMAL_MASK 0x80001FFF ++#define IPQESS_WOL_IMR_NORMAL_MASK 0x1 ++ ++/* Edma receive consumer index */ ++#define IPQESS_REG_RX_SW_CONS_IDX_Q(x) (0x220 + ((x) << 2)) /* x is the queue id */ ++ ++/* Edma transmit consumer index */ ++#define IPQESS_REG_TX_SW_CONS_IDX_Q(x) (0x240 + ((x) << 2)) /* x is the queue id */ ++ ++/* IRQ Moderator Initial Timer Register */ ++#define IPQESS_REG_IRQ_MODRT_TIMER_INIT 0x280 ++#define IPQESS_IRQ_MODRT_TIMER_MASK 0xFFFF ++#define IPQESS_IRQ_MODRT_RX_TIMER_SHIFT 0 ++#define IPQESS_IRQ_MODRT_TX_TIMER_SHIFT 16 ++ ++/* Interrupt Control Register */ ++#define IPQESS_REG_INTR_CTRL 0x284 ++#define IPQESS_INTR_CLR_TYP_SHIFT 0 ++#define IPQESS_INTR_SW_IDX_W_TYP_SHIFT 1 ++#define IPQESS_INTR_CLEAR_TYPE_W1 0 ++#define IPQESS_INTR_CLEAR_TYPE_R 1 ++ ++/* RX Interrupt Mask Register */ ++#define IPQESS_REG_RX_INT_MASK_Q(x) (0x300 + ((x) << 2)) /* x = queue id */ ++ ++/* TX Interrupt mask register */ ++#define IPQESS_REG_TX_INT_MASK_Q(x) (0x340 + ((x) << 2)) /* x = queue id */ ++ ++/* Load Ptr Register ++ * Software sets this bit after the initialization of the head and tail ++ */ ++#define IPQESS_REG_TX_SRAM_PART 0x400 ++#define IPQESS_LOAD_PTR_SHIFT 16 ++ ++/* TXQ Control Register */ ++#define IPQESS_REG_TXQ_CTRL 0x404 ++#define IPQESS_TXQ_CTRL_IP_OPTION_EN 0x10 ++#define IPQESS_TXQ_CTRL_TXQ_EN 0x20 ++#define IPQESS_TXQ_CTRL_ENH_MODE 0x40 ++#define IPQESS_TXQ_CTRL_LS_8023_EN 0x80 ++#define IPQESS_TXQ_CTRL_TPD_BURST_EN 0x100 ++#define IPQESS_TXQ_CTRL_LSO_BREAK_EN 0x200 ++#define IPQESS_TXQ_NUM_TPD_BURST_MASK 0xF ++#define IPQESS_TXQ_TXF_BURST_NUM_MASK 0xFFFF ++#define IPQESS_TXQ_NUM_TPD_BURST_SHIFT 0 ++#define IPQESS_TXQ_TXF_BURST_NUM_SHIFT 16 ++ ++#define IPQESS_REG_TXF_WATER_MARK 0x408 /* In 8-bytes */ ++#define IPQESS_TXF_WATER_MARK_MASK 0x0FFF ++#define IPQESS_TXF_LOW_WATER_MARK_SHIFT 0 ++#define IPQESS_TXF_HIGH_WATER_MARK_SHIFT 16 ++#define IPQESS_TXQ_CTRL_BURST_MODE_EN 0x80000000 ++ ++/* WRR Control Register */ ++#define IPQESS_REG_WRR_CTRL_Q0_Q3 0x40c ++#define IPQESS_REG_WRR_CTRL_Q4_Q7 0x410 ++#define IPQESS_REG_WRR_CTRL_Q8_Q11 0x414 ++#define IPQESS_REG_WRR_CTRL_Q12_Q15 0x418 ++ ++/* Weight round robin(WRR), it takes queue as input, and computes ++ * starting bits where we need to write the weight for a particular ++ * queue ++ */ ++#define IPQESS_WRR_SHIFT(x) (((x) * 5) % 20) ++ ++/* Tx Descriptor Control Register */ ++#define IPQESS_REG_TPD_RING_SIZE 0x41C ++#define IPQESS_TPD_RING_SIZE_SHIFT 0 ++#define IPQESS_TPD_RING_SIZE_MASK 0xFFFF ++ ++/* Transmit descriptor base address */ ++#define IPQESS_REG_TPD_BASE_ADDR_Q(x) (0x420 + ((x) << 2)) /* x = queue id */ ++ ++/* TPD Index Register */ ++#define IPQESS_REG_TPD_IDX_Q(x) (0x460 + ((x) << 2)) /* x = queue id */ ++ ++#define IPQESS_TPD_PROD_IDX_BITS 0x0000FFFF ++#define IPQESS_TPD_CONS_IDX_BITS 0xFFFF0000 ++#define IPQESS_TPD_PROD_IDX_MASK 0xFFFF ++#define IPQESS_TPD_CONS_IDX_MASK 0xFFFF ++#define IPQESS_TPD_PROD_IDX_SHIFT 0 ++#define IPQESS_TPD_CONS_IDX_SHIFT 16 ++ ++/* TX Virtual Queue Mapping Control Register */ ++#define IPQESS_REG_VQ_CTRL0 0x4A0 ++#define IPQESS_REG_VQ_CTRL1 0x4A4 ++ ++/* Virtual QID shift, it takes queue as input, and computes ++ * Virtual QID position in virtual qid control register ++ */ ++#define IPQESS_VQ_ID_SHIFT(i) (((i) * 3) % 24) ++ ++/* Virtual Queue Default Value */ ++#define IPQESS_VQ_REG_VALUE 0x240240 ++ ++/* Tx side Port Interface Control Register */ ++#define IPQESS_REG_PORT_CTRL 0x4A8 ++#define IPQESS_PAD_EN_SHIFT 15 ++ ++/* Tx side VLAN Configuration Register */ ++#define IPQESS_REG_VLAN_CFG 0x4AC ++ ++#define IPQESS_VLAN_CFG_SVLAN_TPID_SHIFT 0 ++#define IPQESS_VLAN_CFG_SVLAN_TPID_MASK 0xffff ++#define IPQESS_VLAN_CFG_CVLAN_TPID_SHIFT 16 ++#define IPQESS_VLAN_CFG_CVLAN_TPID_MASK 0xffff ++ ++#define IPQESS_TX_CVLAN 16 ++#define IPQESS_TX_INS_CVLAN 17 ++#define IPQESS_TX_CVLAN_TAG_SHIFT 0 ++ ++#define IPQESS_TX_SVLAN 14 ++#define IPQESS_TX_INS_SVLAN 15 ++#define IPQESS_TX_SVLAN_TAG_SHIFT 16 ++ ++/* Tx Queue Packet Statistic Register */ ++#define IPQESS_REG_TX_STAT_PKT_Q(x) (0x700 + ((x) << 3)) /* x = queue id */ ++ ++#define IPQESS_TX_STAT_PKT_MASK 0xFFFFFF ++ ++/* Tx Queue Byte Statistic Register */ ++#define IPQESS_REG_TX_STAT_BYTE_Q(x) (0x704 + ((x) << 3)) /* x = queue id */ ++ ++/* Load Balance Based Ring Offset Register */ ++#define IPQESS_REG_LB_RING 0x800 ++#define IPQESS_LB_RING_ENTRY_MASK 0xff ++#define IPQESS_LB_RING_ID_MASK 0x7 ++#define IPQESS_LB_RING_PROFILE_ID_MASK 0x3 ++#define IPQESS_LB_RING_ENTRY_BIT_OFFSET 8 ++#define IPQESS_LB_RING_ID_OFFSET 0 ++#define IPQESS_LB_RING_PROFILE_ID_OFFSET 3 ++#define IPQESS_LB_REG_VALUE 0x6040200 ++ ++/* Load Balance Priority Mapping Register */ ++#define IPQESS_REG_LB_PRI_START 0x804 ++#define IPQESS_REG_LB_PRI_END 0x810 ++#define IPQESS_LB_PRI_REG_INC 4 ++#define IPQESS_LB_PRI_ENTRY_BIT_OFFSET 4 ++#define IPQESS_LB_PRI_ENTRY_MASK 0xf ++ ++/* RSS Priority Mapping Register */ ++#define IPQESS_REG_RSS_PRI 0x820 ++#define IPQESS_RSS_PRI_ENTRY_MASK 0xf ++#define IPQESS_RSS_RING_ID_MASK 0x7 ++#define IPQESS_RSS_PRI_ENTRY_BIT_OFFSET 4 ++ ++/* RSS Indirection Register */ ++#define IPQESS_REG_RSS_IDT(x) (0x840 + ((x) << 2)) /* x = No. of indirection table */ ++#define IPQESS_NUM_IDT 16 ++#define IPQESS_RSS_IDT_VALUE 0x64206420 ++ ++/* Default RSS Ring Register */ ++#define IPQESS_REG_DEF_RSS 0x890 ++#define IPQESS_DEF_RSS_MASK 0x7 ++ ++/* RSS Hash Function Type Register */ ++#define IPQESS_REG_RSS_TYPE 0x894 ++#define IPQESS_RSS_TYPE_NONE 0x01 ++#define IPQESS_RSS_TYPE_IPV4TCP 0x02 ++#define IPQESS_RSS_TYPE_IPV6_TCP 0x04 ++#define IPQESS_RSS_TYPE_IPV4_UDP 0x08 ++#define IPQESS_RSS_TYPE_IPV6UDP 0x10 ++#define IPQESS_RSS_TYPE_IPV4 0x20 ++#define IPQESS_RSS_TYPE_IPV6 0x40 ++#define IPQESS_RSS_HASH_MODE_MASK 0x7f ++ ++#define IPQESS_REG_RSS_HASH_VALUE 0x8C0 ++ ++#define IPQESS_REG_RSS_TYPE_RESULT 0x8C4 ++ ++#define IPQESS_HASH_TYPE_START 0 ++#define IPQESS_HASH_TYPE_END 5 ++#define IPQESS_HASH_TYPE_SHIFT 12 ++ ++#define IPQESS_RFS_FLOW_ENTRIES 1024 ++#define IPQESS_RFS_FLOW_ENTRIES_MASK (IPQESS_RFS_FLOW_ENTRIES - 1) ++#define IPQESS_RFS_EXPIRE_COUNT_PER_CALL 128 ++ ++/* RFD Base Address Register */ ++#define IPQESS_REG_RFD_BASE_ADDR_Q(x) (0x950 + ((x) << 2)) /* x = queue id */ ++ ++/* RFD Index Register */ ++#define IPQESS_REG_RFD_IDX_Q(x) (0x9B0 + ((x) << 2)) /* x = queue id */ ++ ++#define IPQESS_RFD_PROD_IDX_BITS 0x00000FFF ++#define IPQESS_RFD_CONS_IDX_BITS 0x0FFF0000 ++#define IPQESS_RFD_PROD_IDX_MASK 0xFFF ++#define IPQESS_RFD_CONS_IDX_MASK 0xFFF ++#define IPQESS_RFD_PROD_IDX_SHIFT 0 ++#define IPQESS_RFD_CONS_IDX_SHIFT 16 ++ ++/* Rx Descriptor Control Register */ ++#define IPQESS_REG_RX_DESC0 0xA10 ++#define IPQESS_RFD_RING_SIZE_MASK 0xFFF ++#define IPQESS_RX_BUF_SIZE_MASK 0xFFFF ++#define IPQESS_RFD_RING_SIZE_SHIFT 0 ++#define IPQESS_RX_BUF_SIZE_SHIFT 16 ++ ++#define IPQESS_REG_RX_DESC1 0xA14 ++#define IPQESS_RXQ_RFD_BURST_NUM_MASK 0x3F ++#define IPQESS_RXQ_RFD_PF_THRESH_MASK 0x1F ++#define IPQESS_RXQ_RFD_LOW_THRESH_MASK 0xFFF ++#define IPQESS_RXQ_RFD_BURST_NUM_SHIFT 0 ++#define IPQESS_RXQ_RFD_PF_THRESH_SHIFT 8 ++#define IPQESS_RXQ_RFD_LOW_THRESH_SHIFT 16 ++ ++/* RXQ Control Register */ ++#define IPQESS_REG_RXQ_CTRL 0xA18 ++#define IPQESS_FIFO_THRESH_TYPE_SHIF 0 ++#define IPQESS_FIFO_THRESH_128_BYTE 0x0 ++#define IPQESS_FIFO_THRESH_64_BYTE 0x1 ++#define IPQESS_RXQ_CTRL_RMV_VLAN 0x00000002 ++#define IPQESS_RXQ_CTRL_EN_MASK GENMASK(15, 8) ++#define IPQESS_RXQ_CTRL_EN(__qid) BIT(8 + (__qid)) ++ ++/* AXI Burst Size Config */ ++#define IPQESS_REG_AXIW_CTRL_MAXWRSIZE 0xA1C ++#define IPQESS_AXIW_MAXWRSIZE_VALUE 0x0 ++ ++/* Rx Statistics Register */ ++#define IPQESS_REG_RX_STAT_BYTE_Q(x) (0xA30 + ((x) << 2)) /* x = queue id */ ++#define IPQESS_REG_RX_STAT_PKT_Q(x) (0xA50 + ((x) << 2)) /* x = queue id */ ++ ++/* WoL Pattern Length Register */ ++#define IPQESS_REG_WOL_PATTERN_LEN0 0xC00 ++#define IPQESS_WOL_PT_LEN_MASK 0xFF ++#define IPQESS_WOL_PT0_LEN_SHIFT 0 ++#define IPQESS_WOL_PT1_LEN_SHIFT 8 ++#define IPQESS_WOL_PT2_LEN_SHIFT 16 ++#define IPQESS_WOL_PT3_LEN_SHIFT 24 ++ ++#define IPQESS_REG_WOL_PATTERN_LEN1 0xC04 ++#define IPQESS_WOL_PT4_LEN_SHIFT 0 ++#define IPQESS_WOL_PT5_LEN_SHIFT 8 ++#define IPQESS_WOL_PT6_LEN_SHIFT 16 ++ ++/* WoL Control Register */ ++#define IPQESS_REG_WOL_CTRL 0xC08 ++#define IPQESS_WOL_WK_EN 0x00000001 ++#define IPQESS_WOL_MG_EN 0x00000002 ++#define IPQESS_WOL_PT0_EN 0x00000004 ++#define IPQESS_WOL_PT1_EN 0x00000008 ++#define IPQESS_WOL_PT2_EN 0x00000010 ++#define IPQESS_WOL_PT3_EN 0x00000020 ++#define IPQESS_WOL_PT4_EN 0x00000040 ++#define IPQESS_WOL_PT5_EN 0x00000080 ++#define IPQESS_WOL_PT6_EN 0x00000100 ++ ++/* MAC Control Register */ ++#define IPQESS_REG_MAC_CTRL0 0xC20 ++#define IPQESS_REG_MAC_CTRL1 0xC24 ++ ++/* WoL Pattern Register */ ++#define IPQESS_REG_WOL_PATTERN_START 0x5000 ++#define IPQESS_PATTERN_PART_REG_OFFSET 0x40 ++ ++/* TX descriptor fields */ ++#define IPQESS_TPD_HDR_SHIFT 0 ++#define IPQESS_TPD_PPPOE_EN 0x00000100 ++#define IPQESS_TPD_IP_CSUM_EN 0x00000200 ++#define IPQESS_TPD_TCP_CSUM_EN 0x0000400 ++#define IPQESS_TPD_UDP_CSUM_EN 0x00000800 ++#define IPQESS_TPD_CUSTOM_CSUM_EN 0x00000C00 ++#define IPQESS_TPD_LSO_EN 0x00001000 ++#define IPQESS_TPD_LSO_V2_EN 0x00002000 ++/* The VLAN_TAGGED bit is not used in the publicly available ++ * drivers. The definition has been stolen from the Atheros ++ * 'alx' driver (drivers/net/ethernet/atheros/alx/hw.h). It ++ * seems that it has the same meaning in regard to the EDMA ++ * hardware. ++ */ ++#define IPQESS_TPD_VLAN_TAGGED 0x00004000 ++#define IPQESS_TPD_IPV4_EN 0x00010000 ++#define IPQESS_TPD_MSS_MASK 0x1FFF ++#define IPQESS_TPD_MSS_SHIFT 18 ++#define IPQESS_TPD_CUSTOM_CSUM_SHIFT 18 ++ ++/* RRD descriptor fields */ ++#define IPQESS_RRD_NUM_RFD_MASK 0x000F ++#define IPQESS_RRD_PKT_SIZE_MASK 0x3FFF ++#define IPQESS_RRD_SRC_PORT_NUM_MASK 0x4000 ++#define IPQESS_RRD_SVLAN 0x8000 ++#define IPQESS_RRD_FLOW_COOKIE_MASK 0x07FF ++ ++#define IPQESS_RRD_PKT_SIZE_MASK 0x3FFF ++#define IPQESS_RRD_CSUM_FAIL_MASK 0xC000 ++#define IPQESS_RRD_CVLAN 0x0001 ++#define IPQESS_RRD_DESC_VALID 0x8000 ++ ++#define IPQESS_RRD_PRIORITY_SHIFT 4 ++#define IPQESS_RRD_PRIORITY_MASK 0x7 ++#define IPQESS_RRD_PORT_TYPE_SHIFT 7 ++#define IPQESS_RRD_PORT_TYPE_MASK 0x1F ++ ++#define IPQESS_RRD_PORT_ID_MASK 0x7000 ++ ++#endif +--- /dev/null ++++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess_ethtool.c +@@ -0,0 +1,164 @@ ++// SPDX-License-Identifier: GPL-2.0 OR ISC ++/* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2017 - 2018, John Crispin ++ * Copyright (c) 2021 - 2022, Maxime Chevallier ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "ipqess.h" ++ ++struct ipqess_ethtool_stats { ++ u8 string[ETH_GSTRING_LEN]; ++ u32 offset; ++}; ++ ++#define IPQESS_STAT(m) offsetof(struct ipqess_statistics, m) ++#define DRVINFO_LEN 32 ++ ++static const struct ipqess_ethtool_stats ipqess_stats[] = { ++ {"tx_q0_pkt", IPQESS_STAT(tx_q0_pkt)}, ++ {"tx_q1_pkt", IPQESS_STAT(tx_q1_pkt)}, ++ {"tx_q2_pkt", IPQESS_STAT(tx_q2_pkt)}, ++ {"tx_q3_pkt", IPQESS_STAT(tx_q3_pkt)}, ++ {"tx_q4_pkt", IPQESS_STAT(tx_q4_pkt)}, ++ {"tx_q5_pkt", IPQESS_STAT(tx_q5_pkt)}, ++ {"tx_q6_pkt", IPQESS_STAT(tx_q6_pkt)}, ++ {"tx_q7_pkt", IPQESS_STAT(tx_q7_pkt)}, ++ {"tx_q8_pkt", IPQESS_STAT(tx_q8_pkt)}, ++ {"tx_q9_pkt", IPQESS_STAT(tx_q9_pkt)}, ++ {"tx_q10_pkt", IPQESS_STAT(tx_q10_pkt)}, ++ {"tx_q11_pkt", IPQESS_STAT(tx_q11_pkt)}, ++ {"tx_q12_pkt", IPQESS_STAT(tx_q12_pkt)}, ++ {"tx_q13_pkt", IPQESS_STAT(tx_q13_pkt)}, ++ {"tx_q14_pkt", IPQESS_STAT(tx_q14_pkt)}, ++ {"tx_q15_pkt", IPQESS_STAT(tx_q15_pkt)}, ++ {"tx_q0_byte", IPQESS_STAT(tx_q0_byte)}, ++ {"tx_q1_byte", IPQESS_STAT(tx_q1_byte)}, ++ {"tx_q2_byte", IPQESS_STAT(tx_q2_byte)}, ++ {"tx_q3_byte", IPQESS_STAT(tx_q3_byte)}, ++ {"tx_q4_byte", IPQESS_STAT(tx_q4_byte)}, ++ {"tx_q5_byte", IPQESS_STAT(tx_q5_byte)}, ++ {"tx_q6_byte", IPQESS_STAT(tx_q6_byte)}, ++ {"tx_q7_byte", IPQESS_STAT(tx_q7_byte)}, ++ {"tx_q8_byte", IPQESS_STAT(tx_q8_byte)}, ++ {"tx_q9_byte", IPQESS_STAT(tx_q9_byte)}, ++ {"tx_q10_byte", IPQESS_STAT(tx_q10_byte)}, ++ {"tx_q11_byte", IPQESS_STAT(tx_q11_byte)}, ++ {"tx_q12_byte", IPQESS_STAT(tx_q12_byte)}, ++ {"tx_q13_byte", IPQESS_STAT(tx_q13_byte)}, ++ {"tx_q14_byte", IPQESS_STAT(tx_q14_byte)}, ++ {"tx_q15_byte", IPQESS_STAT(tx_q15_byte)}, ++ {"rx_q0_pkt", IPQESS_STAT(rx_q0_pkt)}, ++ {"rx_q1_pkt", IPQESS_STAT(rx_q1_pkt)}, ++ {"rx_q2_pkt", IPQESS_STAT(rx_q2_pkt)}, ++ {"rx_q3_pkt", IPQESS_STAT(rx_q3_pkt)}, ++ {"rx_q4_pkt", IPQESS_STAT(rx_q4_pkt)}, ++ {"rx_q5_pkt", IPQESS_STAT(rx_q5_pkt)}, ++ {"rx_q6_pkt", IPQESS_STAT(rx_q6_pkt)}, ++ {"rx_q7_pkt", IPQESS_STAT(rx_q7_pkt)}, ++ {"rx_q0_byte", IPQESS_STAT(rx_q0_byte)}, ++ {"rx_q1_byte", IPQESS_STAT(rx_q1_byte)}, ++ {"rx_q2_byte", IPQESS_STAT(rx_q2_byte)}, ++ {"rx_q3_byte", IPQESS_STAT(rx_q3_byte)}, ++ {"rx_q4_byte", IPQESS_STAT(rx_q4_byte)}, ++ {"rx_q5_byte", IPQESS_STAT(rx_q5_byte)}, ++ {"rx_q6_byte", IPQESS_STAT(rx_q6_byte)}, ++ {"rx_q7_byte", IPQESS_STAT(rx_q7_byte)}, ++ {"tx_desc_error", IPQESS_STAT(tx_desc_error)}, ++}; ++ ++static int ipqess_get_strset_count(struct net_device *netdev, int sset) ++{ ++ switch (sset) { ++ case ETH_SS_STATS: ++ return ARRAY_SIZE(ipqess_stats); ++ default: ++ netdev_dbg(netdev, "%s: Unsupported string set", __func__); ++ return -EOPNOTSUPP; ++ } ++} ++ ++static void ipqess_get_strings(struct net_device *netdev, u32 stringset, ++ u8 *data) ++{ ++ u8 *p = data; ++ u32 i; ++ ++ switch (stringset) { ++ case ETH_SS_STATS: ++ for (i = 0; i < ARRAY_SIZE(ipqess_stats); i++) ++ ethtool_sprintf(&p, ipqess_stats[i].string); ++ break; ++ } ++} ++ ++static void ipqess_get_ethtool_stats(struct net_device *netdev, ++ struct ethtool_stats *stats, ++ uint64_t *data) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ u32 *essstats = (u32 *)&ess->ipqess_stats; ++ int i; ++ ++ spin_lock(&ess->stats_lock); ++ ++ ipqess_update_hw_stats(ess); ++ ++ for (i = 0; i < ARRAY_SIZE(ipqess_stats); i++) ++ data[i] = *(u32 *)(essstats + (ipqess_stats[i].offset / sizeof(u32))); ++ ++ spin_unlock(&ess->stats_lock); ++} ++ ++static void ipqess_get_drvinfo(struct net_device *dev, ++ struct ethtool_drvinfo *info) ++{ ++ strscpy(info->driver, "qca_ipqess", DRVINFO_LEN); ++ strscpy(info->bus_info, "axi", ETHTOOL_BUSINFO_LEN); ++} ++ ++static int ipqess_get_link_ksettings(struct net_device *netdev, ++ struct ethtool_link_ksettings *cmd) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ return phylink_ethtool_ksettings_get(ess->phylink, cmd); ++} ++ ++static int ipqess_set_link_ksettings(struct net_device *netdev, ++ const struct ethtool_link_ksettings *cmd) ++{ ++ struct ipqess *ess = netdev_priv(netdev); ++ ++ return phylink_ethtool_ksettings_set(ess->phylink, cmd); ++} ++ ++static void ipqess_get_ringparam(struct net_device *netdev, ++ struct ethtool_ringparam *ring, ++ struct kernel_ethtool_ringparam *kernel_ering, ++ struct netlink_ext_ack *extack) ++{ ++ ring->tx_max_pending = IPQESS_TX_RING_SIZE; ++ ring->rx_max_pending = IPQESS_RX_RING_SIZE; ++} ++ ++static const struct ethtool_ops ipqesstool_ops = { ++ .get_drvinfo = &ipqess_get_drvinfo, ++ .get_link = ðtool_op_get_link, ++ .get_link_ksettings = &ipqess_get_link_ksettings, ++ .set_link_ksettings = &ipqess_set_link_ksettings, ++ .get_strings = &ipqess_get_strings, ++ .get_sset_count = &ipqess_get_strset_count, ++ .get_ethtool_stats = &ipqess_get_ethtool_stats, ++ .get_ringparam = ipqess_get_ringparam, ++}; ++ ++void ipqess_set_ethtool_ops(struct net_device *netdev) ++{ ++ netdev->ethtool_ops = &ipqesstool_ops; ++} diff --git a/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch b/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch new file mode 100644 index 0000000000..b3d4ed9085 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/701-net-dsa-add-out-of-band-tagging-protocol.patch @@ -0,0 +1,238 @@ +From a32e16b3c2fc1954ad6e09737439f60e5890278e Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Fri, 4 Nov 2022 18:41:49 +0100 +Subject: [PATCH] net: dsa: add out-of-band tagging protocol + +This tagging protocol is designed for the situation where the link +between the MAC and the Switch is designed such that the Destination +Port, which is usually embedded in some part of the Ethernet Header, is +sent out-of-band, and isn't present at all in the Ethernet frame. + +This can happen when the MAC and Switch are tightly integrated on an +SoC, as is the case with the Qualcomm IPQ4019 for example, where the DSA +tag is inserted directly into the DMA descriptors. In that case, +the MAC driver is responsible for sending the tag to the switch using +the out-of-band medium. To do so, the MAC driver needs to have the +information of the destination port for that skb. + +Add a new tagging protocol based on SKB extensions to convey the +information about the destination port to the MAC driver + +Signed-off-by: Maxime Chevallier +--- + Documentation/networking/dsa/dsa.rst | 13 +++++++- + MAINTAINERS | 1 + + include/linux/dsa/oob.h | 16 +++++++++ + include/linux/skbuff.h | 3 ++ + include/net/dsa.h | 2 ++ + net/core/skbuff.c | 10 ++++++ + net/dsa/Kconfig | 9 +++++ + net/dsa/Makefile | 1 + + net/dsa/tag_oob.c | 49 ++++++++++++++++++++++++++++ + 9 files changed, 103 insertions(+), 1 deletion(-) + create mode 100644 include/linux/dsa/oob.h + create mode 100644 net/dsa/tag_oob.c + +--- a/Documentation/networking/dsa/dsa.rst ++++ b/Documentation/networking/dsa/dsa.rst +@@ -66,7 +66,8 @@ Switch tagging protocols + ------------------------ + + DSA supports many vendor-specific tagging protocols, one software-defined +-tagging protocol, and a tag-less mode as well (``DSA_TAG_PROTO_NONE``). ++tagging protocol, a tag-less mode as well (``DSA_TAG_PROTO_NONE``) and an ++out-of-band tagging protocol (``DSA_TAG_PROTO_OOB``). + + The exact format of the tag protocol is vendor specific, but in general, they + all contain something which: +@@ -217,6 +218,16 @@ receive all frames regardless of the val + setting the ``promisc_on_master`` property of the ``struct dsa_device_ops``. + Note that this assumes a DSA-unaware master driver, which is the norm. + ++Some SoCs have a tight integration between the conduit network interface and the ++embedded switch, such that the DSA tag isn't transmitted in the packet data, ++but through another media, using so-called out-of-band tagging. In that case, ++the host MAC driver is in charge of transmitting the tag to the switch. ++An example is the IPQ4019 SoC, that transmits the tag between the ipqess ++ethernet controller and the qca8k switch using the DMA descriptor. In that ++configuration, tag-chaining is permitted, but the OOB tag will always be the ++top-most switch in the tree. The tagger (``DSA_TAG_PROTO_OOB``) uses skb ++extensions to transmit the tag to and from the MAC driver. ++ + Master network devices + ---------------------- + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -17070,6 +17070,7 @@ L: netdev@vger.kernel.org + S: Maintained + F: Documentation/devicetree/bindings/net/qcom,ipq4019-ess-edma.yaml + F: drivers/net/ethernet/qualcomm/ipqess/ ++F: net/dsa/tag_oob.c + + QUALCOMM ETHQOS ETHERNET DRIVER + M: Vinod Koul +--- /dev/null ++++ b/include/linux/dsa/oob.h +@@ -0,0 +1,16 @@ ++/* SPDX-License-Identifier: GPL-2.0-only ++ * Copyright (C) 2022 Maxime Chevallier ++ */ ++ ++#ifndef _NET_DSA_OOB_H ++#define _NET_DSA_OOB_H ++ ++#include ++ ++struct dsa_oob_tag_info { ++ u16 port; ++}; ++ ++int dsa_oob_tag_push(struct sk_buff *skb, struct dsa_oob_tag_info *ti); ++int dsa_oob_tag_pop(struct sk_buff *skb, struct dsa_oob_tag_info *ti); ++#endif +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -4580,6 +4580,9 @@ enum skb_ext_id { + #if IS_ENABLED(CONFIG_MCTP_FLOWS) + SKB_EXT_MCTP, + #endif ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_OOB) ++ SKB_EXT_DSA_OOB, ++#endif + SKB_EXT_NUM, /* must be last */ + }; + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -55,6 +55,7 @@ struct phylink_link_state; + #define DSA_TAG_PROTO_RTL8_4T_VALUE 25 + #define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26 + #define DSA_TAG_PROTO_LAN937X_VALUE 27 ++#define DSA_TAG_PROTO_OOB_VALUE 28 + + enum dsa_tag_protocol { + DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, +@@ -85,6 +86,7 @@ enum dsa_tag_protocol { + DSA_TAG_PROTO_RTL8_4T = DSA_TAG_PROTO_RTL8_4T_VALUE, + DSA_TAG_PROTO_RZN1_A5PSW = DSA_TAG_PROTO_RZN1_A5PSW_VALUE, + DSA_TAG_PROTO_LAN937X = DSA_TAG_PROTO_LAN937X_VALUE, ++ DSA_TAG_PROTO_OOB = DSA_TAG_PROTO_OOB_VALUE, + }; + + struct dsa_switch; +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -62,8 +62,12 @@ + #include + #include + #include ++#ifdef CONFIG_NET_DSA_TAG_OOB ++#include ++#endif + + #include ++#include + #include + #include + #include +@@ -4510,6 +4514,9 @@ static const u8 skb_ext_type_len[] = { + #if IS_ENABLED(CONFIG_MCTP_FLOWS) + [SKB_EXT_MCTP] = SKB_EXT_CHUNKSIZEOF(struct mctp_flow), + #endif ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_OOB) ++ [SKB_EXT_DSA_OOB] = SKB_EXT_CHUNKSIZEOF(struct dsa_oob_tag_info), ++#endif + }; + + static __always_inline unsigned int skb_ext_total_length(void) +@@ -4530,6 +4537,9 @@ static __always_inline unsigned int skb_ + #if IS_ENABLED(CONFIG_MCTP_FLOWS) + skb_ext_type_len[SKB_EXT_MCTP] + + #endif ++#if IS_ENABLED(CONFIG_NET_DSA_TAG_OOB) ++ skb_ext_type_len[SKB_EXT_DSA_OOB] + ++#endif + 0; + } + +--- a/net/dsa/Kconfig ++++ b/net/dsa/Kconfig +@@ -113,6 +113,15 @@ config NET_DSA_TAG_OCELOT_8021Q + this mode, less TCAM resources (VCAP IS1, IS2, ES0) are available for + use with tc-flower. + ++config NET_DSA_TAG_OOB ++ select SKB_EXTENSIONS ++ tristate "Tag driver for Out-of-band tagging drivers" ++ help ++ Say Y or M if you want to enable support for pairs of embedded ++ switches and host MAC drivers which perform demultiplexing and ++ packet steering to ports using out of band metadata processed ++ by the DSA master, rather than tags present in the packets. ++ + config NET_DSA_TAG_QCA + tristate "Tag driver for Qualcomm Atheros QCA8K switches" + help +--- a/net/dsa/Makefile ++++ b/net/dsa/Makefile +@@ -22,6 +22,7 @@ obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag + obj-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o + obj-$(CONFIG_NET_DSA_TAG_OCELOT) += tag_ocelot.o + obj-$(CONFIG_NET_DSA_TAG_OCELOT_8021Q) += tag_ocelot_8021q.o ++obj-$(CONFIG_NET_DSA_TAG_OOB) += tag_oob.o + obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o + obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o + obj-$(CONFIG_NET_DSA_TAG_RTL8_4) += tag_rtl8_4.o +--- /dev/null ++++ b/net/dsa/tag_oob.c +@@ -0,0 +1,49 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++ ++/* Copyright (c) 2022, Maxime Chevallier */ ++ ++#include ++#include ++#include ++ ++#include "dsa_priv.h" ++ ++static struct sk_buff *oob_tag_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct dsa_oob_tag_info *tag_info = skb_ext_add(skb, SKB_EXT_DSA_OOB); ++ struct dsa_port *dp = dsa_slave_to_port(dev); ++ ++ tag_info->port = dp->index; ++ ++ return skb; ++} ++ ++static struct sk_buff *oob_tag_rcv(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct dsa_oob_tag_info *tag_info = skb_ext_find(skb, SKB_EXT_DSA_OOB); ++ ++ if (!tag_info) ++ return NULL; ++ ++ skb->dev = dsa_master_find_slave(dev, 0, tag_info->port); ++ if (!skb->dev) ++ return NULL; ++ ++ return skb; ++} ++ ++static const struct dsa_device_ops oob_tag_dsa_ops = { ++ .name = "oob", ++ .proto = DSA_TAG_PROTO_OOB, ++ .xmit = oob_tag_xmit, ++ .rcv = oob_tag_rcv, ++}; ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("DSA tag driver for out-of-band tagging"); ++MODULE_AUTHOR("Maxime Chevallier "); ++MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_OOB); ++ ++module_dsa_tag_driver(oob_tag_dsa_ops); diff --git a/target/linux/ipq40xx/patches-6.1/702-net-ipqess-Add-out-of-band-DSA-tagging-support.patch b/target/linux/ipq40xx/patches-6.1/702-net-ipqess-Add-out-of-band-DSA-tagging-support.patch new file mode 100644 index 0000000000..ac0718ba2c --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/702-net-ipqess-Add-out-of-band-DSA-tagging-support.patch @@ -0,0 +1,173 @@ +From 4975e2b3f1d37bba04f262784cef0d5b7e0a30a4 Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Fri, 4 Nov 2022 18:41:50 +0100 +Subject: [PATCH] net: ipqess: Add out-of-band DSA tagging support + +On the IPQ4019, there's an 5 ports switch connected to the CPU through +the IPQESS Ethernet controller. The way the DSA tag is sent-out to that +switch is through the DMA descriptor, due to how tightly it is +integrated with the switch. + +We use the out-of-band tagging protocol by getting the source +port from the descriptor, push it into the skb extensions, and have the +tagger pull it to infer the destination netdev. The reverse process is +done on the TX side, where the driver pulls the tag from the skb and +builds the descriptor accordingly. + +Signed-off-by: Maxime Chevallier +--- + drivers/net/ethernet/qualcomm/Kconfig | 1 + + drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 64 ++++++++++++++++++- + drivers/net/ethernet/qualcomm/ipqess/ipqess.h | 4 ++ + 3 files changed, 68 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/qualcomm/Kconfig ++++ b/drivers/net/ethernet/qualcomm/Kconfig +@@ -64,6 +64,7 @@ config QCOM_IPQ4019_ESS_EDMA + tristate "Qualcomm Atheros IPQ4019 ESS EDMA support" + depends on (OF && ARCH_QCOM) || COMPILE_TEST + select PHYLINK ++ select NET_DSA_TAG_OOB + help + This driver supports the Qualcomm Atheros IPQ40xx built-in + ESS EDMA ethernet controller. +--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c ++++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c +@@ -9,6 +9,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -22,6 +23,7 @@ + #include + #include + #include ++#include + #include + + #include "ipqess.h" +@@ -327,6 +329,7 @@ static int ipqess_rx_poll(struct ipqess_ + tail &= IPQESS_RFD_CONS_IDX_MASK; + + while (done < budget) { ++ struct dsa_oob_tag_info *tag_info; + struct ipqess_rx_desc *rd; + struct sk_buff *skb; + +@@ -406,6 +409,12 @@ static int ipqess_rx_poll(struct ipqess_ + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD), + le16_to_cpu(rd->rrd4)); + ++ if (likely(rx_ring->ess->dsa_ports)) { ++ tag_info = skb_ext_add(skb, SKB_EXT_DSA_OOB); ++ tag_info->port = FIELD_GET(IPQESS_RRD_PORT_ID_MASK, ++ le16_to_cpu(rd->rrd1)); ++ } ++ + napi_gro_receive(&rx_ring->napi_rx, skb); + + rx_ring->ess->stats.rx_packets++; +@@ -706,6 +715,23 @@ static void ipqess_rollback_tx(struct ip + tx_ring->head = start_index; + } + ++static void ipqess_process_dsa_tag_sh(struct ipqess *ess, struct sk_buff *skb, ++ u32 *word3) ++{ ++ struct dsa_oob_tag_info *tag_info; ++ ++ if (unlikely(!ess->dsa_ports)) ++ return; ++ ++ tag_info = skb_ext_find(skb, SKB_EXT_DSA_OOB); ++ if (!tag_info) ++ return; ++ ++ *word3 |= tag_info->port << IPQESS_TPD_PORT_BITMAP_SHIFT; ++ *word3 |= BIT(IPQESS_TPD_FROM_CPU_SHIFT); ++ *word3 |= 0x3e << IPQESS_TPD_PORT_BITMAP_SHIFT; ++} ++ + static int ipqess_tx_map_and_fill(struct ipqess_tx_ring *tx_ring, + struct sk_buff *skb) + { +@@ -716,6 +742,8 @@ static int ipqess_tx_map_and_fill(struct + u16 len; + int i; + ++ ipqess_process_dsa_tag_sh(tx_ring->ess, skb, &word3); ++ + if (skb_is_gso(skb)) { + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) { + lso_word1 |= IPQESS_TPD_IPV4_EN; +@@ -917,6 +945,33 @@ static const struct net_device_ops ipqes + .ndo_tx_timeout = ipqess_tx_timeout, + }; + ++static int ipqess_netdevice_event(struct notifier_block *nb, ++ unsigned long event, void *ptr) ++{ ++ struct ipqess *ess = container_of(nb, struct ipqess, netdev_notifier); ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ struct netdev_notifier_changeupper_info *info; ++ ++ if (dev != ess->netdev) ++ return NOTIFY_DONE; ++ ++ switch (event) { ++ case NETDEV_CHANGEUPPER: ++ info = ptr; ++ ++ if (!dsa_slave_dev_check(info->upper_dev)) ++ return NOTIFY_DONE; ++ ++ if (info->linking) ++ ess->dsa_ports++; ++ else ++ ess->dsa_ports--; ++ ++ return NOTIFY_DONE; ++ } ++ return NOTIFY_OK; ++} ++ + static void ipqess_hw_stop(struct ipqess *ess) + { + int i; +@@ -1184,12 +1239,19 @@ static int ipqess_axi_probe(struct platf + netif_napi_add(netdev, &ess->rx_ring[i].napi_rx, ipqess_rx_napi); + } + +- err = register_netdev(netdev); ++ ess->netdev_notifier.notifier_call = ipqess_netdevice_event; ++ err = register_netdevice_notifier(&ess->netdev_notifier); + if (err) + goto err_hw_stop; + ++ err = register_netdev(netdev); ++ if (err) ++ goto err_notifier_unregister; ++ + return 0; + ++err_notifier_unregister: ++ unregister_netdevice_notifier(&ess->netdev_notifier); + err_hw_stop: + ipqess_hw_stop(ess); + +--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.h ++++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.h +@@ -171,6 +171,10 @@ struct ipqess { + struct platform_device *pdev; + struct phylink *phylink; + struct phylink_config phylink_config; ++ ++ struct notifier_block netdev_notifier; ++ int dsa_ports; ++ + struct ipqess_tx_ring tx_ring[IPQESS_NETDEV_QUEUES]; + + struct ipqess_statistics ipqess_stats; diff --git a/target/linux/ipq40xx/patches-6.1/703-net-qualcomm-ipqess-release-IRQ-s-on-network-device-.patch b/target/linux/ipq40xx/patches-6.1/703-net-qualcomm-ipqess-release-IRQ-s-on-network-device-.patch new file mode 100644 index 0000000000..bd890e5c71 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/703-net-qualcomm-ipqess-release-IRQ-s-on-network-device-.patch @@ -0,0 +1,75 @@ +From 5f15f7f170c76220dfd36cb9037d7848d1fc4aaf Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 15 Aug 2023 14:30:50 +0200 +Subject: [PATCH] net: qualcomm: ipqess: release IRQ-s on network device stop + +Currently, IPQESS driver is obtaining the IRQ-s during ndo_open, but they +are never freed as they are device managed. + +However, it is not enough for them to be released when device is removed +as the same network device can be stopped and started multiple times which +on the second start would lead to IRQ request to fail with -EBUSY as they +have already been requested before and are not of the shared type with: +[ 34.480769] ipqess-edma c080000.ethernet eth0: Link is Down +[ 34.488070] ipqess-edma c080000.ethernet eth0: ipqess_open +[ 34.488131] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0) +[ 34.494527] ipqess-edma c080000.ethernet eth0: ipqess_open +[ 34.502892] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0) +[ 34.508137] qca8k-ipq4019 c000000.switch lan1: failed to open master eth0 +[ 34.518966] br-lan: port 1(lan1) entered blocking state +[ 34.525165] br-lan: port 1(lan1) entered disabled state +[ 34.530633] device lan1 entered promiscuous mode +[ 34.548598] ipqess-edma c080000.ethernet eth0: ipqess_open +[ 34.548660] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0) +[ 34.553111] qca8k-ipq4019 c000000.switch lan2: failed to open master eth0 +[ 34.563841] br-lan: port 2(lan2) entered blocking state +[ 34.570083] br-lan: port 2(lan2) entered disabled state +[ 34.575530] device lan2 entered promiscuous mode +[ 34.587067] ipqess-edma c080000.ethernet eth0: ipqess_open +[ 34.587132] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0) +[ 34.591579] qca8k-ipq4019 c000000.switch lan3: failed to open master eth0 +[ 34.602451] br-lan: port 3(lan3) entered blocking state +[ 34.608496] br-lan: port 3(lan3) entered disabled state +[ 34.614084] device lan3 entered promiscuous mode +[ 34.626405] ipqess-edma c080000.ethernet eth0: ipqess_open +[ 34.626468] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0) +[ 34.630871] qca8k-ipq4019 c000000.switch lan4: failed to open master eth0 +[ 34.641689] br-lan: port 4(lan4) entered blocking state +[ 34.647834] br-lan: port 4(lan4) entered disabled state +[ 34.653455] device lan4 entered promiscuous mode +[ 34.667282] ipqess-edma c080000.ethernet eth0: ipqess_open +[ 34.667364] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0) +[ 34.671830] qca8k-ipq4019 c000000.switch wan: failed to open master eth0 + +So, lets free the IRQ-s on ndo_stop after stopping NAPI and HW IRQ-s. + +Signed-off-by: Robert Marko +--- + drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c ++++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c +@@ -636,9 +636,22 @@ static int ipqess_stop(struct net_device + netif_tx_stop_all_queues(netdev); + phylink_stop(ess->phylink); + ipqess_irq_disable(ess); ++ + for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) { ++ int qid; ++ + napi_disable(&ess->tx_ring[i].napi_tx); + napi_disable(&ess->rx_ring[i].napi_rx); ++ ++ qid = ess->tx_ring[i].idx; ++ devm_free_irq(&netdev->dev, ++ ess->tx_irq[qid], ++ &ess->tx_ring[i]); ++ ++ qid = ess->rx_ring[i].idx; ++ devm_free_irq(&netdev->dev, ++ ess->rx_irq[qid], ++ &ess->rx_ring[i]); + } + + return 0; diff --git a/target/linux/ipq40xx/patches-6.1/704-net-qualcomm-ipqess-enable-threaded-NAPI-by-default.patch b/target/linux/ipq40xx/patches-6.1/704-net-qualcomm-ipqess-enable-threaded-NAPI-by-default.patch new file mode 100644 index 0000000000..cd58677284 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/704-net-qualcomm-ipqess-enable-threaded-NAPI-by-default.patch @@ -0,0 +1,49 @@ +From 9fa4a57a65e270e4d579cace4de5c438f46c7d12 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 15 Aug 2023 14:38:44 +0200 +Subject: [PATCH] net: qualcomm: ipqess: enable threaded NAPI by default + +Threaded NAPI provides a nice performance boost, so lets enable it by +default. + +We do however need to move the __napi_schedule() after HW IRQ has been +cleared in order to avoid concurency issues. + +Signed-off-by: Robert Marko +--- + drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c ++++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c +@@ -530,9 +530,9 @@ static irqreturn_t ipqess_interrupt_tx(i + struct ipqess_tx_ring *tx_ring = (struct ipqess_tx_ring *)priv; + + if (likely(napi_schedule_prep(&tx_ring->napi_tx))) { +- __napi_schedule(&tx_ring->napi_tx); + ipqess_w32(tx_ring->ess, IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx), + 0x0); ++ __napi_schedule(&tx_ring->napi_tx); + } + + return IRQ_HANDLED; +@@ -543,9 +543,9 @@ static irqreturn_t ipqess_interrupt_rx(i + struct ipqess_rx_ring *rx_ring = (struct ipqess_rx_ring *)priv; + + if (likely(napi_schedule_prep(&rx_ring->napi_rx))) { +- __napi_schedule(&rx_ring->napi_rx); + ipqess_w32(rx_ring->ess, IPQESS_REG_RX_INT_MASK_Q(rx_ring->idx), + 0x0); ++ __napi_schedule(&rx_ring->napi_rx); + } + + return IRQ_HANDLED; +@@ -1261,6 +1261,8 @@ static int ipqess_axi_probe(struct platf + if (err) + goto err_notifier_unregister; + ++ dev_set_threaded(netdev, true); ++ + return 0; + + err_notifier_unregister: diff --git a/target/linux/ipq40xx/patches-6.1/703-arm-dts-ipq4019-add-ethernet-controller-DT-node.patch b/target/linux/ipq40xx/patches-6.1/705-ARM-dts-qcom-ipq4019-Add-description-for-the-IPQESS-.patch similarity index 71% rename from target/linux/ipq40xx/patches-6.1/703-arm-dts-ipq4019-add-ethernet-controller-DT-node.patch rename to target/linux/ipq40xx/patches-6.1/705-ARM-dts-qcom-ipq4019-Add-description-for-the-IPQESS-.patch index 68fb4eb4ce..70596f3c22 100644 --- a/target/linux/ipq40xx/patches-6.1/703-arm-dts-ipq4019-add-ethernet-controller-DT-node.patch +++ b/target/linux/ipq40xx/patches-6.1/705-ARM-dts-qcom-ipq4019-Add-description-for-the-IPQESS-.patch @@ -1,27 +1,27 @@ -From 44327d7098d4f32c24ec8c528e5aff6e030956bc Mon Sep 17 00:00:00 2001 -From: Robert Marko -Date: Wed, 20 Oct 2021 13:21:45 +0200 -Subject: [PATCH] arm: dts: ipq4019: add ethernet controller DT node +From 5b71dbb867680887d47954ce1cc145cb747cbce6 Mon Sep 17 00:00:00 2001 +From: Maxime Chevallier +Date: Fri, 4 Nov 2022 18:41:51 +0100 +Subject: [PATCH] ARM: dts: qcom: ipq4019: Add description for the IPQESS + Ethernet controller -Since IPQ40xx SoC built-in ethernet controller now has a driver, -add its DT node so it can be used. +The Qualcomm IPQ4019 includes an internal 5 ports switch, which is +connected to the CPU through the internal IPQESS Ethernet controller. -Signed-off-by: Robert Marko +Add support for this internal interface, which is internally connected to a +modified version of the QCA8K Ethernet switch. + +This Ethernet controller only support a specific internal interface mode +for connection to the switch. + +Signed-off-by: Maxime Chevallier +Reviewed-by: Krzysztof Kozlowski --- arch/arm/boot/dts/qcom-ipq4019.dtsi | 48 +++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) --- a/arch/arm/boot/dts/qcom-ipq4019.dtsi +++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi -@@ -38,6 +38,7 @@ - spi1 = &blsp1_spi2; - i2c0 = &blsp1_i2c3; - i2c1 = &blsp1_i2c4; -+ ethernet0 = &gmac; - }; - - cpus { -@@ -589,6 +590,57 @@ +@@ -591,6 +591,54 @@ status = "disabled"; }; @@ -29,9 +29,9 @@ Signed-off-by: Robert Marko + compatible = "qcom,ipq4019-ess-edma"; + reg = <0xc080000 0x8000>; + resets = <&gcc ESS_RESET>; -+ reset-names = "ess_rst"; ++ reset-names = "ess"; + clocks = <&gcc GCC_ESS_CLK>; -+ clock-names = "ess_clk"; ++ clock-names = "ess"; + interrupts = , + , + , @@ -64,15 +64,12 @@ Signed-off-by: Robert Marko + , + , + ; -+ -+ status = "disabled"; -+ + phy-mode = "internal"; ++ status = "disabled"; + fixed-link { + speed = <1000>; + full-duplex; + pause; -+ asym-pause; + }; + }; + diff --git a/target/linux/ipq40xx/patches-6.1/706-net-dsa-qca8k-add-IPQ4019-built-in-switch-support.patch b/target/linux/ipq40xx/patches-6.1/706-net-dsa-qca8k-add-IPQ4019-built-in-switch-support.patch new file mode 100644 index 0000000000..8bacb2c710 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/706-net-dsa-qca8k-add-IPQ4019-built-in-switch-support.patch @@ -0,0 +1,1132 @@ +From a38126870488398932e017dd9d76174b4aadbbbb Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Sat, 10 Sep 2022 15:46:09 +0200 +Subject: [PATCH] net: dsa: qca8k: add IPQ4019 built-in switch support + +Qualcomm IPQ40xx SoC-s have a variant of QCA8337N switch built-in. + +It shares most of the stuff with its external counterpart, however it is +modified for the SoC. +Namely, it doesn't have second CPU port (Port 6), so it has 6 ports +instead of 7. +It also has no built-in PHY-s but rather requires external PSGMII based +companion PHY-s (QCA8072 and QCA8075) for which it first needs to carry +out calibration before using them. +PSGMII has a SoC built-in PHY that is used to connect to the PHY-s which +unfortunately requires some magic values as the datasheet doesnt document +the bits that are being set or the register at all. + +Since its built-in it is MMIO like other peripherals and doesn't have its +own MDIO bus but depends on the SoC provided one. + +CPU connection is at Port 0 and it uses some kind of a internal connection +and no traditional RGMII/SGMII. + +It also doesn't use in-band tagging like other qca8k switches so a out of +band based tagger is used. + +Signed-off-by: Robert Marko +--- + drivers/net/dsa/qca/Kconfig | 8 + + drivers/net/dsa/qca/Makefile | 1 + + drivers/net/dsa/qca/qca8k-common.c | 6 +- + drivers/net/dsa/qca/qca8k-ipq4019.c | 948 ++++++++++++++++++++++++++++ + drivers/net/dsa/qca/qca8k.h | 56 ++ + 5 files changed, 1016 insertions(+), 3 deletions(-) + create mode 100644 drivers/net/dsa/qca/qca8k-ipq4019.c + +--- a/drivers/net/dsa/qca/Kconfig ++++ b/drivers/net/dsa/qca/Kconfig +@@ -23,3 +23,11 @@ config NET_DSA_QCA8K_LEDS_SUPPORT + help + This enabled support for LEDs present on the Qualcomm Atheros + QCA8K Ethernet switch chips. ++ ++config NET_DSA_QCA8K_IPQ4019 ++ tristate "Qualcomm Atheros IPQ4019 Ethernet switch support" ++ select NET_DSA_TAG_OOB ++ select REGMAP_MMIO ++ help ++ This enables support for the switch built-into Qualcomm Atheros ++ IPQ4019 SoCs. +--- a/drivers/net/dsa/qca/Makefile ++++ b/drivers/net/dsa/qca/Makefile +@@ -5,3 +5,4 @@ qca8k-y += qca8k-common.o qca8k-8xxx. + ifdef CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT + qca8k-y += qca8k-leds.o + endif ++obj-$(CONFIG_NET_DSA_QCA8K_IPQ4019) += qca8k-ipq4019.o qca8k-common.o +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -449,7 +449,7 @@ static int qca8k_vlan_del(struct qca8k_p + + /* Check if we're the last member to be removed */ + del = true; +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ for (i = 0; i < priv->ds->num_ports; i++) { + mask = QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(i); + + if ((reg & mask) != mask) { +@@ -642,7 +642,7 @@ int qca8k_port_bridge_join(struct dsa_sw + cpu_port = dsa_to_port(ds, port)->cpu_dp->index; + port_mask = BIT(cpu_port); + +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ for (i = 0; i < ds->num_ports; i++) { + if (dsa_is_cpu_port(ds, i)) + continue; + if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge)) +@@ -674,7 +674,7 @@ void qca8k_port_bridge_leave(struct dsa_ + + cpu_port = dsa_to_port(ds, port)->cpu_dp->index; + +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ for (i = 0; i < ds->num_ports; i++) { + if (dsa_is_cpu_port(ds, i)) + continue; + if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge)) +--- /dev/null ++++ b/drivers/net/dsa/qca/qca8k-ipq4019.c +@@ -0,0 +1,948 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2009 Felix Fietkau ++ * Copyright (C) 2011-2012, 2020-2021 Gabor Juhos ++ * Copyright (c) 2015, 2019, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2016 John Crispin ++ * Copyright (c) 2022 Robert Marko ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "qca8k.h" ++ ++static struct regmap_config qca8k_ipq4019_regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .max_register = 0x16ac, /* end MIB - Port6 range */ ++ .rd_table = &qca8k_readable_table, ++}; ++ ++static struct regmap_config qca8k_ipq4019_psgmii_phy_regmap_config = { ++ .name = "psgmii-phy", ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .max_register = 0x7fc, ++}; ++ ++static enum dsa_tag_protocol ++qca8k_ipq4019_get_tag_protocol(struct dsa_switch *ds, int port, ++ enum dsa_tag_protocol mp) ++{ ++ return DSA_TAG_PROTO_OOB; ++} ++ ++static struct phylink_pcs * ++qca8k_ipq4019_phylink_mac_select_pcs(struct dsa_switch *ds, int port, ++ phy_interface_t interface) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ struct phylink_pcs *pcs = NULL; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_PSGMII: ++ switch (port) { ++ case 0: ++ pcs = &priv->pcs_port_0.pcs; ++ break; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ return pcs; ++} ++ ++static int qca8k_ipq4019_pcs_config(struct phylink_pcs *pcs, unsigned int mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) ++{ ++ return 0; ++} ++ ++static void qca8k_ipq4019_pcs_an_restart(struct phylink_pcs *pcs) ++{ ++} ++ ++static struct qca8k_pcs *pcs_to_qca8k_pcs(struct phylink_pcs *pcs) ++{ ++ return container_of(pcs, struct qca8k_pcs, pcs); ++} ++ ++static void qca8k_ipq4019_pcs_get_state(struct phylink_pcs *pcs, ++ struct phylink_link_state *state) ++{ ++ struct qca8k_priv *priv = pcs_to_qca8k_pcs(pcs)->priv; ++ int port = pcs_to_qca8k_pcs(pcs)->port; ++ u32 reg; ++ int ret; ++ ++ ret = qca8k_read(priv, QCA8K_REG_PORT_STATUS(port), ®); ++ if (ret < 0) { ++ state->link = false; ++ return; ++ } ++ ++ state->link = !!(reg & QCA8K_PORT_STATUS_LINK_UP); ++ state->an_complete = state->link; ++ state->duplex = (reg & QCA8K_PORT_STATUS_DUPLEX) ? DUPLEX_FULL : ++ DUPLEX_HALF; ++ ++ switch (reg & QCA8K_PORT_STATUS_SPEED) { ++ case QCA8K_PORT_STATUS_SPEED_10: ++ state->speed = SPEED_10; ++ break; ++ case QCA8K_PORT_STATUS_SPEED_100: ++ state->speed = SPEED_100; ++ break; ++ case QCA8K_PORT_STATUS_SPEED_1000: ++ state->speed = SPEED_1000; ++ break; ++ default: ++ state->speed = SPEED_UNKNOWN; ++ break; ++ } ++ ++ if (reg & QCA8K_PORT_STATUS_RXFLOW) ++ state->pause |= MLO_PAUSE_RX; ++ if (reg & QCA8K_PORT_STATUS_TXFLOW) ++ state->pause |= MLO_PAUSE_TX; ++} ++ ++static const struct phylink_pcs_ops qca8k_pcs_ops = { ++ .pcs_get_state = qca8k_ipq4019_pcs_get_state, ++ .pcs_config = qca8k_ipq4019_pcs_config, ++ .pcs_an_restart = qca8k_ipq4019_pcs_an_restart, ++}; ++ ++static void qca8k_ipq4019_setup_pcs(struct qca8k_priv *priv, ++ struct qca8k_pcs *qpcs, ++ int port) ++{ ++ qpcs->pcs.ops = &qca8k_pcs_ops; ++ ++ /* We don't have interrupts for link changes, so we need to poll */ ++ qpcs->pcs.poll = true; ++ qpcs->priv = priv; ++ qpcs->port = port; ++} ++ ++static void qca8k_ipq4019_phylink_get_caps(struct dsa_switch *ds, int port, ++ struct phylink_config *config) ++{ ++ switch (port) { ++ case 0: /* CPU port */ ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ config->supported_interfaces); ++ break; ++ ++ case 1: ++ case 2: ++ case 3: ++ __set_bit(PHY_INTERFACE_MODE_PSGMII, ++ config->supported_interfaces); ++ break; ++ case 4: ++ case 5: ++ phy_interface_set_rgmii(config->supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_PSGMII, ++ config->supported_interfaces); ++ break; ++ } ++ ++ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10 | MAC_100 | MAC_1000FD; ++ ++ config->legacy_pre_march2020 = false; ++} ++ ++static void ++qca8k_phylink_ipq4019_mac_link_down(struct dsa_switch *ds, int port, ++ unsigned int mode, ++ phy_interface_t interface) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ qca8k_port_set_status(priv, port, 0); ++} ++ ++static void ++qca8k_phylink_ipq4019_mac_link_up(struct dsa_switch *ds, int port, ++ unsigned int mode, phy_interface_t interface, ++ struct phy_device *phydev, int speed, ++ int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ u32 reg; ++ ++ if (phylink_autoneg_inband(mode)) { ++ reg = QCA8K_PORT_STATUS_LINK_AUTO; ++ } else { ++ switch (speed) { ++ case SPEED_10: ++ reg = QCA8K_PORT_STATUS_SPEED_10; ++ break; ++ case SPEED_100: ++ reg = QCA8K_PORT_STATUS_SPEED_100; ++ break; ++ case SPEED_1000: ++ reg = QCA8K_PORT_STATUS_SPEED_1000; ++ break; ++ default: ++ reg = QCA8K_PORT_STATUS_LINK_AUTO; ++ break; ++ } ++ ++ if (duplex == DUPLEX_FULL) ++ reg |= QCA8K_PORT_STATUS_DUPLEX; ++ ++ if (rx_pause || dsa_is_cpu_port(ds, port)) ++ reg |= QCA8K_PORT_STATUS_RXFLOW; ++ ++ if (tx_pause || dsa_is_cpu_port(ds, port)) ++ reg |= QCA8K_PORT_STATUS_TXFLOW; ++ } ++ ++ reg |= QCA8K_PORT_STATUS_TXMAC | QCA8K_PORT_STATUS_RXMAC; ++ ++ qca8k_write(priv, QCA8K_REG_PORT_STATUS(port), reg); ++} ++ ++static int psgmii_vco_calibrate(struct qca8k_priv *priv) ++{ ++ int val, ret; ++ ++ if (!priv->psgmii_ethphy) { ++ dev_err(priv->dev, "PSGMII eth PHY missing, calibration failed!\n"); ++ return -ENODEV; ++ } ++ ++ /* Fix PSGMII RX 20bit */ ++ ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x5b); ++ /* Reset PHY PSGMII */ ++ ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x1b); ++ /* Release PHY PSGMII reset */ ++ ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x5b); ++ ++ /* Poll for VCO PLL calibration finish - Malibu(QCA8075) */ ++ ret = phy_read_mmd_poll_timeout(priv->psgmii_ethphy, ++ MDIO_MMD_PMAPMD, ++ 0x28, val, ++ (val & BIT(0)), ++ 10000, 1000000, ++ false); ++ if (ret) { ++ dev_err(priv->dev, "QCA807x PSGMII VCO calibration PLL not ready\n"); ++ return ret; ++ } ++ mdelay(50); ++ ++ /* Freeze PSGMII RX CDR */ ++ ret = phy_write(priv->psgmii_ethphy, MII_RESV2, 0x2230); ++ ++ /* Start PSGMIIPHY VCO PLL calibration */ ++ ret = regmap_set_bits(priv->psgmii, ++ PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_1, ++ PSGMIIPHY_REG_PLL_VCO_CALIB_RESTART); ++ ++ /* Poll for PSGMIIPHY PLL calibration finish - Dakota(IPQ40xx) */ ++ ret = regmap_read_poll_timeout(priv->psgmii, ++ PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_2, ++ val, val & PSGMIIPHY_REG_PLL_VCO_CALIB_READY, ++ 10000, 1000000); ++ if (ret) { ++ dev_err(priv->dev, "IPQ PSGMIIPHY VCO calibration PLL not ready\n"); ++ return ret; ++ } ++ mdelay(50); ++ ++ /* Release PSGMII RX CDR */ ++ ret = phy_write(priv->psgmii_ethphy, MII_RESV2, 0x3230); ++ /* Release PSGMII RX 20bit */ ++ ret = phy_write(priv->psgmii_ethphy, MII_BMCR, 0x5f); ++ mdelay(200); ++ ++ return ret; ++} ++ ++static void ++qca8k_switch_port_loopback_on_off(struct qca8k_priv *priv, int port, int on) ++{ ++ u32 val = QCA8K_PORT_LOOKUP_LOOPBACK_EN; ++ ++ if (on == 0) ++ val = 0; ++ ++ qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LOOPBACK_EN, val); ++} ++ ++static int ++qca8k_wait_for_phy_link_state(struct phy_device *phy, int need_status) ++{ ++ int a; ++ u16 status; ++ ++ for (a = 0; a < 100; a++) { ++ status = phy_read(phy, MII_QCA8075_SSTATUS); ++ status &= QCA8075_PHY_SPEC_STATUS_LINK; ++ status = !!status; ++ if (status == need_status) ++ return 0; ++ mdelay(8); ++ } ++ ++ return -1; ++} ++ ++static void ++qca8k_phy_loopback_on_off(struct qca8k_priv *priv, struct phy_device *phy, ++ int sw_port, int on) ++{ ++ if (on) { ++ phy_write(phy, MII_BMCR, BMCR_ANENABLE | BMCR_RESET); ++ phy_modify(phy, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN); ++ qca8k_wait_for_phy_link_state(phy, 0); ++ qca8k_write(priv, QCA8K_REG_PORT_STATUS(sw_port), 0); ++ phy_write(phy, MII_BMCR, ++ BMCR_SPEED1000 | ++ BMCR_FULLDPLX | ++ BMCR_LOOPBACK); ++ qca8k_wait_for_phy_link_state(phy, 1); ++ qca8k_write(priv, QCA8K_REG_PORT_STATUS(sw_port), ++ QCA8K_PORT_STATUS_SPEED_1000 | ++ QCA8K_PORT_STATUS_TXMAC | ++ QCA8K_PORT_STATUS_RXMAC | ++ QCA8K_PORT_STATUS_DUPLEX); ++ qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(sw_port), ++ QCA8K_PORT_LOOKUP_STATE_FORWARD, ++ QCA8K_PORT_LOOKUP_STATE_FORWARD); ++ } else { /* off */ ++ qca8k_write(priv, QCA8K_REG_PORT_STATUS(sw_port), 0); ++ qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(sw_port), ++ QCA8K_PORT_LOOKUP_STATE_DISABLED, ++ QCA8K_PORT_LOOKUP_STATE_DISABLED); ++ phy_write(phy, MII_BMCR, BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_RESET); ++ /* turn off the power of the phys - so that unused ++ ports do not raise links */ ++ phy_modify(phy, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN); ++ } ++} ++ ++static void ++qca8k_phy_pkt_gen_prep(struct qca8k_priv *priv, struct phy_device *phy, ++ int pkts_num, int on) ++{ ++ if (on) { ++ /* enable CRC checker and packets counters */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_CRC_AND_PKTS_COUNT, 0); ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_CRC_AND_PKTS_COUNT, ++ QCA8075_MMD7_CNT_FRAME_CHK_EN | QCA8075_MMD7_CNT_SELFCLR); ++ qca8k_wait_for_phy_link_state(phy, 1); ++ /* packet number */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_PKT_NUMB, pkts_num); ++ /* pkt size - 1504 bytes + 20 bytes */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_PKT_SIZE, 1504); ++ } else { /* off */ ++ /* packet number */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_PKT_NUMB, 0); ++ /* disable CRC checker and packet counter */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_CRC_AND_PKTS_COUNT, 0); ++ /* disable traffic gen */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_CTRL, 0); ++ } ++} ++ ++static void ++qca8k_wait_for_phy_pkt_gen_fin(struct qca8k_priv *priv, struct phy_device *phy) ++{ ++ int val; ++ /* wait for all traffic end: 4096(pkt num)*1524(size)*8ns(125MHz)=49938us */ ++ phy_read_mmd_poll_timeout(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_CTRL, ++ val, !(val & QCA8075_MMD7_PKT_GEN_INPROGR), ++ 50000, 1000000, true); ++} ++ ++static void ++qca8k_start_phy_pkt_gen(struct phy_device *phy) ++{ ++ /* start traffic gen */ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_PKT_GEN_CTRL, ++ QCA8075_MMD7_PKT_GEN_START | QCA8075_MMD7_PKT_GEN_INPROGR); ++} ++ ++static int ++qca8k_start_all_phys_pkt_gens(struct qca8k_priv *priv) ++{ ++ struct phy_device *phy; ++ phy = phy_device_create(priv->bus, QCA8075_MDIO_BRDCST_PHY_ADDR, ++ 0, 0, NULL); ++ if (!phy) { ++ dev_err(priv->dev, "unable to create mdio broadcast PHY(0x%x)\n", ++ QCA8075_MDIO_BRDCST_PHY_ADDR); ++ return -ENODEV; ++ } ++ ++ qca8k_start_phy_pkt_gen(phy); ++ ++ phy_device_free(phy); ++ return 0; ++} ++ ++static int ++qca8k_get_phy_pkt_gen_test_result(struct phy_device *phy, int pkts_num) ++{ ++ u32 tx_ok, tx_error; ++ u32 rx_ok, rx_error; ++ u32 tx_ok_high16; ++ u32 rx_ok_high16; ++ u32 tx_all_ok, rx_all_ok; ++ ++ /* check counters */ ++ tx_ok = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_EG_FRAME_RECV_CNT_LO); ++ tx_ok_high16 = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_EG_FRAME_RECV_CNT_HI); ++ tx_error = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_EG_FRAME_ERR_CNT); ++ rx_ok = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_IG_FRAME_RECV_CNT_LO); ++ rx_ok_high16 = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_IG_FRAME_RECV_CNT_HI); ++ rx_error = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_IG_FRAME_ERR_CNT); ++ tx_all_ok = tx_ok + (tx_ok_high16 << 16); ++ rx_all_ok = rx_ok + (rx_ok_high16 << 16); ++ ++ if (tx_all_ok < pkts_num) ++ return -1; ++ if(rx_all_ok < pkts_num) ++ return -2; ++ if(tx_error) ++ return -3; ++ if(rx_error) ++ return -4; ++ return 0; /* test is ok */ ++} ++ ++static ++void qca8k_phy_broadcast_write_on_off(struct qca8k_priv *priv, ++ struct phy_device *phy, int on) ++{ ++ u32 val; ++ ++ val = phy_read_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_MDIO_BRDCST_WRITE); ++ ++ if (on == 0) ++ val &= ~QCA8075_MMD7_MDIO_BRDCST_WRITE_EN; ++ else ++ val |= QCA8075_MMD7_MDIO_BRDCST_WRITE_EN; ++ ++ phy_write_mmd(phy, MDIO_MMD_AN, QCA8075_MMD7_MDIO_BRDCST_WRITE, val); ++} ++ ++static int ++qca8k_test_dsa_port_for_errors(struct qca8k_priv *priv, struct phy_device *phy, ++ int port, int test_phase) ++{ ++ int res = 0; ++ const int test_pkts_num = QCA8075_PKT_GEN_PKTS_COUNT; ++ ++ if (test_phase == 1) { /* start test preps */ ++ qca8k_phy_loopback_on_off(priv, phy, port, 1); ++ qca8k_switch_port_loopback_on_off(priv, port, 1); ++ qca8k_phy_broadcast_write_on_off(priv, phy, 1); ++ qca8k_phy_pkt_gen_prep(priv, phy, test_pkts_num, 1); ++ } else if (test_phase == 2) { ++ /* wait for test results, collect it and cleanup */ ++ qca8k_wait_for_phy_pkt_gen_fin(priv, phy); ++ res = qca8k_get_phy_pkt_gen_test_result(phy, test_pkts_num); ++ qca8k_phy_pkt_gen_prep(priv, phy, test_pkts_num, 0); ++ qca8k_phy_broadcast_write_on_off(priv, phy, 0); ++ qca8k_switch_port_loopback_on_off(priv, port, 0); ++ qca8k_phy_loopback_on_off(priv, phy, port, 0); ++ } ++ ++ return res; ++} ++ ++static int ++qca8k_do_dsa_sw_ports_self_test(struct qca8k_priv *priv, int parallel_test) ++{ ++ struct device_node *dn = priv->dev->of_node; ++ struct device_node *ports, *port; ++ struct device_node *phy_dn; ++ struct phy_device *phy; ++ int reg, err = 0, test_phase; ++ u32 tests_result = 0; ++ ++ ports = of_get_child_by_name(dn, "ports"); ++ if (!ports) { ++ dev_err(priv->dev, "no ports child node found\n"); ++ return -EINVAL; ++ } ++ ++ for (test_phase = 1; test_phase <= 2; test_phase++) { ++ if (parallel_test && test_phase == 2) { ++ err = qca8k_start_all_phys_pkt_gens(priv); ++ if (err) ++ goto error; ++ } ++ for_each_available_child_of_node(ports, port) { ++ err = of_property_read_u32(port, "reg", ®); ++ if (err) ++ goto error; ++ if (reg >= QCA8K_NUM_PORTS) { ++ err = -EINVAL; ++ goto error; ++ } ++ phy_dn = of_parse_phandle(port, "phy-handle", 0); ++ if (phy_dn) { ++ phy = of_phy_find_device(phy_dn); ++ of_node_put(phy_dn); ++ if (phy) { ++ int result; ++ result = qca8k_test_dsa_port_for_errors(priv, ++ phy, reg, test_phase); ++ if (!parallel_test && test_phase == 1) ++ qca8k_start_phy_pkt_gen(phy); ++ put_device(&phy->mdio.dev); ++ if (test_phase == 2) { ++ tests_result <<= 1; ++ if (result) ++ tests_result |= 1; ++ } ++ } ++ } ++ } ++ } ++ ++end: ++ of_node_put(ports); ++ qca8k_fdb_flush(priv); ++ return tests_result; ++error: ++ tests_result |= 0xf000; ++ goto end; ++} ++ ++static int ++psgmii_vco_calibrate_and_test(struct dsa_switch *ds) ++{ ++ int ret, a, test_result; ++ struct qca8k_priv *priv = ds->priv; ++ ++ for (a = 0; a <= QCA8K_PSGMII_CALB_NUM; a++) { ++ ret = psgmii_vco_calibrate(priv); ++ if (ret) ++ return ret; ++ /* first we run serial test */ ++ test_result = qca8k_do_dsa_sw_ports_self_test(priv, 0); ++ /* and if it is ok then we run the test in parallel */ ++ if (!test_result) ++ test_result = qca8k_do_dsa_sw_ports_self_test(priv, 1); ++ if (!test_result) { ++ if (a > 0) { ++ dev_warn(priv->dev, "PSGMII work was stabilized after %d " ++ "calibration retries !\n", a); ++ } ++ return 0; ++ } else { ++ schedule(); ++ if (a > 0 && a % 10 == 0) { ++ dev_err(priv->dev, "PSGMII work is unstable !!! " ++ "Let's try to wait a bit ... %d\n", a); ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(msecs_to_jiffies(a * 100)); ++ } ++ } ++ } ++ ++ panic("PSGMII work is unstable !!! " ++ "Repeated recalibration attempts did not help(0x%x) !\n", ++ test_result); ++ ++ return -EFAULT; ++} ++ ++static int ++ipq4019_psgmii_configure(struct dsa_switch *ds) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ int ret; ++ ++ if (!priv->psgmii_calibrated) { ++ dev_info(ds->dev, "PSGMII calibration!\n"); ++ ret = psgmii_vco_calibrate_and_test(ds); ++ ++ ret = regmap_clear_bits(priv->psgmii, PSGMIIPHY_MODE_CONTROL, ++ PSGMIIPHY_MODE_ATHR_CSCO_MODE_25M); ++ ret = regmap_write(priv->psgmii, PSGMIIPHY_TX_CONTROL, ++ PSGMIIPHY_TX_CONTROL_MAGIC_VALUE); ++ ++ priv->psgmii_calibrated = true; ++ ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void ++qca8k_phylink_ipq4019_mac_config(struct dsa_switch *ds, int port, ++ unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++ struct qca8k_priv *priv = ds->priv; ++ ++ switch (port) { ++ case 0: ++ /* CPU port, no configuration needed */ ++ return; ++ case 1: ++ case 2: ++ case 3: ++ if (state->interface == PHY_INTERFACE_MODE_PSGMII) ++ if (ipq4019_psgmii_configure(ds)) ++ dev_err(ds->dev, "PSGMII configuration failed!\n"); ++ return; ++ case 4: ++ case 5: ++ if (state->interface == PHY_INTERFACE_MODE_RGMII || ++ state->interface == PHY_INTERFACE_MODE_RGMII_ID || ++ state->interface == PHY_INTERFACE_MODE_RGMII_RXID || ++ state->interface == PHY_INTERFACE_MODE_RGMII_TXID) { ++ regmap_set_bits(priv->regmap, ++ QCA8K_IPQ4019_REG_RGMII_CTRL, ++ QCA8K_IPQ4019_RGMII_CTRL_CLK); ++ } ++ ++ if (state->interface == PHY_INTERFACE_MODE_PSGMII) ++ if (ipq4019_psgmii_configure(ds)) ++ dev_err(ds->dev, "PSGMII configuration failed!\n"); ++ return; ++ default: ++ dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port); ++ return; ++ } ++} ++ ++static int ++qca8k_ipq4019_setup_port(struct dsa_switch *ds, int port) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ int ret; ++ ++ /* CPU port gets connected to all user ports of the switch */ ++ if (dsa_is_cpu_port(ds, port)) { ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds)); ++ if (ret) ++ return ret; ++ ++ /* Disable CPU ARP Auto-learning by default */ ++ ret = regmap_clear_bits(priv->regmap, ++ QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LEARN); ++ if (ret) ++ return ret; ++ } ++ ++ /* Individual user ports get connected to CPU port only */ ++ if (dsa_is_user_port(ds, port)) { ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, ++ BIT(QCA8K_IPQ4019_CPU_PORT)); ++ if (ret) ++ return ret; ++ ++ /* Enable ARP Auto-learning by default */ ++ ret = regmap_set_bits(priv->regmap, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_LEARN); ++ if (ret) ++ return ret; ++ ++ /* For port based vlans to work we need to set the ++ * default egress vid ++ */ ++ ret = qca8k_rmw(priv, QCA8K_EGRESS_VLAN(port), ++ QCA8K_EGREES_VLAN_PORT_MASK(port), ++ QCA8K_EGREES_VLAN_PORT(port, QCA8K_PORT_VID_DEF)); ++ if (ret) ++ return ret; ++ ++ ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(port), ++ QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) | ++ QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF)); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++qca8k_ipq4019_setup(struct dsa_switch *ds) ++{ ++ struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; ++ int ret, i; ++ ++ /* Make sure that port 0 is the cpu port */ ++ if (!dsa_is_cpu_port(ds, QCA8K_IPQ4019_CPU_PORT)) { ++ dev_err(priv->dev, "port %d is not the CPU port", ++ QCA8K_IPQ4019_CPU_PORT); ++ return -EINVAL; ++ } ++ ++ qca8k_ipq4019_setup_pcs(priv, &priv->pcs_port_0, 0); ++ ++ /* Enable CPU Port */ ++ ret = regmap_set_bits(priv->regmap, QCA8K_REG_GLOBAL_FW_CTRL0, ++ QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN); ++ if (ret) { ++ dev_err(priv->dev, "failed enabling CPU port"); ++ return ret; ++ } ++ ++ /* Enable MIB counters */ ++ ret = qca8k_mib_init(priv); ++ if (ret) ++ dev_warn(priv->dev, "MIB init failed"); ++ ++ /* Disable forwarding by default on all ports */ ++ for (i = 0; i < QCA8K_IPQ4019_NUM_PORTS; i++) { ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i), ++ QCA8K_PORT_LOOKUP_MEMBER, 0); ++ if (ret) ++ return ret; ++ } ++ ++ /* Enable QCA header mode on the CPU port */ ++ ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_IPQ4019_CPU_PORT), ++ FIELD_PREP(QCA8K_PORT_HDR_CTRL_TX_MASK, QCA8K_PORT_HDR_CTRL_ALL) | ++ FIELD_PREP(QCA8K_PORT_HDR_CTRL_RX_MASK, QCA8K_PORT_HDR_CTRL_ALL)); ++ if (ret) { ++ dev_err(priv->dev, "failed enabling QCA header mode"); ++ return ret; ++ } ++ ++ /* Disable MAC by default on all ports */ ++ for (i = 0; i < QCA8K_IPQ4019_NUM_PORTS; i++) { ++ if (dsa_is_user_port(ds, i)) ++ qca8k_port_set_status(priv, i, 0); ++ } ++ ++ /* Forward all unknown frames to CPU port for Linux processing */ ++ ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1, ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_MASK, BIT(QCA8K_IPQ4019_CPU_PORT)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_BC_DP_MASK, BIT(QCA8K_IPQ4019_CPU_PORT)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_MC_DP_MASK, BIT(QCA8K_IPQ4019_CPU_PORT)) | ++ FIELD_PREP(QCA8K_GLOBAL_FW_CTRL1_UC_DP_MASK, BIT(QCA8K_IPQ4019_CPU_PORT))); ++ if (ret) ++ return ret; ++ ++ /* Setup connection between CPU port & user ports */ ++ for (i = 0; i < QCA8K_IPQ4019_NUM_PORTS; i++) { ++ ret = qca8k_ipq4019_setup_port(ds, i); ++ if (ret) ++ return ret; ++ } ++ ++ /* Setup our port MTUs to match power on defaults */ ++ ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN); ++ if (ret) ++ dev_warn(priv->dev, "failed setting MTU settings"); ++ ++ /* Flush the FDB table */ ++ qca8k_fdb_flush(priv); ++ ++ /* Set min a max ageing value supported */ ++ ds->ageing_time_min = 7000; ++ ds->ageing_time_max = 458745000; ++ ++ /* Set max number of LAGs supported */ ++ ds->num_lag_ids = QCA8K_NUM_LAGS; ++ ++ /* CPU port HW learning doesnt work correctly, so let DSA handle it */ ++ ds->assisted_learning_on_cpu_port = true; ++ ++ return 0; ++} ++ ++static const struct dsa_switch_ops qca8k_ipq4019_switch_ops = { ++ .get_tag_protocol = qca8k_ipq4019_get_tag_protocol, ++ .setup = qca8k_ipq4019_setup, ++ .get_strings = qca8k_get_strings, ++ .get_ethtool_stats = qca8k_get_ethtool_stats, ++ .get_sset_count = qca8k_get_sset_count, ++ .set_ageing_time = qca8k_set_ageing_time, ++ .get_mac_eee = qca8k_get_mac_eee, ++ .set_mac_eee = qca8k_set_mac_eee, ++ .port_enable = qca8k_port_enable, ++ .port_disable = qca8k_port_disable, ++ .port_change_mtu = qca8k_port_change_mtu, ++ .port_max_mtu = qca8k_port_max_mtu, ++ .port_stp_state_set = qca8k_port_stp_state_set, ++ .port_bridge_join = qca8k_port_bridge_join, ++ .port_bridge_leave = qca8k_port_bridge_leave, ++ .port_fast_age = qca8k_port_fast_age, ++ .port_fdb_add = qca8k_port_fdb_add, ++ .port_fdb_del = qca8k_port_fdb_del, ++ .port_fdb_dump = qca8k_port_fdb_dump, ++ .port_mdb_add = qca8k_port_mdb_add, ++ .port_mdb_del = qca8k_port_mdb_del, ++ .port_mirror_add = qca8k_port_mirror_add, ++ .port_mirror_del = qca8k_port_mirror_del, ++ .port_vlan_filtering = qca8k_port_vlan_filtering, ++ .port_vlan_add = qca8k_port_vlan_add, ++ .port_vlan_del = qca8k_port_vlan_del, ++ .phylink_mac_select_pcs = qca8k_ipq4019_phylink_mac_select_pcs, ++ .phylink_get_caps = qca8k_ipq4019_phylink_get_caps, ++ .phylink_mac_config = qca8k_phylink_ipq4019_mac_config, ++ .phylink_mac_link_down = qca8k_phylink_ipq4019_mac_link_down, ++ .phylink_mac_link_up = qca8k_phylink_ipq4019_mac_link_up, ++ .port_lag_join = qca8k_port_lag_join, ++ .port_lag_leave = qca8k_port_lag_leave, ++}; ++ ++static const struct qca8k_match_data ipq4019 = { ++ .id = QCA8K_ID_IPQ4019, ++ .mib_count = QCA8K_QCA833X_MIB_COUNT, ++}; ++ ++static int ++qca8k_ipq4019_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct qca8k_priv *priv; ++ void __iomem *base, *psgmii; ++ struct device_node *np = dev->of_node, *mdio_np, *psgmii_ethphy_np; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dev = dev; ++ priv->info = &ipq4019; ++ ++ /* Start by setting up the register mapping */ ++ base = devm_platform_ioremap_resource_byname(pdev, "base"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ priv->regmap = devm_regmap_init_mmio(dev, base, ++ &qca8k_ipq4019_regmap_config); ++ if (IS_ERR(priv->regmap)) { ++ ret = PTR_ERR(priv->regmap); ++ dev_err(dev, "base regmap initialization failed, %d\n", ret); ++ return ret; ++ } ++ ++ psgmii = devm_platform_ioremap_resource_byname(pdev, "psgmii_phy"); ++ if (IS_ERR(psgmii)) ++ return PTR_ERR(psgmii); ++ ++ priv->psgmii = devm_regmap_init_mmio(dev, psgmii, ++ &qca8k_ipq4019_psgmii_phy_regmap_config); ++ if (IS_ERR(priv->psgmii)) { ++ ret = PTR_ERR(priv->psgmii); ++ dev_err(dev, "PSGMII regmap initialization failed, %d\n", ret); ++ return ret; ++ } ++ ++ mdio_np = of_parse_phandle(np, "mdio", 0); ++ if (!mdio_np) { ++ dev_err(dev, "unable to get MDIO bus phandle\n"); ++ of_node_put(mdio_np); ++ return -EINVAL; ++ } ++ ++ priv->bus = of_mdio_find_bus(mdio_np); ++ of_node_put(mdio_np); ++ if (!priv->bus) { ++ dev_err(dev, "unable to find MDIO bus\n"); ++ return -EPROBE_DEFER; ++ } ++ ++ psgmii_ethphy_np = of_parse_phandle(np, "psgmii-ethphy", 0); ++ if (!psgmii_ethphy_np) { ++ dev_dbg(dev, "unable to get PSGMII eth PHY phandle\n"); ++ of_node_put(psgmii_ethphy_np); ++ } ++ ++ if (psgmii_ethphy_np) { ++ priv->psgmii_ethphy = of_phy_find_device(psgmii_ethphy_np); ++ of_node_put(psgmii_ethphy_np); ++ if (!priv->psgmii_ethphy) { ++ dev_err(dev, "unable to get PSGMII eth PHY\n"); ++ return -ENODEV; ++ } ++ } ++ ++ /* Check the detected switch id */ ++ ret = qca8k_read_switch_id(priv); ++ if (ret) ++ return ret; ++ ++ priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL); ++ if (!priv->ds) ++ return -ENOMEM; ++ ++ priv->ds->dev = dev; ++ priv->ds->num_ports = QCA8K_IPQ4019_NUM_PORTS; ++ priv->ds->priv = priv; ++ priv->ds->ops = &qca8k_ipq4019_switch_ops; ++ mutex_init(&priv->reg_mutex); ++ platform_set_drvdata(pdev, priv); ++ ++ return dsa_register_switch(priv->ds); ++} ++ ++static int ++qca8k_ipq4019_remove(struct platform_device *pdev) ++{ ++ struct qca8k_priv *priv = dev_get_drvdata(&pdev->dev); ++ int i; ++ ++ if (!priv) ++ return 0; ++ ++ for (i = 0; i < QCA8K_IPQ4019_NUM_PORTS; i++) ++ qca8k_port_set_status(priv, i, 0); ++ ++ dsa_unregister_switch(priv->ds); ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static const struct of_device_id qca8k_ipq4019_of_match[] = { ++ { .compatible = "qca,ipq4019-qca8337n", }, ++ { /* sentinel */ }, ++}; ++ ++static struct platform_driver qca8k_ipq4019_driver = { ++ .probe = qca8k_ipq4019_probe, ++ .remove = qca8k_ipq4019_remove, ++ .driver = { ++ .name = "qca8k-ipq4019", ++ .of_match_table = qca8k_ipq4019_of_match, ++ }, ++}; ++ ++module_platform_driver(qca8k_ipq4019_driver); ++ ++MODULE_AUTHOR("Mathieu Olivari, John Crispin "); ++MODULE_AUTHOR("Gabor Juhos , Robert Marko "); ++MODULE_DESCRIPTION("Qualcomm IPQ4019 built-in switch driver"); ++MODULE_LICENSE("GPL"); +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -19,7 +19,10 @@ + #define QCA8K_ETHERNET_TIMEOUT 5 + + #define QCA8K_NUM_PORTS 7 ++#define QCA8K_IPQ4019_NUM_PORTS 6 + #define QCA8K_NUM_CPU_PORTS 2 ++#define QCA8K_IPQ4019_NUM_CPU_PORTS 1 ++#define QCA8K_IPQ4019_CPU_PORT 0 + #define QCA8K_MAX_MTU 9000 + #define QCA8K_NUM_LAGS 4 + #define QCA8K_NUM_PORTS_FOR_LAG 4 +@@ -28,6 +31,7 @@ + #define QCA8K_ID_QCA8327 0x12 + #define PHY_ID_QCA8337 0x004dd036 + #define QCA8K_ID_QCA8337 0x13 ++#define QCA8K_ID_IPQ4019 0x14 + + #define QCA8K_QCA832X_MIB_COUNT 39 + #define QCA8K_QCA833X_MIB_COUNT 41 +@@ -263,6 +267,7 @@ + #define QCA8K_PORT_LOOKUP_STATE_LEARNING QCA8K_PORT_LOOKUP_STATE(0x3) + #define QCA8K_PORT_LOOKUP_STATE_FORWARD QCA8K_PORT_LOOKUP_STATE(0x4) + #define QCA8K_PORT_LOOKUP_LEARN BIT(20) ++#define QCA8K_PORT_LOOKUP_LOOPBACK_EN BIT(21) + #define QCA8K_PORT_LOOKUP_ING_MIRROR_EN BIT(25) + + #define QCA8K_REG_GOL_TRUNK_CTRL0 0x700 +@@ -339,6 +344,53 @@ + #define MII_ATH_MMD_ADDR 0x0d + #define MII_ATH_MMD_DATA 0x0e + ++/* IPQ4019 PSGMII PHY registers */ ++#define QCA8K_IPQ4019_REG_RGMII_CTRL 0x004 ++#define QCA8K_IPQ4019_RGMII_CTRL_RGMII_RXC GENMASK(1, 0) ++#define QCA8K_IPQ4019_RGMII_CTRL_RGMII_TXC GENMASK(9, 8) ++/* Some kind of CLK selection ++ * 0: gcc_ess_dly2ns ++ * 1: gcc_ess_clk ++ */ ++#define QCA8K_IPQ4019_RGMII_CTRL_CLK BIT(10) ++#define QCA8K_IPQ4019_RGMII_CTRL_DELAY_RMII0 GENMASK(17, 16) ++#define QCA8K_IPQ4019_RGMII_CTRL_INVERT_RMII0_REF_CLK BIT(18) ++#define QCA8K_IPQ4019_RGMII_CTRL_DELAY_RMII1 GENMASK(20, 19) ++#define QCA8K_IPQ4019_RGMII_CTRL_INVERT_RMII1_REF_CLK BIT(21) ++#define QCA8K_IPQ4019_RGMII_CTRL_INVERT_RMII0_MASTER_EN BIT(24) ++#define QCA8K_IPQ4019_RGMII_CTRL_INVERT_RMII1_MASTER_EN BIT(25) ++ ++#define PSGMIIPHY_MODE_CONTROL 0x1b4 ++#define PSGMIIPHY_MODE_ATHR_CSCO_MODE_25M BIT(0) ++#define PSGMIIPHY_TX_CONTROL 0x288 ++#define PSGMIIPHY_TX_CONTROL_MAGIC_VALUE 0x8380 ++#define PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_1 0x9c ++#define PSGMIIPHY_REG_PLL_VCO_CALIB_RESTART BIT(14) ++#define PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_2 0xa0 ++#define PSGMIIPHY_REG_PLL_VCO_CALIB_READY BIT(0) ++ ++#define QCA8K_PSGMII_CALB_NUM 100 ++#define MII_QCA8075_SSTATUS 0x11 ++#define QCA8075_PHY_SPEC_STATUS_LINK BIT(10) ++#define QCA8075_MMD7_CRC_AND_PKTS_COUNT 0x8029 ++#define QCA8075_MMD7_PKT_GEN_PKT_NUMB 0x8021 ++#define QCA8075_MMD7_PKT_GEN_PKT_SIZE 0x8062 ++#define QCA8075_MMD7_PKT_GEN_CTRL 0x8020 ++#define QCA8075_MMD7_CNT_SELFCLR BIT(1) ++#define QCA8075_MMD7_CNT_FRAME_CHK_EN BIT(0) ++#define QCA8075_MMD7_PKT_GEN_START BIT(13) ++#define QCA8075_MMD7_PKT_GEN_INPROGR BIT(15) ++#define QCA8075_MMD7_IG_FRAME_RECV_CNT_HI 0x802a ++#define QCA8075_MMD7_IG_FRAME_RECV_CNT_LO 0x802b ++#define QCA8075_MMD7_IG_FRAME_ERR_CNT 0x802c ++#define QCA8075_MMD7_EG_FRAME_RECV_CNT_HI 0x802d ++#define QCA8075_MMD7_EG_FRAME_RECV_CNT_LO 0x802e ++#define QCA8075_MMD7_EG_FRAME_ERR_CNT 0x802f ++#define QCA8075_MMD7_MDIO_BRDCST_WRITE 0x8028 ++#define QCA8075_MMD7_MDIO_BRDCST_WRITE_EN BIT(15) ++#define QCA8075_MDIO_BRDCST_PHY_ADDR 0x1f ++#define QCA8075_PKT_GEN_PKTS_COUNT 4096 ++ + enum { + QCA8K_PORT_SPEED_10M = 0, + QCA8K_PORT_SPEED_100M = 1, +@@ -467,6 +519,10 @@ struct qca8k_priv { + struct qca8k_pcs pcs_port_6; + const struct qca8k_match_data *info; + struct qca8k_led ports_led[QCA8K_LED_COUNT]; ++ /* IPQ4019 specific */ ++ struct regmap *psgmii; ++ struct phy_device *psgmii_ethphy; ++ bool psgmii_calibrated; + }; + + struct qca8k_mib_desc { diff --git a/target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch b/target/linux/ipq40xx/patches-6.1/707-arm-dts-ipq4019-add-switch-node.patch similarity index 97% rename from target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch rename to target/linux/ipq40xx/patches-6.1/707-arm-dts-ipq4019-add-switch-node.patch index b1a6a2bf34..136c15a678 100644 --- a/target/linux/ipq40xx/patches-6.1/706-arm-dts-ipq4019-add-switch-node.patch +++ b/target/linux/ipq40xx/patches-6.1/707-arm-dts-ipq4019-add-switch-node.patch @@ -1,4 +1,4 @@ -From 8cbdb2526c3d7ba2e0c8c771773595f195135f54 Mon Sep 17 00:00:00 2001 +From 19c507c3fe4a6fc60317dcae2c55de452aecb7d5 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 1 Nov 2021 18:15:04 +0100 Subject: [PATCH] arm: dts: ipq4019: add switch node diff --git a/target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch b/target/linux/ipq40xx/patches-6.1/708-dt-bindings-net-add-QCA807x-PHY.patch similarity index 97% rename from target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch rename to target/linux/ipq40xx/patches-6.1/708-dt-bindings-net-add-QCA807x-PHY.patch index e026b7550d..b325d9e535 100644 --- a/target/linux/ipq40xx/patches-6.1/707-dt-bindings-net-add-QCA807x-PHY.patch +++ b/target/linux/ipq40xx/patches-6.1/708-dt-bindings-net-add-QCA807x-PHY.patch @@ -1,4 +1,4 @@ -From dfba344da3657ee4d91e7ebd1217e93423d03624 Mon Sep 17 00:00:00 2001 +From 96eb388c082bd0086b128d82def9daaab1617951 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Thu, 1 Oct 2020 15:05:35 +0200 Subject: [PATCH] dt-bindings: net: add QCA807x PHY diff --git a/target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch b/target/linux/ipq40xx/patches-6.1/709-net-phy-Add-Qualcom-QCA807x-driver.patch similarity index 94% rename from target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch rename to target/linux/ipq40xx/patches-6.1/709-net-phy-Add-Qualcom-QCA807x-driver.patch index dd2bb33c55..9bae6e7b96 100644 --- a/target/linux/ipq40xx/patches-6.1/708-net-phy-Add-Qualcom-QCA807x-driver.patch +++ b/target/linux/ipq40xx/patches-6.1/709-net-phy-Add-Qualcom-QCA807x-driver.patch @@ -1,4 +1,4 @@ -From 95179775debad6b0bdab241d4a305135fc5e67dc Mon Sep 17 00:00:00 2001 +From 876bb5b69c1e083be526c0ea261982d5eb78556f Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 9 Sep 2022 23:44:42 +0200 Subject: [PATCH] net: phy: Add Qualcom QCA807x driver @@ -25,7 +25,7 @@ Signed-off-by: Robert Marko --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -362,6 +362,13 @@ config AT803X_PHY +@@ -369,6 +369,13 @@ config AT803X_PHY Currently supports the AR8030, AR8031, AR8033, AR8035 and internal QCA8337(Internal qca8k PHY) model diff --git a/target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch b/target/linux/ipq40xx/patches-6.1/710-arm-dts-ipq4019-QCA807x-properties.patch similarity index 95% rename from target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch rename to target/linux/ipq40xx/patches-6.1/710-arm-dts-ipq4019-QCA807x-properties.patch index 5d8a9bf053..ddfedcf5af 100644 --- a/target/linux/ipq40xx/patches-6.1/709-arm-dts-ipq4019-QCA807x-properties.patch +++ b/target/linux/ipq40xx/patches-6.1/710-arm-dts-ipq4019-QCA807x-properties.patch @@ -1,4 +1,4 @@ -From 03ebcd291974e4ca5d77026111f63309bc708326 Mon Sep 17 00:00:00 2001 +From 79b38b9f85da868ca59b66715c20aa55104b640b Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 2 Oct 2020 10:43:26 +0200 Subject: [PATCH] arm: dts: ipq4019: QCA807x properties diff --git a/target/linux/ipq40xx/patches-6.1/711-net-qualcomm-ipqess-fix-TX-timeout-errors.patch b/target/linux/ipq40xx/patches-6.1/711-net-qualcomm-ipqess-fix-TX-timeout-errors.patch new file mode 100644 index 0000000000..149208aa69 --- /dev/null +++ b/target/linux/ipq40xx/patches-6.1/711-net-qualcomm-ipqess-fix-TX-timeout-errors.patch @@ -0,0 +1,64 @@ +From d0055b03d9c8d48ad2b971821989b09ba95c39f8 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 17 Sep 2023 20:18:31 +0200 +Subject: [PATCH] net: qualcomm: ipqess: fix TX timeout errors + +Currently logic to handle napi tx completion is flawed and on the long +run on loaded condition cause TX timeout error with the queue not being +able to handle any new packet. + +There are 2 main cause of this: +- incrementing the packet done value wrongly +- handling 2 times the tx_ring tail + +ipqess_tx_unmap_and_free may return 2 kind values: +- 0: we are handling first and middle descriptor for the packet +- packet len: we are at the last descriptor for the packet + +Done value was wrongly incremented also for first and intermediate +descriptor for the packet resulting causing panic and TX timeouts by +comunicating to the kernel an inconsistent value of packet handling not +matching the expected ones. + +Tx_ring tail was handled twice for ipqess_tx_complete run resulting in +again done value incremented wrongly and also problem with idx handling +by actually skipping descriptor for some packets. + +Rework the loop logic to fix these 2 problem and also add some comments +to make sure ipqess_tx_unmap_and_free ret value is better +understandable. + +Signed-off-by: Christian Marangi +--- + drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c ++++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c +@@ -453,13 +453,22 @@ static int ipqess_tx_complete(struct ipq + tail >>= IPQESS_TPD_CONS_IDX_SHIFT; + tail &= IPQESS_TPD_CONS_IDX_MASK; + +- do { ++ while ((tx_ring->tail != tail) && (done < budget)) { + ret = ipqess_tx_unmap_and_free(&tx_ring->ess->pdev->dev, + &tx_ring->buf[tx_ring->tail]); +- tx_ring->tail = IPQESS_NEXT_IDX(tx_ring->tail, tx_ring->count); ++ /* ipqess_tx_unmap_and_free may return 2 kind values: ++ * - 0: we are handling first and middle descriptor for the packet ++ * - packet len: we are at the last descriptor for the packet ++ * Increment total bytes handled and packet done only if we are ++ * handling the last descriptor for the packet. ++ */ ++ if (ret) { ++ total += ret; ++ done++; ++ } + +- total += ret; +- } while ((++done < budget) && (tx_ring->tail != tail)); ++ tx_ring->tail = IPQESS_NEXT_IDX(tx_ring->tail, tx_ring->count); ++ }; + + ipqess_w32(tx_ring->ess, IPQESS_REG_TX_SW_CONS_IDX_Q(tx_ring->idx), + tx_ring->tail); From 825cfa4e36cb6597c1cf9d320e33585e2d43c8e9 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 14 Aug 2023 18:49:37 +0200 Subject: [PATCH 12/24] ipq40xx: 6.1: refresh kernel config Refresh the kernel config via make kernel_menuconfig. Signed-off-by: Robert Marko --- target/linux/ipq40xx/config-6.1 | 68 ++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/target/linux/ipq40xx/config-6.1 b/target/linux/ipq40xx/config-6.1 index 0acc013a81..1fbc33103a 100644 --- a/target/linux/ipq40xx/config-6.1 +++ b/target/linux/ipq40xx/config-6.1 @@ -7,6 +7,8 @@ CONFIG_ARCH_IPQ40XX=y CONFIG_ARCH_KEEP_MEMBLOCK=y # CONFIG_ARCH_MDM9615 is not set CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +# CONFIG_ARCH_MSM8909 is not set +# CONFIG_ARCH_MSM8916 is not set # CONFIG_ARCH_MSM8960 is not set # CONFIG_ARCH_MSM8974 is not set # CONFIG_ARCH_MSM8X60 is not set @@ -28,9 +30,8 @@ CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y # CONFIG_ARM_ATAG_DTB_COMPAT is not set CONFIG_ARM_CPUIDLE=y # CONFIG_ARM_CPU_TOPOLOGY is not set -CONFIG_ARM_CRYPTO=y CONFIG_ARM_GIC=y -CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_ARM_HAS_GROUP_RELOCS=y CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_L1_CACHE_SHIFT_6=y CONFIG_ARM_PATCH_IDIV=y @@ -50,12 +51,18 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_MQ_PCI=y CONFIG_BOUNCE=y # CONFIG_CACHE_L2X0 is not set +CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_CC_NO_ARRAY_BOUNDS=y CONFIG_CLKSRC_QCOM=y CONFIG_CLONE_BACKWARDS=y CONFIG_CMDLINE_PARTITION=y CONFIG_COMMON_CLK=y CONFIG_COMMON_CLK_QCOM=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y CONFIG_CPUFREQ_DT=y CONFIG_CPUFREQ_DT_PLATDEV=y CONFIG_CPU_32v6K=y @@ -82,6 +89,7 @@ CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_PABRT_V7=y CONFIG_CPU_PM=y CONFIG_CPU_RMAP=y @@ -96,6 +104,7 @@ CONFIG_CRC32_SLICEBY8=y CONFIG_CRC8=y CONFIG_CRYPTO_AES_ARM=y CONFIG_CRYPTO_AES_ARM_BS=y +CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S=y CONFIG_CRYPTO_BLAKE2S_ARM=y CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_CRYPTD=y @@ -117,9 +126,10 @@ CONFIG_CRYPTO_HASH_INFO=y CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_HW=y CONFIG_CRYPTO_JITTERENTROPY=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_LIB_DES=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 @@ -132,14 +142,15 @@ CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_SIMD=y CONFIG_CRYPTO_XTS=y CONFIG_CRYPTO_ZSTD=y +CONFIG_CURRENT_POINTER_IN_TPIDRURO=y CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_INFO=y CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" CONFIG_DEBUG_MISC=y CONFIG_DMADEVICES=y CONFIG_DMA_ENGINE=y CONFIG_DMA_OF=y CONFIG_DMA_OPS=y -CONFIG_DMA_REMAP=y CONFIG_DMA_SHARED_BUFFER=y CONFIG_DMA_VIRTUAL_CHANNELS=y CONFIG_DTC=y @@ -147,11 +158,14 @@ CONFIG_DT_IDLE_STATES=y CONFIG_EDAC_ATOMIC_SCRUB=y CONFIG_EDAC_SUPPORT=y CONFIG_EEPROM_AT24=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y CONFIG_EXTCON=y CONFIG_FIXED_PHY=y CONFIG_FIX_EARLYCON_MEM=y CONFIG_FWNODE_MDIO=y CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GCC11_NO_ARRAY_BOUNDS=y CONFIG_GENERIC_ALLOCATOR=y CONFIG_GENERIC_BUG=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -185,7 +199,6 @@ CONFIG_GPIO_CDEV=y CONFIG_GPIO_WATCHDOG=y CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y CONFIG_GRO_CELLS=y -CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDEN_BRANCH_PREDICTOR=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_HAS_DMA=y @@ -217,6 +230,7 @@ CONFIG_IPQ_GCC_4019=y # CONFIG_IPQ_GCC_8074 is not set # CONFIG_IPQ_LCC_806X is not set CONFIG_IRQCHIP=y +CONFIG_IRQSTACKS=y CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS=y @@ -260,10 +274,12 @@ CONFIG_MMC_SDHCI_MSM=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MODULES_USE_ELF_REL=y # CONFIG_MSM_GCC_8660 is not set +# CONFIG_MSM_GCC_8909 is not set # CONFIG_MSM_GCC_8916 is not set # CONFIG_MSM_GCC_8939 is not set # CONFIG_MSM_GCC_8960 is not set # CONFIG_MSM_GCC_8974 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 @@ -296,7 +312,7 @@ CONFIG_NEON=y CONFIG_NET_DEVLINK=y CONFIG_NET_DSA=y CONFIG_NET_DSA_QCA8K_IPQ4019=y -CONFIG_NET_DSA_TAG_IPQ4019=y +CONFIG_NET_DSA_TAG_OOB=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_PTP_CLASSIFY=y CONFIG_NET_SELFTESTS=y @@ -321,9 +337,11 @@ CONFIG_OF_MDIO=y CONFIG_OLD_SIGACTION=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_OPTEE=y -CONFIG_OPTEE_SHM_NUM_PRIV_PAGES=1 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_PCI=y CONFIG_PCIEAER=y CONFIG_PCIEPORTBUS=y @@ -340,6 +358,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHYLINK=y # CONFIG_PHY_QCOM_APQ8064_SATA is not set +# CONFIG_PHY_QCOM_EDP is not set CONFIG_PHY_QCOM_IPQ4019_USB=y # CONFIG_PHY_QCOM_IPQ806X_SATA is not set # CONFIG_PHY_QCOM_IPQ806X_USB is not set @@ -353,37 +372,30 @@ CONFIG_PINCTRL=y # CONFIG_PINCTRL_APQ8064 is not set # CONFIG_PINCTRL_APQ8084 is not set CONFIG_PINCTRL_IPQ4019=y -# CONFIG_PINCTRL_IPQ6018 is not set # CONFIG_PINCTRL_IPQ8064 is not set -# CONFIG_PINCTRL_IPQ8074 is not set # CONFIG_PINCTRL_MDM9615 is not set CONFIG_PINCTRL_MSM=y # CONFIG_PINCTRL_MSM8226 is not set # CONFIG_PINCTRL_MSM8660 is not set +# CONFIG_PINCTRL_MSM8909 is not set # CONFIG_PINCTRL_MSM8916 is not set # CONFIG_PINCTRL_MSM8960 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_QCOM_SPMI_PMIC is not set # CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set -# CONFIG_PINCTRL_QCS404 is not set -# CONFIG_PINCTRL_SC7180 is not set -# CONFIG_PINCTRL_SDM660 is not set -# CONFIG_PINCTRL_SDM845 is not set -# CONFIG_PINCTRL_SM8150 is not set -# CONFIG_PINCTRL_SM8250 is not set +# CONFIG_PINCTRL_SDX65 is not set CONFIG_PM_OPP=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_POWER_RESET_MSM=y CONFIG_POWER_SUPPLY=y CONFIG_PPS=y +CONFIG_PREEMPT_NONE_BUILD=y CONFIG_PRINTK_TIME=y CONFIG_PTP_1588_CLOCK=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_QCA807X_PHY=y +# CONFIG_QCM_DISPCC_2290 is not set +# CONFIG_QCM_GCC_2290 is not set CONFIG_QCOM_A53PLL=y # CONFIG_QCOM_ADM is not set CONFIG_QCOM_BAM_DMA=y @@ -393,6 +405,7 @@ CONFIG_QCOM_BAM_DMA=y # 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_IOMMU is not set CONFIG_QCOM_IPQ4019_ESS_EDMA=y # CONFIG_QCOM_LLCC is not set @@ -405,12 +418,15 @@ CONFIG_QCOM_SCM=y CONFIG_QCOM_SMEM=y # CONFIG_QCOM_SMSM is not set # CONFIG_QCOM_SOCINFO is not set +# CONFIG_QCOM_SPM is not set +# CONFIG_QCOM_STATS is not set CONFIG_QCOM_TCSR=y # CONFIG_QCOM_TSENS 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_RANDSTRUCT_NONE=y CONFIG_RAS=y CONFIG_RATIONAL=y CONFIG_REGMAP=y @@ -429,13 +445,18 @@ CONFIG_RESET_CONTROLLER=y CONFIG_RFS_ACCEL=y CONFIG_RPS=y CONFIG_RTC_CLASS=y +# CONFIG_RTC_DRV_OPTEE is not set CONFIG_RTC_I2C_AND_SPI=y CONFIG_RTC_MC146818_LIB=y CONFIG_RWSEM_SPIN_ON_OWNER=y +# CONFIG_SC_CAMCC_7280 is not set # CONFIG_SC_DISPCC_7180 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_LPASS_CORECC_7180 is not set +# CONFIG_SC_LPASS_CORECC_7280 is not set # CONFIG_SC_MSS_7180 is not set # CONFIG_SC_VIDEOCC_7180 is not set # CONFIG_SDM_CAMCC_845 is not set @@ -445,20 +466,27 @@ CONFIG_RWSEM_SPIN_ON_OWNER=y # CONFIG_SDM_GPUCC_845 is not set # CONFIG_SDM_LPASSCC_845 is not set # CONFIG_SDM_VIDEOCC_845 is not set +# CONFIG_SDX_GCC_65 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_SKB_EXTENSIONS=y CONFIG_SMP=y CONFIG_SMP_ON_UP=y +# CONFIG_SM_CAMCC_8450 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_GPUCC_6350 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_VIDEOCC_8150 is not set # CONFIG_SM_VIDEOCC_8250 is not set CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y CONFIG_SPARSE_IRQ=y CONFIG_SPI=y CONFIG_SPI_BITBANG=y @@ -480,6 +508,7 @@ 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 @@ -504,5 +533,6 @@ 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 From b50827fb105cf770cf86f37a1ec6331c0a138eea Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 14 Aug 2023 12:08:07 +0200 Subject: [PATCH 13/24] ipq40xx: add 6.1 as testing kernel Allow selecting 6.1 as the testing kernel. Signed-off-by: Robert Marko --- target/linux/ipq40xx/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/ipq40xx/Makefile b/target/linux/ipq40xx/Makefile index 53b2f909ae..9af7b7d256 100644 --- a/target/linux/ipq40xx/Makefile +++ b/target/linux/ipq40xx/Makefile @@ -9,6 +9,7 @@ CPU_SUBTYPE:=neon-vfpv4 SUBTARGETS:=generic chromium mikrotik KERNEL_PATCHVER:=5.15 +KERNEL_TESTING_PATCHVER:=6.1 KERNELNAME:=zImage Image dtbs From 98bad1b4fc0d1a42b20eb1d3518f59aa7bb0b2d8 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sun, 17 Sep 2023 22:19:23 +0200 Subject: [PATCH 14/24] ipq40xx: 6.1: add missing secure QFPROM symbol Kernel config for 6.1 on ipq40xx is missing the config for CONFIG_NVMEM_QCOM_SEC_QFPROM which them makes the build stop with a prompt. Symbol is there in 5.15 config but 6.1 config was based of a version that does not yet have it set as it was introduced after the 6.1 PR. So, disable CONFIG_NVMEM_QCOM_SEC_QFPROM to fix building on 6.1. Fixes: 825cfa4e36cb ("ipq40xx: 6.1: refresh kernel config") Signed-off-by: Robert Marko --- target/linux/ipq40xx/config-6.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/ipq40xx/config-6.1 b/target/linux/ipq40xx/config-6.1 index 1fbc33103a..2619f3f87c 100644 --- a/target/linux/ipq40xx/config-6.1 +++ b/target/linux/ipq40xx/config-6.1 @@ -324,6 +324,7 @@ CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=4 CONFIG_NVMEM=y CONFIG_NVMEM_QCOM_QFPROM=y +# CONFIG_NVMEM_QCOM_SEC_QFPROM is not set # CONFIG_NVMEM_SPMI_SDAM is not set CONFIG_NVMEM_SYSFS=y CONFIG_OF=y From 794349a28a7b9036b54e13487a96120609db924e Mon Sep 17 00:00:00 2001 From: Max Qian Date: Thu, 14 Sep 2023 21:54:30 -0700 Subject: [PATCH 15/24] ramips: RT1800: fix invalid octal number error This commit removes the padded zeros in the date formatting. The padded zeros from the date command causes the numbers to be interpreted as an octal number by printf. Months, days, and years with the number 08 or 09 raise an error in printf as an "invalid octal number" and get interpreted as a zero. Signed-off-by: Max Qian --- target/linux/ramips/image/mt7621.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index abcdc08ade..065a61de28 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -119,7 +119,7 @@ define Build/belkin-header ( \ type_fw_date=$$(printf "01%02x%02x%02x" \ - $$(date -d "@$(SOURCE_DATE_EPOCH)" "+%y %m %d")); \ + $$(date -d "@$(SOURCE_DATE_EPOCH)" "+%-y %-m %-d")); \ hw_fw_ver=$$(printf "%02x%02x%02x%02x" \ $(hw_ver) $$(echo $(fw_ver) | cut -d. -f-3 | tr . ' ')); \ fw_len_crc=$$(gzip -c $@ | tail -c 8 | od -An -tx8 | tr -d ' \n'); \ From 12584395dc5d45333df298554ff73a8b9495e119 Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Sat, 2 Sep 2023 00:18:18 +0200 Subject: [PATCH 16/24] sunxi: add support for H616 SoC and Orangepi Zero 2 Specifications: SoC: Allwinner H616 @ 1.5 Ghz DRAM: 1Gb LPDDR3 Power: 5V USB-C Video: HDMI (Type 2.0A - micro) Network: 10/100/1000Mbps Ethernet (Realtek RTL8211F), AW859A BT+wifi Storage: microSD / 2Mb SPI flash USB: 1 USB2.0 Host Debug Serial UART Flashing instructions: Standard sunxi SD card installation procedure - copy image to SD card, insert into SD card slot on the device and boot. Signed-off-by: Zoltan HERPAI --- .../boot/arm-trusted-firmware-sunxi/Makefile | 8 +- package/boot/uboot-sunxi/Makefile | 10 + package/boot/uboot-sunxi/uEnv-h616.txt | 7 + target/linux/sunxi/cortexa53/config-6.1 | 4 +- target/linux/sunxi/image/cortexa53.mk | 12 ++ ...dings-usb-Add-H616-compatible-string.patch | 43 ++++ ...Add-special-clock-for-Allwinner-H616.patch | 82 ++++++++ ...m64-dts-allwinner-h616-Add-USB-nodes.patch | 190 ++++++++++++++++++ ...ner-h616-OrangePi-Zero-2-Add-USB-nod.patch | 84 ++++++++ 9 files changed, 438 insertions(+), 2 deletions(-) create mode 100644 package/boot/uboot-sunxi/uEnv-h616.txt create mode 100644 target/linux/sunxi/patches-6.1/460-dt-bindings-usb-Add-H616-compatible-string.patch create mode 100644 target/linux/sunxi/patches-6.1/461-dt-bindings-phy-Add-special-clock-for-Allwinner-H616.patch create mode 100644 target/linux/sunxi/patches-6.1/462-arm64-dts-allwinner-h616-Add-USB-nodes.patch create mode 100644 target/linux/sunxi/patches-6.1/463-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch diff --git a/package/boot/arm-trusted-firmware-sunxi/Makefile b/package/boot/arm-trusted-firmware-sunxi/Makefile index 0535640f95..c9d5668122 100644 --- a/package/boot/arm-trusted-firmware-sunxi/Makefile +++ b/package/boot/arm-trusted-firmware-sunxi/Makefile @@ -36,9 +36,15 @@ define Trusted-Firmware-A/sunxi-h6 PLAT:=sun50i_h6 endef +define Trusted-Firmware-A/sunxi-h616 + NAME:=Allwinner H616 + PLAT:=sun50i_h616 +endef + TFA_TARGETS:= \ sunxi-a64 \ - sunxi-h6 + sunxi-h6 \ + sunxi-h616 define Package/trusted-firmware-a/install $(INSTALL_DIR) $(STAGING_DIR_IMAGE) diff --git a/package/boot/uboot-sunxi/Makefile b/package/boot/uboot-sunxi/Makefile index be4c8411a9..e141eb7af7 100644 --- a/package/boot/uboot-sunxi/Makefile +++ b/package/boot/uboot-sunxi/Makefile @@ -328,6 +328,15 @@ define U-Boot/orangepi_pc2 ATF:=a64 endef +define U-Boot/orangepi_zero2 + BUILD_SUBTARGET:=cortexa53 + NAME:=Xunlong Orange Pi Zero2 + BUILD_DEVICES:=xunlong_orangepi-zero2 + DEPENDS:=+PACKAGE_u-boot-orangepi_zero2:trusted-firmware-a-sunxi-h616 + UENV:=h616 + ATF:=h616 +endef + define U-Boot/Bananapi_M2_Ultra BUILD_SUBTARGET:=cortexa7 NAME:=Bananapi M2 Ultra @@ -382,6 +391,7 @@ UBOOT_TARGETS := \ orangepi_plus \ orangepi_2 \ orangepi_pc2 \ + orangepi_zero2 \ pangolin \ pine64_plus \ Sinovoip_BPI_M3 \ diff --git a/package/boot/uboot-sunxi/uEnv-h616.txt b/package/boot/uboot-sunxi/uEnv-h616.txt new file mode 100644 index 0000000000..78810ff223 --- /dev/null +++ b/package/boot/uboot-sunxi/uEnv-h616.txt @@ -0,0 +1,7 @@ +setenv mmc_rootpart 2 +part uuid mmc ${mmc_bootdev}:${mmc_rootpart} uuid +setenv loadkernel fatload mmc \$mmc_bootdev \$kernel_addr_r uImage +setenv loaddtb fatload mmc \$mmc_bootdev \$fdt_addr_r dtb +setenv bootargs console=ttyS0,115200 earlyprintk root=PARTUUID=${uuid} rootwait +setenv uenvcmd run loadkernel \&\& run loaddtb \&\& booti \$kernel_addr_r - \$fdt_addr_r +run uenvcmd diff --git a/target/linux/sunxi/cortexa53/config-6.1 b/target/linux/sunxi/cortexa53/config-6.1 index 54453d75ec..f57c664540 100644 --- a/target/linux/sunxi/cortexa53/config-6.1 +++ b/target/linux/sunxi/cortexa53/config-6.1 @@ -66,6 +66,8 @@ CONFIG_PINCTRL_SUN50I_A64_R=y CONFIG_PINCTRL_SUN50I_H5=y CONFIG_PINCTRL_SUN50I_H6=y CONFIG_PINCTRL_SUN50I_H6_R=y +CONFIG_PINCTRL_SUN50I_H616=y +CONFIG_PINCTRL_SUN50I_H616_R=y # CONFIG_PREEMPT_DYNAMIC is not set CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y @@ -83,7 +85,7 @@ CONFIG_SUN50I_A100_R_CCU=y CONFIG_SUN50I_A64_CCU=y CONFIG_SUN50I_DE2_BUS=y CONFIG_SUN50I_ERRATUM_UNKNOWN1=y -# CONFIG_SUN50I_H616_CCU is not set +CONFIG_SUN50I_H616_CCU=y CONFIG_SUN50I_H6_CCU=y CONFIG_SUN50I_H6_R_CCU=y # CONFIG_SUN6I_RTC_CCU is not set diff --git a/target/linux/sunxi/image/cortexa53.mk b/target/linux/sunxi/image/cortexa53.mk index a00bac2c81..80718b34bf 100644 --- a/target/linux/sunxi/image/cortexa53.mk +++ b/target/linux/sunxi/image/cortexa53.mk @@ -24,6 +24,11 @@ define Device/sun50i-h6 $(Device/sun50i) endef +define Device/sun50i-h616 + SOC := sun50i-h616 + $(Device/sun50i) +endef + define Device/friendlyarm_nanopi-neo-plus2 DEVICE_VENDOR := FriendlyARM DEVICE_MODEL := NanoPi NEO Plus2 @@ -108,6 +113,13 @@ define Device/xunlong_orangepi-pc2 endef TARGET_DEVICES += xunlong_orangepi-pc2 +define Device/xunlong_orangepi-zero2 + DEVICE_VENDOR := Xunlong + DEVICE_MODEL := Orange Pi Zero 2 + $(Device/sun50i-h616) +endef +TARGET_DEVICES += xunlong_orangepi-zero2 + define Device/xunlong_orangepi-zero-plus DEVICE_VENDOR := Xunlong DEVICE_MODEL := Orange Pi Zero Plus diff --git a/target/linux/sunxi/patches-6.1/460-dt-bindings-usb-Add-H616-compatible-string.patch b/target/linux/sunxi/patches-6.1/460-dt-bindings-usb-Add-H616-compatible-string.patch new file mode 100644 index 0000000000..929b567e67 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/460-dt-bindings-usb-Add-H616-compatible-string.patch @@ -0,0 +1,43 @@ +From e4045c8125d88a9eb8b4f8f74b5c7955d5d9adc0 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Thu, 17 Jun 2021 10:54:22 +0100 +Subject: [PATCH 5000/5006] dt-bindings: usb: Add H616 compatible string + +The Allwinner H616 contains four fully OHCI/EHCI compatible USB host +controllers, so just add their compatible strings to the list of +generic OHCI/EHCI controllers. + +Signed-off-by: Andre Przywara +Acked-by: Krzysztof Kozlowski +--- + Documentation/devicetree/bindings/usb/generic-ehci.yaml | 1 + + Documentation/devicetree/bindings/usb/generic-ohci.yaml | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml +index c5f629c5bc61..994818cb6044 100644 +--- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml ++++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml +@@ -30,6 +30,7 @@ properties: + - allwinner,sun4i-a10-ehci + - allwinner,sun50i-a64-ehci + - allwinner,sun50i-h6-ehci ++ - allwinner,sun50i-h616-ehci + - allwinner,sun5i-a13-ehci + - allwinner,sun6i-a31-ehci + - allwinner,sun7i-a20-ehci +diff --git a/Documentation/devicetree/bindings/usb/generic-ohci.yaml b/Documentation/devicetree/bindings/usb/generic-ohci.yaml +index f838f78d6164..4fcbd0add49d 100644 +--- a/Documentation/devicetree/bindings/usb/generic-ohci.yaml ++++ b/Documentation/devicetree/bindings/usb/generic-ohci.yaml +@@ -20,6 +20,7 @@ properties: + - allwinner,sun4i-a10-ohci + - allwinner,sun50i-a64-ohci + - allwinner,sun50i-h6-ohci ++ - allwinner,sun50i-h616-ohci + - allwinner,sun5i-a13-ohci + - allwinner,sun6i-a31-ohci + - allwinner,sun7i-a20-ohci +-- +2.20.1 + diff --git a/target/linux/sunxi/patches-6.1/461-dt-bindings-phy-Add-special-clock-for-Allwinner-H616.patch b/target/linux/sunxi/patches-6.1/461-dt-bindings-phy-Add-special-clock-for-Allwinner-H616.patch new file mode 100644 index 0000000000..2cd3acce2c --- /dev/null +++ b/target/linux/sunxi/patches-6.1/461-dt-bindings-phy-Add-special-clock-for-Allwinner-H616.patch @@ -0,0 +1,82 @@ +From e2078ae0c559b6ac91db19262b56d8cf334354cb Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 12 Sep 2022 00:03:22 +0100 +Subject: [PATCH 5001/5006] dt-bindings: phy: Add special clock for Allwinner + H616 PHY + +The USB PHY IP in the Allwinner H616 SoC requires a quirk that involves +some resources from port 2's PHY and HCI IP. In particular the PMU clock +for port 2 must be surely ungated before accessing the REG_HCI_PHY_CTL +register of port 2. To allow each USB port to be controlled +independently of port 2, we need a handle to that particular PMU clock +in the *PHY* node, as the HCI and PHY part might be handled by separate +drivers. + +Add that clock to the requirements of the H616 PHY binding, so that a +PHY driver can apply the quirk in isolation, without requiring help from +port 2's HCI driver. + +Signed-off-by: Andre Przywara +--- + .../phy/allwinner,sun8i-h3-usb-phy.yaml | 26 +++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml +index 77539b4601c2..2df012d13655 100644 +--- a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml ++++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml +@@ -36,18 +36,22 @@ properties: + - const: pmu3 + + clocks: ++ minItems: 4 + items: + - description: USB OTG PHY bus clock + - description: USB Host 0 PHY bus clock + - description: USB Host 1 PHY bus clock + - description: USB Host 2 PHY bus clock ++ - description: PMU clock for host port 2 + + clock-names: ++ minItems: 4 + items: + - const: usb0_phy + - const: usb1_phy + - const: usb2_phy + - const: usb3_phy ++ - const: pmu2_clk + + resets: + items: +@@ -96,6 +100,28 @@ required: + - resets + - reset-names + ++allOf: ++ - if: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - allwinner,sun50i-h616-usb-phy ++ then: ++ properties: ++ clocks: ++ minItems: 5 ++ ++ clock-names: ++ minItems: 5 ++ else: ++ properties: ++ clocks: ++ maxItems: 4 ++ ++ clock-names: ++ maxItems: 4 ++ + additionalProperties: false + + examples: +-- +2.20.1 + diff --git a/target/linux/sunxi/patches-6.1/462-arm64-dts-allwinner-h616-Add-USB-nodes.patch b/target/linux/sunxi/patches-6.1/462-arm64-dts-allwinner-h616-Add-USB-nodes.patch new file mode 100644 index 0000000000..5d626a014e --- /dev/null +++ b/target/linux/sunxi/patches-6.1/462-arm64-dts-allwinner-h616-Add-USB-nodes.patch @@ -0,0 +1,190 @@ +From 4cfd9d9350a57fc3ced240dbf61ca2f444283c50 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Wed, 16 Jun 2021 18:20:47 +0100 +Subject: [PATCH 5004/5006] arm64: dts: allwinner: h616: Add USB nodes + +Add the nodes for the MUSB and the four USB host controllers to the SoC +.dtsi, along with the PHY node needed to bind all of them together. + +EHCI/OHCI and MUSB are compatible to previous SoCs, but the PHY requires +some quirks (handled in the driver). + +Signed-off-by: Andre Przywara +--- + .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 160 ++++++++++++++++++ + 1 file changed, 160 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +index 622a1f7d1641..74aed0d232a9 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +@@ -504,6 +504,166 @@ + }; + }; + ++ usbotg: usb@5100000 { ++ compatible = "allwinner,sun50i-h616-musb", ++ "allwinner,sun8i-h3-musb"; ++ reg = <0x05100000 0x0400>; ++ clocks = <&ccu CLK_BUS_OTG>; ++ resets = <&ccu RST_BUS_OTG>; ++ interrupts = ; ++ interrupt-names = "mc"; ++ phys = <&usbphy 0>; ++ phy-names = "usb"; ++ extcon = <&usbphy 0>; ++ status = "disabled"; ++ }; ++ ++ usbphy: phy@5100400 { ++ compatible = "allwinner,sun50i-h616-usb-phy"; ++ reg = <0x05100400 0x24>, ++ <0x05101800 0x14>, ++ <0x05200800 0x14>, ++ <0x05310800 0x14>, ++ <0x05311800 0x14>; ++ reg-names = "phy_ctrl", ++ "pmu0", ++ "pmu1", ++ "pmu2", ++ "pmu3"; ++ clocks = <&ccu CLK_USB_PHY0>, ++ <&ccu CLK_USB_PHY1>, ++ <&ccu CLK_USB_PHY2>, ++ <&ccu CLK_USB_PHY3>, ++ <&ccu CLK_BUS_EHCI2>; ++ clock-names = "usb0_phy", ++ "usb1_phy", ++ "usb2_phy", ++ "usb3_phy", ++ "pmu2_clk"; ++ resets = <&ccu RST_USB_PHY0>, ++ <&ccu RST_USB_PHY1>, ++ <&ccu RST_USB_PHY2>, ++ <&ccu RST_USB_PHY3>; ++ reset-names = "usb0_reset", ++ "usb1_reset", ++ "usb2_reset", ++ "usb3_reset"; ++ status = "disabled"; ++ #phy-cells = <1>; ++ }; ++ ++ ehci0: usb@5101000 { ++ compatible = "allwinner,sun50i-h616-ehci", ++ "generic-ehci"; ++ reg = <0x05101000 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI0>, ++ <&ccu CLK_BUS_EHCI0>, ++ <&ccu CLK_USB_OHCI0>; ++ resets = <&ccu RST_BUS_OHCI0>, ++ <&ccu RST_BUS_EHCI0>; ++ phys = <&usbphy 0>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci0: usb@5101400 { ++ compatible = "allwinner,sun50i-h616-ohci", ++ "generic-ohci"; ++ reg = <0x05101400 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI0>, ++ <&ccu CLK_USB_OHCI0>; ++ resets = <&ccu RST_BUS_OHCI0>; ++ phys = <&usbphy 0>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ehci1: usb@5200000 { ++ compatible = "allwinner,sun50i-h616-ehci", ++ "generic-ehci"; ++ reg = <0x05200000 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI1>, ++ <&ccu CLK_BUS_EHCI1>, ++ <&ccu CLK_USB_OHCI1>; ++ resets = <&ccu RST_BUS_OHCI1>, ++ <&ccu RST_BUS_EHCI1>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci1: usb@5200400 { ++ compatible = "allwinner,sun50i-h616-ohci", ++ "generic-ohci"; ++ reg = <0x05200400 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI1>, ++ <&ccu CLK_USB_OHCI1>; ++ resets = <&ccu RST_BUS_OHCI1>; ++ phys = <&usbphy 1>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ehci2: usb@5310000 { ++ compatible = "allwinner,sun50i-h616-ehci", ++ "generic-ehci"; ++ reg = <0x05310000 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI2>, ++ <&ccu CLK_BUS_EHCI2>, ++ <&ccu CLK_USB_OHCI2>; ++ resets = <&ccu RST_BUS_OHCI2>, ++ <&ccu RST_BUS_EHCI2>; ++ phys = <&usbphy 2>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci2: usb@5310400 { ++ compatible = "allwinner,sun50i-h616-ohci", ++ "generic-ohci"; ++ reg = <0x05310400 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI2>, ++ <&ccu CLK_USB_OHCI2>; ++ resets = <&ccu RST_BUS_OHCI2>; ++ phys = <&usbphy 2>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ehci3: usb@5311000 { ++ compatible = "allwinner,sun50i-h616-ehci", ++ "generic-ehci"; ++ reg = <0x05311000 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI3>, ++ <&ccu CLK_BUS_EHCI3>, ++ <&ccu CLK_USB_OHCI3>; ++ resets = <&ccu RST_BUS_OHCI3>, ++ <&ccu RST_BUS_EHCI3>; ++ phys = <&usbphy 3>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ ++ ohci3: usb@5311400 { ++ compatible = "allwinner,sun50i-h616-ohci", ++ "generic-ohci"; ++ reg = <0x05311400 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_OHCI3>, ++ <&ccu CLK_USB_OHCI3>; ++ resets = <&ccu RST_BUS_OHCI3>; ++ phys = <&usbphy 3>; ++ phy-names = "usb"; ++ status = "disabled"; ++ }; ++ + rtc: rtc@7000000 { + compatible = "allwinner,sun50i-h616-rtc"; + reg = <0x07000000 0x400>; +-- +2.20.1 + diff --git a/target/linux/sunxi/patches-6.1/463-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch b/target/linux/sunxi/patches-6.1/463-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch new file mode 100644 index 0000000000..d3460c54e6 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/463-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch @@ -0,0 +1,84 @@ +From 1bc12a9ae690a22a525f9b71778022bb4533fec1 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Wed, 16 Jun 2021 18:32:36 +0100 +Subject: [PATCH 5005/5006] arm64: dts: allwinner: h616: OrangePi Zero 2: Add + USB nodes + +The OrangePi Zero 2 has one USB-A host port, VBUS is provided by +a GPIO controlled regulator. +The USB-C port is meant to power the board, but is also connected to +the USB 0 port, which we configure as an MUSB peripheral. + +Signed-off-by: Andre Przywara +--- + .../allwinner/sun50i-h616-orangepi-zero2.dts | 41 +++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts +index 02893f3ac99d..cb8600d0ea1e 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts +@@ -49,8 +49,24 @@ + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; ++ ++ reg_usb1_vbus: regulator-usb1-vbus { ++ compatible = "regulator-fixed"; ++ regulator-name = "usb1-vbus"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <®_vcc5v>; ++ enable-active-high; ++ gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */ ++ }; + }; + ++&ehci1 { ++ status = "okay"; ++}; ++ ++/* USB 2 & 3 are on headers only. */ ++ + &emac0 { + pinctrl-names = "default"; + pinctrl-0 = <&ext_rgmii_pins>; +@@ -76,6 +92,10 @@ + status = "okay"; + }; + ++&ohci1 { ++ status = "okay"; ++}; ++ + &r_rsb { + status = "okay"; + +@@ -211,3 +231,24 @@ + pinctrl-0 = <&uart0_ph_pins>; + status = "okay"; + }; ++ ++&usbotg { ++ /* ++ * PHY0 pins are connected to a USB-C socket, but a role switch ++ * is not implemented: both CC pins are pulled to GND. ++ * The VBUS pins power the device, so a fixed peripheral mode ++ * is the best choice. ++ * The board can be powered via GPIOs, in this case port0 *can* ++ * act as a host (with a cable/adapter ignoring CC), as VBUS is ++ * then provided by the GPIOs. Any user of this setup would ++ * need to adjust the DT accordingly: dr_mode set to "host", ++ * enabling OHCI0 and EHCI0. ++ */ ++ dr_mode = "peripheral"; ++ status = "okay"; ++}; ++ ++&usbphy { ++ usb1_vbus-supply = <®_usb1_vbus>; ++ status = "okay"; ++}; +-- +2.20.1 + From a9cc3708e0c3c4869711a9ba4b9c1437ed250721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=B6hler?= Date: Tue, 12 Sep 2023 19:57:55 +0200 Subject: [PATCH 17/24] ipq40xx: fix image building for ZTE MF287 series MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the ZTE MF287 series, a special recovery image is built. The Makefile worked fine on snapshot, but created corrupt images on the 23.05 images. By using the appropriate variable, this should be fixed. Signed-off-by: Andreas Böhler --- target/linux/ipq40xx/image/generic.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ipq40xx/image/generic.mk b/target/linux/ipq40xx/image/generic.mk index 29778156df..8fd7ab2915 100644 --- a/target/linux/ipq40xx/image/generic.mk +++ b/target/linux/ipq40xx/image/generic.mk @@ -1162,7 +1162,7 @@ define Device/zte_mf287_common # exploit for the web interface IMAGES += factory.bin recovery.bin IMAGE/factory.bin := append-ubi - IMAGE/recovery.bin := append-squashfs4-fakeroot | sysupgrade-tar kernel=$$$$(BIN_DIR)/openwrt-$$(BOARD)$$(if $$(SUBTARGET),-$$(SUBTARGET))-$$(DEVICE_NAME)-initramfs-zImage.itb rootfs=$$$$@ | append-metadata + IMAGE/recovery.bin := append-squashfs4-fakeroot | sysupgrade-tar kernel=$$$$(BIN_DIR)/$$(KERNEL_INITRAMFS_IMAGE) rootfs=$$$$@ | append-metadata endef define Device/zte_mf287plus From eb8ddf5d5c9df9e3ca97c12ee2e7685ffc4c88be Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Sun, 17 Sep 2023 23:18:05 +0800 Subject: [PATCH 18/24] ipq-wifi: update to version 2023-09-16 Contains following updates: * ipq8074: add Asus RT-AX89X BDF * ipq8074: update RegDB in new submitted BDF * ipq40xx: add YYeTs LE1 BDF * ipq8074: add Netgear WAX620 * qca-wireless: ipq40xx: add BDFs for ZTE MF287 * ipq8174: Add Linksys MX4200 Signed-off-by: Chukun Pan --- package/firmware/ipq-wifi/Makefile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/package/firmware/ipq-wifi/Makefile b/package/firmware/ipq-wifi/Makefile index aa1466418e..e65afbdd14 100644 --- a/package/firmware/ipq-wifi/Makefile +++ b/package/firmware/ipq-wifi/Makefile @@ -2,13 +2,13 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/version.mk PKG_NAME:=ipq-wifi -PKG_RELEASE:=2 +PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware/qca-wireless.git -PKG_SOURCE_DATE:=2023-06-03 -PKG_SOURCE_VERSION:=cd9c30ca47b8e5388b770c523a7f6b8b969e2f92 -PKG_MIRROR_HASH:=45e623fcc512b514ade0f22e217275536aa8de4afba7dfdb11696482b8fa71a2 +PKG_SOURCE_DATE:=2023-09-16 +PKG_SOURCE_VERSION:=57aa1b1562ac60f11a6bec8be02cd3b68b12b3fa +PKG_MIRROR_HASH:=f8f9ab78ae85180a6e601d7c911d6c350b0cc132172d4baefc8f9fe07566ce0f PKG_FLAGS:=nonshared @@ -41,6 +41,7 @@ ALLWIFIBOARDS:= \ wallys_dr40x9 \ xiaomi_ax3600 \ xiaomi_ax9000 \ + yyets_le1 \ zte_mf289f \ zte_mf287plus \ zyxel_nbg7815 @@ -130,6 +131,7 @@ $(eval $(call generate-ipq-wifi-package,redmi_ax6,Redmi AX6)) $(eval $(call generate-ipq-wifi-package,wallys_dr40x9,Wallys DR40X9)) $(eval $(call generate-ipq-wifi-package,xiaomi_ax3600,Xiaomi AX3600)) $(eval $(call generate-ipq-wifi-package,xiaomi_ax9000,Xiaomi AX9000)) +$(eval $(call generate-ipq-wifi-package,yyets_le1,YYeTs LE1)) $(eval $(call generate-ipq-wifi-package,zte_mf289f,ZTE MF289F)) $(eval $(call generate-ipq-wifi-package,zte_mf287plus,ZTE MF287Plus)) $(eval $(call generate-ipq-wifi-package,zyxel_nbg7815,Zyxel NBG7815)) From 9889de3397acc0b0ca4d1f0d42a8f7321c7f5ba0 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Wed, 3 May 2023 23:18:48 +0800 Subject: [PATCH 19/24] ipq40xx: add support for YYeTs LE1 Hardware Highlights: SoC: Qualcomm IPQ4019 717 MHz RAM: 512M NT5CC256M16ER-EK Flash: 32M SPI NOR MX25L25635F WIFI1: 2.4 GHz 2T2R integrated WIFI2: 5 GHz 2T2R integrated Ethernet: QCA8075 (4x LAN, 1x WAN) LEDS: power, wlan2g, wlan5g, usb USB: 1x 3.0 Button: Reset Installation: Upload factory.bin in stock firmware's upgrade page, and this will take a few minutes. Signed-off-by: Chukun Pan --- .../ipq40xx/base-files/etc/board.d/02_network | 1 + .../arch/arm/boot/dts/qcom-ipq4019-le1.dts | 326 ++++++++++++++++++ target/linux/ipq40xx/image/generic.mk | 14 + 3 files changed, 341 insertions(+) create mode 100644 target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-le1.dts diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network index 614afa8590..5353cd398d 100644 --- a/target/linux/ipq40xx/base-files/etc/board.d/02_network +++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network @@ -25,6 +25,7 @@ ipq40xx_setup_interfaces() p2w,r619ac-128m|\ pakedge,wr-1|\ teltonika,rutx50|\ + yyets,le1|\ zyxel,nbg6617) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" ;; diff --git a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-le1.dts b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-le1.dts new file mode 100644 index 0000000000..282a0eaaa6 --- /dev/null +++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-le1.dts @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq4019.dtsi" +#include +#include +#include + +/ { + model = "YYeTs LE1"; + compatible = "yyets,le1"; + + aliases { + led-boot = &led_usb; + led-failsafe = &led_usb; + led-upgrade = &led_usb; + + ethernet0 = &swport5; + ethernet1 = &gmac; + label-mac-device = &gmac; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&tlmm 18 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_usb: usb { + label = "green:usb"; + gpios = <&tlmm 36 GPIO_ACTIVE_LOW>; + linux,default-trigger = "usbport"; + trigger-sources = <&usb3_port1>, <&usb3_port2>, <&usb2_port1>; + }; + + wlan2g { + label = "green:wlan2g"; + gpios = <&tlmm 32 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + + wlan5g { + label = "green:wlan5g"; + gpios = <&tlmm 50 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy1tpt"; + }; + }; + + soc { + tcsr@1949000 { + compatible = "qcom,tcsr"; + reg = <0x1949000 0x100>; + qcom,wifi_glb_cfg = ; + }; + + tcsr@194b000 { + compatible = "qcom,tcsr"; + reg = <0x194b000 0x100>; + qcom,usb-hsphy-mode-select = ; + }; + + ess_tcsr@1953000 { + compatible = "qcom,tcsr"; + reg = <0x1953000 0x1000>; + qcom,ess-interface-select = ; + }; + + tcsr@1957000 { + compatible = "qcom,tcsr"; + reg = <0x1957000 0x100>; + qcom,wifi_noc_memtype_m0_m2 = ; + }; + }; +}; + +&blsp_dma { + status = "okay"; +}; + +&blsp1_spi1 { + cs-gpios = <&tlmm 12 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&spi_0_pins>; + pinctrl-names = "default"; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <24000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SBL1"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "MIBIB"; + reg = <0x40000 0x20000>; + read-only; + }; + + partition@60000 { + label = "QSEE"; + reg = <0x60000 0x60000>; + read-only; + }; + + partition@c0000 { + label = "CDT"; + reg = <0xc0000 0x10000>; + read-only; + }; + + partition@d0000 { + label = "DDRPARAMS"; + reg = <0xd0000 0x10000>; + read-only; + }; + + partition@e0000 { + label = "APPSBLENV"; + reg = <0xe0000 0x10000>; + read-only; + }; + + partition@f0000 { + label = "APPSBL"; + reg = <0xf0000 0x80000>; + read-only; + }; + + partition@170000 { + label = "ART"; + reg = <0x170000 0x10000>; + read-only; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + precal_art_1000: precal@1000 { + reg = <0x1000 0x2f20>; + }; + + precal_art_5000: precal@5000 { + reg = <0x5000 0x2f20>; + }; + }; + + partition@180000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x180000 0x1e80000>; + }; + }; + }; +}; + +&blsp1_uart1 { + pinctrl-0 = <&serial_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&cryptobam { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&gmac { + status = "okay"; +}; + +&mdio { + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&prng { + status = "okay"; +}; + +&switch { + status = "okay"; +}; + +&swport1 { + status = "okay"; +}; + +&swport2 { + status = "okay"; +}; + +&swport3 { + status = "okay"; +}; + +&swport4 { + status = "okay"; +}; + +&swport5 { + status = "okay"; +}; + +&tlmm { + mdio_pins: mdio_pinmux { + mux_1 { + pins = "gpio6"; + function = "mdio"; + bias-pull-up; + }; + mux_2 { + pins = "gpio7"; + function = "mdc"; + bias-pull-up; + }; + }; + + serial_pins: serial_pinmux { + mux { + pins = "gpio16", "gpio17"; + function = "blsp_uart0"; + bias-disable; + }; + }; + + spi_0_pins: spi_0_pinmux { + pinmux { + function = "blsp_spi0"; + pins = "gpio13", "gpio14", "gpio15"; + drive-strength = <12>; + bias-disable; + }; + + pinmux_cs { + function = "gpio"; + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; +}; + +&usb2 { + status = "okay"; + + dwc3@6000000 { + #address-cells = <1>; + #size-cells = <0>; + + usb2_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + }; +}; + +&usb2_hs_phy { + status = "okay"; +}; + +&usb3 { + status = "okay"; + + dwc3@8a00000 { + #address-cells = <1>; + #size-cells = <0>; + + usb3_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + usb3_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; + }; +}; + +&usb3_hs_phy { + status = "okay"; +}; + +&usb3_ss_phy { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&wifi0 { + status = "okay"; + nvmem-cells = <&precal_art_1000>; + nvmem-cell-names = "pre-calibration"; + qcom,ath10k-calibration-variant = "YYeTs-LE1"; +}; + +&wifi1 { + status = "okay"; + nvmem-cells = <&precal_art_5000>; + nvmem-cell-names = "pre-calibration"; + qcom,ath10k-calibration-variant = "YYeTs-LE1"; +}; diff --git a/target/linux/ipq40xx/image/generic.mk b/target/linux/ipq40xx/image/generic.mk index 8fd7ab2915..6dd4549f8d 100644 --- a/target/linux/ipq40xx/image/generic.mk +++ b/target/linux/ipq40xx/image/generic.mk @@ -1122,6 +1122,20 @@ define Device/wallys_dr40x9 endef TARGET_DEVICES += wallys_dr40x9 +define Device/yyets_le1 + $(call Device/FitzImage) + DEVICE_VENDOR := YYeTs + DEVICE_MODEL := LE1 + SOC := qcom-ipq4019 + KERNEL_SIZE := 4096k + IMAGE_SIZE := 31232k + IMAGES += factory.bin + IMAGE/factory.bin := qsdk-ipq-factory-nor | check-size + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata + DEVICE_PACKAGES := ipq-wifi-yyets_le1 kmod-usb-ledtrig-usbport +endef +TARGET_DEVICES += yyets_le1 + define Device/zte_mf18a $(call Device/FitImage) DEVICE_VENDOR := ZTE From 13b24340d7f2e1117373b0db8ff878b6f1865ae9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 18 Sep 2023 12:50:45 +0200 Subject: [PATCH 20/24] mac80211: backport upstream patch required for mt76 update Signed-off-by: Felix Fietkau --- ...lify-ath11k_mac_validate_vht_he_fixe.patch | 4 +- ...Consistently-use-ath11k_vif_to_arvif.patch | 16 +- ...notate-iftype_data-pointer-with-spar.patch | 467 ++++++++++++++++++ 3 files changed, 477 insertions(+), 10 deletions(-) create mode 100644 package/kernel/mac80211/patches/subsys/312-wifi-cfg80211-annotate-iftype_data-pointer-with-spar.patch diff --git a/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-simplify-ath11k_mac_validate_vht_he_fixe.patch b/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-simplify-ath11k_mac_validate_vht_he_fixe.patch index 2bdde1c72f..ad761e6a90 100644 --- a/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-simplify-ath11k_mac_validate_vht_he_fixe.patch +++ b/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-simplify-ath11k_mac_validate_vht_he_fixe.patch @@ -18,7 +18,7 @@ Link: https://lore.kernel.org/r/20230726092113.78794-1-dmantipov@yandex.ru --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c -@@ -8255,7 +8255,7 @@ ath11k_mac_validate_vht_he_fixed_rate_se +@@ -8258,7 +8258,7 @@ ath11k_mac_validate_vht_he_fixed_rate_se const struct cfg80211_bitrate_mask *mask) { bool he_fixed_rate = false, vht_fixed_rate = false; @@ -27,7 +27,7 @@ Link: https://lore.kernel.org/r/20230726092113.78794-1-dmantipov@yandex.ru const u16 *vht_mcs_mask, *he_mcs_mask; struct ieee80211_link_sta *deflink; u8 vht_nss, he_nss; -@@ -8278,7 +8278,7 @@ ath11k_mac_validate_vht_he_fixed_rate_se +@@ -8281,7 +8281,7 @@ ath11k_mac_validate_vht_he_fixed_rate_se rcu_read_lock(); spin_lock_bh(&ar->ab->base_lock); diff --git a/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-Consistently-use-ath11k_vif_to_arvif.patch b/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-Consistently-use-ath11k_vif_to_arvif.patch index cc54b89441..218b3ac35f 100644 --- a/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-Consistently-use-ath11k_vif_to_arvif.patch +++ b/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-Consistently-use-ath11k_vif_to_arvif.patch @@ -231,7 +231,7 @@ Link: https://lore.kernel.org/r/20230821-ath11k_vif_to_arvif-v1-1-fa2c3b60b5cf@q struct wmi_wmm_params_arg *p = NULL; int ret; -@@ -6455,7 +6455,7 @@ static int ath11k_mac_setup_vdev_params_ +@@ -6458,7 +6458,7 @@ static int ath11k_mac_setup_vdev_params_ return 0; } @@ -240,7 +240,7 @@ Link: https://lore.kernel.org/r/20230821-ath11k_vif_to_arvif-v1-1-fa2c3b60b5cf@q if (arvif->vif->bss_conf.nontransmitted) { if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) -@@ -7408,7 +7408,7 @@ ath11k_mac_update_vif_chan(struct ath11k +@@ -7411,7 +7411,7 @@ ath11k_mac_update_vif_chan(struct ath11k /* TODO: Update ar->rx_channel */ for (i = 0; i < n_vifs; i++) { @@ -249,7 +249,7 @@ Link: https://lore.kernel.org/r/20230821-ath11k_vif_to_arvif-v1-1-fa2c3b60b5cf@q if (WARN_ON(!arvif->is_started)) continue; -@@ -7450,7 +7450,7 @@ ath11k_mac_update_vif_chan(struct ath11k +@@ -7453,7 +7453,7 @@ ath11k_mac_update_vif_chan(struct ath11k mbssid_tx_vif = arvif->vif->mbssid_tx_vif; if (mbssid_tx_vif) @@ -258,7 +258,7 @@ Link: https://lore.kernel.org/r/20230821-ath11k_vif_to_arvif-v1-1-fa2c3b60b5cf@q ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, arvif->bssid, -@@ -7546,7 +7546,7 @@ static int ath11k_start_vdev_delay(struc +@@ -7549,7 +7549,7 @@ static int ath11k_start_vdev_delay(struc { struct ath11k *ar = hw->priv; struct ath11k_base *ab = ar->ab; @@ -267,7 +267,7 @@ Link: https://lore.kernel.org/r/20230821-ath11k_vif_to_arvif-v1-1-fa2c3b60b5cf@q int ret; if (WARN_ON(arvif->is_started)) -@@ -7596,7 +7596,7 @@ ath11k_mac_op_assign_vif_chanctx(struct +@@ -7599,7 +7599,7 @@ ath11k_mac_op_assign_vif_chanctx(struct { struct ath11k *ar = hw->priv; struct ath11k_base *ab = ar->ab; @@ -276,7 +276,7 @@ Link: https://lore.kernel.org/r/20230821-ath11k_vif_to_arvif-v1-1-fa2c3b60b5cf@q int ret; struct peer_create_params param; -@@ -7686,7 +7686,7 @@ ath11k_mac_op_unassign_vif_chanctx(struc +@@ -7689,7 +7689,7 @@ ath11k_mac_op_unassign_vif_chanctx(struc { struct ath11k *ar = hw->priv; struct ath11k_base *ab = ar->ab; @@ -285,7 +285,7 @@ Link: https://lore.kernel.org/r/20230821-ath11k_vif_to_arvif-v1-1-fa2c3b60b5cf@q struct ath11k_peer *peer; int ret; -@@ -8307,7 +8307,7 @@ ath11k_mac_op_set_bitrate_mask(struct ie +@@ -8310,7 +8310,7 @@ ath11k_mac_op_set_bitrate_mask(struct ie struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) { @@ -294,7 +294,7 @@ Link: https://lore.kernel.org/r/20230821-ath11k_vif_to_arvif-v1-1-fa2c3b60b5cf@q struct cfg80211_chan_def def; struct ath11k_pdev_cap *cap; struct ath11k *ar = arvif->ar; -@@ -8904,7 +8904,7 @@ static int ath11k_mac_op_remain_on_chann +@@ -8907,7 +8907,7 @@ static int ath11k_mac_op_remain_on_chann enum ieee80211_roc_type type) { struct ath11k *ar = hw->priv; diff --git a/package/kernel/mac80211/patches/subsys/312-wifi-cfg80211-annotate-iftype_data-pointer-with-spar.patch b/package/kernel/mac80211/patches/subsys/312-wifi-cfg80211-annotate-iftype_data-pointer-with-spar.patch new file mode 100644 index 0000000000..18420a80cf --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/312-wifi-cfg80211-annotate-iftype_data-pointer-with-spar.patch @@ -0,0 +1,467 @@ +From: Johannes Berg +Date: Mon, 28 Aug 2023 09:54:39 +0200 +Subject: [PATCH] wifi: cfg80211: annotate iftype_data pointer with sparse + +There were are a number of cases in mac80211 and iwlwifi (at +least) that used the sband->iftype_data pointer directly, +instead of using the accessors to find the right array entry +to use. + +Make sparse warn when such a thing is done. + +To not have a lot of casts, add two helper functions/macros + + - ieee80211_set_sband_iftype_data() + - for_each_sband_iftype_data() + +Signed-off-by: Johannes Berg +--- + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -5893,8 +5893,9 @@ static void ath11k_mac_setup_he_cap(stru + ar->mac.iftype[NL80211_BAND_2GHZ], + NL80211_BAND_2GHZ); + band = &ar->mac.sbands[NL80211_BAND_2GHZ]; +- band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ]; +- band->n_iftype_data = count; ++ _ieee80211_set_sband_iftype_data(band, ++ ar->mac.iftype[NL80211_BAND_2GHZ], ++ count); + } + + if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) { +@@ -5902,8 +5903,9 @@ static void ath11k_mac_setup_he_cap(stru + ar->mac.iftype[NL80211_BAND_5GHZ], + NL80211_BAND_5GHZ); + band = &ar->mac.sbands[NL80211_BAND_5GHZ]; +- band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ]; +- band->n_iftype_data = count; ++ _ieee80211_set_sband_iftype_data(band, ++ ar->mac.iftype[NL80211_BAND_5GHZ], ++ count); + } + + if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP && +@@ -5912,8 +5914,9 @@ static void ath11k_mac_setup_he_cap(stru + ar->mac.iftype[NL80211_BAND_6GHZ], + NL80211_BAND_6GHZ); + band = &ar->mac.sbands[NL80211_BAND_6GHZ]; +- band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ]; +- band->n_iftype_data = count; ++ _ieee80211_set_sband_iftype_data(band, ++ ar->mac.iftype[NL80211_BAND_6GHZ], ++ count); + } + } + +--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +@@ -1075,8 +1075,8 @@ static void iwl_init_he_hw_capab(struct + + memcpy(iftype_data, iwl_he_eht_capa, sizeof(iwl_he_eht_capa)); + +- sband->iftype_data = iftype_data; +- sband->n_iftype_data = ARRAY_SIZE(iwl_he_eht_capa); ++ _ieee80211_set_sband_iftype_data(sband, iftype_data, ++ ARRAY_SIZE(iwl_he_eht_capa)); + + for (i = 0; i < sband->n_iftype_data; i++) + iwl_nvm_fixup_sband_iftd(trans, data, sband, &iftype_data[i], +--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c +@@ -1119,8 +1119,7 @@ void mt7915_set_stream_he_caps(struct mt + n = mt7915_init_he_caps(phy, NL80211_BAND_2GHZ, data); + + band = &phy->mt76->sband_2g.sband; +- band->iftype_data = data; +- band->n_iftype_data = n; ++ _ieee80211_set_sband_iftype_data(band, data, n); + } + + if (phy->mt76->cap.has_5ghz) { +@@ -1128,8 +1127,7 @@ void mt7915_set_stream_he_caps(struct mt + n = mt7915_init_he_caps(phy, NL80211_BAND_5GHZ, data); + + band = &phy->mt76->sband_5g.sband; +- band->iftype_data = data; +- band->n_iftype_data = n; ++ _ieee80211_set_sband_iftype_data(band, data, n); + } + + if (phy->mt76->cap.has_6ghz) { +@@ -1137,8 +1135,7 @@ void mt7915_set_stream_he_caps(struct mt + n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data); + + band = &phy->mt76->sband_6g.sband; +- band->iftype_data = data; +- band->n_iftype_data = n; ++ _ieee80211_set_sband_iftype_data(band, data, n); + } + } + +--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +@@ -196,8 +196,7 @@ void mt7921_set_stream_he_caps(struct mt + n = mt7921_init_he_caps(phy, NL80211_BAND_2GHZ, data); + + band = &phy->mt76->sband_2g.sband; +- band->iftype_data = data; +- band->n_iftype_data = n; ++ _ieee80211_set_sband_iftype_data(band, data, n); + } + + if (phy->mt76->cap.has_5ghz) { +@@ -205,16 +204,14 @@ void mt7921_set_stream_he_caps(struct mt + n = mt7921_init_he_caps(phy, NL80211_BAND_5GHZ, data); + + band = &phy->mt76->sband_5g.sband; +- band->iftype_data = data; +- band->n_iftype_data = n; ++ _ieee80211_set_sband_iftype_data(band, data, n); + + if (phy->mt76->cap.has_6ghz) { + data = phy->iftype[NL80211_BAND_6GHZ]; + n = mt7921_init_he_caps(phy, NL80211_BAND_6GHZ, data); + + band = &phy->mt76->sband_6g.sband; +- band->iftype_data = data; +- band->n_iftype_data = n; ++ _ieee80211_set_sband_iftype_data(band, data, n); + } + } + } +--- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c +@@ -823,8 +823,7 @@ __mt7996_set_stream_he_eht_caps(struct m + n++; + } + +- sband->iftype_data = data; +- sband->n_iftype_data = n; ++ _ieee80211_set_sband_iftype_data(sband, data, n); + } + + void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy) +--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c ++++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c +@@ -1335,7 +1335,7 @@ static int qtnf_cmd_band_fill_iftype(con + return -EINVAL; + } + +- kfree(band->iftype_data); ++ kfree((__force void *)band->iftype_data); + band->iftype_data = NULL; + band->n_iftype_data = tlv->n_iftype_data; + if (band->n_iftype_data == 0) +@@ -1347,7 +1347,8 @@ static int qtnf_cmd_band_fill_iftype(con + band->n_iftype_data = 0; + return -ENOMEM; + } +- band->iftype_data = iftype_data; ++ ++ _ieee80211_set_sband_iftype_data(band, iftype_data, tlv->n_iftype_data); + + for (i = 0; i < band->n_iftype_data; i++) + qtnf_cmd_conv_iftype(iftype_data++, &tlv->iftype_data[i]); +--- a/drivers/net/wireless/quantenna/qtnfmac/core.c ++++ b/drivers/net/wireless/quantenna/qtnfmac/core.c +@@ -549,7 +549,7 @@ static void qtnf_core_mac_detach(struct + if (!wiphy->bands[band]) + continue; + +- kfree(wiphy->bands[band]->iftype_data); ++ kfree((__force void *)wiphy->bands[band]->iftype_data); + wiphy->bands[band]->n_iftype_data = 0; + + kfree(wiphy->bands[band]->channels); +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -3328,8 +3328,7 @@ static void rtw89_init_he_cap(struct rtw + idx++; + } + +- sband->iftype_data = iftype_data; +- sband->n_iftype_data = idx; ++ _ieee80211_set_sband_iftype_data(sband, iftype_data, idx); + } + + static int rtw89_core_set_supported_band(struct rtw89_dev *rtwdev) +@@ -3374,11 +3373,11 @@ err: + hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL; + hw->wiphy->bands[NL80211_BAND_6GHZ] = NULL; + if (sband_2ghz) +- kfree(sband_2ghz->iftype_data); ++ kfree((__force void *)sband_2ghz->iftype_data); + if (sband_5ghz) +- kfree(sband_5ghz->iftype_data); ++ kfree((__force void *)sband_5ghz->iftype_data); + if (sband_6ghz) +- kfree(sband_6ghz->iftype_data); ++ kfree((__force void *)sband_6ghz->iftype_data); + kfree(sband_2ghz); + kfree(sband_5ghz); + kfree(sband_6ghz); +@@ -3390,11 +3389,11 @@ static void rtw89_core_clr_supported_ban + struct ieee80211_hw *hw = rtwdev->hw; + + if (hw->wiphy->bands[NL80211_BAND_2GHZ]) +- kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data); ++ kfree((__force void *)hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data); + if (hw->wiphy->bands[NL80211_BAND_5GHZ]) +- kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data); ++ kfree((__force void *)hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data); + if (hw->wiphy->bands[NL80211_BAND_6GHZ]) +- kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data); ++ kfree((__force void *)hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data); + kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]); + kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]); + kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]); +--- a/drivers/net/wireless/realtek/rtw89/regd.c ++++ b/drivers/net/wireless/realtek/rtw89/regd.c +@@ -376,7 +376,7 @@ bottom: + return; + + wiphy->bands[NL80211_BAND_6GHZ] = NULL; +- kfree(sband->iftype_data); ++ kfree((__force void *)sband->iftype_data); + kfree(sband); + } + +--- a/drivers/net/wireless/virtual/mac80211_hwsim.c ++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c +@@ -4900,25 +4900,19 @@ static const struct ieee80211_sband_ifty + + static void mac80211_hwsim_sband_capab(struct ieee80211_supported_band *sband) + { +- u16 n_iftype_data; +- +- if (sband->band == NL80211_BAND_2GHZ) { +- n_iftype_data = ARRAY_SIZE(sband_capa_2ghz); +- sband->iftype_data = +- (struct ieee80211_sband_iftype_data *)sband_capa_2ghz; +- } else if (sband->band == NL80211_BAND_5GHZ) { +- n_iftype_data = ARRAY_SIZE(sband_capa_5ghz); +- sband->iftype_data = +- (struct ieee80211_sband_iftype_data *)sband_capa_5ghz; +- } else if (sband->band == NL80211_BAND_6GHZ) { +- n_iftype_data = ARRAY_SIZE(sband_capa_6ghz); +- sband->iftype_data = +- (struct ieee80211_sband_iftype_data *)sband_capa_6ghz; +- } else { +- return; ++ switch (sband->band) { ++ case NL80211_BAND_2GHZ: ++ ieee80211_set_sband_iftype_data(sband, sband_capa_2ghz); ++ break; ++ case NL80211_BAND_5GHZ: ++ ieee80211_set_sband_iftype_data(sband, sband_capa_5ghz); ++ break; ++ case NL80211_BAND_6GHZ: ++ ieee80211_set_sband_iftype_data(sband, sband_capa_6ghz); ++ break; ++ default: ++ break; + } +- +- sband->n_iftype_data = n_iftype_data; + } + + #ifdef CPTCFG_MAC80211_MESH +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -415,6 +415,19 @@ struct ieee80211_sta_eht_cap { + u8 eht_ppe_thres[IEEE80211_EHT_PPE_THRES_MAX_LEN]; + }; + ++/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */ ++#ifdef __CHECKER__ ++/* ++ * This is used to mark the sband->iftype_data pointer which is supposed ++ * to be an array with special access semantics (per iftype), but a lot ++ * of code got it wrong in the past, so with this marking sparse will be ++ * noisy when the pointer is used directly. ++ */ ++# define __iftd __attribute__((noderef, address_space(__iftype_data))) ++#else ++# define __iftd ++#endif /* __CHECKER__ */ ++ + /** + * struct ieee80211_sband_iftype_data - sband data per interface type + * +@@ -548,10 +561,48 @@ struct ieee80211_supported_band { + struct ieee80211_sta_s1g_cap s1g_cap; + struct ieee80211_edmg edmg_cap; + u16 n_iftype_data; +- const struct ieee80211_sband_iftype_data *iftype_data; ++ const struct ieee80211_sband_iftype_data __iftd *iftype_data; + }; + + /** ++ * _ieee80211_set_sband_iftype_data - set sband iftype data array ++ * @sband: the sband to initialize ++ * @iftd: the iftype data array pointer ++ * @n_iftd: the length of the iftype data array ++ * ++ * Set the sband iftype data array; use this where the length cannot ++ * be derived from the ARRAY_SIZE() of the argument, but prefer ++ * ieee80211_set_sband_iftype_data() where it can be used. ++ */ ++static inline void ++_ieee80211_set_sband_iftype_data(struct ieee80211_supported_band *sband, ++ const struct ieee80211_sband_iftype_data *iftd, ++ u16 n_iftd) ++{ ++ sband->iftype_data = (const void __iftd __force *)iftd; ++ sband->n_iftype_data = n_iftd; ++} ++ ++/** ++ * ieee80211_set_sband_iftype_data - set sband iftype data array ++ * @sband: the sband to initialize ++ * @iftd: the iftype data array ++ */ ++#define ieee80211_set_sband_iftype_data(sband, iftd) \ ++ _ieee80211_set_sband_iftype_data(sband, iftd, ARRAY_SIZE(iftd)) ++ ++/** ++ * for_each_sband_iftype_data - iterate sband iftype data entries ++ * @sband: the sband whose iftype_data array to iterate ++ * @i: iterator counter ++ * @iftd: iftype data pointer to set ++ */ ++#define for_each_sband_iftype_data(sband, i, iftd) \ ++ for (i = 0, iftd = (const void __force *)&(sband)->iftype_data[i]; \ ++ i < (sband)->n_iftype_data; \ ++ i++, iftd = (const void __force *)&(sband)->iftype_data[i]) ++ ++/** + * ieee80211_get_sband_iftype_data - return sband data for a given iftype + * @sband: the sband to search for the STA on + * @iftype: enum nl80211_iftype +@@ -562,6 +613,7 @@ static inline const struct ieee80211_sba + ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband, + u8 iftype) + { ++ const struct ieee80211_sband_iftype_data *data; + int i; + + if (WARN_ON(iftype >= NL80211_IFTYPE_MAX)) +@@ -570,10 +622,7 @@ ieee80211_get_sband_iftype_data(const st + if (iftype == NL80211_IFTYPE_AP_VLAN) + iftype = NL80211_IFTYPE_AP; + +- for (i = 0; i < sband->n_iftype_data; i++) { +- const struct ieee80211_sband_iftype_data *data = +- &sband->iftype_data[i]; +- ++ for_each_sband_iftype_data(sband, i, data) { + if (data->types_mask & BIT(iftype)) + return data; + } +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -1055,6 +1055,7 @@ int ieee80211_register_hw(struct ieee802 + supp_he = false; + supp_eht = false; + for (band = 0; band < NUM_NL80211_BANDS; band++) { ++ const struct ieee80211_sband_iftype_data *iftd; + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[band]; +@@ -1101,11 +1102,7 @@ int ieee80211_register_hw(struct ieee802 + supp_ht = supp_ht || sband->ht_cap.ht_supported; + supp_vht = supp_vht || sband->vht_cap.vht_supported; + +- for (i = 0; i < sband->n_iftype_data; i++) { +- const struct ieee80211_sband_iftype_data *iftd; +- +- iftd = &sband->iftype_data[i]; +- ++ for_each_sband_iftype_data(sband, i, iftd) { + supp_he = supp_he || iftd->he_cap.has_he; + supp_eht = supp_eht || iftd->eht_cap.has_eht; + } +--- a/net/wireless/chan.c ++++ b/net/wireless/chan.c +@@ -6,7 +6,7 @@ + * + * Copyright 2009 Johannes Berg + * Copyright 2013-2014 Intel Mobile Communications GmbH +- * Copyright 2018-2022 Intel Corporation ++ * Copyright 2018-2023 Intel Corporation + */ + + #include +@@ -1162,8 +1162,7 @@ bool cfg80211_chandef_usable(struct wiph + if (!sband) + return false; + +- for (i = 0; i < sband->n_iftype_data; i++) { +- iftd = &sband->iftype_data[i]; ++ for_each_sband_iftype_data(sband, i, iftd) { + if (!iftd->eht_cap.has_eht) + continue; + +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -5,7 +5,7 @@ + * Copyright 2006-2010 Johannes Berg + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright 2015-2017 Intel Deutschland GmbH +- * Copyright (C) 2018-2022 Intel Corporation ++ * Copyright (C) 2018-2023 Intel Corporation + */ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +@@ -817,6 +817,7 @@ int wiphy_register(struct wiphy *wiphy) + + /* sanity check supported bands/channels */ + for (band = 0; band < NUM_NL80211_BANDS; band++) { ++ const struct ieee80211_sband_iftype_data *iftd; + u16 types = 0; + bool have_he = false; + +@@ -873,14 +874,11 @@ int wiphy_register(struct wiphy *wiphy) + return -EINVAL; + } + +- for (i = 0; i < sband->n_iftype_data; i++) { +- const struct ieee80211_sband_iftype_data *iftd; ++ for_each_sband_iftype_data(sband, i, iftd) { + bool has_ap, has_non_ap; + u32 ap_bits = BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_GO); + +- iftd = &sband->iftype_data[i]; +- + if (WARN_ON(!iftd->types_mask)) + return -EINVAL; + if (WARN_ON(types & iftd->types_mask)) +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1906,20 +1906,20 @@ static int nl80211_send_band_rateinfo(st + struct nlattr *nl_iftype_data = + nla_nest_start_noflag(msg, + NL80211_BAND_ATTR_IFTYPE_DATA); ++ const struct ieee80211_sband_iftype_data *iftd; + int err; + + if (!nl_iftype_data) + return -ENOBUFS; + +- for (i = 0; i < sband->n_iftype_data; i++) { ++ for_each_sband_iftype_data(sband, i, iftd) { + struct nlattr *iftdata; + + iftdata = nla_nest_start_noflag(msg, i + 1); + if (!iftdata) + return -ENOBUFS; + +- err = nl80211_send_iftype_data(msg, sband, +- &sband->iftype_data[i]); ++ err = nl80211_send_iftype_data(msg, sband, iftd); + if (err) + return err; + From ef8e2f66f563d0d1864be37075dacf3f13defdc7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 18 Sep 2023 12:46:12 +0200 Subject: [PATCH 21/24] mt76: update to the latest version b5d13611d35e mt76: mt7915: fix monitor mode issues bbbac7deee3d wifi: mt76: rename mt76_packet_id_init/flush to mt76_wcid_init/cleanup f1e1e67d97d1 wifi: mt76: fix race condition related to checking tx queue fill status b3f739a64e6b wifi: mt76: mt7996: add eht rx rate support ca4917062f17 wifi: mt76: mt76x0: remove dead code in mt76x0_phy_get_target_power 325a0c493199 wifi: mt76: mt7996: fill txd by host driver cd371fcc98d4 mt76: mt7996: sync with upstream d71f8d1b172b wifi: mt76: use atomic iface iteration for pre-TBTT work 8d5ea32d4895 wifi: mt76: remove unused error path in mt76_connac_tx_complete_skb 01860c02c505 wifi: mt76: add DMA mapping error check in mt76_alloc_txwi() 62ddb6d46a97 wifi: mt76: connac: introduce helper for mt7925 chipset 0837f37e998b wifi: mt76: mt792x: support mt7925 chip init 899ff378082b wifi: mt76: connac: export functions for mt7925 c3858b5bf347 wifi: mt76: connac: add eht support for phy mode config 5df6b26a9fc5 wifi: mt76: connac: add eht support for tx power a8081345c636 wifi: mt76: connac: add data field in struct tlv 9b38aebecf78 wifi: mt76: connac: add more unified command IDs 84984e6dc87d wifi: mt76: connac: add more unified event IDs 6fe92398c9ce wifi: mt76: mt7996: set correct wcid in txp 2cfe2fb0bb80 wifi: mt76: mt7996: fix beamform mcu cmd configuration e512241bb5bb wifi: mt76: mt7996: fix beamformee ss subfield in EHT PHY cap 719a98f832c7 wifi: mt76: mt7996: fix wmm queue mapping 9723562f2a5b wifi: mt76: mt7996: fix rx rate report for CBW320-2 1bb5a6a54943 wifi: mt76: mt7996: fix TWT command format 751b054891f6 wifi: mt76: mt7996: only set vif teardown cmds at remove interface fea1e10c7741 wifi: mt76: mt7996: support more options for mt7996_set_bitrate_mask() d497ee8aa2f5 wifi: mt76: mt7996: support per-band LED control 8ccc84111141 wifi: mt76: Use PTR_ERR_OR_ZERO() to simplify code 161f70217edf wifi: mt76: mt7921e: Support MT7992 IP in Xiaomi Redmibook 15 Pro (2023) 7d25bfc3f0cc wifi: mt76: fix clang-specific fortify warnings 5971aa968401 wifi: mt76: connac: add MBSSID support for mt7996 5a47dd323be1 wifi: mt76: update beacon size limitation d5b4b81dcc9e wifi: mt76: check sta rx control frame to multibss capability af0e1f6dafb5 wifi: mt76: fix potential memory leak of beacon commands 65d91a833b01 wifi: mt76: get rid of false alamrs of tx emission issues 29411e52059f wifi: mt76: fix per-band IEEE80211_CONF_MONITOR flag comparison 4da62774038a wifi: mt76: check vif type before reporting cca and csa 4a85678fe089 wifi: mt76: mt7915: update mpdu density capability 791a45cffadf wifi: mt76: mt7915: fix beamforming availability check 08e1e6cb7d41 wifi: mt76: Drop unnecessary error check for debugfs_create_dir() d1881b1b2bf6 wifi: mt76: move struct ieee80211_chanctx_conf up to struct mt76_vif 66d5694e1898 wifi: mt76: mt7921: fix the wrong rate pickup for the chanctx driver 9fc37b0ac546 wifi: mt76: mt7921: fix the wrong rate selected in fw for the chanctx driver 2afc7285f75d wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips Signed-off-by: Felix Fietkau --- package/kernel/mt76/Makefile | 54 ++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index 78f01c119f..9a3597f770 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:=2023-08-14 -PKG_SOURCE_VERSION:=b14c2351ddb8601c322576d84029e463d456caef -PKG_MIRROR_HASH:=62b5e157ad525424b6857e77ed373e8d39d03af71b057f8b309d8b293d6eac5f +PKG_SOURCE_DATE:=2023-09-18 +PKG_SOURCE_VERSION:=2afc7285f75dca5a0583fd917285bf33f1429cc6 +PKG_MIRROR_HASH:=2c9556b298246277ac2d65415e4449f98e6d5fdb99e0d0a92262f162df772bbc PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 @@ -310,6 +310,38 @@ define KernelPackage/mt7921e AUTOLOAD:=$(call AutoProbe,mt7921e) endef +define KernelPackage/mt7996e + $(KernelPackage/mt76-default) + TITLE:=MediaTek MT7996E wireless driver + DEPENDS+=@PCI_SUPPORT +kmod-mt76-connac + FILES:= $(PKG_BUILD_DIR)/mt7996/mt7996e.ko + AUTOLOAD:=$(call AutoProbe,mt7996e) +endef + +define KernelPackage/mt7925-common + $(KernelPackage/mt76-default) + TITLE:=MediaTek MT7925 wireless driver common code + HIDDEN:=1 + DEPENDS+=+kmod-mt792x-common +@DRIVER_11AX_SUPPORT +kmod-hwmon-core + FILES:= $(PKG_BUILD_DIR)/mt7925/mt7925-common.ko +endef + +define KernelPackage/mt7925u + $(KernelPackage/mt76-default) + TITLE:=MediaTek MT7925U wireless driver + DEPENDS+=+kmod-mt792x-usb +kmod-mt7925-common + FILES:= $(PKG_BUILD_DIR)/mt7925/mt7925u.ko + AUTOLOAD:=$(call AutoProbe,mt7921u) +endef + +define KernelPackage/mt7925e + $(KernelPackage/mt76-default) + TITLE:=MediaTek MT7925e wireless driver + DEPENDS+=@PCI_SUPPORT +kmod-mt7925-common + FILES:= $(PKG_BUILD_DIR)/mt7925/mt7925e.ko + AUTOLOAD:=$(call AutoProbe,mt7921e) +endef + define Package/mt76-test SECTION:=devel CATEGORY:=Development @@ -418,6 +450,18 @@ endif ifdef CONFIG_PACKAGE_kmod-mt7921e PKG_MAKE_FLAGS += CONFIG_MT7921E=m endif +ifdef CONFIG_PACKAGE_kmod-mt7996e + PKG_MAKE_FLAGS += CONFIG_MT7996E=m +endif +ifdef CONFIG_PACKAGE_kmod-mt7925-common + PKG_MAKE_FLAGS += CONFIG_MT7925_COMMON=m +endif +ifdef CONFIG_PACKAGE_kmod-mt7925u + PKG_MAKE_FLAGS += CONFIG_MT7925U=m +endif +ifdef CONFIG_PACKAGE_kmod-mt7925e + PKG_MAKE_FLAGS += CONFIG_MT7925E=m +endif define Build/Compile +$(KERNEL_MAKE) $(PKG_JOBS) \ @@ -591,8 +635,12 @@ $(eval $(call KernelPackage,mt7921-firmware)) $(eval $(call KernelPackage,mt792x-common)) $(eval $(call KernelPackage,mt792x-usb)) $(eval $(call KernelPackage,mt7921-common)) +$(eval $(call KernelPackage,mt7925-common)) $(eval $(call KernelPackage,mt7921u)) $(eval $(call KernelPackage,mt7921s)) $(eval $(call KernelPackage,mt7921e)) +$(eval $(call KernelPackage,mt7925u)) +$(eval $(call KernelPackage,mt7925e)) +$(eval $(call KernelPackage,mt7996e)) $(eval $(call KernelPackage,mt76)) $(eval $(call BuildPackage,mt76-test)) From c64a5d122f9d726eb73211ad24d8a9a87e855304 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Mon, 18 Sep 2023 13:43:59 +0200 Subject: [PATCH 22/24] sunxi: refresh kernel patches Refresh kernel patches for sunxi target. Signed-off-by: Christian Marangi --- ...dt-bindings-usb-Add-H616-compatible-string.patch | 7 ------- ...s-phy-Add-special-clock-for-Allwinner-H616.patch | 5 ----- ...462-arm64-dts-allwinner-h616-Add-USB-nodes.patch | 5 ----- ...allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch | 13 ++++--------- 4 files changed, 4 insertions(+), 26 deletions(-) diff --git a/target/linux/sunxi/patches-6.1/460-dt-bindings-usb-Add-H616-compatible-string.patch b/target/linux/sunxi/patches-6.1/460-dt-bindings-usb-Add-H616-compatible-string.patch index 929b567e67..bab535705c 100644 --- a/target/linux/sunxi/patches-6.1/460-dt-bindings-usb-Add-H616-compatible-string.patch +++ b/target/linux/sunxi/patches-6.1/460-dt-bindings-usb-Add-H616-compatible-string.patch @@ -14,8 +14,6 @@ Acked-by: Krzysztof Kozlowski Documentation/devicetree/bindings/usb/generic-ohci.yaml | 1 + 2 files changed, 2 insertions(+) -diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml -index c5f629c5bc61..994818cb6044 100644 --- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml +++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml @@ -30,6 +30,7 @@ properties: @@ -26,8 +24,6 @@ index c5f629c5bc61..994818cb6044 100644 - allwinner,sun5i-a13-ehci - allwinner,sun6i-a31-ehci - allwinner,sun7i-a20-ehci -diff --git a/Documentation/devicetree/bindings/usb/generic-ohci.yaml b/Documentation/devicetree/bindings/usb/generic-ohci.yaml -index f838f78d6164..4fcbd0add49d 100644 --- a/Documentation/devicetree/bindings/usb/generic-ohci.yaml +++ b/Documentation/devicetree/bindings/usb/generic-ohci.yaml @@ -20,6 +20,7 @@ properties: @@ -38,6 +34,3 @@ index f838f78d6164..4fcbd0add49d 100644 - allwinner,sun5i-a13-ohci - allwinner,sun6i-a31-ohci - allwinner,sun7i-a20-ohci --- -2.20.1 - diff --git a/target/linux/sunxi/patches-6.1/461-dt-bindings-phy-Add-special-clock-for-Allwinner-H616.patch b/target/linux/sunxi/patches-6.1/461-dt-bindings-phy-Add-special-clock-for-Allwinner-H616.patch index 2cd3acce2c..238683b3c5 100644 --- a/target/linux/sunxi/patches-6.1/461-dt-bindings-phy-Add-special-clock-for-Allwinner-H616.patch +++ b/target/linux/sunxi/patches-6.1/461-dt-bindings-phy-Add-special-clock-for-Allwinner-H616.patch @@ -21,8 +21,6 @@ Signed-off-by: Andre Przywara .../phy/allwinner,sun8i-h3-usb-phy.yaml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) -diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml -index 77539b4601c2..2df012d13655 100644 --- a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml +++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml @@ -36,18 +36,22 @@ properties: @@ -77,6 +75,3 @@ index 77539b4601c2..2df012d13655 100644 additionalProperties: false examples: --- -2.20.1 - diff --git a/target/linux/sunxi/patches-6.1/462-arm64-dts-allwinner-h616-Add-USB-nodes.patch b/target/linux/sunxi/patches-6.1/462-arm64-dts-allwinner-h616-Add-USB-nodes.patch index 5d626a014e..9a31bea8bf 100644 --- a/target/linux/sunxi/patches-6.1/462-arm64-dts-allwinner-h616-Add-USB-nodes.patch +++ b/target/linux/sunxi/patches-6.1/462-arm64-dts-allwinner-h616-Add-USB-nodes.patch @@ -14,8 +14,6 @@ Signed-off-by: Andre Przywara .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi -index 622a1f7d1641..74aed0d232a9 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi @@ -504,6 +504,166 @@ @@ -185,6 +183,3 @@ index 622a1f7d1641..74aed0d232a9 100644 rtc: rtc@7000000 { compatible = "allwinner,sun50i-h616-rtc"; reg = <0x07000000 0x400>; --- -2.20.1 - diff --git a/target/linux/sunxi/patches-6.1/463-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch b/target/linux/sunxi/patches-6.1/463-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch index d3460c54e6..9ae5591cca 100644 --- a/target/linux/sunxi/patches-6.1/463-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch +++ b/target/linux/sunxi/patches-6.1/463-arm64-dts-allwinner-h616-OrangePi-Zero-2-Add-USB-nod.patch @@ -14,8 +14,6 @@ Signed-off-by: Andre Przywara .../allwinner/sun50i-h616-orangepi-zero2.dts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts -index 02893f3ac99d..cb8600d0ea1e 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts @@ -49,8 +49,24 @@ @@ -32,12 +30,12 @@ index 02893f3ac99d..cb8600d0ea1e 100644 + enable-active-high; + gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */ + }; - }; - -+&ehci1 { -+ status = "okay"; +}; + ++&ehci1 { ++ status = "okay"; + }; + +/* USB 2 & 3 are on headers only. */ + &emac0 { @@ -79,6 +77,3 @@ index 02893f3ac99d..cb8600d0ea1e 100644 + usb1_vbus-supply = <®_usb1_vbus>; + status = "okay"; +}; --- -2.20.1 - From 93e147c9e6451a6f97706a1759e499ad5daba14b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 18 Sep 2023 16:50:35 +0200 Subject: [PATCH 23/24] hostapd: fix dynamically adding interfaces with 802.11ax support disabled in the build Move an important code line outside of #ifdef CONFIG_IEEE80211AX Signed-off-by: Felix Fietkau --- ...0211_put_freq_params-call-outside-of.patch | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 package/network/services/hostapd/patches/182-nl80211-move-nl80211_put_freq_params-call-outside-of.patch diff --git a/package/network/services/hostapd/patches/182-nl80211-move-nl80211_put_freq_params-call-outside-of.patch b/package/network/services/hostapd/patches/182-nl80211-move-nl80211_put_freq_params-call-outside-of.patch new file mode 100644 index 0000000000..395c645954 --- /dev/null +++ b/package/network/services/hostapd/patches/182-nl80211-move-nl80211_put_freq_params-call-outside-of.patch @@ -0,0 +1,34 @@ +From: Felix Fietkau +Date: Mon, 18 Sep 2023 16:47:41 +0200 +Subject: [PATCH] nl80211: move nl80211_put_freq_params call outside of + 802.11ax #ifdef + +The relevance of this call is not specific to 802.11ax, so it should be done +even with CONFIG_IEEE80211AX disabled. + +Fixes: b3921db426ea ("nl80211: Add frequency info in start AP command") +Signed-off-by: Felix Fietkau +--- + +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -5226,6 +5226,9 @@ static int wpa_driver_nl80211_set_ap(voi + nla_nest_end(msg, ftm); + } + ++ if (params->freq && nl80211_put_freq_params(msg, params->freq) < 0) ++ goto fail; ++ + #ifdef CONFIG_IEEE80211AX + if (params->he_spr_ctrl) { + struct nlattr *spr; +@@ -5260,9 +5263,6 @@ static int wpa_driver_nl80211_set_ap(voi + nla_nest_end(msg, spr); + } + +- if (params->freq && nl80211_put_freq_params(msg, params->freq) < 0) +- goto fail; +- + if (params->freq && params->freq->he_enabled) { + struct nlattr *bss_color; + From 6bf8193b25a147abfe3720104e63af890c1ca2b8 Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Sun, 13 Aug 2023 02:29:06 +0200 Subject: [PATCH 24/24] sunxi: add support for Bananapi P2 Zero CPU: Allwinner H2+ quad-core Cortex-A7 @ 1.2GHz Memory: 512Mb DDR3 Storage: SDcard, 8GB eMMC Network: 10/100M ethernet, optional PoE support, Ampak AP6212 wifi + BT USB: 1x USB 2.0 OTG Other: 40-pin expansion header, mini-HDMI Flashing instructions: Standard sunxi SD card installation procedure - copy image to SD card, insert into SD card slot on the device and boot. Signed-off-by: Zoltan HERPAI --- package/boot/uboot-sunxi/Makefile | 8 + .../254-sunxi-h2-add-bpi-p2-zero.patch | 307 ++++++++++++++++++ target/linux/sunxi/image/cortexa7.mk | 9 + .../410-sunxi-add-bananapi-p2-zero.patch | 292 +++++++++++++++++ 4 files changed, 616 insertions(+) create mode 100644 package/boot/uboot-sunxi/patches/254-sunxi-h2-add-bpi-p2-zero.patch create mode 100644 target/linux/sunxi/patches-6.1/410-sunxi-add-bananapi-p2-zero.patch diff --git a/package/boot/uboot-sunxi/Makefile b/package/boot/uboot-sunxi/Makefile index e141eb7af7..17905802c3 100644 --- a/package/boot/uboot-sunxi/Makefile +++ b/package/boot/uboot-sunxi/Makefile @@ -349,6 +349,13 @@ define U-Boot/bananapi_m2_berry BUILD_DEVICES:=sinovoip_bananapi-m2-berry endef +define U-Boot/bananapi_p2_zero + BUILD_SUBTARGET:=cortexa7 + NAME:=Bananapi P2 Zero + BUILD_DEVICES:=sinovoip_bananapi-p2-zero +endef + + UBOOT_TARGETS := \ a64-olinuxino \ a64-olinuxino-emmc \ @@ -361,6 +368,7 @@ UBOOT_TARGETS := \ bananapi_m2_plus_h3 \ Bananapi \ bananapi_m2_berry \ + bananapi_p2_zero \ Bananapi_M2_Ultra \ Bananapro \ Cubieboard \ diff --git a/package/boot/uboot-sunxi/patches/254-sunxi-h2-add-bpi-p2-zero.patch b/package/boot/uboot-sunxi/patches/254-sunxi-h2-add-bpi-p2-zero.patch new file mode 100644 index 0000000000..9bf1a36b21 --- /dev/null +++ b/package/boot/uboot-sunxi/patches/254-sunxi-h2-add-bpi-p2-zero.patch @@ -0,0 +1,307 @@ +--- /dev/null ++++ b/arch/arm/dts/sun8i-h2-plus-bananapi-p2-zero.dts +@@ -0,0 +1,291 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (C) 2023 Zoltan HERPAI ++ * ++ * Based on sun8i-h2-plus-bananapi-m2-zero.dts, which is: ++ * Copyright (C) 2017 Icenowy Zheng ++ */ ++ ++/dts-v1/; ++#include "sun8i-h3.dtsi" ++#include "sunxi-common-regulators.dtsi" ++ ++#include ++#include ++ ++/ { ++ model = "Banana Pi BPI-P2-Zero"; ++ compatible = "sinovoip,bpi-p2-zero", "allwinner,sun8i-h2-plus"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = &emac; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ connector { ++ compatible = "hdmi-connector"; ++ type = "c"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ pwr_led { ++ label = "bananapi-p2-zero:red:pwr"; ++ gpios = <&r_pio 0 10 GPIO_ACTIVE_LOW>; /* PL10 */ ++ default-state = "on"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ switch-4 { ++ label = "power"; ++ linux,code = ; ++ gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; ++ wakeup-source; ++ }; ++ }; ++ ++ reg_vdd_cpux: vdd-cpux-regulator { ++ compatible = "regulator-gpio"; ++ regulator-name = "vdd-cpux"; ++ regulator-type = "voltage"; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1300000>; ++ regulator-ramp-delay = <50>; /* 4ms */ ++ ++ gpios = <&r_pio 0 1 GPIO_ACTIVE_HIGH>; /* PL1 */ ++ enable-active-high; ++ gpios-states = <0x1>; ++ states = <1100000 0>, <1300000 1>; ++ }; ++ ++ reg_vcc_dram: vcc-dram { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-dram"; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <1500000>; ++ regulator-always-on; ++ regulator-boot-on; ++ enable-active-high; ++ gpio = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */ ++ vin-supply = <®_vcc5v0>; ++ }; ++ ++ reg_vcc1v2: vcc1v2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc1v2"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-always-on; ++ regulator-boot-on; ++ enable-active-high; ++ gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */ ++ vin-supply = <®_vcc5v0>; ++ }; ++ ++ poweroff { ++ compatible = "regulator-poweroff"; ++ cpu-supply = <®_vcc1v2>; ++ }; ++ ++ wifi_pwrseq: wifi_pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */ ++ clocks = <&rtc CLK_OSC32K_FANOUT>; ++ clock-names = "ext_clock"; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <®_vdd_cpux>; ++}; ++ ++&de { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&emac { ++ phy-handle = <&int_mii_phy>; ++ phy-mode = "mii"; ++ allwinner,leds-active-low; ++ status = "okay"; ++}; ++ ++&hdmi { ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ ++&mmc0 { ++ vmmc-supply = <®_vcc3v3>; ++ bus-width = <4>; ++ /* ++ * On the production batch of this board the card detect GPIO is ++ * high active (card inserted), although on the early samples it's ++ * low active. ++ */ ++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ ++ status = "okay"; ++}; ++ ++&mmc1 { ++ vmmc-supply = <®_vcc3v3>; ++ vqmmc-supply = <®_vcc3v3>; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ bus-width = <4>; ++ non-removable; ++ status = "okay"; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ interrupt-parent = <&pio>; ++ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 / EINT10 */ ++ interrupt-names = "host-wake"; ++ }; ++}; ++ ++&mmc2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc2_8bit_pins>; ++ vmmc-supply = <®_vcc3v3>; ++ vqmmc-supply = <®_vcc3v3>; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pa_pins>; ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ uart-has-rtscts; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ max-speed = <1500000>; ++ clocks = <&rtc CLK_OSC32K_FANOUT>; ++ clock-names = "lpo"; ++ vbat-supply = <®_vcc3v3>; ++ vddio-supply = <®_vcc3v3>; ++ device-wakeup-gpios = <&pio 6 13 GPIO_ACTIVE_HIGH>; /* PG13 */ ++ host-wakeup-gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>; /* PG11 */ ++ shutdown-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */ ++ }; ++ ++}; ++ ++&pio { ++ gpio-line-names = ++ /* PA */ ++ "CON2-P13", "CON2-P11", "CON2-P22", "CON2-P15", ++ "CON3-P03", "CON3-P02", "CON2-P07", "CON2-P29", ++ "CON2-P31", "CON2-P33", "CON2-P35", "CON2-P05", ++ "CON2-P03", "CON2-P08", "CON2-P10", "CON2-P16", ++ "CON2-P12", "CON2-P37", "CON2-P28", "CON2-P27", ++ "CON2-P40", "CON2-P38", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PB */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PC */ ++ "CON2-P19", "CON2-P21", "CON2-P23", "CON2-P24", ++ "CON2-P18", "", "", "CON2-P26", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PD */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "CSI-PWR-EN", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PE */ ++ "CN3-P17", "CN3-P13", "CN3-P09", "CN3-P07", ++ "CN3-P19", "CN3-P21", "CN3-P22", "CN3-P20", ++ "CN3-P18", "CN3-P16", "CN3-P14", "CN3-P12", ++ "CN3-P05", "CN3-P03", "CN3-P06", "CN3-P08", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PF */ ++ "SDC0-D1", "SDC0-D0", "SDC0-CLK", "SDC0-CMD", "SDC0-D3", ++ "SDC0-D2", "SDC0-DET", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PG */ ++ "WL-SDIO-CLK", "WL-SDIO-CMD", "WL-SDIO-D0", "WL-SDIO-D1", ++ "WL-SDIO-D2", "WL-SDIO-D3", "BT-UART-TX", "BT-UART-RX", ++ "BT-UART-RTS", "BT-UART-CTS", "WL-WAKE-AP", "BT-WAKE-AP", ++ "BT-RST-N", "AP-WAKE-BT", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", ""; ++}; ++ ++&r_pio { ++ gpio-line-names = ++ /* PL */ ++ "", "CPUX-SET", "CON2-P32", "POWER-KEY", "CON2-P36", ++ "VCC-IO-EN", "USB0-ID", "WL-PWR-EN", ++ "PWR-STB", "PWR-DRAM", "PWR-LED", "IR-RX", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", ""; ++}; ++ ++&usb_otg { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&usbphy { ++ usb0_id_det-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ ++ /* ++ * There're two micro-USB connectors, one is power-only and another is ++ * OTG. The Vbus of these two connectors are connected together, so ++ * the external USB device will be powered just by the power input ++ * from the power-only USB port. ++ */ ++ status = "okay"; ++}; +--- /dev/null ++++ b/configs/bananapi_p2_zero_defconfig +@@ -0,0 +1,10 @@ ++CONFIG_ARM=y ++CONFIG_ARCH_SUNXI=y ++CONFIG_DEFAULT_DEVICE_TREE="sun8i-h2-plus-bananapi-p2-zero" ++CONFIG_SPL=y ++CONFIG_MACH_SUN8I_H3=y ++CONFIG_DRAM_CLK=408 ++# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set ++CONFIG_MMC_SUNXI_SLOT_EXTRA=2 ++CONFIG_SUN8I_EMAC=y ++CONFIG_USB_EHCI_HCD=y diff --git a/target/linux/sunxi/image/cortexa7.mk b/target/linux/sunxi/image/cortexa7.mk index e14db24eb2..3191cec4fd 100644 --- a/target/linux/sunxi/image/cortexa7.mk +++ b/target/linux/sunxi/image/cortexa7.mk @@ -186,6 +186,15 @@ define Device/sinovoip_bananapi-m3 endef TARGET_DEVICES += sinovoip_bananapi-m3 +define Device/sinovoip_bananapi-p2-zero + DEVICE_VENDOR := Sinovoip + DEVICE_MODEL := Banana Pi P2 Zero + DEVICE_PACKAGES:=kmod-leds-gpio kmod-brcmfmac \ + cypress-firmware-43430-sdio wpad-basic-mbedtls + SOC := sun8i-h2-plus +endef +TARGET_DEVICES += sinovoip_bananapi-p2-zero + define Device/xunlong_orangepi-one DEVICE_VENDOR := Xunlong DEVICE_MODEL := Orange Pi One diff --git a/target/linux/sunxi/patches-6.1/410-sunxi-add-bananapi-p2-zero.patch b/target/linux/sunxi/patches-6.1/410-sunxi-add-bananapi-p2-zero.patch new file mode 100644 index 0000000000..3bc55b8cfc --- /dev/null +++ b/target/linux/sunxi/patches-6.1/410-sunxi-add-bananapi-p2-zero.patch @@ -0,0 +1,292 @@ +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -1348,6 +1348,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ + sun8i-a83t-cubietruck-plus.dtb \ + sun8i-a83t-tbs-a711.dtb \ + sun8i-h2-plus-bananapi-m2-zero.dtb \ ++ sun8i-h2-plus-bananapi-p2-zero.dtb \ + sun8i-h2-plus-libretech-all-h3-cc.dtb \ + sun8i-h2-plus-orangepi-r1.dtb \ + sun8i-h2-plus-orangepi-zero.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/sun8i-h2-plus-bananapi-p2-zero.dts +@@ -0,0 +1,279 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (C) 2023 Zoltan HERPAI ++ * ++ * Based on sun8i-h2-plus-bananapi-m2-zero.dts, which is: ++ * Copyright (C) 2017 Icenowy Zheng ++ */ ++ ++/dts-v1/; ++#include "sun8i-h3.dtsi" ++#include "sunxi-common-regulators.dtsi" ++ ++#include ++#include ++ ++/ { ++ model = "Banana Pi BPI-P2-Zero"; ++ compatible = "sinovoip,bpi-p2-zero", "allwinner,sun8i-h2-plus"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ connector { ++ compatible = "hdmi-connector"; ++ type = "c"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ pwr_led { ++ label = "bananapi-p2-zero:red:pwr"; ++ gpios = <&r_pio 0 10 GPIO_ACTIVE_LOW>; /* PL10 */ ++ default-state = "on"; ++ }; ++ }; ++ ++ gpio_keys { ++ compatible = "gpio-keys"; ++ ++ sw4 { ++ label = "power"; ++ linux,code = ; ++ gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ reg_vdd_cpux: vdd-cpux-regulator { ++ compatible = "regulator-gpio"; ++ regulator-name = "vdd-cpux"; ++ regulator-type = "voltage"; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1300000>; ++ regulator-ramp-delay = <50>; /* 4ms */ ++ ++ gpios = <&r_pio 0 1 GPIO_ACTIVE_HIGH>; /* PL1 */ ++ enable-active-high; ++ gpios-states = <0x1>; ++ states = <1100000 0>, <1300000 1>; ++ }; ++ ++ reg_vcc_dram: vcc-dram { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-dram"; ++ regulator-min-microvolt = <1500000>; ++ regulator-max-microvolt = <1500000>; ++ regulator-always-on; ++ regulator-boot-on; ++ enable-active-high; ++ gpio = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */ ++ vin-supply = <®_vcc5v0>; ++ }; ++ ++ reg_vcc1v2: vcc1v2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc1v2"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-always-on; ++ regulator-boot-on; ++ enable-active-high; ++ gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */ ++ vin-supply = <®_vcc5v0>; ++ }; ++ ++ poweroff { ++ compatible = "regulator-poweroff"; ++ cpu-supply = <®_vcc1v2>; ++ }; ++ ++ wifi_pwrseq: wifi_pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */ ++ clocks = <&rtc 1>; ++ clock-names = "ext_clock"; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <®_vdd_cpux>; ++}; ++ ++&de { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&emac { ++ phy-handle = <&int_mii_phy>; ++ phy-mode = "mii"; ++ allwinner,leds-active-low; ++ status = "okay"; ++}; ++ ++&hdmi { ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ ++&mmc0 { ++ vmmc-supply = <®_vcc3v3>; ++ bus-width = <4>; ++ /* ++ * On the production batch of this board the card detect GPIO is ++ * high active (card inserted), although on the early samples it's ++ * low active. ++ */ ++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ ++ status = "okay"; ++}; ++ ++&mmc1 { ++ vmmc-supply = <®_vcc3v3>; ++ vqmmc-supply = <®_vcc3v3>; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ bus-width = <4>; ++ non-removable; ++ status = "okay"; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ interrupt-parent = <&pio>; ++ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 / EINT10 */ ++ interrupt-names = "host-wake"; ++ }; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pa_pins>; ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ uart-has-rtscts; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ max-speed = <1500000>; ++ clocks = <&rtc 1>; ++ clock-names = "lpo"; ++ vbat-supply = <®_vcc3v3>; ++ vddio-supply = <®_vcc3v3>; ++ device-wakeup-gpios = <&pio 6 13 GPIO_ACTIVE_HIGH>; /* PG13 */ ++ host-wakeup-gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>; /* PG11 */ ++ shutdown-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */ ++ }; ++ ++}; ++ ++&pio { ++ gpio-line-names = ++ /* PA */ ++ "CON2-P13", "CON2-P11", "CON2-P22", "CON2-P15", ++ "CON3-P03", "CON3-P02", "CON2-P07", "CON2-P29", ++ "CON2-P31", "CON2-P33", "CON2-P35", "CON2-P05", ++ "CON2-P03", "CON2-P08", "CON2-P10", "CON2-P16", ++ "CON2-P12", "CON2-P37", "CON2-P28", "CON2-P27", ++ "CON2-P40", "CON2-P38", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PB */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PC */ ++ "CON2-P19", "CON2-P21", "CON2-P23", "CON2-P24", ++ "CON2-P18", "", "", "CON2-P26", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PD */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "CSI-PWR-EN", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PE */ ++ "CN3-P17", "CN3-P13", "CN3-P09", "CN3-P07", ++ "CN3-P19", "CN3-P21", "CN3-P22", "CN3-P20", ++ "CN3-P18", "CN3-P16", "CN3-P14", "CN3-P12", ++ "CN3-P05", "CN3-P03", "CN3-P06", "CN3-P08", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PF */ ++ "SDC0-D1", "SDC0-D0", "SDC0-CLK", "SDC0-CMD", "SDC0-D3", ++ "SDC0-D2", "SDC0-DET", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ ++ /* PG */ ++ "WL-SDIO-CLK", "WL-SDIO-CMD", "WL-SDIO-D0", "WL-SDIO-D1", ++ "WL-SDIO-D2", "WL-SDIO-D3", "BT-UART-TX", "BT-UART-RX", ++ "BT-UART-RTS", "BT-UART-CTS", "WL-WAKE-AP", "BT-WAKE-AP", ++ "BT-RST-N", "AP-WAKE-BT", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", ""; ++}; ++ ++&r_pio { ++ gpio-line-names = ++ /* PL */ ++ "", "CPUX-SET", "CON2-P32", "POWER-KEY", "CON2-P36", ++ "VCC-IO-EN", "USB0-ID", "WL-PWR-EN", ++ "PWR-STB", "PWR-DRAM", "PWR-LED", "IR-RX", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", ""; ++}; ++ ++&usb_otg { ++ dr_mode = "otg"; ++ status = "okay"; ++}; ++ ++&usbphy { ++ usb0_id_det-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */ ++ /* ++ * There're two micro-USB connectors, one is power-only and another is ++ * OTG. The Vbus of these two connectors are connected together, so ++ * the external USB device will be powered just by the power input ++ * from the power-only USB port. ++ */ ++ status = "okay"; ++};