aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ti/wl18xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ti/wl18xx')
-rw-r--r--drivers/net/wireless/ti/wl18xx/conf.h21
-rw-r--r--drivers/net/wireless/ti/wl18xx/io.c2
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c117
3 files changed, 106 insertions, 34 deletions
diff --git a/drivers/net/wireless/ti/wl18xx/conf.h b/drivers/net/wireless/ti/wl18xx/conf.h
index fac0b7e87e75..4d426cc20274 100644
--- a/drivers/net/wireless/ti/wl18xx/conf.h
+++ b/drivers/net/wireless/ti/wl18xx/conf.h
@@ -23,7 +23,7 @@
23#define __WL18XX_CONF_H__ 23#define __WL18XX_CONF_H__
24 24
25#define WL18XX_CONF_MAGIC 0x10e100ca 25#define WL18XX_CONF_MAGIC 0x10e100ca
26#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0002) 26#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0003)
27#define WL18XX_CONF_MASK 0x0000ffff 27#define WL18XX_CONF_MASK 0x0000ffff
28#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \ 28#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \
29 sizeof(struct wl18xx_priv_conf)) 29 sizeof(struct wl18xx_priv_conf))
@@ -84,7 +84,26 @@ struct wl18xx_mac_and_phy_params {
84 u8 padding[1]; 84 u8 padding[1];
85} __packed; 85} __packed;
86 86
87enum wl18xx_ht_mode {
88 /* Default - use MIMO, fallback to SISO20 */
89 HT_MODE_DEFAULT = 0,
90
91 /* Wide - use SISO40 */
92 HT_MODE_WIDE = 1,
93
94 /* Use SISO20 */
95 HT_MODE_SISO20 = 2,
96};
97
98struct wl18xx_ht_settings {
99 /* DEFAULT / WIDE / SISO20 */
100 u8 mode;
101} __packed;
102
87struct wl18xx_priv_conf { 103struct wl18xx_priv_conf {
104 /* Module params structures */
105 struct wl18xx_ht_settings ht;
106
88 /* this structure is copied wholesale to FW */ 107 /* this structure is copied wholesale to FW */
89 struct wl18xx_mac_and_phy_params phy; 108 struct wl18xx_mac_and_phy_params phy;
90} __packed; 109} __packed;
diff --git a/drivers/net/wireless/ti/wl18xx/io.c b/drivers/net/wireless/ti/wl18xx/io.c
index 0c06ccfd1b8c..f0abf3ef2c95 100644
--- a/drivers/net/wireless/ti/wl18xx/io.c
+++ b/drivers/net/wireless/ti/wl18xx/io.c
@@ -54,7 +54,7 @@ out:
54 54
55int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out) 55int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out)
56{ 56{
57 u32 val; 57 u32 val = 0;
58 int ret; 58 int ret;
59 59
60 if (WARN_ON(addr % 2)) 60 if (WARN_ON(addr % 2))
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index b378b34c4a6a..69042bb9a097 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -43,8 +43,8 @@
43 43
44#define WL18XX_RX_CHECKSUM_MASK 0x40 44#define WL18XX_RX_CHECKSUM_MASK 0x40
45 45
46static char *ht_mode_param = "default"; 46static char *ht_mode_param = NULL;
47static char *board_type_param = "hdk"; 47static char *board_type_param = NULL;
48static bool checksum_param = false; 48static bool checksum_param = false;
49static bool enable_11a_param = true; 49static bool enable_11a_param = true;
50static int num_rx_desc_param = -1; 50static int num_rx_desc_param = -1;
@@ -494,16 +494,20 @@ static struct wlcore_conf wl18xx_conf = {
494}; 494};
495 495
496static struct wl18xx_priv_conf wl18xx_default_priv_conf = { 496static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
497 .ht = {
498 .mode = HT_MODE_DEFAULT,
499 },
497 .phy = { 500 .phy = {
498 .phy_standalone = 0x00, 501 .phy_standalone = 0x00,
499 .primary_clock_setting_time = 0x05, 502 .primary_clock_setting_time = 0x05,
500 .clock_valid_on_wake_up = 0x00, 503 .clock_valid_on_wake_up = 0x00,
501 .secondary_clock_setting_time = 0x05, 504 .secondary_clock_setting_time = 0x05,
505 .board_type = BOARD_TYPE_HDK_18XX,
502 .rdl = 0x01, 506 .rdl = 0x01,
503 .auto_detect = 0x00, 507 .auto_detect = 0x00,
504 .dedicated_fem = FEM_NONE, 508 .dedicated_fem = FEM_NONE,
505 .low_band_component = COMPONENT_2_WAY_SWITCH, 509 .low_band_component = COMPONENT_2_WAY_SWITCH,
506 .low_band_component_type = 0x05, 510 .low_band_component_type = 0x06,
507 .high_band_component = COMPONENT_2_WAY_SWITCH, 511 .high_band_component = COMPONENT_2_WAY_SWITCH,
508 .high_band_component_type = 0x09, 512 .high_band_component_type = 0x09,
509 .tcxo_ldo_voltage = 0x00, 513 .tcxo_ldo_voltage = 0x00,
@@ -772,16 +776,24 @@ out:
772static int wl18xx_set_mac_and_phy(struct wl1271 *wl) 776static int wl18xx_set_mac_and_phy(struct wl1271 *wl)
773{ 777{
774 struct wl18xx_priv *priv = wl->priv; 778 struct wl18xx_priv *priv = wl->priv;
779 struct wl18xx_mac_and_phy_params *params;
775 int ret; 780 int ret;
776 781
782 params = kmemdup(&priv->conf.phy, sizeof(*params), GFP_KERNEL);
783 if (!params) {
784 ret = -ENOMEM;
785 goto out;
786 }
787
777 ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); 788 ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
778 if (ret < 0) 789 if (ret < 0)
779 goto out; 790 goto out;
780 791
781 ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, 792 ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, params,
782 sizeof(struct wl18xx_mac_and_phy_params), false); 793 sizeof(*params), false);
783 794
784out: 795out:
796 kfree(params);
785 return ret; 797 return ret;
786} 798}
787 799
@@ -1001,6 +1013,13 @@ static void wl18xx_set_rx_csum(struct wl1271 *wl,
1001 skb->ip_summed = CHECKSUM_UNNECESSARY; 1013 skb->ip_summed = CHECKSUM_UNNECESSARY;
1002} 1014}
1003 1015
1016static bool wl18xx_is_mimo_supported(struct wl1271 *wl)
1017{
1018 struct wl18xx_priv *priv = wl->priv;
1019
1020 return priv->conf.phy.number_of_assembled_ant2_4 >= 2;
1021}
1022
1004/* 1023/*
1005 * TODO: instead of having these two functions to get the rate mask, 1024 * TODO: instead of having these two functions to get the rate mask,
1006 * we should modify the wlvif->rate_set instead 1025 * we should modify the wlvif->rate_set instead
@@ -1017,6 +1036,9 @@ static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl,
1017 1036
1018 /* we don't support MIMO in wide-channel mode */ 1037 /* we don't support MIMO in wide-channel mode */
1019 hw_rate_set &= ~CONF_TX_MIMO_RATES; 1038 hw_rate_set &= ~CONF_TX_MIMO_RATES;
1039 } else if (wl18xx_is_mimo_supported(wl)) {
1040 wl1271_debug(DEBUG_ACX, "using MIMO channel rate mask");
1041 hw_rate_set |= CONF_TX_MIMO_RATES;
1020 } 1042 }
1021 1043
1022 return hw_rate_set; 1044 return hw_rate_set;
@@ -1025,8 +1047,6 @@ static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl,
1025static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, 1047static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
1026 struct wl12xx_vif *wlvif) 1048 struct wl12xx_vif *wlvif)
1027{ 1049{
1028 struct wl18xx_priv *priv = wl->priv;
1029
1030 if (wlvif->channel_type == NL80211_CHAN_HT40MINUS || 1050 if (wlvif->channel_type == NL80211_CHAN_HT40MINUS ||
1031 wlvif->channel_type == NL80211_CHAN_HT40PLUS) { 1051 wlvif->channel_type == NL80211_CHAN_HT40PLUS) {
1032 wl1271_debug(DEBUG_ACX, "using wide channel rate mask"); 1052 wl1271_debug(DEBUG_ACX, "using wide channel rate mask");
@@ -1036,7 +1056,7 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl,
1036 return 0; 1056 return 0;
1037 1057
1038 return CONF_TX_RATE_USE_WIDE_CHAN; 1058 return CONF_TX_RATE_USE_WIDE_CHAN;
1039 } else if (priv->conf.phy.number_of_assembled_ant2_4 >= 2 && 1059 } else if (wl18xx_is_mimo_supported(wl) &&
1040 wlvif->band == IEEE80211_BAND_2GHZ) { 1060 wlvif->band == IEEE80211_BAND_2GHZ) {
1041 wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); 1061 wl1271_debug(DEBUG_ACX, "using MIMO rate mask");
1042 /* 1062 /*
@@ -1136,6 +1156,12 @@ static int wl18xx_plt_init(struct wl1271 *wl)
1136{ 1156{
1137 int ret; 1157 int ret;
1138 1158
1159 /* calibrator based auto/fem detect not supported for 18xx */
1160 if (wl->plt_mode == PLT_FEM_DETECT) {
1161 wl1271_error("wl18xx_plt_init: PLT FEM_DETECT not supported");
1162 return -EINVAL;
1163 }
1164
1139 ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT); 1165 ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT);
1140 if (ret < 0) 1166 if (ret < 0)
1141 return ret; 1167 return ret;
@@ -1383,27 +1409,44 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
1383 if (ret < 0) 1409 if (ret < 0)
1384 goto out_free; 1410 goto out_free;
1385 1411
1386 if (!strcmp(board_type_param, "fpga")) { 1412 /* If the module param is set, update it in conf */
1387 priv->conf.phy.board_type = BOARD_TYPE_FPGA_18XX; 1413 if (board_type_param) {
1388 } else if (!strcmp(board_type_param, "hdk")) { 1414 if (!strcmp(board_type_param, "fpga")) {
1389 priv->conf.phy.board_type = BOARD_TYPE_HDK_18XX; 1415 priv->conf.phy.board_type = BOARD_TYPE_FPGA_18XX;
1390 /* HACK! Just for now we hardcode HDK to 0x06 */ 1416 } else if (!strcmp(board_type_param, "hdk")) {
1391 priv->conf.phy.low_band_component_type = 0x06; 1417 priv->conf.phy.board_type = BOARD_TYPE_HDK_18XX;
1392 } else if (!strcmp(board_type_param, "dvp")) { 1418 } else if (!strcmp(board_type_param, "dvp")) {
1393 priv->conf.phy.board_type = BOARD_TYPE_DVP_18XX; 1419 priv->conf.phy.board_type = BOARD_TYPE_DVP_18XX;
1394 } else if (!strcmp(board_type_param, "evb")) { 1420 } else if (!strcmp(board_type_param, "evb")) {
1395 priv->conf.phy.board_type = BOARD_TYPE_EVB_18XX; 1421 priv->conf.phy.board_type = BOARD_TYPE_EVB_18XX;
1396 } else if (!strcmp(board_type_param, "com8")) { 1422 } else if (!strcmp(board_type_param, "com8")) {
1397 priv->conf.phy.board_type = BOARD_TYPE_COM8_18XX; 1423 priv->conf.phy.board_type = BOARD_TYPE_COM8_18XX;
1398 /* HACK! Just for now we hardcode COM8 to 0x06 */ 1424 } else {
1425 wl1271_error("invalid board type '%s'",
1426 board_type_param);
1427 ret = -EINVAL;
1428 goto out_free;
1429 }
1430 }
1431
1432 /* HACK! Just for now we hardcode COM8 and HDK to 0x06 */
1433 switch (priv->conf.phy.board_type) {
1434 case BOARD_TYPE_HDK_18XX:
1435 case BOARD_TYPE_COM8_18XX:
1399 priv->conf.phy.low_band_component_type = 0x06; 1436 priv->conf.phy.low_band_component_type = 0x06;
1400 } else { 1437 break;
1401 wl1271_error("invalid board type '%s'", board_type_param); 1438 case BOARD_TYPE_FPGA_18XX:
1439 case BOARD_TYPE_DVP_18XX:
1440 case BOARD_TYPE_EVB_18XX:
1441 priv->conf.phy.low_band_component_type = 0x05;
1442 break;
1443 default:
1444 wl1271_error("invalid board type '%d'",
1445 priv->conf.phy.board_type);
1402 ret = -EINVAL; 1446 ret = -EINVAL;
1403 goto out_free; 1447 goto out_free;
1404 } 1448 }
1405 1449
1406 /* If the module param is set, update it in conf */
1407 if (low_band_component_param != -1) 1450 if (low_band_component_param != -1)
1408 priv->conf.phy.low_band_component = low_band_component_param; 1451 priv->conf.phy.low_band_component = low_band_component_param;
1409 if (low_band_component_type_param != -1) 1452 if (low_band_component_type_param != -1)
@@ -1424,12 +1467,26 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
1424 if (dc2dc_param != -1) 1467 if (dc2dc_param != -1)
1425 priv->conf.phy.external_pa_dc2dc = dc2dc_param; 1468 priv->conf.phy.external_pa_dc2dc = dc2dc_param;
1426 1469
1427 if (!strcmp(ht_mode_param, "default")) { 1470 if (ht_mode_param) {
1471 if (!strcmp(ht_mode_param, "default"))
1472 priv->conf.ht.mode = HT_MODE_DEFAULT;
1473 else if (!strcmp(ht_mode_param, "wide"))
1474 priv->conf.ht.mode = HT_MODE_WIDE;
1475 else if (!strcmp(ht_mode_param, "siso20"))
1476 priv->conf.ht.mode = HT_MODE_SISO20;
1477 else {
1478 wl1271_error("invalid ht_mode '%s'", ht_mode_param);
1479 ret = -EINVAL;
1480 goto out_free;
1481 }
1482 }
1483
1484 if (priv->conf.ht.mode == HT_MODE_DEFAULT) {
1428 /* 1485 /*
1429 * Only support mimo with multiple antennas. Fall back to 1486 * Only support mimo with multiple antennas. Fall back to
1430 * siso20. 1487 * siso20.
1431 */ 1488 */
1432 if (priv->conf.phy.number_of_assembled_ant2_4 >= 2) 1489 if (wl18xx_is_mimo_supported(wl))
1433 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, 1490 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
1434 &wl18xx_mimo_ht_cap_2ghz); 1491 &wl18xx_mimo_ht_cap_2ghz);
1435 else 1492 else
@@ -1439,20 +1496,16 @@ static int __devinit wl18xx_probe(struct platform_device *pdev)
1439 /* 5Ghz is always wide */ 1496 /* 5Ghz is always wide */
1440 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, 1497 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
1441 &wl18xx_siso40_ht_cap_5ghz); 1498 &wl18xx_siso40_ht_cap_5ghz);
1442 } else if (!strcmp(ht_mode_param, "wide")) { 1499 } else if (priv->conf.ht.mode == HT_MODE_WIDE) {
1443 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, 1500 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
1444 &wl18xx_siso40_ht_cap_2ghz); 1501 &wl18xx_siso40_ht_cap_2ghz);
1445 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, 1502 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
1446 &wl18xx_siso40_ht_cap_5ghz); 1503 &wl18xx_siso40_ht_cap_5ghz);
1447 } else if (!strcmp(ht_mode_param, "siso20")) { 1504 } else if (priv->conf.ht.mode == HT_MODE_SISO20) {
1448 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, 1505 wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ,
1449 &wl18xx_siso20_ht_cap); 1506 &wl18xx_siso20_ht_cap);
1450 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, 1507 wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ,
1451 &wl18xx_siso20_ht_cap); 1508 &wl18xx_siso20_ht_cap);
1452 } else {
1453 wl1271_error("invalid ht_mode '%s'", ht_mode_param);
1454 ret = -EINVAL;
1455 goto out_free;
1456 } 1509 }
1457 1510
1458 if (!checksum_param) { 1511 if (!checksum_param) {