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

Commit 5e1bb9b2 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mhi: controller: force MHI reset before power up"

parents c2cf0ffb e0e84222
Loading
Loading
Loading
Loading
+70 −39
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@

#include <asm/arch_timer.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-direction.h>
#include <linux/list.h>
@@ -33,6 +34,34 @@ static const struct firmware_info firmware_table[] = {
static int debug_mode;
module_param_named(debug_mode, debug_mode, int, 0644);

int mhi_debugfs_trigger_m0(void *data, u64 val)
{
	struct mhi_controller *mhi_cntrl = data;
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);

	MHI_LOG("Trigger M3 Exit\n");
	pm_runtime_get(&mhi_dev->pci_dev->dev);
	pm_runtime_put(&mhi_dev->pci_dev->dev);

	return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_m0_fops, NULL,
			mhi_debugfs_trigger_m0, "%llu\n");

int mhi_debugfs_trigger_m3(void *data, u64 val)
{
	struct mhi_controller *mhi_cntrl = data;
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);

	MHI_LOG("Trigger M3 Entry\n");
	pm_runtime_mark_last_busy(&mhi_dev->pci_dev->dev);
	pm_request_autosuspend(&mhi_dev->pci_dev->dev);

	return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_m3_fops, NULL,
			mhi_debugfs_trigger_m3, "%llu\n");

void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl)
{
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
@@ -351,6 +380,45 @@ static int mhi_lpm_enable(struct mhi_controller *mhi_cntrl, void *priv)
	return ret;
}

static int mhi_qcom_power_up(struct mhi_controller *mhi_cntrl)
{
	enum mhi_dev_state dev_state = mhi_get_mhi_state(mhi_cntrl);
	const u32 delayus = 10;
	int itr = DIV_ROUND_UP(mhi_cntrl->timeout_ms * 1000, delayus);
	int ret;

	/*
	 * It's possible device did not go thru a cold reset before
	 * power up and still in error state. If device in error state,
	 * we need to trigger a soft reset before continue with power
	 * up
	 */
	if (dev_state == MHI_STATE_SYS_ERR) {
		mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET);
		while (itr--) {
			dev_state = mhi_get_mhi_state(mhi_cntrl);
			if (dev_state != MHI_STATE_SYS_ERR)
				break;
			usleep_range(delayus, delayus << 1);
		}
		/* device still in error state, abort power up */
		if (dev_state == MHI_STATE_SYS_ERR)
			return -EIO;
	}

	ret = mhi_async_power_up(mhi_cntrl);

	/* power up create the dentry */
	if (mhi_cntrl->dentry) {
		debugfs_create_file("m0", 0444, mhi_cntrl->dentry, mhi_cntrl,
				    &debugfs_trigger_m0_fops);
		debugfs_create_file("m3", 0444, mhi_cntrl->dentry, mhi_cntrl,
				    &debugfs_trigger_m3_fops);
	}

	return ret;
}

static int mhi_runtime_get(struct mhi_controller *mhi_cntrl, void *priv)
{
	struct mhi_dev *mhi_dev = priv;
@@ -387,36 +455,6 @@ static u64 mhi_time_get(struct mhi_controller *mhi_cntrl, void *priv)
	return arch_counter_get_cntvct();
}

int mhi_debugfs_trigger_m0(void *data, u64 val)
{
	struct mhi_controller *mhi_cntrl = data;
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);

	MHI_LOG("Trigger M3 Exit\n");
	pm_runtime_get(&mhi_dev->pci_dev->dev);
	pm_runtime_put(&mhi_dev->pci_dev->dev);

	return 0;
}

int mhi_debugfs_trigger_m3(void *data, u64 val)
{
	struct mhi_controller *mhi_cntrl = data;
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);

	MHI_LOG("Trigger M3 Entry\n");
	pm_runtime_mark_last_busy(&mhi_dev->pci_dev->dev);
	pm_request_autosuspend(&mhi_dev->pci_dev->dev);

	return 0;
}

DEFINE_DEBUGFS_ATTRIBUTE(debugfs_trigger_m0_fops, NULL,
			 mhi_debugfs_trigger_m0, "%llu\n");

DEFINE_DEBUGFS_ATTRIBUTE(debugfs_trigger_m3_fops, NULL,
			 mhi_debugfs_trigger_m3, "%llu\n");

static ssize_t timeout_ms_show(struct device *dev,
			       struct device_attribute *attr,
			       char *buf)
@@ -455,7 +493,7 @@ static ssize_t power_up_store(struct device *dev,
	struct mhi_device *mhi_dev = to_mhi_device(dev);
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;

	ret = mhi_async_power_up(mhi_cntrl);
	ret = mhi_qcom_power_up(mhi_cntrl);
	if (ret)
		return ret;

@@ -612,7 +650,7 @@ int mhi_pci_probe(struct pci_dev *pci_dev,

	/* start power up sequence */
	if (!debug_mode) {
		ret = mhi_async_power_up(mhi_cntrl);
		ret = mhi_qcom_power_up(mhi_cntrl);
		if (ret)
			goto error_power_up;
	}
@@ -620,13 +658,6 @@ int mhi_pci_probe(struct pci_dev *pci_dev,
	pm_runtime_mark_last_busy(&pci_dev->dev);
	pm_runtime_allow(&pci_dev->dev);

	if (mhi_cntrl->dentry) {
		debugfs_create_file_unsafe("m0", 0444, mhi_cntrl->dentry,
					   mhi_cntrl, &debugfs_trigger_m0_fops);
		debugfs_create_file_unsafe("m3", 0444, mhi_cntrl->dentry,
					   mhi_cntrl, &debugfs_trigger_m3_fops);
	}

	MHI_LOG("Return successful\n");

	return 0;
+0 −3
Original line number Diff line number Diff line
@@ -651,7 +651,6 @@ const char *to_mhi_pm_state_str(enum MHI_PM_STATE state);
void mhi_reset_chan(struct mhi_controller *mhi_cntrl,
		    struct mhi_chan *mhi_chan);
enum mhi_ee mhi_get_exec_env(struct mhi_controller *mhi_cntrl);
enum mhi_dev_state mhi_get_m_state(struct mhi_controller *mhi_cntrl);
int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl,
			       enum MHI_ST_TRANSITION state);
void mhi_pm_st_worker(struct work_struct *work);
@@ -707,8 +706,6 @@ void mhi_write_db(struct mhi_controller *mhi_cntrl, void __iomem *db_addr,
void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd);
void mhi_ring_chan_db(struct mhi_controller *mhi_cntrl,
		      struct mhi_chan *mhi_chan);
void mhi_set_mhi_state(struct mhi_controller *mhi_cntrl,
		       enum mhi_dev_state state);
int mhi_get_capability_offset(struct mhi_controller *mhi_cntrl, u32 capability,
			      u32 *offset);
int mhi_init_timesync(struct mhi_controller *mhi_cntrl);
+3 −3
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ enum mhi_ee mhi_get_exec_env(struct mhi_controller *mhi_cntrl)
	return (ret) ? MHI_EE_MAX : exec;
}

enum mhi_dev_state mhi_get_m_state(struct mhi_controller *mhi_cntrl)
enum mhi_dev_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl)
{
	u32 state;
	int ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, MHISTATUS,
@@ -1232,7 +1232,7 @@ void mhi_ctrl_ev_task(unsigned long data)
	if (!ret) {
		write_lock_irq(&mhi_cntrl->pm_lock);
		if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state))
			state = mhi_get_m_state(mhi_cntrl);
			state = mhi_get_mhi_state(mhi_cntrl);
		if (state == MHI_STATE_SYS_ERR) {
			MHI_ERR("MHI system error detected\n");
			pm_state = mhi_tryset_pm_state(mhi_cntrl,
@@ -1281,7 +1281,7 @@ irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev)

	write_lock_irq(&mhi_cntrl->pm_lock);
	if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state))
		state = mhi_get_m_state(mhi_cntrl);
		state = mhi_get_mhi_state(mhi_cntrl);
	if (state == MHI_STATE_SYS_ERR) {
		MHI_ERR("MHI system error detected\n");
		pm_state = mhi_tryset_pm_state(mhi_cntrl,
+14 −0
Original line number Diff line number Diff line
@@ -605,6 +605,20 @@ int mhi_get_remote_time_sync(struct mhi_device *mhi_dev,
			     u64 *t_host,
			     u64 *t_dev);

/**
 * mhi_get_mhi_state - Return MHI state of device
 * @mhi_cntrl: MHI controller
 */
enum mhi_dev_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl);

/**
 * mhi_set_mhi_state - Set device state
 * @mhi_cntrl: MHI controller
 * @state: state to set
 */
void mhi_set_mhi_state(struct mhi_controller *mhi_cntrl,
		       enum mhi_dev_state state);

#ifndef CONFIG_ARCH_QCOM

#ifdef CONFIG_MHI_DEBUG