diff mbox series

[RFC,v1,098/256] cl8k: add hw.c

Message ID 20210617160223.160998-99-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:59 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/hw.c | 166 ++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/hw.c

--
2.30.0
diff mbox series

Patch

diff --git a/drivers/net/wireless/celeno/cl8k/hw.c b/drivers/net/wireless/celeno/cl8k/hw.c
new file mode 100644
index 000000000000..0f7e7dcc659d
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/hw.c
@@ -0,0 +1,166 @@ 
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include "hw.h"
+#include "rate_ctrl.h"
+#include <linux/spinlock.h>
+#include "reg/reg_access.h"
+
+static void cl_hw_init_tcv0(struct cl_hw *cl_hw)
+{
+       struct cl_controller_reg *controller_reg = &cl_hw->controller_reg;
+
+       cl_hw->fw_dst_kern_id = KERN_LMAC;
+       cl_hw->fw_prefix = 'l';
+
+       controller_reg->breset = LMAC_BRESET;
+       controller_reg->debug_enable = LMAC_DEBUG_ENABLE;
+       controller_reg->dreset = LMAC_DRESET;
+       controller_reg->ocd_halt_on_reset = LMAC_OCD_HALT_ON_RESET;
+       controller_reg->run_stall = LMAC_RUN_STALL;
+
+       cl_hw->mac_hw_regs_offset = 0;
+       cl_hw->phy_regs_offset = 0;
+}
+
+static void cl_hw_init_tcv1(struct cl_hw *cl_hw)
+{
+       struct cl_controller_reg *controller_reg = &cl_hw->controller_reg;
+
+       cl_hw->fw_dst_kern_id = KERN_SMAC;
+       cl_hw->fw_prefix = 's';
+
+       controller_reg->breset = SMAC_BRESET;
+       controller_reg->debug_enable = SMAC_DEBUG_ENABLE;
+       controller_reg->dreset = SMAC_DRESET;
+       controller_reg->ocd_halt_on_reset = SMAC_OCD_HALT_ON_RESET;
+       controller_reg->run_stall = SMAC_RUN_STALL;
+
+       cl_hw->mac_hw_regs_offset = REG_MAC_HW_SMAC_OFFSET;
+       cl_hw->phy_regs_offset = REG_PHY_SMAC_OFFSET;
+}
+
+void cl_hw_init(struct cl_chip *chip, struct cl_hw *cl_hw, u8 tcv_idx)
+{
+       write_lock(&chip->cl_hw_lock);
+       chip->cl_hw_lut[tcv_idx] = cl_hw;
+       write_unlock(&chip->cl_hw_lock);
+
+       if (tcv_idx == TCV0)
+               cl_hw_init_tcv0(cl_hw);
+       else
+               cl_hw_init_tcv1(cl_hw);
+}
+
+void cl_hw_deinit(struct cl_hw *cl_hw, u8 tcv_idx)
+{
+       struct cl_chip *chip = cl_hw->chip;
+
+       write_lock(&chip->cl_hw_lock);
+       chip->cl_hw_lut[tcv_idx] = NULL;
+       write_unlock(&chip->cl_hw_lock);
+}
+
+void cl_hw_lock(struct cl_hw *cl_hw)
+{
+       read_lock(&cl_hw->chip->cl_hw_lock);
+}
+
+void cl_hw_unlock(struct cl_hw *cl_hw)
+{
+       read_unlock(&cl_hw->chip->cl_hw_lock);
+}
+
+struct cl_hw *cl_hw_other_tcv(struct cl_hw *cl_hw)
+{
+       /* This function must be called after read lock is taken */
+       return cl_hw->chip->cl_hw_lut[1 - cl_hw->tcv_idx];
+}
+
+bool cl_hw_is_tcv0(struct cl_hw *cl_hw)
+{
+       return (cl_hw->tcv_idx == TCV0);
+}
+
+bool cl_hw_is_tcv1(struct cl_hw *cl_hw)
+{
+       return (cl_hw->tcv_idx == TCV1);
+}
+
+int cl_hw_set_antennas(struct cl_hw *cl_hw)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       u8 ant_shift = cl_hw_ant_shift(cl_hw);
+
+       /* Set num_antennas and max_antennas + masks for both. */
+       switch (chip->fem.wiring_id) {
+       case FEM_WIRING_0_TCV0_6_TCV1_6:
+       case FEM_WIRING_1_TCV0_6_TCV1_6:
+       case FEM_WIRING_2_TCV0_6_TCV1_6:
+       case FEM_WIRING_3_TCV0_2_ELASTIC_4_TCV1_2:
+       case FEM_WIRING_4_TCV0_2_ELASTIC_4_TCV1_2:
+       case FEM_WIRING_5_TCV0_2_ELASTIC_4_TCV1_2:
+       case FEM_WIRING_6_TCV0_2_ELASTIC_4_TCV1_2:
+               cl_hw->max_antennas = 6;
+               break;
+       case FEM_WIRING_7_TCV0_4_TCV1_4:
+       case FEM_WIRING_8_TCV0_4_TCV1_4:
+       case FEM_WIRING_9_TCV0_4_TCV1_4:
+       case FEM_WIRING_10_TCV0_4_TCV1_4:
+       case FEM_WIRING_11_TCV0_4_TCV1_4_RX_ONLY:
+       case FEM_WIRING_12_TCV0_4_TCV1_4_RX_ONLY:
+       case FEM_WIRING_15_CHAMELEON_4TX_4RX:
+       case FEM_WIRING_18_TCV0_4_TCV1_4:
+       case FEM_WIRING_19_TCV0_2_TCV1_2_SWAPPED:
+               cl_hw->max_antennas = 4;
+               break;
+       case FEM_WIRING_13_SENSING_4RX_2TX:
+       case FEM_WIRING_14_SENSING_4TX_2RX:
+       case FEM_WIRING_20_TCV0_4_TCV1_2:
+       case FEM_WIRING_21_TCV0_4_TCV1_2:
+               cl_hw->max_antennas = cl_hw_is_tcv0(cl_hw) ? 4 : 2;
+               break;
+       case FEM_WIRING_17_TCV0_4_TCV1_0:
+               cl_hw->max_antennas = cl_hw_is_tcv0(cl_hw) ? 4 : 0;
+               break;
+       case FEM_WIRING_16_TCV0_2_TCV1_2:
+               cl_hw->max_antennas = 2;
+               break;
+       default:
+               if (chip->conf->ce_production_mode)
+                       cl_hw->max_antennas = chip->max_antennas / 2;
+               else
+                       return -1;
+               break;
+       }
+
+       cl_hw->num_antennas = cl_hw->conf->ce_num_antennas;
+       cl_hw->mask_num_antennas = ANT_MASK(cl_hw->num_antennas);
+       cl_hw->first_ant = ant_shift;
+       cl_hw->last_ant = cl_hw->num_antennas + ant_shift - 1;
+
+       cl_dbg_trace(cl_hw, "num_antennas = %u, max_antennas = %u\n",
+                    cl_hw->num_antennas, cl_hw->max_antennas);
+
+       if (cl_hw->num_antennas > cl_hw->max_antennas) {
+               CL_DBG_ERROR(cl_hw, "num_antennas (%u) > max_antennas (%u)\n",
+                            cl_hw->num_antennas, cl_hw->max_antennas);
+               return -1;
+       }
+
+       return 0;
+}
+
+u8 cl_hw_ant_shift(struct cl_hw *cl_hw)
+{
+       struct cl_chip *chip = cl_hw->chip;
+
+       /* CL808x uses chains 0 - 3 for both bands */
+       if (cl_chip_is_8ant(chip))
+               return 0;
+
+       /* CL804x uses chains 0 - 1 for TCV0 and chains 2 - 3 for TCV1 */
+       /* CL806x uses chains 0 - 3 for TCV0 and chains 2 - 3 for TCV1 */
+       return cl_hw_is_tcv0(cl_hw) ? 0 : 2;
+}
+