diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-5000.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 111 |
1 files changed, 88 insertions, 23 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a738886b434f..438e4bd0a9a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -44,9 +44,21 @@ | |||
44 | #include "iwl-helpers.h" | 44 | #include "iwl-helpers.h" |
45 | #include "iwl-5000-hw.h" | 45 | #include "iwl-5000-hw.h" |
46 | 46 | ||
47 | #define IWL5000_UCODE_API "-1" | 47 | /* Highest firmware API version supported */ |
48 | #define IWL5000_UCODE_API_MAX 1 | ||
49 | #define IWL5150_UCODE_API_MAX 1 | ||
48 | 50 | ||
49 | #define IWL5000_MODULE_FIRMWARE "iwlwifi-5000" IWL5000_UCODE_API ".ucode" | 51 | /* Lowest firmware API version supported */ |
52 | #define IWL5000_UCODE_API_MIN 1 | ||
53 | #define IWL5150_UCODE_API_MIN 1 | ||
54 | |||
55 | #define IWL5000_FW_PRE "iwlwifi-5000-" | ||
56 | #define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode" | ||
57 | #define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api) | ||
58 | |||
59 | #define IWL5150_FW_PRE "iwlwifi-5150-" | ||
60 | #define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" | ||
61 | #define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) | ||
50 | 62 | ||
51 | static const u16 iwl5000_default_queue_to_tx_fifo[] = { | 63 | static const u16 iwl5000_default_queue_to_tx_fifo[] = { |
52 | IWL_TX_FIFO_AC3, | 64 | IWL_TX_FIFO_AC3, |
@@ -338,9 +350,13 @@ static void iwl5000_gain_computation(struct iwl_priv *priv, | |||
338 | 350 | ||
339 | if (!data->radio_write) { | 351 | if (!data->radio_write) { |
340 | struct iwl_calib_chain_noise_gain_cmd cmd; | 352 | struct iwl_calib_chain_noise_gain_cmd cmd; |
353 | |||
341 | memset(&cmd, 0, sizeof(cmd)); | 354 | memset(&cmd, 0, sizeof(cmd)); |
342 | 355 | ||
343 | cmd.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; | 356 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; |
357 | cmd.hdr.first_group = 0; | ||
358 | cmd.hdr.groups_num = 1; | ||
359 | cmd.hdr.data_valid = 1; | ||
344 | cmd.delta_gain_1 = data->delta_gain_code[1]; | 360 | cmd.delta_gain_1 = data->delta_gain_code[1]; |
345 | cmd.delta_gain_2 = data->delta_gain_code[2]; | 361 | cmd.delta_gain_2 = data->delta_gain_code[2]; |
346 | iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, | 362 | iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, |
@@ -362,14 +378,19 @@ static void iwl5000_gain_computation(struct iwl_priv *priv, | |||
362 | static void iwl5000_chain_noise_reset(struct iwl_priv *priv) | 378 | static void iwl5000_chain_noise_reset(struct iwl_priv *priv) |
363 | { | 379 | { |
364 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 380 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
381 | int ret; | ||
365 | 382 | ||
366 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | 383 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { |
367 | struct iwl_calib_chain_noise_reset_cmd cmd; | 384 | struct iwl_calib_chain_noise_reset_cmd cmd; |
368 | |||
369 | memset(&cmd, 0, sizeof(cmd)); | 385 | memset(&cmd, 0, sizeof(cmd)); |
370 | cmd.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; | 386 | |
371 | if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | 387 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; |
372 | sizeof(cmd), &cmd)) | 388 | cmd.hdr.first_group = 0; |
389 | cmd.hdr.groups_num = 1; | ||
390 | cmd.hdr.data_valid = 1; | ||
391 | ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | ||
392 | sizeof(cmd), &cmd); | ||
393 | if (ret) | ||
373 | IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n"); | 394 | IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n"); |
374 | data->state = IWL_CHAIN_NOISE_ACCUMULATE; | 395 | data->state = IWL_CHAIN_NOISE_ACCUMULATE; |
375 | IWL_DEBUG_CALIB("Run chain_noise_calibrate\n"); | 396 | IWL_DEBUG_CALIB("Run chain_noise_calibrate\n"); |
@@ -415,22 +436,33 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | |||
415 | return &priv->eeprom[address]; | 436 | return &priv->eeprom[address]; |
416 | } | 437 | } |
417 | 438 | ||
439 | static s32 iwl5150_get_ct_threshold(struct iwl_priv *priv) | ||
440 | { | ||
441 | const s32 volt2temp_coef = -5; | ||
442 | u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv, | ||
443 | EEPROM_5000_TEMPERATURE); | ||
444 | /* offset = temperate - voltage / coef */ | ||
445 | s32 offset = temp_calib[0] - temp_calib[1] / volt2temp_coef; | ||
446 | s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) - offset; | ||
447 | return threshold * volt2temp_coef; | ||
448 | } | ||
449 | |||
418 | /* | 450 | /* |
419 | * Calibration | 451 | * Calibration |
420 | */ | 452 | */ |
421 | static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) | 453 | static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) |
422 | { | 454 | { |
423 | u8 data[sizeof(struct iwl_calib_hdr) + | 455 | struct iwl_calib_xtal_freq_cmd cmd; |
424 | sizeof(struct iwl_cal_xtal_freq)]; | ||
425 | struct iwl_calib_cmd *cmd = (struct iwl_calib_cmd *)data; | ||
426 | struct iwl_cal_xtal_freq *xtal = (struct iwl_cal_xtal_freq *)cmd->data; | ||
427 | u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); | 456 | u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); |
428 | 457 | ||
429 | cmd->hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; | 458 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; |
430 | xtal->cap_pin1 = (u8)xtal_calib[0]; | 459 | cmd.hdr.first_group = 0; |
431 | xtal->cap_pin2 = (u8)xtal_calib[1]; | 460 | cmd.hdr.groups_num = 1; |
461 | cmd.hdr.data_valid = 1; | ||
462 | cmd.cap_pin1 = (u8)xtal_calib[0]; | ||
463 | cmd.cap_pin2 = (u8)xtal_calib[1]; | ||
432 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], | 464 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], |
433 | data, sizeof(data)); | 465 | (u8 *)&cmd, sizeof(cmd)); |
434 | } | 466 | } |
435 | 467 | ||
436 | static int iwl5000_send_calib_cfg(struct iwl_priv *priv) | 468 | static int iwl5000_send_calib_cfg(struct iwl_priv *priv) |
@@ -466,6 +498,9 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv, | |||
466 | * uCode. iwl_send_calib_results sends them in a row according to their | 498 | * uCode. iwl_send_calib_results sends them in a row according to their |
467 | * index. We sort them here */ | 499 | * index. We sort them here */ |
468 | switch (hdr->op_code) { | 500 | switch (hdr->op_code) { |
501 | case IWL_PHY_CALIBRATE_DC_CMD: | ||
502 | index = IWL_CALIB_DC; | ||
503 | break; | ||
469 | case IWL_PHY_CALIBRATE_LO_CMD: | 504 | case IWL_PHY_CALIBRATE_LO_CMD: |
470 | index = IWL_CALIB_LO; | 505 | index = IWL_CALIB_LO; |
471 | break; | 506 | break; |
@@ -802,6 +837,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
802 | } | 837 | } |
803 | 838 | ||
804 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | 839 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; |
840 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | ||
805 | priv->hw_params.scd_bc_tbls_size = | 841 | priv->hw_params.scd_bc_tbls_size = |
806 | IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); | 842 | IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); |
807 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 843 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
@@ -845,7 +881,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
845 | case CSR_HW_REV_TYPE_5150: | 881 | case CSR_HW_REV_TYPE_5150: |
846 | /* 5150 wants in Kelvin */ | 882 | /* 5150 wants in Kelvin */ |
847 | priv->hw_params.ct_kill_threshold = | 883 | priv->hw_params.ct_kill_threshold = |
848 | CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD); | 884 | iwl5150_get_ct_threshold(priv); |
849 | break; | 885 | break; |
850 | } | 886 | } |
851 | 887 | ||
@@ -862,7 +898,12 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
862 | BIT(IWL_CALIB_BASE_BAND); | 898 | BIT(IWL_CALIB_BASE_BAND); |
863 | break; | 899 | break; |
864 | case CSR_HW_REV_TYPE_5150: | 900 | case CSR_HW_REV_TYPE_5150: |
865 | priv->hw_params.calib_init_cfg = 0; | 901 | priv->hw_params.calib_init_cfg = |
902 | BIT(IWL_CALIB_DC) | | ||
903 | BIT(IWL_CALIB_LO) | | ||
904 | BIT(IWL_CALIB_TX_IQ) | | ||
905 | BIT(IWL_CALIB_BASE_BAND); | ||
906 | |||
866 | break; | 907 | break; |
867 | } | 908 | } |
868 | 909 | ||
@@ -1501,7 +1542,9 @@ static struct iwl_mod_params iwl50_mod_params = { | |||
1501 | 1542 | ||
1502 | struct iwl_cfg iwl5300_agn_cfg = { | 1543 | struct iwl_cfg iwl5300_agn_cfg = { |
1503 | .name = "5300AGN", | 1544 | .name = "5300AGN", |
1504 | .fw_name = IWL5000_MODULE_FIRMWARE, | 1545 | .fw_name_pre = IWL5000_FW_PRE, |
1546 | .ucode_api_max = IWL5000_UCODE_API_MAX, | ||
1547 | .ucode_api_min = IWL5000_UCODE_API_MIN, | ||
1505 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 1548 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1506 | .ops = &iwl5000_ops, | 1549 | .ops = &iwl5000_ops, |
1507 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1550 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
@@ -1512,7 +1555,9 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1512 | 1555 | ||
1513 | struct iwl_cfg iwl5100_bg_cfg = { | 1556 | struct iwl_cfg iwl5100_bg_cfg = { |
1514 | .name = "5100BG", | 1557 | .name = "5100BG", |
1515 | .fw_name = IWL5000_MODULE_FIRMWARE, | 1558 | .fw_name_pre = IWL5000_FW_PRE, |
1559 | .ucode_api_max = IWL5000_UCODE_API_MAX, | ||
1560 | .ucode_api_min = IWL5000_UCODE_API_MIN, | ||
1516 | .sku = IWL_SKU_G, | 1561 | .sku = IWL_SKU_G, |
1517 | .ops = &iwl5000_ops, | 1562 | .ops = &iwl5000_ops, |
1518 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1563 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
@@ -1523,7 +1568,9 @@ struct iwl_cfg iwl5100_bg_cfg = { | |||
1523 | 1568 | ||
1524 | struct iwl_cfg iwl5100_abg_cfg = { | 1569 | struct iwl_cfg iwl5100_abg_cfg = { |
1525 | .name = "5100ABG", | 1570 | .name = "5100ABG", |
1526 | .fw_name = IWL5000_MODULE_FIRMWARE, | 1571 | .fw_name_pre = IWL5000_FW_PRE, |
1572 | .ucode_api_max = IWL5000_UCODE_API_MAX, | ||
1573 | .ucode_api_min = IWL5000_UCODE_API_MIN, | ||
1527 | .sku = IWL_SKU_A|IWL_SKU_G, | 1574 | .sku = IWL_SKU_A|IWL_SKU_G, |
1528 | .ops = &iwl5000_ops, | 1575 | .ops = &iwl5000_ops, |
1529 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1576 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
@@ -1534,7 +1581,9 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1534 | 1581 | ||
1535 | struct iwl_cfg iwl5100_agn_cfg = { | 1582 | struct iwl_cfg iwl5100_agn_cfg = { |
1536 | .name = "5100AGN", | 1583 | .name = "5100AGN", |
1537 | .fw_name = IWL5000_MODULE_FIRMWARE, | 1584 | .fw_name_pre = IWL5000_FW_PRE, |
1585 | .ucode_api_max = IWL5000_UCODE_API_MAX, | ||
1586 | .ucode_api_min = IWL5000_UCODE_API_MIN, | ||
1538 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 1587 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1539 | .ops = &iwl5000_ops, | 1588 | .ops = &iwl5000_ops, |
1540 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1589 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
@@ -1545,7 +1594,22 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1545 | 1594 | ||
1546 | struct iwl_cfg iwl5350_agn_cfg = { | 1595 | struct iwl_cfg iwl5350_agn_cfg = { |
1547 | .name = "5350AGN", | 1596 | .name = "5350AGN", |
1548 | .fw_name = IWL5000_MODULE_FIRMWARE, | 1597 | .fw_name_pre = IWL5000_FW_PRE, |
1598 | .ucode_api_max = IWL5000_UCODE_API_MAX, | ||
1599 | .ucode_api_min = IWL5000_UCODE_API_MIN, | ||
1600 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
1601 | .ops = &iwl5000_ops, | ||
1602 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | ||
1603 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | ||
1604 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | ||
1605 | .mod_params = &iwl50_mod_params, | ||
1606 | }; | ||
1607 | |||
1608 | struct iwl_cfg iwl5150_agn_cfg = { | ||
1609 | .name = "5150AGN", | ||
1610 | .fw_name_pre = IWL5150_FW_PRE, | ||
1611 | .ucode_api_max = IWL5150_UCODE_API_MAX, | ||
1612 | .ucode_api_min = IWL5150_UCODE_API_MIN, | ||
1549 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 1613 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1550 | .ops = &iwl5000_ops, | 1614 | .ops = &iwl5000_ops, |
1551 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1615 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
@@ -1554,7 +1618,8 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1554 | .mod_params = &iwl50_mod_params, | 1618 | .mod_params = &iwl50_mod_params, |
1555 | }; | 1619 | }; |
1556 | 1620 | ||
1557 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE); | 1621 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); |
1622 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); | ||
1558 | 1623 | ||
1559 | module_param_named(disable50, iwl50_mod_params.disable, int, 0444); | 1624 | module_param_named(disable50, iwl50_mod_params.disable, int, 0444); |
1560 | MODULE_PARM_DESC(disable50, | 1625 | MODULE_PARM_DESC(disable50, |