diff --git a/patches/openwrt/0006-reset-ath79-fix-reset-sequence-for-AR9344.patch b/patches/openwrt/0006-reset-ath79-fix-reset-sequence-for-AR9344.patch new file mode 100644 index 0000000000000000000000000000000000000000..3e55581695e2b5a03d1d321d89f34135b2b9dbcd --- /dev/null +++ b/patches/openwrt/0006-reset-ath79-fix-reset-sequence-for-AR9344.patch @@ -0,0 +1,92 @@ +From: Nico <github@nicoboehr.de> +Date: Mon, 16 Dec 2024 22:19:01 +0000 +Subject: reset: ath79: fix reset sequence for AR9344 + +According to datasheet, on AR9344 the switch and switch analog need to +be reset first before initiating a full reset. + +This fixes sporadic reboot issues. Instead of rebooting, the device will +just hang. Without this patch, I had failed resets after 5, 20 and 250 +tries. With this patch I have more than 2200 successful resets. + +Other chips like AR7100 do not have this specific requirement in the +datasheet and also the meaning for bits 8 and 12 is slightly different, +so only perform this sequence on AR9344. + +diff --git a/target/linux/ath79/patches-6.6/940-ath79-fix-reset-sequence.patch b/target/linux/ath79/patches-6.6/940-ath79-fix-reset-sequence.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..dccb8449e9cc03701495afcbc4196540d0b1c15d +--- /dev/null ++++ b/target/linux/ath79/patches-6.6/940-ath79-fix-reset-sequence.patch +@@ -0,0 +1,71 @@ ++--- a/drivers/reset/reset-ath79.c +++++ b/drivers/reset/reset-ath79.c ++@@ -12,6 +12,8 @@ ++ #include <linux/platform_device.h> ++ #include <linux/reset-controller.h> ++ #include <linux/reboot.h> +++#include <linux/delay.h> +++#include <linux/of.h> ++ ++ struct ath79_reset { ++ struct reset_controller_dev rcdev; ++@@ -21,16 +23,13 @@ struct ath79_reset { ++ }; ++ ++ #define FULL_CHIP_RESET 24 +++#define ETH_SWITCH_RESET 8 +++#define ETH_SWITCH_ARESET 12 ++ ++-static int ath79_reset_update(struct reset_controller_dev *rcdev, +++static void __ath79_reset_update_unlocked(struct ath79_reset *ath79_reset, ++ unsigned long id, bool assert) ++ { ++- struct ath79_reset *ath79_reset = ++- container_of(rcdev, struct ath79_reset, rcdev); ++- unsigned long flags; ++ u32 val; ++- ++- spin_lock_irqsave(&ath79_reset->lock, flags); ++ val = readl(ath79_reset->base); ++ if (assert) ++ val |= BIT(id); ++@@ -39,6 +38,17 @@ static int ath79_reset_update(struct res ++ writel(val, ath79_reset->base); ++ /* Flush cache */ ++ readl(ath79_reset->base); +++} +++ +++static int ath79_reset_update(struct reset_controller_dev *rcdev, +++ unsigned long id, bool assert) +++{ +++ struct ath79_reset *ath79_reset = +++ container_of(rcdev, struct ath79_reset, rcdev); +++ unsigned long flags; +++ +++ spin_lock_irqsave(&ath79_reset->lock, flags); +++ __ath79_reset_update_unlocked(ath79_reset, id, assert); ++ spin_unlock_irqrestore(&ath79_reset->lock, flags); ++ ++ return 0; ++@@ -79,8 +89,20 @@ static int ath79_reset_restart_handler(s ++ { ++ struct ath79_reset *ath79_reset = ++ container_of(nb, struct ath79_reset, restart_nb); +++ unsigned long flags; ++ ++- ath79_reset_assert(&ath79_reset->rcdev, FULL_CHIP_RESET); +++ spin_lock_irqsave(&ath79_reset->lock, flags); +++ /* special reset sequence required for AR9344 - see datasheet p 111 */ +++ if (of_machine_is_compatible("qca,ar9344")) { +++ __ath79_reset_update_unlocked(ath79_reset, ETH_SWITCH_RESET, true); +++ mdelay(2); +++ __ath79_reset_update_unlocked(ath79_reset, ETH_SWITCH_ARESET, true); +++ mdelay(2); +++ __ath79_reset_update_unlocked(ath79_reset, FULL_CHIP_RESET, true); +++ mdelay(10); +++ } else +++ __ath79_reset_update_unlocked(ath79_reset, FULL_CHIP_RESET, true); +++ spin_unlock_irqrestore(&ath79_reset->lock, flags); ++ ++ return NOTIFY_DONE; ++ }