Skip to content

Commit

Permalink
reset: ath79: fix reset sequence for AR9344
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
nrbffs committed Dec 17, 2024
1 parent b180fc2 commit e96843b
Showing 1 changed file with 92 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
From: Nico <[email protected]>
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;
+ }

0 comments on commit e96843b

Please sign in to comment.