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

Commit 0de12bd3 authored by Ghanim Fodi's avatar Ghanim Fodi
Browse files

msm: ipa3: Adapt IPA to new register write uC command format



APPS IPA uses uC register write command to write to
register group 10 registers. Previously the parameter
format was a physical pointer into DDR where the register
address and value are stored. Now, with the support of 64bit
command parameters, the command parameters are saved
immediately in SRAM without DDR referencing.

Change-Id: I4cbf2be07c2e8746d1bf8d153b03a7cfc9b90807
Signed-off-by: default avatarGhanim Fodi <gfodi@codeaurora.org>
parent 8ca03863
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -970,7 +970,8 @@ enum ipa3_hw_features {
 * section in 128B shared memory located in offset zero of SW Partition in IPA
 * SRAM.
 * @cmdOp : CPU->HW command opcode. See IPA_CPU_2_HW_COMMANDS
 * @cmdParams : CPU->HW command parameter. The parameter filed can hold 32 bits
 * @cmdParams : CPU->HW command parameter lower 32bit.
 * @cmdParams_hi : CPU->HW command parameter higher 32bit.
 * of parameters (immediate parameters) and point on structure in system memory
 * (in such case the address must be accessible for HW)
 * @responseOp : HW->CPU response opcode. See IPA_HW_2_CPU_RESPONSES
+135 −144
Original line number Diff line number Diff line
@@ -153,8 +153,7 @@ union IpaHwResetPipeCmdData_t {
/**
 * struct IpaHwRegWriteCmdData_t - holds the parameters for
 * IPA_CPU_2_HW_CMD_REG_WRITE command. Parameters are
 * sent as pointer (not direct) thus should be reside
 * in memory address accessible to HW
 * sent as 64b immediate parameters.
 * @RegisterAddress: RG10 register address where the value needs to be written
 * @RegisterValue: 32-Bit value to be written into the register
 */
@@ -510,6 +509,127 @@ static void ipa3_uc_response_hdlr(enum ipa_irq_type interrupt,
	ipa3_dec_client_disable_clks();
}

static int ipa3_uc_send_cmd_64b_param(u32 cmd_lo, u32 cmd_hi, u32 opcode,
	u32 expected_status, bool polling_mode, unsigned long timeout_jiffies)
{
	int index;
	union IpaHwCpuCmdCompletedResponseData_t uc_rsp;
	unsigned long flags;
	int retries = 0;

	IPA3_UC_LOCK(flags);

	if (ipa3_uc_state_check()) {
		IPADBG("uC send command aborted\n");
		IPA3_UC_UNLOCK(flags);
		return -EBADF;
	}

send_cmd:
	if (ipa3_ctx->apply_rg10_wa) {
		if (!polling_mode)
			IPADBG("Overriding mode to polling mode\n");
		polling_mode = true;
	} else {
		init_completion(&ipa3_ctx->uc_ctx.uc_completion);
	}

	ipa3_ctx->uc_ctx.uc_sram_mmio->cmdParams = cmd_lo;
	ipa3_ctx->uc_ctx.uc_sram_mmio->cmdParams_hi = cmd_hi;
	ipa3_ctx->uc_ctx.uc_sram_mmio->cmdOp = opcode;
	ipa3_ctx->uc_ctx.pending_cmd = opcode;
	ipa3_ctx->uc_ctx.uc_sram_mmio->responseOp = 0;
	ipa3_ctx->uc_ctx.uc_sram_mmio->responseParams = 0;

	ipa3_ctx->uc_ctx.uc_status = 0;

	/* ensure write to shared memory is done before triggering uc */
	wmb();

	if (ipa3_ctx->apply_rg10_wa)
		ipa_write_reg(ipa3_ctx->mmio,
			IPA_UC_MAILBOX_m_n_OFFS_v3_0(IPA_CPU_2_HW_CMD_MBOX_m,
			IPA_CPU_2_HW_CMD_MBOX_n), 0x1);
	else
		ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_EE_UC_n_OFFS(0), 0x1);

	if (polling_mode) {
		for (index = 0; index < IPA_UC_POLL_MAX_RETRY; index++) {
			if (ipa3_ctx->uc_ctx.uc_sram_mmio->responseOp ==
			    IPA_HW_2_CPU_RESPONSE_CMD_COMPLETED) {
				uc_rsp.raw32b = ipa3_ctx->uc_ctx.uc_sram_mmio->
						responseParams;
				if (uc_rsp.params.originalCmdOp ==
					ipa3_ctx->uc_ctx.pending_cmd) {
					ipa3_ctx->uc_ctx.uc_status =
						uc_rsp.params.status;
					break;
				}
			}
			if (ipa3_ctx->apply_rg10_wa)
				udelay(IPA_UC_POLL_SLEEP_USEC);
			else
				usleep_range(IPA_UC_POLL_SLEEP_USEC,
					IPA_UC_POLL_SLEEP_USEC);
		}

		if (index == IPA_UC_POLL_MAX_RETRY) {
			IPAERR("uC max polling retries reached\n");
			if (ipa3_ctx->uc_ctx.uc_failed) {
				IPAERR("uC reported on Error, errorType = %s\n",
					ipa_hw_error_str(ipa3_ctx->
					uc_ctx.uc_error_type));
			}
			IPA3_UC_UNLOCK(flags);
			BUG();
			return -EFAULT;
		}
	} else {
		if (wait_for_completion_timeout(&ipa3_ctx->uc_ctx.uc_completion,
			timeout_jiffies) == 0) {
			IPAERR("uC timed out\n");
			if (ipa3_ctx->uc_ctx.uc_failed) {
				IPAERR("uC reported on Error, errorType = %s\n",
					ipa_hw_error_str(ipa3_ctx->
					uc_ctx.uc_error_type));
			}
			IPA3_UC_UNLOCK(flags);
			BUG();
			return -EFAULT;
		}
	}

	if (ipa3_ctx->uc_ctx.uc_status != expected_status) {
		if (ipa3_ctx->uc_ctx.uc_status ==
			IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE) {
			retries++;
			if (retries == IPA_GSI_CHANNEL_STOP_MAX_RETRY) {
				IPAERR("Failed after %d tries\n", retries);
				IPA3_UC_UNLOCK(flags);
				BUG();
				return -EFAULT;
			}

			ipa3_inject_dma_task_for_gsi();
			/* sleep for short period to flush IPA */
			usleep_range(IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC,
				IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC);
			goto send_cmd;
		}

		IPAERR("Recevied status %u, Expected status %u\n",
			ipa3_ctx->uc_ctx.uc_status, expected_status);
		IPA3_UC_UNLOCK(flags);
		return -EFAULT;
	}

	IPA3_UC_UNLOCK(flags);

	IPADBG("uC cmd %u send succeeded\n", opcode);

	return 0;
}

/**
 * ipa3_uc_interface_init() - Initialize the interface with the uC
 *
@@ -581,7 +701,6 @@ remap_fail:
 * interrupts.
 * The function should perform actions that were not done at init due to uC
 * not being loaded then.
 *
 */
void ipa3_uc_load_notify(void)
{
@@ -614,7 +733,10 @@ EXPORT_SYMBOL(ipa3_uc_load_notify);
/**
 * ipa3_uc_send_cmd() - Send a command to the uC
 *
 * Note: In case the operation times out (No response from the uC) or
 * Note1: This function sends command with 32bit parameter and do not
 *	use the higher 32bit of the command parameter (set to zero).
 *
 * Note2: In case the operation times out (No response from the uC) or
 *       polling maximal amount of retries has reached, the logic
 *       considers it as an invalid state of the uC/IPA, and
 *       issues a kernel panic.
@@ -629,121 +751,8 @@ EXPORT_SYMBOL(ipa3_uc_load_notify);
int ipa3_uc_send_cmd(u32 cmd, u32 opcode, u32 expected_status,
		    bool polling_mode, unsigned long timeout_jiffies)
{
	int index;
	union IpaHwCpuCmdCompletedResponseData_t uc_rsp;
	unsigned long flags;
	int retries = 0;

	IPA3_UC_LOCK(flags);

	if (ipa3_uc_state_check()) {
		IPADBG("uC send command aborted\n");
		IPA3_UC_UNLOCK(flags);
		return -EBADF;
	}

send_cmd:
	if (ipa3_ctx->apply_rg10_wa) {
		if (!polling_mode)
			IPADBG("Overriding mode to polling mode\n");
		polling_mode = true;
	} else {
		init_completion(&ipa3_ctx->uc_ctx.uc_completion);
	}

	ipa3_ctx->uc_ctx.uc_sram_mmio->cmdParams = cmd;
	ipa3_ctx->uc_ctx.uc_sram_mmio->cmdOp = opcode;
	ipa3_ctx->uc_ctx.pending_cmd = opcode;
	ipa3_ctx->uc_ctx.uc_sram_mmio->responseOp = 0;
	ipa3_ctx->uc_ctx.uc_sram_mmio->responseParams = 0;

	ipa3_ctx->uc_ctx.uc_status = 0;

	/* ensure write to shared memory is done before triggering uc */
	wmb();

	if (ipa3_ctx->apply_rg10_wa)
		ipa_write_reg(ipa3_ctx->mmio,
			IPA_UC_MAILBOX_m_n_OFFS_v3_0(IPA_CPU_2_HW_CMD_MBOX_m,
			IPA_CPU_2_HW_CMD_MBOX_n), 0x1);
	else
		ipa_write_reg(ipa3_ctx->mmio, IPA_IRQ_EE_UC_n_OFFS(0), 0x1);

	if (polling_mode) {
		for (index = 0; index < IPA_UC_POLL_MAX_RETRY; index++) {
			if (ipa3_ctx->uc_ctx.uc_sram_mmio->responseOp ==
			    IPA_HW_2_CPU_RESPONSE_CMD_COMPLETED) {
				uc_rsp.raw32b = ipa3_ctx->uc_ctx.uc_sram_mmio->
						responseParams;
				if (uc_rsp.params.originalCmdOp ==
					ipa3_ctx->uc_ctx.pending_cmd) {
					ipa3_ctx->uc_ctx.uc_status =
						uc_rsp.params.status;
					break;
				}
			}
			if (ipa3_ctx->apply_rg10_wa)
				udelay(IPA_UC_POLL_SLEEP_USEC);
			else
				usleep_range(IPA_UC_POLL_SLEEP_USEC,
					IPA_UC_POLL_SLEEP_USEC);
		}

		if (index == IPA_UC_POLL_MAX_RETRY) {
			IPAERR("uC max polling retries reached\n");
			if (ipa3_ctx->uc_ctx.uc_failed) {
				IPAERR("uC reported on Error, errorType = %s\n",
					ipa_hw_error_str(ipa3_ctx->
					uc_ctx.uc_error_type));
			}
			IPA3_UC_UNLOCK(flags);
			BUG();
			return -EFAULT;
		}
	} else {
		if (wait_for_completion_timeout(&ipa3_ctx->uc_ctx.uc_completion,
			timeout_jiffies) == 0) {
			IPAERR("uC timed out\n");
			if (ipa3_ctx->uc_ctx.uc_failed) {
				IPAERR("uC reported on Error, errorType = %s\n",
					ipa_hw_error_str(ipa3_ctx->
					uc_ctx.uc_error_type));
			}
			IPA3_UC_UNLOCK(flags);
			BUG();
			return -EFAULT;
		}
	}

	if (ipa3_ctx->uc_ctx.uc_status != expected_status) {
		if (ipa3_ctx->uc_ctx.uc_status ==
			IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE) {
			retries++;
			if (retries == IPA_GSI_CHANNEL_STOP_MAX_RETRY) {
				IPAERR("Failed after %d tries\n", retries);
				IPA3_UC_UNLOCK(flags);
				BUG();
				return -EFAULT;
			}

			ipa3_inject_dma_task_for_gsi();
			/* sleep for short period to flush IPA */
			usleep_range(IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC,
				IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC);
			goto send_cmd;
		}

		IPAERR("Recevied status %u, Expected status %u\n",
			ipa3_ctx->uc_ctx.uc_status, expected_status);
		IPA3_UC_UNLOCK(flags);
		return -EFAULT;
	}

	IPA3_UC_UNLOCK(flags);

	IPADBG("uC cmd %u send succeeded\n", opcode);

	return 0;
	return ipa3_uc_send_cmd_64b_param(cmd, 0, opcode,
		expected_status, polling_mode, timeout_jiffies);
}

/**
@@ -883,42 +892,24 @@ int ipa3_uc_update_hw_flags(u32 flags)
 */
void ipa3_uc_rg10_write_reg(void *base, u32 offset, u32 val)
{
	struct ipa3_mem_buffer reg_data_mem = {0};
	struct IpaHwRegWriteCmdData_t *reg_data;
	int ret = 0;
	u32 pbase;
	int ret;
	u32 paddr;

	if (!ipa3_ctx->apply_rg10_wa)
		return ipa_write_reg(base, offset, val);

	reg_data_mem.size = sizeof(struct IpaHwRegWriteCmdData_t);
	reg_data_mem.base = dma_alloc_coherent(ipa3_ctx->uc_pdev,
		reg_data_mem.size, &reg_data_mem.phys_base,
		GFP_ATOMIC | __GFP_REPEAT);
	if (!reg_data_mem.base) {
		IPAERR("fail to alloc DMA buff of size %d\n",
			reg_data_mem.size);
		BUG();
	}

	/* calculate physical base address */
	pbase = ipa3_ctx->ipa_wrapper_base + ipa3_ctx->ctrl->ipa_reg_base_ofst;

	reg_data = reg_data_mem.base;
	reg_data->RegisterAddress = pbase + offset;
	reg_data->RegisterValue = val;
	/* calculate register physical address */
	paddr = ipa3_ctx->ipa_wrapper_base + ipa3_ctx->ctrl->ipa_reg_base_ofst;
	paddr += offset;

	IPADBG("Sending uC cmd to reg write: addr=0x%x val=0x%x\n",
		reg_data->RegisterAddress, val);
	ret = ipa3_uc_send_cmd((u32)reg_data_mem.phys_base,
		paddr, val);
	ret = ipa3_uc_send_cmd_64b_param(paddr, val,
		IPA_CPU_2_HW_CMD_REG_WRITE, 0, true, 0);
	if (ret) {
		IPAERR("failed to send cmd to uC for reg write\n");
		BUG();
	}

	dma_free_coherent(ipa3_ctx->uc_pdev, reg_data_mem.size,
		reg_data_mem.base, reg_data_mem.phys_base);
}

/**