Skip to content

Commit

Permalink
Merge pull request #545 from grische/patch/ath79-fix-reset-sequence-f…
Browse files Browse the repository at this point in the history
…or-ar9344

[gluon-v2023.2.x] patches: ath79: fix reset sequence for AR9344
  • Loading branch information
grische authored Jan 3, 2025
2 parents f60a393 + 1bbf123 commit a8d21fb
Showing 1 changed file with 123 additions and 0 deletions.
123 changes: 123 additions & 0 deletions patches/0001-reset-ath79-fix-reset-sequence-for-AR9344.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
From 4d9905d11f34784183fca3ef4f70dacc949c5ff6 Mon Sep 17 00:00:00 2001
From: nrb <[email protected]>
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 <[email protected]>
---
...-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 <[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-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 <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;
++ }
--
2.34.1

0 comments on commit a8d21fb

Please sign in to comment.