blob: 2a780b60326390650e72f483cb00a40ead1c32c5 [file] [log] [blame]
/* Copyright (c) 2012-2017, 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
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/init.h>
#include <linux/ipa.h>
#include <linux/kernel.h>
#include <linux/msm_ipa.h>
#include "ipahal_i.h"
#include "ipahal_reg.h"
#include "ipahal_reg_i.h"
static const char *ipareg_name_to_str[IPA_REG_MAX] = {
__stringify(IPA_ROUTE),
__stringify(IPA_IRQ_STTS_EE_n),
__stringify(IPA_IRQ_EN_EE_n),
__stringify(IPA_IRQ_CLR_EE_n),
__stringify(IPA_IRQ_SUSPEND_INFO_EE_n),
__stringify(IPA_SUSPEND_IRQ_EN_EE_n),
__stringify(IPA_SUSPEND_IRQ_CLR_EE_n),
__stringify(IPA_BCR),
__stringify(IPA_ENABLED_PIPES),
__stringify(IPA_COMP_SW_RESET),
__stringify(IPA_VERSION),
__stringify(IPA_TAG_TIMER),
__stringify(IPA_COMP_HW_VERSION),
__stringify(IPA_SPARE_REG_1),
__stringify(IPA_SPARE_REG_2),
__stringify(IPA_COMP_CFG),
__stringify(IPA_STATE_AGGR_ACTIVE),
__stringify(IPA_ENDP_INIT_HDR_n),
__stringify(IPA_ENDP_INIT_HDR_EXT_n),
__stringify(IPA_ENDP_INIT_AGGR_n),
__stringify(IPA_AGGR_FORCE_CLOSE),
__stringify(IPA_ENDP_INIT_ROUTE_n),
__stringify(IPA_ENDP_INIT_MODE_n),
__stringify(IPA_ENDP_INIT_NAT_n),
__stringify(IPA_ENDP_INIT_CTRL_n),
__stringify(IPA_ENDP_INIT_CTRL_SCND_n),
__stringify(IPA_ENDP_INIT_HOL_BLOCK_EN_n),
__stringify(IPA_ENDP_INIT_HOL_BLOCK_TIMER_n),
__stringify(IPA_ENDP_INIT_DEAGGR_n),
__stringify(IPA_ENDP_INIT_SEQ_n),
__stringify(IPA_DEBUG_CNT_REG_n),
__stringify(IPA_ENDP_INIT_CFG_n),
__stringify(IPA_IRQ_EE_UC_n),
__stringify(IPA_ENDP_INIT_HDR_METADATA_MASK_n),
__stringify(IPA_ENDP_INIT_HDR_METADATA_n),
__stringify(IPA_ENDP_INIT_RSRC_GRP_n),
__stringify(IPA_SHARED_MEM_SIZE),
__stringify(IPA_SRAM_DIRECT_ACCESS_n),
__stringify(IPA_DEBUG_CNT_CTRL_n),
__stringify(IPA_UC_MAILBOX_m_n),
__stringify(IPA_FILT_ROUT_HASH_FLUSH),
__stringify(IPA_SINGLE_NDP_MODE),
__stringify(IPA_QCNCM),
__stringify(IPA_SYS_PKT_PROC_CNTXT_BASE),
__stringify(IPA_LOCAL_PKT_PROC_CNTXT_BASE),
__stringify(IPA_ENDP_STATUS_n),
__stringify(IPA_ENDP_FILTER_ROUTER_HSH_CFG_n),
__stringify(IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n),
__stringify(IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n),
__stringify(IPA_SRC_RSRC_GRP_45_RSRC_TYPE_n),
__stringify(IPA_SRC_RSRC_GRP_67_RSRC_TYPE_n),
__stringify(IPA_DST_RSRC_GRP_01_RSRC_TYPE_n),
__stringify(IPA_DST_RSRC_GRP_23_RSRC_TYPE_n),
__stringify(IPA_DST_RSRC_GRP_45_RSRC_TYPE_n),
__stringify(IPA_DST_RSRC_GRP_67_RSRC_TYPE_n),
__stringify(IPA_RX_HPS_CLIENTS_MIN_DEPTH_0),
__stringify(IPA_RX_HPS_CLIENTS_MIN_DEPTH_1),
__stringify(IPA_RX_HPS_CLIENTS_MAX_DEPTH_0),
__stringify(IPA_RX_HPS_CLIENTS_MAX_DEPTH_1),
__stringify(IPA_QSB_MAX_WRITES),
__stringify(IPA_QSB_MAX_READS),
__stringify(IPA_TX_CFG),
};
static void ipareg_construct_dummy(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
IPAHAL_ERR("No construct function for %s\n",
ipahal_reg_name_str(reg));
WARN_ON(1);
}
static void ipareg_parse_dummy(enum ipahal_reg_name reg,
void *fields, u32 val)
{
IPAHAL_ERR("No parse function for %s\n",
ipahal_reg_name_str(reg));
WARN_ON(1);
}
static void ipareg_construct_rx_hps_clients_depth1(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_rx_hps_clients *clients =
(struct ipahal_reg_rx_hps_clients *)fields;
IPA_SETFIELD_IN_REG(*val, clients->client_minmax[0],
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(0),
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK(0));
IPA_SETFIELD_IN_REG(*val, clients->client_minmax[1],
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(1),
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK(1));
}
static void ipareg_construct_rx_hps_clients_depth0(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_rx_hps_clients *clients =
(struct ipahal_reg_rx_hps_clients *)fields;
IPA_SETFIELD_IN_REG(*val, clients->client_minmax[0],
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(0),
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK(0));
IPA_SETFIELD_IN_REG(*val, clients->client_minmax[1],
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(1),
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK(1));
IPA_SETFIELD_IN_REG(*val, clients->client_minmax[2],
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(2),
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK(2));
IPA_SETFIELD_IN_REG(*val, clients->client_minmax[3],
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(3),
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK(3));
}
static void ipareg_construct_rx_hps_clients_depth0_v3_5(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_rx_hps_clients *clients =
(struct ipahal_reg_rx_hps_clients *)fields;
IPA_SETFIELD_IN_REG(*val, clients->client_minmax[0],
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(0),
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK_V3_5(0));
IPA_SETFIELD_IN_REG(*val, clients->client_minmax[1],
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(1),
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK_V3_5(1));
IPA_SETFIELD_IN_REG(*val, clients->client_minmax[2],
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(2),
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK_V3_5(2));
IPA_SETFIELD_IN_REG(*val, clients->client_minmax[3],
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_SHFT(3),
IPA_RX_HPS_CLIENTS_MINMAX_DEPTH_X_CLIENT_n_BMSK_V3_5(3));
}
static void ipareg_construct_rsrg_grp_xy(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_rsrc_grp_cfg *grp =
(struct ipahal_reg_rsrc_grp_cfg *)fields;
IPA_SETFIELD_IN_REG(*val, grp->x_min,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MIN_LIM_SHFT,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MIN_LIM_BMSK);
IPA_SETFIELD_IN_REG(*val, grp->x_max,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MAX_LIM_SHFT,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MAX_LIM_BMSK);
IPA_SETFIELD_IN_REG(*val, grp->y_min,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MIN_LIM_SHFT,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MIN_LIM_BMSK);
IPA_SETFIELD_IN_REG(*val, grp->y_max,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MAX_LIM_SHFT,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MAX_LIM_BMSK);
}
static void ipareg_construct_rsrg_grp_xy_v3_5(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_rsrc_grp_cfg *grp =
(struct ipahal_reg_rsrc_grp_cfg *)fields;
IPA_SETFIELD_IN_REG(*val, grp->x_min,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MIN_LIM_SHFT_V3_5,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MIN_LIM_BMSK_V3_5);
IPA_SETFIELD_IN_REG(*val, grp->x_max,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MAX_LIM_SHFT_V3_5,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_X_MAX_LIM_BMSK_V3_5);
/* DST_23 register has only X fields at ipa V3_5 */
if (reg == IPA_DST_RSRC_GRP_23_RSRC_TYPE_n)
return;
IPA_SETFIELD_IN_REG(*val, grp->y_min,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MIN_LIM_SHFT_V3_5,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MIN_LIM_BMSK_V3_5);
IPA_SETFIELD_IN_REG(*val, grp->y_max,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MAX_LIM_SHFT_V3_5,
IPA_RSRC_GRP_XY_RSRC_TYPE_n_Y_MAX_LIM_BMSK_V3_5);
}
static void ipareg_construct_hash_cfg_n(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_fltrt_hash_tuple *tuple =
(struct ipahal_reg_fltrt_hash_tuple *)fields;
IPA_SETFIELD_IN_REG(*val, tuple->flt.src_id,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_ID_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_ID_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->flt.src_ip_addr,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_IP_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_IP_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->flt.dst_ip_addr,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_DST_IP_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_DST_IP_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->flt.src_port,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_PORT_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_PORT_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->flt.dst_port,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_DST_PORT_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_DST_PORT_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->flt.protocol,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_PROTOCOL_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_PROTOCOL_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->flt.meta_data,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_METADATA_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_METADATA_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->undefined1,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED1_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED1_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->rt.src_id,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_ID_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_ID_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->rt.src_ip_addr,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_IP_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_IP_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->rt.dst_ip_addr,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_DST_IP_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_DST_IP_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->rt.src_port,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_PORT_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_PORT_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->rt.dst_port,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_DST_PORT_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_DST_PORT_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->rt.protocol,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_PROTOCOL_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_PROTOCOL_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->rt.meta_data,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_METADATA_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_METADATA_BMSK);
IPA_SETFIELD_IN_REG(*val, tuple->undefined2,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED2_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED2_BMSK);
}
static void ipareg_parse_hash_cfg_n(
enum ipahal_reg_name reg, void *fields, u32 val)
{
struct ipahal_reg_fltrt_hash_tuple *tuple =
(struct ipahal_reg_fltrt_hash_tuple *)fields;
tuple->flt.src_id =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_ID_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_ID_BMSK);
tuple->flt.src_ip_addr =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_IP_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_IP_BMSK);
tuple->flt.dst_ip_addr =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_DST_IP_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_DST_IP_BMSK);
tuple->flt.src_port =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_PORT_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_SRC_PORT_BMSK);
tuple->flt.dst_port =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_DST_PORT_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_DST_PORT_BMSK);
tuple->flt.protocol =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_PROTOCOL_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_PROTOCOL_BMSK);
tuple->flt.meta_data =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_METADATA_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_FILTER_HASH_MSK_METADATA_BMSK);
tuple->undefined1 =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED1_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED1_BMSK);
tuple->rt.src_id =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_ID_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_ID_BMSK);
tuple->rt.src_ip_addr =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_IP_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_IP_BMSK);
tuple->rt.dst_ip_addr =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_DST_IP_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_DST_IP_BMSK);
tuple->rt.src_port =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_PORT_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_SRC_PORT_BMSK);
tuple->rt.dst_port =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_DST_PORT_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_DST_PORT_BMSK);
tuple->rt.protocol =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_PROTOCOL_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_PROTOCOL_BMSK);
tuple->rt.meta_data =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_METADATA_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_ROUTER_HASH_MSK_METADATA_BMSK);
tuple->undefined2 =
IPA_GETFIELD_FROM_REG(val,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED2_SHFT,
IPA_ENDP_FILTER_ROUTER_HSH_CFG_n_UNDEFINED2_BMSK);
}
static void ipareg_construct_endp_status_n(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_ep_cfg_status *ep_status =
(struct ipahal_reg_ep_cfg_status *)fields;
IPA_SETFIELD_IN_REG(*val, ep_status->status_en,
IPA_ENDP_STATUS_n_STATUS_EN_SHFT,
IPA_ENDP_STATUS_n_STATUS_EN_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_status->status_ep,
IPA_ENDP_STATUS_n_STATUS_ENDP_SHFT,
IPA_ENDP_STATUS_n_STATUS_ENDP_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_status->status_location,
IPA_ENDP_STATUS_n_STATUS_LOCATION_SHFT,
IPA_ENDP_STATUS_n_STATUS_LOCATION_BMSK);
}
static void ipareg_construct_qcncm(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_qcncm *qcncm =
(struct ipahal_reg_qcncm *)fields;
IPA_SETFIELD_IN_REG(*val, qcncm->mode_en ? 1 : 0,
IPA_QCNCM_MODE_EN_SHFT,
IPA_QCNCM_MODE_EN_BMSK);
IPA_SETFIELD_IN_REG(*val, qcncm->mode_val,
IPA_QCNCM_MODE_VAL_SHFT,
IPA_QCNCM_MODE_VAL_BMSK);
IPA_SETFIELD_IN_REG(*val, qcncm->undefined,
0, IPA_QCNCM_MODE_VAL_BMSK);
}
static void ipareg_parse_qcncm(
enum ipahal_reg_name reg, void *fields, u32 val)
{
struct ipahal_reg_qcncm *qcncm =
(struct ipahal_reg_qcncm *)fields;
memset(qcncm, 0, sizeof(struct ipahal_reg_qcncm));
qcncm->mode_en = IPA_GETFIELD_FROM_REG(val,
IPA_QCNCM_MODE_EN_SHFT,
IPA_QCNCM_MODE_EN_BMSK);
qcncm->mode_val = IPA_GETFIELD_FROM_REG(val,
IPA_QCNCM_MODE_VAL_SHFT,
IPA_QCNCM_MODE_VAL_BMSK);
qcncm->undefined = IPA_GETFIELD_FROM_REG(val,
0, IPA_QCNCM_UNDEFINED1_BMSK);
qcncm->undefined |= IPA_GETFIELD_FROM_REG(val,
0, IPA_QCNCM_MODE_UNDEFINED2_BMSK);
}
static void ipareg_construct_single_ndp_mode(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_single_ndp_mode *mode =
(struct ipahal_reg_single_ndp_mode *)fields;
IPA_SETFIELD_IN_REG(*val, mode->single_ndp_en ? 1 : 0,
IPA_SINGLE_NDP_MODE_SINGLE_NDP_EN_SHFT,
IPA_SINGLE_NDP_MODE_SINGLE_NDP_EN_BMSK);
IPA_SETFIELD_IN_REG(*val, mode->undefined,
IPA_SINGLE_NDP_MODE_UNDEFINED_SHFT,
IPA_SINGLE_NDP_MODE_UNDEFINED_BMSK);
}
static void ipareg_parse_single_ndp_mode(
enum ipahal_reg_name reg, void *fields, u32 val)
{
struct ipahal_reg_single_ndp_mode *mode =
(struct ipahal_reg_single_ndp_mode *)fields;
memset(mode, 0, sizeof(struct ipahal_reg_single_ndp_mode));
mode->single_ndp_en = IPA_GETFIELD_FROM_REG(val,
IPA_SINGLE_NDP_MODE_SINGLE_NDP_EN_SHFT,
IPA_SINGLE_NDP_MODE_SINGLE_NDP_EN_BMSK);
mode->undefined = IPA_GETFIELD_FROM_REG(val,
IPA_SINGLE_NDP_MODE_UNDEFINED_SHFT,
IPA_SINGLE_NDP_MODE_UNDEFINED_BMSK);
}
static void ipareg_construct_debug_cnt_ctrl_n(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_debug_cnt_ctrl *dbg_cnt_ctrl =
(struct ipahal_reg_debug_cnt_ctrl *)fields;
u8 type;
IPA_SETFIELD_IN_REG(*val, dbg_cnt_ctrl->en ? 1 : 0,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_EN_SHFT,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_EN_BMSK);
switch (dbg_cnt_ctrl->type) {
case DBG_CNT_TYPE_IPV4_FLTR:
type = 0x0;
if (!dbg_cnt_ctrl->rule_idx_pipe_rule) {
IPAHAL_ERR("No FLT global rules\n");
WARN_ON(1);
}
break;
case DBG_CNT_TYPE_IPV4_ROUT:
type = 0x1;
break;
case DBG_CNT_TYPE_GENERAL:
type = 0x2;
break;
case DBG_CNT_TYPE_IPV6_FLTR:
type = 0x4;
if (!dbg_cnt_ctrl->rule_idx_pipe_rule) {
IPAHAL_ERR("No FLT global rules\n");
WARN_ON(1);
}
break;
case DBG_CNT_TYPE_IPV6_ROUT:
type = 0x5;
break;
default:
IPAHAL_ERR("Invalid dbg_cnt_ctrl type (%d) for %s\n",
dbg_cnt_ctrl->type, ipahal_reg_name_str(reg));
WARN_ON(1);
return;
};
IPA_SETFIELD_IN_REG(*val, type,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_TYPE_SHFT,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_TYPE_BMSK);
IPA_SETFIELD_IN_REG(*val, dbg_cnt_ctrl->product ? 1 : 0,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_PRODUCT_SHFT,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_PRODUCT_BMSK);
IPA_SETFIELD_IN_REG(*val, dbg_cnt_ctrl->src_pipe,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_SOURCE_PIPE_SHFT,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_SOURCE_PIPE_BMSK);
if (ipahal_ctx->hw_type <= IPA_HW_v3_1) {
IPA_SETFIELD_IN_REG(*val, dbg_cnt_ctrl->rule_idx,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_RULE_INDEX_SHFT,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_RULE_INDEX_BMSK);
IPA_SETFIELD_IN_REG(*val, dbg_cnt_ctrl->rule_idx_pipe_rule,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_RULE_INDEX_PIPE_RULE_SHFT,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_RULE_INDEX_PIPE_RULE_BMSK
);
} else {
IPA_SETFIELD_IN_REG(*val, dbg_cnt_ctrl->rule_idx,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_RULE_INDEX_SHFT,
IPA_DEBUG_CNT_CTRL_n_DBG_CNT_RULE_INDEX_BMSK_V3_5);
}
}
static void ipareg_parse_shared_mem_size(
enum ipahal_reg_name reg, void *fields, u32 val)
{
struct ipahal_reg_shared_mem_size *smem_sz =
(struct ipahal_reg_shared_mem_size *)fields;
memset(smem_sz, 0, sizeof(struct ipahal_reg_shared_mem_size));
smem_sz->shared_mem_sz = IPA_GETFIELD_FROM_REG(val,
IPA_SHARED_MEM_SIZE_SHARED_MEM_SIZE_SHFT,
IPA_SHARED_MEM_SIZE_SHARED_MEM_SIZE_BMSK);
smem_sz->shared_mem_baddr = IPA_GETFIELD_FROM_REG(val,
IPA_SHARED_MEM_SIZE_SHARED_MEM_BADDR_SHFT,
IPA_SHARED_MEM_SIZE_SHARED_MEM_BADDR_BMSK);
}
static void ipareg_construct_endp_init_rsrc_grp_n(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_endp_init_rsrc_grp *rsrc_grp =
(struct ipahal_reg_endp_init_rsrc_grp *)fields;
IPA_SETFIELD_IN_REG(*val, rsrc_grp->rsrc_grp,
IPA_ENDP_INIT_RSRC_GRP_n_RSRC_GRP_SHFT,
IPA_ENDP_INIT_RSRC_GRP_n_RSRC_GRP_BMSK);
}
static void ipareg_construct_endp_init_rsrc_grp_n_v3_5(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipahal_reg_endp_init_rsrc_grp *rsrc_grp =
(struct ipahal_reg_endp_init_rsrc_grp *)fields;
IPA_SETFIELD_IN_REG(*val, rsrc_grp->rsrc_grp,
IPA_ENDP_INIT_RSRC_GRP_n_RSRC_GRP_SHFT_v3_5,
IPA_ENDP_INIT_RSRC_GRP_n_RSRC_GRP_BMSK_v3_5);
}
static void ipareg_construct_endp_init_hdr_metadata_n(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipa_ep_cfg_metadata *metadata =
(struct ipa_ep_cfg_metadata *)fields;
IPA_SETFIELD_IN_REG(*val, metadata->qmap_id,
IPA_ENDP_INIT_HDR_METADATA_n_METADATA_SHFT,
IPA_ENDP_INIT_HDR_METADATA_n_METADATA_BMSK);
}
static void ipareg_construct_endp_init_hdr_metadata_mask_n(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipa_ep_cfg_metadata_mask *metadata_mask =
(struct ipa_ep_cfg_metadata_mask *)fields;
IPA_SETFIELD_IN_REG(*val, metadata_mask->metadata_mask,
IPA_ENDP_INIT_HDR_METADATA_MASK_n_METADATA_MASK_SHFT,
IPA_ENDP_INIT_HDR_METADATA_MASK_n_METADATA_MASK_BMSK);
}
static void ipareg_construct_endp_init_cfg_n(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipa_ep_cfg_cfg *cfg =
(struct ipa_ep_cfg_cfg *)fields;
u32 cs_offload_en;
switch (cfg->cs_offload_en) {
case IPA_DISABLE_CS_OFFLOAD:
cs_offload_en = 0;
break;
case IPA_ENABLE_CS_OFFLOAD_UL:
cs_offload_en = 1;
break;
case IPA_ENABLE_CS_OFFLOAD_DL:
cs_offload_en = 2;
break;
default:
IPAHAL_ERR("Invalid cs_offload_en value for %s\n",
ipahal_reg_name_str(reg));
WARN_ON(1);
return;
}
IPA_SETFIELD_IN_REG(*val, cfg->frag_offload_en ? 1 : 0,
IPA_ENDP_INIT_CFG_n_FRAG_OFFLOAD_EN_SHFT,
IPA_ENDP_INIT_CFG_n_FRAG_OFFLOAD_EN_BMSK);
IPA_SETFIELD_IN_REG(*val, cs_offload_en,
IPA_ENDP_INIT_CFG_n_CS_OFFLOAD_EN_SHFT,
IPA_ENDP_INIT_CFG_n_CS_OFFLOAD_EN_BMSK);
IPA_SETFIELD_IN_REG(*val, cfg->cs_metadata_hdr_offset,
IPA_ENDP_INIT_CFG_n_CS_METADATA_HDR_OFFSET_SHFT,
IPA_ENDP_INIT_CFG_n_CS_METADATA_HDR_OFFSET_BMSK);
IPA_SETFIELD_IN_REG(*val, cfg->gen_qmb_master_sel,
IPA_ENDP_INIT_CFG_n_CS_GEN_QMB_MASTER_SEL_SHFT,
IPA_ENDP_INIT_CFG_n_CS_GEN_QMB_MASTER_SEL_BMSK);
}
static void ipareg_construct_endp_init_deaggr_n(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipa_ep_cfg_deaggr *ep_deaggr =
(struct ipa_ep_cfg_deaggr *)fields;
IPA_SETFIELD_IN_REG(*val, ep_deaggr->deaggr_hdr_len,
IPA_ENDP_INIT_DEAGGR_n_DEAGGR_HDR_LEN_SHFT,
IPA_ENDP_INIT_DEAGGR_n_DEAGGR_HDR_LEN_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_deaggr->packet_offset_valid,
IPA_ENDP_INIT_DEAGGR_n_PACKET_OFFSET_VALID_SHFT,
IPA_ENDP_INIT_DEAGGR_n_PACKET_OFFSET_VALID_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_deaggr->packet_offset_location,
IPA_ENDP_INIT_DEAGGR_n_PACKET_OFFSET_LOCATION_SHFT,
IPA_ENDP_INIT_DEAGGR_n_PACKET_OFFSET_LOCATION_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_deaggr->max_packet_len,
IPA_ENDP_INIT_DEAGGR_n_MAX_PACKET_LEN_SHFT,
IPA_ENDP_INIT_DEAGGR_n_MAX_PACKET_LEN_BMSK);
}
static void ipareg_construct_endp_init_hol_block_en_n(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipa_ep_cfg_holb *ep_holb =
(struct ipa_ep_cfg_holb *)fields;
IPA_SETFIELD_IN_REG(*val, ep_holb->en,
IPA_ENDP_INIT_HOL_BLOCK_EN_n_EN_SHFT,
IPA_ENDP_INIT_HOL_BLOCK_EN_n_EN_BMSK);
}
static void ipareg_construct_endp_init_hol_block_timer_n(
enum ipahal_reg_name reg, const void *fields, u32 *val)
{
struct ipa_ep_cfg_holb *ep_holb =
(struct ipa_ep_cfg_holb *)fields;
IPA_SETFIELD_IN_REG(*val, ep_holb->tmr_val,
IPA_ENDP_INIT_HOL_BLOCK_TIMER_n_TIMER_SHFT,
IPA_ENDP_INIT_HOL_BLOCK_TIMER_n_TIMER_BMSK);
}
static void ipareg_construct_endp_init_ctrl_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipa_ep_cfg_ctrl *ep_ctrl =
(struct ipa_ep_cfg_ctrl *)fields;
IPA_SETFIELD_IN_REG(*val, ep_ctrl->ipa_ep_suspend,
IPA_ENDP_INIT_CTRL_n_ENDP_SUSPEND_SHFT,
IPA_ENDP_INIT_CTRL_n_ENDP_SUSPEND_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_ctrl->ipa_ep_delay,
IPA_ENDP_INIT_CTRL_n_ENDP_DELAY_SHFT,
IPA_ENDP_INIT_CTRL_n_ENDP_DELAY_BMSK);
}
static void ipareg_construct_endp_init_ctrl_scnd_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipahal_ep_cfg_ctrl_scnd *ep_ctrl_scnd =
(struct ipahal_ep_cfg_ctrl_scnd *)fields;
IPA_SETFIELD_IN_REG(*val, ep_ctrl_scnd->endp_delay,
IPA_ENDP_INIT_CTRL_SCND_n_ENDP_DELAY_SHFT,
IPA_ENDP_INIT_CTRL_SCND_n_ENDP_DELAY_BMSK);
}
static void ipareg_construct_endp_init_nat_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipa_ep_cfg_nat *ep_nat =
(struct ipa_ep_cfg_nat *)fields;
IPA_SETFIELD_IN_REG(*val, ep_nat->nat_en,
IPA_ENDP_INIT_NAT_n_NAT_EN_SHFT,
IPA_ENDP_INIT_NAT_n_NAT_EN_BMSK);
}
static void ipareg_construct_endp_init_mode_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipahal_reg_endp_init_mode *init_mode =
(struct ipahal_reg_endp_init_mode *)fields;
IPA_SETFIELD_IN_REG(*val, init_mode->ep_mode.mode,
IPA_ENDP_INIT_MODE_n_MODE_SHFT,
IPA_ENDP_INIT_MODE_n_MODE_BMSK);
IPA_SETFIELD_IN_REG(*val, init_mode->dst_pipe_number,
IPA_ENDP_INIT_MODE_n_DEST_PIPE_INDEX_SHFT,
IPA_ENDP_INIT_MODE_n_DEST_PIPE_INDEX_BMSK);
}
static void ipareg_construct_endp_init_route_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipahal_reg_endp_init_route *ep_init_rt =
(struct ipahal_reg_endp_init_route *)fields;
IPA_SETFIELD_IN_REG(*val, ep_init_rt->route_table_index,
IPA_ENDP_INIT_ROUTE_n_ROUTE_TABLE_INDEX_SHFT,
IPA_ENDP_INIT_ROUTE_n_ROUTE_TABLE_INDEX_BMSK);
}
static void ipareg_parse_endp_init_aggr_n(enum ipahal_reg_name reg,
void *fields, u32 val)
{
struct ipa_ep_cfg_aggr *ep_aggr =
(struct ipa_ep_cfg_aggr *)fields;
memset(ep_aggr, 0, sizeof(struct ipa_ep_cfg_aggr));
ep_aggr->aggr_en =
(((val & IPA_ENDP_INIT_AGGR_n_AGGR_EN_BMSK) >>
IPA_ENDP_INIT_AGGR_n_AGGR_EN_SHFT)
== IPA_ENABLE_AGGR);
ep_aggr->aggr =
((val & IPA_ENDP_INIT_AGGR_n_AGGR_TYPE_BMSK) >>
IPA_ENDP_INIT_AGGR_n_AGGR_TYPE_SHFT);
ep_aggr->aggr_byte_limit =
((val & IPA_ENDP_INIT_AGGR_n_AGGR_BYTE_LIMIT_BMSK) >>
IPA_ENDP_INIT_AGGR_n_AGGR_BYTE_LIMIT_SHFT);
ep_aggr->aggr_time_limit =
((val & IPA_ENDP_INIT_AGGR_n_AGGR_TIME_LIMIT_BMSK) >>
IPA_ENDP_INIT_AGGR_n_AGGR_TIME_LIMIT_SHFT);
ep_aggr->aggr_pkt_limit =
((val & IPA_ENDP_INIT_AGGR_n_AGGR_PKT_LIMIT_BMSK) >>
IPA_ENDP_INIT_AGGR_n_AGGR_PKT_LIMIT_SHFT);
ep_aggr->aggr_sw_eof_active =
((val & IPA_ENDP_INIT_AGGR_n_AGGR_SW_EOF_ACTIVE_BMSK) >>
IPA_ENDP_INIT_AGGR_n_AGGR_SW_EOF_ACTIVE_SHFT);
ep_aggr->aggr_hard_byte_limit_en =
((val & IPA_ENDP_INIT_AGGR_n_AGGR_HARD_BYTE_LIMIT_ENABLE_BMSK)
>>
IPA_ENDP_INIT_AGGR_n_AGGR_HARD_BYTE_LIMIT_ENABLE_SHFT);
}
static void ipareg_construct_endp_init_aggr_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipa_ep_cfg_aggr *ep_aggr =
(struct ipa_ep_cfg_aggr *)fields;
IPA_SETFIELD_IN_REG(*val, ep_aggr->aggr_en,
IPA_ENDP_INIT_AGGR_n_AGGR_EN_SHFT,
IPA_ENDP_INIT_AGGR_n_AGGR_EN_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_aggr->aggr,
IPA_ENDP_INIT_AGGR_n_AGGR_TYPE_SHFT,
IPA_ENDP_INIT_AGGR_n_AGGR_TYPE_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_aggr->aggr_byte_limit,
IPA_ENDP_INIT_AGGR_n_AGGR_BYTE_LIMIT_SHFT,
IPA_ENDP_INIT_AGGR_n_AGGR_BYTE_LIMIT_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_aggr->aggr_time_limit,
IPA_ENDP_INIT_AGGR_n_AGGR_TIME_LIMIT_SHFT,
IPA_ENDP_INIT_AGGR_n_AGGR_TIME_LIMIT_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_aggr->aggr_pkt_limit,
IPA_ENDP_INIT_AGGR_n_AGGR_PKT_LIMIT_SHFT,
IPA_ENDP_INIT_AGGR_n_AGGR_PKT_LIMIT_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_aggr->aggr_sw_eof_active,
IPA_ENDP_INIT_AGGR_n_AGGR_SW_EOF_ACTIVE_SHFT,
IPA_ENDP_INIT_AGGR_n_AGGR_SW_EOF_ACTIVE_BMSK);
/* At IPAv3 hard_byte_limit is not supported */
ep_aggr->aggr_hard_byte_limit_en = 0;
IPA_SETFIELD_IN_REG(*val, ep_aggr->aggr_hard_byte_limit_en,
IPA_ENDP_INIT_AGGR_n_AGGR_HARD_BYTE_LIMIT_ENABLE_SHFT,
IPA_ENDP_INIT_AGGR_n_AGGR_HARD_BYTE_LIMIT_ENABLE_BMSK);
}
static void ipareg_construct_endp_init_hdr_ext_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipa_ep_cfg_hdr_ext *ep_hdr_ext;
u8 hdr_endianness;
ep_hdr_ext = (struct ipa_ep_cfg_hdr_ext *)fields;
hdr_endianness = ep_hdr_ext->hdr_little_endian ? 0 : 1;
IPA_SETFIELD_IN_REG(*val, ep_hdr_ext->hdr_pad_to_alignment,
IPA_ENDP_INIT_HDR_EXT_n_HDR_PAD_TO_ALIGNMENT_SHFT,
IPA_ENDP_INIT_HDR_EXT_n_HDR_PAD_TO_ALIGNMENT_BMSK_v3_0);
IPA_SETFIELD_IN_REG(*val, ep_hdr_ext->hdr_total_len_or_pad_offset,
IPA_ENDP_INIT_HDR_EXT_n_HDR_TOTAL_LEN_OR_PAD_OFFSET_SHFT,
IPA_ENDP_INIT_HDR_EXT_n_HDR_TOTAL_LEN_OR_PAD_OFFSET_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_hdr_ext->hdr_payload_len_inc_padding,
IPA_ENDP_INIT_HDR_EXT_n_HDR_PAYLOAD_LEN_INC_PADDING_SHFT,
IPA_ENDP_INIT_HDR_EXT_n_HDR_PAYLOAD_LEN_INC_PADDING_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_hdr_ext->hdr_total_len_or_pad,
IPA_ENDP_INIT_HDR_EXT_n_HDR_TOTAL_LEN_OR_PAD_SHFT,
IPA_ENDP_INIT_HDR_EXT_n_HDR_TOTAL_LEN_OR_PAD_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_hdr_ext->hdr_total_len_or_pad_valid,
IPA_ENDP_INIT_HDR_EXT_n_HDR_TOTAL_LEN_OR_PAD_VALID_SHFT,
IPA_ENDP_INIT_HDR_EXT_n_HDR_TOTAL_LEN_OR_PAD_VALID_BMSK);
IPA_SETFIELD_IN_REG(*val, hdr_endianness,
IPA_ENDP_INIT_HDR_EXT_n_HDR_ENDIANNESS_SHFT,
IPA_ENDP_INIT_HDR_EXT_n_HDR_ENDIANNESS_BMSK);
}
static void ipareg_construct_endp_init_hdr_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipa_ep_cfg_hdr *ep_hdr;
ep_hdr = (struct ipa_ep_cfg_hdr *)fields;
IPA_SETFIELD_IN_REG(*val, ep_hdr->hdr_metadata_reg_valid,
IPA_ENDP_INIT_HDR_n_HDR_METADATA_REG_VALID_SHFT_v2,
IPA_ENDP_INIT_HDR_n_HDR_METADATA_REG_VALID_BMSK_v2);
IPA_SETFIELD_IN_REG(*val, ep_hdr->hdr_remove_additional,
IPA_ENDP_INIT_HDR_n_HDR_LEN_INC_DEAGG_HDR_SHFT_v2,
IPA_ENDP_INIT_HDR_n_HDR_LEN_INC_DEAGG_HDR_BMSK_v2);
IPA_SETFIELD_IN_REG(*val, ep_hdr->hdr_a5_mux,
IPA_ENDP_INIT_HDR_n_HDR_A5_MUX_SHFT,
IPA_ENDP_INIT_HDR_n_HDR_A5_MUX_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_hdr->hdr_ofst_pkt_size,
IPA_ENDP_INIT_HDR_n_HDR_OFST_PKT_SIZE_SHFT,
IPA_ENDP_INIT_HDR_n_HDR_OFST_PKT_SIZE_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_hdr->hdr_ofst_pkt_size_valid,
IPA_ENDP_INIT_HDR_n_HDR_OFST_PKT_SIZE_VALID_SHFT,
IPA_ENDP_INIT_HDR_n_HDR_OFST_PKT_SIZE_VALID_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_hdr->hdr_additional_const_len,
IPA_ENDP_INIT_HDR_n_HDR_ADDITIONAL_CONST_LEN_SHFT,
IPA_ENDP_INIT_HDR_n_HDR_ADDITIONAL_CONST_LEN_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_hdr->hdr_ofst_metadata,
IPA_ENDP_INIT_HDR_n_HDR_OFST_METADATA_SHFT,
IPA_ENDP_INIT_HDR_n_HDR_OFST_METADATA_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_hdr->hdr_ofst_metadata_valid,
IPA_ENDP_INIT_HDR_n_HDR_OFST_METADATA_VALID_SHFT,
IPA_ENDP_INIT_HDR_n_HDR_OFST_METADATA_VALID_BMSK);
IPA_SETFIELD_IN_REG(*val, ep_hdr->hdr_len,
IPA_ENDP_INIT_HDR_n_HDR_LEN_SHFT,
IPA_ENDP_INIT_HDR_n_HDR_LEN_BMSK);
}
static void ipareg_construct_route(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipahal_reg_route *route;
route = (struct ipahal_reg_route *)fields;
IPA_SETFIELD_IN_REG(*val, route->route_dis,
IPA_ROUTE_ROUTE_DIS_SHFT,
IPA_ROUTE_ROUTE_DIS_BMSK);
IPA_SETFIELD_IN_REG(*val, route->route_def_pipe,
IPA_ROUTE_ROUTE_DEF_PIPE_SHFT,
IPA_ROUTE_ROUTE_DEF_PIPE_BMSK);
IPA_SETFIELD_IN_REG(*val, route->route_def_hdr_table,
IPA_ROUTE_ROUTE_DEF_HDR_TABLE_SHFT,
IPA_ROUTE_ROUTE_DEF_HDR_TABLE_BMSK);
IPA_SETFIELD_IN_REG(*val, route->route_def_hdr_ofst,
IPA_ROUTE_ROUTE_DEF_HDR_OFST_SHFT,
IPA_ROUTE_ROUTE_DEF_HDR_OFST_BMSK);
IPA_SETFIELD_IN_REG(*val, route->route_frag_def_pipe,
IPA_ROUTE_ROUTE_FRAG_DEF_PIPE_SHFT,
IPA_ROUTE_ROUTE_FRAG_DEF_PIPE_BMSK);
IPA_SETFIELD_IN_REG(*val, route->route_def_retain_hdr,
IPA_ROUTE_ROUTE_DEF_RETAIN_HDR_SHFT,
IPA_ROUTE_ROUTE_DEF_RETAIN_HDR_BMSK);
}
static void ipareg_construct_qsb_max_writes(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
int *qsb_max_writes = (int *)fields;
IPA_SETFIELD_IN_REG(*val, qsb_max_writes[0],
IPA_QSB_MAX_WRITES_GEN_QMB_0_MAX_WRITES_SHFT,
IPA_QSB_MAX_WRITES_GEN_QMB_0_MAX_WRITES_BMSK);
IPA_SETFIELD_IN_REG(*val, qsb_max_writes[1],
IPA_QSB_MAX_WRITES_GEN_QMB_1_MAX_WRITES_SHFT,
IPA_QSB_MAX_WRITES_GEN_QMB_1_MAX_WRITES_BMSK);
}
static void ipareg_construct_qsb_max_reads(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
int *qsb_max_reads = (int *)fields;
IPA_SETFIELD_IN_REG(*val, qsb_max_reads[0],
IPA_QSB_MAX_READS_GEN_QMB_0_MAX_READS_SHFT,
IPA_QSB_MAX_READS_GEN_QMB_0_MAX_READS_BMSK);
IPA_SETFIELD_IN_REG(*val, qsb_max_reads[1],
IPA_QSB_MAX_READS_GEN_QMB_1_MAX_READS_SHFT,
IPA_QSB_MAX_READS_GEN_QMB_1_MAX_READS_BMSK);
}
static void ipareg_construct_tx_cfg(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipahal_reg_tx_cfg *tx_cfg;
tx_cfg = (struct ipahal_reg_tx_cfg *)fields;
IPA_SETFIELD_IN_REG(*val, tx_cfg->tx0_prefetch_disable,
IPA_TX_CFG_TX0_PREFETCH_DISABLE_SHFT_V3_5,
IPA_TX_CFG_TX0_PREFETCH_DISABLE_BMSK_V3_5);
IPA_SETFIELD_IN_REG(*val, tx_cfg->tx1_prefetch_disable,
IPA_TX_CFG_TX1_PREFETCH_DISABLE_SHFT_V3_5,
IPA_TX_CFG_TX1_PREFETCH_DISABLE_BMSK_V3_5);
IPA_SETFIELD_IN_REG(*val, tx_cfg->prefetch_almost_empty_size,
IPA_TX_CFG_PREFETCH_ALMOST_EMPTY_SIZE_SHFT_V3_5,
IPA_TX_CFG_PREFETCH_ALMOST_EMPTY_SIZE_BMSK_V3_5);
}
static void ipareg_construct_idle_indication_cfg(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
struct ipahal_reg_idle_indication_cfg *idle_indication_cfg;
idle_indication_cfg = (struct ipahal_reg_idle_indication_cfg *)fields;
IPA_SETFIELD_IN_REG(*val,
idle_indication_cfg->enter_idle_debounce_thresh,
IPA_IDLE_INDICATION_CFG_ENTER_IDLE_DEBOUNCE_THRESH_SHFT_V3_5,
IPA_IDLE_INDICATION_CFG_ENTER_IDLE_DEBOUNCE_THRESH_BMSK_V3_5);
IPA_SETFIELD_IN_REG(*val,
idle_indication_cfg->const_non_idle_enable,
IPA_IDLE_INDICATION_CFG_CONST_NON_IDLE_ENABLE_SHFT_V3_5,
IPA_IDLE_INDICATION_CFG_CONST_NON_IDLE_ENABLE_BMSK_V3_5);
}
/*
* struct ipahal_reg_obj - Register H/W information for specific IPA version
* @construct - CB to construct register value from abstracted structure
* @parse - CB to parse register value to abstracted structure
* @offset - register offset relative to base address
* @n_ofst - N parameterized register sub-offset
*/
struct ipahal_reg_obj {
void (*construct)(enum ipahal_reg_name reg, const void *fields,
u32 *val);
void (*parse)(enum ipahal_reg_name reg, void *fields,
u32 val);
u32 offset;
u32 n_ofst;
};
/*
* This table contains the info regarding each register for IPAv3 and later.
* Information like: offset and construct/parse functions.
* All the information on the register on IPAv3 are statically defined below.
* If information is missing regarding some register on some IPA version,
* the init function will fill it with the information from the previous
* IPA version.
* Information is considered missing if all of the fields are 0.
* If offset is -1, this means that the register is removed on the
* specific version.
*/
static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = {
/* IPAv3 */
[IPA_HW_v3_0][IPA_ROUTE] = {
ipareg_construct_route, ipareg_parse_dummy,
0x00000048, 0},
[IPA_HW_v3_0][IPA_IRQ_STTS_EE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00003008, 0x1000},
[IPA_HW_v3_0][IPA_IRQ_EN_EE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x0000300c, 0x1000},
[IPA_HW_v3_0][IPA_IRQ_CLR_EE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00003010, 0x1000},
[IPA_HW_v3_0][IPA_IRQ_SUSPEND_INFO_EE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00003098, 0x1000},
[IPA_HW_v3_0][IPA_BCR] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x000001D0, 0},
[IPA_HW_v3_0][IPA_ENABLED_PIPES] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00000038, 0},
[IPA_HW_v3_0][IPA_COMP_SW_RESET] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00000040, 0},
[IPA_HW_v3_0][IPA_VERSION] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00000034, 0},
[IPA_HW_v3_0][IPA_TAG_TIMER] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00000060, 0 },
[IPA_HW_v3_0][IPA_COMP_HW_VERSION] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00000030, 0},
[IPA_HW_v3_0][IPA_SPARE_REG_1] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00005090, 0},
[IPA_HW_v3_0][IPA_SPARE_REG_2] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00005094, 0},
[IPA_HW_v3_0][IPA_COMP_CFG] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x0000003C, 0},
[IPA_HW_v3_0][IPA_STATE_AGGR_ACTIVE] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x0000010C, 0},
[IPA_HW_v3_0][IPA_ENDP_INIT_HDR_n] = {
ipareg_construct_endp_init_hdr_n, ipareg_parse_dummy,
0x00000810, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_HDR_EXT_n] = {
ipareg_construct_endp_init_hdr_ext_n, ipareg_parse_dummy,
0x00000814, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_AGGR_n] = {
ipareg_construct_endp_init_aggr_n,
ipareg_parse_endp_init_aggr_n,
0x00000824, 0x70},
[IPA_HW_v3_0][IPA_AGGR_FORCE_CLOSE] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x000001EC, 0},
[IPA_HW_v3_0][IPA_ENDP_INIT_ROUTE_n] = {
ipareg_construct_endp_init_route_n, ipareg_parse_dummy,
0x00000828, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_MODE_n] = {
ipareg_construct_endp_init_mode_n, ipareg_parse_dummy,
0x00000820, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_NAT_n] = {
ipareg_construct_endp_init_nat_n, ipareg_parse_dummy,
0x0000080C, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_CTRL_n] = {
ipareg_construct_endp_init_ctrl_n, ipareg_parse_dummy,
0x00000800, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_CTRL_SCND_n] = {
ipareg_construct_endp_init_ctrl_scnd_n, ipareg_parse_dummy,
0x00000804, 0x70 },
[IPA_HW_v3_0][IPA_ENDP_INIT_HOL_BLOCK_EN_n] = {
ipareg_construct_endp_init_hol_block_en_n,
ipareg_parse_dummy,
0x0000082c, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_HOL_BLOCK_TIMER_n] = {
ipareg_construct_endp_init_hol_block_timer_n,
ipareg_parse_dummy,
0x00000830, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_DEAGGR_n] = {
ipareg_construct_endp_init_deaggr_n,
ipareg_parse_dummy,
0x00000834, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_SEQ_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x0000083C, 0x70},
[IPA_HW_v3_0][IPA_DEBUG_CNT_REG_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00000600, 0x4},
[IPA_HW_v3_0][IPA_ENDP_INIT_CFG_n] = {
ipareg_construct_endp_init_cfg_n, ipareg_parse_dummy,
0x00000808, 0x70},
[IPA_HW_v3_0][IPA_IRQ_EE_UC_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x0000301c, 0x1000},
[IPA_HW_v3_0][IPA_ENDP_INIT_HDR_METADATA_MASK_n] = {
ipareg_construct_endp_init_hdr_metadata_mask_n,
ipareg_parse_dummy,
0x00000818, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_HDR_METADATA_n] = {
ipareg_construct_endp_init_hdr_metadata_n,
ipareg_parse_dummy,
0x0000081c, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_RSRC_GRP_n] = {
ipareg_construct_endp_init_rsrc_grp_n,
ipareg_parse_dummy,
0x00000838, 0x70},
[IPA_HW_v3_0][IPA_SHARED_MEM_SIZE] = {
ipareg_construct_dummy, ipareg_parse_shared_mem_size,
0x00000054, 0},
[IPA_HW_v3_0][IPA_SRAM_DIRECT_ACCESS_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00007000, 0x4},
[IPA_HW_v3_0][IPA_DEBUG_CNT_CTRL_n] = {
ipareg_construct_debug_cnt_ctrl_n, ipareg_parse_dummy,
0x00000640, 0x4},
[IPA_HW_v3_0][IPA_UC_MAILBOX_m_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00032000, 0x4},
[IPA_HW_v3_0][IPA_FILT_ROUT_HASH_FLUSH] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00000090, 0},
[IPA_HW_v3_0][IPA_SINGLE_NDP_MODE] = {
ipareg_construct_single_ndp_mode, ipareg_parse_single_ndp_mode,
0x00000068, 0},
[IPA_HW_v3_0][IPA_QCNCM] = {
ipareg_construct_qcncm, ipareg_parse_qcncm,
0x00000064, 0},
[IPA_HW_v3_0][IPA_SYS_PKT_PROC_CNTXT_BASE] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x000001e0, 0},
[IPA_HW_v3_0][IPA_LOCAL_PKT_PROC_CNTXT_BASE] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x000001e8, 0},
[IPA_HW_v3_0][IPA_ENDP_STATUS_n] = {
ipareg_construct_endp_status_n, ipareg_parse_dummy,
0x00000840, 0x70},
[IPA_HW_v3_0][IPA_ENDP_FILTER_ROUTER_HSH_CFG_n] = {
ipareg_construct_hash_cfg_n, ipareg_parse_hash_cfg_n,
0x0000085C, 0x70},
[IPA_HW_v3_0][IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
0x00000400, 0x20},
[IPA_HW_v3_0][IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
0x00000404, 0x20},
[IPA_HW_v3_0][IPA_SRC_RSRC_GRP_45_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
0x00000408, 0x20},
[IPA_HW_v3_0][IPA_SRC_RSRC_GRP_67_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
0x0000040C, 0x20},
[IPA_HW_v3_0][IPA_DST_RSRC_GRP_01_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
0x00000500, 0x20},
[IPA_HW_v3_0][IPA_DST_RSRC_GRP_23_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
0x00000504, 0x20},
[IPA_HW_v3_0][IPA_DST_RSRC_GRP_45_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
0x00000508, 0x20},
[IPA_HW_v3_0][IPA_DST_RSRC_GRP_67_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
0x0000050c, 0x20},
[IPA_HW_v3_0][IPA_RX_HPS_CLIENTS_MIN_DEPTH_0] = {
ipareg_construct_rx_hps_clients_depth0, ipareg_parse_dummy,
0x000023C4, 0},
[IPA_HW_v3_0][IPA_RX_HPS_CLIENTS_MIN_DEPTH_1] = {
ipareg_construct_rx_hps_clients_depth1, ipareg_parse_dummy,
0x000023C8, 0},
[IPA_HW_v3_0][IPA_RX_HPS_CLIENTS_MAX_DEPTH_0] = {
ipareg_construct_rx_hps_clients_depth0, ipareg_parse_dummy,
0x000023CC, 0},
[IPA_HW_v3_0][IPA_RX_HPS_CLIENTS_MAX_DEPTH_1] = {
ipareg_construct_rx_hps_clients_depth1, ipareg_parse_dummy,
0x000023D0, 0},
[IPA_HW_v3_0][IPA_QSB_MAX_WRITES] = {
ipareg_construct_qsb_max_writes, ipareg_parse_dummy,
0x00000074, 0},
[IPA_HW_v3_0][IPA_QSB_MAX_READS] = {
ipareg_construct_qsb_max_reads, ipareg_parse_dummy,
0x00000078, 0},
[IPA_HW_v3_0][IPA_DPS_SEQUENCER_FIRST] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x0001e000, 0},
[IPA_HW_v3_0][IPA_HPS_SEQUENCER_FIRST] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x0001e080, 0},
/* IPAv3.1 */
[IPA_HW_v3_1][IPA_IRQ_SUSPEND_INFO_EE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00003030, 0x1000},
[IPA_HW_v3_1][IPA_SUSPEND_IRQ_EN_EE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00003034, 0x1000},
[IPA_HW_v3_1][IPA_SUSPEND_IRQ_CLR_EE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00003038, 0x1000},
/* IPAv3.5 */
[IPA_HW_v3_5][IPA_TX_CFG] = {
ipareg_construct_tx_cfg, ipareg_parse_dummy,
0x000001FC, 0},
[IPA_HW_v3_5][IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy_v3_5, ipareg_parse_dummy,
0x00000400, 0x20},
[IPA_HW_v3_5][IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy_v3_5, ipareg_parse_dummy,
0x00000404, 0x20},
[IPA_HW_v3_5][IPA_SRC_RSRC_GRP_45_RSRC_TYPE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
-1, 0},
[IPA_HW_v3_5][IPA_SRC_RSRC_GRP_67_RSRC_TYPE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
-1, 0},
[IPA_HW_v3_5][IPA_DST_RSRC_GRP_01_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy_v3_5, ipareg_parse_dummy,
0x00000500, 0x20},
[IPA_HW_v3_5][IPA_DST_RSRC_GRP_23_RSRC_TYPE_n] = {
ipareg_construct_rsrg_grp_xy_v3_5, ipareg_parse_dummy,
0x00000504, 0x20},
[IPA_HW_v3_5][IPA_DST_RSRC_GRP_45_RSRC_TYPE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
-1, 0},
[IPA_HW_v3_5][IPA_DST_RSRC_GRP_67_RSRC_TYPE_n] = {
ipareg_construct_dummy, ipareg_parse_dummy,
-1, 0},
[IPA_HW_v3_5][IPA_ENDP_INIT_RSRC_GRP_n] = {
ipareg_construct_endp_init_rsrc_grp_n_v3_5,
ipareg_parse_dummy,
0x00000838, 0x70},
[IPA_HW_v3_5][IPA_RX_HPS_CLIENTS_MIN_DEPTH_0] = {
ipareg_construct_rx_hps_clients_depth0_v3_5,
ipareg_parse_dummy,
0x000023C4, 0},
[IPA_HW_v3_5][IPA_RX_HPS_CLIENTS_MIN_DEPTH_1] = {
ipareg_construct_dummy, ipareg_parse_dummy,
-1, 0},
[IPA_HW_v3_5][IPA_RX_HPS_CLIENTS_MAX_DEPTH_0] = {
ipareg_construct_rx_hps_clients_depth0_v3_5,
ipareg_parse_dummy,
0x000023CC, 0},
[IPA_HW_v3_5][IPA_RX_HPS_CLIENTS_MAX_DEPTH_1] = {
ipareg_construct_dummy, ipareg_parse_dummy,
-1, 0},
[IPA_HW_v3_5][IPA_SPARE_REG_1] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00002780, 0},
[IPA_HW_v3_5][IPA_SPARE_REG_2] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00002784, 0},
[IPA_HW_v3_5][IPA_IDLE_INDICATION_CFG] = {
ipareg_construct_idle_indication_cfg, ipareg_parse_dummy,
0x00000220, 0},
};
/*
* ipahal_reg_init() - Build the registers information table
* See ipahal_reg_objs[][] comments
*
* Note: As global variables are initialized with zero, any un-overridden
* register entry will be zero. By this we recognize them.
*/
int ipahal_reg_init(enum ipa_hw_type ipa_hw_type)
{
int i;
int j;
struct ipahal_reg_obj zero_obj;
IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
return -EINVAL;
}
memset(&zero_obj, 0, sizeof(zero_obj));
for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
for (j = 0; j < IPA_REG_MAX ; j++) {
if (!memcmp(&ipahal_reg_objs[i+1][j], &zero_obj,
sizeof(struct ipahal_reg_obj))) {
memcpy(&ipahal_reg_objs[i+1][j],
&ipahal_reg_objs[i][j],
sizeof(struct ipahal_reg_obj));
} else {
/*
* explicitly overridden register.
* Check validity
*/
if (!ipahal_reg_objs[i+1][j].offset) {
IPAHAL_ERR(
"reg=%s with zero offset ipa_ver=%d\n",
ipahal_reg_name_str(j), i+1);
WARN_ON(1);
}
if (!ipahal_reg_objs[i+1][j].construct) {
IPAHAL_ERR(
"reg=%s with NULL construct func ipa_ver=%d\n",
ipahal_reg_name_str(j), i+1);
WARN_ON(1);
}
if (!ipahal_reg_objs[i+1][j].parse) {
IPAHAL_ERR(
"reg=%s with NULL parse func ipa_ver=%d\n",
ipahal_reg_name_str(j), i+1);
WARN_ON(1);
}
}
}
}
return 0;
}
/*
* ipahal_reg_name_str() - returns string that represent the register
* @reg_name: [in] register name
*/
const char *ipahal_reg_name_str(enum ipahal_reg_name reg_name)
{
if (reg_name < 0 || reg_name >= IPA_REG_MAX) {
IPAHAL_ERR("requested name of invalid reg=%d\n", reg_name);
return "Invalid Register";
}
return ipareg_name_to_str[reg_name];
}
/*
* ipahal_read_reg_n() - Get n parameterized reg value
*/
u32 ipahal_read_reg_n(enum ipahal_reg_name reg, u32 n)
{
u32 offset;
if (reg >= IPA_REG_MAX) {
IPAHAL_ERR("Invalid register reg=%u\n", reg);
WARN_ON(1);
return -EFAULT;
}
IPAHAL_DBG_LOW("read from %s n=%u\n",
ipahal_reg_name_str(reg), n);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
if (offset == -1) {
IPAHAL_ERR("Read access to obsolete reg=%s\n",
ipahal_reg_name_str(reg));
WARN_ON(1);
return -EFAULT;
}
offset += ipahal_reg_objs[ipahal_ctx->hw_type][reg].n_ofst * n;
return ioread32(ipahal_ctx->base + offset);
}
/*
* ipahal_read_reg_mn() - Get mn parameterized reg value
*/
u32 ipahal_read_reg_mn(enum ipahal_reg_name reg, u32 m, u32 n)
{
u32 offset;
if (reg >= IPA_REG_MAX) {
IPAHAL_ERR("Invalid register reg=%u\n", reg);
return -EFAULT;
}
IPAHAL_DBG_LOW("read %s m=%u n=%u\n",
ipahal_reg_name_str(reg), m, n);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
if (offset == -1) {
IPAHAL_ERR("Read access to obsolete reg=%s\n",
ipahal_reg_name_str(reg));
WARN_ON_ONCE(1);
return -EFAULT;
}
/*
* Currently there is one register with m and n parameters
* IPA_UC_MAILBOX_m_n. The m value of it is 0x80.
* If more such registers will be added in the future,
* we can move the m parameter to the table above.
*/
offset += 0x80 * m;
offset += ipahal_reg_objs[ipahal_ctx->hw_type][reg].n_ofst * n;
return ioread32(ipahal_ctx->base + offset);
}
/*
* ipahal_write_reg_mn() - Write to m/n parameterized reg a raw value
*/
void ipahal_write_reg_mn(enum ipahal_reg_name reg, u32 m, u32 n, u32 val)
{
u32 offset;
if (reg >= IPA_REG_MAX) {
IPAHAL_ERR("Invalid register reg=%u\n", reg);
return;
}
IPAHAL_DBG_LOW("write to %s m=%u n=%u val=%u\n",
ipahal_reg_name_str(reg), m, n, val);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
if (offset == -1) {
IPAHAL_ERR("Write access to obsolete reg=%s\n",
ipahal_reg_name_str(reg));
WARN_ON(1);
return;
}
/*
* Currently there is one register with m and n parameters
* IPA_UC_MAILBOX_m_n. The m value of it is 0x80.
* If more such registers will be added in the future,
* we can move the m parameter to the table above.
*/
offset += 0x80 * m;
offset += ipahal_reg_objs[ipahal_ctx->hw_type][reg].n_ofst * n;
iowrite32(val, ipahal_ctx->base + offset);
}
/*
* ipahal_read_reg_n_fields() - Get the parsed value of n parameterized reg
*/
u32 ipahal_read_reg_n_fields(enum ipahal_reg_name reg, u32 n, void *fields)
{
u32 val = 0;
u32 offset;
if (!fields) {
IPAHAL_ERR("Input error fields=%p\n", fields);
WARN_ON(1);
return -EFAULT;
}
if (reg >= IPA_REG_MAX) {
IPAHAL_ERR("Invalid register reg=%u\n", reg);
WARN_ON(1);
return -EFAULT;
}
IPAHAL_DBG_LOW("read from %s n=%u and parse it\n",
ipahal_reg_name_str(reg), n);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
if (offset == -1) {
IPAHAL_ERR("Read access to obsolete reg=%s\n",
ipahal_reg_name_str(reg));
WARN_ON(1);
return -EFAULT;
}
offset += ipahal_reg_objs[ipahal_ctx->hw_type][reg].n_ofst * n;
val = ioread32(ipahal_ctx->base + offset);
ipahal_reg_objs[ipahal_ctx->hw_type][reg].parse(reg, fields, val);
return val;
}
/*
* ipahal_write_reg_n_fields() - Write to n parameterized reg a prased value
*/
void ipahal_write_reg_n_fields(enum ipahal_reg_name reg, u32 n,
const void *fields)
{
u32 val = 0;
u32 offset;
if (!fields) {
IPAHAL_ERR("Input error fields=%p\n", fields);
return;
}
if (reg >= IPA_REG_MAX) {
IPAHAL_ERR("Invalid register reg=%u\n", reg);
return;
}
IPAHAL_DBG_LOW("write to %s n=%u after constructing it\n",
ipahal_reg_name_str(reg), n);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
if (offset == -1) {
IPAHAL_ERR("Write access to obsolete reg=%s\n",
ipahal_reg_name_str(reg));
WARN_ON(1);
return;
}
offset += ipahal_reg_objs[ipahal_ctx->hw_type][reg].n_ofst * n;
ipahal_reg_objs[ipahal_ctx->hw_type][reg].construct(reg, fields, &val);
iowrite32(val, ipahal_ctx->base + offset);
}
/*
* Get the offset of a m/n parameterized register
*/
u32 ipahal_get_reg_mn_ofst(enum ipahal_reg_name reg, u32 m, u32 n)
{
u32 offset;
if (reg >= IPA_REG_MAX) {
IPAHAL_ERR("Invalid register reg=%u\n", reg);
WARN_ON(1);
return -EFAULT;
}
IPAHAL_DBG_LOW("get offset of %s m=%u n=%u\n",
ipahal_reg_name_str(reg), m, n);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
if (offset == -1) {
IPAHAL_ERR("Access to obsolete reg=%s\n",
ipahal_reg_name_str(reg));
WARN_ON(1);
return -EFAULT;
}
/*
* Currently there is one register with m and n parameters
* IPA_UC_MAILBOX_m_n. The m value of it is 0x80.
* If more such registers will be added in the future,
* we can move the m parameter to the table above.
*/
offset += 0x80 * m;
offset += ipahal_reg_objs[ipahal_ctx->hw_type][reg].n_ofst * n;
return offset;
}
u32 ipahal_get_reg_base(void)
{
return 0x00040000;
}
/*
* Specific functions
* These functions supply specific register values for specific operations
* that cannot be reached by generic functions.
* E.g. To disable aggregation, need to write to specific bits of the AGGR
* register. The other bits should be untouched. This oeprate is very specific
* and cannot be generically defined. For such operations we define these
* specific functions.
*/
void ipahal_get_disable_aggr_valmask(struct ipahal_reg_valmask *valmask)
{
if (!valmask) {
IPAHAL_ERR("Input error\n");
return;
}
valmask->val = (1 & IPA_ENDP_INIT_AGGR_n_AGGR_FORCE_CLOSE_BMSK) <<
IPA_ENDP_INIT_AGGR_n_AGGR_FORCE_CLOSE_SHFT;
valmask->mask = IPA_ENDP_INIT_AGGR_n_AGGR_FORCE_CLOSE_BMSK <<
IPA_ENDP_INIT_AGGR_n_AGGR_FORCE_CLOSE_SHFT;
valmask->val |= ((0 & IPA_ENDP_INIT_AGGR_n_AGGR_EN_BMSK) <<
IPA_ENDP_INIT_AGGR_n_AGGR_EN_SHFT);
valmask->mask |= ((IPA_ENDP_INIT_AGGR_n_AGGR_EN_BMSK <<
IPA_ENDP_INIT_AGGR_n_AGGR_EN_SHFT));
}
u32 ipahal_aggr_get_max_byte_limit(void)
{
return
IPA_ENDP_INIT_AGGR_n_AGGR_BYTE_LIMIT_BMSK >>
IPA_ENDP_INIT_AGGR_n_AGGR_BYTE_LIMIT_SHFT;
}
u32 ipahal_aggr_get_max_pkt_limit(void)
{
return
IPA_ENDP_INIT_AGGR_n_AGGR_PKT_LIMIT_BMSK >>
IPA_ENDP_INIT_AGGR_n_AGGR_PKT_LIMIT_SHFT;
}
void ipahal_get_aggr_force_close_valmask(int ep_idx,
struct ipahal_reg_valmask *valmask)
{
u32 shft;
u32 bmsk;
if (!valmask) {
IPAHAL_ERR("Input error\n");
return;
}
if (ipahal_ctx->hw_type <= IPA_HW_v3_1) {
shft = IPA_AGGR_FORCE_CLOSE_AGGR_FORCE_CLOSE_PIPE_BITMAP_SHFT;
bmsk = IPA_AGGR_FORCE_CLOSE_AGGR_FORCE_CLOSE_PIPE_BITMAP_BMSK;
} else {
shft =
IPA_AGGR_FORCE_CLOSE_AGGR_FORCE_CLOSE_PIPE_BITMAP_SHFT_V3_5;
bmsk =
IPA_AGGR_FORCE_CLOSE_AGGR_FORCE_CLOSE_PIPE_BITMAP_BMSK_V3_5;
}
IPA_SETFIELD_IN_REG(valmask->val, 1 << ep_idx, shft, bmsk);
valmask->mask = bmsk << shft;
}
void ipahal_get_fltrt_hash_flush_valmask(
struct ipahal_reg_fltrt_hash_flush *flush,
struct ipahal_reg_valmask *valmask)
{
if (!flush || !valmask) {
IPAHAL_ERR("Input error: flush=%p ; valmask=%p\n",
flush, valmask);
return;
}
memset(valmask, 0, sizeof(struct ipahal_reg_valmask));
if (flush->v6_rt)
valmask->val |=
(1<<IPA_FILT_ROUT_HASH_FLUSH_IPv6_ROUT_SHFT);
if (flush->v6_flt)
valmask->val |=
(1<<IPA_FILT_ROUT_HASH_FLUSH_IPv6_FILT_SHFT);
if (flush->v4_rt)
valmask->val |=
(1<<IPA_FILT_ROUT_HASH_FLUSH_IPv4_ROUT_SHFT);
if (flush->v4_flt)
valmask->val |=
(1<<IPA_FILT_ROUT_HASH_FLUSH_IPv4_FILT_SHFT);
valmask->mask = valmask->val;
}
void ipahal_get_status_ep_valmask(int pipe_num,
struct ipahal_reg_valmask *valmask)
{
if (!valmask) {
IPAHAL_ERR("Input error\n");
return;
}
valmask->val =
(pipe_num & IPA_ENDP_STATUS_n_STATUS_ENDP_BMSK) <<
IPA_ENDP_STATUS_n_STATUS_ENDP_SHFT;
valmask->mask =
IPA_ENDP_STATUS_n_STATUS_ENDP_BMSK <<
IPA_ENDP_STATUS_n_STATUS_ENDP_SHFT;
}