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