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

Commit c9939cf8 authored by Skylar Chang's avatar Skylar Chang
Browse files

msm: gsi: add support for generic commands



Expose a new API from GSI driver to allow client driver to
disable channel for other Execution Environment.
This API will be used as part of SSR cleanup.

Change-Id: I3b9400643aff76ca2195a597aba9ea18aab3085e
CRs-Fixed: 2008582
Acked-by: default avatarAdy Abrahan <adya@qti.qualcomm.com>
Signed-off-by: default avatarSkylar Chang <chiaweic@codeaurora.org>
parent 7cb7aff9
Loading
Loading
Loading
Loading
+68 −2
Original line number Diff line number Diff line
@@ -264,6 +264,11 @@ static void gsi_handle_glob_err(uint32_t err)
	}
}

static void gsi_handle_gp_int1(void)
{
	complete(&gsi_ctx->gen_ee_cmd_compl);
}

static void gsi_handle_glob_ee(int ee)
{
	uint32_t val;
@@ -288,8 +293,7 @@ static void gsi_handle_glob_ee(int ee)
	}

	if (val & GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT1_BMSK) {
		notify.evt_id = GSI_PER_EVT_GLOB_GP1;
		gsi_ctx->per.notify_cb(&notify);
		gsi_handle_gp_int1();
	}

	if (val & GSI_EE_n_CNTXT_GLOB_IRQ_EN_GP_INT2_BMSK) {
@@ -2745,6 +2749,67 @@ void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset,
}
EXPORT_SYMBOL(gsi_get_inst_ram_offset_and_size);

int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code)
{
	enum gsi_generic_ee_cmd_opcode op = GSI_GEN_EE_CMD_HALT_CHANNEL;
	uint32_t val;
	int res;

	if (!gsi_ctx) {
		pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__);
		return -GSI_STATUS_NODEV;
	}

	if (chan_idx >= gsi_ctx->max_ch || !code) {
		GSIERR("bad params chan_idx=%d\n", chan_idx);
		return -GSI_STATUS_INVALID_PARAMS;
	}

	mutex_lock(&gsi_ctx->mlock);
	reinit_completion(&gsi_ctx->gen_ee_cmd_compl);

	/* invalidate the response */
	gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base +
			GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
	gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code = 0;
	gsi_writel(gsi_ctx->scratch.word0.val, gsi_ctx->base +
			GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));

	gsi_ctx->gen_ee_cmd_dbg.halt_channel++;
	val = (((op << GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT) &
		GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK) |
		((chan_idx << GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT) &
			GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK) |
		((ee << GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT) &
			GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK));
	gsi_writel(val, gsi_ctx->base +
		GSI_EE_n_GSI_EE_GENERIC_CMD_OFFS(gsi_ctx->per.ee));

	res = wait_for_completion_timeout(&gsi_ctx->gen_ee_cmd_compl,
		msecs_to_jiffies(GSI_CMD_TIMEOUT));
	if (res == 0) {
		GSIERR("chan_idx=%u ee=%u timed out\n", chan_idx, ee);
		res = -GSI_STATUS_TIMED_OUT;
		goto free_lock;
	}

	gsi_ctx->scratch.word0.val = gsi_readl(gsi_ctx->base +
		GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
	if (gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code == 0) {
		GSIERR("No response received\n");
		res = -GSI_STATUS_ERROR;
		goto free_lock;
	}

	res = GSI_STATUS_SUCCESS;
	*code = gsi_ctx->scratch.word0.s.generic_ee_cmd_return_code;
free_lock:
	mutex_unlock(&gsi_ctx->mlock);

	return res;
}
EXPORT_SYMBOL(gsi_halt_channel_ee);

static int msm_gsi_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
@@ -2757,6 +2822,7 @@ static int msm_gsi_probe(struct platform_device *pdev)
	}

	gsi_ctx->dev = dev;
	init_completion(&gsi_ctx->gen_ee_cmd_compl);
	gsi_debugfs_init();

	return 0;
+24 −3
Original line number Diff line number Diff line
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-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
@@ -115,9 +115,12 @@ struct gsi_evt_ctx {
struct gsi_ee_scratch {
	union __packed {
		struct {
			uint32_t resvd1:15;
			uint32_t inter_ee_cmd_return_code:3;
			uint32_t resvd1:2;
			uint32_t generic_ee_cmd_return_code:3;
			uint32_t resvd2:7;
			uint32_t max_usb_pkt_size:1;
			uint32_t resvd2:8;
			uint32_t resvd3:8;
			uint32_t mhi_base_chan_idx:8;
		} s;
		uint32_t val;
@@ -135,6 +138,10 @@ struct ch_debug_stats {
	unsigned long cmd_completed;
};

struct gsi_generic_ee_cmd_debug_stats {
	unsigned long halt_channel;
};

struct gsi_ctx {
	void __iomem *base;
	struct device *dev;
@@ -143,6 +150,7 @@ struct gsi_ctx {
	struct gsi_chan_ctx chan[GSI_CHAN_MAX];
	struct ch_debug_stats ch_dbg[GSI_CHAN_MAX];
	struct gsi_evt_ctx evtr[GSI_EVT_RING_MAX];
	struct gsi_generic_ee_cmd_debug_stats gen_ee_cmd_dbg;
	struct mutex mlock;
	spinlock_t slock;
	unsigned long evt_bmap;
@@ -154,6 +162,7 @@ struct gsi_ctx {
	struct workqueue_struct *dp_stat_wq;
	u32 max_ch;
	u32 max_ev;
	struct completion gen_ee_cmd_compl;
};

enum gsi_re_type {
@@ -227,6 +236,18 @@ enum gsi_evt_ch_cmd_opcode {
	GSI_EVT_DE_ALLOC = 0xa,
};

enum gsi_generic_ee_cmd_opcode {
	GSI_GEN_EE_CMD_HALT_CHANNEL = 0x1,
};

enum gsi_generic_ee_cmd_return_code {
	GSI_GEN_EE_CMD_RETURN_CODE_SUCCESS = 0x1,
	GSI_GEN_EE_CMD_RETURN_CODE_CHANNEL_NOT_RUNNING = 0x2,
	GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_DIRECTION = 0x3,
	GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_TYPE = 0x4,
	GSI_GEN_EE_CMD_RETURN_CODE_INCORRECT_CHANNEL_INDEX = 0x5,
};

extern struct gsi_ctx *gsi_ctx;
void gsi_debugfs_init(void);
uint16_t gsi_find_idx_from_addr(struct gsi_ring_ctx *ctx, uint64_t addr);
+5 −1
Original line number Diff line number Diff line
@@ -1365,8 +1365,12 @@
	(GSI_GSI_REG_BASE_OFFS + 0x0001f018 + 0x4000 * (n))
#define GSI_EE_n_GSI_EE_GENERIC_CMD_RMSK 0xffffffff
#define GSI_EE_n_GSI_EE_GENERIC_CMD_MAXn 3
#define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK 0xffffffff
#define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_BMSK 0x1f
#define GSI_EE_n_GSI_EE_GENERIC_CMD_OPCODE_SHFT 0x0
#define GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_BMSK 0x3e0
#define GSI_EE_n_GSI_EE_GENERIC_CMD_VIRT_CHAN_IDX_SHFT 0x5
#define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_BMSK 0x3c00
#define GSI_EE_n_GSI_EE_GENERIC_CMD_EE_SHFT 0xa

/* v1.0 */
#define GSI_V1_0_EE_n_GSI_HW_PARAM_OFFS(n) \
+18 −0
Original line number Diff line number Diff line
@@ -1053,6 +1053,18 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size);
void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset,
		unsigned long *size);

/**
 * gsi_halt_channel_ee - Peripheral should call this function
 * to stop other EE's channel. This is usually used in SSR clean
 *
 * @chan_idx: Virtual channel index
 * @ee: EE
 * @code: [out] response code for operation

 * @Return gsi_status
 */
int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee, int *code);

/*
 * Here is a typical sequence of calls
 *
@@ -1250,5 +1262,11 @@ static inline void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset,
		unsigned long *size)
{
}

static inline int gsi_halt_channel_ee(unsigned int chan_idx, unsigned int ee,
	 int *code)
{
	return -GSI_STATUS_UNSUPPORTED_OP;
}
#endif
#endif