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

Allow modem debugging using CTI pulses.

Change-Id: I092f4e8728aceb1fcb6712425ca930d8bc3fa14b
Signed-off-by: Hanumant Singh <hanumant@codeaurora.org>
This commit is contained in:
Hanumant Singh 2014-01-24 15:35:26 -08:00
parent 5830ea788f
commit 658e9de055
1 changed files with 70 additions and 0 deletions

View File

@ -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,