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

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

Merge "ARM: dts: msm: add ipa node for sm8150_sdxprairie target"

parents 53b470fc 910d876c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -108,6 +108,10 @@ memory allocation over a PCIe bridge
				registers, collected upon crash, reside.
- qcom,ipa-endp-delay-wa: Boolean context flag to indicate end point delay work around
				supported or not.
- qcom,secure-debug-check-action: Drives secure memory debug check. Three values allowed:
				0 (use scm call),
				1 (override scm call as though it returned true), and
				2 (override scm call as though it returned false)

IPA pipe sub nodes (A2 static pipes configurations):

+1 −0
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@
		qcom,register-collection-on-crash;
		qcom,testbus-collection-on-crash;
		qcom,non-tn-collection-on-crash;
		qcom,secure-debug-check-action = <0>;
	};

	qcom,ipa_fws {
+2 −0
Original line number Diff line number Diff line
@@ -16,4 +16,6 @@ obj-$(CONFIG_IPA_ETH) += ethernet/

ipat-$(CONFIG_IPA3_REGDUMP) += dump/ipa_reg_dump.o

ccflags-$(CONFIG_IPA3_REGDUMP) += -Idrivers/platform/msm/ipa/ipa_v3/dump

ccflags-$(CONFIG_IPA3_REGDUMP_SM8150) += -Idrivers/platform/msm/ipa/ipa_v3/dump/sm8150
+119 −35
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
 * GNU General Public License for more details.
 */
#include "ipa_reg_dump.h"
#include "ipa_access_control.h"

/* Total size required for test bus */
#define IPA_MEM_OVERLAY_SIZE     0x66000
@@ -338,13 +339,13 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = {
					    ipa_dst_rsrc_grp_23_rsrc_type_n),

	/* Source Resource Group Count Registers */
	IPA_REG_SAVE_CFG_ENTRY_SRC_RSRC_CNT_GRP
		(IPA_SRC_RSRC_GRP_0123_RSRC_TYPE_CNT_n,
	IPA_REG_SAVE_CFG_ENTRY_SRC_RSRC_CNT_GRP(
		IPA_SRC_RSRC_GRP_0123_RSRC_TYPE_CNT_n,
		ipa_src_rsrc_grp_0123_rsrc_type_cnt_n),

	/* Destination Resource Group Count Registers */
	IPA_REG_SAVE_CFG_ENTRY_DST_RSRC_CNT_GRP
		(IPA_DST_RSRC_GRP_0123_RSRC_TYPE_CNT_n,
	IPA_REG_SAVE_CFG_ENTRY_DST_RSRC_CNT_GRP(
		IPA_DST_RSRC_GRP_0123_RSRC_TYPE_CNT_n,
		ipa_dst_rsrc_grp_0123_rsrc_type_cnt_n),

	/*
@@ -360,6 +361,9 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = {
	GEN_SRC_DST_ADDR_MAP(GSI_REE_CFG,
			     gsi.gen,
			     gsi_ree_cfg),
	IPA_REG_SAVE_GSI_VER(
			     IPA_GSI_TOP_GSI_INST_RAM_n,
			     ipa_gsi_top_gsi_inst_ram_n),

	/* GSI Debug Registers */
	GEN_SRC_DST_ADDR_MAP(IPA_GSI_TOP_GSI_DEBUG_BUSY_REG,
@@ -651,6 +655,73 @@ static void ipa_hal_save_regs_ipa_cmdq(void);
static void ipa_hal_save_regs_rsrc_db(void);
static void ipa_reg_save_anomaly_check(void);

static struct reg_access_funcs_s *get_access_funcs(u32 addr)
{
	u32 i, asub = ipa3_ctx->sd_state;

	for (i = 0; i < ARRAY_SIZE(mem_access_map); i++) {
		if (addr >= mem_access_map[i].addr_range_begin &&
		    addr <= mem_access_map[i].addr_range_end) {
			return mem_access_map[i].access[asub];
		}
	}

	IPAERR("Unknown register offset(0x%08X). Using dflt access methods\n",
		   addr);

	return &io_matrix[AA_COMBO];
}

static u32 in_dword(
	u32 addr)
{
	struct reg_access_funcs_s *io = get_access_funcs(addr);

	return io->read(ipa3_ctx->reg_collection_base + addr);
}

static u32 in_dword_masked(
	u32 addr,
	u32 mask)
{
	struct reg_access_funcs_s *io = get_access_funcs(addr);
	u32 val;

	val = io->read(ipa3_ctx->reg_collection_base + addr);

	if (io->read == act_read)
		return val & mask;

	return val;
}

static void out_dword(
	u32 addr,
	u32 val)
{
	struct reg_access_funcs_s *io = get_access_funcs(addr);

	io->write(ipa3_ctx->reg_collection_base + addr, val);
}

/*
 * FUNCTION:  ipa_save_gsi_ver
 *
 * Saves the gsi version
 *
 * @return
 * None
 */
void ipa_save_gsi_ver(void)
{
	if (!ipa3_ctx->do_register_collection_on_crash)
		return;

	ipa_reg_save.gsi.fw_ver =
		IPA_READ_1xVECTOR_REG(IPA_GSI_TOP_GSI_INST_RAM_n, 0) &
		0x0000FFFF;
}

/*
 * FUNCTION:  ipa_save_registers
 *
@@ -669,7 +740,7 @@ void ipa_save_registers(void)
	union ipa_hwio_def_ipa_rsrc_mngr_db_rsrc_read_u
	    ipa_rsrc_mngr_db_rsrc_read;

	if (ipa3_ctx->do_register_collection_on_crash == false)
	if (!ipa3_ctx->do_register_collection_on_crash)
		return;

	IPAERR("Commencing\n");
@@ -831,36 +902,49 @@ void ipa_save_registers(void)
	 * true, via dtsi, and the collection will be done.
	 */
	if (ipa3_ctx->do_non_tn_collection_on_crash == true) {
		/* Copy Pkt context directly from IPA_CTX_ID register space */
		u32 ofst = GEN_2xVECTOR_REG_OFST(IPA_CTX_ID_m_CTX_NUM_n, 0, 0);
		struct reg_access_funcs_s *io = get_access_funcs(ofst);
		/*
		 * If the memory is accessible, copy pkt context directly from
		 * IPA_CTX_ID register space
		 */
		if (io->read == act_read) {
			memcpy((void *)ipa_reg_save.pkt_ctntx,
		       (void *)((u8 *) ipa3_ctx->reg_collection_base +
				GEN_2xVECTOR_REG_OFST(
				    IPA_CTX_ID_m_CTX_NUM_n, 0, 0)),
				   (const void *)
				   (ipa3_ctx->reg_collection_base + ofst),
				   sizeof(ipa_reg_save.pkt_ctntx));

			ipa_rsrc_mngr_db_cfg.value =
				IPA_READ_SCALER_REG(IPA_RSRC_MNGR_DB_CFG);

			ipa_rsrc_mngr_db_cfg.def.rsrc_type_sel = 0;
		IPA_WRITE_SCALER_REG(IPA_RSRC_MNGR_DB_CFG,

			IPA_WRITE_SCALER_REG(
				IPA_RSRC_MNGR_DB_CFG,
				ipa_rsrc_mngr_db_cfg.value);

			for (i = 0; i < IPA_HW_PKT_CTNTX_MAX; i++) {
				ipa_rsrc_mngr_db_cfg.def.rsrc_id_sel = i;
			IPA_WRITE_SCALER_REG(IPA_RSRC_MNGR_DB_CFG,

				IPA_WRITE_SCALER_REG(
					IPA_RSRC_MNGR_DB_CFG,
					ipa_rsrc_mngr_db_cfg.value);

				ipa_rsrc_mngr_db_rsrc_read.value =
				IPA_READ_SCALER_REG(IPA_RSRC_MNGR_DB_RSRC_READ);
					IPA_READ_SCALER_REG(
						IPA_RSRC_MNGR_DB_RSRC_READ);

			if (ipa_rsrc_mngr_db_rsrc_read.def.rsrc_occupied ==
			    true) {
				if (ipa_rsrc_mngr_db_rsrc_read.def.rsrc_occupied
					== true) {
					ipa_reg_save.pkt_ctntx_active[i] = true;
					ipa_reg_save.pkt_cntxt_state[i] =
						(enum ipa_hw_pkt_cntxt_state_e)
						ipa_reg_save.pkt_ctntx[i].state;
				}
			}
		} else {
			IPAERR("IPA_CTX_ID is not currently accessible\n");
		}
	}

	ipa_reg_save_anomaly_check();
@@ -1316,11 +1400,11 @@ static void ipa_hal_save_regs_save_ipa_testbus(void)
 *
 * @return
 */
int ipa_reg_save_init(u8 value)
int ipa_reg_save_init(u32 value)
{
	u32 i, num_regs = ARRAY_SIZE(ipa_regs_to_save_array);

	if (ipa3_ctx->do_register_collection_on_crash == false)
	if (!ipa3_ctx->do_register_collection_on_crash)
		return 0;

	memset(&ipa_reg_save, value, sizeof(ipa_reg_save));
+121 −20
Original line number Diff line number Diff line
@@ -26,21 +26,9 @@
 */
#define my_in_dword(addr) \
	(readl(addr))
#define in_dword(addr) \
	my_in_dword((u8 *) ipa3_ctx->reg_collection_base + \
		    (u32)(addr))

#define my_in_dword_masked(addr, mask) \
	(my_in_dword(addr) & (mask))
#define in_dword_masked(addr, mask) \
	my_in_dword_masked((u8 *) ipa3_ctx->reg_collection_base + \
			   (u32)(addr), (mask))

#define my_out_dword(addr, val) \
	({ __iowmb(); writel_relaxed((val), (addr)); })
#define out_dword(addr, val) \
	my_out_dword((u8 *) ipa3_ctx->reg_collection_base + \
		     (u32)(addr), (val))

#define IPA_0_IPA_WRAPPER_BASE 0 /* required by following includes */

@@ -238,6 +226,12 @@ struct map_src_dst_addr_s {
		ipa_reg_save.ipa.testbus->ep_rsrc[rsrc_type].entry_ep \
		[rsrc_grp].testbus_data.value)

/*
 * Macro to pluck the gsi version from ram.
 */
#define IPA_REG_SAVE_GSI_VER(reg_name, var_name)	\
	{ GEN_1xVECTOR_REG_OFST(reg_name, 0), \
		(u32 *)&ipa_reg_save.gsi.gen.var_name }
/*
 * Macro to define a particular register cfg entry for all 3 EE
 * indexed register
@@ -916,6 +910,8 @@ struct ipa_reg_save_gsi_gen_s {
	  gsi_cfg;
	struct gsi_hwio_def_gsi_ree_cfg_s
	  gsi_ree_cfg;
	struct ipa_hwio_def_ipa_gsi_top_gsi_inst_ram_n_s
	  ipa_gsi_top_gsi_inst_ram_n;
};

/* GSI General EE register save data struct */
@@ -1226,6 +1222,7 @@ struct ipa_regs_save_hierarchy_s {

/* Top level GSI register save data struct */
struct gsi_regs_save_hierarchy_s {
	u32 fw_ver;
	struct ipa_reg_save_gsi_gen_s		gen;
	struct ipa_reg_save_gsi_gen_ee_s	gen_ee[IPA_REG_SAVE_GSI_NUM_EE];
	struct ipa_reg_save_gsi_ch_cntxt_s	ch_cntxt;
@@ -1268,17 +1265,121 @@ struct ipa_reg_save_rsrc_cnts_s {

/* Top level IPA and GSI registers save data struct */
struct regs_save_hierarchy_s {
	struct ipa_regs_save_hierarchy_s	ipa;
	struct gsi_regs_save_hierarchy_s	gsi;
	bool pkt_ctntx_active[IPA_HW_PKT_CTNTX_MAX];
	union ipa_hwio_def_ipa_ctxh_ctrl_u	pkt_ctntxt_lock;
	struct ipa_regs_save_hierarchy_s
		ipa;
	struct gsi_regs_save_hierarchy_s
		gsi;
	bool
		pkt_ctntx_active[IPA_HW_PKT_CTNTX_MAX];
	union ipa_hwio_def_ipa_ctxh_ctrl_u
		pkt_ctntxt_lock;
	enum ipa_hw_pkt_cntxt_state_e
		pkt_cntxt_state[IPA_HW_PKT_CTNTX_MAX];
	struct ipa_pkt_ctntx_s
		pkt_ctntx[IPA_HW_PKT_CTNTX_MAX];
	struct ipa_reg_save_rsrc_cnts_s		rsrc_cnts;
	struct ipa_reg_save_rsrc_cnts_s
		rsrc_cnts;
	struct ipa_reg_save_gsi_fifo_status_s
		gsi_fifo_status[IPA_HW_PIPE_ID_MAX];
};

/*
 * The following section deals with handling IPA registers' memory
 * access relative to pre-defined memory protection schemes
 * (ie. "access control").
 *
 * In a nut shell, the intent of the data stuctures below is to allow
 * higher level register accessors to be unaware of what really is
 * going on at the lowest level (ie. real vs non-real access).  This
 * methodology is also designed to allow for platform specific "access
 * maps."
 */

/*
 * Function for doing an actual read
 */
static inline u32
act_read(void __iomem *addr)
{
	u32 val = my_in_dword(addr);

	return val;
}

/*
 * Function for doing an actual write
 */
static inline void
act_write(void __iomem *addr, u32 val)
{
	my_out_dword(addr, val);
}

/*
 * Function that pretends to do a read
 */
static inline u32
nop_read(void __iomem *addr)
{
	return IPA_MEM_INIT_VAL;
}

/*
 * Function that pretends to do a write
 */
static inline void
nop_write(void __iomem *addr, u32 val)
{
}

/*
 * The following are used to define struct reg_access_funcs_s below...
 */
typedef u32 (*reg_read_func_t)(
	void __iomem *addr);
typedef void (*reg_write_func_t)(
	void __iomem *addr,
	u32 val);

/*
 * The following in used to define io_matrix[] below...
 */
struct reg_access_funcs_s {
	reg_read_func_t  read;
	reg_write_func_t write;
};

/*
 * The following will be used to appropriately index into the
 * read/write combos defined in io_matrix[] below...
 */
#define AA_COMBO 0 /* actual read, actual write */
#define AN_COMBO 1 /* actual read, no-op write  */
#define NA_COMBO 2 /* no-op read,  actual write */
#define NN_COMBO 3 /* no-op read,  no-op write  */

/*
 * The following will be used to dictate registers' access methods
 * relative to the state of secure debug...whether it's enabled or
 * disabled.
 *
 * NOTE: The table below defines all access combinations.
 */
static struct reg_access_funcs_s io_matrix[] = {
	{ act_read, act_write }, /* the AA_COMBO */
	{ act_read, nop_write }, /* the AN_COMBO */
	{ nop_read, act_write }, /* the NA_COMBO */
	{ nop_read, nop_write }, /* the NN_COMBO */
};

/*
 * The following will be used to define and drive IPA's register
 * access rules.
 */
struct reg_mem_access_map_t {
	u32 addr_range_begin;
	u32 addr_range_end;
	struct reg_access_funcs_s *access[2];
};

#endif /* #if !defined(_IPA_REG_DUMP_H_) */
Loading