18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* ZD1211 USB-WLAN driver for Linux 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de> 58c2ecf20Sopenharmony_ci * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/errno.h> 98c2ecf20Sopenharmony_ci#include <linux/string.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "zd_def.h" 128c2ecf20Sopenharmony_ci#include "zd_rf.h" 138c2ecf20Sopenharmony_ci#include "zd_mac.h" 148c2ecf20Sopenharmony_ci#include "zd_chip.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic const char * const rfs[] = { 178c2ecf20Sopenharmony_ci [0] = "unknown RF0", 188c2ecf20Sopenharmony_ci [1] = "unknown RF1", 198c2ecf20Sopenharmony_ci [UW2451_RF] = "UW2451_RF", 208c2ecf20Sopenharmony_ci [UCHIP_RF] = "UCHIP_RF", 218c2ecf20Sopenharmony_ci [AL2230_RF] = "AL2230_RF", 228c2ecf20Sopenharmony_ci [AL7230B_RF] = "AL7230B_RF", 238c2ecf20Sopenharmony_ci [THETA_RF] = "THETA_RF", 248c2ecf20Sopenharmony_ci [AL2210_RF] = "AL2210_RF", 258c2ecf20Sopenharmony_ci [MAXIM_NEW_RF] = "MAXIM_NEW_RF", 268c2ecf20Sopenharmony_ci [UW2453_RF] = "UW2453_RF", 278c2ecf20Sopenharmony_ci [AL2230S_RF] = "AL2230S_RF", 288c2ecf20Sopenharmony_ci [RALINK_RF] = "RALINK_RF", 298c2ecf20Sopenharmony_ci [INTERSIL_RF] = "INTERSIL_RF", 308c2ecf20Sopenharmony_ci [RF2959_RF] = "RF2959_RF", 318c2ecf20Sopenharmony_ci [MAXIM_NEW2_RF] = "MAXIM_NEW2_RF", 328c2ecf20Sopenharmony_ci [PHILIPS_RF] = "PHILIPS_RF", 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ciconst char *zd_rf_name(u8 type) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci if (type & 0xf0) 388c2ecf20Sopenharmony_ci type = 0; 398c2ecf20Sopenharmony_ci return rfs[type]; 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_civoid zd_rf_init(struct zd_rf *rf) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci memset(rf, 0, sizeof(*rf)); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci /* default to update channel integration, as almost all RF's do want 478c2ecf20Sopenharmony_ci * this */ 488c2ecf20Sopenharmony_ci rf->update_channel_int = 1; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_civoid zd_rf_clear(struct zd_rf *rf) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci if (rf->clear) 548c2ecf20Sopenharmony_ci rf->clear(rf); 558c2ecf20Sopenharmony_ci ZD_MEMCLEAR(rf, sizeof(*rf)); 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ciint zd_rf_init_hw(struct zd_rf *rf, u8 type) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci int r = 0; 618c2ecf20Sopenharmony_ci int t; 628c2ecf20Sopenharmony_ci struct zd_chip *chip = zd_rf_to_chip(rf); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci ZD_ASSERT(mutex_is_locked(&chip->mutex)); 658c2ecf20Sopenharmony_ci switch (type) { 668c2ecf20Sopenharmony_ci case RF2959_RF: 678c2ecf20Sopenharmony_ci r = zd_rf_init_rf2959(rf); 688c2ecf20Sopenharmony_ci break; 698c2ecf20Sopenharmony_ci case AL2230_RF: 708c2ecf20Sopenharmony_ci case AL2230S_RF: 718c2ecf20Sopenharmony_ci r = zd_rf_init_al2230(rf); 728c2ecf20Sopenharmony_ci break; 738c2ecf20Sopenharmony_ci case AL7230B_RF: 748c2ecf20Sopenharmony_ci r = zd_rf_init_al7230b(rf); 758c2ecf20Sopenharmony_ci break; 768c2ecf20Sopenharmony_ci case MAXIM_NEW_RF: 778c2ecf20Sopenharmony_ci case UW2453_RF: 788c2ecf20Sopenharmony_ci r = zd_rf_init_uw2453(rf); 798c2ecf20Sopenharmony_ci break; 808c2ecf20Sopenharmony_ci default: 818c2ecf20Sopenharmony_ci dev_err(zd_chip_dev(chip), 828c2ecf20Sopenharmony_ci "RF %s %#x is not supported\n", zd_rf_name(type), type); 838c2ecf20Sopenharmony_ci rf->type = 0; 848c2ecf20Sopenharmony_ci return -ENODEV; 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (r) 888c2ecf20Sopenharmony_ci return r; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci rf->type = type; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci r = zd_chip_lock_phy_regs(chip); 938c2ecf20Sopenharmony_ci if (r) 948c2ecf20Sopenharmony_ci return r; 958c2ecf20Sopenharmony_ci t = rf->init_hw(rf); 968c2ecf20Sopenharmony_ci r = zd_chip_unlock_phy_regs(chip); 978c2ecf20Sopenharmony_ci if (t) 988c2ecf20Sopenharmony_ci r = t; 998c2ecf20Sopenharmony_ci return r; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ciint zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci return scnprintf(buffer, size, "%s", zd_rf_name(rf->type)); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ciint zd_rf_set_channel(struct zd_rf *rf, u8 channel) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci int r; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex)); 1128c2ecf20Sopenharmony_ci if (channel < MIN_CHANNEL24) 1138c2ecf20Sopenharmony_ci return -EINVAL; 1148c2ecf20Sopenharmony_ci if (channel > MAX_CHANNEL24) 1158c2ecf20Sopenharmony_ci return -EINVAL; 1168c2ecf20Sopenharmony_ci dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci r = rf->set_channel(rf, channel); 1198c2ecf20Sopenharmony_ci if (r >= 0) 1208c2ecf20Sopenharmony_ci rf->channel = channel; 1218c2ecf20Sopenharmony_ci return r; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ciint zd_switch_radio_on(struct zd_rf *rf) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci int r, t; 1278c2ecf20Sopenharmony_ci struct zd_chip *chip = zd_rf_to_chip(rf); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci ZD_ASSERT(mutex_is_locked(&chip->mutex)); 1308c2ecf20Sopenharmony_ci r = zd_chip_lock_phy_regs(chip); 1318c2ecf20Sopenharmony_ci if (r) 1328c2ecf20Sopenharmony_ci return r; 1338c2ecf20Sopenharmony_ci t = rf->switch_radio_on(rf); 1348c2ecf20Sopenharmony_ci r = zd_chip_unlock_phy_regs(chip); 1358c2ecf20Sopenharmony_ci if (t) 1368c2ecf20Sopenharmony_ci r = t; 1378c2ecf20Sopenharmony_ci return r; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ciint zd_switch_radio_off(struct zd_rf *rf) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci int r, t; 1438c2ecf20Sopenharmony_ci struct zd_chip *chip = zd_rf_to_chip(rf); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* TODO: move phy regs handling to zd_chip */ 1468c2ecf20Sopenharmony_ci ZD_ASSERT(mutex_is_locked(&chip->mutex)); 1478c2ecf20Sopenharmony_ci r = zd_chip_lock_phy_regs(chip); 1488c2ecf20Sopenharmony_ci if (r) 1498c2ecf20Sopenharmony_ci return r; 1508c2ecf20Sopenharmony_ci t = rf->switch_radio_off(rf); 1518c2ecf20Sopenharmony_ci r = zd_chip_unlock_phy_regs(chip); 1528c2ecf20Sopenharmony_ci if (t) 1538c2ecf20Sopenharmony_ci r = t; 1548c2ecf20Sopenharmony_ci return r; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ciint zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci if (!rf->patch_6m_band_edge) 1608c2ecf20Sopenharmony_ci return 0; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci return rf->patch_6m_band_edge(rf, channel); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ciint zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci return zd_chip_generic_patch_6m_band(zd_rf_to_chip(rf), channel); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 170