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

Commit 153e58c7 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: wcd934x: WDSP debug enhancement"

parents 1f5ff4b6 83b05847
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -838,6 +838,45 @@ static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg,
	return 0;
}

#ifdef CONFIG_DEBUG_FS
static int wdsp_debug_dump_handler(struct wdsp_mgr_priv *wdsp, void *arg)
{
	struct wdsp_err_signal_arg *err_data;
	int ret = 0;

	WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
	/* If there is no SSR, set the SSR type to collect ramdumps */
	if (wdsp->ssr_type == WDSP_SSR_TYPE_NO_SSR) {
		wdsp->ssr_type = WDSP_SSR_TYPE_WDSP_DOWN;
	} else {
		WDSP_DBG(wdsp, "SSR handling is running, skip debug ramdump");
		ret = 0;
		WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
		goto done;
	}
	if (arg) {
		err_data = (struct wdsp_err_signal_arg *) arg;
		memcpy(&wdsp->dump_data.err_data, err_data,
		       sizeof(*err_data));
	} else {
		WDSP_DBG(wdsp, "Invalid input, arg is NULL");
		ret = -EINVAL;
		WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
		goto done;
	}
	wdsp_collect_ramdumps(wdsp);
	wdsp->ssr_type = WDSP_SSR_TYPE_NO_SSR;
	WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
done:
	return ret;
}
#else
static int wdsp_debug_dump_handler(struct wdsp_mgr_priv *wdsp, void *arg)
{
	return 0;
}
#endif

static int wdsp_signal_handler(struct device *wdsp_dev,
			       enum wdsp_signal signal, void *arg)
{
@@ -866,6 +905,9 @@ static int wdsp_signal_handler(struct device *wdsp_dev,
	case WDSP_CDC_UP_SIGNAL:
		ret = wdsp_ssr_handler(wdsp, arg, WDSP_SSR_TYPE_CDC_UP);
		break;
	case WDSP_DEBUG_DUMP:
		ret = wdsp_debug_dump_handler(wdsp, arg);
		break;
	default:
		ret = -EINVAL;
		break;
+107 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#define WCD_PROCFS_ENTRY_MAX_LEN 16
#define WCD_934X_RAMDUMP_START_ADDR 0x20100000
#define WCD_934X_RAMDUMP_SIZE ((1024 * 1024) - 128)
#define WCD_MISCDEV_CMD_MAX_LEN 11

#define WCD_CNTL_MUTEX_LOCK(codec, lock)             \
{                                                    \
@@ -76,6 +77,95 @@ static u8 mem_enable_values[] = {
	0xE0, 0xC0, 0x80, 0x00,
};

#ifdef CONFIG_DEBUG_FS
#define WCD_CNTL_SET_ERR_IRQ_FLAG(cntl)\
	atomic_cmpxchg(&cntl->err_irq_flag, 0, 1)
#define WCD_CNTL_CLR_ERR_IRQ_FLAG(cntl)\
	atomic_set(&cntl->err_irq_flag, 0)

static u16 wdsp_reg_for_debug_dump[] = {
	WCD934X_CPE_SS_CPE_CTL,
	WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_0,
	WCD934X_CPE_SS_PWR_SYS_PSTATE_CTL_1,
	WCD934X_CPE_SS_PWR_CPEFLL_CTL,
	WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0,
	WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1,
	WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_OVERRIDE,
	WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_0,
	WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_1,
	WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2,
	WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3,
	WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_4,
	WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_5,
	WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN,
	WCD934X_CPE_SS_SOC_SW_COLLAPSE_CTL,
	WCD934X_CPE_SS_MAD_CTL,
	WCD934X_CPE_SS_CPAR_CTL,
	WCD934X_CPE_SS_WDOG_CFG,
	WCD934X_CPE_SS_STATUS,
	WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A,
	WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B,
	WCD934X_CPE_SS_SS_ERROR_INT_MASK_1A,
	WCD934X_CPE_SS_SS_ERROR_INT_MASK_1B,
	WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0A,
	WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0B,
	WCD934X_CPE_SS_SS_ERROR_INT_STATUS_1A,
	WCD934X_CPE_SS_SS_ERROR_INT_STATUS_1B,
};

static void wcd_cntl_collect_debug_dumps(struct wcd_dsp_cntl *cntl)
{
	struct snd_soc_codec *codec = cntl->codec;
	struct wdsp_err_signal_arg arg;
	int i;
	u8 val;

	/* If WDSP SSR happens, skip collecting debug dumps */
	if (WCD_CNTL_SET_ERR_IRQ_FLAG(cntl) != 0)
		return;

	/* Mask all error interrupts */
	snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A,
		      0xFF);
	snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B,
		      0xFF);

	/* Collect important WDSP registers dump for debug use */
	pr_err("%s: Dump the WDSP registers for debug use\n", __func__);
	for (i = 0; i < sizeof(wdsp_reg_for_debug_dump)/sizeof(u16); i++) {
		val = snd_soc_read(codec, wdsp_reg_for_debug_dump[i]);
		pr_err("%s: reg = 0x%x, val = 0x%x\n", __func__,
		       wdsp_reg_for_debug_dump[i], val);
	}

	/* Trigger NMI in WDSP to sync and update the memory */
	snd_soc_write(codec, WCD934X_CPE_SS_BACKUP_INT, 0x02);

	/* Collect WDSP ramdump for debug use */
	if (cntl->m_dev && cntl->m_ops && cntl->m_ops->signal_handler) {
		arg.mem_dumps_enabled = cntl->ramdump_enable;
		arg.remote_start_addr = WCD_934X_RAMDUMP_START_ADDR;
		arg.dump_size = WCD_934X_RAMDUMP_SIZE;
		cntl->m_ops->signal_handler(cntl->m_dev, WDSP_DEBUG_DUMP,
					    &arg);
	}

	/* Unmask the fatal irqs */
	snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A,
		      ~(cntl->irqs.fatal_irqs & 0xFF));
	snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0B,
		      ~((cntl->irqs.fatal_irqs >> 8) & 0xFF));

	WCD_CNTL_CLR_ERR_IRQ_FLAG(cntl);
}
#else
#define WCD_CNTL_SET_ERR_IRQ_FLAG(cntl) 0
#define WCD_CNTL_CLR_ERR_IRQ_FLAG(cntl) do {} while (0)
static void wcd_cntl_collect_debug_dumps(struct wcd_dsp_cntl *cntl)
{
}
#endif

static ssize_t wdsp_boot_show(struct wcd_dsp_cntl *cntl, char *buf)
{
	return snprintf(buf, WCD_SYSFS_ENTRY_MAX_LEN,
@@ -663,6 +753,7 @@ static int wcd_cntl_do_boot(struct wcd_dsp_cntl *cntl)
	if (!ret) {
		dev_err(codec->dev, "%s: WDSP boot timed out\n",
			__func__);
		wcd_cntl_collect_debug_dumps(cntl);
		ret = -ETIMEDOUT;
		goto err_boot;
	} else {
@@ -719,7 +810,7 @@ static irqreturn_t wcd_cntl_err_irq(int irq, void *data)
	struct wdsp_err_signal_arg arg;
	u16 status = 0;
	u8 reg_val;
	int ret = 0;
	int rc, ret = 0;

	reg_val = snd_soc_read(codec, WCD934X_CPE_SS_SS_ERROR_INT_STATUS_0A);
	status = status | reg_val;
@@ -732,6 +823,12 @@ static irqreturn_t wcd_cntl_err_irq(int irq, void *data)

	if ((status & cntl->irqs.fatal_irqs) &&
	    (cntl->m_dev && cntl->m_ops && cntl->m_ops->signal_handler)) {
		/*
		 * If WDSP SSR happens, skip collecting debug dumps.
		 * If debug dumps collecting happens first, WDSP_ERR_INTR
		 * will be blocked in signal_handler and get processed later.
		 */
		rc = WCD_CNTL_SET_ERR_IRQ_FLAG(cntl);
		arg.mem_dumps_enabled = cntl->ramdump_enable;
		arg.remote_start_addr = WCD_934X_RAMDUMP_START_ADDR;
		arg.dump_size = WCD_934X_RAMDUMP_SIZE;
@@ -742,6 +839,8 @@ static irqreturn_t wcd_cntl_err_irq(int irq, void *data)
				"%s: Failed to handle fatal irq 0x%x\n",
				__func__, status & cntl->irqs.fatal_irqs);
		wcd_cntl_change_online_state(cntl, 0);
		if (rc == 0)
			WCD_CNTL_CLR_ERR_IRQ_FLAG(cntl);
	} else {
		dev_err(cntl->codec->dev, "%s: Invalid signal_handler\n",
			__func__);
@@ -912,7 +1011,7 @@ static ssize_t wcd_miscdev_write(struct file *filep, const char __user *ubuf,
	bool vote;
	int ret = 0;

	if (count == 0 || count > 2) {
	if (count == 0 || count > WCD_MISCDEV_CMD_MAX_LEN) {
		pr_err("%s: Invalid count = %zd\n", __func__, count);
		ret = -EINVAL;
		goto done;
@@ -939,6 +1038,11 @@ static ssize_t wcd_miscdev_write(struct file *filep, const char __user *ubuf,
		}
		cntl->boot_reqs--;
		vote = false;
	} else if (!strcmp(val, "DEBUG_DUMP")) {
		dev_dbg(cntl->codec->dev,
			"%s: Collect dumps for debug use\n", __func__);
		wcd_cntl_collect_debug_dumps(cntl);
		goto done;
	} else {
		dev_err(cntl->codec->dev, "%s: Invalid value %s\n",
			__func__, val);
@@ -1309,6 +1413,7 @@ void wcd_dsp_cntl_init(struct snd_soc_codec *codec,
	mutex_init(&control->clk_mutex);
	mutex_init(&control->ssr_mutex);
	init_waitqueue_head(&control->ssr_entry.offline_poll_wait);
	WCD_CNTL_CLR_ERR_IRQ_FLAG(control);

	/*
	 * The default state of WDSP is in SVS mode.
+5 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -109,6 +109,10 @@ struct wcd_dsp_cntl {
	/* Misc device related */
	char miscdev_name[256];
	struct miscdevice miscdev;
#ifdef CONFIG_DEBUG_FS
	/* Debug dump related */
	atomic_t err_irq_flag;
#endif
};

void wcd_dsp_cntl_init(struct snd_soc_codec *codec,