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

Commit 32ae1d7d authored by Ghanim Fodi's avatar Ghanim Fodi Committed by Gerrit - the friendly Code Review server
Browse files

msm: ipa3: Add IPA HAL layer I/S and registers support



Add an IPA HAL layer I/S to IPA driver which abstracts
the H/W towards the core IPA driver. Registers read/write
access support is added.

CRs-Fixed: 970323
Change-Id: I9faf38798b53c263bd8f31d11061220b174f463d
Signed-off-by: default avatarGhanim Fodi <gfodi@codeaurora.org>
parent 676c9bc2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -408,7 +408,7 @@ int ipa_cfg_ep_holb_by_client(enum ipa_client_type client,
EXPORT_SYMBOL(ipa_cfg_ep_holb_by_client);

/**
 * ipa_cfg_ep_hdr() -  IPA end-point Control configuration
 * ipa_cfg_ep_ctrl() -  IPA end-point Control configuration
 * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
 * @ipa_ep_cfg_ctrl:	[in] IPA end-point configuration params
 *
+4 −2
Original line number Diff line number Diff line
@@ -1413,7 +1413,8 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
					RMNET_IOCTL_EGRESS_FORMAT_CHECKSUM) {
				apps_to_ipa_ep_cfg.ipa_ep_cfg.hdr.hdr_len = 8;
				apps_to_ipa_ep_cfg.ipa_ep_cfg.cfg.
					cs_offload_en = 1;
					cs_offload_en =
					IPA_ENABLE_CS_OFFLOAD_UL;
				apps_to_ipa_ep_cfg.ipa_ep_cfg.cfg.
					cs_metadata_hdr_offset = 1;
			} else {
@@ -1471,7 +1472,8 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
			if ((extend_ioctl_data.u.data) &
					RMNET_IOCTL_INGRESS_FORMAT_CHECKSUM)
				ipa_to_apps_ep_cfg.ipa_ep_cfg.cfg.
					cs_offload_en = 2;
					cs_offload_en =
					IPA_ENABLE_CS_OFFLOAD_DL;

			if ((extend_ioctl_data.u.data) &
					RMNET_IOCTL_INGRESS_FORMAT_AGG_DATA) {
+2 −0
Original line number Diff line number Diff line
obj-$(CONFIG_IPA3) += ipahal/

obj-$(CONFIG_IPA3) += ipat.o
ipat-y := ipa.o ipa_debugfs.o ipa_hdr.o ipa_flt.o ipa_rt.o ipa_dp.o ipa_client.o \
	ipa_utils.o ipa_nat.o ipa_intf.o teth_bridge.o ipa_interrupts.o odu_bridge.o \
+48 −56
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
#include <linux/hash.h>
#include "ipa_i.h"
#include "ipa_rm_i.h"
#include "ipahal/ipahal.h"

#define CREATE_TRACE_POINTS
#include "ipa_trace.h"
@@ -1482,7 +1483,7 @@ static int ipa3_setup_exception_path(void)
{
	struct ipa_ioc_add_hdr *hdr;
	struct ipa_hdr_add *hdr_entry;
	struct ipa3_route route = { 0 };
	struct ipahal_reg_route route = { 0 };
	int ret;

	/* install the basic exception header */
@@ -1637,22 +1638,21 @@ static void ipa3_free_buffer(void *user1, int user2)

static int ipa3_q6_pipe_delay(void)
{
	u32 reg_val = 0;
	int client_idx;
	int ep_idx;
	struct ipa_ep_cfg_ctrl ep_ctrl;

	memset(&ep_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
	for (client_idx = 0; client_idx < IPA_CLIENT_MAX; client_idx++) {
		if (IPA_CLIENT_IS_Q6_PROD(client_idx)) {
			ep_idx = ipa3_get_ep_mapping(client_idx);
			if (ep_idx == -1)
				continue;

			IPA_SETFIELD_IN_REG(reg_val, 1,
				IPA_ENDP_INIT_CTRL_N_ENDP_DELAY_SHFT,
				IPA_ENDP_INIT_CTRL_N_ENDP_DELAY_BMSK);
			ep_ctrl.ipa_ep_delay = 1;

			ipa_write_reg(ipa3_ctx->mmio,
				IPA_ENDP_INIT_CTRL_N_OFST(ep_idx), reg_val);
			ipahal_write_reg_n_fields(IPA_ENDP_INIT_CTRL_n,
				ep_idx, &ep_ctrl);
		}
	}

@@ -1661,12 +1661,13 @@ static int ipa3_q6_pipe_delay(void)

static int ipa3_q6_avoid_holb(void)
{
	u32 reg_val;
	int ep_idx;
	int client_idx;
	struct ipa_ep_cfg_ctrl avoid_holb;
	struct ipa_ep_cfg_holb ep_holb;

	memset(&avoid_holb, 0, sizeof(avoid_holb));
	memset(&ep_holb, 0, sizeof(ep_holb));
	avoid_holb.ipa_ep_suspend = true;

	for (client_idx = 0; client_idx < IPA_CLIENT_MAX; client_idx++) {
@@ -1681,23 +1682,14 @@ static int ipa3_q6_avoid_holb(void)
			 * they are not valid, therefore, the above function
			 * will fail.
			 */
			reg_val = 0;
			IPA_SETFIELD_IN_REG(reg_val, 0,
				IPA_ENDP_INIT_HOL_BLOCK_TIMER_N_TIMER_SHFT,
				IPA_ENDP_INIT_HOL_BLOCK_TIMER_N_TIMER_BMSK);

			ipa_write_reg(ipa3_ctx->mmio,
			IPA_ENDP_INIT_HOL_BLOCK_TIMER_N_OFST_v3_0(ep_idx),
				reg_val);

			reg_val = 0;
			IPA_SETFIELD_IN_REG(reg_val, 1,
				IPA_ENDP_INIT_HOL_BLOCK_EN_N_EN_SHFT,
				IPA_ENDP_INIT_HOL_BLOCK_EN_N_EN_BMSK);

			ipa_write_reg(ipa3_ctx->mmio,
				IPA_ENDP_INIT_HOL_BLOCK_EN_N_OFST_v3_0(ep_idx),
				reg_val);
			ep_holb.tmr_val = 0;
			ep_holb.en = 1;
			ipahal_write_reg_n_fields(
				IPA_ENDP_INIT_HOL_BLOCK_TIMER_n,
				ep_idx, &ep_holb);
			ipahal_write_reg_n_fields(
				IPA_ENDP_INIT_HOL_BLOCK_EN_n,
				ep_idx, &ep_holb);

			ipa3_cfg_ep_ctrl(ep_idx, &avoid_holb);
		}
@@ -1944,23 +1936,17 @@ bail_dma:
static void ipa3_q6_disable_agg_reg(struct ipa3_register_write *reg_write,
				   int ep_idx)
{
	struct ipahal_reg_valmask valmask;

	reg_write->skip_pipeline_clear = 0;
	reg_write->pipeline_clear_options = IPA_FULL_PIPELINE_CLEAR;

	reg_write->offset = IPA_ENDP_INIT_AGGR_N_OFST_v3_0(ep_idx);
	reg_write->value =
		(1 & IPA_ENDP_INIT_AGGR_N_AGGR_FORCE_CLOSE_BMSK) <<
		IPA_ENDP_INIT_AGGR_N_AGGR_FORCE_CLOSE_SHFT;
	reg_write->value_mask =
		IPA_ENDP_INIT_AGGR_N_AGGR_FORCE_CLOSE_BMSK <<
		IPA_ENDP_INIT_AGGR_N_AGGR_FORCE_CLOSE_SHFT;
	reg_write->offset = ipahal_get_reg_n_ofst(IPA_ENDP_INIT_AGGR_n, ep_idx);

	ipahal_get_disable_aggr_valmask(&valmask);

	reg_write->value |=
		((0 & IPA_ENDP_INIT_AGGR_N_AGGR_EN_BMSK) <<
		IPA_ENDP_INIT_AGGR_N_AGGR_EN_SHFT);
	reg_write->value_mask |=
		((IPA_ENDP_INIT_AGGR_N_AGGR_EN_BMSK <<
		IPA_ENDP_INIT_AGGR_N_AGGR_EN_SHFT));
	reg_write->value = valmask.val;
	reg_write->value_mask = valmask.mask;
}

static int ipa3_q6_set_ex_path_dis_agg(void)
@@ -1972,6 +1958,7 @@ static int ipa3_q6_set_ex_path_dis_agg(void)
	int index;
	struct ipa3_register_write *reg_write;
	int retval;
	struct ipahal_reg_valmask valmask;

	desc = kcalloc(ipa3_ctx->ipa_num_pipes, sizeof(struct ipa3_desc),
			GFP_KERNEL);
@@ -1998,14 +1985,13 @@ static int ipa3_q6_set_ex_path_dis_agg(void)
			reg_write->skip_pipeline_clear = 0;
			reg_write->pipeline_clear_options =
				IPA_FULL_PIPELINE_CLEAR;
			reg_write->offset = IPA_ENDP_STATUS_n_OFST(ep_idx);
			reg_write->value =
				(ipa3_get_ep_mapping(IPA_CLIENT_APPS_LAN_CONS) &
				IPA_ENDP_STATUS_n_STATUS_ENDP_BMSK) <<
				IPA_ENDP_STATUS_n_STATUS_ENDP_SHFT;
			reg_write->value_mask =
				IPA_ENDP_STATUS_n_STATUS_ENDP_BMSK <<
				IPA_ENDP_STATUS_n_STATUS_ENDP_SHFT;
			reg_write->offset =
				ipahal_get_reg_ofst(IPA_ENDP_STATUS_n);
			ipahal_get_status_ep_valmask(
				ipa3_get_ep_mapping(IPA_CLIENT_APPS_LAN_CONS),
				&valmask);
			reg_write->value = valmask.val;
			reg_write->value_mask = valmask.mask;

			desc[num_descs].opcode = IPA_REGISTER_WRITE;
			desc[num_descs].pyld = reg_write;
@@ -2146,7 +2132,7 @@ int _ipa_init_sram_v3_0(void)

	phys_addr = ipa3_ctx->ipa_wrapper_base +
		ipa3_ctx->ctrl->ipa_reg_base_ofst +
		IPA_SRAM_DIRECT_ACCESS_N_OFST_v3_0(
		ipahal_get_reg_n_ofst(IPA_SRAM_DIRECT_ACCESS_n,
			ipa3_ctx->smem_restricted_bytes / 4);

	ipa_sram_mmio = ioremap(phys_addr, ipa3_ctx->smem_sz);
@@ -2263,9 +2249,7 @@ int _ipa_init_hdr_v3_0(void)
		return -EFAULT;
	}

	ipa_write_reg(ipa3_ctx->mmio,
		IPA_LOCAL_PKT_PROC_CNTXT_BASE_OFST,
		dma_cmd.local_addr);
	ipahal_write_reg(IPA_LOCAL_PKT_PROC_CNTXT_BASE, dma_cmd.local_addr);

	dma_free_coherent(ipa3_ctx->pdev, mem.size, mem.base, mem.phys_base);

@@ -2563,9 +2547,9 @@ int _ipa_init_flt6_v3(void)
static int ipa3_setup_flt_hash_tuple(void)
{
	int pipe_idx;
	struct ipa3_hash_tuple tuple;
	struct ipahal_reg_hash_tuple tuple;

	memset(&tuple, 0, sizeof(struct ipa3_hash_tuple));
	memset(&tuple, 0, sizeof(struct ipahal_reg_hash_tuple));

	for (pipe_idx = 0; pipe_idx < ipa3_ctx->ipa_num_pipes ; pipe_idx++) {
		if (!ipa_is_ep_support_flt(pipe_idx))
@@ -2586,9 +2570,9 @@ static int ipa3_setup_flt_hash_tuple(void)
static int ipa3_setup_rt_hash_tuple(void)
{
	int tbl_idx;
	struct ipa3_hash_tuple tuple;
	struct ipahal_reg_hash_tuple tuple;

	memset(&tuple, 0, sizeof(struct ipa3_hash_tuple));
	memset(&tuple, 0, sizeof(struct ipahal_reg_hash_tuple));

	for (tbl_idx = 0;
		tbl_idx < max(IPA_MEM_PART(v6_rt_num_index),
@@ -4017,6 +4001,12 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
		goto fail_remap;
	}

	if (ipahal_init(ipa3_ctx->ipa_hw_type, ipa3_ctx->mmio)) {
		IPAERR("fail to init ipahal\n");
		result = -EFAULT;
		goto fail_ipahal;
	}

	result = ipa3_init_hw();
	if (result) {
		IPAERR(":error initializing HW.\n");
@@ -4404,8 +4394,10 @@ fail_clk:
	ipa3_active_clients_log_destroy();
fail_init_active_client:
	msm_bus_scale_unregister_client(ipa3_ctx->ipa_bus_hdl);
fail_bus_reg:
fail_ipahal:
	ipa3_bus_scale_table = NULL;
fail_bus_reg:
	ipahal_destroy();
fail_bind:
	kfree(ipa3_ctx->ctrl);
fail_mem_ctrl:
+18 −27
Original line number Diff line number Diff line
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -44,8 +44,7 @@ int ipa3_enable_data_path(u32 clnt_hdl)
	struct ipa_ep_cfg_holb holb_cfg;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
	int res = 0;
	u32 reg_val = 0;
	int ep_grp;
	struct ipahal_reg_endp_init_rsrc_grp rsrc_grp;

	IPADBG("Enabling data path\n");
	if (IPA_CLIENT_IS_CONS(ep->client)) {
@@ -66,20 +65,18 @@ int ipa3_enable_data_path(u32 clnt_hdl)
	}

	/* Assign the resource group for pipe */
	ep_grp = ipa_get_ep_group(ep->client);
	if (ep_grp == -1) {
	memset(&rsrc_grp, 0, sizeof(rsrc_grp));
	rsrc_grp.rsrc_grp = ipa_get_ep_group(ep->client);
	if (rsrc_grp.rsrc_grp == -1) {
		IPAERR("invalid group for client %d\n", ep->client);
		WARN_ON(1);
		return -EFAULT;
	}

	IPADBG("Setting group %d for pipe %d\n",
		ep_grp, clnt_hdl);
	IPA_SETFIELD_IN_REG(reg_val, ep_grp,
		IPA_ENDP_INIT_RSRC_GRP_n_RSRC_GRP_SHFT,
		IPA_ENDP_INIT_RSRC_GRP_n_RSRC_GRP_BMSK);
	ipa_write_reg(ipa3_ctx->mmio,
		IPA_ENDP_INIT_RSRC_GRP_n(clnt_hdl), reg_val);
		rsrc_grp.rsrc_grp, clnt_hdl);
	ipahal_write_reg_n_fields(IPA_ENDP_INIT_RSRC_GRP_n, clnt_hdl,
		&rsrc_grp);

	return res;
}
@@ -89,7 +86,7 @@ int ipa3_disable_data_path(u32 clnt_hdl)
	struct ipa3_ep_context *ep = &ipa3_ctx->ep[clnt_hdl];
	struct ipa_ep_cfg_holb holb_cfg;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
	u32 aggr_init;
	struct ipa_ep_cfg_aggr ep_aggr;
	int res = 0;

	IPADBG("Disabling data path\n");
@@ -108,10 +105,8 @@ int ipa3_disable_data_path(u32 clnt_hdl)
	}

	udelay(IPA_PKT_FLUSH_TO_US);
	aggr_init = ipa_read_reg(ipa3_ctx->mmio,
			IPA_ENDP_INIT_AGGR_N_OFST_v3_0(clnt_hdl));
	if (((aggr_init & IPA_ENDP_INIT_AGGR_N_AGGR_EN_BMSK) >>
	    IPA_ENDP_INIT_AGGR_N_AGGR_EN_SHFT) == IPA_ENABLE_AGGR) {
	ipahal_read_reg_n_fields(IPA_ENDP_INIT_AGGR_n, clnt_hdl, &ep_aggr);
	if (ep_aggr.aggr_en) {
		res = ipa3_tag_aggr_force_close(clnt_hdl);
		if (res) {
			IPAERR("tag process timeout, client:%d err:%d\n",
@@ -286,7 +281,7 @@ int ipa3_connect(const struct ipa_connect_params *in,
	int ipa_ep_idx;
	int result = -EFAULT;
	struct ipa3_ep_context *ep;
	struct ipa3_ep_cfg_status ep_status;
	struct ipahal_reg_ep_cfg_status ep_status;
	unsigned long base;
	struct iommu_domain *smmu_domain;

@@ -850,8 +845,7 @@ static int ipa3_reset_with_open_aggr_frame_wa(u32 clnt_hdl,
	int aggr_active_bitmap = 0;

	IPADBG("Applying reset channel with open aggregation frame WA\n");
	ipa_write_reg(ipa3_ctx->mmio, IPA_AGGR_FORCE_CLOSE_OFST,
		(1 << clnt_hdl));
	ipahal_write_reg(IPA_AGGR_FORCE_CLOSE, (1 << clnt_hdl));

	/* Reset channel */
	gsi_res = gsi_reset_channel(ep->gsi_chan_hdl);
@@ -900,8 +894,7 @@ static int ipa3_reset_with_open_aggr_frame_wa(u32 clnt_hdl,

	/* Wait for aggregation frame to be closed and stop channel*/
	for (i = 0; i < IPA_POLL_AGGR_STATE_RETRIES_NUM; i++) {
		aggr_active_bitmap = ipa_read_reg(ipa3_ctx->mmio,
			IPA_STATE_AGGR_ACTIVE_OFST);
		aggr_active_bitmap = ipahal_read_reg(IPA_STATE_AGGR_ACTIVE);
		if (!(aggr_active_bitmap & (1 << clnt_hdl)))
			break;
		msleep(IPA_POLL_AGGR_STATE_SLEEP_MSEC);
@@ -980,8 +973,7 @@ int ipa3_reset_gsi_channel(u32 clnt_hdl)
	 * reset with open aggregation frame WA
	 */
	if (IPA_CLIENT_IS_CONS(ep->client)) {
		aggr_active_bitmap = ipa_read_reg(ipa3_ctx->mmio,
				IPA_STATE_AGGR_ACTIVE_OFST);
		aggr_active_bitmap = ipahal_read_reg(IPA_STATE_AGGR_ACTIVE);
		if (aggr_active_bitmap & (1 << clnt_hdl)) {
			result = ipa3_reset_with_open_aggr_frame_wa(clnt_hdl,
				ep);
@@ -1067,7 +1059,7 @@ int ipa3_request_gsi_channel(struct ipa_request_gsi_channel_params *params,
	int ipa_ep_idx;
	int result = -EFAULT;
	struct ipa3_ep_context *ep;
	struct ipa3_ep_cfg_status ep_status;
	struct ipahal_reg_ep_cfg_status ep_status;
	unsigned long gsi_dev_hdl;
	enum gsi_status gsi_res;
	struct ipa_gsi_ep_config gsi_ep_cfg;
@@ -1714,8 +1706,7 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
	}

	if (!dl_data_pending) {
		aggr_active_bitmap = ipa_read_reg(ipa3_ctx->mmio,
				IPA_STATE_AGGR_ACTIVE_OFST);
		aggr_active_bitmap = ipahal_read_reg(IPA_STATE_AGGR_ACTIVE);
		if (aggr_active_bitmap & (1 << dl_clnt_hdl)) {
			IPADBG("DL/DPL data pending due to open aggr. frame\n");
			dl_data_pending = true;
Loading