Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
a572ac1a
Commit
a572ac1a
authored
Jun 26, 2012
by
Luciano Coelho
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'wl12xx-next' into for-linville
parents
6bcfe67f
680c6055
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
1257 additions
and
475 deletions
+1257
-475
drivers/net/wireless/ti/wl12xx/main.c
drivers/net/wireless/ti/wl12xx/main.c
+254
-89
drivers/net/wireless/ti/wl18xx/acx.h
drivers/net/wireless/ti/wl18xx/acx.h
+15
-19
drivers/net/wireless/ti/wl18xx/io.c
drivers/net/wireless/ti/wl18xx/io.c
+27
-12
drivers/net/wireless/ti/wl18xx/io.h
drivers/net/wireless/ti/wl18xx/io.h
+2
-2
drivers/net/wireless/ti/wl18xx/main.c
drivers/net/wireless/ti/wl18xx/main.c
+162
-98
drivers/net/wireless/ti/wlcore/boot.c
drivers/net/wireless/ti/wlcore/boot.c
+60
-24
drivers/net/wireless/ti/wlcore/cmd.c
drivers/net/wireless/ti/wlcore/cmd.c
+55
-22
drivers/net/wireless/ti/wlcore/debugfs.c
drivers/net/wireless/ti/wlcore/debugfs.c
+192
-0
drivers/net/wireless/ti/wlcore/event.c
drivers/net/wireless/ti/wlcore/event.c
+10
-5
drivers/net/wireless/ti/wlcore/hw_ops.h
drivers/net/wireless/ti/wlcore/hw_ops.h
+8
-4
drivers/net/wireless/ti/wlcore/io.c
drivers/net/wireless/ti/wlcore/io.c
+38
-17
drivers/net/wireless/ti/wlcore/io.h
drivers/net/wireless/ti/wlcore/io.h
+95
-49
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/main.c
+189
-62
drivers/net/wireless/ti/wlcore/ps.c
drivers/net/wireless/ti/wlcore/ps.c
+12
-2
drivers/net/wireless/ti/wlcore/rx.c
drivers/net/wireless/ti/wlcore/rx.c
+27
-10
drivers/net/wireless/ti/wlcore/rx.h
drivers/net/wireless/ti/wlcore/rx.h
+2
-2
drivers/net/wireless/ti/wlcore/sdio.c
drivers/net/wireless/ti/wlcore/sdio.c
+29
-21
drivers/net/wireless/ti/wlcore/spi.c
drivers/net/wireless/ti/wlcore/spi.c
+9
-5
drivers/net/wireless/ti/wlcore/tx.c
drivers/net/wireless/ti/wlcore/tx.c
+57
-19
drivers/net/wireless/ti/wlcore/tx.h
drivers/net/wireless/ti/wlcore/tx.h
+2
-2
drivers/net/wireless/ti/wlcore/wlcore.h
drivers/net/wireless/ti/wlcore/wlcore.h
+7
-7
drivers/net/wireless/ti/wlcore/wlcore_i.h
drivers/net/wireless/ti/wlcore/wlcore_i.h
+5
-4
No files found.
drivers/net/wireless/ti/wl12xx/main.c
View file @
a572ac1a
...
...
@@ -598,8 +598,10 @@ static const int wl12xx_rtable[REG_TABLE_LEN] = {
#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
static
void
wl127x_prepare_read
(
struct
wl1271
*
wl
,
u32
rx_desc
,
u32
len
)
static
int
wl127x_prepare_read
(
struct
wl1271
*
wl
,
u32
rx_desc
,
u32
len
)
{
int
ret
;
if
(
wl
->
chip
.
id
!=
CHIP_ID_1283_PG20
)
{
struct
wl1271_acx_mem_map
*
wl_mem_map
=
wl
->
target_mem_map
;
struct
wl127x_rx_mem_pool_addr
rx_mem_addr
;
...
...
@@ -616,9 +618,13 @@ static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
rx_mem_addr
.
addr_extra
=
rx_mem_addr
.
addr
+
4
;
wl1271_write
(
wl
,
WL1271_SLV_REG_DATA
,
&
rx_mem_addr
,
sizeof
(
rx_mem_addr
),
false
);
ret
=
wlcore_write
(
wl
,
WL1271_SLV_REG_DATA
,
&
rx_mem_addr
,
sizeof
(
rx_mem_addr
),
false
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
}
static
int
wl12xx_identify_chip
(
struct
wl1271
*
wl
)
...
...
@@ -682,64 +688,95 @@ static int wl12xx_identify_chip(struct wl1271 *wl)
return
ret
;
}
static
void
wl12xx_top_reg_write
(
struct
wl1271
*
wl
,
int
addr
,
u16
val
)
static
int
__must_check
wl12xx_top_reg_write
(
struct
wl1271
*
wl
,
int
addr
,
u16
val
)
{
int
ret
;
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
addr
=
(
addr
>>
1
)
+
0x30000
;
wl1271_write32
(
wl
,
WL12XX_OCP_POR_CTR
,
addr
);
ret
=
wlcore_write32
(
wl
,
WL12XX_OCP_POR_CTR
,
addr
);
if
(
ret
<
0
)
goto
out
;
/* write value to OCP_POR_WDATA */
wl1271_write32
(
wl
,
WL12XX_OCP_DATA_WRITE
,
val
);
ret
=
wlcore_write32
(
wl
,
WL12XX_OCP_DATA_WRITE
,
val
);
if
(
ret
<
0
)
goto
out
;
/* write 1 to OCP_CMD */
wl1271_write32
(
wl
,
WL12XX_OCP_CMD
,
OCP_CMD_WRITE
);
ret
=
wlcore_write32
(
wl
,
WL12XX_OCP_CMD
,
OCP_CMD_WRITE
);
if
(
ret
<
0
)
goto
out
;
out:
return
ret
;
}
static
u16
wl12xx_top_reg_read
(
struct
wl1271
*
wl
,
int
addr
)
static
int
__must_check
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
;
wl1271_write32
(
wl
,
WL12XX_OCP_POR_CTR
,
addr
);
ret
=
wlcore_write32
(
wl
,
WL12XX_OCP_POR_CTR
,
addr
);
if
(
ret
<
0
)
return
ret
;
/* write 2 to OCP_CMD */
wl1271_write32
(
wl
,
WL12XX_OCP_CMD
,
OCP_CMD_READ
);
ret
=
wlcore_write32
(
wl
,
WL12XX_OCP_CMD
,
OCP_CMD_READ
);
if
(
ret
<
0
)
return
ret
;
/* 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
));
wl12xx_top_reg_write
(
wl
,
WL_SPARE_REG
,
spare_reg
);
ret
=
wl12xx_top_reg_write
(
wl
,
WL_SPARE_REG
,
spare_reg
);
if
(
ret
<
0
)
return
ret
;
/* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
wl12xx_top_reg_write
(
wl
,
SYS_CLK_CFG_REG
,
WL_CLK_REQ_TYPE_PG2
|
MCS_PLL_CLK_SEL_FREF
);
ret
=
wl12xx_top_reg_write
(
wl
,
SYS_CLK_CFG_REG
,
WL_CLK_REQ_TYPE_PG2
|
MCS_PLL_CLK_SEL_FREF
);
if
(
ret
<
0
)
return
ret
;
/* Delay execution for 15msec, to let the HW settle */
mdelay
(
15
);
...
...
@@ -750,8 +787,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
;
...
...
@@ -761,8 +802,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
;
...
...
@@ -771,11 +816,21 @@ static bool wl128x_is_fref_valid(struct wl1271 *wl)
static
int
wl128x_manually_configure_mcs_pll
(
struct
wl1271
*
wl
)
{
wl12xx_top_reg_write
(
wl
,
MCS_PLL_M_REG
,
MCS_PLL_M_REG_VAL
);
wl12xx_top_reg_write
(
wl
,
MCS_PLL_N_REG
,
MCS_PLL_N_REG_VAL
);
wl12xx_top_reg_write
(
wl
,
MCS_PLL_CONFIG_REG
,
MCS_PLL_CONFIG_REG_VAL
);
int
ret
;
return
0
;
ret
=
wl12xx_top_reg_write
(
wl
,
MCS_PLL_M_REG
,
MCS_PLL_M_REG_VAL
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl12xx_top_reg_write
(
wl
,
MCS_PLL_N_REG
,
MCS_PLL_N_REG_VAL
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl12xx_top_reg_write
(
wl
,
MCS_PLL_CONFIG_REG
,
MCS_PLL_CONFIG_REG_VAL
);
out:
return
ret
;
}
static
int
wl128x_configure_mcs_pll
(
struct
wl1271
*
wl
,
int
clk
)
...
...
@@ -784,13 +839,19 @@ 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
);
wl12xx_top_reg_write
(
wl
,
WL_SPARE_REG
,
spare_reg
);
ret
=
wl12xx_top_reg_write
(
wl
,
WL_SPARE_REG
,
spare_reg
);
if
(
ret
<
0
)
return
ret
;
/* Handle special cases of the TCXO clock */
if
(
priv
->
tcxo_clock
==
WL12XX_TCXOCLOCK_16_8
||
...
...
@@ -800,14 +861,17 @@ 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
);
pll_config
|=
MCS_PLL_ENABLE_HP
;
wl12xx_top_reg_write
(
wl
,
MCS_PLL_CONFIG_REG
,
pll_config
);
ret
=
wl12xx_top_reg_write
(
wl
,
MCS_PLL_CONFIG_REG
,
pll_config
);
return
0
;
return
ret
;
}
/*
...
...
@@ -821,6 +885,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
||
...
...
@@ -831,7 +896,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
)
...
...
@@ -866,6 +934,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
;
...
...
@@ -886,48 +955,74 @@ 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
);
ret
=
wl12xx_top_reg_write
(
wl
,
OCP_REG_CLK_TYPE
,
val
);
if
(
ret
<
0
)
goto
out
;
/* 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
);
ret
=
wl12xx_top_reg_write
(
wl
,
OCP_REG_CLK_PULL
,
val
);
if
(
ret
<
0
)
goto
out
;
}
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
);
ret
=
wl12xx_top_reg_write
(
wl
,
OCP_REG_CLK_POLARITY
,
val
);
if
(
ret
<
0
)
goto
out
;
}
wl1271_write32
(
wl
,
WL12XX_PLL_PARAMETERS
,
clk
);
ret
=
wlcore_write32
(
wl
,
WL12XX_PLL_PARAMETERS
,
clk
);
if
(
ret
<
0
)
goto
out
;
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
);
ret
=
wlcore
_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
);
ret
=
wlcore_write32
(
wl
,
WL12XX_SLV_SOFT_RESET
,
ACX_SLV_SOFT_RESET_BIT
);
if
(
ret
<
0
)
goto
out
;
/* 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
;
...
...
@@ -943,12 +1038,15 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
}
/* disable Rx/Tx */
wl1271_write32
(
wl
,
WL12XX_ENABLE
,
0x0
);
ret
=
wlcore_write32
(
wl
,
WL12XX_ENABLE
,
0x0
);
if
(
ret
<
0
)
goto
out
;
/* disable auto calibration on start*/
wl1271
_write32
(
wl
,
WL12XX_SPARE_A2
,
0xffff
);
ret
=
wlcore
_write32
(
wl
,
WL12XX_SPARE_A2
,
0xffff
);
return
0
;
out:
return
ret
;
}
static
int
wl12xx_pre_boot
(
struct
wl1271
*
wl
)
...
...
@@ -969,16 +1067,23 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
}
/* Continue the ELP wake up sequence */
wl1271_write32
(
wl
,
WL12XX_WELP_ARM_COMMAND
,
WELP_ARM_COMMAND_VAL
);
ret
=
wlcore_write32
(
wl
,
WL12XX_WELP_ARM_COMMAND
,
WELP_ARM_COMMAND_VAL
);
if
(
ret
<
0
)
goto
out
;
udelay
(
500
);
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_DRPW
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_DRPW
]);
if
(
ret
<
0
)
goto
out
;
/* Read-modify-write DRPW_SCRATCH_START register (see next state)
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
);
...
...
@@ -987,12 +1092,18 @@ static int wl12xx_pre_boot(struct wl1271 *wl)
else
clk
|=
(
priv
->
ref_clock
<<
1
)
<<
4
;
wl1271_write32
(
wl
,
WL12XX_DRPW_SCRATCH_START
,
clk
);
ret
=
wlcore_write32
(
wl
,
WL12XX_DRPW_SCRATCH_START
,
clk
);
if
(
ret
<
0
)
goto
out
;
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_WORK
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_WORK
]);
if
(
ret
<
0
)
goto
out
;
/* Disable interrupts */
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
);
ret
=
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
);
if
(
ret
<
0
)
goto
out
;
ret
=
wl1271_boot_soft_reset
(
wl
);
if
(
ret
<
0
)
...
...
@@ -1002,47 +1113,72 @@ 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
);
ret
=
wlcore_write32
(
wl
,
WL12XX_EEPROMLESS_IND
,
WL12XX_EEPROMLESS_IND
);
if
(
ret
<
0
)
goto
out
;
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) */
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
wl12xx_top_reg_write
(
wl
,
SDIO_IO_DS
,
HCI_IO_DS_6MA
);
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
ret
=
wl12xx_top_reg_write
(
wl
,
SDIO_IO_DS
,
HCI_IO_DS_6MA
);
if
(
ret
<
0
)
goto
out
;
}
/* 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
);
ret
=
wl12xx_top_reg_write
(
wl
,
OCP_REG_POLARITY
,
polarity
);
out:
return
ret
;
}
static
void
wl12xx_enable_interrupts
(
struct
wl1271
*
wl
)
static
int
wl12xx_enable_interrupts
(
struct
wl1271
*
wl
)
{
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL12XX_ACX_ALL_EVENTS_VECTOR
);
int
ret
;
ret
=
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL12XX_ACX_ALL_EVENTS_VECTOR
);
if
(
ret
<
0
)
goto
out
;
wlcore_enable_interrupts
(
wl
);
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
&
~
(
WL12XX_INTR_MASK
));
ret
=
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
&
~
(
WL12XX_INTR_MASK
));
if
(
ret
<
0
)
goto
out
;
wl1271_write32
(
wl
,
WL12XX_HI_CFG
,
HI_CFG_DEF_VAL
);
ret
=
wlcore_write32
(
wl
,
WL12XX_HI_CFG
,
HI_CFG_DEF_VAL
);
out:
return
ret
;
}
static
int
wl12xx_boot
(
struct
wl1271
*
wl
)
...
...
@@ -1057,7 +1193,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
)
...
...
@@ -1067,22 +1205,30 @@ static int wl12xx_boot(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out
;
wl12xx_enable_interrupts
(
wl
);
ret
=
wl12xx_enable_interrupts
(
wl
);
out:
return
ret
;
}
static
void
wl12xx_trigger_cmd
(
struct
wl1271
*
wl
,
int
cmd_box_addr
,
static
int
wl12xx_trigger_cmd
(
struct
wl1271
*
wl
,
int
cmd_box_addr
,
void
*
buf
,
size_t
len
)
{
wl1271_write
(
wl
,
cmd_box_addr
,
buf
,
len
,
false
);
wlcore_write_reg
(
wl
,
REG_INTERRUPT_TRIG
,
WL12XX_INTR_TRIG_CMD
);
int
ret
;
ret
=
wlcore_write
(
wl
,
cmd_box_addr
,
buf
,
len
,
false
);
if
(
ret
<
0
)
return
ret
;
ret
=
wlcore_write_reg
(
wl
,
REG_INTERRUPT_TRIG
,
WL12XX_INTR_TRIG_CMD
);
return
ret
;
}
static
void
wl12xx_ack_event
(
struct
wl1271
*
wl
)
static
int
wl12xx_ack_event
(
struct
wl1271
*
wl
)
{
wlcore_write_reg
(
wl
,
REG_INTERRUPT_TRIG
,
WL12XX_INTR_TRIG_EVENT_ACK
);
return
wlcore_write_reg
(
wl
,
REG_INTERRUPT_TRIG
,
WL12XX_INTR_TRIG_EVENT_ACK
);
}
static
u32
wl12xx_calc_tx_blocks
(
struct
wl1271
*
wl
,
u32
len
,
u32
spare_blks
)
...
...
@@ -1162,13 +1308,13 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
return
data_len
-
sizeof
(
*
desc
)
-
desc
->
pad_len
;
}
static
void
wl12xx_tx_delayed_compl
(
struct
wl1271
*
wl
)
static
int
wl12xx_tx_delayed_compl
(
struct
wl1271
*
wl
)
{
if
(
wl
->
fw_status_1
->
tx_results_counter
==
(
wl
->
tx_results_count
&
0xff
))
return
;
return
0
;
wl1271
_tx_complete
(
wl
);
return
wlcore
_tx_complete
(
wl
);
}
static
int
wl12xx_hw_init
(
struct
wl1271
*
wl
)
...
...
@@ -1269,39 +1415,58 @@ 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
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_DRPW
]);
if
(
ret
<
0
)
goto
out
;
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
]);
ret
=
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
,
...
...
drivers/net/wireless/ti/wl18xx/acx.h
View file @
a572ac1a
...
...
@@ -32,25 +32,21 @@ enum {
/* 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)
#define WL18XX_ACX_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 | \
WL1271_ACX_SW_INTR_WATCHDOG)
#define WL18XX_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)
struct
wl18xx_acx_host_config_bitmap
{
struct
acx_header
header
;
...
...
drivers/net/wireless/ti/wl18xx/io.c
View file @
a572ac1a
...
...
@@ -24,37 +24,52 @@
#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
;
int
ret
;
if
(
WARN_ON
(
addr
%
2
))
return
;
return
-
EINVAL
;
if
((
addr
%
4
)
==
0
)
{
tmp
=
wl1271_read32
(
wl
,
addr
);
ret
=
wlcore_read32
(
wl
,
addr
,
&
tmp
);
if
(
ret
<
0
)
goto
out
;
tmp
=
(
tmp
&
0xffff0000
)
|
val
;
wl1271
_write32
(
wl
,
addr
,
tmp
);
ret
=
wlcore
_write32
(
wl
,
addr
,
tmp
);
}
else
{
tmp
=
wl1271_read32
(
wl
,
addr
-
2
);
ret
=
wlcore_read32
(
wl
,
addr
-
2
,
&
tmp
);
if
(
ret
<
0
)
goto
out
;
tmp
=
(
tmp
&
0xffff
)
|
(
val
<<
16
);
wl1271
_write32
(
wl
,
addr
-
2
,
tmp
);
ret
=
wlcore
_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
;
int
ret
;
if
(
WARN_ON
(
addr
%
2
))
return
0
;
return
-
EINVAL
;
if
((
addr
%
4
)
==
0
)
{
/* address is 4-bytes aligned */
val
=
wl1271_read32
(
wl
,
addr
);
return
val
&
0xffff
;
ret
=
wlcore_read32
(
wl
,
addr
,
&
val
);
if
(
ret
>=
0
&&
out
)
*
out
=
val
&
0xffff
;
}
else
{
val
=
wl1271_read32
(
wl
,
addr
-
2
);
return
(
val
&
0xffff0000
)
>>
16
;
ret
=
wlcore_read32
(
wl
,
addr
-
2
,
&
val
);
if
(
ret
>=
0
&&
out
)
*
out
=
(
val
&
0xffff0000
)
>>
16
;
}
return
ret
;
}
drivers/net/wireless/ti/wl18xx/io.h
View file @
a572ac1a
...
...
@@ -22,7 +22,7 @@
#ifndef __WL18XX_IO_H__
#define __WL18XX_IO_H__
void
wl18xx_top_reg_write
(
struct
wl1271
*
wl
,
int
addr
,
u16
val
);
u16
wl18xx_top_reg_read
(
struct
wl1271
*
wl
,
int
addr
);
int
__must_check
wl18xx_top_reg_write
(
struct
wl1271
*
wl
,
int
addr
,
u16
val
);
int
__must_check
wl18xx_top_reg_read
(
struct
wl1271
*
wl
,
int
addr
,
u16
*
out
);
#endif
/* __WL18XX_IO_H__ */
drivers/net/wireless/ti/wl18xx/main.c
View file @
a572ac1a
...
...
@@ -612,20 +612,11 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
WLCORE_QUIRK_TX_PAD_LAST_FRAME
;
break
;
case
CHIP_ID_185x_PG10
:
wl1271_debug
(
DEBUG_BOOT
,
"chip id 0x%x (185x PG10)"
,
wl
->
chip
.
id
);
wl
->
sr_fw_name
=
WL18XX_FW_NAME
;
/* wl18xx uses the same firmware for PLT */
wl
->
plt_fw_name
=
WL18XX_FW_NAME
;
wl
->
quirks
|=
WLCORE_QUIRK_NO_ELP
|
WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED
|
WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN
|
WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN
;
/* PG 1.0 has some problems with MCS_13, so disable it */
wl
->
ht_cap
[
IEEE80211_BAND_2GHZ
].
mcs
.
rx_mask
[
1
]
&=
~
BIT
(
5
);
wl1271_warning
(
"chip id 0x%x (185x PG10) is deprecated"
,
wl
->
chip
.
id
);
ret
=
-
ENODEV
;
goto
out
;
break
;
default:
wl1271_warning
(
"unsupported chip id: 0x%x"
,
wl
->
chip
.
id
);
ret
=
-
ENODEV
;
...
...
@@ -636,123 +627,178 @@ static int wl18xx_identify_chip(struct wl1271 *wl)
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
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_TOP_PRCM_ELP_SOC
]);
if
(
ret
<
0
)
goto
out
;
/* 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
,
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
].
swallow
?
"swallow"
:
"spit"
);
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_N
,
wl18xx_clk_table
[
clk_freq
].
n
);
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_M
,
wl18xx_clk_table
[
clk_freq
].
m
);
ret
=
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_N
,
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
)
{
/* first the 16 lower bits */
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_Q_FACTOR_CFG_1
,
wl18xx_clk_table
[
clk_freq
].
q
&
PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK
);
ret
=
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_Q_FACTOR_CFG_1
,
wl18xx_clk_table
[
clk_freq
].
q
&
PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK
);
if
(
ret
<
0
)
goto
out
;
/* then the 16 higher bits, masked out */
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_Q_FACTOR_CFG_2
,
(
wl18xx_clk_table
[
clk_freq
].
q
>>
16
)
&
PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK
);
ret
=
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_Q_FACTOR_CFG_2
,
(
wl18xx_clk_table
[
clk_freq
].
q
>>
16
)
&
PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK
);
if
(
ret
<
0
)
goto
out
;
/* first the 16 lower bits */
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_P_FACTOR_CFG_1
,
wl18xx_clk_table
[
clk_freq
].
p
&
PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK
);
ret
=
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_P_FACTOR_CFG_1
,
wl18xx_clk_table
[
clk_freq
].
p
&
PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK
);
if
(
ret
<
0
)
goto
out
;
/* then the 16 higher bits, masked out */
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_P_FACTOR_CFG_2
,
(
wl18xx_clk_table
[
clk_freq
].
p
>>
16
)
&
PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK
);
ret
=
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_P_FACTOR_CFG_2
,
(
wl18xx_clk_table
[
clk_freq
].
p
>>
16
)
&
PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK
);
}
else
{
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_SWALLOW_EN
,
PLLSH_WCS_PLL_SWALLOW_EN_VAL2
);
ret
=
wl18xx_top_reg_write
(
wl
,
PLLSH_WCS_PLL_SWALLOW_EN
,
PLLSH_WCS_PLL_SWALLOW_EN_VAL2
);
}
out:
return
ret
;
}
static
void
wl18xx_boot_soft_reset
(
struct
wl1271
*
wl
)
static
int
wl18xx_boot_soft_reset
(
struct
wl1271
*
wl
)
{
int
ret
;
/* disable Rx/Tx */
wl1271_write32
(
wl
,
WL18XX_ENABLE
,
0x0
);
ret
=
wlcore_write32
(
wl
,
WL18XX_ENABLE
,
0x0
);
if
(
ret
<
0
)
goto
out
;
/* disable auto calibration on start*/
wl1271_write32
(
wl
,
WL18XX_SPARE_A2
,
0xffff
);
ret
=
wlcore_write32
(
wl
,
WL18XX_SPARE_A2
,
0xffff
);
out:
return
ret
;
}
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 */
wl1271_write32
(
wl
,
WL18XX_WELP_ARM_COMMAND
,
WELP_ARM_COMMAND_VAL
);
ret
=
wlcore_write32
(
wl
,
WL18XX_WELP_ARM_COMMAND
,
WELP_ARM_COMMAND_VAL
);
if
(
ret
<
0
)
goto
out
;
udelay
(
500
);
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
if
(
ret
<
0
)
goto
out
;
/* Disable interrupts */
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
);
ret
=
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
);
if
(
ret
<
0
)
goto
out
;
wl18xx_boot_soft_reset
(
wl
);
ret
=
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
;
int
ret
;
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
if
(
ret
<
0
)
goto
out
;
/* TODO: check if this is all needed */
wl1271_write32
(
wl
,
WL18XX_EEPROMLESS_IND
,
WL18XX_EEPROMLESS_IND
);
ret
=
wlcore_write32
(
wl
,
WL18XX_EEPROMLESS_IND
,
WL18XX_EEPROMLESS_IND
);
if
(
ret
<
0
)
goto
out
;
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
);
tmp
=
wl1271_read32
(
wl
,
WL18XX_SCR_PAD2
);
ret
=
wlcore_read32
(
wl
,
WL18XX_SCR_PAD2
,
&
tmp
);
out:
return
ret
;
}
static
void
wl18xx_set_mac_and_phy
(
struct
wl1271
*
wl
)
static
int
wl18xx_set_mac_and_phy
(
struct
wl1271
*
wl
)
{
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
size_t
len
;
int
ret
;
/* the parameters struct is smaller for PG1 */
if
(
wl
->
chip
.
id
==
CHIP_ID_185x_PG10
)
len
=
offsetof
(
struct
wl18xx_mac_and_phy_params
,
psat
)
+
1
;
else
len
=
sizeof
(
struct
wl18xx_mac_and_phy_params
);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_PHY_INIT
]);
if
(
ret
<
0
)
goto
out
;
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_PHY_INIT
]);
wl1271_write
(
wl
,
WL18XX_PHY_INIT_MEM_ADDR
,
(
u8
*
)
&
priv
->
conf
.
phy
,
len
,
false
);
ret
=
wlcore_write
(
wl
,
WL18XX_PHY_INIT_MEM_ADDR
,
(
u8
*
)
&
priv
->
conf
.
phy
,
sizeof
(
struct
wl18xx_mac_and_phy_params
),
false
);
out:
return
ret
;
}
static
void
wl18xx_enable_interrupts
(
struct
wl1271
*
wl
)
static
int
wl18xx_enable_interrupts
(
struct
wl1271
*
wl
)
{
u32
event_mask
,
intr_mask
;
int
ret
;
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
;
}
event_mask
=
WL18XX_ACX_EVENTS_VECTOR
;
intr_mask
=
WL18XX_INTR_MASK
;
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
event_mask
);
ret
=
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
event_mask
);
if
(
ret
<
0
)
goto
out
;
wlcore_enable_interrupts
(
wl
);
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
&
~
intr_mask
);
ret
=
wlcore_write_reg
(
wl
,
REG_INTERRUPT_MASK
,
WL1271_ACX_INTR_ALL
&
~
intr_mask
);
out:
return
ret
;
}
static
int
wl18xx_boot
(
struct
wl1271
*
wl
)
...
...
@@ -763,25 +809,29 @@ static int wl18xx_boot(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out
;
wl18xx_pre_upload
(
wl
);
ret
=
wl18xx_pre_upload
(
wl
);
if
(
ret
<
0
)
goto
out
;
ret
=
wlcore_boot_upload_firmware
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl18xx_set_mac_and_phy
(
wl
);
ret
=
wl18xx_set_mac_and_phy
(
wl
);
if
(
ret
<
0
)
goto
out
;
ret
=
wlcore_boot_run_firmware
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl18xx_enable_interrupts
(
wl
);
ret
=
wl18xx_enable_interrupts
(
wl
);
out:
return
ret
;
}
static
void
wl18xx_trigger_cmd
(
struct
wl1271
*
wl
,
int
cmd_box_addr
,
static
int
wl18xx_trigger_cmd
(
struct
wl1271
*
wl
,
int
cmd_box_addr
,
void
*
buf
,
size_t
len
)
{
struct
wl18xx_priv
*
priv
=
wl
->
priv
;
...
...
@@ -789,13 +839,14 @@ static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
memcpy
(
priv
->
cmd_buf
,
buf
,
len
);
memset
(
priv
->
cmd_buf
+
len
,
0
,
WL18XX_CMD_MAX_SIZE
-
len
);
wl1271_write
(
wl
,
cmd_box_addr
,
priv
->
cmd_buf
,
WL18XX_CMD_MAX_SIZE
,
false
);
return
wlcore_write
(
wl
,
cmd_box_addr
,
priv
->
cmd_buf
,
WL18XX_CMD_MAX_SIZE
,
false
);
}
static
void
wl18xx_ack_event
(
struct
wl1271
*
wl
)
static
int
wl18xx_ack_event
(
struct
wl1271
*
wl
)
{
wlcore_write_reg
(
wl
,
REG_INTERRUPT_TRIG
,
WL18XX_INTR_TRIG_EVENT_ACK
);
return
wlcore_write_reg
(
wl
,
REG_INTERRUPT_TRIG
,
WL18XX_INTR_TRIG_EVENT_ACK
);
}
static
u32
wl18xx_calc_tx_blocks
(
struct
wl1271
*
wl
,
u32
len
,
u32
spare_blks
)
...
...
@@ -977,34 +1028,32 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
}
else
if
(
!
strcmp
(
ht_mode_param
,
"mimo"
))
{
wl1271_debug
(
DEBUG_ACX
,
"using MIMO rate mask"
);
/*
* PG 1.0 has some problems with MCS_13, so disable it
*
* TODO: instead of hacking this in here, we should
* make it more general and change a bit in the
* wlvif->rate_set instead.
*/
if
(
wl
->
chip
.
id
==
CHIP_ID_185x_PG10
)
return
CONF_TX_MIMO_RATES
&
~
CONF_HW_BIT_RATE_MCS_13
;
return
CONF_TX_MIMO_RATES
;
}
else
{
return
0
;
}
}
static
s8
wl18xx_get_pg_ver
(
struct
wl1271
*
wl
)
static
int
wl18xx_get_pg_ver
(
struct
wl1271
*
wl
,
s8
*
ver
)
{
u32
fuse
;
int
ret
;
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_TOP_PRCM_ELP_SOC
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_TOP_PRCM_ELP_SOC
]);
if
(
ret
<
0
)
goto
out
;
fuse
=
wl1271_read32
(
wl
,
WL18XX_REG_FUSE_DATA_1_3
);
fuse
=
(
fuse
&
WL18XX_PG_VER_MASK
)
>>
WL18XX_PG_VER_OFFSET
;
ret
=
wlcore_read32
(
wl
,
WL18XX_REG_FUSE_DATA_1_3
,
&
fuse
);
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
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
return
(
s8
)
fuse
;
out:
return
ret
;
}
#define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin"
...
...
@@ -1070,26 +1119,41 @@ static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev)
static
int
wl18xx_plt_init
(
struct
wl1271
*
wl
)
{
wl1271_write32
(
wl
,
WL18XX_SCR_PAD8
,
WL18XX_SCR_PAD8_PLT
);
int
ret
;
ret
=
wlcore_write32
(
wl
,
WL18XX_SCR_PAD8
,
WL18XX_SCR_PAD8_PLT
);
if
(
ret
<
0
)
return
ret
;
return
wl
->
ops
->
boot
(
wl
);
}
static
void
wl18xx_get_mac
(
struct
wl1271
*
wl
)
static
int
wl18xx_get_mac
(
struct
wl1271
*
wl
)
{
u32
mac1
,
mac2
;
int
ret
;
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_TOP_PRCM_ELP_SOC
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_TOP_PRCM_ELP_SOC
]);
if
(
ret
<
0
)
goto
out
;
mac1
=
wl1271_read32
(
wl
,
WL18XX_REG_FUSE_BD_ADDR_1
);
mac2
=
wl1271_read32
(
wl
,
WL18XX_REG_FUSE_BD_ADDR_2
);
ret
=
wlcore_read32
(
wl
,
WL18XX_REG_FUSE_BD_ADDR_1
,
&
mac1
);
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 */
wl
->
fuse_oui_addr
=
((
mac2
&
0xffff
)
<<
8
)
+
((
mac1
&
0xff000000
)
>>
24
);
wl
->
fuse_nic_addr
=
(
mac1
&
0xffffff
);
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_DOWN
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_DOWN
]);
out:
return
ret
;
}
static
int
wl18xx_handle_static_data
(
struct
wl1271
*
wl
,
...
...
drivers/net/wireless/ti/wlcore/boot.c
View file @
a572ac1a
...
...
@@ -33,16 +33,22 @@
#include "rx.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
;
int
ret
;
/* 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) */
cpu_ctrl
|=
flag
;
wlcore_write_reg
(
wl
,
REG_ECPU_CONTROL
,
cpu_ctrl
);
ret
=
wlcore_write_reg
(
wl
,
REG_ECPU_CONTROL
,
cpu_ctrl
);
out:
return
ret
;
}
static
int
wlcore_boot_parse_fw_ver
(
struct
wl1271
*
wl
,
...
...
@@ -87,7 +93,9 @@ static int wlcore_boot_static_data(struct wl1271 *wl)
goto
out
;
}
wl1271_read
(
wl
,
wl
->
cmd_box_addr
,
static_data
,
len
,
false
);
ret
=
wlcore_read
(
wl
,
wl
->
cmd_box_addr
,
static_data
,
len
,
false
);
if
(
ret
<
0
)
goto
out_free
;
ret
=
wlcore_boot_parse_fw_ver
(
wl
,
static_data
);
if
(
ret
<
0
)
...
...
@@ -109,6 +117,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
struct
wlcore_partition_set
partition
;
int
addr
,
chunk_num
,
partition_limit
;
u8
*
p
,
*
chunk
;
int
ret
;
/* whal_FwCtrl_LoadFwImageSm() */
...
...
@@ -130,7 +139,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy
(
&
partition
,
&
wl
->
ptable
[
PART_DOWN
],
sizeof
(
partition
));
partition
.
mem
.
start
=
dest
;
wlcore_set_partition
(
wl
,
&
partition
);
ret
=
wlcore_set_partition
(
wl
,
&
partition
);
if
(
ret
<
0
)
return
ret
;
/* 10.1 set partition limit and chunk num */
chunk_num
=
0
;
...
...
@@ -144,7 +155,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
partition_limit
=
chunk_num
*
CHUNK_SIZE
+
wl
->
ptable
[
PART_DOWN
].
mem
.
size
;
partition
.
mem
.
start
=
addr
;
wlcore_set_partition
(
wl
,
&
partition
);
ret
=
wlcore_set_partition
(
wl
,
&
partition
);
if
(
ret
<
0
)
return
ret
;
}
/* 10.3 upload the chunk */
...
...
@@ -153,7 +166,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy
(
chunk
,
p
,
CHUNK_SIZE
);
wl1271_debug
(
DEBUG_BOOT
,
"uploading fw chunk 0x%p to 0x%x"
,
p
,
addr
);
wl1271_write
(
wl
,
addr
,
chunk
,
CHUNK_SIZE
,
false
);
ret
=
wlcore_write
(
wl
,
addr
,
chunk
,
CHUNK_SIZE
,
false
);
if
(
ret
<
0
)
goto
out
;
chunk_num
++
;
}
...
...
@@ -164,10 +179,11 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy
(
chunk
,
p
,
fw_data_len
%
CHUNK_SIZE
);
wl1271_debug
(
DEBUG_BOOT
,
"uploading fw last chunk (%zd B) 0x%p to 0x%x"
,
fw_data_len
%
CHUNK_SIZE
,
p
,
addr
);
wl1271
_write
(
wl
,
addr
,
chunk
,
fw_data_len
%
CHUNK_SIZE
,
false
);
ret
=
wlcore
_write
(
wl
,
addr
,
chunk
,
fw_data_len
%
CHUNK_SIZE
,
false
);
out:
kfree
(
chunk
);
return
0
;
return
ret
;
}
int
wlcore_boot_upload_firmware
(
struct
wl1271
*
wl
)
...
...
@@ -210,6 +226,7 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
int
i
;
u32
dest_addr
,
val
;
u8
*
nvs_ptr
,
*
nvs_aligned
;
int
ret
;
if
(
wl
->
nvs
==
NULL
)
{
wl1271_error
(
"NVS file is needed during boot"
);
...
...
@@ -307,7 +324,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
wl1271_debug
(
DEBUG_BOOT
,
"nvs burst write 0x%x: 0x%x"
,
dest_addr
,
val
);
wl1271_write32
(
wl
,
dest_addr
,
val
);
ret
=
wlcore_write32
(
wl
,
dest_addr
,
val
);
if
(
ret
<
0
)
return
ret
;
nvs_ptr
+=
4
;
dest_addr
+=
4
;
...
...
@@ -333,7 +352,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
nvs_len
-=
nvs_ptr
-
(
u8
*
)
wl
->
nvs
;
/* Now we must set the partition correctly */
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_WORK
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_WORK
]);
if
(
ret
<
0
)
return
ret
;
/* Copy the NVS tables to a new block to ensure alignment */
nvs_aligned
=
kmemdup
(
nvs_ptr
,
nvs_len
,
GFP_KERNEL
);
...
...
@@ -341,11 +362,11 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
return
-
ENOMEM
;
/* And finally we upload the NVS tables */
wlcore_write_data
(
wl
,
REG_CMD_MBOX_ADDRESS
,
nvs_aligned
,
nvs_len
,
false
);
ret
=
wlcore_write_data
(
wl
,
REG_CMD_MBOX_ADDRESS
,
nvs_aligned
,
nvs_len
,
false
);
kfree
(
nvs_aligned
);
return
0
;
return
ret
;
out_badnvs:
wl1271_error
(
"nvs data is malformed"
);
...
...
@@ -359,11 +380,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
u32
chip_id
,
intr
;
/* Make sure we have the boot partition */
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
if
(
ret
<
0
)
return
ret
;
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
);
...
...
@@ -376,7 +403,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
loop
=
0
;
while
(
loop
++
<
INIT_LOOP
)
{
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
)
{
wl1271_error
(
"error reading hardware complete "
...
...
@@ -385,8 +414,10 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
}
/* check that ACX_INTR_INIT_COMPLETE is enabled */
else
if
(
intr
&
WL1271_ACX_INTR_INIT_COMPLETE
)
{
wlcore_write_reg
(
wl
,
REG_INTERRUPT_ACK
,
WL1271_ACX_INTR_INIT_COMPLETE
);
ret
=
wlcore_write_reg
(
wl
,
REG_INTERRUPT_ACK
,
WL1271_ACX_INTR_INIT_COMPLETE
);
if
(
ret
<
0
)
return
ret
;
break
;
}
}
...
...
@@ -398,12 +429,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
}
/* 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
);
/* 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
);
wl1271_debug
(
DEBUG_MAILBOX
,
"MBOX ptrs: 0x%x 0x%x"
,
...
...
@@ -445,9 +481,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
}
/* set the working partition to its "running" mode offset */
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_WORK
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_WORK
]);
/* firmware startup completed */
return
0
;
return
ret
;
}
EXPORT_SYMBOL_GPL
(
wlcore_boot_run_firmware
);
drivers/net/wireless/ti/wlcore/cmd.c
View file @
a572ac1a
...
...
@@ -65,17 +65,24 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
WARN_ON
(
len
%
4
!=
0
);
WARN_ON
(
test_bit
(
WL1271_FLAG_IN_ELP
,
&
wl
->
flags
));
wl1271_write
(
wl
,
wl
->
cmd_box_addr
,
buf
,
len
,
false
);
ret
=
wlcore_write
(
wl
,
wl
->
cmd_box_addr
,
buf
,
len
,
false
);
if
(
ret
<
0
)
goto
fail
;
/*
* TODO: we just need this because one bit is in a different
* place. Is there any better way?
*/
wl
->
ops
->
trigger_cmd
(
wl
,
wl
->
cmd_box_addr
,
buf
,
len
);
ret
=
wl
->
ops
->
trigger_cmd
(
wl
,
wl
->
cmd_box_addr
,
buf
,
len
);
if
(
ret
<
0
)
goto
fail
;
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
))
{
if
(
time_after
(
jiffies
,
timeout
))
{
wl1271_error
(
"command complete timeout"
);
...
...
@@ -89,13 +96,18 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
else
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 */
if
(
res_len
==
0
)
res_len
=
sizeof
(
struct
wl1271_cmd_header
);
wl1271_read
(
wl
,
wl
->
cmd_box_addr
,
cmd
,
res_len
,
false
);
ret
=
wlcore_read
(
wl
,
wl
->
cmd_box_addr
,
cmd
,
res_len
,
false
);
if
(
ret
<
0
)
goto
fail
;
status
=
le16_to_cpu
(
cmd
->
status
);
if
(
status
!=
CMD_STATUS_SUCCESS
)
{
...
...
@@ -104,11 +116,14 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
goto
fail
;
}
wlcore_write_reg
(
wl
,
REG_INTERRUPT_ACK
,
WL1271_ACX_INTR_CMD_COMPLETE
);
ret
=
wlcore_write_reg
(
wl
,
REG_INTERRUPT_ACK
,
WL1271_ACX_INTR_CMD_COMPLETE
);
if
(
ret
<
0
)
goto
fail
;
return
0
;
fail:
WARN_ON
(
1
);
wl12xx_queue_recovery_work
(
wl
);
return
ret
;
}
...
...
@@ -117,35 +132,45 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
* Poll the mailbox event field until any of the bits in the mask is set or a
* timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
*/
static
int
wl1271_cmd_wait_for_event_or_timeout
(
struct
wl1271
*
wl
,
u32
mask
)
static
int
wl1271_cmd_wait_for_event_or_timeout
(
struct
wl1271
*
wl
,
u32
mask
,
bool
*
timeout
)
{
u32
*
events_vector
;
u32
event
;
unsigned
long
timeout
;
unsigned
long
timeout
_time
;
int
ret
=
0
;
*
timeout
=
false
;
events_vector
=
kmalloc
(
sizeof
(
*
events_vector
),
GFP_KERNEL
|
GFP_DMA
);
if
(
!
events_vector
)
return
-
ENOMEM
;
timeout
=
jiffies
+
msecs_to_jiffies
(
WL1271_EVENT_TIMEOUT
);
timeout
_time
=
jiffies
+
msecs_to_jiffies
(
WL1271_EVENT_TIMEOUT
);
do
{
if
(
time_after
(
jiffies
,
timeout
))
{
if
(
time_after
(
jiffies
,
timeout
_time
))
{
wl1271_debug
(
DEBUG_CMD
,
"timeout waiting for event %d"
,
(
int
)
mask
);
ret
=
-
ETIMEDOUT
;
*
timeout
=
true
;
goto
out
;
}
msleep
(
1
);
/* read from both event fields */
wl1271_read
(
wl
,
wl
->
mbox_ptr
[
0
],
events_vector
,
sizeof
(
*
events_vector
),
false
);
ret
=
wlcore_read
(
wl
,
wl
->
mbox_ptr
[
0
],
events_vector
,
sizeof
(
*
events_vector
),
false
);
if
(
ret
<
0
)
goto
out
;
event
=
*
events_vector
&
mask
;
wl1271_read
(
wl
,
wl
->
mbox_ptr
[
1
],
events_vector
,
sizeof
(
*
events_vector
),
false
);
ret
=
wlcore_read
(
wl
,
wl
->
mbox_ptr
[
1
],
events_vector
,
sizeof
(
*
events_vector
),
false
);
if
(
ret
<
0
)
goto
out
;
event
|=
*
events_vector
&
mask
;
}
while
(
!
event
);
...
...
@@ -157,9 +182,10 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask)
static
int
wl1271_cmd_wait_for_event
(
struct
wl1271
*
wl
,
u32
mask
)
{
int
ret
;
bool
timeout
=
false
;
ret
=
wl1271_cmd_wait_for_event_or_timeout
(
wl
,
mask
);
if
(
ret
!=
0
)
{
ret
=
wl1271_cmd_wait_for_event_or_timeout
(
wl
,
mask
,
&
timeout
);
if
(
ret
!=
0
||
timeout
)
{
wl12xx_queue_recovery_work
(
wl
);
return
ret
;
}
...
...
@@ -1412,6 +1438,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
{
struct
wl12xx_cmd_remove_peer
*
cmd
;
int
ret
;
bool
timeout
=
false
;
wl1271_debug
(
DEBUG_CMD
,
"cmd remove peer %d"
,
(
int
)
hlid
);
...
...
@@ -1432,12 +1459,16 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
goto
out_free
;
}
ret
=
wl1271_cmd_wait_for_event_or_timeout
(
wl
,
PEER_REMOVE_COMPLETE_EVENT_ID
,
&
timeout
);
/*
* We are ok with a timeout here. The event is sometimes not sent
* due to a firmware bug.
* due to a firmware bug. In case of another error (like SDIO timeout)
* queue a recovery.
*/
wl1271_cmd_wait_for_event_or_timeout
(
wl
,
PEER_REMOVE_COMPLETE_EVENT_ID
);
if
(
ret
)
wl12xx_queue_recovery_work
(
wl
);
out_free:
kfree
(
cmd
);
...
...
@@ -1754,7 +1785,9 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
return
-
EINVAL
;
/* flush all pending packets */
wl1271_tx_work_locked
(
wl
);
ret
=
wlcore_tx_work_locked
(
wl
);
if
(
ret
<
0
)
goto
out
;
if
(
test_bit
(
wlvif
->
dev_role_id
,
wl
->
roc_map
))
{
ret
=
wl12xx_croc
(
wl
,
wlvif
->
dev_role_id
);
...
...
drivers/net/wireless/ti/wlcore/debugfs.c
View file @
a572ac1a
...
...
@@ -38,6 +38,8 @@
/* ms */
#define WL1271_DEBUGFS_STATS_LIFETIME 1000
#define WLCORE_MAX_BLOCK_SIZE ((size_t)(4*PAGE_SIZE))
/* debugfs macros idea from mac80211 */
int
wl1271_format_buffer
(
char
__user
*
userbuf
,
size_t
count
,
loff_t
*
ppos
,
char
*
fmt
,
...)
...
...
@@ -1025,6 +1027,195 @@ static const struct file_operations sleep_auth_ops = {
.
llseek
=
default_llseek
,
};
static
ssize_t
dev_mem_read
(
struct
file
*
file
,
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
struct
wlcore_partition_set
part
,
old_part
;
size_t
bytes
=
count
;
int
ret
;
char
*
buf
;
/* only requests of dword-aligned size and offset are supported */
if
(
bytes
%
4
)
return
-
EINVAL
;
if
(
*
ppos
%
4
)
return
-
EINVAL
;
/* function should return in reasonable time */
bytes
=
min
(
bytes
,
WLCORE_MAX_BLOCK_SIZE
);
if
(
bytes
==
0
)
return
-
EINVAL
;
memset
(
&
part
,
0
,
sizeof
(
part
));
part
.
mem
.
start
=
file
->
f_pos
;
part
.
mem
.
size
=
bytes
;
buf
=
kmalloc
(
bytes
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
)
{
ret
=
-
EFAULT
;
goto
skip_read
;
}
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
skip_read
;
/* store current partition and switch partition */
memcpy
(
&
old_part
,
&
wl
->
curr_part
,
sizeof
(
old_part
));
ret
=
wlcore_set_partition
(
wl
,
&
part
);
if
(
ret
<
0
)
goto
part_err
;
ret
=
wlcore_raw_read
(
wl
,
0
,
buf
,
bytes
,
false
);
if
(
ret
<
0
)
goto
read_err
;
read_err:
/* recover partition */
ret
=
wlcore_set_partition
(
wl
,
&
old_part
);
if
(
ret
<
0
)
goto
part_err
;
part_err:
wl1271_ps_elp_sleep
(
wl
);
skip_read:
mutex_unlock
(
&
wl
->
mutex
);
if
(
ret
==
0
)
{
ret
=
copy_to_user
(
user_buf
,
buf
,
bytes
);
if
(
ret
<
bytes
)
{
bytes
-=
ret
;
*
ppos
+=
bytes
;
ret
=
0
;
}
else
{
ret
=
-
EFAULT
;
}
}
kfree
(
buf
);
return
((
ret
==
0
)
?
bytes
:
ret
);
}
static
ssize_t
dev_mem_write
(
struct
file
*
file
,
const
char
__user
*
user_buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
wl1271
*
wl
=
file
->
private_data
;
struct
wlcore_partition_set
part
,
old_part
;
size_t
bytes
=
count
;
int
ret
;
char
*
buf
;
/* only requests of dword-aligned size and offset are supported */
if
(
bytes
%
4
)
return
-
EINVAL
;
if
(
*
ppos
%
4
)
return
-
EINVAL
;
/* function should return in reasonable time */
bytes
=
min
(
bytes
,
WLCORE_MAX_BLOCK_SIZE
);
if
(
bytes
==
0
)
return
-
EINVAL
;
memset
(
&
part
,
0
,
sizeof
(
part
));
part
.
mem
.
start
=
file
->
f_pos
;
part
.
mem
.
size
=
bytes
;
buf
=
kmalloc
(
bytes
,
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
ret
=
copy_from_user
(
buf
,
user_buf
,
bytes
);
if
(
ret
)
{
ret
=
-
EFAULT
;
goto
err_out
;
}
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
)
{
ret
=
-
EFAULT
;
goto
skip_write
;
}
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
skip_write
;
/* store current partition and switch partition */
memcpy
(
&
old_part
,
&
wl
->
curr_part
,
sizeof
(
old_part
));
ret
=
wlcore_set_partition
(
wl
,
&
part
);
if
(
ret
<
0
)
goto
part_err
;
ret
=
wlcore_raw_write
(
wl
,
0
,
buf
,
bytes
,
false
);
if
(
ret
<
0
)
goto
write_err
;
write_err:
/* recover partition */
ret
=
wlcore_set_partition
(
wl
,
&
old_part
);
if
(
ret
<
0
)
goto
part_err
;
part_err:
wl1271_ps_elp_sleep
(
wl
);
skip_write:
mutex_unlock
(
&
wl
->
mutex
);
if
(
ret
==
0
)
*
ppos
+=
bytes
;
err_out:
kfree
(
buf
);
return
((
ret
==
0
)
?
bytes
:
ret
);
}
static
loff_t
dev_mem_seek
(
struct
file
*
file
,
loff_t
offset
,
int
orig
)
{
loff_t
ret
;
/* only requests of dword-aligned size and offset are supported */
if
(
offset
%
4
)
return
-
EINVAL
;
switch
(
orig
)
{
case
SEEK_SET
:
file
->
f_pos
=
offset
;
ret
=
file
->
f_pos
;
break
;
case
SEEK_CUR
:
file
->
f_pos
+=
offset
;
ret
=
file
->
f_pos
;
break
;
default:
ret
=
-
EINVAL
;
}
return
ret
;
}
static
const
struct
file_operations
dev_mem_ops
=
{
.
open
=
simple_open
,
.
read
=
dev_mem_read
,
.
write
=
dev_mem_write
,
.
llseek
=
dev_mem_seek
,
};
static
int
wl1271_debugfs_add_files
(
struct
wl1271
*
wl
,
struct
dentry
*
rootdir
)
{
...
...
@@ -1059,6 +1250,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD_PREFIX
(
rx_streaming
,
interval
,
streaming
);
DEBUGFS_ADD_PREFIX
(
rx_streaming
,
always
,
streaming
);
DEBUGFS_ADD_PREFIX
(
dev
,
mem
,
rootdir
);
return
0
;
...
...
drivers/net/wireless/ti/wlcore/event.c
View file @
a572ac1a
...
...
@@ -105,6 +105,7 @@ static int wl1271_event_process(struct wl1271 *wl)
u32
vector
;
bool
disconnect_sta
=
false
;
unsigned
long
sta_bitmap
=
0
;
int
ret
;
wl1271_event_mbox_dump
(
mbox
);
...
...
@@ -228,7 +229,9 @@ static int wl1271_event_process(struct wl1271 *wl)
if
((
vector
&
DUMMY_PACKET_EVENT_ID
))
{
wl1271_debug
(
DEBUG_EVENT
,
"DUMMY_PACKET_ID_EVENT_ID"
);
wl1271_tx_dummy_packet
(
wl
);
ret
=
wl1271_tx_dummy_packet
(
wl
);
if
(
ret
<
0
)
return
ret
;
}
/*
...
...
@@ -301,8 +304,10 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
return
-
EINVAL
;
/* first we read the mbox descriptor */
wl1271_read
(
wl
,
wl
->
mbox_ptr
[
mbox_num
],
wl
->
mbox
,
sizeof
(
*
wl
->
mbox
),
false
);
ret
=
wlcore_read
(
wl
,
wl
->
mbox_ptr
[
mbox_num
],
wl
->
mbox
,
sizeof
(
*
wl
->
mbox
),
false
);
if
(
ret
<
0
)
return
ret
;
/* process the descriptor */
ret
=
wl1271_event_process
(
wl
);
...
...
@@ -313,7 +318,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
* TODO: we just need this because one bit is in a different
* place. Is there any better way?
*/
wl
->
ops
->
ack_event
(
wl
);
ret
=
wl
->
ops
->
ack_event
(
wl
);
return
0
;
return
ret
;
}
drivers/net/wireless/ti/wlcore/hw_ops.h
View file @
a572ac1a
...
...
@@ -65,11 +65,13 @@ wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
return
wl
->
ops
->
get_rx_buf_align
(
wl
,
rx_desc
);
}
static
inline
void
static
inline
int
wlcore_hw_prepare_read
(
struct
wl1271
*
wl
,
u32
rx_desc
,
u32
len
)
{
if
(
wl
->
ops
->
prepare_read
)
wl
->
ops
->
prepare_read
(
wl
,
rx_desc
,
len
);
return
wl
->
ops
->
prepare_read
(
wl
,
rx_desc
,
len
);
return
0
;
}
static
inline
u32
...
...
@@ -81,10 +83,12 @@ wlcore_hw_get_rx_packet_len(struct wl1271 *wl, void *rx_data, u32 data_len)
return
wl
->
ops
->
get_rx_packet_len
(
wl
,
rx_data
,
data_len
);
}
static
inline
void
wlcore_hw_tx_delayed_compl
(
struct
wl1271
*
wl
)
static
inline
int
wlcore_hw_tx_delayed_compl
(
struct
wl1271
*
wl
)
{
if
(
wl
->
ops
->
tx_delayed_compl
)
wl
->
ops
->
tx_delayed_compl
(
wl
);
return
wl
->
ops
->
tx_delayed_compl
(
wl
);
return
0
;
}
static
inline
void
wlcore_hw_tx_immediate_compl
(
struct
wl1271
*
wl
)
...
...
drivers/net/wireless/ti/wlcore/io.c
View file @
a572ac1a
...
...
@@ -48,6 +48,12 @@ void wlcore_disable_interrupts(struct wl1271 *wl)
}
EXPORT_SYMBOL_GPL
(
wlcore_disable_interrupts
);
void
wlcore_disable_interrupts_nosync
(
struct
wl1271
*
wl
)
{
disable_irq_nosync
(
wl
->
irq
);
}
EXPORT_SYMBOL_GPL
(
wlcore_disable_interrupts_nosync
);
void
wlcore_enable_interrupts
(
struct
wl1271
*
wl
)
{
enable_irq
(
wl
->
irq
);
...
...
@@ -122,9 +128,11 @@ EXPORT_SYMBOL_GPL(wlcore_translate_addr);
* | |
*
*/
void
wlcore_set_partition
(
struct
wl1271
*
wl
,
const
struct
wlcore_partition_set
*
p
)
int
wlcore_set_partition
(
struct
wl1271
*
wl
,
const
struct
wlcore_partition_set
*
p
)
{
int
ret
;
/* copy partition info */
memcpy
(
&
wl
->
curr_part
,
p
,
sizeof
(
*
p
));
...
...
@@ -137,28 +145,41 @@ void wlcore_set_partition(struct wl1271 *wl,
wl1271_debug
(
DEBUG_IO
,
"mem3_start %08X mem3_size %08X"
,
p
->
mem3
.
start
,
p
->
mem3
.
size
);
wl1271_raw_write32
(
wl
,
HW_PART0_START_ADDR
,
p
->
mem
.
start
);
wl1271_raw_write32
(
wl
,
HW_PART0_SIZE_ADDR
,
p
->
mem
.
size
);
wl1271_raw_write32
(
wl
,
HW_PART1_START_ADDR
,
p
->
reg
.
start
);
wl1271_raw_write32
(
wl
,
HW_PART1_SIZE_ADDR
,
p
->
reg
.
size
);
wl1271_raw_write32
(
wl
,
HW_PART2_START_ADDR
,
p
->
mem2
.
start
);
wl1271_raw_write32
(
wl
,
HW_PART2_SIZE_ADDR
,
p
->
mem2
.
size
);
ret
=
wlcore_raw_write32
(
wl
,
HW_PART0_START_ADDR
,
p
->
mem
.
start
);
if
(
ret
<
0
)
goto
out
;
ret
=
wlcore_raw_write32
(
wl
,
HW_PART0_SIZE_ADDR
,
p
->
mem
.
size
);
if
(
ret
<
0
)
goto
out
;
ret
=
wlcore_raw_write32
(
wl
,
HW_PART1_START_ADDR
,
p
->
reg
.
start
);
if
(
ret
<
0
)
goto
out
;
ret
=
wlcore_raw_write32
(
wl
,
HW_PART1_SIZE_ADDR
,
p
->
reg
.
size
);
if
(
ret
<
0
)
goto
out
;
ret
=
wlcore_raw_write32
(
wl
,
HW_PART2_START_ADDR
,
p
->
mem2
.
start
);
if
(
ret
<
0
)
goto
out
;
ret
=
wlcore_raw_write32
(
wl
,
HW_PART2_SIZE_ADDR
,
p
->
mem2
.
size
);
if
(
ret
<
0
)
goto
out
;
/*
* We don't need the size of the last partition, as it is
* automatically calculated based on the total memory size and
* the sizes of the previous partitions.
*/
wl1271_raw_write32
(
wl
,
HW_PART3_START_ADDR
,
p
->
mem3
.
start
);
}
EXPORT_SYMBOL_GPL
(
wlcore_set_partition
);
ret
=
wlcore_raw_write32
(
wl
,
HW_PART3_START_ADDR
,
p
->
mem3
.
start
);
void
wlcore_select_partition
(
struct
wl1271
*
wl
,
u8
part
)
{
wl1271_debug
(
DEBUG_IO
,
"setting partition %d"
,
part
);
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
part
]);
out:
return
ret
;
}
EXPORT_SYMBOL_GPL
(
wlcore_se
lec
t_partition
);
EXPORT_SYMBOL_GPL
(
wlcore_set_partition
);
void
wl1271_io_reset
(
struct
wl1271
*
wl
)
{
...
...
drivers/net/wireless/ti/wlcore/io.h
View file @
a572ac1a
...
...
@@ -45,6 +45,7 @@
struct
wl1271
;
void
wlcore_disable_interrupts
(
struct
wl1271
*
wl
);
void
wlcore_disable_interrupts_nosync
(
struct
wl1271
*
wl
);
void
wlcore_enable_interrupts
(
struct
wl1271
*
wl
);
void
wl1271_io_reset
(
struct
wl1271
*
wl
);
...
...
@@ -52,79 +53,113 @@ void wl1271_io_init(struct wl1271 *wl);
int
wlcore_translate_addr
(
struct
wl1271
*
wl
,
int
addr
);
/* Raw target IO, address is not translated */
static
inline
void
wl1271_raw_write
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
inline
int
__must_check
wlcore_raw_write
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
wl
->
if_ops
->
write
(
wl
->
dev
,
addr
,
buf
,
len
,
fixed
);
int
ret
;
if
(
test_bit
(
WL1271_FLAG_SDIO_FAILED
,
&
wl
->
flags
))
return
-
EIO
;
ret
=
wl
->
if_ops
->
write
(
wl
->
dev
,
addr
,
buf
,
len
,
fixed
);
if
(
ret
)
set_bit
(
WL1271_FLAG_SDIO_FAILED
,
&
wl
->
flags
);
return
ret
;
}
static
inline
void
wl1271_raw_read
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
inline
int
__must_check
wlcore_raw_read
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
wl
->
if_ops
->
read
(
wl
->
dev
,
addr
,
buf
,
len
,
fixed
);
int
ret
;
if
(
test_bit
(
WL1271_FLAG_SDIO_FAILED
,
&
wl
->
flags
))
return
-
EIO
;
ret
=
wl
->
if_ops
->
read
(
wl
->
dev
,
addr
,
buf
,
len
,
fixed
);
if
(
ret
)
set_bit
(
WL1271_FLAG_SDIO_FAILED
,
&
wl
->
flags
);
return
ret
;
}
static
inline
void
wlcore_raw_read_data
(
struct
wl1271
*
wl
,
int
reg
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
inline
int
__must_check
wlcore_raw_read_data
(
struct
wl1271
*
wl
,
int
reg
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
wl1271
_raw_read
(
wl
,
wl
->
rtable
[
reg
],
buf
,
len
,
fixed
);
return
wlcore
_raw_read
(
wl
,
wl
->
rtable
[
reg
],
buf
,
len
,
fixed
);
}
static
inline
void
wlcore_raw_write_data
(
struct
wl1271
*
wl
,
int
reg
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
inline
int
__must_check
wlcore_raw_write_data
(
struct
wl1271
*
wl
,
int
reg
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
wl1271
_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
__must_check
wlcore_raw_read32
(
struct
wl1271
*
wl
,
int
addr
,
u32
*
val
)
{
wl1271_raw_read
(
wl
,
addr
,
&
wl
->
buffer_32
,
sizeof
(
wl
->
buffer_32
),
false
);
int
ret
;
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
le32_to_cpu
(
wl
->
buffer_32
)
;
return
0
;
}
static
inline
void
wl1271_raw_write32
(
struct
wl1271
*
wl
,
int
addr
,
u32
val
)
static
inline
int
__must_check
wlcore_raw_write32
(
struct
wl1271
*
wl
,
int
addr
,
u32
val
)
{
wl
->
buffer_32
=
cpu_to_le32
(
val
);
wl1271
_raw_write
(
wl
,
addr
,
&
wl
->
buffer_32
,
sizeof
(
wl
->
buffer_32
),
false
);
return
wlcore
_raw_write
(
wl
,
addr
,
&
wl
->
buffer_32
,
sizeof
(
wl
->
buffer_32
),
false
);
}
static
inline
void
wl1271_read
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
inline
int
__must_check
wlcore_read
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
int
physical
;
physical
=
wlcore_translate_addr
(
wl
,
addr
);
wl1271
_raw_read
(
wl
,
physical
,
buf
,
len
,
fixed
);
return
wlcore
_raw_read
(
wl
,
physical
,
buf
,
len
,
fixed
);
}
static
inline
void
wl1271_write
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
inline
int
__must_check
wlcore_write
(
struct
wl1271
*
wl
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
int
physical
;
physical
=
wlcore_translate_addr
(
wl
,
addr
);
wl1271
_raw_write
(
wl
,
physical
,
buf
,
len
,
fixed
);
return
wlcore
_raw_write
(
wl
,
physical
,
buf
,
len
,
fixed
);
}
static
inline
void
wlcore_write_data
(
struct
wl1271
*
wl
,
int
reg
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
inline
int
__must_check
wlcore_write_data
(
struct
wl1271
*
wl
,
int
reg
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
wl1271
_write
(
wl
,
wl
->
rtable
[
reg
],
buf
,
len
,
fixed
);
return
wlcore
_write
(
wl
,
wl
->
rtable
[
reg
],
buf
,
len
,
fixed
);
}
static
inline
void
wlcore_read_data
(
struct
wl1271
*
wl
,
int
reg
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
inline
int
__must_check
wlcore_read_data
(
struct
wl1271
*
wl
,
int
reg
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
wl1271
_read
(
wl
,
wl
->
rtable
[
reg
],
buf
,
len
,
fixed
);
return
wlcore
_read
(
wl
,
wl
->
rtable
[
reg
],
buf
,
len
,
fixed
);
}
static
inline
void
wl1271_read_hwaddr
(
struct
wl1271
*
wl
,
int
hwaddr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
inline
int
__must_check
wlcore_read_hwaddr
(
struct
wl1271
*
wl
,
int
hwaddr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
int
physical
;
int
addr
;
...
...
@@ -134,34 +169,47 @@ static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
physical
=
wlcore_translate_addr
(
wl
,
addr
);
wl1271
_raw_read
(
wl
,
physical
,
buf
,
len
,
fixed
);
return
wlcore
_raw_read
(
wl
,
physical
,
buf
,
len
,
fixed
);
}
static
inline
u32
wl1271_read32
(
struct
wl1271
*
wl
,
int
addr
)
static
inline
int
__must_check
wlcore_read32
(
struct
wl1271
*
wl
,
int
addr
,
u32
*
val
)
{
return
wl
1271_raw_read32
(
wl
,
wlcore_translate_addr
(
wl
,
addr
)
);
return
wl
core_raw_read32
(
wl
,
wlcore_translate_addr
(
wl
,
addr
),
val
);
}
static
inline
void
wl1271_write32
(
struct
wl1271
*
wl
,
int
addr
,
u32
val
)
static
inline
int
__must_check
wlcore_write32
(
struct
wl1271
*
wl
,
int
addr
,
u32
val
)
{
wl1271
_raw_write32
(
wl
,
wlcore_translate_addr
(
wl
,
addr
),
val
);
return
wlcore
_raw_write32
(
wl
,
wlcore_translate_addr
(
wl
,
addr
),
val
);
}
static
inline
u32
wlcore_read_reg
(
struct
wl1271
*
wl
,
int
reg
)
static
inline
int
__must_check
wlcore_read_reg
(
struct
wl1271
*
wl
,
int
reg
,
u32
*
val
)
{
return
wl1271_raw_read32
(
wl
,
wlcore_translate_addr
(
wl
,
wl
->
rtable
[
reg
]));
return
wlcore_raw_read32
(
wl
,
wlcore_translate_addr
(
wl
,
wl
->
rtable
[
reg
]),
val
);
}
static
inline
void
wlcore_write_reg
(
struct
wl1271
*
wl
,
int
reg
,
u32
val
)
static
inline
int
__must_check
wlcore_write_reg
(
struct
wl1271
*
wl
,
int
reg
,
u32
val
)
{
wl1271_raw_write32
(
wl
,
wlcore_translate_addr
(
wl
,
wl
->
rtable
[
reg
]),
val
);
return
wlcore_raw_write32
(
wl
,
wlcore_translate_addr
(
wl
,
wl
->
rtable
[
reg
]),
val
);
}
static
inline
void
wl1271_power_off
(
struct
wl1271
*
wl
)
{
wl
->
if_ops
->
power
(
wl
->
dev
,
false
);
clear_bit
(
WL1271_FLAG_GPIO_POWER
,
&
wl
->
flags
);
int
ret
;
if
(
!
test_bit
(
WL1271_FLAG_GPIO_POWER
,
&
wl
->
flags
))
return
;
ret
=
wl
->
if_ops
->
power
(
wl
->
dev
,
false
);
if
(
!
ret
)
clear_bit
(
WL1271_FLAG_GPIO_POWER
,
&
wl
->
flags
);
}
static
inline
int
wl1271_power_on
(
struct
wl1271
*
wl
)
...
...
@@ -173,8 +221,8 @@ static inline int wl1271_power_on(struct wl1271 *wl)
return
ret
;
}
void
wlcore_set_partition
(
struct
wl1271
*
wl
,
const
struct
wlcore_partition_set
*
p
);
int
wlcore_set_partition
(
struct
wl1271
*
wl
,
const
struct
wlcore_partition_set
*
p
);
bool
wl1271_set_block_size
(
struct
wl1271
*
wl
);
...
...
@@ -182,6 +230,4 @@ bool wl1271_set_block_size(struct wl1271 *wl);
int
wl1271_tx_dummy_packet
(
struct
wl1271
*
wl
);
void
wlcore_select_partition
(
struct
wl1271
*
wl
,
u8
part
);
#endif
drivers/net/wireless/ti/wlcore/main.c
View file @
a572ac1a
...
...
@@ -378,9 +378,9 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
}
}
static
void
wl12xx
_fw_status
(
struct
wl1271
*
wl
,
struct
wl_fw_status_1
*
status_1
,
struct
wl_fw_status_2
*
status_2
)
static
int
wlcore
_fw_status
(
struct
wl1271
*
wl
,
struct
wl_fw_status_1
*
status_1
,
struct
wl_fw_status_2
*
status_2
)
{
struct
wl12xx_vif
*
wlvif
;
struct
timespec
ts
;
...
...
@@ -388,12 +388,15 @@ static void wl12xx_fw_status(struct wl1271 *wl,
int
avail
,
freed_blocks
;
int
i
;
size_t
status_len
;
int
ret
;
status_len
=
WLCORE_FW_STATUS_1_LEN
(
wl
->
num_rx_desc
)
+
sizeof
(
*
status_2
)
+
wl
->
fw_status_priv_len
;
wlcore_raw_read_data
(
wl
,
REG_RAW_FW_STATUS_ADDR
,
status_1
,
status_len
,
false
);
ret
=
wlcore_raw_read_data
(
wl
,
REG_RAW_FW_STATUS_ADDR
,
status_1
,
status_len
,
false
);
if
(
ret
<
0
)
return
ret
;
wl1271_debug
(
DEBUG_IRQ
,
"intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)"
,
...
...
@@ -462,6 +465,8 @@ static void wl12xx_fw_status(struct wl1271 *wl,
getnstimeofday
(
&
ts
);
wl
->
time_offset
=
(
timespec_to_ns
(
&
ts
)
>>
10
)
-
(
s64
)
le32_to_cpu
(
status_2
->
fw_localtime
);
return
0
;
}
static
void
wl1271_flush_deferred_work
(
struct
wl1271
*
wl
)
...
...
@@ -489,20 +494,15 @@ static void wl1271_netstack_work(struct work_struct *work)
#define WL1271_IRQ_MAX_LOOPS 256
static
i
rqreturn_t
wl1271_irq
(
int
irq
,
void
*
cookie
)
static
i
nt
wlcore_irq_locked
(
struct
wl1271
*
wl
)
{
int
ret
;
int
ret
=
0
;
u32
intr
;
int
loopcount
=
WL1271_IRQ_MAX_LOOPS
;
struct
wl1271
*
wl
=
(
struct
wl1271
*
)
cookie
;
bool
done
=
false
;
unsigned
int
defer_count
;
unsigned
long
flags
;
/* TX might be handled here, avoid redundant work */
set_bit
(
WL1271_FLAG_TX_PENDING
,
&
wl
->
flags
);
cancel_work_sync
(
&
wl
->
tx_work
);
/*
* In case edge triggered interrupt must be used, we cannot iterate
* more than once without introducing race conditions with the hardirq.
...
...
@@ -510,8 +510,6 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
if
(
wl
->
platform_quirks
&
WL12XX_PLATFORM_QUIRK_EDGE_IRQ
)
loopcount
=
1
;
mutex_lock
(
&
wl
->
mutex
);
wl1271_debug
(
DEBUG_IRQ
,
"IRQ work"
);
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
...
...
@@ -530,7 +528,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
clear_bit
(
WL1271_FLAG_IRQ_RUNNING
,
&
wl
->
flags
);
smp_mb__after_clear_bit
();
wl12xx_fw_status
(
wl
,
wl
->
fw_status_1
,
wl
->
fw_status_2
);
ret
=
wlcore_fw_status
(
wl
,
wl
->
fw_status_1
,
wl
->
fw_status_2
);
if
(
ret
<
0
)
goto
out
;
wlcore_hw_tx_immediate_compl
(
wl
);
...
...
@@ -544,7 +544,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
if
(
unlikely
(
intr
&
WL1271_ACX_INTR_WATCHDOG
))
{
wl1271_error
(
"HW watchdog interrupt received! starting recovery."
);
wl
->
watchdog_recovery
=
true
;
wl12xx_queue_recovery_work
(
wl
)
;
ret
=
-
EIO
;
/* restarting the chip. ignore any other interrupt. */
goto
out
;
...
...
@@ -554,7 +554,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
wl1271_error
(
"SW watchdog interrupt received! "
"starting recovery."
);
wl
->
watchdog_recovery
=
true
;
wl12xx_queue_recovery_work
(
wl
)
;
ret
=
-
EIO
;
/* restarting the chip. ignore any other interrupt. */
goto
out
;
...
...
@@ -563,7 +563,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
if
(
likely
(
intr
&
WL1271_ACX_INTR_DATA
))
{
wl1271_debug
(
DEBUG_IRQ
,
"WL1271_ACX_INTR_DATA"
);
wl12xx_rx
(
wl
,
wl
->
fw_status_1
);
ret
=
wlcore_rx
(
wl
,
wl
->
fw_status_1
);
if
(
ret
<
0
)
goto
out
;
/* Check if any tx blocks were freed */
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
...
...
@@ -574,13 +576,17 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
* In order to avoid starvation of the TX path,
* call the work function directly.
*/
wl1271_tx_work_locked
(
wl
);
ret
=
wlcore_tx_work_locked
(
wl
);
if
(
ret
<
0
)
goto
out
;
}
else
{
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
}
/* check for tx results */
wlcore_hw_tx_delayed_compl
(
wl
);
ret
=
wlcore_hw_tx_delayed_compl
(
wl
);
if
(
ret
<
0
)
goto
out
;
/* Make sure the deferred queues don't get too long */
defer_count
=
skb_queue_len
(
&
wl
->
deferred_tx_queue
)
+
...
...
@@ -591,12 +597,16 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
if
(
intr
&
WL1271_ACX_INTR_EVENT_A
)
{
wl1271_debug
(
DEBUG_IRQ
,
"WL1271_ACX_INTR_EVENT_A"
);
wl1271_event_handle
(
wl
,
0
);
ret
=
wl1271_event_handle
(
wl
,
0
);
if
(
ret
<
0
)
goto
out
;
}
if
(
intr
&
WL1271_ACX_INTR_EVENT_B
)
{
wl1271_debug
(
DEBUG_IRQ
,
"WL1271_ACX_INTR_EVENT_B"
);
wl1271_event_handle
(
wl
,
1
);
ret
=
wl1271_event_handle
(
wl
,
1
);
if
(
ret
<
0
)
goto
out
;
}
if
(
intr
&
WL1271_ACX_INTR_INIT_COMPLETE
)
...
...
@@ -610,6 +620,25 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
wl1271_ps_elp_sleep
(
wl
);
out:
return
ret
;
}
static
irqreturn_t
wlcore_irq
(
int
irq
,
void
*
cookie
)
{
int
ret
;
unsigned
long
flags
;
struct
wl1271
*
wl
=
cookie
;
/* TX might be handled here, avoid redundant work */
set_bit
(
WL1271_FLAG_TX_PENDING
,
&
wl
->
flags
);
cancel_work_sync
(
&
wl
->
tx_work
);
mutex_lock
(
&
wl
->
mutex
);
ret
=
wlcore_irq_locked
(
wl
);
if
(
ret
)
wl12xx_queue_recovery_work
(
wl
);
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
/* In case TX was not handled here, queue TX work */
clear_bit
(
WL1271_FLAG_TX_PENDING
,
&
wl
->
flags
);
...
...
@@ -743,8 +772,13 @@ static void wl1271_fetch_nvs(struct wl1271 *wl)
void
wl12xx_queue_recovery_work
(
struct
wl1271
*
wl
)
{
if
(
!
test_bit
(
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
&
wl
->
flags
))
WARN_ON
(
!
test_bit
(
WL1271_FLAG_INTENDED_FW_RECOVERY
,
&
wl
->
flags
));
/* Avoid a recursive recovery */
if
(
!
test_and_set_bit
(
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
&
wl
->
flags
))
{
wlcore_disable_interrupts_nosync
(
wl
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
}
}
size_t
wl12xx_copy_fwlog
(
struct
wl1271
*
wl
,
u8
*
memblock
,
size_t
maxlen
)
...
...
@@ -778,6 +812,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
u32
offset
;
u32
end_of_log
;
u8
*
block
;
int
ret
;
if
((
wl
->
quirks
&
WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED
)
||
(
wl
->
conf
.
fwlog
.
mem_blocks
==
0
))
...
...
@@ -799,7 +834,10 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
wl12xx_cmd_stop_fwlog
(
wl
);
/* Read the first memory block address */
wl12xx_fw_status
(
wl
,
wl
->
fw_status_1
,
wl
->
fw_status_2
);
ret
=
wlcore_fw_status
(
wl
,
wl
->
fw_status_1
,
wl
->
fw_status_2
);
if
(
ret
<
0
)
goto
out
;
addr
=
le32_to_cpu
(
wl
->
fw_status_2
->
log_start_addr
);
if
(
!
addr
)
goto
out
;
...
...
@@ -815,8 +853,10 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
/* Traverse the memory blocks linked list */
do
{
memset
(
block
,
0
,
WL12XX_HW_BLOCK_SIZE
);
wl1271_read_hwaddr
(
wl
,
addr
,
block
,
WL12XX_HW_BLOCK_SIZE
,
false
);
ret
=
wlcore_read_hwaddr
(
wl
,
addr
,
block
,
WL12XX_HW_BLOCK_SIZE
,
false
);
if
(
ret
<
0
)
goto
out
;
/*
* Memory blocks are linked to one another. The first 4 bytes
...
...
@@ -836,6 +876,34 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
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 */
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
if
(
ret
<
0
)
return
;
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
)
{
struct
wl1271
*
wl
=
...
...
@@ -848,19 +916,9 @@ static void wl1271_recovery_work(struct work_struct *work)
if
(
wl
->
state
!=
WL1271_STATE_ON
||
wl
->
plt
)
goto
out_unlock
;
/* Avoid a recursive recovery */
set_bit
(
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
&
wl
->
flags
);
wl12xx_read_fwlog_panic
(
wl
);
/* change partitions momentarily so we can read the FW pc */
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
]);
wlcore_print_recovery
(
wl
);
BUG_ON
(
bug_on_recovery
&&
!
test_bit
(
WL1271_FLAG_INTENDED_FW_RECOVERY
,
&
wl
->
flags
));
...
...
@@ -902,8 +960,6 @@ static void wl1271_recovery_work(struct work_struct *work)
mutex_unlock
(
&
wl
->
mutex
);
wl1271_op_stop
(
wl
->
hw
);
clear_bit
(
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
&
wl
->
flags
);
ieee80211_restart_hw
(
wl
->
hw
);
/*
...
...
@@ -917,9 +973,9 @@ static void wl1271_recovery_work(struct work_struct *work)
mutex_unlock
(
&
wl
->
mutex
);
}
static
void
wl1271
_fw_wakeup
(
struct
wl1271
*
wl
)
static
int
wlcore
_fw_wakeup
(
struct
wl1271
*
wl
)
{
wl1271
_raw_write32
(
wl
,
HW_ACCESS_ELP_CTRL_REG
,
ELPCTRL_WAKE_UP
);
return
wlcore
_raw_write32
(
wl
,
HW_ACCESS_ELP_CTRL_REG
,
ELPCTRL_WAKE_UP
);
}
static
int
wl1271_setup
(
struct
wl1271
*
wl
)
...
...
@@ -955,13 +1011,21 @@ static int wl12xx_set_power_on(struct wl1271 *wl)
wl1271_io_reset
(
wl
);
wl1271_io_init
(
wl
);
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
ret
=
wlcore_set_partition
(
wl
,
&
wl
->
ptable
[
PART_BOOT
]);
if
(
ret
<
0
)
goto
fail
;
/* ELP module wake up */
wl1271_fw_wakeup
(
wl
);
ret
=
wlcore_fw_wakeup
(
wl
);
if
(
ret
<
0
)
goto
fail
;
out:
return
ret
;
fail:
wl1271_power_off
(
wl
);
return
ret
;
}
static
int
wl12xx_chip_wakeup
(
struct
wl1271
*
wl
,
bool
plt
)
...
...
@@ -1184,7 +1248,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl)
/* The FW is low on RX memory blocks, so send the dummy packet asap */
if
(
!
test_bit
(
WL1271_FLAG_FW_TX_BUSY
,
&
wl
->
flags
))
wl1271
_tx_work_locked
(
wl
);
return
wlcore
_tx_work_locked
(
wl
);
/*
* If the FW TX is busy, TX work will be scheduled by the threaded
...
...
@@ -1451,8 +1515,15 @@ static int wl1271_configure_wowlan(struct wl1271 *wl,
int
i
,
ret
;
if
(
!
wow
||
wow
->
any
||
!
wow
->
n_patterns
)
{
wl1271_acx_default_rx_filter_enable
(
wl
,
0
,
FILTER_SIGNAL
);
wl1271_rx_filter_clear_all
(
wl
);
ret
=
wl1271_acx_default_rx_filter_enable
(
wl
,
0
,
FILTER_SIGNAL
);
if
(
ret
)
goto
out
;
ret
=
wl1271_rx_filter_clear_all
(
wl
);
if
(
ret
)
goto
out
;
return
0
;
}
...
...
@@ -1468,8 +1539,13 @@ static int wl1271_configure_wowlan(struct wl1271 *wl,
}
}
wl1271_acx_default_rx_filter_enable
(
wl
,
0
,
FILTER_SIGNAL
);
wl1271_rx_filter_clear_all
(
wl
);
ret
=
wl1271_acx_default_rx_filter_enable
(
wl
,
0
,
FILTER_SIGNAL
);
if
(
ret
)
goto
out
;
ret
=
wl1271_rx_filter_clear_all
(
wl
);
if
(
ret
)
goto
out
;
/* Translate WoWLAN patterns into filters */
for
(
i
=
0
;
i
<
wow
->
n_patterns
;
i
++
)
{
...
...
@@ -1511,7 +1587,10 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
if
(
ret
<
0
)
goto
out
;
wl1271_configure_wowlan
(
wl
,
wow
);
ret
=
wl1271_configure_wowlan
(
wl
,
wow
);
if
(
ret
<
0
)
goto
out_sleep
;
ret
=
wl1271_acx_wake_up_conditions
(
wl
,
wlvif
,
wl
->
conf
.
conn
.
suspend_wake_up_event
,
wl
->
conf
.
conn
.
suspend_listen_interval
);
...
...
@@ -1519,8 +1598,8 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
if
(
ret
<
0
)
wl1271_error
(
"suspend: set wake up conditions failed: %d"
,
ret
);
out_sleep:
wl1271_ps_elp_sleep
(
wl
);
out:
return
ret
;
...
...
@@ -1599,6 +1678,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 suspend wow=%d"
,
!!
wow
);
WARN_ON
(
!
wow
);
/* we want to perform the recovery before suspending */
if
(
test_bit
(
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
&
wl
->
flags
))
{
wl1271_warning
(
"postponing suspend to perform recovery"
);
return
-
EBUSY
;
}
wl1271_tx_flush
(
wl
);
mutex_lock
(
&
wl
->
mutex
);
...
...
@@ -1639,7 +1724,8 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
struct
wl1271
*
wl
=
hw
->
priv
;
struct
wl12xx_vif
*
wlvif
;
unsigned
long
flags
;
bool
run_irq_work
=
false
;
bool
run_irq_work
=
false
,
pending_recovery
;
int
ret
;
wl1271_debug
(
DEBUG_MAC80211
,
"mac80211 resume wow=%d"
,
wl
->
wow_enabled
);
...
...
@@ -1655,17 +1741,37 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
run_irq_work
=
true
;
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
mutex_lock
(
&
wl
->
mutex
);
/* test the recovery flag before calling any SDIO functions */
pending_recovery
=
test_bit
(
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
&
wl
->
flags
);
if
(
run_irq_work
)
{
wl1271_debug
(
DEBUG_MAC80211
,
"run postponed irq_work directly"
);
wl1271_irq
(
0
,
wl
);
/* don't talk to the HW if recovery is pending */
if
(
!
pending_recovery
)
{
ret
=
wlcore_irq_locked
(
wl
);
if
(
ret
)
wl12xx_queue_recovery_work
(
wl
);
}
wlcore_enable_interrupts
(
wl
);
}
mutex_lock
(
&
wl
->
mutex
);
if
(
pending_recovery
)
{
wl1271_warning
(
"queuing forgotten recovery on resume"
);
ieee80211_queue_work
(
wl
->
hw
,
&
wl
->
recovery_work
);
goto
out
;
}
wl12xx_for_each_wlvif
(
wl
,
wlvif
)
{
wl1271_configure_resume
(
wl
,
wlvif
);
}
out:
wl
->
wow_enabled
=
false
;
mutex_unlock
(
&
wl
->
mutex
);
...
...
@@ -1706,6 +1812,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wlcore_disable_interrupts
(
wl
);
mutex_lock
(
&
wl
->
mutex
);
if
(
wl
->
state
==
WL1271_STATE_OFF
)
{
if
(
test_and_clear_bit
(
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
&
wl
->
flags
))
wlcore_enable_interrupts
(
wl
);
mutex_unlock
(
&
wl
->
mutex
);
/*
...
...
@@ -1737,6 +1847,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
mutex_lock
(
&
wl
->
mutex
);
wl1271_power_off
(
wl
);
/*
* In case a recovery was scheduled, interrupts were disabled to avoid
* an interrupt storm. Now that the power is down, it is safe to
* re-enable interrupts to balance the disable depth
*/
if
(
test_and_clear_bit
(
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
&
wl
->
flags
))
wlcore_enable_interrupts
(
wl
);
wl
->
band
=
IEEE80211_BAND_2GHZ
;
...
...
@@ -2475,7 +2592,10 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
(
wlvif
->
channel
!=
channel
)
||
(
wlvif
->
channel_type
!=
conf
->
channel_type
)))
{
/* send all pending packets */
wl1271_tx_work_locked
(
wl
);
ret
=
wlcore_tx_work_locked
(
wl
);
if
(
ret
<
0
)
return
ret
;
wlvif
->
band
=
conf
->
channel
->
band
;
wlvif
->
channel
=
channel
;
wlvif
->
channel_type
=
conf
->
channel_type
;
...
...
@@ -4934,18 +5054,22 @@ static int wl12xx_get_hw_info(struct wl1271 *wl)
if
(
ret
<
0
)
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_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
)
wl
->
ops
->
get_mac
(
wl
);
ret
=
wl
->
ops
->
get_mac
(
wl
);
wl1271_power_off
(
wl
);
out:
wl1271_power_off
(
wl
);
return
ret
;
}
...
...
@@ -5372,7 +5496,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
else
irqflags
=
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
;
ret
=
request_threaded_irq
(
wl
->
irq
,
wl12xx_hardirq
,
wl
1271
_irq
,
ret
=
request_threaded_irq
(
wl
->
irq
,
wl12xx_hardirq
,
wl
core
_irq
,
irqflags
,
pdev
->
name
,
wl
);
if
(
ret
<
0
)
{
...
...
@@ -5398,12 +5522,12 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
ret
=
wl12xx_get_hw_info
(
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"couldn't get hw info"
);
goto
out
;
goto
out
_irq
;
}
ret
=
wl
->
ops
->
identify_chip
(
wl
);
if
(
ret
<
0
)
goto
out
;
goto
out
_irq
;
ret
=
wl1271_init_ieee80211
(
wl
);
if
(
ret
)
...
...
@@ -5417,7 +5541,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
ret
=
device_create_file
(
wl
->
dev
,
&
dev_attr_bt_coex_state
);
if
(
ret
<
0
)
{
wl1271_error
(
"failed to create sysfs file bt_coex_state"
);
goto
out_
irq
;
goto
out_
unreg
;
}
/* Create sysfs file to get HW PG version */
...
...
@@ -5442,6 +5566,9 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
out_bt_coex_state:
device_remove_file
(
wl
->
dev
,
&
dev_attr_bt_coex_state
);
out_unreg:
wl1271_unregister_hw
(
wl
);
out_irq:
free_irq
(
wl
->
irq
,
wl
);
...
...
drivers/net/wireless/ti/wlcore/ps.c
View file @
a572ac1a
...
...
@@ -35,6 +35,7 @@ void wl1271_elp_work(struct work_struct *work)
struct
delayed_work
*
dwork
;
struct
wl1271
*
wl
;
struct
wl12xx_vif
*
wlvif
;
int
ret
;
dwork
=
container_of
(
work
,
struct
delayed_work
,
work
);
wl
=
container_of
(
dwork
,
struct
wl1271
,
elp_work
);
...
...
@@ -63,7 +64,12 @@ void wl1271_elp_work(struct work_struct *work)
}
wl1271_debug
(
DEBUG_PSM
,
"chip to elp"
);
wl1271_raw_write32
(
wl
,
HW_ACCESS_ELP_CTRL_REG
,
ELPCTRL_SLEEP
);
ret
=
wlcore_raw_write32
(
wl
,
HW_ACCESS_ELP_CTRL_REG
,
ELPCTRL_SLEEP
);
if
(
ret
<
0
)
{
wl12xx_queue_recovery_work
(
wl
);
goto
out
;
}
set_bit
(
WL1271_FLAG_IN_ELP
,
&
wl
->
flags
);
out:
...
...
@@ -135,7 +141,11 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
wl
->
elp_compl
=
&
compl
;
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
wl1271_raw_write32
(
wl
,
HW_ACCESS_ELP_CTRL_REG
,
ELPCTRL_WAKE_UP
);
ret
=
wlcore_raw_write32
(
wl
,
HW_ACCESS_ELP_CTRL_REG
,
ELPCTRL_WAKE_UP
);
if
(
ret
<
0
)
{
wl12xx_queue_recovery_work
(
wl
);
goto
err
;
}
if
(
!
pending
)
{
ret
=
wait_for_completion_timeout
(
...
...
drivers/net/wireless/ti/wlcore/rx.c
View file @
a572ac1a
...
...
@@ -200,7 +200,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
return
is_data
;
}
void
wl12xx
_rx
(
struct
wl1271
*
wl
,
struct
wl_fw_status_1
*
status
)
int
wlcore
_rx
(
struct
wl1271
*
wl
,
struct
wl_fw_status_1
*
status
)
{
unsigned
long
active_hlids
[
BITS_TO_LONGS
(
WL12XX_MAX_LINKS
)]
=
{
0
};
u32
buf_size
;
...
...
@@ -211,6 +211,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
u32
pkt_offset
,
des
;
u8
hlid
;
enum
wl_rx_buf_align
rx_align
;
int
ret
=
0
;
while
(
drv_rx_counter
!=
fw_rx_counter
)
{
buf_size
=
0
;
...
...
@@ -234,9 +235,14 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
/* Read all available packets at once */
des
=
le32_to_cpu
(
status
->
rx_pkt_descs
[
drv_rx_counter
]);
wlcore_hw_prepare_read
(
wl
,
des
,
buf_size
);
wlcore_read_data
(
wl
,
REG_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_size
,
true
);
ret
=
wlcore_hw_prepare_read
(
wl
,
des
,
buf_size
);
if
(
ret
<
0
)
goto
out
;
ret
=
wlcore_read_data
(
wl
,
REG_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_size
,
true
);
if
(
ret
<
0
)
goto
out
;
/* Split data into separate packets */
pkt_offset
=
0
;
...
...
@@ -273,11 +279,17 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
* Write the driver's packet counter to the FW. This is only required
* for older hardware revisions
*/
if
(
wl
->
quirks
&
WLCORE_QUIRK_END_OF_TRANSACTION
)
wl1271_write32
(
wl
,
WL12XX_REG_RX_DRIVER_COUNTER
,
wl
->
rx_counter
);
if
(
wl
->
quirks
&
WLCORE_QUIRK_END_OF_TRANSACTION
)
{
ret
=
wlcore_write32
(
wl
,
WL12XX_REG_RX_DRIVER_COUNTER
,
wl
->
rx_counter
);
if
(
ret
<
0
)
goto
out
;
}
wl12xx_rearm_rx_streaming
(
wl
,
active_hlids
);
out:
return
ret
;
}
#ifdef CONFIG_PM
...
...
@@ -306,14 +318,19 @@ int wl1271_rx_filter_enable(struct wl1271 *wl,
return
0
;
}
void
wl1271_rx_filter_clear_all
(
struct
wl1271
*
wl
)
int
wl1271_rx_filter_clear_all
(
struct
wl1271
*
wl
)
{
int
i
;
int
i
,
ret
=
0
;
for
(
i
=
0
;
i
<
WL1271_MAX_RX_FILTERS
;
i
++
)
{
if
(
!
wl
->
rx_filter_enabled
[
i
])
continue
;
wl1271_rx_filter_enable
(
wl
,
i
,
0
,
NULL
);
ret
=
wl1271_rx_filter_enable
(
wl
,
i
,
0
,
NULL
);
if
(
ret
)
goto
out
;
}
out:
return
ret
;
}
#endif
/* CONFIG_PM */
drivers/net/wireless/ti/wlcore/rx.h
View file @
a572ac1a
...
...
@@ -143,11 +143,11 @@ struct wl1271_rx_descriptor {
u8
reserved
;
}
__packed
;
void
wl12xx
_rx
(
struct
wl1271
*
wl
,
struct
wl_fw_status_1
*
status
);
int
wlcore
_rx
(
struct
wl1271
*
wl
,
struct
wl_fw_status_1
*
status
);
u8
wl1271_rate_to_idx
(
int
rate
,
enum
ieee80211_band
band
);
int
wl1271_rx_filter_enable
(
struct
wl1271
*
wl
,
int
index
,
bool
enable
,
struct
wl12xx_rx_filter
*
filter
);
void
wl1271_rx_filter_clear_all
(
struct
wl1271
*
wl
);
int
wl1271_rx_filter_clear_all
(
struct
wl1271
*
wl
);
#endif
drivers/net/wireless/ti/wlcore/sdio.c
View file @
a572ac1a
...
...
@@ -71,8 +71,8 @@ static void wl1271_sdio_set_block_size(struct device *child,
sdio_release_host
(
func
);
}
static
void
wl12xx_sdio_raw_read
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
int
__must_check
wl12xx_sdio_raw_read
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
int
ret
;
struct
wl12xx_sdio_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
...
...
@@ -103,12 +103,14 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
sdio_release_host
(
func
);
if
(
ret
)
if
(
WARN_ON
(
ret
)
)
dev_err
(
child
->
parent
,
"sdio read failed (%d)
\n
"
,
ret
);
return
ret
;
}
static
void
wl12xx_sdio_raw_write
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
int
__must_check
wl12xx_sdio_raw_write
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
int
ret
;
struct
wl12xx_sdio_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
...
...
@@ -139,25 +141,30 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
sdio_release_host
(
func
);
if
(
ret
)
if
(
WARN_ON
(
ret
)
)
dev_err
(
child
->
parent
,
"sdio write failed (%d)
\n
"
,
ret
);
return
ret
;
}
static
int
wl12xx_sdio_power_on
(
struct
wl12xx_sdio_glue
*
glue
)
{
int
ret
;
struct
sdio_func
*
func
=
dev_to_sdio_func
(
glue
->
dev
);
struct
mmc_card
*
card
=
func
->
card
;
/* If enabled, tell runtime PM not to power off the card */
if
(
pm_runtime_enabled
(
&
func
->
dev
))
{
ret
=
pm_runtime_get_sync
(
&
func
->
dev
);
if
(
ret
<
0
)
goto
out
;
}
else
{
/* Runtime PM is disabled: power up the card manually */
ret
=
mmc_power_restore_host
(
func
->
card
->
host
);
if
(
ret
<
0
)
ret
=
pm_runtime_get_sync
(
&
card
->
dev
);
if
(
ret
)
{
/*
* Runtime PM might be temporarily disabled, or the device
* might have a positive reference counter. Make sure it is
* really powered on.
*/
ret
=
mmc_power_restore_host
(
card
->
host
);
if
(
ret
<
0
)
{
pm_runtime_put_sync
(
&
card
->
dev
);
goto
out
;
}
}
sdio_claim_host
(
func
);
...
...
@@ -172,20 +179,21 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
{
int
ret
;
struct
sdio_func
*
func
=
dev_to_sdio_func
(
glue
->
dev
);
struct
mmc_card
*
card
=
func
->
card
;
sdio_claim_host
(
func
);
sdio_disable_func
(
func
);
sdio_release_host
(
func
);
/* Power off the card manually
, even if runtime PM is enabled.
*/
ret
=
mmc_power_save_host
(
func
->
card
->
host
);
/* Power off the card manually
in case it wasn't powered off above
*/
ret
=
mmc_power_save_host
(
card
->
host
);
if
(
ret
<
0
)
return
re
t
;
goto
ou
t
;
/* If enabled, let runtime PM know the card is powered off */
if
(
pm_runtime_enabled
(
&
func
->
dev
))
ret
=
pm_runtime_put_sync
(
&
func
->
dev
);
/* Let runtime PM know the card is powered off */
pm_runtime_put_sync
(
&
card
->
dev
);
out:
return
ret
;
}
...
...
drivers/net/wireless/ti/wlcore/spi.c
View file @
a572ac1a
...
...
@@ -193,8 +193,8 @@ static int wl12xx_spi_read_busy(struct device *child)
return
-
ETIMEDOUT
;
}
static
void
wl12xx_spi_raw_read
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
int
__must_check
wl12xx_spi_raw_read
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
struct
wl12xx_spi_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
struct
wl1271
*
wl
=
dev_get_drvdata
(
child
);
...
...
@@ -238,7 +238,7 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf,
if
(
!
(
busy_buf
[
WL1271_BUSY_WORD_CNT
-
1
]
&
0x1
)
&&
wl12xx_spi_read_busy
(
child
))
{
memset
(
buf
,
0
,
chunk_len
);
return
;
return
0
;
}
spi_message_init
(
&
m
);
...
...
@@ -256,10 +256,12 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf,
buf
+=
chunk_len
;
len
-=
chunk_len
;
}
return
0
;
}
static
void
wl12xx_spi_raw_write
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
static
int
__must_check
wl12xx_spi_raw_write
(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
)
{
struct
wl12xx_spi_glue
*
glue
=
dev_get_drvdata
(
child
->
parent
);
struct
spi_transfer
t
[
2
*
WSPI_MAX_NUM_OF_CHUNKS
];
...
...
@@ -304,6 +306,8 @@ static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf,
}
spi_sync
(
to_spi_device
(
glue
->
dev
),
&
m
);
return
0
;
}
static
struct
wl1271_if_operations
spi_ops
=
{
...
...
drivers/net/wireless/ti/wlcore/tx.c
View file @
a572ac1a
...
...
@@ -352,8 +352,10 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
bool
is_dummy
;
bool
is_gem
=
false
;
if
(
!
skb
)
if
(
!
skb
)
{
wl1271_error
(
"discarding null skb"
);
return
-
EINVAL
;
}
info
=
IEEE80211_SKB_CB
(
skb
);
...
...
@@ -662,7 +664,17 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids)
}
}
void
wl1271_tx_work_locked
(
struct
wl1271
*
wl
)
/*
* Returns failure values only in case of failed bus ops within this function.
* wl1271_prepare_tx_frame retvals won't be returned in order to avoid
* triggering recovery by higher layers when not necessary.
* In case a FW command fails within wl1271_prepare_tx_frame fails a recovery
* will be queued in wl1271_cmd_send. -EAGAIN/-EBUSY from prepare_tx_frame
* can occur and are legitimate so don't propagate. -EINVAL will emit a WARNING
* within prepare_tx_frame code but there's nothing we should do about those
* as well.
*/
int
wlcore_tx_work_locked
(
struct
wl1271
*
wl
)
{
struct
wl12xx_vif
*
wlvif
;
struct
sk_buff
*
skb
;
...
...
@@ -670,10 +682,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
u32
buf_offset
=
0
,
last_len
=
0
;
bool
sent_packets
=
false
;
unsigned
long
active_hlids
[
BITS_TO_LONGS
(
WL12XX_MAX_LINKS
)]
=
{
0
};
int
ret
;
int
ret
=
0
;
int
bus_ret
=
0
;
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
return
;
return
0
;
while
((
skb
=
wl1271_skb_dequeue
(
wl
)))
{
struct
ieee80211_tx_info
*
info
=
IEEE80211_SKB_CB
(
skb
);
...
...
@@ -694,8 +707,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
buf_offset
=
wlcore_hw_pre_pkt_send
(
wl
,
buf_offset
,
last_len
);
wlcore_write_data
(
wl
,
REG_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_offset
,
true
);
bus_ret
=
wlcore_write_data
(
wl
,
REG_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_offset
,
true
);
if
(
bus_ret
<
0
)
goto
out
;
sent_packets
=
true
;
buf_offset
=
0
;
continue
;
...
...
@@ -731,8 +747,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
out_ack:
if
(
buf_offset
)
{
buf_offset
=
wlcore_hw_pre_pkt_send
(
wl
,
buf_offset
,
last_len
);
wlcore_write_data
(
wl
,
REG_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_offset
,
true
);
bus_ret
=
wlcore_write_data
(
wl
,
REG_SLV_MEM_DATA
,
wl
->
aggr_buf
,
buf_offset
,
true
);
if
(
bus_ret
<
0
)
goto
out
;
sent_packets
=
true
;
}
if
(
sent_packets
)
{
...
...
@@ -740,13 +759,19 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
* Interrupt the firmware with the new packets. This is only
* required for older hardware revisions
*/
if
(
wl
->
quirks
&
WLCORE_QUIRK_END_OF_TRANSACTION
)
wl1271_write32
(
wl
,
WL12XX_HOST_WR_ACCESS
,
wl
->
tx_packets_count
);
if
(
wl
->
quirks
&
WLCORE_QUIRK_END_OF_TRANSACTION
)
{
bus_ret
=
wlcore_write32
(
wl
,
WL12XX_HOST_WR_ACCESS
,
wl
->
tx_packets_count
);
if
(
bus_ret
<
0
)
goto
out
;
}
wl1271_handle_tx_low_watermark
(
wl
);
}
wl12xx_rearm_rx_streaming
(
wl
,
active_hlids
);
out:
return
bus_ret
;
}
void
wl1271_tx_work
(
struct
work_struct
*
work
)
...
...
@@ -759,7 +784,11 @@ void wl1271_tx_work(struct work_struct *work)
if
(
ret
<
0
)
goto
out
;
wl1271_tx_work_locked
(
wl
);
ret
=
wlcore_tx_work_locked
(
wl
);
if
(
ret
<
0
)
{
wl12xx_queue_recovery_work
(
wl
);
goto
out
;
}
wl1271_ps_elp_sleep
(
wl
);
out:
...
...
@@ -881,22 +910,28 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
}
/* Called upon reception of a TX complete interrupt */
void
wl1271
_tx_complete
(
struct
wl1271
*
wl
)
int
wlcore
_tx_complete
(
struct
wl1271
*
wl
)
{
struct
wl1271_acx_mem_map
*
memmap
=
(
struct
wl1271_acx_mem_map
*
)
wl
->
target_mem_map
;
u32
count
,
fw_counter
;
u32
i
;
int
ret
;
/* read the tx results from the chipset */
wl1271_read
(
wl
,
le32_to_cpu
(
memmap
->
tx_result
),
wl
->
tx_res_if
,
sizeof
(
*
wl
->
tx_res_if
),
false
);
ret
=
wlcore_read
(
wl
,
le32_to_cpu
(
memmap
->
tx_result
),
wl
->
tx_res_if
,
sizeof
(
*
wl
->
tx_res_if
),
false
);
if
(
ret
<
0
)
goto
out
;
fw_counter
=
le32_to_cpu
(
wl
->
tx_res_if
->
tx_result_fw_counter
);
/* write host counter to chipset (to ack) */
wl1271_write32
(
wl
,
le32_to_cpu
(
memmap
->
tx_result
)
+
offsetof
(
struct
wl1271_tx_hw_res_if
,
tx_result_host_counter
),
fw_counter
);
ret
=
wlcore_write32
(
wl
,
le32_to_cpu
(
memmap
->
tx_result
)
+
offsetof
(
struct
wl1271_tx_hw_res_if
,
tx_result_host_counter
),
fw_counter
);
if
(
ret
<
0
)
goto
out
;
count
=
fw_counter
-
wl
->
tx_results_count
;
wl1271_debug
(
DEBUG_TX
,
"tx_complete received, packets: %d"
,
count
);
...
...
@@ -916,8 +951,11 @@ void wl1271_tx_complete(struct wl1271 *wl)
wl
->
tx_results_count
++
;
}
out:
return
ret
;
}
EXPORT_SYMBOL
(
wl
1271
_tx_complete
);
EXPORT_SYMBOL
(
wl
core
_tx_complete
);
void
wl1271_tx_reset_link_queues
(
struct
wl1271
*
wl
,
u8
hlid
)
{
...
...
drivers/net/wireless/ti/wlcore/tx.h
View file @
a572ac1a
...
...
@@ -234,8 +234,8 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
}
void
wl1271_tx_work
(
struct
work_struct
*
work
);
void
wl1271
_tx_work_locked
(
struct
wl1271
*
wl
);
void
wl1271
_tx_complete
(
struct
wl1271
*
wl
);
int
wlcore
_tx_work_locked
(
struct
wl1271
*
wl
);
int
wlcore
_tx_complete
(
struct
wl1271
*
wl
);
void
wl12xx_tx_reset_wlvif
(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
void
wl12xx_tx_reset
(
struct
wl1271
*
wl
);
void
wl1271_tx_flush
(
struct
wl1271
*
wl
);
...
...
drivers/net/wireless/ti/wlcore/wlcore.h
View file @
a572ac1a
...
...
@@ -41,9 +41,9 @@ struct wlcore_ops {
int
(
*
identify_fw
)(
struct
wl1271
*
wl
);
int
(
*
boot
)(
struct
wl1271
*
wl
);
int
(
*
plt_init
)(
struct
wl1271
*
wl
);
void
(
*
trigger_cmd
)(
struct
wl1271
*
wl
,
int
cmd_box_addr
,
void
*
buf
,
size_t
len
);
void
(
*
ack_event
)(
struct
wl1271
*
wl
);
int
(
*
trigger_cmd
)(
struct
wl1271
*
wl
,
int
cmd_box_addr
,
void
*
buf
,
size_t
len
);
int
(
*
ack_event
)(
struct
wl1271
*
wl
);
u32
(
*
calc_tx_blocks
)(
struct
wl1271
*
wl
,
u32
len
,
u32
spare_blks
);
void
(
*
set_tx_desc_blocks
)(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
...
...
@@ -53,17 +53,17 @@ struct wlcore_ops {
struct
sk_buff
*
skb
);
enum
wl_rx_buf_align
(
*
get_rx_buf_align
)(
struct
wl1271
*
wl
,
u32
rx_desc
);
void
(
*
prepare_read
)(
struct
wl1271
*
wl
,
u32
rx_desc
,
u32
len
);
int
(
*
prepare_read
)(
struct
wl1271
*
wl
,
u32
rx_desc
,
u32
len
);
u32
(
*
get_rx_packet_len
)(
struct
wl1271
*
wl
,
void
*
rx_data
,
u32
data_len
);
void
(
*
tx_delayed_compl
)(
struct
wl1271
*
wl
);
int
(
*
tx_delayed_compl
)(
struct
wl1271
*
wl
);
void
(
*
tx_immediate_compl
)(
struct
wl1271
*
wl
);
int
(
*
hw_init
)(
struct
wl1271
*
wl
);
int
(
*
init_vif
)(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
u32
(
*
sta_get_ap_rate_mask
)(
struct
wl1271
*
wl
,
struct
wl12xx_vif
*
wlvif
);
s8
(
*
get_pg_ver
)(
struct
wl1271
*
wl
);
void
(
*
get_mac
)(
struct
wl1271
*
wl
);
int
(
*
get_pg_ver
)(
struct
wl1271
*
wl
,
s8
*
ver
);
int
(
*
get_mac
)(
struct
wl1271
*
wl
);
void
(
*
set_tx_desc_csum
)(
struct
wl1271
*
wl
,
struct
wl1271_tx_hw_descr
*
desc
,
struct
sk_buff
*
skb
);
...
...
drivers/net/wireless/ti/wlcore/wlcore_i.h
View file @
a572ac1a
...
...
@@ -209,10 +209,10 @@ struct wl1271_scan {
};
struct
wl1271_if_operations
{
void
(
*
read
)(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
);
void
(
*
write
)(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
);
int
__must_check
(
*
read
)(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
);
int
__must_check
(
*
write
)(
struct
device
*
child
,
int
addr
,
void
*
buf
,
size_t
len
,
bool
fixed
);
void
(
*
reset
)(
struct
device
*
child
);
void
(
*
init
)(
struct
device
*
child
);
int
(
*
power
)(
struct
device
*
child
,
bool
enable
);
...
...
@@ -247,6 +247,7 @@ enum wl12xx_flags {
WL1271_FLAG_RECOVERY_IN_PROGRESS
,
WL1271_FLAG_VIF_CHANGE_IN_PROGRESS
,
WL1271_FLAG_INTENDED_FW_RECOVERY
,
WL1271_FLAG_SDIO_FAILED
,
};
enum
wl12xx_vif_flags
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment