Search Linux Wireless

[RFC v1 071/256] cl8k: add ela.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Viktor Barna <viktor.barna@xxxxxxxxxx>

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

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

diff --git a/drivers/net/wireless/celeno/cl8k/ela.c b/drivers/net/wireless/celeno/cl8k/ela.c
new file mode 100644
index 000000000000..49f4d2d21054
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/ela.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2021, Celeno Communications Ltd. */
+
+#include "ela.h"
+#include "utils/file.h"
+#include "reg/reg_access.h"
+#include "reg/reg_lcu_common.h"
+#include "reg/reg_lcu_phy.h"
+
+#define CL_ELA_MODE_DFLT_ALIAS          "default"
+#define CL_ELA_MODE_DFLT_SYMB_LINK      "lcu_default.conf"
+#define CL_ELA_MODE_DFLT_OFF            "OFF"
+#define CL_ELA_LCU_CONF_TOKENS_CNT      3 /* cmd addr1 addr2 */
+#define CL_ELA_LCU_MEM_WRITE_CMD_STR    "mem_write"
+#define CL_ELA_LCU_MEM_WRITE_CMD_SZ     sizeof(CL_ELA_LCU_MEM_WRITE_CMD_STR)
+#define CL_ELA_LCU_UNKNOWN_CMD_TYPE     0
+#define CL_ELA_LCU_MEM_WRITE_CMD_TYPE   1
+#define CL_ELA_LCU_UNKNOWN_CMD_STR      "unknown"
+
+static int __must_check get_lcu_cmd_type(char *cmd)
+{
+       if (!strncmp(CL_ELA_LCU_MEM_WRITE_CMD_STR, cmd, CL_ELA_LCU_MEM_WRITE_CMD_SZ))
+               return CL_ELA_LCU_MEM_WRITE_CMD_TYPE;
+
+       return CL_ELA_LCU_UNKNOWN_CMD_TYPE;
+}
+
+static int add_lcu_cmd(struct cl_ela_db *ed, u32 type, u32 offset, u32 value)
+{
+       struct cl_lcu_cmd *cmd = NULL;
+
+       cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+       if (!cmd)
+               return -ENOMEM;
+
+       cmd->type = type;
+       cmd->offset = offset;
+       cmd->value = value;
+
+       list_add_tail(&cmd->cmd_list, &ed->cmd_head);
+
+       return 0;
+}
+
+static void remove_lcu_cmd(struct cl_lcu_cmd *cmd)
+{
+       list_del(&cmd->cmd_list);
+       kfree(cmd);
+}
+
+static void reset_stats(struct cl_ela_db *db)
+{
+       memset(&db->stats, 0, sizeof(db->stats));
+}
+
+static int load_cmds_from_buf(struct cl_chip *chip, char *buf, size_t size)
+{
+       struct cl_ela_db *ed = &chip->ela_db;
+       char *line = buf;
+       char cmd[STR_LEN_256B];
+       u32 type = CL_ELA_LCU_UNKNOWN_CMD_TYPE;
+       u32 offset = 0;
+       u32 value = 0;
+       int tokens_cnt = 0;
+       int ret = 0;
+
+       while (line && strlen(line) && (line != (buf + size))) {
+               if ((*line == '#') || (*line == '\n')) {
+                       /* Skip comment or blank line */
+                       line = strstr(line, "\n") + 1;
+               } else if (*line) {
+                       tokens_cnt = sscanf(line, "%s %x %x\n", cmd, &offset, &value);
+                       cl_dbg_chip_trace(chip,
+                                         "tokens(%d):cmd(%s), offset(0x%X), value(0x%X)\n",
+                                         tokens_cnt, cmd, offset, value);
+
+                       type = get_lcu_cmd_type(cmd);
+                       if (type == CL_ELA_LCU_UNKNOWN_CMD_TYPE) {
+                               cl_dbg_chip_trace(chip, "Detected extra token, skipping\n");
+                               goto newline;
+                       }
+                       if (tokens_cnt != CL_ELA_LCU_CONF_TOKENS_CNT) {
+                               cl_dbg_chip_err(chip,
+                                               "Tokens count is wrong! (%d != %d)\n",
+                                               CL_ELA_LCU_CONF_TOKENS_CNT,
+                                               tokens_cnt);
+                               ret = -EBADMSG;
+                               goto exit;
+                       }
+
+                       ret = add_lcu_cmd(ed, type, offset, value);
+                       if (ret)
+                               goto exit;
+
+newline:
+                       line = strstr(line, "\n") + 1;
+               }
+       }
+
+exit:
+       ed->stats.adaptations_cnt++;
+       return ret;
+}
+
+void cl_ela_lcu_reset(struct cl_chip *chip)
+{
+       lcu_common_sw_rst_set(chip, 0x1);
+       lcu_phy_lcu_sw_rst_set(chip->cl_hw_tcv0, 0x1);
+       lcu_phy_lcu_sw_rst_set(chip->cl_hw_tcv1, 0x1);
+}
+
+void cl_ela_lcu_apply_config(struct cl_chip *chip)
+{
+       struct cl_ela_db *ed = &chip->ela_db;
+       struct cl_lcu_cmd *cmd = NULL;
+
+       if (!cl_ela_lcu_is_valid_config(chip)) {
+               cl_dbg_chip_err(chip, "Active ELA LCU config is not valid\n");
+               return;
+       }
+
+       list_for_each_entry(cmd, &ed->cmd_head, cmd_list) {
+               cl_dbg_chip_info(chip, "Writing cmd (0x%X, 0x%X)\n",
+                                cmd->offset, cmd->value);
+               cl_reg_write_chip(chip, cmd->offset, cmd->value);
+       }
+       ed->stats.applications_cnt++;
+}
+
+bool cl_ela_is_on(struct cl_chip *chip)
+{
+       return !!strncmp(CL_ELA_MODE_DFLT_OFF, chip->conf->ce_ela_mode,
+                        sizeof(chip->conf->ce_ela_mode));
+}
+
+bool cl_ela_is_default(struct cl_chip *chip)
+{
+       return !strncmp(CL_ELA_MODE_DFLT_ALIAS, chip->conf->ce_ela_mode,
+                       sizeof(chip->conf->ce_ela_mode));
+}
+
+bool cl_ela_lcu_is_valid_config(struct cl_chip *chip)
+{
+       struct cl_ela_db *ed = &chip->ela_db;
+
+       return ed->error_state == 0;
+}
+
+char *cl_ela_lcu_cmd_str(u32 type)
+{
+       if (type == CL_ELA_LCU_MEM_WRITE_CMD_TYPE)
+               return CL_ELA_LCU_MEM_WRITE_CMD_STR;
+
+       return CL_ELA_LCU_UNKNOWN_CMD_STR;
+}
+
+char *cl_ela_lcu_config_name(struct cl_chip *chip)
+{
+       if (!cl_ela_is_on(chip))
+               return CL_ELA_MODE_DFLT_OFF;
+
+       if (cl_ela_is_default(chip))
+               return CL_ELA_MODE_DFLT_SYMB_LINK;
+
+       return chip->conf->ce_ela_mode;
+}
+
+int cl_ela_lcu_config_read(struct cl_chip *chip)
+{
+       struct cl_ela_db *ed = &chip->ela_db;
+       char filename[CL_FILENAME_MAX] = {0};
+       size_t size = 0;
+       int ret = 0;
+
+       if (!cl_ela_is_on(chip)) {
+               ret = -EOPNOTSUPP;
+               goto exit;
+       }
+
+       reset_stats(ed);
+
+       snprintf(filename, sizeof(filename), "%s", cl_ela_lcu_config_name(chip));
+       size = cl_file_open_and_read(chip, filename, &ed->raw_lcu_config);
+       if (!ed->raw_lcu_config) {
+               ret = -ENODATA;
+               goto exit;
+       }
+
+       ret = load_cmds_from_buf(chip, ed->raw_lcu_config, size);
+exit:
+       ed->error_state = ret;
+       return ret;
+}
+
+int cl_ela_init(struct cl_chip *chip)
+{
+       struct cl_ela_db *ed = &chip->ela_db;
+       int ret = 0;
+
+       if (!cl_ela_is_on(chip))
+               return 0;
+
+       INIT_LIST_HEAD(&ed->cmd_head);
+
+       ret = cl_ela_lcu_config_read(chip);
+       if (ret == 0) {
+               cl_ela_lcu_reset(chip);
+               cl_ela_lcu_apply_config(chip);
+       }
+
+       return ret;
+}
+
+void cl_ela_deinit(struct cl_chip *chip)
+{
+       struct cl_ela_db *ed = &chip->ela_db;
+       struct cl_lcu_cmd *cmd = NULL, *cmd_tmp = NULL;
+
+       if (!cl_ela_is_on(chip))
+               return;
+
+       kfree(ed->raw_lcu_config);
+       ed->raw_lcu_config = NULL;
+
+       list_for_each_entry_safe(cmd, cmd_tmp, &ed->cmd_head, cmd_list)
+               remove_lcu_cmd(cmd);
+}
--
2.30.0

________________________________
The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any retransmission, dissemination, copying or other use of, or taking of any action in reliance upon this information is prohibited. If you received this in error, please contact the sender and delete the material from any computer. Nothing contained herein shall be deemed as a representation, warranty or a commitment by Celeno. No warranties are expressed or implied, including, but not limited to, any implied warranties of non-infringement, merchantability and fitness for a particular purpose.
________________________________






[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux