summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIdo Reis <idor@ti.com>2012-04-23 14:35:25 (GMT)
committerLuciano Coelho <coelho@ti.com>2012-06-07 15:11:01 (GMT)
commitf5755fe96cb010031a50458e6d1391377d94c275 (patch)
treeb33e6dc91f3a3d1c5e975a4553973d7cd2761eef
parent16ea4733210d741eeb5413acd261e675a12f980e (diff)
downloadlinux-fsl-qoriq-f5755fe96cb010031a50458e6d1391377d94c275.tar.xz
wl18xx: PG2.0 HW Watch dog interrupt support
In PG2, the HW watchdog interrupt occupies bit0 of the event vector, and the SW watchdog is relocated to bit9. We perform the relocation globally, as there's only one watchdog bit on previous platforms (bit0). [Only mask in the new bit9 for platforms supporting it. This avoids spurious events on other platforms - Arik] Signed-off-by: Orit Brayer <orit@ti.com> Signed-off-by: Ido Reis <idor@ti.com> Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
-rw-r--r--drivers/net/wireless/ti/wl12xx/acx.h14
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c4
-rw-r--r--drivers/net/wireless/ti/wl18xx/acx.h20
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c14
-rw-r--r--drivers/net/wireless/ti/wlcore/acx.h27
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c13
6 files changed, 71 insertions, 21 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/acx.h b/drivers/net/wireless/ti/wl12xx/acx.h
index 1be0f2d..2a26868 100644
--- a/drivers/net/wireless/ti/wl12xx/acx.h
+++ b/drivers/net/wireless/ti/wl12xx/acx.h
@@ -26,6 +26,20 @@
#include "../wlcore/wlcore.h"
#include "../wlcore/acx.h"
+#define WL12XX_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \
+ WL1271_ACX_INTR_INIT_COMPLETE | \
+ WL1271_ACX_INTR_EVENT_A | \
+ WL1271_ACX_INTR_EVENT_B | \
+ WL1271_ACX_INTR_CMD_COMPLETE | \
+ WL1271_ACX_INTR_HW_AVAILABLE | \
+ WL1271_ACX_INTR_DATA)
+
+#define WL12XX_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \
+ WL1271_ACX_INTR_EVENT_A | \
+ WL1271_ACX_INTR_EVENT_B | \
+ WL1271_ACX_INTR_HW_AVAILABLE | \
+ WL1271_ACX_INTR_DATA)
+
struct wl1271_acx_host_config_bitmap {
struct acx_header header;
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 41017ba..f74d76c 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1034,11 +1034,11 @@ static void wl12xx_pre_upload(struct wl1271 *wl)
static void wl12xx_enable_interrupts(struct wl1271 *wl)
{
- wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR);
+ wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL12XX_ACX_ALL_EVENTS_VECTOR);
wlcore_enable_interrupts(wl);
wlcore_write_reg(wl, REG_INTERRUPT_MASK,
- WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
+ WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK));
wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
}
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h
index cb6fd85..7d74b03 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.h
+++ b/drivers/net/wireless/ti/wl18xx/acx.h
@@ -28,6 +28,26 @@
/* numbers of bits the length field takes (add 1 for the actual number) */
#define WL18XX_HOST_IF_LEN_SIZE_FIELD 15
+#define WL18XX_ACX_EVENTS_VECTOR_PG1 (WL1271_ACX_INTR_WATCHDOG | \
+ WL1271_ACX_INTR_INIT_COMPLETE | \
+ WL1271_ACX_INTR_EVENT_A | \
+ WL1271_ACX_INTR_EVENT_B | \
+ WL1271_ACX_INTR_CMD_COMPLETE | \
+ WL1271_ACX_INTR_HW_AVAILABLE | \
+ WL1271_ACX_INTR_DATA)
+
+#define WL18XX_ACX_EVENTS_VECTOR_PG2 (WL18XX_ACX_EVENTS_VECTOR_PG1 | \
+ WL1271_ACX_SW_INTR_WATCHDOG)
+
+#define WL18XX_INTR_MASK_PG1 (WL1271_ACX_INTR_WATCHDOG | \
+ WL1271_ACX_INTR_EVENT_A | \
+ WL1271_ACX_INTR_EVENT_B | \
+ WL1271_ACX_INTR_HW_AVAILABLE | \
+ WL1271_ACX_INTR_DATA)
+
+#define WL18XX_INTR_MASK_PG2 (WL18XX_INTR_MASK_PG1 | \
+ WL1271_ACX_SW_INTR_WATCHDOG)
+
struct wl18xx_acx_host_config_bitmap {
struct acx_header header;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index bdf4ee1..84f8e27 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -776,11 +776,21 @@ static void wl18xx_set_mac_and_phy(struct wl1271 *wl)
static void wl18xx_enable_interrupts(struct wl1271 *wl)
{
- wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR);
+ u32 event_mask, intr_mask;
+
+ if (wl->chip.id == CHIP_ID_185x_PG10) {
+ event_mask = WL18XX_ACX_EVENTS_VECTOR_PG1;
+ intr_mask = WL18XX_INTR_MASK_PG1;
+ } else {
+ event_mask = WL18XX_ACX_EVENTS_VECTOR_PG2;
+ intr_mask = WL18XX_INTR_MASK_PG2;
+ }
+
+ wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask);
wlcore_enable_interrupts(wl);
wlcore_write_reg(wl, REG_INTERRUPT_MASK,
- WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
+ WL1271_ACX_INTR_ALL & ~intr_mask);
}
static int wl18xx_boot(struct wl1271 *wl)
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index 46c300d..c018125 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -51,21 +51,18 @@
#define WL1271_ACX_INTR_TRACE_A BIT(7)
/* Trace message on MBOX #B */
#define WL1271_ACX_INTR_TRACE_B BIT(8)
-
-#define WL1271_ACX_INTR_ALL 0xFFFFFFFF
-#define WL1271_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \
- WL1271_ACX_INTR_INIT_COMPLETE | \
- WL1271_ACX_INTR_EVENT_A | \
- WL1271_ACX_INTR_EVENT_B | \
- WL1271_ACX_INTR_CMD_COMPLETE | \
- WL1271_ACX_INTR_HW_AVAILABLE | \
- WL1271_ACX_INTR_DATA)
-
-#define WL1271_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \
- WL1271_ACX_INTR_EVENT_A | \
- WL1271_ACX_INTR_EVENT_B | \
- WL1271_ACX_INTR_HW_AVAILABLE | \
- WL1271_ACX_INTR_DATA)
+/* SW FW Initiated interrupt Watchdog timer expiration */
+#define WL1271_ACX_SW_INTR_WATCHDOG BIT(9)
+
+#define WL1271_ACX_INTR_ALL 0xFFFFFFFF
+
+/* all possible interrupts - only appropriate ones will be masked in */
+#define WLCORE_ALL_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \
+ WL1271_ACX_INTR_EVENT_A | \
+ WL1271_ACX_INTR_EVENT_B | \
+ WL1271_ACX_INTR_HW_AVAILABLE | \
+ WL1271_ACX_INTR_DATA | \
+ WL1271_ACX_SW_INTR_WATCHDOG)
/* Target's information element */
struct acx_header {
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 8800a63..176a311 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -535,14 +535,23 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
wlcore_hw_tx_immediate_compl(wl);
intr = le32_to_cpu(wl->fw_status_1->intr);
- intr &= WL1271_INTR_MASK;
+ intr &= WLCORE_ALL_INTR_MASK;
if (!intr) {
done = true;
continue;
}
if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {
- wl1271_error("watchdog interrupt received! "
+ wl1271_error("HW watchdog interrupt received! starting recovery.");
+ wl->watchdog_recovery = true;
+ wl12xx_queue_recovery_work(wl);
+
+ /* restarting the chip. ignore any other interrupt. */
+ goto out;
+ }
+
+ if (unlikely(intr & WL1271_ACX_SW_INTR_WATCHDOG)) {
+ wl1271_error("SW watchdog interrupt received! "
"starting recovery.");
wl->watchdog_recovery = true;
wl12xx_queue_recovery_work(wl);