wl18xx: FDSP Code RAM Corruption fix
authorIdo Reis <idor@ti.com>
Tue, 27 Nov 2012 06:44:51 +0000 (08:44 +0200)
committerLuciano Coelho <coelho@ti.com>
Mon, 17 Jun 2013 08:56:58 +0000 (11:56 +0300)
In PG2.0 there is an issue where PHY's FDSP Code RAM sometimes gets
corrupted when exiting from ELP mode. This issue is related to FDSP
Code RAM clock implementation.

PG2.1 introduces a HW fix for this issue that requires the driver to
change the FDSP Code Ram clock settings (mux it to ATGP clock instead
of its own clock).

This workaround uses PHY_FPGA_SPARE_1 register and is relevant to WL8
PG2.1 devices.

The fix is also backward compatible with older PG2.0 devices where the
register PHY_FPGA_SPARE_1 is not used and not connected.

The fix is done in the wl18xx_pre_upload function (must be performed
before uploading the FW code) and includes the following steps:

1. Disable FDSP clock
2. Set ATPG clock toward FDSP Code RAM rather than its own clock.
3. Re-enable FDSP clock

Signed-off-by: Yair Shapira <yair.shapira@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>
drivers/net/wireless/ti/wl18xx/main.c
drivers/net/wireless/ti/wl18xx/reg.h

index 9fa692d110250bde779c627e66af87e10ba4f5f2..ae85ae46c61b4d23f9494847f8c79dc800a97632 100644 (file)
@@ -594,8 +594,8 @@ static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
                .mem3 = { .start = 0x00000000, .size  = 0x00000000 },
        },
        [PART_PHY_INIT] = {
-               .mem  = { .start = 0x80926000,
-                         .size = sizeof(struct wl18xx_mac_and_phy_params) },
+               .mem  = { .start = WL18XX_PHY_INIT_MEM_ADDR,
+                         .size  = WL18XX_PHY_INIT_MEM_SIZE },
                .reg  = { .start = 0x00000000, .size = 0x00000000 },
                .mem2 = { .start = 0x00000000, .size = 0x00000000 },
                .mem3 = { .start = 0x00000000, .size = 0x00000000 },
@@ -799,6 +799,9 @@ static int wl18xx_pre_upload(struct wl1271 *wl)
        u32 tmp;
        int ret;
 
+       BUILD_BUG_ON(sizeof(struct wl18xx_mac_and_phy_params) >
+               WL18XX_PHY_INIT_MEM_SIZE);
+
        ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
        if (ret < 0)
                goto out;
@@ -815,6 +818,35 @@ static int wl18xx_pre_upload(struct wl1271 *wl)
        wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
 
        ret = wlcore_read32(wl, WL18XX_SCR_PAD2, &tmp);
+       if (ret < 0)
+               goto out;
+
+       /*
+        * Workaround for FDSP code RAM corruption (needed for PG2.1
+        * and newer; for older chips it's a NOP).  Change FDSP clock
+        * settings so that it's muxed to the ATGP clock instead of
+        * its own clock.
+        */
+
+       ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
+       if (ret < 0)
+               goto out;
+
+       /* disable FDSP clock */
+       ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
+                            MEM_FDSP_CLK_120_DISABLE);
+       if (ret < 0)
+               goto out;
+
+       /* set ATPG clock toward FDSP Code RAM rather than its own clock */
+       ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
+                            MEM_FDSP_CODERAM_FUNC_CLK_SEL);
+       if (ret < 0)
+               goto out;
+
+       /* re-enable FDSP clock */
+       ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
+                            MEM_FDSP_CLK_120_ENABLE);
 
 out:
        return ret;
index 6306e04cd2580676e6683ae62a64cecc3578c719..05dd8bad27469389e0e5ff3cf713fab083d348d5 100644 (file)
@@ -38,6 +38,9 @@
 #define WL18XX_REG_BOOT_PART_SIZE  0x00014578
 
 #define WL18XX_PHY_INIT_MEM_ADDR   0x80926000
+#define WL18XX_PHY_END_MEM_ADDR           0x8093CA44
+#define WL18XX_PHY_INIT_MEM_SIZE \
+       (WL18XX_PHY_END_MEM_ADDR - WL18XX_PHY_INIT_MEM_ADDR)
 
 #define WL18XX_SDIO_WSPI_BASE          (WL18XX_REGISTERS_BASE)
 #define WL18XX_REG_CONFIG_BASE         (WL18XX_REGISTERS_BASE + 0x02000)
@@ -217,4 +220,16 @@ static const char * const rdl_names[] = {
        [RDL_4_SP]      = "1897 MIMO",
 };
 
+/* FPGA_SPARE_1 register - used to change the PHY ATPG clock at boot time */
+#define WL18XX_PHY_FPGA_SPARE_1                0x8093CA40
+
+/* command to disable FDSP clock */
+#define MEM_FDSP_CLK_120_DISABLE        0x80000000
+
+/* command to set ATPG clock toward FDSP Code RAM rather than its own clock */
+#define MEM_FDSP_CODERAM_FUNC_CLK_SEL  0xC0000000
+
+/* command to re-enable FDSP clock */
+#define MEM_FDSP_CLK_120_ENABLE                0x40000000
+
 #endif /* __REG_H__ */