Search Linux Wireless

[RFC v1 149/256] cl8k: add reg/reg_cli.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>
---
 .../net/wireless/celeno/cl8k/reg/reg_cli.c    | 277 ++++++++++++++++++
 1 file changed, 277 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/reg/reg_cli.c

diff --git a/drivers/net/wireless/celeno/cl8k/reg/reg_cli.c b/drivers/net/wireless/celeno/cl8k/reg/reg_cli.c
new file mode 100644
index 000000000000..2293b09c0da9
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/reg/reg_cli.c
@@ -0,0 +1,277 @@
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include "reg/reg_cli.h"
+#include "reg/reg_access.h"
+#include "reg/reg_modem_gcu.h"
+
+/*
+ * iwcl command to read registers and write to registers:
+ * iwcl <iface> cecli reg.-r.<reg_addr>
+ * iwcl <iface> cecli reg.-w.<reg_addr>.<reg_value>
+ * iwcl <iface> cecli reg.-m.<reg_addr>.<reg_value>.<reg_mask>
+ * iwcl <iface> cecli reg.-x.<type>.<offset>.<value>
+ * iwcl <iface> cecli reg.-y.<type>.<offset>
+ * iwcl <iface> cecli reg.-z.<type>.<offset>.<value>.<mask>
+ * reg_value should not include PCI base address
+ * The advantage of using iwcl command instead of mem command is
+ * that with using the iwcl command the relevant registers will
+ * be added to the recovery procedure.
+ */
+
+static int cl_reg_cli_write_mask(struct cl_hw *cl_hw, u32 address, u32 value, u32 mask)
+{
+       char reply_str[7] = {0};
+       u16 reply_strlen = 0;
+       int ret = cl_reg_write_mask(cl_hw, address, value, mask);
+
+       cl_dbg_verbose(cl_hw, "WRITE: Address = 0x%x, Value = 0x%x, Mask = 0x%x\n",
+                      address, value, mask);
+       reply_strlen = snprintf(&reply_str[0], sizeof(reply_str), "ret=%d", ret);
+
+       return cl_vendor_reply(cl_hw, reply_str, reply_strlen);
+}
+
+static int cl_reg_cli_read(struct cl_hw *cl_hw, u32 address)
+{
+       u32 value = cl_reg_read(cl_hw, address);
+       char reply_str[11] = {0};
+       u16 reply_strlen = 0;
+
+       reply_strlen = snprintf(&reply_str[0], sizeof(reply_str), "0x%08x", value);
+
+       return cl_vendor_reply(cl_hw, reply_str, reply_strlen);
+}
+
+static void cl_reg_cli_read_block(struct cl_hw *cl_hw, u32 first_address, u32 last_address)
+{
+       u32 address = first_address;
+       u32 value;
+
+       if ((first_address & 0x3) != 0) {
+               pr_err("Invalid first address - 0x%x\n", first_address);
+               return;
+       }
+
+       if ((last_address & 0x3) != 0) {
+               pr_err("Invalid last address - 0x%x\n", last_address);
+               return;
+       }
+
+       if (first_address > last_address) {
+               pr_err("Invalid addresses - first [0x%x] > last [0x%x]\n",
+                      first_address, last_address);
+               return;
+       }
+
+       pr_debug("-------------------------\n");
+       pr_debug("| Address  | Value      |\n");
+       pr_debug("|----------+------------|\n");
+
+       while (address <= last_address) {
+               value = cl_reg_read(cl_hw, address);
+               pr_debug("| 0x%06x | 0x%08x |\n", address, value);
+               address += 4;
+       }
+
+       pr_debug("-------------------------\n");
+}
+
+static int cl_reg_cli_write(struct cl_hw *cl_hw, u32 address, u32 value)
+{
+       char reply_str[7] = {0};
+       u16 reply_strlen = 0;
+       int ret = cl_reg_write(cl_hw, address, value);
+
+       cl_dbg_verbose(cl_hw, "WRITE: Address = 0x%x, Value = 0x%x\n", address, value);
+       reply_strlen = snprintf(&reply_str[0], sizeof(reply_str), "ret=%d", ret);
+
+       return cl_vendor_reply(cl_hw, reply_str, reply_strlen);
+}
+
+static int cl_reg_cli_write_type(struct cl_hw *cl_hw, u32 type, u32 offset, u32 value)
+{
+       if (type == 0) /* GCU */
+               cl_reg_write_direct(cl_hw, REG_MODEM_GCU_BASE_ADDR + offset, value);
+       else /* RIU */
+               cl_reg_write_direct(cl_hw, REG_RIU_BASE_ADDR + offset, value);
+
+       return 0;
+}
+
+static int cl_reg_cli_read_type(struct cl_hw *cl_hw, u32 type, u32 offset)
+{
+       u32 base = (type == 0) ? REG_MODEM_GCU_BASE_ADDR : REG_RIU_BASE_ADDR;
+
+       return cl_reg_cli_read(cl_hw, base + offset);
+}
+
+static int cl_reg_cli_write_type_mask(struct cl_hw *cl_hw, u32 type, u32 offset,
+                                     u32 value, u32 mask)
+{
+       if (type == 0) /* GCU */
+               cl_reg_write_mask(cl_hw, REG_MODEM_GCU_BASE_ADDR + offset, value, mask);
+       else /* RIU */
+               cl_reg_write_mask(cl_hw, REG_RIU_BASE_ADDR + offset, value, mask);
+
+       return 0;
+}
+
+static int cl_reg_cli_set_debug(struct cl_hw *cl_hw, bool enable)
+{
+       if (enable) {
+               cl_hw->reg_dbg = true;
+               cl_hw->chip->reg_dbg |= (1 << cl_hw->tcv_idx);
+       } else {
+               cl_hw->reg_dbg = false;
+               cl_hw->chip->reg_dbg &= ~(1 << cl_hw->tcv_idx);
+       }
+
+       return 0;
+}
+
+static int cl_reg_cli_help(struct cl_hw *cl_hw)
+{
+       char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       int err = 0;
+
+       if (!buf)
+               return -ENOMEM;
+
+       snprintf(buf, PAGE_SIZE,
+                "reg usage:\n"
+                "-d : Set debug [0:Disable|1:Enable]\n"
+                "-m : Write masked value to address [address].[value].[mask]\n"
+                "-r : Read address [address]\n"
+                "-s : Read block [first address].[last address]\n"
+                "-w : Write value to address [address].[value]\n"
+                "-x : Write type [0:GCU|1:RIU][offset].[value]\n"
+                "-y : Read type [0:GCU|1:RIU][offset]\n"
+                "-z : Write type mask [0:GCU|1:RIU][offset].[value].[mask]\n");
+
+       err = cl_vendor_reply(cl_hw, buf, strlen(buf));
+       kfree(buf);
+
+       return err;
+}
+
+int cl_reg_cli(struct cl_hw *cl_hw, struct cli_params *cli_params)
+{
+       u32 expected_params = 0;
+       bool set_debug = false;
+       bool reg_write_mask = false;
+       bool reg_read = false;
+       bool reg_read_block = false;
+       bool reg_write = false;
+       bool reg_write_type = false;
+       bool reg_read_type = false;
+       bool reg_write_type_mask = false;
+
+       switch (cli_params->option) {
+       case 'd':
+               set_debug = true;
+               expected_params = 1;
+               break;
+       case 'm':
+               reg_write_mask = true;
+               expected_params = 3;
+               break;
+       case 'r':
+               reg_read = true;
+               expected_params = 1;
+               break;
+       case 's':
+               reg_read_block = true;
+               expected_params = 2;
+               break;
+       case 'w':
+               reg_write = true;
+               expected_params = 2;
+               break;
+       case 'x':
+               reg_write_type = true;
+               expected_params = 3;
+               break;
+       case 'y':
+               reg_read_type = true;
+               expected_params = 2;
+               break;
+       case 'z':
+               reg_write_type_mask = true;
+               expected_params = 4;
+               break;
+       case '?':
+               return cl_reg_cli_help(cl_hw);
+       default:
+               cl_dbg_err(cl_hw, "Illegal option (%c) - try '?' for help\n", cli_params->option);
+               goto out_err;
+       }
+
+       if (expected_params != cli_params->num_params) {
+               cl_dbg_err(cl_hw, "Wrong number of arguments (expected %u) (actual %u)\n",
+                          expected_params, cli_params->num_params);
+               goto out_err;
+       }
+
+       if (set_debug) {
+               u32 enable = cli_params->params[0];
+
+               return cl_reg_cli_set_debug(cl_hw, enable);
+       }
+
+       if (reg_write_mask) {
+               u32 address = cli_params->params[0];
+               u32 value = cli_params->params[1];
+               u32 mask = cli_params->params[2];
+
+               return cl_reg_cli_write_mask(cl_hw, address, value, mask);
+       }
+
+       if (reg_read) {
+               u32 address = cli_params->params[0];
+
+               return cl_reg_cli_read(cl_hw, address);
+       }
+
+       if (reg_read_block) {
+               u32 first_address = cli_params->params[0];
+               u32 last_address = cli_params->params[1];
+
+               cl_reg_cli_read_block(cl_hw, first_address, last_address);
+               return 0;
+       }
+
+       if (reg_write) {
+               u32 address = cli_params->params[0];
+               u32 value = cli_params->params[1];
+
+               return cl_reg_cli_write(cl_hw, address, value);
+       }
+
+       if (reg_write_type) {
+               u32 type = cli_params->params[0];
+               u32 offset = cli_params->params[1];
+               u32 value = cli_params->params[2];
+
+               return cl_reg_cli_write_type(cl_hw, type, offset, value);
+       }
+
+       if (reg_read_type) {
+               u32 type = cli_params->params[0];
+               u32 offset = cli_params->params[1];
+
+               return cl_reg_cli_read_type(cl_hw, type, offset);
+       }
+
+       if (reg_write_type_mask) {
+               u32 type = cli_params->params[0];
+               u32 offset = cli_params->params[1];
+               u32 value = cli_params->params[2];
+               u32 mask = cli_params->params[3];
+
+               return cl_reg_cli_write_type_mask(cl_hw, type, offset, value, mask);
+       }
+
+out_err:
+       return -EIO;
+}
--
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