diff mbox series

[RFC,v1,036/256] cl8k: add chandef.c

Message ID 20210617160223.160998-37-viktor.barna@celeno.com (mailing list archive)
State RFC
Delegated to: Kalle Valo
Headers show
Series wireless: cl8k driver for Celeno IEEE 802.11ax devices | expand

Commit Message

Viktor Barna June 17, 2021, 3:58 p.m. UTC
From: Viktor Barna <viktor.barna@celeno.com>

(Part of the split. Please, take a look at the cover letter for more
details).

Signed-off-by: Viktor Barna <viktor.barna@celeno.com>
---
 drivers/net/wireless/celeno/cl8k/chandef.c | 152 +++++++++++++++++++++
 1 file changed, 152 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/chandef.c

--
2.30.0
diff mbox series

Patch

diff --git a/drivers/net/wireless/celeno/cl8k/chandef.c b/drivers/net/wireless/celeno/cl8k/chandef.c
new file mode 100644
index 000000000000..61e127386b32
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/chandef.c
@@ -0,0 +1,152 @@ 
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include "chandef.h"
+#include "band.h"
+#include "utils/utils.h"
+#include "chip.h"
+
+static int cl_chandef_calc_6g(struct cl_hw *cl_hw, u16 freq, u32 bw, u32 offset,
+                             u32 *primary, u32 *center)
+{
+       u32 bw_mhz = BW_TO_MHZ(bw);
+       u32 min_freq = 0;
+
+       if (freq == FREQ6G(2)) {
+               min_freq = FREQ6G(2);
+       } else if (freq >= FREQ6G(1) && freq <= FREQ6G(233)) {
+               min_freq = FREQ6G(1);
+       } else {
+               cl_dbg_err(cl_hw, "Invalid frequecy - %u\n", freq);
+               return -EINVAL;
+       }
+
+       *primary = freq - (freq - min_freq) % 20;
+       *center = *primary - (*primary - min_freq) % bw_mhz + offset;
+
+       return 0;
+}
+
+static int cl_chandef_calc_5g(struct cl_hw *cl_hw, u16 freq, u32 bw, u32 offset,
+                             u32 *primary, u32 *center)
+{
+       u32 bw_mhz = BW_TO_MHZ(bw);
+       u32 min_freq = 0;
+
+       if ((freq >= FREQ5G(36) && freq <= FREQ5G(64)) ||
+           (freq >= FREQ5G(100) && freq <= FREQ5G(144))) {
+               min_freq = FREQ5G(36);
+       } else if (freq >= FREQ5G(149) && freq <= FREQ5G(165)) {
+               min_freq = FREQ5G(149);
+       } else {
+               cl_dbg_err(cl_hw, "Invalid frequecy - %u\n", freq);
+               return -EINVAL;
+       }
+
+       *primary = freq - (freq - min_freq) % 20;
+       *center = *primary - (*primary - min_freq) % bw_mhz + offset;
+
+       return 0;
+}
+
+static int cl_chandef_calc_24g(struct cl_hw *cl_hw, u16 freq, u32 bw, u32 offset,
+                              u32 *primary, u32 *center)
+{
+       u32 min_freq = 0;
+
+       if (freq < FREQ2G(1) || freq > FREQ2G(14)) {
+               cl_dbg_err(cl_hw, "Invalid frequecy - %u\n", freq);
+               return -EINVAL;
+       }
+
+       min_freq = freq < FREQ2G(14) ? FREQ2G(1) : FREQ2G(14);
+       *primary = freq - (freq - min_freq) % 5;
+
+       if (bw == CHNL_BW_20) {
+               *center = *primary;
+       } else {
+               if (freq <= FREQ2G(4)) {
+                       /* Above extension channel */
+                       *center = *primary + offset;
+               } else if (freq >= FREQ2G(10)) {
+                       /* Below extension channel */
+                       *center = *primary - offset;
+               } else {
+                       /* Channels 5-9 must be below if channel 13 is not supported */
+                       if (!cl_chan_info_get(cl_hw, 13, CHNL_BW_20) &&
+                           /* For Calibration, when using 2.4GHz channels on TCV0 to set SX0. */
+                           !cl_chan_info_get(cl_hw->chip->cl_hw_tcv1, 13, CHNL_BW_20)) {
+                               *center = *primary - offset;
+                       } else {
+                               /* Set below/above according to NVRAM configuration */
+                               if (cl_hw->conf->ce_extension_channel == -1)
+                                       *center = *primary - offset;
+                               else
+                                       *center = *primary + offset;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int cl_chandef_calc(struct cl_hw *cl_hw, u32 channel, u32 bw,
+                   enum nl80211_chan_width *width, u32 *primary, u32 *center)
+{
+       u16 freq = ieee80211_channel_to_frequency(channel, cl_hw->nl_band);
+       u32 offset = 0;
+       int ret = 0;
+
+       switch (bw) {
+       case CHNL_BW_20:
+               offset = 0;
+               if (channel == 14)
+                       *width = NL80211_CHAN_WIDTH_20_NOHT;
+               else
+                       *width = NL80211_CHAN_WIDTH_20;
+               break;
+       case CHNL_BW_40:
+               offset = 10;
+               *width = NL80211_CHAN_WIDTH_40;
+               break;
+       case CHNL_BW_80:
+               if (cl_band_is_24g(cl_hw)) {
+                       cl_dbg_err(cl_hw, "Invalid bandwidth - %u\n", bw);
+                       return -EINVAL;
+               }
+               offset = 30;
+               *width = NL80211_CHAN_WIDTH_80;
+               break;
+       case CHNL_BW_160:
+               if (cl_band_is_24g(cl_hw)) {
+                       cl_dbg_err(cl_hw, "Invalid bandwidth - %u\n", bw);
+                       return -EINVAL;
+               }
+               offset = 70;
+               *width = NL80211_CHAN_WIDTH_160;
+               break;
+       default:
+               cl_dbg_err(cl_hw, "Invalid bandwidth - %u\n", bw);
+               return -EINVAL;
+       }
+
+       if (cl_band_is_6g(cl_hw))
+               ret = cl_chandef_calc_6g(cl_hw, freq, bw, offset, primary, center);
+       else if (cl_band_is_5g(cl_hw))
+               ret = cl_chandef_calc_5g(cl_hw, freq, bw, offset, primary, center);
+       else
+               ret = cl_chandef_calc_24g(cl_hw, freq, bw, offset, primary, center);
+
+       cl_dbg_trace(cl_hw, "primary=%u center=%u\n", *primary, *center);
+
+       return ret;
+}
+
+int cl_chandef_get_default(struct cl_hw *cl_hw, enum nl80211_chan_width *width,
+                          u32 *primary, u32 *center)
+{
+       u32 bw = cl_hw->conf->ce_channel_bandwidth;
+       u32 channel = cl_hw->conf->ha_channel;
+
+       return cl_chandef_calc(cl_hw, channel, bw, width, primary, center);
+}