18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> 38c2ecf20Sopenharmony_ci * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and distribute this software for any 68c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 78c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 108c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 118c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 128c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 138c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 148c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 158c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/*************************************\ 208c2ecf20Sopenharmony_ci* Attach/Detach Functions and helpers * 218c2ecf20Sopenharmony_ci\*************************************/ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <linux/pci.h> 268c2ecf20Sopenharmony_ci#include <linux/slab.h> 278c2ecf20Sopenharmony_ci#include "ath5k.h" 288c2ecf20Sopenharmony_ci#include "reg.h" 298c2ecf20Sopenharmony_ci#include "debug.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/** 328c2ecf20Sopenharmony_ci * ath5k_hw_post() - Power On Self Test helper function 338c2ecf20Sopenharmony_ci * @ah: The &struct ath5k_hw 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_cistatic int ath5k_hw_post(struct ath5k_hw *ah) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci static const u32 static_pattern[4] = { 398c2ecf20Sopenharmony_ci 0x55555555, 0xaaaaaaaa, 408c2ecf20Sopenharmony_ci 0x66666666, 0x99999999 418c2ecf20Sopenharmony_ci }; 428c2ecf20Sopenharmony_ci static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) }; 438c2ecf20Sopenharmony_ci int i, c; 448c2ecf20Sopenharmony_ci u16 cur_reg; 458c2ecf20Sopenharmony_ci u32 var_pattern; 468c2ecf20Sopenharmony_ci u32 init_val; 478c2ecf20Sopenharmony_ci u32 cur_val; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci for (c = 0; c < 2; c++) { 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci cur_reg = regs[c]; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* Save previous value */ 548c2ecf20Sopenharmony_ci init_val = ath5k_hw_reg_read(ah, cur_reg); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci for (i = 0; i < 256; i++) { 578c2ecf20Sopenharmony_ci var_pattern = i << 16 | i; 588c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, var_pattern, cur_reg); 598c2ecf20Sopenharmony_ci cur_val = ath5k_hw_reg_read(ah, cur_reg); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci if (cur_val != var_pattern) { 628c2ecf20Sopenharmony_ci ATH5K_ERR(ah, "POST Failed !!!\n"); 638c2ecf20Sopenharmony_ci return -EAGAIN; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* Found on ndiswrapper dumps */ 678c2ecf20Sopenharmony_ci var_pattern = 0x0039080f; 688c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, var_pattern, cur_reg); 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 728c2ecf20Sopenharmony_ci var_pattern = static_pattern[i]; 738c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, var_pattern, cur_reg); 748c2ecf20Sopenharmony_ci cur_val = ath5k_hw_reg_read(ah, cur_reg); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (cur_val != var_pattern) { 778c2ecf20Sopenharmony_ci ATH5K_ERR(ah, "POST Failed !!!\n"); 788c2ecf20Sopenharmony_ci return -EAGAIN; 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* Found on ndiswrapper dumps */ 828c2ecf20Sopenharmony_ci var_pattern = 0x003b080f; 838c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, var_pattern, cur_reg); 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* Restore previous value */ 878c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, init_val, cur_reg); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci return 0; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/** 968c2ecf20Sopenharmony_ci * ath5k_hw_init() - Check if hw is supported and init the needed structs 978c2ecf20Sopenharmony_ci * @ah: The &struct ath5k_hw associated with the device 988c2ecf20Sopenharmony_ci * 998c2ecf20Sopenharmony_ci * Check if the device is supported, perform a POST and initialize the needed 1008c2ecf20Sopenharmony_ci * structs. Returns -ENOMEM if we don't have memory for the needed structs, 1018c2ecf20Sopenharmony_ci * -ENODEV if the device is not supported or prints an error msg if something 1028c2ecf20Sopenharmony_ci * else went wrong. 1038c2ecf20Sopenharmony_ci */ 1048c2ecf20Sopenharmony_ciint ath5k_hw_init(struct ath5k_hw *ah) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci static const u8 zero_mac[ETH_ALEN] = { }; 1078c2ecf20Sopenharmony_ci struct ath_common *common = ath5k_hw_common(ah); 1088c2ecf20Sopenharmony_ci struct pci_dev *pdev = ah->pdev; 1098c2ecf20Sopenharmony_ci struct ath5k_eeprom_info *ee; 1108c2ecf20Sopenharmony_ci int ret; 1118c2ecf20Sopenharmony_ci u32 srev; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* 1148c2ecf20Sopenharmony_ci * HW information 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_ci ah->ah_bwmode = AR5K_BWMODE_DEFAULT; 1178c2ecf20Sopenharmony_ci ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; 1188c2ecf20Sopenharmony_ci ah->ah_imr = 0; 1198c2ecf20Sopenharmony_ci ah->ah_retry_short = AR5K_INIT_RETRY_SHORT; 1208c2ecf20Sopenharmony_ci ah->ah_retry_long = AR5K_INIT_RETRY_LONG; 1218c2ecf20Sopenharmony_ci ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; 1228c2ecf20Sopenharmony_ci ah->ah_noise_floor = -95; /* until first NF calibration is run */ 1238c2ecf20Sopenharmony_ci ah->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; 1248c2ecf20Sopenharmony_ci ah->ah_current_channel = &ah->channels[0]; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* 1278c2ecf20Sopenharmony_ci * Find the mac version 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci ath5k_hw_read_srev(ah); 1308c2ecf20Sopenharmony_ci srev = ah->ah_mac_srev; 1318c2ecf20Sopenharmony_ci if (srev < AR5K_SREV_AR5311) 1328c2ecf20Sopenharmony_ci ah->ah_version = AR5K_AR5210; 1338c2ecf20Sopenharmony_ci else if (srev < AR5K_SREV_AR5212) 1348c2ecf20Sopenharmony_ci ah->ah_version = AR5K_AR5211; 1358c2ecf20Sopenharmony_ci else 1368c2ecf20Sopenharmony_ci ah->ah_version = AR5K_AR5212; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* Get the MAC version */ 1398c2ecf20Sopenharmony_ci ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* Fill the ath5k_hw struct with the needed functions */ 1428c2ecf20Sopenharmony_ci ret = ath5k_hw_init_desc_functions(ah); 1438c2ecf20Sopenharmony_ci if (ret) 1448c2ecf20Sopenharmony_ci goto err; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* Bring device out of sleep and reset its units */ 1478c2ecf20Sopenharmony_ci ret = ath5k_hw_nic_wakeup(ah, NULL); 1488c2ecf20Sopenharmony_ci if (ret) 1498c2ecf20Sopenharmony_ci goto err; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* Get PHY and RADIO revisions */ 1528c2ecf20Sopenharmony_ci ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & 1538c2ecf20Sopenharmony_ci 0xffffffff; 1548c2ecf20Sopenharmony_ci ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, 1558c2ecf20Sopenharmony_ci NL80211_BAND_5GHZ); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* Try to identify radio chip based on its srev */ 1588c2ecf20Sopenharmony_ci switch (ah->ah_radio_5ghz_revision & 0xf0) { 1598c2ecf20Sopenharmony_ci case AR5K_SREV_RAD_5111: 1608c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF5111; 1618c2ecf20Sopenharmony_ci ah->ah_single_chip = false; 1628c2ecf20Sopenharmony_ci ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, 1638c2ecf20Sopenharmony_ci NL80211_BAND_2GHZ); 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci case AR5K_SREV_RAD_5112: 1668c2ecf20Sopenharmony_ci case AR5K_SREV_RAD_2112: 1678c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF5112; 1688c2ecf20Sopenharmony_ci ah->ah_single_chip = false; 1698c2ecf20Sopenharmony_ci ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, 1708c2ecf20Sopenharmony_ci NL80211_BAND_2GHZ); 1718c2ecf20Sopenharmony_ci break; 1728c2ecf20Sopenharmony_ci case AR5K_SREV_RAD_2413: 1738c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF2413; 1748c2ecf20Sopenharmony_ci ah->ah_single_chip = true; 1758c2ecf20Sopenharmony_ci break; 1768c2ecf20Sopenharmony_ci case AR5K_SREV_RAD_5413: 1778c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF5413; 1788c2ecf20Sopenharmony_ci ah->ah_single_chip = true; 1798c2ecf20Sopenharmony_ci break; 1808c2ecf20Sopenharmony_ci case AR5K_SREV_RAD_2316: 1818c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF2316; 1828c2ecf20Sopenharmony_ci ah->ah_single_chip = true; 1838c2ecf20Sopenharmony_ci break; 1848c2ecf20Sopenharmony_ci case AR5K_SREV_RAD_2317: 1858c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF2317; 1868c2ecf20Sopenharmony_ci ah->ah_single_chip = true; 1878c2ecf20Sopenharmony_ci break; 1888c2ecf20Sopenharmony_ci case AR5K_SREV_RAD_5424: 1898c2ecf20Sopenharmony_ci if (ah->ah_mac_version == AR5K_SREV_AR2425 || 1908c2ecf20Sopenharmony_ci ah->ah_mac_version == AR5K_SREV_AR2417) { 1918c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF2425; 1928c2ecf20Sopenharmony_ci ah->ah_single_chip = true; 1938c2ecf20Sopenharmony_ci } else { 1948c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF5413; 1958c2ecf20Sopenharmony_ci ah->ah_single_chip = true; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci break; 1988c2ecf20Sopenharmony_ci default: 1998c2ecf20Sopenharmony_ci /* Identify radio based on mac/phy srev */ 2008c2ecf20Sopenharmony_ci if (ah->ah_version == AR5K_AR5210) { 2018c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF5110; 2028c2ecf20Sopenharmony_ci ah->ah_single_chip = false; 2038c2ecf20Sopenharmony_ci } else if (ah->ah_version == AR5K_AR5211) { 2048c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF5111; 2058c2ecf20Sopenharmony_ci ah->ah_single_chip = false; 2068c2ecf20Sopenharmony_ci ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, 2078c2ecf20Sopenharmony_ci NL80211_BAND_2GHZ); 2088c2ecf20Sopenharmony_ci } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) || 2098c2ecf20Sopenharmony_ci ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) || 2108c2ecf20Sopenharmony_ci ah->ah_phy_revision == AR5K_SREV_PHY_2425) { 2118c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF2425; 2128c2ecf20Sopenharmony_ci ah->ah_single_chip = true; 2138c2ecf20Sopenharmony_ci ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425; 2148c2ecf20Sopenharmony_ci } else if (srev == AR5K_SREV_AR5213A && 2158c2ecf20Sopenharmony_ci ah->ah_phy_revision == AR5K_SREV_PHY_5212B) { 2168c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF5112; 2178c2ecf20Sopenharmony_ci ah->ah_single_chip = false; 2188c2ecf20Sopenharmony_ci ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B; 2198c2ecf20Sopenharmony_ci } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4) || 2208c2ecf20Sopenharmony_ci ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) { 2218c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF2316; 2228c2ecf20Sopenharmony_ci ah->ah_single_chip = true; 2238c2ecf20Sopenharmony_ci ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316; 2248c2ecf20Sopenharmony_ci } else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) || 2258c2ecf20Sopenharmony_ci ah->ah_phy_revision == AR5K_SREV_PHY_5413) { 2268c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF5413; 2278c2ecf20Sopenharmony_ci ah->ah_single_chip = true; 2288c2ecf20Sopenharmony_ci ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413; 2298c2ecf20Sopenharmony_ci } else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) || 2308c2ecf20Sopenharmony_ci ah->ah_phy_revision == AR5K_SREV_PHY_2413) { 2318c2ecf20Sopenharmony_ci ah->ah_radio = AR5K_RF2413; 2328c2ecf20Sopenharmony_ci ah->ah_single_chip = true; 2338c2ecf20Sopenharmony_ci ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413; 2348c2ecf20Sopenharmony_ci } else { 2358c2ecf20Sopenharmony_ci ATH5K_ERR(ah, "Couldn't identify radio revision.\n"); 2368c2ecf20Sopenharmony_ci ret = -ENODEV; 2378c2ecf20Sopenharmony_ci goto err; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* Return on unsupported chips (unsupported eeprom etc) */ 2438c2ecf20Sopenharmony_ci if ((srev >= AR5K_SREV_AR5416) && (srev < AR5K_SREV_AR2425)) { 2448c2ecf20Sopenharmony_ci ATH5K_ERR(ah, "Device not yet supported.\n"); 2458c2ecf20Sopenharmony_ci ret = -ENODEV; 2468c2ecf20Sopenharmony_ci goto err; 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* 2508c2ecf20Sopenharmony_ci * POST 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_ci ret = ath5k_hw_post(ah); 2538c2ecf20Sopenharmony_ci if (ret) 2548c2ecf20Sopenharmony_ci goto err; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* Enable pci core retry fix on Hainan (5213A) and later chips */ 2578c2ecf20Sopenharmony_ci if (srev >= AR5K_SREV_AR5213A) 2588c2ecf20Sopenharmony_ci AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_RETRY_FIX); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci /* 2618c2ecf20Sopenharmony_ci * Get card capabilities, calibration values etc 2628c2ecf20Sopenharmony_ci * TODO: EEPROM work 2638c2ecf20Sopenharmony_ci */ 2648c2ecf20Sopenharmony_ci ret = ath5k_eeprom_init(ah); 2658c2ecf20Sopenharmony_ci if (ret) { 2668c2ecf20Sopenharmony_ci ATH5K_ERR(ah, "unable to init EEPROM\n"); 2678c2ecf20Sopenharmony_ci goto err; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci ee = &ah->ah_capabilities.cap_eeprom; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci /* 2738c2ecf20Sopenharmony_ci * Write PCI-E power save settings 2748c2ecf20Sopenharmony_ci */ 2758c2ecf20Sopenharmony_ci if ((ah->ah_version == AR5K_AR5212) && pdev && (pci_is_pcie(pdev))) { 2768c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); 2778c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* Shut off RX when elecidle is asserted */ 2808c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES); 2818c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* If serdes programming is enabled, increase PCI-E 2848c2ecf20Sopenharmony_ci * tx power for systems with long trace from host 2858c2ecf20Sopenharmony_ci * to minicard connector. */ 2868c2ecf20Sopenharmony_ci if (ee->ee_serdes) 2878c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES); 2888c2ecf20Sopenharmony_ci else 2898c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0xf6800579, AR5K_PCIE_SERDES); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* Shut off PLL and CLKREQ active in L1 */ 2928c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* Preserve other settings */ 2958c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES); 2968c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES); 2978c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci /* Reset SERDES to load new settings */ 3008c2ecf20Sopenharmony_ci ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET); 3018c2ecf20Sopenharmony_ci usleep_range(1000, 1500); 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci /* Get misc capabilities */ 3058c2ecf20Sopenharmony_ci ret = ath5k_hw_set_capabilities(ah); 3068c2ecf20Sopenharmony_ci if (ret) { 3078c2ecf20Sopenharmony_ci ATH5K_ERR(ah, "unable to get device capabilities\n"); 3088c2ecf20Sopenharmony_ci goto err; 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci /* Crypto settings */ 3128c2ecf20Sopenharmony_ci common->keymax = (ah->ah_version == AR5K_AR5210 ? 3138c2ecf20Sopenharmony_ci AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci if (srev >= AR5K_SREV_AR5212_V4 && 3168c2ecf20Sopenharmony_ci (ee->ee_version < AR5K_EEPROM_VERSION_5_0 || 3178c2ecf20Sopenharmony_ci !AR5K_EEPROM_AES_DIS(ee->ee_misc5))) 3188c2ecf20Sopenharmony_ci common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci if (srev >= AR5K_SREV_AR2414) { 3218c2ecf20Sopenharmony_ci common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; 3228c2ecf20Sopenharmony_ci AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE, 3238c2ecf20Sopenharmony_ci AR5K_MISC_MODE_COMBINED_MIC); 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* MAC address is cleared until add_interface */ 3278c2ecf20Sopenharmony_ci ath5k_hw_set_lladdr(ah, zero_mac); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ 3308c2ecf20Sopenharmony_ci eth_broadcast_addr(common->curbssid); 3318c2ecf20Sopenharmony_ci ath5k_hw_set_bssid(ah); 3328c2ecf20Sopenharmony_ci ath5k_hw_set_opmode(ah, ah->opmode); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci ath5k_hw_rfgain_opt_init(ah); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci ath5k_hw_init_nfcal_hist(ah); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* turn on HW LEDs */ 3398c2ecf20Sopenharmony_ci ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci return 0; 3428c2ecf20Sopenharmony_cierr: 3438c2ecf20Sopenharmony_ci return ret; 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci/** 3478c2ecf20Sopenharmony_ci * ath5k_hw_deinit() - Free the &struct ath5k_hw 3488c2ecf20Sopenharmony_ci * @ah: The &struct ath5k_hw 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_civoid ath5k_hw_deinit(struct ath5k_hw *ah) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci __set_bit(ATH_STAT_INVALID, ah->status); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci kfree(ah->ah_rf_banks); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci ath5k_eeprom_detach(ah); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci /* assume interrupts are down */ 3598c2ecf20Sopenharmony_ci} 360