Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 314893
b: refs/heads/master
c: 6134323
h: refs/heads/master
i:
  314891: 459715a
v: v3
  • Loading branch information
Ido Yariv authored and Luciano Coelho committed Jun 22, 2012
1 parent 35ca3d3 commit 156a659
Show file tree
Hide file tree
Showing 10 changed files with 310 additions and 114 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: eb96f841b9563ba34969be25615548635728faf5
refs/heads/master: 6134323f42b0dbae8e8206414d26cb167b9bedfc
152 changes: 115 additions & 37 deletions trunk/drivers/net/wireless/ti/wl12xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

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;
int timeout = OCP_CMD_LOOP;
int ret;

/* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr = (addr >> 1) + 0x30000;
Expand All @@ -715,29 +716,38 @@ static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr)

/* poll for data ready */
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);

if (!timeout) {
wl1271_warning("Top register access timed out.");
return 0xffff;
return -ETIMEDOUT;
}

/* check data status and return if OK */
if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
return val & 0xffff;
else {
if ((val & OCP_STATUS_MASK) != OCP_STATUS_OK) {
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)
{
u16 spare_reg;
int ret;

/* 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)
return -EFAULT;
spare_reg |= (BIT(3) | BIT(5) | BIT(6));
Expand All @@ -756,8 +766,12 @@ static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
{
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)
return false;

Expand All @@ -767,8 +781,12 @@ static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
static bool wl128x_is_fref_valid(struct wl1271 *wl)
{
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)
return false;

Expand All @@ -790,9 +808,13 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
u16 pll_config;
u8 input_freq;
struct wl12xx_priv *priv = wl->priv;
int ret;

/* 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)
return -EFAULT;
spare_reg |= BIT(2);
Expand All @@ -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 */
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)
return -EFAULT;
pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
Expand All @@ -827,6 +852,7 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
{
struct wl12xx_priv *priv = wl->priv;
u16 sys_clk_cfg;
int ret;

/* For XTAL-only modes, FREF will be used after switching from TCXO */
if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
Expand All @@ -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 */
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)
return -EINVAL;
if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
Expand Down Expand Up @@ -872,6 +901,7 @@ static int wl127x_boot_clk(struct wl1271 *wl)
struct wl12xx_priv *priv = wl->priv;
u32 pause;
u32 clk;
int ret;

if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
Expand All @@ -892,48 +922,64 @@ static int wl127x_boot_clk(struct wl1271 *wl)
if (priv->ref_clock != CONF_REF_CLK_19_2_E) {
u16 val;
/* 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;
wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val);

/* 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;
wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val);
} else {
u16 val;
/* 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 |= CLK_REQ_OUTN_SEL;
wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
}

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);

pause &= ~(WU_COUNTER_PAUSE_VAL);
pause |= WU_COUNTER_PAUSE_VAL;
wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);

return 0;
out:
return ret;
}

static int wl1271_boot_soft_reset(struct wl1271 *wl)
{
unsigned long timeout;
u32 boot_data;
int ret = 0;

/* perform soft reset */
wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);

/* SOFT_RESET is self clearing */
timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
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);
if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
break;
Expand All @@ -954,7 +1000,8 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
/* disable auto calibration on start*/
wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff);

return 0;
out:
return ret;
}

static int wl12xx_pre_boot(struct wl1271 *wl)
Expand Down Expand Up @@ -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
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);

Expand All @@ -1008,22 +1057,28 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
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
* ACX_EEPROMLESS_IND_REG */
wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");

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);

/* 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
* to upload_fw) */
Expand All @@ -1032,12 +1087,16 @@ static void wl12xx_pre_upload(struct wl1271 *wl)
wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);

/* 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 */
polarity &= ~POLARITY_LOW;
wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity);

out:
return ret;
}

static void wl12xx_enable_interrupts(struct wl1271 *wl)
Expand All @@ -1063,7 +1122,9 @@ static int wl12xx_boot(struct wl1271 *wl)
if (ret < 0)
goto out;

wl12xx_pre_upload(wl);
ret = wl12xx_pre_upload(wl);
if (ret < 0)
goto out;

ret = wlcore_boot_upload_firmware(wl);
if (ret < 0)
Expand Down Expand Up @@ -1282,39 +1343,56 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
return supported;
}

static void wl12xx_get_fuse_mac(struct wl1271 *wl)
static int wl12xx_get_fuse_mac(struct wl1271 *wl)
{
u32 mac1, mac2;
int ret;

wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);

mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1, &mac1);
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 */
wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
((mac1 & 0xff000000) >> 24);
wl->fuse_nic_addr = mac1 & 0xffffff;

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)
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
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))
wl12xx_get_fuse_mac(wl);
return wl12xx_get_fuse_mac(wl);

return 0;
}

static void wl12xx_set_tx_desc_csum(struct wl1271 *wl,
Expand Down
Loading

0 comments on commit 156a659

Please sign in to comment.