Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 710d5226 authored by Yue Ma's avatar Yue Ma
Browse files

cnss2: Extend register read/write debugfs



Extend register read/write debugfs with MMIO register access
options for debug purpose.

Change-Id: Ic67505698e24f16c1032b337dbb3dc918c12713e
Signed-off-by: default avatarYue Ma <yuem@codeaurora.org>
parent cd914bbc
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -417,3 +417,37 @@ int cnss_bus_is_device_down(struct cnss_plat_data *plat_priv)
		return 0;
	}
}

int cnss_bus_debug_reg_read(struct cnss_plat_data *plat_priv, u32 offset,
			    u32 *val)
{
	if (!plat_priv)
		return -ENODEV;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_debug_reg_read(plat_priv->bus_priv, offset,
					       val);
	default:
		cnss_pr_dbg("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return 0;
	}
}

int cnss_bus_debug_reg_write(struct cnss_plat_data *plat_priv, u32 offset,
			     u32 val)
{
	if (!plat_priv)
		return -ENODEV;

	switch (plat_priv->bus_type) {
	case CNSS_BUS_PCI:
		return cnss_pci_debug_reg_write(plat_priv->bus_priv, offset,
						val);
	default:
		cnss_pr_dbg("Unsupported bus type: %d\n",
			    plat_priv->bus_type);
		return 0;
	}
}
+4 −0
Original line number Diff line number Diff line
@@ -48,5 +48,9 @@ int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv,
int cnss_bus_update_status(struct cnss_plat_data *plat_priv,
			   enum cnss_driver_status status);
int cnss_bus_is_device_down(struct cnss_plat_data *plat_priv);
int cnss_bus_debug_reg_read(struct cnss_plat_data *plat_priv, u32 offset,
			    u32 *val);
int cnss_bus_debug_reg_write(struct cnss_plat_data *plat_priv, u32 offset,
			     u32 val);

#endif /* _CNSS_BUS_H */
+36 −11
Original line number Diff line number Diff line
@@ -5,9 +5,12 @@
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include "main.h"
#include "bus.h"
#include "debug.h"
#include "pci.h"

#define MMIO_REG_ACCESS_MEM_TYPE		0xFF

void *cnss_ipc_log_context;
void *cnss_ipc_log_long_context;

@@ -238,6 +241,8 @@ static int cnss_reg_read_debug_show(struct seq_file *s, void *data)
	mutex_lock(&plat_priv->dev_lock);
	if (!plat_priv->diag_reg_read_buf) {
		seq_puts(s, "\nUsage: echo <mem_type> <offset> <data_len> > <debugfs_path>/cnss/reg_read\n");
		seq_puts(s, "Use mem_type = 0xff for register read by IO access, data_len will be ignored\n");
		seq_puts(s, "Use other mem_type for register read by QMI\n");
		mutex_unlock(&plat_priv->dev_lock);
		return 0;
	}
@@ -269,16 +274,11 @@ static ssize_t cnss_reg_read_debug_write(struct file *fp,
	char *sptr, *token;
	unsigned int len = 0;
	u32 reg_offset, mem_type;
	u32 data_len = 0;
	u32 data_len = 0, reg_val = 0;
	u8 *reg_buf = NULL;
	const char *delim = " ";
	int ret = 0;

	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
		cnss_pr_err("Firmware is not ready yet\n");
		return -EINVAL;
	}

	len = min(count, sizeof(buf) - 1);
	if (copy_from_user(buf, user_buf, len))
		return -EFAULT;
@@ -313,6 +313,20 @@ static ssize_t cnss_reg_read_debug_write(struct file *fp,
	if (kstrtou32(token, 0, &data_len))
		return -EINVAL;

	if (mem_type == MMIO_REG_ACCESS_MEM_TYPE) {
		ret = cnss_bus_debug_reg_read(plat_priv, reg_offset, &reg_val);
		if (ret)
			return ret;
		cnss_pr_dbg("Read 0x%x from register offset 0x%x\n", reg_val,
			    reg_offset);
		return count;
	}

	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
		cnss_pr_err("Firmware is not ready yet\n");
		return -EINVAL;
	}

	mutex_lock(&plat_priv->dev_lock);
	kfree(plat_priv->diag_reg_read_buf);
	plat_priv->diag_reg_read_buf = NULL;
@@ -357,6 +371,8 @@ static const struct file_operations cnss_reg_read_debug_fops = {
static int cnss_reg_write_debug_show(struct seq_file *s, void *data)
{
	seq_puts(s, "\nUsage: echo <mem_type> <offset> <reg_val> > <debugfs_path>/cnss/reg_write\n");
	seq_puts(s, "Use mem_type = 0xff for register write by IO access\n");
	seq_puts(s, "Use other mem_type for register write by QMI\n");

	return 0;
}
@@ -374,11 +390,6 @@ static ssize_t cnss_reg_write_debug_write(struct file *fp,
	const char *delim = " ";
	int ret = 0;

	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
		cnss_pr_err("Firmware is not ready yet\n");
		return -EINVAL;
	}

	len = min(count, sizeof(buf) - 1);
	if (copy_from_user(buf, user_buf, len))
		return -EFAULT;
@@ -413,6 +424,20 @@ static ssize_t cnss_reg_write_debug_write(struct file *fp,
	if (kstrtou32(token, 0, &reg_val))
		return -EINVAL;

	if (mem_type == MMIO_REG_ACCESS_MEM_TYPE) {
		ret = cnss_bus_debug_reg_write(plat_priv, reg_offset, reg_val);
		if (ret)
			return ret;
		cnss_pr_dbg("Wrote 0x%x to register offset 0x%x\n", reg_val,
			    reg_offset);
		return count;
	}

	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
		cnss_pr_err("Firmware is not ready yet\n");
		return -EINVAL;
	}

	ret = cnss_wlfw_athdiag_write_send_sync(plat_priv, reg_offset, mem_type,
						sizeof(u32),
						(u8 *)&reg_val);
+62 −0
Original line number Diff line number Diff line
@@ -475,6 +475,68 @@ static int cnss_pci_force_wake_put(struct cnss_pci_data *pci_priv)
	return ret;
}

int cnss_pci_debug_reg_read(struct cnss_pci_data *pci_priv, u32 offset,
			    u32 *val)
{
	int ret = 0;

	ret = cnss_pci_is_device_down(&pci_priv->pci_dev->dev);
	if (ret)
		goto out;

	ret = cnss_pci_pm_runtime_get_sync(pci_priv);
	if (ret < 0)
		goto runtime_pm_put;

	cnss_pci_force_wake_get(pci_priv);

	ret = cnss_pci_reg_read(pci_priv, offset, val);
	if (ret) {
		cnss_pr_err("Failed to read register offset 0x%x, err = %d\n",
			    offset, ret);
		goto force_wake_put;
	}

force_wake_put:
	cnss_pci_force_wake_put(pci_priv);
runtime_pm_put:
	cnss_pci_pm_runtime_mark_last_busy(pci_priv);
	cnss_pci_pm_runtime_put_autosuspend(pci_priv);
out:
	return ret;
}

int cnss_pci_debug_reg_write(struct cnss_pci_data *pci_priv, u32 offset,
			     u32 val)
{
	int ret = 0;

	ret = cnss_pci_is_device_down(&pci_priv->pci_dev->dev);
	if (ret)
		goto out;

	ret = cnss_pci_pm_runtime_get_sync(pci_priv);
	if (ret < 0)
		goto runtime_pm_put;

	cnss_pci_force_wake_get(pci_priv);

	ret = cnss_pci_reg_write(pci_priv, offset, val);
	if (ret) {
		cnss_pr_err("Failed to write 0x%x to register offset 0x%x, err = %d\n",
			    val, offset, ret);
		goto force_wake_put;
	}

force_wake_put:
	cnss_pci_force_wake_put(pci_priv);
runtime_pm_put:
	cnss_pci_pm_runtime_mark_last_busy(pci_priv);
	cnss_pci_pm_runtime_put_autosuspend(pci_priv);
out:
	return ret;
}

static int cnss_set_pci_config_space(struct cnss_pci_data *pci_priv, bool save)
{
	struct pci_dev *pci_dev = pci_priv->pci_dev;
+4 −0
Original line number Diff line number Diff line
@@ -201,5 +201,9 @@ int cnss_pci_update_status(struct cnss_pci_data *pci_priv,
int cnss_pcie_is_device_down(struct cnss_pci_data *pci_priv);
int cnss_pci_suspend_bus(struct cnss_pci_data *pci_priv);
int cnss_pci_resume_bus(struct cnss_pci_data *pci_priv);
int cnss_pci_debug_reg_read(struct cnss_pci_data *pci_priv, u32 offset,
			    u32 *val);
int cnss_pci_debug_reg_write(struct cnss_pci_data *pci_priv, u32 offset,
			     u32 val);

#endif /* _CNSS_PCI_H */