diff --git a/patches/0001-reset-ath79-fix-reset-sequence-for-AR9344.patch b/patches/0001-reset-ath79-fix-reset-sequence-for-AR9344.patch new file mode 100644 index 00000000..11281600 --- /dev/null +++ b/patches/0001-reset-ath79-fix-reset-sequence-for-AR9344.patch @@ -0,0 +1,123 @@ +From 4d9905d11f34784183fca3ef4f70dacc949c5ff6 Mon Sep 17 00:00:00 2001 +From: nrb <38812627+nrbffs@users.noreply.github.com> +Date: Tue, 17 Dec 2024 18:52:03 +0100 +Subject: [PATCH] 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. + +Signed-off-by: Nico Boehr +--- + ...-ath79-fix-reset-sequence-for-AR9344.patch | 92 +++++++++++++++++++ + 1 file changed, 92 insertions(+) + create mode 100644 patches/openwrt/0006-reset-ath79-fix-reset-sequence-for-AR9344.patch + +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 00000000..2d310e1d +--- /dev/null ++++ b/patches/openwrt/0006-reset-ath79-fix-reset-sequence-for-AR9344.patch +@@ -0,0 +1,92 @@ ++From: Nico ++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-5.15/941-ath79-fix-reset-sequence.patch b/target/linux/ath79/patches-5.15/941-ath79-fix-reset-sequence.patch ++new file mode 100644 ++index 0000000000000000000000000000000000000000..dccb8449e9cc03701495afcbc4196540d0b1c15d ++--- /dev/null +++++ b/target/linux/ath79/patches-5.15/941-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 +++ #include +++ #include ++++#include ++++#include +++ +++ 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; +++ } +-- +2.34.1 +