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