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

Commit 658e9de0 authored by Hanumant Singh's avatar Hanumant Singh
Browse files

esoc: mdm-4x: Add coresight support for external modem.



Allow modem debugging using CTI pulses.

Change-Id: I092f4e8728aceb1fcb6712425ca930d8bc3fa14b
Signed-off-by: default avatarHanumant Singh <hanumant@codeaurora.org>
parent 5830ea78
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -10,10 +10,13 @@
 * GNU General Public License for more details.
 */

#include <linux/coresight.h>
#include <linux/coresight-cti.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
@@ -38,6 +41,11 @@
#define RD_BUF_SIZE			100
#define SFR_MAX_RETRIES			10
#define SFR_RETRY_INTERVAL		1000
#define MDM_DBG_OFFSET			0x934
#define MDM_DBG_MODE			0x53444247
#define MDM_CTI_NAME			"coresight-cti-rpm-cpu0"
#define MDM_CTI_TRIG			0
#define MDM_CTI_CH			0

enum mdm_gpio {
	AP2MDM_WAKEUP = 0,
@@ -96,6 +104,10 @@ struct mdm_ctrl {
	bool ready;
	bool dual_interface;
	u32 status;
	void __iomem *dbg_addr;
	bool dbg_mode;
	struct coresight_cti *cti;
	int trig_cnt;
};

struct mdm_ops {
@@ -242,6 +254,18 @@ static void mdm_update_gpio_configs(struct mdm_ctrl *mdm,
	}
}

static void mdm_trigger_dbg(struct mdm_ctrl *mdm)
{
	int ret;

	if (mdm->dbg_mode && !mdm->trig_cnt) {
		ret = coresight_cti_pulse_trig(mdm->cti, MDM_CTI_CH);
		mdm->trig_cnt++;
		if (ret)
			dev_err(mdm->dev, "unable to trigger cti pulse on\n");
	}
}

/* This function can be called from atomic context. */
static void mdm_toggle_soft_reset(struct mdm_ctrl *mdm)
{
@@ -321,6 +345,7 @@ static int mdm_cmd_exe(enum esoc_cmd cmd, struct esoc_clink *esoc)
		mdm_disable_irqs(mdm);
		mdm->debug = 0;
		mdm->ready = false;
		mdm->trig_cnt = 0;
		ret = sysmon_send_shutdown(mdm->sysmon_subsys_id);
		if (ret)
			dev_err(mdm->dev, "Graceful shutdown fail, ret = %d\n",
@@ -367,6 +392,7 @@ shutdown_cleanup:
		break;
	case ESOC_EXE_DEBUG:
		mdm->debug = 1;
		mdm->trig_cnt = 0;
		mdm_toggle_soft_reset(mdm);
		/*
		 * wait for ramdumps to be collected
@@ -549,6 +575,7 @@ static irqreturn_t mdm_status_change(int irq, void *dev_id)
		cancel_delayed_work(&mdm->mdm2ap_status_check_work);
		dev_dbg(dev, "status = 1: mdm is now ready\n");
		mdm->ready = true;
		mdm_trigger_dbg(mdm);
		queue_work(mdm->mdm_queue, &mdm->mdm_status_work);
		if (mdm->get_restart_reason)
			queue_work(mdm->mdm_queue, &mdm->restart_reason_work);
@@ -571,6 +598,7 @@ static irqreturn_t mdm_pblrdy_change(int irq, void *dev_id)
			gpio_get_value(MDM_GPIO(mdm, MDM2AP_PBLRDY)));
	if (mdm->init) {
		mdm->init = 0;
		mdm_trigger_dbg(mdm);
		esoc_clink_queue_request(ESOC_REQ_IMG, esoc);
		return IRQ_HANDLED;
	}
@@ -590,6 +618,46 @@ static int mdm_get_status(u32 *status, struct esoc_clink *esoc)
	return 0;
}

static void mdm_configure_debug(struct mdm_ctrl *mdm)
{
	void __iomem *addr;
	unsigned val;
	int ret;
	struct device_node *node = mdm->dev->of_node;

	addr = of_iomap(node, 0);
	if (IS_ERR(addr)) {
		dev_err(mdm->dev, "failed to get debug base addres\n");
		return;
	}
	mdm->dbg_addr = addr + MDM_DBG_OFFSET;
	val = readl_relaxed(mdm->dbg_addr);
	if (val == MDM_DBG_MODE) {
		mdm->dbg_mode = true;
		mdm->cti = coresight_cti_get(MDM_CTI_NAME);
		if (IS_ERR(mdm->cti)) {
			dev_err(mdm->dev, "unable to get cti handle\n");
			goto cti_get_err;
		}
		ret = coresight_cti_map_trigout(mdm->cti, MDM_CTI_TRIG,
								MDM_CTI_CH);
		if (ret) {
			dev_err(mdm->dev, "unable to map trig to channel\n");
			goto cti_map_err;
		}
		mdm->trig_cnt = 0;
	} else {
		dev_dbg(mdm->dev, "Not in debug mode. debug mode = %u\n", val);
		mdm->dbg_mode = false;
	}
	return;
cti_map_err:
	coresight_cti_put(mdm->cti);
cti_get_err:
	mdm->dbg_mode = false;
	return;
}

/* Fail if any of the required gpios is absent. */
static int mdm_dt_parse_gpios(struct mdm_ctrl *mdm)
{
@@ -786,6 +854,7 @@ static int mdm9x25_setup_hw(struct mdm_ctrl *mdm,
	ret = mdm_configure_ipc(mdm, pdev);
	if (ret)
		return ret;
	mdm_configure_debug(mdm);
	dev_err(mdm->dev, "ipc configure done\n");
	esoc->name = MDM9x25_LABEL;
	esoc->link_name = MDM9x25_HSIC;
@@ -839,6 +908,7 @@ static int mdm9x35_setup_hw(struct mdm_ctrl *mdm,
	ret = mdm_configure_ipc(mdm, pdev);
	if (ret)
		return ret;
	mdm_configure_debug(mdm);
	dev_dbg(mdm->dev, "ipc configure done\n");
	esoc->name = MDM9x35_LABEL;
	mdm->dual_interface = of_property_read_bool(node,