wlcore: Propagate errors from wl1271_raw_read32

Propagate errors from wl1271_raw_read32. Since the read functions had no
way of returning errors in-band, change their prototypes.
Also rename prefixes of wlcore functions which their prototypes had to
be changed.

Signed-off-by: Ido Yariv <ido@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
Ido Yariv 2012-06-18 15:50:21 +03:00 committed by Luciano Coelho
parent eb96f841b9
commit 6134323f42
9 changed files with 309 additions and 113 deletions

View file

@ -701,10 +701,11 @@ static void wl12xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE); wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE);
} }
static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr) static int wl12xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out)
{ {
u32 val; u32 val;
int timeout = OCP_CMD_LOOP; int timeout = OCP_CMD_LOOP;
int ret;
/* write address >> 1 + 0x30000 to OCP_POR_CTR */ /* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr = (addr >> 1) + 0x30000; addr = (addr >> 1) + 0x30000;
@ -715,29 +716,38 @@ static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr)
/* poll for data ready */ /* poll for data ready */
do { do {
val = wl1271_read32(wl, WL12XX_OCP_DATA_READ); ret = wlcore_read32(wl, WL12XX_OCP_DATA_READ, &val);
if (ret < 0)
return ret;
} while (!(val & OCP_READY_MASK) && --timeout); } while (!(val & OCP_READY_MASK) && --timeout);
if (!timeout) { if (!timeout) {
wl1271_warning("Top register access timed out."); wl1271_warning("Top register access timed out.");
return 0xffff; return -ETIMEDOUT;
} }
/* check data status and return if OK */ /* check data status and return if OK */
if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) if ((val & OCP_STATUS_MASK) != OCP_STATUS_OK) {
return val & 0xffff;
else {
wl1271_warning("Top register access returned error."); wl1271_warning("Top register access returned error.");
return 0xffff; return -EIO;
} }
if (out)
*out = val & 0xffff;
return 0;
} }
static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
{ {
u16 spare_reg; u16 spare_reg;
int ret;
/* Mask bits [2] & [8:4] in the sys_clk_cfg register */ /* Mask bits [2] & [8:4] in the sys_clk_cfg register */
spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg);
if (ret < 0)
return ret;
if (spare_reg == 0xFFFF) if (spare_reg == 0xFFFF)
return -EFAULT; return -EFAULT;
spare_reg |= (BIT(3) | BIT(5) | BIT(6)); spare_reg |= (BIT(3) | BIT(5) | BIT(6));
@ -756,8 +766,12 @@ static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
static bool wl128x_is_tcxo_valid(struct wl1271 *wl) static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
{ {
u16 tcxo_detection; u16 tcxo_detection;
int ret;
ret = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG, &tcxo_detection);
if (ret < 0)
return false;
tcxo_detection = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG);
if (tcxo_detection & TCXO_DET_FAILED) if (tcxo_detection & TCXO_DET_FAILED)
return false; return false;
@ -767,8 +781,12 @@ static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
static bool wl128x_is_fref_valid(struct wl1271 *wl) static bool wl128x_is_fref_valid(struct wl1271 *wl)
{ {
u16 fref_detection; u16 fref_detection;
int ret;
ret = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG, &fref_detection);
if (ret < 0)
return false;
fref_detection = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG);
if (fref_detection & FREF_CLK_DETECT_FAIL) if (fref_detection & FREF_CLK_DETECT_FAIL)
return false; return false;
@ -790,9 +808,13 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
u16 pll_config; u16 pll_config;
u8 input_freq; u8 input_freq;
struct wl12xx_priv *priv = wl->priv; struct wl12xx_priv *priv = wl->priv;
int ret;
/* Mask bits [3:1] in the sys_clk_cfg register */ /* Mask bits [3:1] in the sys_clk_cfg register */
spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg);
if (ret < 0)
return ret;
if (spare_reg == 0xFFFF) if (spare_reg == 0xFFFF)
return -EFAULT; return -EFAULT;
spare_reg |= BIT(2); spare_reg |= BIT(2);
@ -806,7 +828,10 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
/* Set the input frequency according to the selected clock source */ /* Set the input frequency according to the selected clock source */
input_freq = (clk & 1) + 1; input_freq = (clk & 1) + 1;
pll_config = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG); ret = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG, &pll_config);
if (ret < 0)
return ret;
if (pll_config == 0xFFFF) if (pll_config == 0xFFFF)
return -EFAULT; return -EFAULT;
pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
@ -827,6 +852,7 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
{ {
struct wl12xx_priv *priv = wl->priv; struct wl12xx_priv *priv = wl->priv;
u16 sys_clk_cfg; u16 sys_clk_cfg;
int ret;
/* For XTAL-only modes, FREF will be used after switching from TCXO */ /* For XTAL-only modes, FREF will be used after switching from TCXO */
if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
@ -837,7 +863,10 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
} }
/* Query the HW, to determine which clock source we should use */ /* Query the HW, to determine which clock source we should use */
sys_clk_cfg = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG); ret = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG, &sys_clk_cfg);
if (ret < 0)
return ret;
if (sys_clk_cfg == 0xFFFF) if (sys_clk_cfg == 0xFFFF)
return -EINVAL; return -EINVAL;
if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
@ -872,6 +901,7 @@ static int wl127x_boot_clk(struct wl1271 *wl)
struct wl12xx_priv *priv = wl->priv; struct wl12xx_priv *priv = wl->priv;
u32 pause; u32 pause;
u32 clk; u32 clk;
int ret;
if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
@ -892,18 +922,27 @@ static int wl127x_boot_clk(struct wl1271 *wl)
if (priv->ref_clock != CONF_REF_CLK_19_2_E) { if (priv->ref_clock != CONF_REF_CLK_19_2_E) {
u16 val; u16 val;
/* Set clock type (open drain) */ /* Set clock type (open drain) */
val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE); ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE, &val);
if (ret < 0)
goto out;
val &= FREF_CLK_TYPE_BITS; val &= FREF_CLK_TYPE_BITS;
wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val); wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
/* Set clock pull mode (no pull) */ /* Set clock pull mode (no pull) */
val = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL); ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL, &val);
if (ret < 0)
goto out;
val |= NO_PULL; val |= NO_PULL;
wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val); wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val);
} else { } else {
u16 val; u16 val;
/* Set clock polarity */ /* Set clock polarity */
val = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY); ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY, &val);
if (ret < 0)
goto out;
val &= FREF_CLK_POLARITY_BITS; val &= FREF_CLK_POLARITY_BITS;
val |= CLK_REQ_OUTN_SEL; val |= CLK_REQ_OUTN_SEL;
wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
@ -911,7 +950,9 @@ static int wl127x_boot_clk(struct wl1271 *wl)
wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk); wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk);
pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS); ret = wlcore_read32(wl, WL12XX_PLL_PARAMETERS, &pause);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
@ -919,13 +960,15 @@ static int wl127x_boot_clk(struct wl1271 *wl)
pause |= WU_COUNTER_PAUSE_VAL; pause |= WU_COUNTER_PAUSE_VAL;
wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause); wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);
return 0; out:
return ret;
} }
static int wl1271_boot_soft_reset(struct wl1271 *wl) static int wl1271_boot_soft_reset(struct wl1271 *wl)
{ {
unsigned long timeout; unsigned long timeout;
u32 boot_data; u32 boot_data;
int ret = 0;
/* perform soft reset */ /* perform soft reset */
wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
@ -933,7 +976,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
/* SOFT_RESET is self clearing */ /* SOFT_RESET is self clearing */
timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
while (1) { while (1) {
boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET); ret = wlcore_read32(wl, WL12XX_SLV_SOFT_RESET, &boot_data);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
break; break;
@ -954,7 +1000,8 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
/* disable auto calibration on start*/ /* disable auto calibration on start*/
wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff); wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff);
return 0; out:
return ret;
} }
static int wl12xx_pre_boot(struct wl1271 *wl) static int wl12xx_pre_boot(struct wl1271 *wl)
@ -984,7 +1031,9 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
to be used by DRPw FW. The RTRIM value will be added by the FW to be used by DRPw FW. The RTRIM value will be added by the FW
before taking DRPw out of reset */ before taking DRPw out of reset */
clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START); ret = wlcore_read32(wl, WL12XX_DRPW_SCRATCH_START, &clk);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
@ -1008,9 +1057,11 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
return ret; return ret;
} }
static void wl12xx_pre_upload(struct wl1271 *wl) static int wl12xx_pre_upload(struct wl1271 *wl)
{ {
u32 tmp, polarity; u32 tmp;
u16 polarity;
int ret;
/* write firmware's last address (ie. it's length) to /* write firmware's last address (ie. it's length) to
* ACX_EEPROMLESS_IND_REG */ * ACX_EEPROMLESS_IND_REG */
@ -1018,12 +1069,16 @@ static void wl12xx_pre_upload(struct wl1271 *wl)
wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND); wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND);
tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
/* 6. read the EEPROM parameters */ /* 6. read the EEPROM parameters */
tmp = wl1271_read32(wl, WL12XX_SCR_PAD2); ret = wlcore_read32(wl, WL12XX_SCR_PAD2, &tmp);
if (ret < 0)
goto out;
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */ * to upload_fw) */
@ -1032,12 +1087,16 @@ static void wl12xx_pre_upload(struct wl1271 *wl)
wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
/* polarity must be set before the firmware is loaded */ /* polarity must be set before the firmware is loaded */
polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY); ret = wl12xx_top_reg_read(wl, OCP_REG_POLARITY, &polarity);
if (ret < 0)
goto out;
/* We use HIGH polarity, so unset the LOW bit */ /* We use HIGH polarity, so unset the LOW bit */
polarity &= ~POLARITY_LOW; polarity &= ~POLARITY_LOW;
wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity);
out:
return ret;
} }
static void wl12xx_enable_interrupts(struct wl1271 *wl) static void wl12xx_enable_interrupts(struct wl1271 *wl)
@ -1063,7 +1122,9 @@ static int wl12xx_boot(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
goto out; goto out;
wl12xx_pre_upload(wl); ret = wl12xx_pre_upload(wl);
if (ret < 0)
goto out;
ret = wlcore_boot_upload_firmware(wl); ret = wlcore_boot_upload_firmware(wl);
if (ret < 0) if (ret < 0)
@ -1282,14 +1343,20 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
return supported; return supported;
} }
static void wl12xx_get_fuse_mac(struct wl1271 *wl) static int wl12xx_get_fuse_mac(struct wl1271 *wl)
{ {
u32 mac1, mac2; u32 mac1, mac2;
int ret;
wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1); ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1, &mac1);
mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2); if (ret < 0)
goto out;
ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2, &mac2);
if (ret < 0)
goto out;
/* these are the two parts of the BD_ADDR */ /* these are the two parts of the BD_ADDR */
wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
@ -1297,24 +1364,35 @@ static void wl12xx_get_fuse_mac(struct wl1271 *wl)
wl->fuse_nic_addr = mac1 & 0xffffff; wl->fuse_nic_addr = mac1 & 0xffffff;
wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
out:
return ret;
} }
static s8 wl12xx_get_pg_ver(struct wl1271 *wl) static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
{ {
u32 die_info; u16 die_info;
int ret;
if (wl->chip.id == CHIP_ID_1283_PG20) if (wl->chip.id == CHIP_ID_1283_PG20)
die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1,
&die_info);
else else
die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); ret = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1,
&die_info);
return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET; if (ret >= 0 && ver)
*ver = (s8)((die_info & PG_VER_MASK) >> PG_VER_OFFSET);
return ret;
} }
static void wl12xx_get_mac(struct wl1271 *wl) static int wl12xx_get_mac(struct wl1271 *wl)
{ {
if (wl12xx_mac_in_fuse(wl)) if (wl12xx_mac_in_fuse(wl))
wl12xx_get_fuse_mac(wl); return wl12xx_get_fuse_mac(wl);
return 0;
} }
static void wl12xx_set_tx_desc_csum(struct wl1271 *wl, static void wl12xx_set_tx_desc_csum(struct wl1271 *wl,

View file

@ -24,37 +24,52 @@
#include "io.h" #include "io.h"
void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) int wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
{ {
u32 tmp; u32 tmp;
int ret;
if (WARN_ON(addr % 2)) if (WARN_ON(addr % 2))
return; return -EINVAL;
if ((addr % 4) == 0) { if ((addr % 4) == 0) {
tmp = wl1271_read32(wl, addr); ret = wlcore_read32(wl, addr, &tmp);
if (ret < 0)
goto out;
tmp = (tmp & 0xffff0000) | val; tmp = (tmp & 0xffff0000) | val;
wl1271_write32(wl, addr, tmp); wl1271_write32(wl, addr, tmp);
} else { } else {
tmp = wl1271_read32(wl, addr - 2); ret = wlcore_read32(wl, addr - 2, &tmp);
if (ret < 0)
goto out;
tmp = (tmp & 0xffff) | (val << 16); tmp = (tmp & 0xffff) | (val << 16);
wl1271_write32(wl, addr - 2, tmp); wl1271_write32(wl, addr - 2, tmp);
} }
out:
return ret;
} }
u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr) int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out)
{ {
u32 val; u32 val;
int ret;
if (WARN_ON(addr % 2)) if (WARN_ON(addr % 2))
return 0; return -EINVAL;
if ((addr % 4) == 0) { if ((addr % 4) == 0) {
/* address is 4-bytes aligned */ /* address is 4-bytes aligned */
val = wl1271_read32(wl, addr); ret = wlcore_read32(wl, addr, &val);
return val & 0xffff; if (ret >= 0 && out)
*out = val & 0xffff;
} else { } else {
val = wl1271_read32(wl, addr - 2); ret = wlcore_read32(wl, addr - 2, &val);
return (val & 0xffff0000) >> 16; if (ret >= 0 && out)
*out = (val & 0xffff0000) >> 16;
} }
return ret;
} }

View file

@ -22,7 +22,7 @@
#ifndef __WL18XX_IO_H__ #ifndef __WL18XX_IO_H__
#define __WL18XX_IO_H__ #define __WL18XX_IO_H__
void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val); int wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val);
u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr); int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out);
#endif /* __WL18XX_IO_H__ */ #endif /* __WL18XX_IO_H__ */

View file

@ -636,45 +636,67 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
return ret; return ret;
} }
static void wl18xx_set_clk(struct wl1271 *wl) static int wl18xx_set_clk(struct wl1271 *wl)
{ {
u32 clk_freq; u16 clk_freq;
int ret;
wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
/* TODO: PG2: apparently we need to read the clk type */ /* TODO: PG2: apparently we need to read the clk type */
clk_freq = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT); ret = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT, &clk_freq);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq, wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq,
wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m, wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m,
wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q,
wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit");
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, wl18xx_clk_table[clk_freq].n); ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N,
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, wl18xx_clk_table[clk_freq].m); wl18xx_clk_table[clk_freq].n);
if (ret < 0)
goto out;
ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M,
wl18xx_clk_table[clk_freq].m);
if (ret < 0)
goto out;
if (wl18xx_clk_table[clk_freq].swallow) { if (wl18xx_clk_table[clk_freq].swallow) {
/* first the 16 lower bits */ /* first the 16 lower bits */
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1, ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1,
wl18xx_clk_table[clk_freq].q & wl18xx_clk_table[clk_freq].q &
PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK); PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK);
if (ret < 0)
goto out;
/* then the 16 higher bits, masked out */ /* then the 16 higher bits, masked out */
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2, ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2,
(wl18xx_clk_table[clk_freq].q >> 16) & (wl18xx_clk_table[clk_freq].q >> 16) &
PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK); PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK);
if (ret < 0)
goto out;
/* first the 16 lower bits */ /* first the 16 lower bits */
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1, ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1,
wl18xx_clk_table[clk_freq].p & wl18xx_clk_table[clk_freq].p &
PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK); PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK);
if (ret < 0)
goto out;
/* then the 16 higher bits, masked out */ /* then the 16 higher bits, masked out */
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2, ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2,
(wl18xx_clk_table[clk_freq].p >> 16) & (wl18xx_clk_table[clk_freq].p >> 16) &
PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK); PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK);
} else { } else {
wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN, ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN,
PLLSH_WCS_PLL_SWALLOW_EN_VAL2); PLLSH_WCS_PLL_SWALLOW_EN_VAL2);
} }
out:
return ret;
} }
static void wl18xx_boot_soft_reset(struct wl1271 *wl) static void wl18xx_boot_soft_reset(struct wl1271 *wl)
@ -688,7 +710,11 @@ static void wl18xx_boot_soft_reset(struct wl1271 *wl)
static int wl18xx_pre_boot(struct wl1271 *wl) static int wl18xx_pre_boot(struct wl1271 *wl)
{ {
wl18xx_set_clk(wl); int ret;
ret = wl18xx_set_clk(wl);
if (ret < 0)
goto out;
/* Continue the ELP wake up sequence */ /* Continue the ELP wake up sequence */
wl1271_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); wl1271_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
@ -701,23 +727,30 @@ static int wl18xx_pre_boot(struct wl1271 *wl)
wl18xx_boot_soft_reset(wl); wl18xx_boot_soft_reset(wl);
return 0; out:
return ret;
} }
static void wl18xx_pre_upload(struct wl1271 *wl) static int wl18xx_pre_upload(struct wl1271 *wl)
{ {
u32 tmp; u32 tmp;
int ret;
wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
/* TODO: check if this is all needed */ /* TODO: check if this is all needed */
wl1271_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND); wl1271_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND);
tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp);
if (ret < 0)
goto out;
wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
tmp = wl1271_read32(wl, WL18XX_SCR_PAD2); ret = wlcore_read32(wl, WL18XX_SCR_PAD2, &tmp);
out:
return ret;
} }
static int wl18xx_set_mac_and_phy(struct wl1271 *wl) static int wl18xx_set_mac_and_phy(struct wl1271 *wl)
@ -766,7 +799,9 @@ static int wl18xx_boot(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
goto out; goto out;
wl18xx_pre_upload(wl); ret = wl18xx_pre_upload(wl);
if (ret < 0)
goto out;
ret = wlcore_boot_upload_firmware(wl); ret = wlcore_boot_upload_firmware(wl);
if (ret < 0) if (ret < 0)
@ -998,18 +1033,24 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
} }
} }
static s8 wl18xx_get_pg_ver(struct wl1271 *wl) static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver)
{ {
u32 fuse; u32 fuse;
int ret;
wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
fuse = wl1271_read32(wl, WL18XX_REG_FUSE_DATA_1_3); ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse);
fuse = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; if (ret < 0)
goto out;
if (ver)
*ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET;
wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
return (s8)fuse; out:
return ret;
} }
#define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin" #define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin"
@ -1080,14 +1121,20 @@ static int wl18xx_plt_init(struct wl1271 *wl)
return wl->ops->boot(wl); return wl->ops->boot(wl);
} }
static void wl18xx_get_mac(struct wl1271 *wl) static int wl18xx_get_mac(struct wl1271 *wl)
{ {
u32 mac1, mac2; u32 mac1, mac2;
int ret;
wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
mac1 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1); ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1, &mac1);
mac2 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2); if (ret < 0)
goto out;
ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2, &mac2);
if (ret < 0)
goto out;
/* these are the two parts of the BD_ADDR */ /* these are the two parts of the BD_ADDR */
wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
@ -1095,6 +1142,9 @@ static void wl18xx_get_mac(struct wl1271 *wl)
wl->fuse_nic_addr = (mac1 & 0xffffff); wl->fuse_nic_addr = (mac1 & 0xffffff);
wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
out:
return ret;
} }
static int wl18xx_handle_static_data(struct wl1271 *wl, static int wl18xx_handle_static_data(struct wl1271 *wl,

View file

@ -33,16 +33,22 @@
#include "rx.h" #include "rx.h"
#include "hw_ops.h" #include "hw_ops.h"
static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) static int wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
{ {
u32 cpu_ctrl; u32 cpu_ctrl;
int ret;
/* 10.5.0 run the firmware (I) */ /* 10.5.0 run the firmware (I) */
cpu_ctrl = wlcore_read_reg(wl, REG_ECPU_CONTROL); ret = wlcore_read_reg(wl, REG_ECPU_CONTROL, &cpu_ctrl);
if (ret < 0)
goto out;
/* 10.5.1 run the firmware (II) */ /* 10.5.1 run the firmware (II) */
cpu_ctrl |= flag; cpu_ctrl |= flag;
wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl);
out:
return ret;
} }
static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, static int wlcore_boot_parse_fw_ver(struct wl1271 *wl,
@ -368,9 +374,13 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
/* Make sure we have the boot partition */ /* Make sure we have the boot partition */
wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); ret = wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
if (ret < 0)
return ret;
chip_id = wlcore_read_reg(wl, REG_CHIP_ID_B); ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &chip_id);
if (ret < 0)
return ret;
wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
@ -383,7 +393,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
loop = 0; loop = 0;
while (loop++ < INIT_LOOP) { while (loop++ < INIT_LOOP) {
udelay(INIT_LOOP_DELAY); udelay(INIT_LOOP_DELAY);
intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
if (ret < 0)
return ret;
if (intr == 0xffffffff) { if (intr == 0xffffffff) {
wl1271_error("error reading hardware complete " wl1271_error("error reading hardware complete "
@ -405,12 +417,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
} }
/* get hardware config command mail box */ /* get hardware config command mail box */
wl->cmd_box_addr = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR); ret = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR, &wl->cmd_box_addr);
if (ret < 0)
return ret;
wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr); wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr);
/* get hardware config event mail box */ /* get hardware config event mail box */
wl->mbox_ptr[0] = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR); ret = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR, &wl->mbox_ptr[0]);
if (ret < 0)
return ret;
wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x",

View file

@ -79,7 +79,10 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
if (ret < 0)
goto fail;
while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
wl1271_error("command complete timeout"); wl1271_error("command complete timeout");
@ -93,7 +96,9 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
else else
msleep(1); msleep(1);
intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
if (ret < 0)
goto fail;
} }
/* read back the status code of the command */ /* read back the status code of the command */

View file

@ -77,12 +77,19 @@ static inline int wlcore_raw_write_data(struct wl1271 *wl, int reg, void *buf,
return wlcore_raw_write(wl, wl->rtable[reg], buf, len, fixed); return wlcore_raw_write(wl, wl->rtable[reg], buf, len, fixed);
} }
static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) static inline int wlcore_raw_read32(struct wl1271 *wl, int addr, u32 *val)
{ {
wlcore_raw_read(wl, addr, &wl->buffer_32, int ret;
sizeof(wl->buffer_32), false);
return le32_to_cpu(wl->buffer_32); ret = wlcore_raw_read(wl, addr, &wl->buffer_32,
sizeof(wl->buffer_32), false);
if (ret < 0)
return ret;
if (val)
*val = le32_to_cpu(wl->buffer_32);
return 0;
} }
static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
@ -138,9 +145,9 @@ static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
wlcore_raw_read(wl, physical, buf, len, fixed); wlcore_raw_read(wl, physical, buf, len, fixed);
} }
static inline u32 wl1271_read32(struct wl1271 *wl, int addr) static inline int wlcore_read32(struct wl1271 *wl, int addr, u32 *val)
{ {
return wl1271_raw_read32(wl, wlcore_translate_addr(wl, addr)); return wlcore_raw_read32(wl, wlcore_translate_addr(wl, addr), val);
} }
static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
@ -148,10 +155,11 @@ static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val); wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val);
} }
static inline u32 wlcore_read_reg(struct wl1271 *wl, int reg) static inline int wlcore_read_reg(struct wl1271 *wl, int reg, u32 *val)
{ {
return wl1271_raw_read32(wl, return wlcore_raw_read32(wl,
wlcore_translate_addr(wl, wl->rtable[reg])); wlcore_translate_addr(wl, wl->rtable[reg]),
val);
} }
static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val) static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val)

View file

@ -872,6 +872,32 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
kfree(block); kfree(block);
} }
static void wlcore_print_recovery(struct wl1271 *wl)
{
u32 pc = 0;
u32 hint_sts = 0;
int ret;
wl1271_info("Hardware recovery in progress. FW ver: %s",
wl->chip.fw_ver_str);
/* change partitions momentarily so we can read the FW pc */
wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
ret = wlcore_read_reg(wl, REG_PC_ON_RECOVERY, &pc);
if (ret < 0)
return;
ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &hint_sts);
if (ret < 0)
return;
wl1271_info("pc: 0x%x, hint_sts: 0x%08x", pc, hint_sts);
wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
}
static void wl1271_recovery_work(struct work_struct *work) static void wl1271_recovery_work(struct work_struct *work)
{ {
struct wl1271 *wl = struct wl1271 *wl =
@ -886,14 +912,7 @@ static void wl1271_recovery_work(struct work_struct *work)
wl12xx_read_fwlog_panic(wl); wl12xx_read_fwlog_panic(wl);
/* change partitions momentarily so we can read the FW pc */ wlcore_print_recovery(wl);
wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x "
"hint_sts: 0x%08x",
wl->chip.fw_ver_str,
wlcore_read_reg(wl, REG_PC_ON_RECOVERY),
wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR));
wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
BUG_ON(bug_on_recovery && BUG_ON(bug_on_recovery &&
!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
@ -4979,18 +4998,22 @@ static int wl12xx_get_hw_info(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
goto out; goto out;
wl->chip.id = wlcore_read_reg(wl, REG_CHIP_ID_B); ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &wl->chip.id);
if (ret < 0)
goto out;
wl->fuse_oui_addr = 0; wl->fuse_oui_addr = 0;
wl->fuse_nic_addr = 0; wl->fuse_nic_addr = 0;
wl->hw_pg_ver = wl->ops->get_pg_ver(wl); ret = wl->ops->get_pg_ver(wl, &wl->hw_pg_ver);
if (ret < 0)
goto out;
if (wl->ops->get_mac) if (wl->ops->get_mac)
wl->ops->get_mac(wl); ret = wl->ops->get_mac(wl);
wl1271_power_off(wl);
out: out:
wl1271_power_off(wl);
return ret; return ret;
} }

View file

@ -62,8 +62,8 @@ struct wlcore_ops {
int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl,
struct wl12xx_vif *wlvif); struct wl12xx_vif *wlvif);
s8 (*get_pg_ver)(struct wl1271 *wl); int (*get_pg_ver)(struct wl1271 *wl, s8 *ver);
void (*get_mac)(struct wl1271 *wl); int (*get_mac)(struct wl1271 *wl);
void (*set_tx_desc_csum)(struct wl1271 *wl, void (*set_tx_desc_csum)(struct wl1271 *wl,
struct wl1271_tx_hw_descr *desc, struct wl1271_tx_hw_descr *desc,
struct sk_buff *skb); struct sk_buff *skb);