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

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

Merge "mhi: core: allocate SBL image buffer using CMA pool if configured"

parents e1497928 7e4cc1c1
Loading
Loading
Loading
Loading
+6 −12
Original line number Diff line number Diff line
@@ -268,15 +268,13 @@ static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl,
}

static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl,
			   void *buf,
			   dma_addr_t dma_addr,
			   size_t size)
{
	u32 tx_status, val;
	int i, ret;
	void __iomem *base = mhi_cntrl->bhi;
	rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
	dma_addr_t dma_addr = dma_map_single(mhi_cntrl->dev, buf, size,
					     DMA_TO_DEVICE);
	struct {
		char *name;
		u32 offset;
@@ -288,9 +286,6 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl,
		{ NULL },
	};

	if (dma_mapping_error(mhi_cntrl->dev, dma_addr))
		return -ENOMEM;

	MHI_LOG("Starting BHI programming\n");

	/* program start sbl download via  bhi protocol */
@@ -339,12 +334,9 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl,
		goto invalid_pm_state;
	}

	dma_unmap_single(mhi_cntrl->dev, dma_addr, size, DMA_TO_DEVICE);

	return (tx_status == BHI_STATUS_SUCCESS) ? 0 : -ETIMEDOUT;

invalid_pm_state:
	dma_unmap_single(mhi_cntrl->dev, dma_addr, size, DMA_TO_DEVICE);

	return -EIO;
}
@@ -462,6 +454,7 @@ void mhi_fw_load_worker(struct work_struct *work)
	const struct firmware *firmware;
	struct image_info *image_info;
	void *buf;
	dma_addr_t dma_addr;
	size_t size;

	mhi_cntrl = container_of(work, struct mhi_controller, fw_worker);
@@ -506,7 +499,7 @@ void mhi_fw_load_worker(struct work_struct *work)
	if (size > firmware->size)
		size = firmware->size;

	buf = kmemdup(firmware->data, size, GFP_KERNEL);
	buf = mhi_alloc_coherent(mhi_cntrl, size, &dma_addr, GFP_KERNEL);
	if (!buf) {
		MHI_ERR("Could not allocate memory for image\n");
		release_firmware(firmware);
@@ -514,8 +507,9 @@ void mhi_fw_load_worker(struct work_struct *work)
	}

	/* load sbl image */
	ret = mhi_fw_load_sbl(mhi_cntrl, buf, size);
	kfree(buf);
	memcpy(buf, firmware->data, size);
	ret = mhi_fw_load_sbl(mhi_cntrl, dma_addr, size);
	mhi_free_coherent(mhi_cntrl, size, buf, dma_addr);

	if (!mhi_cntrl->fbc_download || ret || mhi_cntrl->ee == MHI_EE_EDL)
		release_firmware(firmware);
+12 −15
Original line number Diff line number Diff line
@@ -54,20 +54,18 @@ const char * const mhi_state_str[MHI_STATE_MAX] = {
};

static const char * const mhi_pm_state_str[] = {
	"DISABLE",
	"POR",
	"M0",
	"M1",
	"M1->M2",
	"M2",
	"M?->M3",
	"M3",
	"M3->M0",
	"FW DL Error",
	"SYS_ERR Detect",
	"SYS_ERR Process",
	"SHUTDOWN Process",
	"LD or Error Fatal Detect",
	[MHI_PM_BIT_DISABLE] = "DISABLE",
	[MHI_PM_BIT_POR] = "POR",
	[MHI_PM_BIT_M0] = "M0",
	[MHI_PM_BIT_M2] = "M2",
	[MHI_PM_BIT_M3_ENTER] = "M?->M3",
	[MHI_PM_BIT_M3] = "M3",
	[MHI_PM_BIT_M3_EXIT] = "M3->M0",
	[MHI_PM_BIT_FW_DL_ERR] = "FW DL Error",
	[MHI_PM_BIT_SYS_ERR_DETECT] = "SYS_ERR Detect",
	[MHI_PM_BIT_SYS_ERR_PROCESS] = "SYS_ERR Process",
	[MHI_PM_BIT_SHUTDOWN_PROCESS] = "SHUTDOWN Process",
	[MHI_PM_BIT_LD_ERR_FATAL_DETECT] = "LD or Error Fatal Detect",
};

struct mhi_bus mhi_bus;
@@ -1087,7 +1085,6 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl)
	spin_lock_init(&mhi_cntrl->wlock);
	INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker);
	INIT_WORK(&mhi_cntrl->fw_worker, mhi_fw_load_worker);
	INIT_WORK(&mhi_cntrl->m1_worker, mhi_pm_m1_worker);
	INIT_WORK(&mhi_cntrl->syserr_worker, mhi_pm_sys_err_worker);
	init_waitqueue_head(&mhi_cntrl->state_event);

+33 −19
Original line number Diff line number Diff line
@@ -425,33 +425,49 @@ extern const char * const mhi_state_str[MHI_STATE_MAX];
				  !mhi_state_str[state]) ? \
				"INVALID_STATE" : mhi_state_str[state])

enum {
	MHI_PM_BIT_DISABLE,
	MHI_PM_BIT_POR,
	MHI_PM_BIT_M0,
	MHI_PM_BIT_M2,
	MHI_PM_BIT_M3_ENTER,
	MHI_PM_BIT_M3,
	MHI_PM_BIT_M3_EXIT,
	MHI_PM_BIT_FW_DL_ERR,
	MHI_PM_BIT_SYS_ERR_DETECT,
	MHI_PM_BIT_SYS_ERR_PROCESS,
	MHI_PM_BIT_SHUTDOWN_PROCESS,
	MHI_PM_BIT_LD_ERR_FATAL_DETECT,
	MHI_PM_BIT_MAX
};

/* internal power states */
enum MHI_PM_STATE {
	MHI_PM_DISABLE = BIT(0), /* MHI is not enabled */
	MHI_PM_POR = BIT(1), /* reset state */
	MHI_PM_M0 = BIT(2),
	MHI_PM_M1 = BIT(3),
	MHI_PM_M1_M2_TRANSITION = BIT(4), /* register access not allowed */
	MHI_PM_M2 = BIT(5),
	MHI_PM_M3_ENTER = BIT(6),
	MHI_PM_M3 = BIT(7),
	MHI_PM_M3_EXIT = BIT(8),
	MHI_PM_FW_DL_ERR = BIT(9), /* firmware download failure state */
	MHI_PM_SYS_ERR_DETECT = BIT(10),
	MHI_PM_SYS_ERR_PROCESS = BIT(11),
	MHI_PM_SHUTDOWN_PROCESS = BIT(12),
	MHI_PM_LD_ERR_FATAL_DETECT = BIT(13), /* link not accessible */
	MHI_PM_DISABLE = BIT(MHI_PM_BIT_DISABLE), /* MHI is not enabled */
	MHI_PM_POR = BIT(MHI_PM_BIT_POR), /* reset state */
	MHI_PM_M0 = BIT(MHI_PM_BIT_M0),
	MHI_PM_M2 = BIT(MHI_PM_BIT_M2),
	MHI_PM_M3_ENTER = BIT(MHI_PM_BIT_M3_ENTER),
	MHI_PM_M3 = BIT(MHI_PM_BIT_M3),
	MHI_PM_M3_EXIT = BIT(MHI_PM_BIT_M3_EXIT),
	/* firmware download failure state */
	MHI_PM_FW_DL_ERR = BIT(MHI_PM_BIT_FW_DL_ERR),
	MHI_PM_SYS_ERR_DETECT = BIT(MHI_PM_BIT_SYS_ERR_DETECT),
	MHI_PM_SYS_ERR_PROCESS = BIT(MHI_PM_BIT_SYS_ERR_PROCESS),
	MHI_PM_SHUTDOWN_PROCESS = BIT(MHI_PM_BIT_SHUTDOWN_PROCESS),
	/* link not accessible */
	MHI_PM_LD_ERR_FATAL_DETECT = BIT(MHI_PM_BIT_LD_ERR_FATAL_DETECT),
};

#define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \
		MHI_PM_M1 | MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \
		MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \
		MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \
		MHI_PM_SHUTDOWN_PROCESS | MHI_PM_FW_DL_ERR)))
#define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR)
#define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT)
#define MHI_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | MHI_PM_M1))
#define MHI_DB_ACCESS_VALID(pm_state) (pm_state & MHI_PM_M0)
#define MHI_WAKE_DB_CLEAR_VALID(pm_state) (pm_state & (MHI_PM_M0 | \
						       MHI_PM_M1 | MHI_PM_M2))
						       MHI_PM_M2))
#define MHI_WAKE_DB_SET_VALID(pm_state) (pm_state & MHI_PM_M2)
#define MHI_WAKE_DB_FORCE_SET_VALID(pm_state) MHI_WAKE_DB_CLEAR_VALID(pm_state)
#define MHI_EVENT_ACCESS_INVALID(pm_state) (pm_state == MHI_PM_DISABLE || \
@@ -471,7 +487,6 @@ enum MHI_XFER_TYPE {
#define CMD_EL_PER_RING (128)
#define PRIMARY_CMD_RING (0)
#define MHI_DEV_WAKE_DB (127)
#define MHI_M2_DEBOUNCE_TMR_US (10000)
#define MHI_MAX_MTU (0xffff)

enum MHI_ER_TYPE {
@@ -654,7 +669,6 @@ int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl,
			       enum MHI_ST_TRANSITION state);
void mhi_pm_st_worker(struct work_struct *work);
void mhi_fw_load_worker(struct work_struct *work);
void mhi_pm_m1_worker(struct work_struct *work);
void mhi_pm_sys_err_worker(struct work_struct *work);
int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl);
void mhi_ctrl_ev_task(unsigned long data);
+2 −2
Original line number Diff line number Diff line
@@ -1582,11 +1582,11 @@ int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d)
	struct mhi_controller *mhi_cntrl = m->private;

	seq_printf(m,
		   "pm_state:%s dev_state:%s EE:%s M0:%u M1:%u M2:%u M3:%u wake:%d dev_wake:%u alloc_size:%u\n",
		   "pm_state:%s dev_state:%s EE:%s M0:%u M2:%u M3:%u wake:%d dev_wake:%u alloc_size:%u\n",
		   to_mhi_pm_state_str(mhi_cntrl->pm_state),
		   TO_MHI_STATE_STR(mhi_cntrl->dev_state),
		   TO_MHI_EXEC_STR(mhi_cntrl->ee),
		   mhi_cntrl->M0, mhi_cntrl->M1, mhi_cntrl->M2, mhi_cntrl->M3,
		   mhi_cntrl->M0, mhi_cntrl->M2, mhi_cntrl->M3,
		   mhi_cntrl->wake_set,
		   atomic_read(&mhi_cntrl->dev_wake),
		   atomic_read(&mhi_cntrl->alloc_size));
+25 −94
Original line number Diff line number Diff line
@@ -36,13 +36,11 @@
 * Valid transitions:
 * L0: DISABLE <--> POR
 *     POR <--> POR
 *     POR -> M0 -> M1 -> M1_M2 -> M2 --> M0
 *     POR -> M0 -> M2 --> M0
 *     POR -> FW_DL_ERR
 *     FW_DL_ERR <--> FW_DL_ERR
 *     M0 -> FW_DL_ERR
 *     M1_M2 -> M0 (Device can trigger it)
 *     M0 -> M3_ENTER -> M3 -> M3_EXIT --> M0
 *     M1 -> M3_ENTER --> M3
 * L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS --> POR
 * L2: SHUTDOWN_PROCESS -> DISABLE
 * L3: LD_ERR_FATAL_DETECT <--> LD_ERR_FATAL_DETECT
@@ -62,21 +60,10 @@ static struct mhi_pm_transitions const mhi_state_transitions[] = {
	},
	{
		MHI_PM_M0,
		MHI_PM_M1 | MHI_PM_M3_ENTER | MHI_PM_SYS_ERR_DETECT |
		MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_SYS_ERR_DETECT |
		MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT |
		MHI_PM_FW_DL_ERR
	},
	{
		MHI_PM_M1,
		MHI_PM_M1_M2_TRANSITION | MHI_PM_M3_ENTER |
		MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS |
		MHI_PM_LD_ERR_FATAL_DETECT
	},
	{
		MHI_PM_M1_M2_TRANSITION,
		MHI_PM_M2 | MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT |
		MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT
	},
	{
		MHI_PM_M2,
		MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS |
@@ -376,56 +363,22 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl)
	return 0;
}

void mhi_pm_m1_worker(struct work_struct *work)
void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl)
{
	enum MHI_PM_STATE cur_state;
	struct mhi_controller *mhi_cntrl;

	mhi_cntrl = container_of(work, struct mhi_controller, m1_worker);

	MHI_LOG("M1 state transition from dev_state:%s pm_state:%s\n",
		TO_MHI_STATE_STR(mhi_cntrl->dev_state),
		to_mhi_pm_state_str(mhi_cntrl->pm_state));
	enum MHI_PM_STATE state;

	mutex_lock(&mhi_cntrl->pm_mutex);
	write_lock_irq(&mhi_cntrl->pm_lock);

	/* we either Entered M3 or we did M3->M0 Exit */
	if (mhi_cntrl->pm_state != MHI_PM_M1)
		goto invalid_pm_state;

	MHI_LOG("Transitioning to M2 Transition\n");
	cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M1_M2_TRANSITION);
	if (unlikely(cur_state != MHI_PM_M1_M2_TRANSITION)) {
		MHI_ERR("Failed to transition to state %s from %s\n",
			to_mhi_pm_state_str(MHI_PM_M1_M2_TRANSITION),
			to_mhi_pm_state_str(cur_state));
		goto invalid_pm_state;
	}

	mhi_cntrl->dev_state = MHI_STATE_M2;
	/* if it fails, means we transition to M3 */
	state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M2);
	if (state == MHI_PM_M2) {
		MHI_VERB("Entered M2 State\n");
		mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M2);
	write_unlock_irq(&mhi_cntrl->pm_lock);
		mhi_cntrl->dev_state = MHI_STATE_M2;
		mhi_cntrl->M2++;

	/* during M2 transition we cannot access DB registers must sleep */
	usleep_range(MHI_M2_DEBOUNCE_TMR_US, MHI_M2_DEBOUNCE_TMR_US + 50);
	write_lock_irq(&mhi_cntrl->pm_lock);

	/* during de-bounce time could be receiving M0 Event */
	if (mhi_cntrl->pm_state == MHI_PM_M1_M2_TRANSITION) {
		MHI_LOG("Entered M2 State\n");
		cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M2);
		if (unlikely(cur_state != MHI_PM_M2)) {
			MHI_ERR("Failed to transition to state %s from %s\n",
				to_mhi_pm_state_str(MHI_PM_M2),
				to_mhi_pm_state_str(cur_state));
			goto invalid_pm_state;
		}
	}
		write_unlock_irq(&mhi_cntrl->pm_lock);

	/* transfer pending, exit M2 */
		/* transfer pending, exit M2 immediately */
		if (unlikely(atomic_read(&mhi_cntrl->dev_wake))) {
			MHI_VERB("Exiting M2 Immediately, count:%d\n",
				 atomic_read(&mhi_cntrl->dev_wake));
@@ -433,35 +386,14 @@ void mhi_pm_m1_worker(struct work_struct *work)
			mhi_cntrl->wake_get(mhi_cntrl, true);
			mhi_cntrl->wake_put(mhi_cntrl, false);
			read_unlock_bh(&mhi_cntrl->pm_lock);
	} else
		} else {
			mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data,
					     MHI_CB_IDLE);

	mutex_unlock(&mhi_cntrl->pm_mutex);
	return;

invalid_pm_state:
	write_unlock_irq(&mhi_cntrl->pm_lock);
	mutex_unlock(&mhi_cntrl->pm_mutex);
}

void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl)
{
	enum MHI_PM_STATE state;

	write_lock_irq(&mhi_cntrl->pm_lock);
	mhi_cntrl->dev_state = mhi_get_m_state(mhi_cntrl);
	if (mhi_cntrl->dev_state == MHI_STATE_M1) {
		state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M1);

		/* schedule M1->M2 transition */
		if (state == MHI_PM_M1) {
			schedule_work(&mhi_cntrl->m1_worker);
			mhi_cntrl->M1++;
		}
		}
	} else {
		write_unlock_irq(&mhi_cntrl->pm_lock);
	}
}

int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl)
{
@@ -619,7 +551,6 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,
	mutex_unlock(&mhi_cntrl->pm_mutex);
	MHI_LOG("Waiting for all pending threads to complete\n");
	wake_up(&mhi_cntrl->state_event);
	flush_work(&mhi_cntrl->m1_worker);
	flush_work(&mhi_cntrl->st_worker);
	flush_work(&mhi_cntrl->fw_worker);

Loading