diff options
| author | David Bauer | 2025-01-03 20:46:13 +0000 |
|---|---|---|
| committer | Hauke Mehrtens | 2025-08-14 18:27:40 +0000 |
| commit | 539228933caab51a21c239ec3b7e8f7a366e96b9 (patch) | |
| tree | dc65992ce796d73f2fa9bdf67ed02c8fe7093e54 | |
| parent | fc876e9d50c701280fa27ea3f122672643163346 (diff) | |
| download | openwrt-539228933caab51a21c239ec3b7e8f7a366e96b9.tar.gz | |
ath79: add extended AR9344 reset sequence
According to datasheet, on AR9344 the switch and switch analog need to
be reset first before initiating a full reset.
Resetting these systems fixes spurious reset hangs on Atheros AR9344
SoCs.
Link: https://github.com/freifunk-gluon/gluon/issues/2904
Signed-off-by: David Bauer <mail@david-bauer.net>
(cherry picked from commit 144af32b47be6181f01815762159dff863f4616b)
account for
torvalds/linux/commit/41ccb3a0eb57741eebd72e51e011ef098bb1493d
torvalds/linux/commit/5eddff6add4feebac625f256d2fe292935351ce3
[felix.bau@gmx.de: adjust patch so it applies without commits above]
Signed-off-by: Felix Baumann <felix.bau@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/19759
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
| -rw-r--r-- | target/linux/ath79/patches-5.15/101-reset-ath79-reset-ETH-switch-for-AR9344.patch | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/target/linux/ath79/patches-5.15/101-reset-ath79-reset-ETH-switch-for-AR9344.patch b/target/linux/ath79/patches-5.15/101-reset-ath79-reset-ETH-switch-for-AR9344.patch new file mode 100644 index 0000000000..c4cfbf6124 --- /dev/null +++ b/target/linux/ath79/patches-5.15/101-reset-ath79-reset-ETH-switch-for-AR9344.patch @@ -0,0 +1,105 @@ +From: David Bauer <mail@david-bauer.net> +Date: Tue, 2 Jan 2025 19:22:40 +0100 +Subject: [PATCH] reset: ath79: reset ETH switch for AR9344 + +According to datasheet, on AR9344 the switch and switch analog need to +be reset first before initiating a full reset. + +Resetting these systems fixes spurious reset hangs on Atheros AR9344 +SoCs. + +Link: https://github.com/freifunk-gluon/gluon/issues/2904 + +Signed-off-by: David Bauer <mail@david-bauer.net> + +--- a/drivers/reset/reset-ath79.c ++++ b/drivers/reset/reset-ath79.c +@@ -12,8 +12,11 @@ + #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 platform_device *pdev; + struct reset_controller_dev rcdev; + struct notifier_block restart_nb; + void __iomem *base; +@@ -21,16 +24,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 +39,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 +90,28 @@ 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); ++ ++ if (of_device_is_compatible(ath79_reset->pdev->dev.of_node, "qca,ar9340-reset")) { ++ /** ++ * AR9344 has been observed to hang on reboot in rare cases. ++ * ++ * Datasheet states to reset the ETH switch systems before asserting ++ * full chip reset. See page 111 of the AR9344 datasheet. ++ */ ++ __ath79_reset_update_unlocked(ath79_reset, ETH_SWITCH_RESET, true); ++ mdelay(1); ++ __ath79_reset_update_unlocked(ath79_reset, ETH_SWITCH_ARESET, true); ++ mdelay(1); ++ __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; + } +@@ -96,6 +127,8 @@ static int ath79_reset_probe(struct plat + if (!ath79_reset) + return -ENOMEM; + ++ ath79_reset->pdev = pdev; ++ + platform_set_drvdata(pdev, ath79_reset); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |