Skip to content
Snippets Groups Projects
Unverified Commit 5765d033 authored by nrb's avatar nrb
Browse files

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: default avatarNico Boehr <github-ffs@nicoboehr.de>
parent b180fc28
No related branches found
No related tags found
No related merge requests found
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;
+ }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment