Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
e55034e9
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
e55034e9
编写于
4月 25, 2011
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-linville' of
git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
上级
73b48099
cf27d867
变更
29
展开全部
隐藏空白更改
内联
并排
Showing
29 changed file
with
1324 addition
and
289 deletion
+1324
-289
drivers/net/wireless/wl12xx/Kconfig
drivers/net/wireless/wl12xx/Kconfig
+1
-1
drivers/net/wireless/wl12xx/acx.c
drivers/net/wireless/wl12xx/acx.c
+47
-12
drivers/net/wireless/wl12xx/acx.h
drivers/net/wireless/wl12xx/acx.h
+11
-0
drivers/net/wireless/wl12xx/boot.c
drivers/net/wireless/wl12xx/boot.c
+236
-43
drivers/net/wireless/wl12xx/boot.h
drivers/net/wireless/wl12xx/boot.h
+52
-0
drivers/net/wireless/wl12xx/cmd.c
drivers/net/wireless/wl12xx/cmd.c
+91
-6
drivers/net/wireless/wl12xx/cmd.h
drivers/net/wireless/wl12xx/cmd.h
+34
-0
drivers/net/wireless/wl12xx/conf.h
drivers/net/wireless/wl12xx/conf.h
+6
-11
drivers/net/wireless/wl12xx/debugfs.c
drivers/net/wireless/wl12xx/debugfs.c
+1
-1
drivers/net/wireless/wl12xx/event.c
drivers/net/wireless/wl12xx/event.c
+12
-5
drivers/net/wireless/wl12xx/event.h
drivers/net/wireless/wl12xx/event.h
+4
-1
drivers/net/wireless/wl12xx/ini.h
drivers/net/wireless/wl12xx/ini.h
+96
-2
drivers/net/wireless/wl12xx/init.c
drivers/net/wireless/wl12xx/init.c
+40
-5
drivers/net/wireless/wl12xx/init.h
drivers/net/wireless/wl12xx/init.h
+1
-0
drivers/net/wireless/wl12xx/io.c
drivers/net/wireless/wl12xx/io.c
+11
-0
drivers/net/wireless/wl12xx/io.h
drivers/net/wireless/wl12xx/io.h
+3
-0
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/main.c
+276
-67
drivers/net/wireless/wl12xx/ps.c
drivers/net/wireless/wl12xx/ps.c
+0
-3
drivers/net/wireless/wl12xx/reg.h
drivers/net/wireless/wl12xx/reg.h
+2
-13
drivers/net/wireless/wl12xx/rx.c
drivers/net/wireless/wl12xx/rx.c
+24
-20
drivers/net/wireless/wl12xx/scan.c
drivers/net/wireless/wl12xx/scan.c
+10
-7
drivers/net/wireless/wl12xx/sdio.c
drivers/net/wireless/wl12xx/sdio.c
+24
-3
drivers/net/wireless/wl12xx/sdio_test.c
drivers/net/wireless/wl12xx/sdio_test.c
+17
-3
drivers/net/wireless/wl12xx/spi.c
drivers/net/wireless/wl12xx/spi.c
+14
-3
drivers/net/wireless/wl12xx/testmode.c
drivers/net/wireless/wl12xx/testmode.c
+5
-1
drivers/net/wireless/wl12xx/tx.c
drivers/net/wireless/wl12xx/tx.c
+176
-58
drivers/net/wireless/wl12xx/tx.h
drivers/net/wireless/wl12xx/tx.h
+50
-10
drivers/net/wireless/wl12xx/wl12xx.h
drivers/net/wireless/wl12xx/wl12xx.h
+56
-9
include/linux/wl12xx.h
include/linux/wl12xx.h
+24
-5
未找到文件。
drivers/net/wireless/wl12xx/Kconfig
浏览文件 @
e55034e9
...
...
@@ -3,7 +3,7 @@ menuconfig WL12XX_MENU
depends on MAC80211 && EXPERIMENTAL
---help---
This will enable TI wl12xx driver support for the following chips:
wl1271
and wl127
3.
wl1271
, wl1273, wl1281 and wl128
3.
The drivers make use of the mac80211 stack.
config WL12XX
...
...
drivers/net/wireless/wl12xx/acx.c
浏览文件 @
e55034e9
...
...
@@ -965,10 +965,13 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
}
/* memory config */
mem_conf
->
num_stations
=
wl
->
conf
.
mem
.
num_stations
;
mem_conf
->
rx_mem_block_num
=
wl
->
conf
.
mem
.
rx_block_num
;
mem_conf
->
tx_min_mem_block_num
=
wl
->
conf
.
mem
.
tx_min_block_num
;
mem_conf
->
num_ssid_profiles
=
wl
->
conf
.
mem
.
ssid_profiles
;
/* FIXME: for now we always use mem_wl127x for AP, because it
* doesn't support dynamic memory and we don't have the
* optimal values for wl128x without dynamic memory yet */
mem_conf
->
num_stations
=
wl
->
conf
.
mem_wl127x
.
num_stations
;
mem_conf
->
rx_mem_block_num
=
wl
->
conf
.
mem_wl127x
.
rx_block_num
;
mem_conf
->
tx_min_mem_block_num
=
wl
->
conf
.
mem_wl127x
.
tx_min_block_num
;
mem_conf
->
num_ssid_profiles
=
wl
->
conf
.
mem_wl127x
.
ssid_profiles
;
mem_conf
->
total_tx_descriptors
=
cpu_to_le32
(
ACX_TX_DESCRIPTORS
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_MEM_CFG
,
mem_conf
,
...
...
@@ -986,6 +989,7 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
int
wl1271_acx_sta_mem_cfg
(
struct
wl1271
*
wl
)
{
struct
wl1271_acx_sta_config_memory
*
mem_conf
;
struct
conf_memory_settings
*
mem
;
int
ret
;
wl1271_debug
(
DEBUG_ACX
,
"wl1271 mem cfg"
);
...
...
@@ -996,16 +1000,21 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
goto
out
;
}
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
mem
=
&
wl
->
conf
.
mem_wl128x
;
else
mem
=
&
wl
->
conf
.
mem_wl127x
;
/* memory config */
mem_conf
->
num_stations
=
wl
->
conf
.
mem
.
num_stations
;
mem_conf
->
rx_mem_block_num
=
wl
->
conf
.
mem
.
rx_block_num
;
mem_conf
->
tx_min_mem_block_num
=
wl
->
conf
.
mem
.
tx_min_block_num
;
mem_conf
->
num_ssid_profiles
=
wl
->
conf
.
mem
.
ssid_profiles
;
mem_conf
->
num_stations
=
mem
->
num_stations
;
mem_conf
->
rx_mem_block_num
=
mem
->
rx_block_num
;
mem_conf
->
tx_min_mem_block_num
=
mem
->
tx_min_block_num
;
mem_conf
->
num_ssid_profiles
=
mem
->
ssid_profiles
;
mem_conf
->
total_tx_descriptors
=
cpu_to_le32
(
ACX_TX_DESCRIPTORS
);
mem_conf
->
dyn_mem_enable
=
wl
->
conf
.
mem
.
dynamic_memory
;
mem_conf
->
tx_free_req
=
wl
->
conf
.
mem
.
min_req_tx_blocks
;
mem_conf
->
rx_free_req
=
wl
->
conf
.
mem
.
min_req_rx_blocks
;
mem_conf
->
tx_min
=
wl
->
conf
.
mem
.
tx_min
;
mem_conf
->
dyn_mem_enable
=
mem
->
dynamic_memory
;
mem_conf
->
tx_free_req
=
mem
->
min_req_tx_blocks
;
mem_conf
->
rx_free_req
=
mem
->
min_req_rx_blocks
;
mem_conf
->
tx_min
=
mem
->
tx_min
;
ret
=
wl1271_cmd_configure
(
wl
,
ACX_MEM_CFG
,
mem_conf
,
sizeof
(
*
mem_conf
));
...
...
@@ -1019,6 +1028,32 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
return
ret
;
}
int
wl1271_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
)
{
struct
wl1271_acx_host_config_bitmap
*
bitmap_conf
;
int
ret
;
bitmap_conf
=
kzalloc
(
sizeof
(
*
bitmap_conf
),
GFP_KERNEL
);
if
(
!
bitmap_conf
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
bitmap_conf
->
host_cfg_bitmap
=
cpu_to_le32
(
host_cfg_bitmap
);
ret
=
wl1271_cmd_configure
(
wl
,
ACX_HOST_IF_CFG_BITMAP
,
bitmap_conf
,
sizeof
(
*
bitmap_conf
));
if
(
ret
<
0
)
{
wl1271_warning
(
"wl1271 bitmap config opt failed: %d"
,
ret
);
goto
out
;
}
out:
kfree
(
bitmap_conf
);
return
ret
;
}
int
wl1271_acx_init_mem_config
(
struct
wl1271
*
wl
)
{
int
ret
;
...
...
drivers/net/wireless/wl12xx/acx.h
浏览文件 @
e55034e9
...
...
@@ -939,6 +939,16 @@ struct wl1271_acx_keep_alive_config {
u8
padding
;
}
__packed
;
#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0)
#define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1)
#define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3)
struct
wl1271_acx_host_config_bitmap
{
struct
acx_header
header
;
__le32
host_cfg_bitmap
;
}
__packed
;
enum
{
WL1271_ACX_TRIG_TYPE_LEVEL
=
0
,
WL1271_ACX_TRIG_TYPE_EDGE
,
...
...
@@ -1275,6 +1285,7 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl);
int
wl1271_acx_ap_mem_cfg
(
struct
wl1271
*
wl
);
int
wl1271_acx_sta_mem_cfg
(
struct
wl1271
*
wl
);
int
wl1271_acx_init_mem_config
(
struct
wl1271
*
wl
);
int
wl1271_acx_host_if_cfg_bitmap
(
struct
wl1271
*
wl
,
u32
host_cfg_bitmap
);
int
wl1271_acx_init_rx_interrupt
(
struct
wl1271
*
wl
);
int
wl1271_acx_smart_reflex
(
struct
wl1271
*
wl
);
int
wl1271_acx_bet_enable
(
struct
wl1271
*
wl
,
bool
enable
);
...
...
drivers/net/wireless/wl12xx/boot.c
浏览文件 @
e55034e9
...
...
@@ -22,6 +22,7 @@
*/
#include <linux/slab.h>
#include <linux/wl12xx.h>
#include "acx.h"
#include "reg.h"
...
...
@@ -243,33 +244,57 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
if
(
wl
->
nvs
==
NULL
)
return
-
ENODEV
;
/*
* FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
* configurations) can be removed when those NVS files stop floating
* around.
*/
if
(
wl
->
nvs_len
==
sizeof
(
struct
wl1271_nvs_file
)
||
wl
->
nvs_len
==
WL1271_INI_LEGACY_NVS_FILE_SIZE
)
{
/* for now 11a is unsupported in AP mode */
if
(
wl
->
bss_type
!=
BSS_TYPE_AP_BSS
&&
wl
->
nvs
->
general_params
.
dual_mode_select
)
wl
->
enable_11a
=
true
;
}
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
struct
wl128x_nvs_file
*
nvs
=
(
struct
wl128x_nvs_file
*
)
wl
->
nvs
;
if
(
wl
->
nvs_len
==
sizeof
(
struct
wl128x_nvs_file
))
{
if
(
nvs
->
general_params
.
dual_mode_select
)
wl
->
enable_11a
=
true
;
}
else
{
wl1271_error
(
"nvs size is not as expected: %zu != %zu"
,
wl
->
nvs_len
,
sizeof
(
struct
wl128x_nvs_file
));
kfree
(
wl
->
nvs
);
wl
->
nvs
=
NULL
;
wl
->
nvs_len
=
0
;
return
-
EILSEQ
;
}
if
(
wl
->
nvs_len
!=
sizeof
(
struct
wl1271_nvs_file
)
&&
(
wl
->
nvs_len
!=
WL1271_INI_LEGACY_NVS_FILE_SIZE
||
wl
->
enable_11a
))
{
wl1271_error
(
"nvs size is not as expected: %zu != %zu"
,
wl
->
nvs_len
,
sizeof
(
struct
wl1271_nvs_file
));
kfree
(
wl
->
nvs
);
wl
->
nvs
=
NULL
;
wl
->
nvs_len
=
0
;
return
-
EILSEQ
;
}
/* only the first part of the NVS needs to be uploaded */
nvs_len
=
sizeof
(
nvs
->
nvs
);
nvs_ptr
=
(
u8
*
)
nvs
->
nvs
;
}
else
{
struct
wl1271_nvs_file
*
nvs
=
(
struct
wl1271_nvs_file
*
)
wl
->
nvs
;
/*
* FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
* band configurations) can be removed when those NVS files stop
* floating around.
*/
if
(
wl
->
nvs_len
==
sizeof
(
struct
wl1271_nvs_file
)
||
wl
->
nvs_len
==
WL1271_INI_LEGACY_NVS_FILE_SIZE
)
{
/* for now 11a is unsupported in AP mode */
if
(
wl
->
bss_type
!=
BSS_TYPE_AP_BSS
&&
nvs
->
general_params
.
dual_mode_select
)
wl
->
enable_11a
=
true
;
}
/* only the first part of the NVS needs to be uploaded */
nvs_len
=
sizeof
(
wl
->
nvs
->
nvs
);
nvs_ptr
=
(
u8
*
)
wl
->
nvs
->
nvs
;
if
(
wl
->
nvs_len
!=
sizeof
(
struct
wl1271_nvs_file
)
&&
(
wl
->
nvs_len
!=
WL1271_INI_LEGACY_NVS_FILE_SIZE
||
wl
->
enable_11a
))
{
wl1271_error
(
"nvs size is not as expected: %zu != %zu"
,
wl
->
nvs_len
,
sizeof
(
struct
wl1271_nvs_file
));
kfree
(
wl
->
nvs
);
wl
->
nvs
=
NULL
;
wl
->
nvs_len
=
0
;
return
-
EILSEQ
;
}
/* only the first part of the NVS needs to be uploaded */
nvs_len
=
sizeof
(
nvs
->
nvs
);
nvs_ptr
=
(
u8
*
)
nvs
->
nvs
;
}
/* update current MAC address to NVS */
nvs_ptr
[
11
]
=
wl
->
mac_addr
[
0
];
...
...
@@ -319,10 +344,13 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
/*
* We've reached the first zero length, the first NVS table
* is located at an aligned offset which is at least 7 bytes further.
* NOTE: The wl->nvs->nvs element must be first, in order to
* simplify the casting, we assume it is at the beginning of
* the wl->nvs structure.
*/
nvs_ptr
=
(
u8
*
)
wl
->
nvs
->
nvs
+
ALIGN
(
nvs_ptr
-
(
u8
*
)
wl
->
nvs
->
nvs
+
7
,
4
);
nvs_len
-=
nvs_ptr
-
(
u8
*
)
wl
->
nvs
->
nvs
;
nvs_ptr
=
(
u8
*
)
wl
->
nvs
+
ALIGN
(
nvs_ptr
-
(
u8
*
)
wl
->
nvs
+
7
,
4
);
nvs_len
-=
nvs_ptr
-
(
u8
*
)
wl
->
nvs
;
/* Now we must set the partition correctly */
wl1271_set_partition
(
wl
,
&
part_table
[
PART_WORK
]);
...
...
@@ -454,6 +482,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
wl
->
event_mask
|=
STA_REMOVE_COMPLETE_EVENT_ID
;
else
wl
->
event_mask
|=
DUMMY_PACKET_EVENT_ID
;
ret
=
wl1271_event_unmask
(
wl
);
if
(
ret
<
0
)
{
...
...
@@ -493,24 +523,159 @@ static void wl1271_boot_hw_version(struct wl1271 *wl)
wl
->
quirks
|=
WL12XX_QUIRK_END_OF_TRANSACTION
;
}
/* uploads NVS and firmware */
int
wl1271_load_firmware
(
struct
wl1271
*
wl
)
static
int
wl128x_switch_tcxo_to_fref
(
struct
wl1271
*
wl
)
{
int
ret
=
0
;
u32
tmp
,
clk
,
pause
;
u16
spare_reg
;
/* Mask bits [2] & [8:4] in the sys_clk_cfg register */
spare_reg
=
wl1271_top_reg_read
(
wl
,
WL_SPARE_REG
);
if
(
spare_reg
==
0xFFFF
)
return
-
EFAULT
;
spare_reg
|=
(
BIT
(
3
)
|
BIT
(
5
)
|
BIT
(
6
));
wl1271_top_reg_write
(
wl
,
WL_SPARE_REG
,
spare_reg
);
/* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
wl1271_top_reg_write
(
wl
,
SYS_CLK_CFG_REG
,
WL_CLK_REQ_TYPE_PG2
|
MCS_PLL_CLK_SEL_FREF
);
/* Delay execution for 15msec, to let the HW settle */
mdelay
(
15
);
return
0
;
}
static
bool
wl128x_is_tcxo_valid
(
struct
wl1271
*
wl
)
{
u16
tcxo_detection
;
tcxo_detection
=
wl1271_top_reg_read
(
wl
,
TCXO_CLK_DETECT_REG
);
if
(
tcxo_detection
&
TCXO_DET_FAILED
)
return
false
;
return
true
;
}
static
bool
wl128x_is_fref_valid
(
struct
wl1271
*
wl
)
{
u16
fref_detection
;
fref_detection
=
wl1271_top_reg_read
(
wl
,
FREF_CLK_DETECT_REG
);
if
(
fref_detection
&
FREF_CLK_DETECT_FAIL
)
return
false
;
return
true
;
}
static
int
wl128x_manually_configure_mcs_pll
(
struct
wl1271
*
wl
)
{
wl1271_top_reg_write
(
wl
,
MCS_PLL_M_REG
,
MCS_PLL_M_REG_VAL
);
wl1271_top_reg_write
(
wl
,
MCS_PLL_N_REG
,
MCS_PLL_N_REG_VAL
);
wl1271_top_reg_write
(
wl
,
MCS_PLL_CONFIG_REG
,
MCS_PLL_CONFIG_REG_VAL
);
return
0
;
}
static
int
wl128x_configure_mcs_pll
(
struct
wl1271
*
wl
,
int
clk
)
{
u16
spare_reg
;
u16
pll_config
;
u8
input_freq
;
/* Mask bits [3:1] in the sys_clk_cfg register */
spare_reg
=
wl1271_top_reg_read
(
wl
,
WL_SPARE_REG
);
if
(
spare_reg
==
0xFFFF
)
return
-
EFAULT
;
spare_reg
|=
BIT
(
2
);
wl1271_top_reg_write
(
wl
,
WL_SPARE_REG
,
spare_reg
);
/* Handle special cases of the TCXO clock */
if
(
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_16_8
||
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_33_6
)
return
wl128x_manually_configure_mcs_pll
(
wl
);
/* Set the input frequency according to the selected clock source */
input_freq
=
(
clk
&
1
)
+
1
;
pll_config
=
wl1271_top_reg_read
(
wl
,
MCS_PLL_CONFIG_REG
);
if
(
pll_config
==
0xFFFF
)
return
-
EFAULT
;
pll_config
|=
(
input_freq
<<
MCS_SEL_IN_FREQ_SHIFT
);
pll_config
|=
MCS_PLL_ENABLE_HP
;
wl1271_top_reg_write
(
wl
,
MCS_PLL_CONFIG_REG
,
pll_config
);
return
0
;
}
/*
* WL128x has two clocks input - TCXO and FREF.
* TCXO is the main clock of the device, while FREF is used to sync
* between the GPS and the cellular modem.
* In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
* as the WLAN/BT main clock.
*/
static
int
wl128x_boot_clk
(
struct
wl1271
*
wl
,
int
*
selected_clock
)
{
u16
sys_clk_cfg
;
/* For XTAL-only modes, FREF will be used after switching from TCXO */
if
(
wl
->
ref_clock
==
WL12XX_REFCLOCK_26_XTAL
||
wl
->
ref_clock
==
WL12XX_REFCLOCK_38_XTAL
)
{
if
(
!
wl128x_switch_tcxo_to_fref
(
wl
))
return
-
EINVAL
;
goto
fref_clk
;
}
/* Query the HW, to determine which clock source we should use */
sys_clk_cfg
=
wl1271_top_reg_read
(
wl
,
SYS_CLK_CFG_REG
);
if
(
sys_clk_cfg
==
0xFFFF
)
return
-
EINVAL
;
if
(
sys_clk_cfg
&
PRCM_CM_EN_MUX_WLAN_FREF
)
goto
fref_clk
;
/* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
if
(
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_16_368
||
wl
->
tcxo_clock
==
WL12XX_TCXOCLOCK_32_736
)
{
if
(
!
wl128x_switch_tcxo_to_fref
(
wl
))
return
-
EINVAL
;
goto
fref_clk
;
}
/* TCXO clock is selected */
if
(
!
wl128x_is_tcxo_valid
(
wl
))
return
-
EINVAL
;
*
selected_clock
=
wl
->
tcxo_clock
;
goto
config_mcs_pll
;
fref_clk:
/* FREF clock is selected */
if
(
!
wl128x_is_fref_valid
(
wl
))
return
-
EINVAL
;
*
selected_clock
=
wl
->
ref_clock
;
config_mcs_pll:
return
wl128x_configure_mcs_pll
(
wl
,
*
selected_clock
);
}
static
int
wl127x_boot_clk
(
struct
wl1271
*
wl
)
{
u32
pause
;
u32
clk
;
wl1271_boot_hw_version
(
wl
);
if
(
wl
->
ref_clock
==
0
||
wl
->
ref_clock
==
2
||
wl
->
ref_clock
==
4
)
if
(
wl
->
ref_clock
==
CONF_REF_CLK_19_2_E
||
wl
->
ref_clock
==
CONF_REF_CLK_38_4_E
||
wl
->
ref_clock
==
CONF_REF_CLK_38_4_M_XTAL
)
/* ref clk: 19.2/38.4/38.4-XTAL */
clk
=
0x3
;
else
if
(
wl
->
ref_clock
==
1
||
wl
->
ref_clock
==
3
)
else
if
(
wl
->
ref_clock
==
CONF_REF_CLK_26_E
||
wl
->
ref_clock
==
CONF_REF_CLK_52_E
)
/* ref clk: 26/52 */
clk
=
0x5
;
else
return
-
EINVAL
;
if
(
wl
->
ref_clock
!=
0
)
{
if
(
wl
->
ref_clock
!=
CONF_REF_CLK_19_2_E
)
{
u16
val
;
/* Set clock type (open drain) */
val
=
wl1271_top_reg_read
(
wl
,
OCP_REG_CLK_TYPE
);
...
...
@@ -540,6 +705,26 @@ int wl1271_load_firmware(struct wl1271 *wl)
pause
|=
WU_COUNTER_PAUSE_VAL
;
wl1271_write32
(
wl
,
WU_COUNTER_PAUSE
,
pause
);
return
0
;
}
/* uploads NVS and firmware */
int
wl1271_load_firmware
(
struct
wl1271
*
wl
)
{
int
ret
=
0
;
u32
tmp
,
clk
;
int
selected_clock
=
-
1
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
ret
=
wl128x_boot_clk
(
wl
,
&
selected_clock
);
if
(
ret
<
0
)
goto
out
;
}
else
{
ret
=
wl127x_boot_clk
(
wl
);
if
(
ret
<
0
)
goto
out
;
}
/* Continue the ELP wake up sequence */
wl1271_write32
(
wl
,
WELP_ARM_COMMAND
,
WELP_ARM_COMMAND_VAL
);
udelay
(
500
);
...
...
@@ -555,7 +740,12 @@ int wl1271_load_firmware(struct wl1271 *wl)
wl1271_debug
(
DEBUG_BOOT
,
"clk2 0x%x"
,
clk
);
clk
|=
(
wl
->
ref_clock
<<
1
)
<<
4
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
clk
|=
((
selected_clock
&
0x3
)
<<
1
)
<<
4
;
}
else
{
clk
|=
(
wl
->
ref_clock
<<
1
)
<<
4
;
}
wl1271_write32
(
wl
,
DRPW_SCRATCH_START
,
clk
);
wl1271_set_partition
(
wl
,
&
part_table
[
PART_WORK
]);
...
...
@@ -585,16 +775,12 @@ int wl1271_load_firmware(struct wl1271 *wl)
/* 6. read the EEPROM parameters */
tmp
=
wl1271_read32
(
wl
,
SCR_PAD2
);
ret
=
wl1271_boot_write_irq_polarity
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_write32
(
wl
,
ACX_REG_INTERRUPT_MASK
,
WL1271_ACX_ALL_EVENTS_VECTOR
);
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
wl1271_top_reg_write
(
wl
,
SDIO_IO_DS
,
wl
->
conf
.
hci_io_ds
);
ret
=
wl1271_boot_upload_firmware
(
wl
);
if
(
ret
<
0
)
goto
out
;
...
...
@@ -618,6 +804,13 @@ int wl1271_boot(struct wl1271 *wl)
if
(
ret
<
0
)
goto
out
;
ret
=
wl1271_boot_write_irq_polarity
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_write32
(
wl
,
ACX_REG_INTERRUPT_MASK
,
WL1271_ACX_ALL_EVENTS_VECTOR
);
/* Enable firmware interrupts now */
wl1271_boot_enable_interrupts
(
wl
);
...
...
drivers/net/wireless/wl12xx/boot.h
浏览文件 @
e55034e9
...
...
@@ -74,4 +74,56 @@ struct wl1271_static_data {
#define FREF_CLK_POLARITY_BITS 0xfffff8ff
#define CLK_REQ_OUTN_SEL 0x700
/* PLL configuration algorithm for wl128x */
#define SYS_CLK_CFG_REG 0x2200
/* Bit[0] - 0-TCXO, 1-FREF */
#define MCS_PLL_CLK_SEL_FREF BIT(0)
/* Bit[3:2] - 01-TCXO, 10-FREF */
#define WL_CLK_REQ_TYPE_FREF BIT(3)
#define WL_CLK_REQ_TYPE_PG2 (BIT(3) | BIT(2))
/* Bit[4] - 0-TCXO, 1-FREF */
#define PRCM_CM_EN_MUX_WLAN_FREF BIT(4)
#define TCXO_ILOAD_INT_REG 0x2264
#define TCXO_CLK_DETECT_REG 0x2266
#define TCXO_DET_FAILED BIT(4)
#define FREF_ILOAD_INT_REG 0x2084
#define FREF_CLK_DETECT_REG 0x2086
#define FREF_CLK_DETECT_FAIL BIT(4)
/* Use this reg for masking during driver access */
#define WL_SPARE_REG 0x2320
#define WL_SPARE_VAL BIT(2)
/* Bit[6:5:3] - mask wl write SYS_CLK_CFG[8:5:2:4] */
#define WL_SPARE_MASK_8526 (BIT(6) | BIT(5) | BIT(3))
#define PLL_LOCK_COUNTERS_REG 0xD8C
#define PLL_LOCK_COUNTERS_COEX 0x0F
#define PLL_LOCK_COUNTERS_MCS 0xF0
#define MCS_PLL_OVERRIDE_REG 0xD90
#define MCS_PLL_CONFIG_REG 0xD92
#define MCS_SEL_IN_FREQ_MASK 0x0070
#define MCS_SEL_IN_FREQ_SHIFT 4
#define MCS_PLL_CONFIG_REG_VAL 0x73
#define MCS_PLL_ENABLE_HP (BIT(0) | BIT(1))
#define MCS_PLL_M_REG 0xD94
#define MCS_PLL_N_REG 0xD96
#define MCS_PLL_M_REG_VAL 0xC8
#define MCS_PLL_N_REG_VAL 0x07
#define SDIO_IO_DS 0xd14
/* SDIO/wSPI DS configuration values */
enum
{
HCI_IO_DS_8MA
=
0
,
HCI_IO_DS_4MA
=
1
,
/* default */
HCI_IO_DS_6MA
=
2
,
HCI_IO_DS_2MA
=
3
,
};
/* end PLL configuration algorithm for wl128x */
#endif
drivers/net/wireless/wl12xx/cmd.c
浏览文件 @
e55034e9
...
...
@@ -110,7 +110,47 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
int
wl1271_cmd_general_parms
(
struct
wl1271
*
wl
)
{
struct
wl1271_general_parms_cmd
*
gen_parms
;
struct
wl1271_ini_general_params
*
gp
=
&
wl
->
nvs
->
general_params
;
struct
wl1271_ini_general_params
*
gp
=
&
((
struct
wl1271_nvs_file
*
)
wl
->
nvs
)
->
general_params
;
bool
answer
=
false
;
int
ret
;
if
(
!
wl
->
nvs
)
return
-
ENODEV
;
gen_parms
=
kzalloc
(
sizeof
(
*
gen_parms
),
GFP_KERNEL
);
if
(
!
gen_parms
)
return
-
ENOMEM
;
gen_parms
->
test
.
id
=
TEST_CMD_INI_FILE_GENERAL_PARAM
;
memcpy
(
&
gen_parms
->
general_params
,
gp
,
sizeof
(
*
gp
));
if
(
gp
->
tx_bip_fem_auto_detect
)
answer
=
true
;
ret
=
wl1271_cmd_test
(
wl
,
gen_parms
,
sizeof
(
*
gen_parms
),
answer
);
if
(
ret
<
0
)
{
wl1271_warning
(
"CMD_INI_FILE_GENERAL_PARAM failed"
);
goto
out
;
}
gp
->
tx_bip_fem_manufacturer
=
gen_parms
->
general_params
.
tx_bip_fem_manufacturer
;
wl1271_debug
(
DEBUG_CMD
,
"FEM autodetect: %s, manufacturer: %d
\n
"
,
answer
?
"auto"
:
"manual"
,
gp
->
tx_bip_fem_manufacturer
);
out:
kfree
(
gen_parms
);
return
ret
;
}
int
wl128x_cmd_general_parms
(
struct
wl1271
*
wl
)
{
struct
wl128x_general_parms_cmd
*
gen_parms
;
struct
wl128x_ini_general_params
*
gp
=
&
((
struct
wl128x_nvs_file
*
)
wl
->
nvs
)
->
general_params
;
bool
answer
=
false
;
int
ret
;
...
...
@@ -147,8 +187,9 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
int
wl1271_cmd_radio_parms
(
struct
wl1271
*
wl
)
{
struct
wl1271_nvs_file
*
nvs
=
(
struct
wl1271_nvs_file
*
)
wl
->
nvs
;
struct
wl1271_radio_parms_cmd
*
radio_parms
;
struct
wl1271_ini_general_params
*
gp
=
&
wl
->
nvs
->
general_params
;
struct
wl1271_ini_general_params
*
gp
=
&
nvs
->
general_params
;
int
ret
;
if
(
!
wl
->
nvs
)
...
...
@@ -161,18 +202,18 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
radio_parms
->
test
.
id
=
TEST_CMD_INI_FILE_RADIO_PARAM
;
/* 2.4GHz parameters */
memcpy
(
&
radio_parms
->
static_params_2
,
&
wl
->
nvs
->
stat_radio_params_2
,
memcpy
(
&
radio_parms
->
static_params_2
,
&
nvs
->
stat_radio_params_2
,
sizeof
(
struct
wl1271_ini_band_params_2
));
memcpy
(
&
radio_parms
->
dyn_params_2
,
&
wl
->
nvs
->
dyn_radio_params_2
[
gp
->
tx_bip_fem_manufacturer
].
params
,
&
nvs
->
dyn_radio_params_2
[
gp
->
tx_bip_fem_manufacturer
].
params
,
sizeof
(
struct
wl1271_ini_fem_params_2
));
/* 5GHz parameters */
memcpy
(
&
radio_parms
->
static_params_5
,
&
wl
->
nvs
->
stat_radio_params_5
,
&
nvs
->
stat_radio_params_5
,
sizeof
(
struct
wl1271_ini_band_params_5
));
memcpy
(
&
radio_parms
->
dyn_params_5
,
&
wl
->
nvs
->
dyn_radio_params_5
[
gp
->
tx_bip_fem_manufacturer
].
params
,
&
nvs
->
dyn_radio_params_5
[
gp
->
tx_bip_fem_manufacturer
].
params
,
sizeof
(
struct
wl1271_ini_fem_params_5
));
wl1271_dump
(
DEBUG_CMD
,
"TEST_CMD_INI_FILE_RADIO_PARAM: "
,
...
...
@@ -186,6 +227,50 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
return
ret
;
}
int
wl128x_cmd_radio_parms
(
struct
wl1271
*
wl
)
{
struct
wl128x_nvs_file
*
nvs
=
(
struct
wl128x_nvs_file
*
)
wl
->
nvs
;
struct
wl128x_radio_parms_cmd
*
radio_parms
;
struct
wl128x_ini_general_params
*
gp
=
&
nvs
->
general_params
;
int
ret
;
if
(
!
wl
->
nvs
)
return
-
ENODEV
;
radio_parms
=
kzalloc
(
sizeof
(
*
radio_parms
),
GFP_KERNEL
);
if
(
!
radio_parms
)
return
-
ENOMEM
;
radio_parms
->
test
.
id
=
TEST_CMD_INI_FILE_RADIO_PARAM
;
/* 2.4GHz parameters */
memcpy
(
&
radio_parms
->
static_params_2
,
&
nvs
->
stat_radio_params_2
,
sizeof
(
struct
wl128x_ini_band_params_2
));
memcpy
(
&
radio_parms
->
dyn_params_2
,
&
nvs
->
dyn_radio_params_2
[
gp
->
tx_bip_fem_manufacturer
].
params
,
sizeof
(
struct
wl128x_ini_fem_params_2
));
/* 5GHz parameters */
memcpy
(
&
radio_parms
->
static_params_5
,
&
nvs
->
stat_radio_params_5
,
sizeof
(
struct
wl128x_ini_band_params_5
));
memcpy
(
&
radio_parms
->
dyn_params_5
,
&
nvs
->
dyn_radio_params_5
[
gp
->
tx_bip_fem_manufacturer
].
params
,
sizeof
(
struct
wl128x_ini_fem_params_5
));
radio_parms
->
fem_vendor_and_options
=
nvs
->
fem_vendor_and_options
;
wl1271_dump
(
DEBUG_CMD
,
"TEST_CMD_INI_FILE_RADIO_PARAM: "
,
radio_parms
,
sizeof
(
*
radio_parms
));
ret
=
wl1271_cmd_test
(
wl
,
radio_parms
,
sizeof
(
*
radio_parms
),
0
);
if
(
ret
<
0
)
wl1271_warning
(
"CMD_INI_FILE_RADIO_PARAM failed"
);
kfree
(
radio_parms
);
return
ret
;
}
int
wl1271_cmd_ext_radio_parms
(
struct
wl1271
*
wl
)
{
struct
wl1271_ext_radio_parms_cmd
*
ext_radio_parms
;
...
...
drivers/net/wireless/wl12xx/cmd.h
浏览文件 @
e55034e9
...
...
@@ -32,7 +32,9 @@ struct acx_header;
int
wl1271_cmd_send
(
struct
wl1271
*
wl
,
u16
id
,
void
*
buf
,
size_t
len
,
size_t
res_len
);
int
wl1271_cmd_general_parms
(
struct
wl1271
*
wl
);
int
wl128x_cmd_general_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl128x_cmd_radio_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_ext_radio_parms
(
struct
wl1271
*
wl
);
int
wl1271_cmd_join
(
struct
wl1271
*
wl
,
u8
bss_type
);
int
wl1271_cmd_test
(
struct
wl1271
*
wl
,
void
*
buf
,
size_t
buf_len
,
u8
answer
);
...
...
@@ -415,6 +417,21 @@ struct wl1271_general_parms_cmd {
u8
padding
[
3
];
}
__packed
;
struct
wl128x_general_parms_cmd
{
struct
wl1271_cmd_header
header
;
struct
wl1271_cmd_test_header
test
;
struct
wl128x_ini_general_params
general_params
;
u8
sr_debug_table
[
WL1271_INI_MAX_SMART_REFLEX_PARAM
];
u8
sr_sen_n_p
;
u8
sr_sen_n_p_gain
;
u8
sr_sen_nrn
;
u8
sr_sen_prn
;
u8
padding
[
3
];
}
__packed
;
struct
wl1271_radio_parms_cmd
{
struct
wl1271_cmd_header
header
;
...
...
@@ -431,6 +448,23 @@ struct wl1271_radio_parms_cmd {
u8
padding3
[
2
];
}
__packed
;
struct
wl128x_radio_parms_cmd
{
struct
wl1271_cmd_header
header
;
struct
wl1271_cmd_test_header
test
;
/* Static radio parameters */
struct
wl128x_ini_band_params_2
static_params_2
;
struct
wl128x_ini_band_params_5
static_params_5
;
u8
fem_vendor_and_options
;
/* Dynamic radio parameters */
struct
wl128x_ini_fem_params_2
dyn_params_2
;
u8
padding2
;
struct
wl128x_ini_fem_params_5
dyn_params_5
;
}
__packed
;
struct
wl1271_ext_radio_parms_cmd
{
struct
wl1271_cmd_header
header
;
...
...
drivers/net/wireless/wl12xx/conf.h
浏览文件 @
e55034e9
...
...
@@ -1004,7 +1004,9 @@ enum {
CONF_REF_CLK_19_2_E
,
CONF_REF_CLK_26_E
,
CONF_REF_CLK_38_4_E
,
CONF_REF_CLK_52_E
CONF_REF_CLK_52_E
,
CONF_REF_CLK_38_4_M_XTAL
,
CONF_REF_CLK_26_M_XTAL
,
};
enum
single_dual_band_enum
{
...
...
@@ -1018,15 +1020,6 @@ enum single_dual_band_enum {
#define CONF_NUMBER_OF_CHANNELS_2_4 14
#define CONF_NUMBER_OF_CHANNELS_5 35
struct
conf_radio_parms
{
/*
* FEM parameter set to use
*
* Range: 0 or 1
*/
u8
fem
;
};
struct
conf_itrim_settings
{
/* enable dco itrim */
u8
enable
;
...
...
@@ -1202,7 +1195,9 @@ struct conf_drv_settings {
struct
conf_scan_settings
scan
;
struct
conf_rf_settings
rf
;
struct
conf_ht_setting
ht
;
struct
conf_memory_settings
mem
;
struct
conf_memory_settings
mem_wl127x
;
struct
conf_memory_settings
mem_wl128x
;
u8
hci_io_ds
;
};
#endif
drivers/net/wireless/wl12xx/debugfs.c
浏览文件 @
e55034e9
...
...
@@ -267,7 +267,7 @@ static ssize_t gpio_power_write(struct file *file,
}
buf
[
len
]
=
'\0'
;
ret
=
strict_
strtoul
(
buf
,
0
,
&
value
);
ret
=
k
strtoul
(
buf
,
0
,
&
value
);
if
(
ret
<
0
)
{
wl1271_warning
(
"illegal value in gpio_power"
);
return
-
EINVAL
;
...
...
drivers/net/wireless/wl12xx/event.c
浏览文件 @
e55034e9
...
...
@@ -33,6 +33,7 @@ void wl1271_pspoll_work(struct work_struct *work)
{
struct
delayed_work
*
dwork
;
struct
wl1271
*
wl
;
int
ret
;
dwork
=
container_of
(
work
,
struct
delayed_work
,
work
);
wl
=
container_of
(
dwork
,
struct
wl1271
,
pspoll_work
);
...
...
@@ -55,8 +56,13 @@ void wl1271_pspoll_work(struct work_struct *work)
* delivery failure occurred, and no-one changed state since, so
* we should go back to powersave.
*/
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_ps_set_mode
(
wl
,
STATION_POWER_SAVE_MODE
,
wl
->
basic_rate
,
true
);
wl1271_ps_elp_sleep
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
};
...
...
@@ -129,11 +135,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
/* enable beacon early termination */
ret
=
wl1271_acx_bet_enable
(
wl
,
true
);
if
(
ret
<
0
)
break
;
/* go to extremely low power mode */
wl1271_ps_elp_sleep
(
wl
);
break
;
default:
break
;
...
...
@@ -228,6 +229,12 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_event_rssi_trigger
(
wl
,
mbox
);
}
if
((
vector
&
DUMMY_PACKET_EVENT_ID
)
&&
!
is_ap
)
{
wl1271_debug
(
DEBUG_EVENT
,
"DUMMY_PACKET_ID_EVENT_ID"
);
if
(
wl
->
vif
)
wl1271_tx_dummy_packet
(
wl
);
}
if
(
wl
->
vif
&&
beacon_loss
)
ieee80211_connection_loss
(
wl
->
vif
);
...
...
drivers/net/wireless/wl12xx/event.h
浏览文件 @
e55034e9
...
...
@@ -59,7 +59,10 @@ enum {
BSS_LOSE_EVENT_ID
=
BIT
(
18
),
REGAINED_BSS_EVENT_ID
=
BIT
(
19
),
ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID
=
BIT
(
20
),
STA_REMOVE_COMPLETE_EVENT_ID
=
BIT
(
21
),
/* AP */
/* STA: dummy paket for dynamic mem blocks */
DUMMY_PACKET_EVENT_ID
=
BIT
(
21
),
/* AP: STA remove complete */
STA_REMOVE_COMPLETE_EVENT_ID
=
BIT
(
21
),
SOFT_GEMINI_SENSE_EVENT_ID
=
BIT
(
22
),
SOFT_GEMINI_PREDICTION_EVENT_ID
=
BIT
(
23
),
SOFT_GEMINI_AVALANCHE_EVENT_ID
=
BIT
(
24
),
...
...
drivers/net/wireless/wl12xx/ini.h
浏览文件 @
e55034e9
...
...
@@ -41,6 +41,28 @@ struct wl1271_ini_general_params {
u8
srf3
[
WL1271_INI_MAX_SMART_REFLEX_PARAM
];
}
__packed
;
#define WL128X_INI_MAX_SETTINGS_PARAM 4
struct
wl128x_ini_general_params
{
u8
ref_clock
;
u8
settling_time
;
u8
clk_valid_on_wakeup
;
u8
tcxo_ref_clock
;
u8
tcxo_settling_time
;
u8
tcxo_valid_on_wakeup
;
u8
tcxo_ldo_voltage
;
u8
xtal_itrim_val
;
u8
platform_conf
;
u8
dual_mode_select
;
u8
tx_bip_fem_auto_detect
;
u8
tx_bip_fem_manufacturer
;
u8
general_settings
[
WL128X_INI_MAX_SETTINGS_PARAM
];
u8
sr_state
;
u8
srf1
[
WL1271_INI_MAX_SMART_REFLEX_PARAM
];
u8
srf2
[
WL1271_INI_MAX_SMART_REFLEX_PARAM
];
u8
srf3
[
WL1271_INI_MAX_SMART_REFLEX_PARAM
];
}
__packed
;
#define WL1271_INI_RSSI_PROCESS_COMPENS_SIZE 15
struct
wl1271_ini_band_params_2
{
...
...
@@ -49,9 +71,16 @@ struct wl1271_ini_band_params_2 {
u8
rx_rssi_process_compens
[
WL1271_INI_RSSI_PROCESS_COMPENS_SIZE
];
}
__packed
;
#define WL1271_INI_RATE_GROUP_COUNT 6
#define WL1271_INI_CHANNEL_COUNT_2 14
struct
wl128x_ini_band_params_2
{
u8
rx_trace_insertion_loss
;
u8
tx_trace_loss
[
WL1271_INI_CHANNEL_COUNT_2
];
u8
rx_rssi_process_compens
[
WL1271_INI_RSSI_PROCESS_COMPENS_SIZE
];
}
__packed
;
#define WL1271_INI_RATE_GROUP_COUNT 6
struct
wl1271_ini_fem_params_2
{
__le16
tx_bip_ref_pd_voltage
;
u8
tx_bip_ref_power
;
...
...
@@ -68,6 +97,28 @@ struct wl1271_ini_fem_params_2 {
u8
normal_to_degraded_high_thr
;
}
__packed
;
#define WL128X_INI_RATE_GROUP_COUNT 7
/* low and high temperatures */
#define WL128X_INI_PD_VS_TEMPERATURE_RANGES 2
struct
wl128x_ini_fem_params_2
{
__le16
tx_bip_ref_pd_voltage
;
u8
tx_bip_ref_power
;
u8
tx_bip_ref_offset
;
u8
tx_per_rate_pwr_limits_normal
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_rate_pwr_limits_degraded
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_rate_pwr_limits_extreme
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_chan_pwr_limits_11b
[
WL1271_INI_CHANNEL_COUNT_2
];
u8
tx_per_chan_pwr_limits_ofdm
[
WL1271_INI_CHANNEL_COUNT_2
];
u8
tx_pd_vs_rate_offsets
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_ibias
[
WL128X_INI_RATE_GROUP_COUNT
+
1
];
u8
tx_pd_vs_chan_offsets
[
WL1271_INI_CHANNEL_COUNT_2
];
u8
tx_pd_vs_temperature
[
WL128X_INI_PD_VS_TEMPERATURE_RANGES
];
u8
rx_fem_insertion_loss
;
u8
degraded_low_to_normal_thr
;
u8
normal_to_degraded_high_thr
;
}
__packed
;
#define WL1271_INI_CHANNEL_COUNT_5 35
#define WL1271_INI_SUB_BAND_COUNT_5 7
...
...
@@ -77,6 +128,12 @@ struct wl1271_ini_band_params_5 {
u8
rx_rssi_process_compens
[
WL1271_INI_RSSI_PROCESS_COMPENS_SIZE
];
}
__packed
;
struct
wl128x_ini_band_params_5
{
u8
rx_trace_insertion_loss
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
tx_trace_loss
[
WL1271_INI_CHANNEL_COUNT_5
];
u8
rx_rssi_process_compens
[
WL1271_INI_RSSI_PROCESS_COMPENS_SIZE
];
}
__packed
;
struct
wl1271_ini_fem_params_5
{
__le16
tx_bip_ref_pd_voltage
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
tx_bip_ref_power
[
WL1271_INI_SUB_BAND_COUNT_5
];
...
...
@@ -92,6 +149,23 @@ struct wl1271_ini_fem_params_5 {
u8
normal_to_degraded_high_thr
;
}
__packed
;
struct
wl128x_ini_fem_params_5
{
__le16
tx_bip_ref_pd_voltage
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
tx_bip_ref_power
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
tx_bip_ref_offset
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
tx_per_rate_pwr_limits_normal
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_rate_pwr_limits_degraded
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_rate_pwr_limits_extreme
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_per_chan_pwr_limits_ofdm
[
WL1271_INI_CHANNEL_COUNT_5
];
u8
tx_pd_vs_rate_offsets
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_ibias
[
WL128X_INI_RATE_GROUP_COUNT
];
u8
tx_pd_vs_chan_offsets
[
WL1271_INI_CHANNEL_COUNT_5
];
u8
tx_pd_vs_temperature
[
WL1271_INI_SUB_BAND_COUNT_5
*
WL128X_INI_PD_VS_TEMPERATURE_RANGES
];
u8
rx_fem_insertion_loss
[
WL1271_INI_SUB_BAND_COUNT_5
];
u8
degraded_low_to_normal_thr
;
u8
normal_to_degraded_high_thr
;
}
__packed
;
/* NVS data structure */
#define WL1271_INI_NVS_SECTION_SIZE 468
...
...
@@ -100,7 +174,7 @@ struct wl1271_ini_fem_params_5 {
#define WL1271_INI_LEGACY_NVS_FILE_SIZE 800
struct
wl1271_nvs_file
{
/* NVS section */
/* NVS section
- must be first!
*/
u8
nvs
[
WL1271_INI_NVS_SECTION_SIZE
];
/* INI section */
...
...
@@ -120,4 +194,24 @@ struct wl1271_nvs_file {
}
dyn_radio_params_5
[
WL1271_INI_FEM_MODULE_COUNT
];
}
__packed
;
struct
wl128x_nvs_file
{
/* NVS section - must be first! */
u8
nvs
[
WL1271_INI_NVS_SECTION_SIZE
];
/* INI section */
struct
wl128x_ini_general_params
general_params
;
u8
fem_vendor_and_options
;
struct
wl128x_ini_band_params_2
stat_radio_params_2
;
u8
padding2
;
struct
{
struct
wl128x_ini_fem_params_2
params
;
u8
padding
;
}
dyn_radio_params_2
[
WL1271_INI_FEM_MODULE_COUNT
];
struct
wl128x_ini_band_params_5
stat_radio_params_5
;
u8
padding3
;
struct
{
struct
wl128x_ini_fem_params_5
params
;
u8
padding
;
}
dyn_radio_params_5
[
WL1271_INI_FEM_MODULE_COUNT
];
}
__packed
;
#endif
drivers/net/wireless/wl12xx/init.c
浏览文件 @
e55034e9
...
...
@@ -31,6 +31,7 @@
#include "cmd.h"
#include "reg.h"
#include "tx.h"
#include "io.h"
int
wl1271_sta_init_templates_config
(
struct
wl1271
*
wl
)
{
...
...
@@ -321,9 +322,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
{
int
ret
;
ret
=
wl1271_cmd_ext_radio_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
if
(
wl
->
chip
.
id
!=
CHIP_ID_1283_PG20
)
{
ret
=
wl1271_cmd_ext_radio_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
}
/* PS config */
ret
=
wl1271_acx_config_ps
(
wl
);
...
...
@@ -504,6 +507,27 @@ static int wl1271_set_ba_policies(struct wl1271 *wl)
return
ret
;
}
int
wl1271_chip_specific_init
(
struct
wl1271
*
wl
)
{
int
ret
=
0
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
u32
host_cfg_bitmap
=
HOST_IF_CFG_RX_FIFO_ENABLE
;
if
(
wl
->
quirks
&
WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT
)
/* Enable SDIO padding */
host_cfg_bitmap
|=
HOST_IF_CFG_TX_PAD_TO_SDIO_BLK
;
/* Must be before wl1271_acx_init_mem_config() */
ret
=
wl1271_acx_host_if_cfg_bitmap
(
wl
,
host_cfg_bitmap
);
if
(
ret
<
0
)
goto
out
;
}
out:
return
ret
;
}
int
wl1271_hw_init
(
struct
wl1271
*
wl
)
{
struct
conf_tx_ac_category
*
conf_ac
;
...
...
@@ -511,11 +535,22 @@ int wl1271_hw_init(struct wl1271 *wl)
int
ret
,
i
;
bool
is_ap
=
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
);
ret
=
wl1271_cmd_general_parms
(
wl
);
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
ret
=
wl128x_cmd_general_parms
(
wl
);
else
ret
=
wl1271_cmd_general_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
ret
=
wl128x_cmd_radio_parms
(
wl
);
else
ret
=
wl1271_cmd_radio_parms
(
wl
);
if
(
ret
<
0
)
return
ret
;
ret
=
wl1271_cmd_radio_parms
(
wl
);
/* Chip-specific init */
ret
=
wl1271_chip_specific_init
(
wl
);
if
(
ret
<
0
)
return
ret
;
...
...
drivers/net/wireless/wl12xx/init.h
浏览文件 @
e55034e9
...
...
@@ -31,6 +31,7 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl);
int
wl1271_init_phy_config
(
struct
wl1271
*
wl
);
int
wl1271_init_pta
(
struct
wl1271
*
wl
);
int
wl1271_init_energy_detection
(
struct
wl1271
*
wl
);
int
wl1271_chip_specific_init
(
struct
wl1271
*
wl
);
int
wl1271_hw_init
(
struct
wl1271
*
wl
);
#endif
drivers/net/wireless/wl12xx/io.c
浏览文件 @
e55034e9
...
...
@@ -29,6 +29,7 @@
#include "wl12xx.h"
#include "wl12xx_80211.h"
#include "io.h"
#include "tx.h"
#define OCP_CMD_LOOP 32
...
...
@@ -43,6 +44,16 @@
#define OCP_STATUS_REQ_FAILED 0x20000
#define OCP_STATUS_RESP_ERROR 0x30000
bool
wl1271_set_block_size
(
struct
wl1271
*
wl
)
{
if
(
wl
->
if_ops
->
set_block_size
)
{
wl
->
if_ops
->
set_block_size
(
wl
,
WL12XX_BUS_BLOCK_SIZE
);
return
true
;
}
return
false
;
}
void
wl1271_disable_interrupts
(
struct
wl1271
*
wl
)
{
wl
->
if_ops
->
disable_irq
(
wl
);
...
...
drivers/net/wireless/wl12xx/io.h
浏览文件 @
e55034e9
...
...
@@ -169,5 +169,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl);
struct
ieee80211_hw
*
wl1271_alloc_hw
(
void
);
int
wl1271_free_hw
(
struct
wl1271
*
wl
);
irqreturn_t
wl1271_irq
(
int
irq
,
void
*
data
);
bool
wl1271_set_block_size
(
struct
wl1271
*
wl
);
int
wl1271_tx_dummy_packet
(
struct
wl1271
*
wl
);
void
wl1271_configure_filters
(
struct
wl1271
*
wl
,
unsigned
int
filters
);
#endif
drivers/net/wireless/wl12xx/main.c
浏览文件 @
e55034e9
此差异已折叠。
点击以展开。
drivers/net/wireless/wl12xx/ps.c
浏览文件 @
e55034e9
...
...
@@ -149,9 +149,6 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
case
STATION_ACTIVE_MODE
:
default:
wl1271_debug
(
DEBUG_PSM
,
"leaving psm"
);
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
return
ret
;
/* disable beacon early termination */
ret
=
wl1271_acx_bet_enable
(
wl
,
false
);
...
...
drivers/net/wireless/wl12xx/reg.h
浏览文件 @
e55034e9
...
...
@@ -207,6 +207,8 @@
#define CHIP_ID_1271_PG10 (0x4030101)
#define CHIP_ID_1271_PG20 (0x4030111)
#define CHIP_ID_1283_PG10 (0x05030101)
#define CHIP_ID_1283_PG20 (0x05030111)
#define ENABLE (REGISTERS_BASE + 0x5450)
...
...
@@ -452,24 +454,11 @@
#define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200
#define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400
/*
* NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile
* for platforms using active high interrupt level
*/
#ifdef USE_ACTIVE_HIGH
#define HI_CFG_DEF_VAL \
(HI_CFG_UART_ENABLE | \
HI_CFG_RST232_ENABLE | \
HI_CFG_CLOCK_REQ_SELECT | \
HI_CFG_HOST_INT_ENABLE)
#else
#define HI_CFG_DEF_VAL \
(HI_CFG_UART_ENABLE | \
HI_CFG_RST232_ENABLE | \
HI_CFG_CLOCK_REQ_SELECT | \
HI_CFG_HOST_INT_ENABLE)
#endif
#define REF_FREQ_19_2 0
#define REF_FREQ_26_0 1
...
...
drivers/net/wireless/wl12xx/rx.c
浏览文件 @
e55034e9
...
...
@@ -48,18 +48,14 @@ static void wl1271_rx_status(struct wl1271 *wl,
struct
ieee80211_rx_status
*
status
,
u8
beacon
)
{
enum
ieee80211_band
desc_band
;
memset
(
status
,
0
,
sizeof
(
struct
ieee80211_rx_status
));
status
->
band
=
wl
->
band
;
if
((
desc
->
flags
&
WL1271_RX_DESC_BAND_MASK
)
==
WL1271_RX_DESC_BAND_BG
)
desc_
band
=
IEEE80211_BAND_2GHZ
;
status
->
band
=
IEEE80211_BAND_2GHZ
;
else
desc_
band
=
IEEE80211_BAND_5GHZ
;
status
->
band
=
IEEE80211_BAND_5GHZ
;
status
->
rate_idx
=
wl1271_rate_to_idx
(
desc
->
rate
,
desc_
band
);
status
->
rate_idx
=
wl1271_rate_to_idx
(
desc
->
rate
,
status
->
band
);
#ifdef CONFIG_WL12XX_HT
/* 11n support */
...
...
@@ -76,7 +72,8 @@ static void wl1271_rx_status(struct wl1271 *wl,
*/
wl
->
noise
=
desc
->
rssi
-
(
desc
->
snr
>>
1
);
status
->
freq
=
ieee80211_channel_to_frequency
(
desc
->
channel
,
desc_band
);
status
->
freq
=
ieee80211_channel_to_frequency
(
desc
->
channel
,
status
->
band
);
if
(
desc
->
flags
&
WL1271_RX_DESC_ENCRYPT_MASK
)
{
status
->
flag
|=
RX_FLAG_IV_STRIPPED
|
RX_FLAG_MMIC_STRIPPED
;
...
...
@@ -163,18 +160,25 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
break
;
}
/*
* Choose the block we want to read
* For aggregated packets, only the first memory block should
* be retrieved. The FW takes care of the rest.
*/
mem_block
=
wl1271_rx_get_mem_block
(
status
,
drv_rx_counter
);
wl
->
rx_mem_pool_addr
.
addr
=
(
mem_block
<<
8
)
+
le32_to_cpu
(
wl_mem_map
->
packet_memory_pool_start
);
wl
->
rx_mem_pool_addr
.
addr_extra
=
wl
->
rx_mem_pool_addr
.
addr
+
4
;
wl1271_write
(
wl
,
WL1271_SLV_REG_DATA
,
&
wl
->
rx_mem_pool_addr
,
sizeof
(
wl
->
rx_mem_pool_addr
),
false
);
if
(
wl
->
chip
.
id
!=
CHIP_ID_1283_PG20
)
{
/*
* Choose the block we want to read
* For aggregated packets, only the first memory block
* should be retrieved. The FW takes care of the rest.
*/
mem_block
=
wl1271_rx_get_mem_block
(
status
,
drv_rx_counter
);
wl
->
rx_mem_pool_addr
.
addr
=
(
mem_block
<<
8
)
+
le32_to_cpu
(
wl_mem_map
->
packet_memory_pool_start
);
wl
->
rx_mem_pool_addr
.
addr_extra
=
wl
->
rx_mem_pool_addr
.
addr
+
4
;
wl1271_write
(
wl
,
WL1271_SLV_REG_DATA
,
&
wl
->
rx_mem_pool_addr
,
sizeof
(
wl
->
rx_mem_pool_addr
),
false
);
}
/* Read all available packets at once */
wl1271_read
(
wl
,
WL1271_SLV_MEM_DATA
,
wl
->
aggr_buf
,
...
...
drivers/net/wireless/wl12xx/scan.c
浏览文件 @
e55034e9
...
...
@@ -48,8 +48,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
goto
out
;
wl
->
scan
.
state
=
WL1271_SCAN_STATE_IDLE
;
kfree
(
wl
->
scan
.
scanned_ch
);
wl
->
scan
.
scanned_ch
=
NULL
;
memset
(
wl
->
scan
.
scanned_ch
,
0
,
sizeof
(
wl
->
scan
.
scanned_ch
));
wl
->
scan
.
req
=
NULL
;
ieee80211_scan_completed
(
wl
->
hw
,
false
);
...
...
@@ -87,7 +86,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
flags
=
req
->
channels
[
i
]
->
flags
;
if
(
!
wl
->
scan
.
scanned_ch
[
i
]
&&
if
(
!
test_bit
(
i
,
wl
->
scan
.
scanned_ch
)
&&
!
(
flags
&
IEEE80211_CHAN_DISABLED
)
&&
((
!!
(
flags
&
IEEE80211_CHAN_PASSIVE_SCAN
))
==
passive
)
&&
(
req
->
channels
[
i
]
->
band
==
band
))
{
...
...
@@ -124,7 +123,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
memset
(
&
channels
[
j
].
bssid_msb
,
0xff
,
2
);
/* Mark the channels we already used */
wl
->
scan
.
scanned_ch
[
i
]
=
true
;
set_bit
(
i
,
wl
->
scan
.
scanned_ch
)
;
j
++
;
}
...
...
@@ -291,6 +290,12 @@ void wl1271_scan_stm(struct wl1271 *wl)
int
wl1271_scan
(
struct
wl1271
*
wl
,
const
u8
*
ssid
,
size_t
ssid_len
,
struct
cfg80211_scan_request
*
req
)
{
/*
* cfg80211 should guarantee that we don't get more channels
* than what we have registered.
*/
BUG_ON
(
req
->
n_channels
>
WL1271_MAX_CHANNELS
);
if
(
wl
->
scan
.
state
!=
WL1271_SCAN_STATE_IDLE
)
return
-
EBUSY
;
...
...
@@ -304,10 +309,8 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
}
wl
->
scan
.
req
=
req
;
memset
(
wl
->
scan
.
scanned_ch
,
0
,
sizeof
(
wl
->
scan
.
scanned_ch
));
wl
->
scan
.
scanned_ch
=
kcalloc
(
req
->
n_channels
,
sizeof
(
*
wl
->
scan
.
scanned_ch
),
GFP_KERNEL
);
/* we assume failure so that timeout scenarios are handled correctly */
wl
->
scan
.
failed
=
true
;
ieee80211_queue_delayed_work
(
wl
->
hw
,
&
wl
->
scan_complete_work
,
...
...
drivers/net/wireless/wl12xx/sdio.c
浏览文件 @
e55034e9
...
...
@@ -51,6 +51,13 @@ static const struct sdio_device_id wl1271_devices[] = {
};
MODULE_DEVICE_TABLE
(
sdio
,
wl1271_devices
);
static
void
wl1271_sdio_set_block_size
(
struct
wl1271
*
wl
,
unsigned
int
blksz
)
{
sdio_claim_host
(
wl
->
if_priv
);
sdio_set_block_size
(
wl
->
if_priv
,
blksz
);
sdio_release_host
(
wl
->
if_priv
);
}
static
inline
struct
sdio_func
*
wl_to_func
(
struct
wl1271
*
wl
)
{
return
wl
->
if_priv
;
...
...
@@ -203,7 +210,8 @@ static struct wl1271_if_operations sdio_ops = {
.
power
=
wl1271_sdio_set_power
,
.
dev
=
wl1271_sdio_wl_to_dev
,
.
enable_irq
=
wl1271_sdio_enable_interrupts
,
.
disable_irq
=
wl1271_sdio_disable_interrupts
.
disable_irq
=
wl1271_sdio_disable_interrupts
,
.
set_block_size
=
wl1271_sdio_set_block_size
,
};
static
int
__devinit
wl1271_probe
(
struct
sdio_func
*
func
,
...
...
@@ -212,6 +220,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
struct
ieee80211_hw
*
hw
;
const
struct
wl12xx_platform_data
*
wlan_data
;
struct
wl1271
*
wl
;
unsigned
long
irqflags
;
int
ret
;
/* We are only able to handle the wlan function */
...
...
@@ -230,6 +239,9 @@ static int __devinit wl1271_probe(struct sdio_func *func,
/* Grab access to FN0 for ELP reg. */
func
->
card
->
quirks
|=
MMC_QUIRK_LENIENT_FN0
;
/* Use block mode for transferring over one block size of data */
func
->
card
->
quirks
|=
MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
;
wlan_data
=
wl12xx_get_platform_data
();
if
(
IS_ERR
(
wlan_data
))
{
ret
=
PTR_ERR
(
wlan_data
);
...
...
@@ -239,9 +251,16 @@ static int __devinit wl1271_probe(struct sdio_func *func,
wl
->
irq
=
wlan_data
->
irq
;
wl
->
ref_clock
=
wlan_data
->
board_ref_clock
;
wl
->
tcxo_clock
=
wlan_data
->
board_tcxo_clock
;
wl
->
platform_quirks
=
wlan_data
->
platform_quirks
;
if
(
wl
->
platform_quirks
&
WL12XX_PLATFORM_QUIRK_EDGE_IRQ
)
irqflags
=
IRQF_TRIGGER_RISING
;
else
irqflags
=
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
;
ret
=
request_threaded_irq
(
wl
->
irq
,
wl1271_hardirq
,
wl1271_irq
,
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
,
irqflags
,
DRIVER_NAME
,
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"request_irq() failed: %d"
,
ret
);
...
...
@@ -343,4 +362,6 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR
(
"Luciano Coelho <coelho@ti.com>"
);
MODULE_AUTHOR
(
"Juuso Oikarinen <juuso.oikarinen@nokia.com>"
);
MODULE_FIRMWARE
(
WL1271_FW_NAME
);
MODULE_FIRMWARE
(
WL1271_AP_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_FW_NAME
);
MODULE_FIRMWARE
(
WL127X_AP_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_AP_FW_NAME
);
drivers/net/wireless/wl12xx/sdio_test.c
浏览文件 @
e55034e9
...
...
@@ -189,7 +189,12 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
const
struct
firmware
*
fw
;
int
ret
;
ret
=
request_firmware
(
&
fw
,
WL1271_FW_NAME
,
wl1271_wl_to_dev
(
wl
));
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
ret
=
request_firmware
(
&
fw
,
WL128X_FW_NAME
,
wl1271_wl_to_dev
(
wl
));
else
ret
=
request_firmware
(
&
fw
,
WL1271_FW_NAME
,
wl1271_wl_to_dev
(
wl
));
if
(
ret
<
0
)
{
wl1271_error
(
"could not get firmware: %d"
,
ret
);
...
...
@@ -227,14 +232,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
const
struct
firmware
*
fw
;
int
ret
;
ret
=
request_firmware
(
&
fw
,
WL12
71
_NVS_NAME
,
wl1271_wl_to_dev
(
wl
));
ret
=
request_firmware
(
&
fw
,
WL12
XX
_NVS_NAME
,
wl1271_wl_to_dev
(
wl
));
if
(
ret
<
0
)
{
wl1271_error
(
"could not get nvs file: %d"
,
ret
);
return
ret
;
}
wl
->
nvs
=
kmemdup
(
fw
->
data
,
sizeof
(
struct
wl1271_nvs_file
)
,
GFP_KERNEL
);
wl
->
nvs
=
kmemdup
(
fw
->
data
,
fw
->
size
,
GFP_KERNEL
);
if
(
!
wl
->
nvs
)
{
wl1271_error
(
"could not allocate memory for the nvs file"
);
...
...
@@ -288,6 +293,11 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
wl1271_notice
(
"chip id 0x%x (1271 PG20)"
,
wl
->
chip
.
id
);
break
;
case
CHIP_ID_1283_PG20
:
wl1271_notice
(
"chip id 0x%x (1283 PG20)"
,
wl
->
chip
.
id
);
break
;
case
CHIP_ID_1283_PG10
:
default:
wl1271_warning
(
"unsupported chip id: 0x%x"
,
wl
->
chip
.
id
);
return
-
ENODEV
;
...
...
@@ -407,6 +417,9 @@ static int __devinit wl1271_probe(struct sdio_func *func,
/* Grab access to FN0 for ELP reg. */
func
->
card
->
quirks
|=
MMC_QUIRK_LENIENT_FN0
;
/* Use block mode for transferring over one block size of data */
func
->
card
->
quirks
|=
MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
;
wlan_data
=
wl12xx_get_platform_data
();
if
(
IS_ERR
(
wlan_data
))
{
ret
=
PTR_ERR
(
wlan_data
);
...
...
@@ -416,6 +429,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
wl
->
irq
=
wlan_data
->
irq
;
wl
->
ref_clock
=
wlan_data
->
board_ref_clock
;
wl
->
tcxo_clock
=
wlan_data
->
board_tcxo_clock
;
sdio_set_drvdata
(
func
,
wl_test
);
...
...
drivers/net/wireless/wl12xx/spi.c
浏览文件 @
e55034e9
...
...
@@ -355,7 +355,8 @@ static struct wl1271_if_operations spi_ops = {
.
power
=
wl1271_spi_set_power
,
.
dev
=
wl1271_spi_wl_to_dev
,
.
enable_irq
=
wl1271_spi_enable_interrupts
,
.
disable_irq
=
wl1271_spi_disable_interrupts
.
disable_irq
=
wl1271_spi_disable_interrupts
,
.
set_block_size
=
NULL
,
};
static
int
__devinit
wl1271_probe
(
struct
spi_device
*
spi
)
...
...
@@ -363,6 +364,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
struct
wl12xx_platform_data
*
pdata
;
struct
ieee80211_hw
*
hw
;
struct
wl1271
*
wl
;
unsigned
long
irqflags
;
int
ret
;
pdata
=
spi
->
dev
.
platform_data
;
...
...
@@ -400,6 +402,13 @@ static int __devinit wl1271_probe(struct spi_device *spi)
}
wl
->
ref_clock
=
pdata
->
board_ref_clock
;
wl
->
tcxo_clock
=
pdata
->
board_tcxo_clock
;
wl
->
platform_quirks
=
pdata
->
platform_quirks
;
if
(
wl
->
platform_quirks
&
WL12XX_PLATFORM_QUIRK_EDGE_IRQ
)
irqflags
=
IRQF_TRIGGER_RISING
;
else
irqflags
=
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
;
wl
->
irq
=
spi
->
irq
;
if
(
wl
->
irq
<
0
)
{
...
...
@@ -409,7 +418,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
}
ret
=
request_threaded_irq
(
wl
->
irq
,
wl1271_hardirq
,
wl1271_irq
,
IRQF_TRIGGER_HIGH
|
IRQF_ONESHOT
,
irqflags
,
DRIVER_NAME
,
wl
);
if
(
ret
<
0
)
{
wl1271_error
(
"request_irq() failed: %d"
,
ret
);
...
...
@@ -490,5 +499,7 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR
(
"Luciano Coelho <coelho@ti.com>"
);
MODULE_AUTHOR
(
"Juuso Oikarinen <juuso.oikarinen@nokia.com>"
);
MODULE_FIRMWARE
(
WL1271_FW_NAME
);
MODULE_FIRMWARE
(
WL1271_AP_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_FW_NAME
);
MODULE_FIRMWARE
(
WL127X_AP_FW_NAME
);
MODULE_FIRMWARE
(
WL128X_AP_FW_NAME
);
MODULE_ALIAS
(
"spi:wl1271"
);
drivers/net/wireless/wl12xx/testmode.c
浏览文件 @
e55034e9
...
...
@@ -27,6 +27,7 @@
#include "wl12xx.h"
#include "acx.h"
#include "reg.h"
#define WL1271_TM_MAX_DATA_LENGTH 1024
...
...
@@ -204,7 +205,10 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
kfree
(
wl
->
nvs
);
if
(
len
!=
sizeof
(
struct
wl1271_nvs_file
))
if
((
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
&&
(
len
!=
sizeof
(
struct
wl128x_nvs_file
)))
return
-
EINVAL
;
else
if
(
len
!=
sizeof
(
struct
wl1271_nvs_file
))
return
-
EINVAL
;
wl
->
nvs
=
kzalloc
(
len
,
GFP_KERNEL
);
...
...
drivers/net/wireless/wl12xx/tx.c
浏览文件 @
e55034e9
...
...
@@ -70,6 +70,28 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id)
}
}
static
int
wl1271_tx_update_filters
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
{
struct
ieee80211_hdr
*
hdr
;
hdr
=
(
struct
ieee80211_hdr
*
)(
skb
->
data
+
sizeof
(
struct
wl1271_tx_hw_descr
));
/*
* stop bssid-based filtering before transmitting authentication
* requests. this way the hw will never drop authentication
* responses coming from BSSIDs it isn't familiar with (e.g. on
* roaming)
*/
if
(
!
ieee80211_is_auth
(
hdr
->
frame_control
))
return
0
;
wl1271_configure_filters
(
wl
,
FIF_OTHER_BSS
);
return
wl1271_acx_rx_config
(
wl
,
wl
->
rx_config
,
wl
->
rx_filter
);
}
static
void
wl1271_tx_ap_update_inconnection_sta
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
{
...
...
@@ -127,13 +149,29 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb)
}
}
static
unsigned
int
wl12xx_calc_packet_alignment
(
struct
wl1271
*
wl
,
unsigned
int
packet_length
)
{
if
(
wl
->
quirks
&
WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT
)
return
ALIGN
(
packet_length
,
WL12XX_BUS_BLOCK_SIZE
);
else
return
ALIGN
(
packet_length
,
WL1271_TX_ALIGN_TO
);
}
static
int
wl1271_tx_allocate
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
extra
,
u32
buf_offset
,
u8
hlid
)
{
struct
wl1271_tx_hw_descr
*
desc
;
u32
total_len
=
skb
->
len
+
sizeof
(
struct
wl1271_tx_hw_descr
)
+
extra
;
u32
len
;
u32
total_blocks
;
int
id
,
ret
=
-
EBUSY
;
u32
spare_blocks
;
if
(
unlikely
(
wl
->
quirks
&
WL12XX_QUIRK_USE_2_SPARE_BLOCKS
))
spare_blocks
=
2
;
else
spare_blocks
=
1
;
if
(
buf_offset
+
total_len
>
WL1271_AGGR_BUFFER_SIZE
)
return
-
EAGAIN
;
...
...
@@ -145,17 +183,27 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
/* approximate the number of blocks required for this packet
in the firmware */
total_blocks
=
total_len
+
TX_HW_BLOCK_SIZE
-
1
;
total_blocks
=
total_blocks
/
TX_HW_BLOCK_SIZE
+
TX_HW_BLOCK_SPARE
;
len
=
wl12xx_calc_packet_alignment
(
wl
,
total_len
);
total_blocks
=
(
len
+
TX_HW_BLOCK_SIZE
-
1
)
/
TX_HW_BLOCK_SIZE
+
spare_blocks
;
if
(
total_blocks
<=
wl
->
tx_blocks_available
)
{
desc
=
(
struct
wl1271_tx_hw_descr
*
)
skb_push
(
skb
,
total_len
-
skb
->
len
);
desc
->
extra_mem_blocks
=
TX_HW_BLOCK_SPARE
;
desc
->
total_mem_blocks
=
total_blocks
;
/* HW descriptor fields change between wl127x and wl128x */
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
desc
->
wl128x_mem
.
total_mem_blocks
=
total_blocks
;
}
else
{
desc
->
wl127x_mem
.
extra_blocks
=
spare_blocks
;
desc
->
wl127x_mem
.
total_mem_blocks
=
total_blocks
;
}
desc
->
id
=
id
;
wl
->
tx_blocks_available
-=
total_blocks
;
wl
->
tx_allocated_blocks
+=
total_blocks
;
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
wl
->
links
[
hlid
].
allocated_blks
+=
total_blocks
;
...
...
@@ -172,13 +220,18 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
return
ret
;
}
static
bool
wl12xx_is_dummy_packet
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
{
return
wl
->
dummy_packet
==
skb
;
}
static
void
wl1271_tx_fill_hdr
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
,
u32
extra
,
struct
ieee80211_tx_info
*
control
,
u8
hlid
)
{
struct
timespec
ts
;
struct
wl1271_tx_hw_descr
*
desc
;
int
pad
,
ac
,
rate_idx
;
int
aligned_len
,
ac
,
rate_idx
;
s64
hosttime
;
u16
tx_attr
;
...
...
@@ -202,12 +255,25 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
else
desc
->
life_time
=
cpu_to_le16
(
TX_HW_AP_MODE_PKT_LIFETIME_TU
);
/* configure the tx attributes */
tx_attr
=
wl
->
session_counter
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
;
/* queue (we use same identifiers for tid's and ac's */
/* queue */
ac
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
desc
->
tid
=
ac
;
desc
->
tid
=
skb
->
priority
;
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
/*
* FW expects the dummy packet to have an invalid session id -
* any session id that is different than the one set in the join
*/
tx_attr
=
((
~
wl
->
session_counter
)
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
)
&
TX_HW_ATTR_SESSION_COUNTER
;
tx_attr
|=
TX_HW_ATTR_TX_DUMMY_REQ
;
}
else
{
/* configure the tx attributes */
tx_attr
=
wl
->
session_counter
<<
TX_HW_ATTR_OFST_SESSION_COUNTER
;
}
if
(
wl
->
bss_type
!=
BSS_TYPE_AP_BSS
)
{
desc
->
aid
=
hlid
;
...
...
@@ -237,20 +303,37 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
tx_attr
|=
rate_idx
<<
TX_HW_ATTR_OFST_RATE_POLICY
;
desc
->
reserved
=
0
;
/* align the length (and store in terms of words) */
pad
=
ALIGN
(
skb
->
len
,
WL1271_TX_ALIGN_TO
);
desc
->
length
=
cpu_to_le16
(
pad
>>
2
);
aligned_len
=
wl12xx_calc_packet_alignment
(
wl
,
skb
->
len
);
/* calculate number of padding bytes */
pad
=
pad
-
skb
->
len
;
tx_attr
|=
pad
<<
TX_HW_ATTR_OFST_LAST_WORD_PAD
;
if
(
wl
->
chip
.
id
==
CHIP_ID_1283_PG20
)
{
desc
->
wl128x_mem
.
extra_bytes
=
aligned_len
-
skb
->
len
;
desc
->
length
=
cpu_to_le16
(
aligned_len
>>
2
)
;
desc
->
tx_attr
=
cpu_to_le16
(
tx_attr
);
wl1271_debug
(
DEBUG_TX
,
"tx_fill_hdr: hlid: %d "
"tx_attr: 0x%x len: %d life: %d mem: %d"
,
desc
->
hlid
,
tx_attr
,
le16_to_cpu
(
desc
->
length
),
le16_to_cpu
(
desc
->
life_time
),
desc
->
wl128x_mem
.
total_mem_blocks
);
}
else
{
int
pad
;
/* Store the aligned length in terms of words */
desc
->
length
=
cpu_to_le16
(
aligned_len
>>
2
);
/* calculate number of padding bytes */
pad
=
aligned_len
-
skb
->
len
;
tx_attr
|=
pad
<<
TX_HW_ATTR_OFST_LAST_WORD_PAD
;
wl1271_debug
(
DEBUG_TX
,
"tx_fill_hdr: pad: %d hlid: %d "
"tx_attr: 0x%x len: %d life: %d mem: %d"
,
pad
,
desc
->
hlid
,
le16_to_cpu
(
desc
->
tx_attr
),
le16_to_cpu
(
desc
->
length
),
le16_to_cpu
(
desc
->
life_time
),
desc
->
total_mem_blocks
);
wl1271_debug
(
DEBUG_TX
,
"tx_fill_hdr: pad: %d hlid: %d "
"tx_attr: 0x%x len: %d life: %d mem: %d"
,
pad
,
desc
->
hlid
,
tx_attr
,
le16_to_cpu
(
desc
->
length
),
le16_to_cpu
(
desc
->
life_time
),
desc
->
wl127x_mem
.
total_mem_blocks
);
}
desc
->
tx_attr
=
cpu_to_le16
(
tx_attr
);
}
/* caller must hold wl->mutex */
...
...
@@ -300,19 +383,29 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
wl1271_tx_ap_update_inconnection_sta
(
wl
,
skb
);
wl1271_tx_regulate_link
(
wl
,
hlid
);
}
else
{
wl1271_tx_update_filters
(
wl
,
skb
);
}
wl1271_tx_fill_hdr
(
wl
,
skb
,
extra
,
info
,
hlid
);
/*
* The length of each packet is stored in terms of words. Thus, we must
* pad the skb data to make sure its length is aligned.
* The number of padding bytes is computed and set in wl1271_tx_fill_hdr
* The length of each packet is stored in terms of
* words. Thus, we must pad the skb data to make sure its
* length is aligned. The number of padding bytes is computed
* and set in wl1271_tx_fill_hdr.
* In special cases, we want to align to a specific block size
* (eg. for wl128x with SDIO we align to 256).
*/
total_len
=
ALIGN
(
skb
->
len
,
WL1271_TX_ALIGN_TO
);
total_len
=
wl12xx_calc_packet_alignment
(
wl
,
skb
->
len
);
memcpy
(
wl
->
aggr_buf
+
buf_offset
,
skb
->
data
,
skb
->
len
);
memset
(
wl
->
aggr_buf
+
buf_offset
+
skb
->
len
,
0
,
total_len
-
skb
->
len
);
/* Revert side effects in the dummy packet skb, so it can be reused */
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
skb_pull
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
return
total_len
;
}
...
...
@@ -425,10 +518,23 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
static
struct
sk_buff
*
wl1271_skb_dequeue
(
struct
wl1271
*
wl
)
{
unsigned
long
flags
;
struct
sk_buff
*
skb
=
NULL
;
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
return
wl1271_ap_skb_dequeue
(
wl
);
skb
=
wl1271_ap_skb_dequeue
(
wl
);
else
skb
=
wl1271_sta_skb_dequeue
(
wl
);
if
(
!
skb
&&
test_and_clear_bit
(
WL1271_FLAG_DUMMY_PACKET_PENDING
,
&
wl
->
flags
))
{
skb
=
wl
->
dummy_packet
;
spin_lock_irqsave
(
&
wl
->
wl_lock
,
flags
);
wl
->
tx_queue_count
--
;
spin_unlock_irqrestore
(
&
wl
->
wl_lock
,
flags
);
}
return
wl1271_sta_skb_dequeue
(
wl
)
;
return
skb
;
}
static
void
wl1271_skb_queue_head
(
struct
wl1271
*
wl
,
struct
sk_buff
*
skb
)
...
...
@@ -436,7 +542,9 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
unsigned
long
flags
;
int
q
=
wl1271_tx_get_queue
(
skb_get_queue_mapping
(
skb
));
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
set_bit
(
WL1271_FLAG_DUMMY_PACKET_PENDING
,
&
wl
->
flags
);
}
else
if
(
wl
->
bss_type
==
BSS_TYPE_AP_BSS
)
{
u8
hlid
=
wl1271_tx_get_hlid
(
skb
);
skb_queue_head
(
&
wl
->
links
[
hlid
].
tx_queue
[
q
],
skb
);
...
...
@@ -454,22 +562,14 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
void
wl1271_tx_work_locked
(
struct
wl1271
*
wl
)
{
struct
sk_buff
*
skb
;
bool
woken_up
=
false
;
u32
buf_offset
=
0
;
bool
sent_packets
=
false
;
int
ret
;
if
(
unlikely
(
wl
->
state
==
WL1271_STATE_OFF
))
goto
out
;
return
;
while
((
skb
=
wl1271_skb_dequeue
(
wl
)))
{
if
(
!
woken_up
)
{
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out_ack
;
woken_up
=
true
;
}
ret
=
wl1271_prepare_tx_frame
(
wl
,
skb
,
buf_offset
);
if
(
ret
==
-
EAGAIN
)
{
/*
...
...
@@ -516,18 +616,22 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
wl1271_handle_tx_low_watermark
(
wl
);
}
out:
if
(
woken_up
)
wl1271_ps_elp_sleep
(
wl
);
}
void
wl1271_tx_work
(
struct
work_struct
*
work
)
{
struct
wl1271
*
wl
=
container_of
(
work
,
struct
wl1271
,
tx_work
);
int
ret
;
mutex_lock
(
&
wl
->
mutex
);
ret
=
wl1271_ps_elp_wakeup
(
wl
);
if
(
ret
<
0
)
goto
out
;
wl1271_tx_work_locked
(
wl
);
wl1271_ps_elp_wakeup
(
wl
);
out:
mutex_unlock
(
&
wl
->
mutex
);
}
...
...
@@ -549,6 +653,11 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
skb
=
wl
->
tx_frames
[
id
];
info
=
IEEE80211_SKB_CB
(
skb
);
if
(
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
wl1271_free_tx_id
(
wl
,
id
);
return
;
}
/* update the TX status info */
if
(
result
->
status
==
TX_SUCCESS
)
{
if
(
!
(
info
->
flags
&
IEEE80211_TX_CTL_NO_ACK
))
...
...
@@ -678,10 +787,13 @@ void wl1271_tx_reset(struct wl1271 *wl)
while
((
skb
=
skb_dequeue
(
&
wl
->
tx_queue
[
i
])))
{
wl1271_debug
(
DEBUG_TX
,
"freeing skb 0x%p"
,
skb
);
info
=
IEEE80211_SKB_CB
(
skb
);
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
if
(
!
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
info
=
IEEE80211_SKB_CB
(
skb
);
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
}
}
}
}
...
...
@@ -702,21 +814,27 @@ void wl1271_tx_reset(struct wl1271 *wl)
wl1271_free_tx_id
(
wl
,
i
);
wl1271_debug
(
DEBUG_TX
,
"freeing skb 0x%p"
,
skb
);
/* Remove private headers before passing the skb to mac80211 */
info
=
IEEE80211_SKB_CB
(
skb
);
skb_pull
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
if
(
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
{
int
hdrlen
=
ieee80211_get_hdrlen_from_skb
(
skb
);
memmove
(
skb
->
data
+
WL1271_TKIP_IV_SPACE
,
skb
->
data
,
hdrlen
);
skb_pull
(
skb
,
WL1271_TKIP_IV_SPACE
);
}
if
(
!
wl12xx_is_dummy_packet
(
wl
,
skb
))
{
/*
* Remove private headers before passing the skb to
* mac80211
*/
info
=
IEEE80211_SKB_CB
(
skb
);
skb_pull
(
skb
,
sizeof
(
struct
wl1271_tx_hw_descr
));
if
(
info
->
control
.
hw_key
&&
info
->
control
.
hw_key
->
cipher
==
WLAN_CIPHER_SUITE_TKIP
)
{
int
hdrlen
=
ieee80211_get_hdrlen_from_skb
(
skb
);
memmove
(
skb
->
data
+
WL1271_TKIP_IV_SPACE
,
skb
->
data
,
hdrlen
);
skb_pull
(
skb
,
WL1271_TKIP_IV_SPACE
);
}
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
info
->
status
.
rates
[
0
].
idx
=
-
1
;
info
->
status
.
rates
[
0
].
count
=
0
;
ieee80211_tx_status
(
wl
->
hw
,
skb
);
ieee80211_tx_status
(
wl
->
hw
,
skb
);
}
}
}
...
...
drivers/net/wireless/wl12xx/tx.h
浏览文件 @
e55034e9
...
...
@@ -25,7 +25,6 @@
#ifndef __TX_H__
#define __TX_H__
#define TX_HW_BLOCK_SPARE 2
#define TX_HW_BLOCK_SIZE 252
#define TX_HW_MGMT_PKT_LIFETIME_TU 2000
...
...
@@ -41,6 +40,7 @@
BIT(8) | BIT(9))
#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11))
#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12)
#define TX_HW_ATTR_TX_DUMMY_REQ BIT(13)
#define TX_HW_ATTR_OFST_SAVE_RETRIES 0
#define TX_HW_ATTR_OFST_HEADER_PAD 1
...
...
@@ -55,20 +55,60 @@
#define WL1271_TX_ALIGN_TO 4
#define WL1271_TKIP_IV_SPACE 4
/* Used for management frames and dummy packets */
#define WL1271_TID_MGMT 7
struct
wl127x_tx_mem
{
/*
* Number of extra memory blocks to allocate for this packet
* in addition to the number of blocks derived from the packet
* length.
*/
u8
extra_blocks
;
/*
* Total number of memory blocks allocated by the host for
* this packet. Must be equal or greater than the actual
* blocks number allocated by HW.
*/
u8
total_mem_blocks
;
}
__packed
;
struct
wl128x_tx_mem
{
/*
* Total number of memory blocks allocated by the host for
* this packet.
*/
u8
total_mem_blocks
;
/*
* Number of extra bytes, at the end of the frame. the host
* uses this padding to complete each frame to integer number
* of SDIO blocks.
*/
u8
extra_bytes
;
}
__packed
;
/*
* On wl128x based devices, when TX packets are aggregated, each packet
* size must be aligned to the SDIO block size. The maximum block size
* is bounded by the type of the padded bytes field that is sent to the
* FW. Currently the type is u8, so the maximum block size is 256 bytes.
*/
#define WL12XX_BUS_BLOCK_SIZE min(512u, \
(1u << (8 * sizeof(((struct wl128x_tx_mem *) 0)->extra_bytes))))
struct
wl1271_tx_hw_descr
{
/* Length of packet in words, including descriptor+header+data */
__le16
length
;
/* Number of extra memory blocks to allocate for this packet in
addition to the number of blocks derived from the packet length */
u8
extra_mem_blocks
;
/* Total number of memory blocks allocated by the host for this packet.
Must be equal or greater than the actual blocks number allocated by
HW!! */
u8
total_mem_blocks
;
union
{
struct
wl127x_tx_mem
wl127x_mem
;
struct
wl128x_tx_mem
wl128x_mem
;
}
__packed
;
/* Device time (in us) when the packet arrived to the driver */
__le32
start_time
;
/* Max delay in TUs until transmission. The last device time the
packet can be transmitted is: startTime+(1024*LifeTime) */
/*
* Max delay in TUs until transmission. The last device time the
* packet can be transmitted is: start_time + (1024 * life_time)
*/
__le16
life_time
;
/* Bitwise fields - see TX_ATTR... definitions above. */
__le16
tx_attr
;
...
...
drivers/net/wireless/wl12xx/wl12xx.h
浏览文件 @
e55034e9
...
...
@@ -131,9 +131,16 @@ extern u32 wl12xx_debug_level;
#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin"
#define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin"
#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin"
#define WL1271_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
/*
* wl127x and wl128x are using the same NVS file name. However, the
* ini parameters between them are different. The driver validates
* the correct NVS size in wl1271_boot_upload_nvs().
*/
#define WL12XX_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
...
...
@@ -200,13 +207,29 @@ struct wl1271_partition_set {
struct
wl1271
;
#define WL12XX_NUM_FW_VER 5
enum
{
FW_VER_CHIP
,
FW_VER_IF_TYPE
,
FW_VER_MAJOR
,
FW_VER_SUBTYPE
,
FW_VER_MINOR
,
NUM_FW_VER
};
#define FW_VER_CHIP_WL127X 6
#define FW_VER_CHIP_WL128X 7
#define FW_VER_IF_TYPE_STA 1
#define FW_VER_IF_TYPE_AP 2
#define FW_VER_MINOR_1_SPARE_STA_MIN 58
#define FW_VER_MINOR_1_SPARE_AP_MIN 47
/* FIXME: I'm not sure about this structure name */
struct
wl1271_chip
{
u32
id
;
char
fw_ver_str
[
ETHTOOL_BUSINFO_LEN
];
unsigned
int
fw_ver
[
WL12XX_
NUM_FW_VER
];
unsigned
int
fw_ver
[
NUM_FW_VER
];
};
struct
wl1271_stats
{
...
...
@@ -261,6 +284,8 @@ struct wl1271_fw_sta_status {
u8
tx_total
;
u8
reserved1
;
__le16
reserved2
;
/* Total structure size is 68 bytes */
u32
padding
;
}
__packed
;
struct
wl1271_fw_full_status
{
...
...
@@ -277,9 +302,10 @@ struct wl1271_rx_mem_pool_addr {
u32
addr_extra
;
};
#define WL1271_MAX_CHANNELS 64
struct
wl1271_scan
{
struct
cfg80211_scan_request
*
req
;
bool
*
scanned_ch
;
unsigned
long
scanned_ch
[
BITS_TO_LONGS
(
WL1271_MAX_CHANNELS
)]
;
bool
failed
;
u8
state
;
u8
ssid
[
IW_ESSID_MAX_SIZE
+
1
];
...
...
@@ -297,6 +323,7 @@ struct wl1271_if_operations {
struct
device
*
(
*
dev
)(
struct
wl1271
*
wl
);
void
(
*
enable_irq
)(
struct
wl1271
*
wl
);
void
(
*
disable_irq
)(
struct
wl1271
*
wl
);
void
(
*
set_block_size
)
(
struct
wl1271
*
wl
,
unsigned
int
blksz
);
};
#define MAX_NUM_KEYS 14
...
...
@@ -327,7 +354,9 @@ enum wl12xx_flags {
WL1271_FLAG_PSPOLL_FAILURE
,
WL1271_FLAG_STA_STATE_SENT
,
WL1271_FLAG_FW_TX_BUSY
,
WL1271_FLAG_AP_STARTED
WL1271_FLAG_AP_STARTED
,
WL1271_FLAG_IF_INITIALIZED
,
WL1271_FLAG_DUMMY_PACKET_PENDING
,
};
struct
wl1271_link
{
...
...
@@ -371,7 +400,7 @@ struct wl1271 {
u8
*
fw
;
size_t
fw_len
;
u8
fw_bss_type
;
struct
wl1271_nvs_file
*
nvs
;
void
*
nvs
;
size_t
nvs_len
;
s8
hw_pg_ver
;
...
...
@@ -389,6 +418,7 @@ struct wl1271 {
/* Accounting for allocated / available TX blocks on HW */
u32
tx_blocks_freed
[
NUM_TX_QUEUES
];
u32
tx_blocks_available
;
u32
tx_allocated_blocks
;
u32
tx_results_count
;
/* Transmitted TX packets counter for chipset interface */
...
...
@@ -430,6 +460,9 @@ struct wl1271 {
/* Intermediate buffer, used for packet aggregation */
u8
*
aggr_buf
;
/* Reusable dummy packet template */
struct
sk_buff
*
dummy_packet
;
/* Network stack work */
struct
work_struct
netstack_work
;
...
...
@@ -527,6 +560,8 @@ struct wl1271 {
bool
ba_support
;
u8
ba_rx_bitmap
;
int
tcxo_clock
;
/*
* AP-mode - links indexed by HLID. The global and broadcast links
* are always active.
...
...
@@ -544,6 +579,9 @@ struct wl1271 {
/* Quirks of specific hardware revisions */
unsigned
int
quirks
;
/* Platform limitations */
unsigned
int
platform_quirks
;
};
struct
wl1271_station
{
...
...
@@ -576,6 +614,15 @@ int wl1271_plt_stop(struct wl1271 *wl);
/* Quirks */
/* Each RX/TX transaction requires an end-of-transaction transfer */
#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0)
#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0)
/*
* Older firmwares use 2 spare TX blocks
* (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47)
*/
#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1)
/* WL128X requires aggregated packets to be aligned to the SDIO block size */
#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2)
#endif
include/linux/wl12xx.h
浏览文件 @
e55034e9
...
...
@@ -24,12 +24,26 @@
#ifndef _LINUX_WL12XX_H
#define _LINUX_WL12XX_H
/*
The board r
eference clock values */
/*
R
eference clock values */
enum
{
WL12XX_REFCLOCK_19
=
0
,
/* 19.2 MHz */
WL12XX_REFCLOCK_26
=
1
,
/* 26 MHz */
WL12XX_REFCLOCK_38
=
2
,
/* 38.4 MHz */
WL12XX_REFCLOCK_54
=
3
,
/* 54 MHz */
WL12XX_REFCLOCK_19
=
0
,
/* 19.2 MHz */
WL12XX_REFCLOCK_26
=
1
,
/* 26 MHz */
WL12XX_REFCLOCK_38
=
2
,
/* 38.4 MHz */
WL12XX_REFCLOCK_52
=
3
,
/* 52 MHz */
WL12XX_REFCLOCK_38_XTAL
=
4
,
/* 38.4 MHz, XTAL */
WL12XX_REFCLOCK_26_XTAL
=
5
,
/* 26 MHz, XTAL */
};
/* TCXO clock values */
enum
{
WL12XX_TCXOCLOCK_19_2
=
0
,
/* 19.2MHz */
WL12XX_TCXOCLOCK_26
=
1
,
/* 26 MHz */
WL12XX_TCXOCLOCK_38_4
=
2
,
/* 38.4MHz */
WL12XX_TCXOCLOCK_52
=
3
,
/* 52 MHz */
WL12XX_TCXOCLOCK_16_368
=
4
,
/* 16.368 MHz */
WL12XX_TCXOCLOCK_32_736
=
5
,
/* 32.736 MHz */
WL12XX_TCXOCLOCK_16_8
=
6
,
/* 16.8 MHz */
WL12XX_TCXOCLOCK_33_6
=
7
,
/* 33.6 MHz */
};
struct
wl12xx_platform_data
{
...
...
@@ -38,8 +52,13 @@ struct wl12xx_platform_data {
int
irq
;
bool
use_eeprom
;
int
board_ref_clock
;
int
board_tcxo_clock
;
unsigned
long
platform_quirks
;
};
/* Platform does not support level trigger interrupts */
#define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0)
#ifdef CONFIG_WL12XX_PLATFORM_DATA
int
wl12xx_set_platform_data
(
const
struct
wl12xx_platform_data
*
data
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录