new file mode 100644
@@ -0,0 +1,390 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/* Copyright(c) 2019-2022, Celeno Communications Ltd. */
+
+#ifndef CL_CALIB_H
+#define CL_CALIB_H
+
+#include <linux/workqueue.h>
+#include <net/cfg80211.h>
+
+#include "def.h"
+
+#define DCOC_LNA_GAIN_NUM 8
+#define MAX_SX 2
+#define IQ_NUM_TONES_REQ 8
+#define IQ_NUM_TONES_CFM (2 * IQ_NUM_TONES_REQ)
+#define SINGLETONS_MAX_NUM 1
+#define LOOPS_MAX_NUM (2 + SINGLETONS_MAX_NUM) /* 1: pre,2-11:singletone,12:post */
+#define SX_FREQ_OFFSET_Q2 5
+
+enum calib_cfm_id_type {
+ CALIB_CFM_DCOC,
+ CALIB_CFM_IQ,
+ CALIB_CFM_MAX
+};
+
+enum calib_channel_idx_24g {
+ CALIB_CHAN_24G_1,
+ CALIB_CHAN_24G_6,
+ CALIB_CHAN_24G_11,
+ CALIB_CHAN_24G_MAX,
+};
+
+enum calib_channel_idx_5g {
+ CALIB_CHAN_5G_36,
+ CALIB_CHAN_5G_40,
+ CALIB_CHAN_5G_44,
+ CALIB_CHAN_5G_48,
+ CALIB_CHAN_5G_52,
+ CALIB_CHAN_5G_56,
+ CALIB_CHAN_5G_60,
+ CALIB_CHAN_5G_64,
+ CALIB_CHAN_5G_100,
+ CALIB_CHAN_5G_104,
+ CALIB_CHAN_5G_108,
+ CALIB_CHAN_5G_112,
+ CALIB_CHAN_5G_116,
+ CALIB_CHAN_5G_120,
+ CALIB_CHAN_5G_124,
+ CALIB_CHAN_5G_128,
+ CALIB_CHAN_5G_132,
+ CALIB_CHAN_5G_136,
+ CALIB_CHAN_5G_140,
+ CALIB_CHAN_5G_144,
+ CALIB_CHAN_5G_149,
+ CALIB_CHAN_5G_153,
+ CALIB_CHAN_5G_157,
+ CALIB_CHAN_5G_161,
+ CALIB_CHAN_5G_165,
+ CALIB_CHAN_5G_MAX
+};
+
+enum calib_channel_idx_6g {
+ CALIB_CHAN_6G_1,
+ CALIB_CHAN_6G_5,
+ CALIB_CHAN_6G_9,
+ CALIB_CHAN_6G_13,
+ CALIB_CHAN_6G_17,
+ CALIB_CHAN_6G_21,
+ CALIB_CHAN_6G_25,
+ CALIB_CHAN_6G_29,
+ CALIB_CHAN_6G_33,
+ CALIB_CHAN_6G_37,
+ CALIB_CHAN_6G_41,
+ CALIB_CHAN_6G_45,
+ CALIB_CHAN_6G_49,
+ CALIB_CHAN_6G_53,
+ CALIB_CHAN_6G_57,
+ CALIB_CHAN_6G_61,
+ CALIB_CHAN_6G_65,
+ CALIB_CHAN_6G_69,
+ CALIB_CHAN_6G_73,
+ CALIB_CHAN_6G_77,
+ CALIB_CHAN_6G_81,
+ CALIB_CHAN_6G_85,
+ CALIB_CHAN_6G_89,
+ CALIB_CHAN_6G_93,
+ CALIB_CHAN_6G_97,
+ CALIB_CHAN_6G_101,
+ CALIB_CHAN_6G_105,
+ CALIB_CHAN_6G_109,
+ CALIB_CHAN_6G_113,
+ CALIB_CHAN_6G_117,
+ CALIB_CHAN_6G_121,
+ CALIB_CHAN_6G_125,
+ CALIB_CHAN_6G_129,
+ CALIB_CHAN_6G_133,
+ CALIB_CHAN_6G_137,
+ CALIB_CHAN_6G_141,
+ CALIB_CHAN_6G_145,
+ CALIB_CHAN_6G_149,
+ CALIB_CHAN_6G_153,
+ CALIB_CHAN_6G_157,
+ CALIB_CHAN_6G_161,
+ CALIB_CHAN_6G_165,
+ CALIB_CHAN_6G_169,
+ CALIB_CHAN_6G_173,
+ CALIB_CHAN_6G_177,
+ CALIB_CHAN_6G_181,
+ CALIB_CHAN_6G_185,
+ CALIB_CHAN_6G_189,
+ CALIB_CHAN_6G_193,
+ CALIB_CHAN_6G_197,
+ CALIB_CHAN_6G_201,
+ CALIB_CHAN_6G_205,
+ CALIB_CHAN_6G_209,
+ CALIB_CHAN_6G_213,
+ CALIB_CHAN_6G_217,
+ CALIB_CHAN_6G_221,
+ CALIB_CHAN_6G_225,
+ CALIB_CHAN_6G_229,
+ CALIB_CHAN_6G_233,
+ CALIB_CHAN_6G_MAX,
+};
+
+/* MAX(CALIB_CHAN_24G_MAX, CALIB_CHAN_5G_MAX, CALIB_CHAN_6G_MAX) */
+#define CALIB_CHAN_MAX CALIB_CHAN_6G_MAX
+
+struct cl_dcoc_calib {
+ s8 i;
+ s8 q;
+};
+
+struct cl_dcoc_report {
+ __le16 i_dc;
+ __le16 i_iterations;
+ __le16 q_dc;
+ __le16 q_iterations;
+};
+
+struct cl_iq_report {
+ u8 status;
+ __le16 amplitude_mismatch[IQ_NUM_TONES_CFM];
+ __le16 phase_mismatch[IQ_NUM_TONES_CFM];
+ s8 ir_db[LOOPS_MAX_NUM][IQ_NUM_TONES_CFM];
+ s8 ir_db_avg_post;
+};
+
+struct cl_iq_calib {
+ __le32 coef0;
+ __le32 coef1;
+ __le32 coef2;
+ __le32 gain;
+};
+
+struct cl_lolc_report {
+ u8 status;
+ u8 n_iter;
+ __le16 lolc_qual;
+};
+
+struct cl_gain_report {
+ u8 status;
+ u8 rx_gain;
+ u8 tx_gain;
+ u8 gain_quality;
+ __le16 final_p2p;
+ __le16 initial_p2p;
+};
+
+struct cl_iq_dcoc_conf {
+ bool dcoc_calib_needed[TCV_MAX];
+ u8 dcoc_file_num_ant[TCV_MAX];
+ bool iq_calib_needed;
+ u8 iq_file_num_ant[TCV_MAX];
+ bool force_calib;
+};
+
+struct cl_iq_dcoc_info {
+ struct cl_dcoc_calib dcoc[DCOC_LNA_GAIN_NUM][MAX_ANTENNAS];
+ struct cl_iq_calib iq_tx[MAX_ANTENNAS];
+ __le32 iq_tx_lolc[MAX_ANTENNAS];
+ struct cl_iq_calib iq_rx[MAX_ANTENNAS];
+};
+
+struct cl_iq_dcoc_report {
+ struct cl_dcoc_report dcoc[DCOC_LNA_GAIN_NUM][MAX_ANTENNAS];
+ struct cl_gain_report gain_tx[MAX_ANTENNAS];
+ struct cl_gain_report gain_rx[MAX_ANTENNAS];
+ struct cl_lolc_report lolc_report[MAX_ANTENNAS];
+ struct cl_iq_report iq_tx[MAX_ANTENNAS];
+ struct cl_iq_report iq_rx[MAX_ANTENNAS];
+};
+
+struct calib_cfm {
+ u8 status;
+ __le16 raw_bits_data_0;
+ __le16 raw_bits_data_1;
+};
+
+struct cl_iq_dcoc_data {
+ struct cl_iq_dcoc_info iq_dcoc_db;
+ struct cl_iq_dcoc_report report;
+ struct calib_cfm dcoc_iq_cfm[CALIB_CFM_MAX];
+};
+
+struct cl_iq_dcoc_data_info {
+ struct cl_iq_dcoc_data *iq_dcoc_data;
+ u32 dma_addr;
+};
+
+struct cl_calib_params {
+ u8 mode;
+ bool first_channel;
+ s8 sx_freq_offset_mhz;
+ u32 plan_bitmap;
+};
+
+struct cl_calib_work {
+ struct work_struct ws;
+ struct cl_hw *cl_hw;
+};
+
+struct cl_calib_chain {
+ u8 pair;
+ u8 initial_tx_gain;
+ u8 initial_rx_gain;
+};
+
+enum cl_calib_flags {
+ CALIB_FLAG_CREATE = 1 << 0,
+ CALIB_FLAG_VERSION = 1 << 1,
+ CALIB_FLAG_TITLE = 1 << 2,
+ CALIB_FLAG_HEADER_TCV0 = 1 << 3,
+ CALIB_FLAG_HEADER_TCV1 = 1 << 4,
+
+ CALIB_FLAG_HEADER_TCV01 = (CALIB_FLAG_HEADER_TCV0 |
+ CALIB_FLAG_HEADER_TCV1),
+ CALIB_FLAG_ALL_REPORT = (CALIB_FLAG_CREATE |
+ CALIB_FLAG_VERSION |
+ CALIB_FLAG_TITLE),
+ CALIB_FLAG_ALL = (CALIB_FLAG_CREATE |
+ CALIB_FLAG_VERSION |
+ CALIB_FLAG_TITLE |
+ CALIB_FLAG_HEADER_TCV0 |
+ CALIB_FLAG_HEADER_TCV1)
+};
+
+struct cl_calib_file_flags {
+ u8 dcoc;
+ u8 dcoc_report;
+ u8 lolc;
+ u8 lolc_report;
+ u8 iq_tx;
+ u8 iq_tx_report;
+ u8 iq_rx;
+ u8 iq_rx_report;
+ u8 rx_gain_report;
+ bool iq_plan;
+};
+
+struct cl_calib_errors {
+ u16 dcoc;
+ u16 lolc;
+ u16 iq_tx;
+ u16 iq_rx;
+};
+
+struct cl_calib_db {
+ struct cl_dcoc_calib
+ dcoc[TCV_MAX][CALIB_CHAN_MAX][CHNL_BW_MAX][MAX_SX][MAX_ANTENNAS][DCOC_LNA_GAIN_NUM];
+ u32 iq_tx_lolc[TCV_MAX][CALIB_CHAN_MAX][CHNL_BW_MAX][MAX_SX][MAX_ANTENNAS];
+ struct cl_iq_calib iq_tx[TCV_MAX][CALIB_CHAN_MAX][CHNL_BW_MAX][MAX_SX][MAX_ANTENNAS];
+ struct cl_iq_calib iq_rx[TCV_MAX][CALIB_CHAN_MAX][CHNL_BW_MAX][MAX_SX][MAX_ANTENNAS];
+ struct cl_calib_file_flags file_flags;
+ struct cl_calib_errors errors[TCV_MAX];
+ struct list_head plan[TCV_MAX][CALIB_CHAN_MAX][CHNL_BW_MAX];
+ bool is_plan_initialized;
+};
+
+#define SET_PHY_DATA_FLAGS_DCOC 0x1 /* Set DCOC calibration data.*/
+#define SET_PHY_DATA_FLAGS_IQ_TX 0x2 /* Set IQ Tx calibration data.*/
+#define SET_PHY_DATA_FLAGS_IQ_RX 0x4 /* Set IQ Rx calibration data.*/
+#define SET_PHY_DATA_FLAGS_IQ_TX_LOLC 0x8 /* Set IQ Tx LOLC calibration data.*/
+#define SET_PHY_DATA_FLAGS_ALL ( \
+ SET_PHY_DATA_FLAGS_DCOC | \
+ SET_PHY_DATA_FLAGS_IQ_TX | \
+ SET_PHY_DATA_FLAGS_IQ_RX | \
+ SET_PHY_DATA_FLAGS_IQ_TX_LOLC)
+#define SET_PHY_DATA_FLAGS_LISTENER ( \
+ SET_PHY_DATA_FLAGS_DCOC | \
+ SET_PHY_DATA_FLAGS_IQ_RX)
+
+#define CL_CALIB_PARAMS_DEFAULT_STRUCT \
+ ((struct cl_calib_params){SET_CHANNEL_MODE_OPERETIONAL, false, 0, 0})
+
+#define CALIB_CHAN_5G_PLAN 6
+#define CALIB_CHAN_6G_PLAN 15
+
+struct cl_chip;
+
+void cl_calib_dcoc_init_calibration(struct cl_hw *cl_hw);
+u8 cl_calib_dcoc_channel_bw_to_idx(struct cl_hw *cl_hw, u8 channel, u8 bw);
+void cl_calib_dcoc_fill_data(struct cl_hw *cl_hw, struct cl_iq_dcoc_info *iq_dcoc_db);
+u8 cl_calib_dcoc_tcv_channel_to_idx(struct cl_chip *chip, u8 tcv_idx, u8 channel, u8 bw);
+void cl_calib_dcoc_handle_set_channel_cfm(struct cl_hw *cl_hw, bool first_channel);
+void cl_calib_common_start_work(struct cl_hw *cl_hw);
+void cl_calib_common_fill_phy_data(struct cl_hw *cl_hw, struct cl_iq_dcoc_info *iq_dcoc_db,
+ u8 flags);
+int cl_calib_common_tables_alloc(struct cl_hw *cl_hw);
+void cl_calib_common_tables_free(struct cl_hw *cl_hw);
+int cl_calib_common_handle_set_channel_cfm(struct cl_hw *cl_hw,
+ struct cl_calib_params calib_params);
+int cl_calib_common_check_errors(struct cl_hw *cl_hw);
+s16 cl_calib_common_get_temperature(struct cl_hw *cl_hw, u8 cfm_type);
+
+/* Calibration constants */
+#define CALIB_TX_GAIN_DEFAULT (0x75)
+#define GAIN_SLEEVE_TRSHLD_DEFAULT (2)
+#define CALIB_NCO_AMP_DEFAULT (-10)
+#define CALIB_NCO_FREQ_DEFAULT (16) /* 5M/312.5K for LO & RGC */
+#define LO_P_THRESH (1000000)
+#define N_SAMPLES_EXP_LOLC (13)
+#define N_SAMPLES_EXP_IQC (13)
+#define N_BIT_FIR_SCALE (11)
+#define N_BIT_AMP_SCALE (10)
+#define N_BIT_PHASE_SCALE (10)
+#define GP_RAD_TRSHLD_DEFAULT (1144) /* Represents 1 degree in Q(16,16): 1*(pi/180) */
+#define GA_LIN_UPPER_TRSHLD_DEFAULT (66295) /* Represents 0.1 db in Q(16,16): 10^( 0.1/20)*2^16 */
+#define GA_LIN_LOWER_TRSHLD_DEFAULT (64786) /* Represents -0.1 db in Q(16,16): 10^(-0.1/20)*2^16 */
+#define COMP_FILTER_LEN_DEFAULT (9)
+#define SINGLETONS_NUM_DEFAULT (10) /* Set to SINGLETONS_MAX_NUM for now */
+#define IQ_POST_IDX (LOOPS_MAX_NUM - 1)
+#define RAMPUP_TIME (50)
+#define LO_COARSE_STEP (20)
+#define LO_FINE_STEP (1)
+
+#define DCOC_MAX_VGA 0x14
+#define CALIB_RX_GAIN_DEFAULT 0x83
+#define CALIB_RX_GAIN_UPPER_LIMIT 0x14
+#define CALIB_RX_GAIN_LOWER_LIMIT 0x0
+#define DCOC_MAX_VGA_ATHOS 0x1E
+#define CALIB_RX_GAIN_DEFAULT_ATHOS 0x8D
+#define CALIB_RX_GAIN_UPPER_LIMIT_ATHOS 0x1E
+#define CALIB_RX_GAIN_LOWER_LIMIT_ATHOS 0x0A
+#define DCOC_MAX_VGA_ATHOS_B 0x14
+#define CALIB_RX_GAIN_DEFAULT_ATHOS_B 0x81
+#define CALIB_RX_GAIN_UPPER_LIMIT_ATHOS_B 0x14
+#define CALIB_RX_GAIN_LOWER_LIMIT_ATHOS_B 0x0
+
+struct cl_calib_iq_restore {
+ u8 bw;
+ u32 primary;
+ u32 center;
+ u8 channel;
+};
+
+bool cl_calib_iq_calibration_needed(struct cl_hw *cl_hw);
+void cl_calib_iq_file_flags_clear(struct cl_chip *chip);
+void cl_calib_iq_file_flags_set(struct cl_chip *chip);
+int cl_calib_iq_post_read_actions(struct cl_chip *chip, char *buf);
+void cl_calib_iq_init_calibration(struct cl_hw *cl_hw);
+void cl_calib_iq_fill_data(struct cl_hw *cl_hw, struct cl_iq_calib *iq_data,
+ struct cl_iq_calib *iq_chip_data);
+void cl_calib_iq_lolc_fill_data(struct cl_hw *cl_hw, __le32 *iq_lolc);
+void cl_calib_iq_handle_set_channel_cfm(struct cl_hw *cl_hw, u8 plan_bitmap);
+void cl_calib_iq_lolc_handle_set_channel_cfm(struct cl_hw *cl_hw, u8 plan_bitmap);
+int cl_calib_iq_lolc_write_version(struct cl_hw *cl_hw);
+int cl_calib_iq_lolc_report_write_version(struct cl_hw *cl_hw);
+int cl_calib_iq_lolc_write_file(struct cl_hw *cl_hw, s32 *params);
+int cl_calib_iq_lolc_report_write_file(struct cl_hw *cl_hw, s32 *params);
+void cl_calib_iq_get_tone_vector(struct cl_hw *cl_hw, __le16 *tone_vector);
+void cl_calib_iq_init_production(struct cl_hw *cl_hw);
+int cl_calib_iq_set_idle(struct cl_hw *cl_hw, bool idle);
+void cl_calib_restore_channel(struct cl_hw *cl_hw, struct cl_calib_iq_restore *iq_restore);
+void cl_calib_save_channel(struct cl_hw *cl_hw, struct cl_calib_iq_restore *iq_restore);
+
+#define UNCALIBRATED_POWER 15
+#define UNCALIBRATED_POWER_OFFSET 0
+#define UNCALIBRATED_TEMPERATURE 35
+
+struct point;
+void cl_calib_power_read(struct cl_hw *cl_hw);
+void cl_calib_power_offset_fill(struct cl_hw *cl_hw, u8 channel,
+ u8 bw, u8 offset[MAX_ANTENNAS]);
+int cl_calib_runtime_and_switch_channel(struct cl_hw *cl_hw, u32 channel, u8 bw, u32 primary,
+ u32 center);
+void cl_calib_runtime_work(struct cl_hw *cl_hw, u32 channel, u8 bw, u16 primary, u16 center);
+bool cl_calib_runtime_is_allowed(struct cl_hw *cl_hw);
+
+#endif /* CL_CALIB_H */