diff options
Diffstat (limited to 'drivers/net/wireless/ti/wl18xx')
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/conf.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/io.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/main.c | 117 |
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 | ||
87 | enum 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 | |||
98 | struct wl18xx_ht_settings { | ||
99 | /* DEFAULT / WIDE / SISO20 */ | ||
100 | u8 mode; | ||
101 | } __packed; | ||
102 | |||
87 | struct wl18xx_priv_conf { | 103 | struct 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 | ||
55 | int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out) | 55 | int 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 | ||
46 | static char *ht_mode_param = "default"; | 46 | static char *ht_mode_param = NULL; |
47 | static char *board_type_param = "hdk"; | 47 | static char *board_type_param = NULL; |
48 | static bool checksum_param = false; | 48 | static bool checksum_param = false; |
49 | static bool enable_11a_param = true; | 49 | static bool enable_11a_param = true; |
50 | static int num_rx_desc_param = -1; | 50 | static int num_rx_desc_param = -1; |
@@ -494,16 +494,20 @@ static struct wlcore_conf wl18xx_conf = { | |||
494 | }; | 494 | }; |
495 | 495 | ||
496 | static struct wl18xx_priv_conf wl18xx_default_priv_conf = { | 496 | static 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: | |||
772 | static int wl18xx_set_mac_and_phy(struct wl1271 *wl) | 776 | static 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 | ||
784 | out: | 795 | out: |
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 | ||
1016 | static 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, | |||
1025 | static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, | 1047 | static 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) { |