162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* ZD1211 USB-WLAN driver for Linux 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de> 562306a36Sopenharmony_ci * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/errno.h> 962306a36Sopenharmony_ci#include <linux/string.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "zd_def.h" 1262306a36Sopenharmony_ci#include "zd_rf.h" 1362306a36Sopenharmony_ci#include "zd_mac.h" 1462306a36Sopenharmony_ci#include "zd_chip.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic const char * const rfs[] = { 1762306a36Sopenharmony_ci [0] = "unknown RF0", 1862306a36Sopenharmony_ci [1] = "unknown RF1", 1962306a36Sopenharmony_ci [UW2451_RF] = "UW2451_RF", 2062306a36Sopenharmony_ci [UCHIP_RF] = "UCHIP_RF", 2162306a36Sopenharmony_ci [AL2230_RF] = "AL2230_RF", 2262306a36Sopenharmony_ci [AL7230B_RF] = "AL7230B_RF", 2362306a36Sopenharmony_ci [THETA_RF] = "THETA_RF", 2462306a36Sopenharmony_ci [AL2210_RF] = "AL2210_RF", 2562306a36Sopenharmony_ci [MAXIM_NEW_RF] = "MAXIM_NEW_RF", 2662306a36Sopenharmony_ci [UW2453_RF] = "UW2453_RF", 2762306a36Sopenharmony_ci [AL2230S_RF] = "AL2230S_RF", 2862306a36Sopenharmony_ci [RALINK_RF] = "RALINK_RF", 2962306a36Sopenharmony_ci [INTERSIL_RF] = "INTERSIL_RF", 3062306a36Sopenharmony_ci [RF2959_RF] = "RF2959_RF", 3162306a36Sopenharmony_ci [MAXIM_NEW2_RF] = "MAXIM_NEW2_RF", 3262306a36Sopenharmony_ci [PHILIPS_RF] = "PHILIPS_RF", 3362306a36Sopenharmony_ci}; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ciconst char *zd_rf_name(u8 type) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci if (type & 0xf0) 3862306a36Sopenharmony_ci type = 0; 3962306a36Sopenharmony_ci return rfs[type]; 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_civoid zd_rf_init(struct zd_rf *rf) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci memset(rf, 0, sizeof(*rf)); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci /* default to update channel integration, as almost all RF's do want 4762306a36Sopenharmony_ci * this */ 4862306a36Sopenharmony_ci rf->update_channel_int = 1; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_civoid zd_rf_clear(struct zd_rf *rf) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci if (rf->clear) 5462306a36Sopenharmony_ci rf->clear(rf); 5562306a36Sopenharmony_ci ZD_MEMCLEAR(rf, sizeof(*rf)); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ciint zd_rf_init_hw(struct zd_rf *rf, u8 type) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci int r = 0; 6162306a36Sopenharmony_ci int t; 6262306a36Sopenharmony_ci struct zd_chip *chip = zd_rf_to_chip(rf); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci ZD_ASSERT(mutex_is_locked(&chip->mutex)); 6562306a36Sopenharmony_ci switch (type) { 6662306a36Sopenharmony_ci case RF2959_RF: 6762306a36Sopenharmony_ci r = zd_rf_init_rf2959(rf); 6862306a36Sopenharmony_ci break; 6962306a36Sopenharmony_ci case AL2230_RF: 7062306a36Sopenharmony_ci case AL2230S_RF: 7162306a36Sopenharmony_ci r = zd_rf_init_al2230(rf); 7262306a36Sopenharmony_ci break; 7362306a36Sopenharmony_ci case AL7230B_RF: 7462306a36Sopenharmony_ci r = zd_rf_init_al7230b(rf); 7562306a36Sopenharmony_ci break; 7662306a36Sopenharmony_ci case MAXIM_NEW_RF: 7762306a36Sopenharmony_ci case UW2453_RF: 7862306a36Sopenharmony_ci r = zd_rf_init_uw2453(rf); 7962306a36Sopenharmony_ci break; 8062306a36Sopenharmony_ci default: 8162306a36Sopenharmony_ci dev_err(zd_chip_dev(chip), 8262306a36Sopenharmony_ci "RF %s %#x is not supported\n", zd_rf_name(type), type); 8362306a36Sopenharmony_ci rf->type = 0; 8462306a36Sopenharmony_ci return -ENODEV; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (r) 8862306a36Sopenharmony_ci return r; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci rf->type = type; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci r = zd_chip_lock_phy_regs(chip); 9362306a36Sopenharmony_ci if (r) 9462306a36Sopenharmony_ci return r; 9562306a36Sopenharmony_ci t = rf->init_hw(rf); 9662306a36Sopenharmony_ci r = zd_chip_unlock_phy_regs(chip); 9762306a36Sopenharmony_ci if (t) 9862306a36Sopenharmony_ci r = t; 9962306a36Sopenharmony_ci return r; 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ciint zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci return scnprintf(buffer, size, "%s", zd_rf_name(rf->type)); 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciint zd_rf_set_channel(struct zd_rf *rf, u8 channel) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci int r; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex)); 11262306a36Sopenharmony_ci if (channel < MIN_CHANNEL24) 11362306a36Sopenharmony_ci return -EINVAL; 11462306a36Sopenharmony_ci if (channel > MAX_CHANNEL24) 11562306a36Sopenharmony_ci return -EINVAL; 11662306a36Sopenharmony_ci dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci r = rf->set_channel(rf, channel); 11962306a36Sopenharmony_ci if (r >= 0) 12062306a36Sopenharmony_ci rf->channel = channel; 12162306a36Sopenharmony_ci return r; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciint zd_switch_radio_on(struct zd_rf *rf) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci int r, t; 12762306a36Sopenharmony_ci struct zd_chip *chip = zd_rf_to_chip(rf); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci ZD_ASSERT(mutex_is_locked(&chip->mutex)); 13062306a36Sopenharmony_ci r = zd_chip_lock_phy_regs(chip); 13162306a36Sopenharmony_ci if (r) 13262306a36Sopenharmony_ci return r; 13362306a36Sopenharmony_ci t = rf->switch_radio_on(rf); 13462306a36Sopenharmony_ci r = zd_chip_unlock_phy_regs(chip); 13562306a36Sopenharmony_ci if (t) 13662306a36Sopenharmony_ci r = t; 13762306a36Sopenharmony_ci return r; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ciint zd_switch_radio_off(struct zd_rf *rf) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci int r, t; 14362306a36Sopenharmony_ci struct zd_chip *chip = zd_rf_to_chip(rf); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci /* TODO: move phy regs handling to zd_chip */ 14662306a36Sopenharmony_ci ZD_ASSERT(mutex_is_locked(&chip->mutex)); 14762306a36Sopenharmony_ci r = zd_chip_lock_phy_regs(chip); 14862306a36Sopenharmony_ci if (r) 14962306a36Sopenharmony_ci return r; 15062306a36Sopenharmony_ci t = rf->switch_radio_off(rf); 15162306a36Sopenharmony_ci r = zd_chip_unlock_phy_regs(chip); 15262306a36Sopenharmony_ci if (t) 15362306a36Sopenharmony_ci r = t; 15462306a36Sopenharmony_ci return r; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ciint zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci if (!rf->patch_6m_band_edge) 16062306a36Sopenharmony_ci return 0; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci return rf->patch_6m_band_edge(rf, channel); 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ciint zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci return zd_chip_generic_patch_6m_band(zd_rf_to_chip(rf), channel); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 170