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

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

Merge "dma: gpi: Add support to assign static GPII for I2C Touch on Lahaina"

parents aea646dc d2378797
Loading
Loading
Loading
Loading
+124 −45
Original line number Diff line number Diff line
@@ -134,6 +134,11 @@ enum EV_PRIORITY {
#define STATE_IGNORE (U32_MAX)
#define REQ_OF_DMA_ARGS (5) /* # of arguments required from client */

#define NOOP_TRE_MASK(link_rx, bei, ieot, ieob, ch) \
	((0x0 << 20) | (0x0 << 16) | (link_rx << 11) | (bei << 10) | \
	(ieot << 9) | (ieob << 8) | ch)
#define NOOP_TRE (0x0 << 20 | 0x1 << 16)

struct __packed gpi_error_log_entry {
	u32 routine : 4;
	u32 type : 4;
@@ -436,6 +441,7 @@ struct gpi_dev {
	void *ee_base; /*ee register base address*/
	u32 max_gpii; /* maximum # of gpii instances available per gpi block */
	u32 gpii_mask; /* gpii instances available for apps */
	u32 static_gpii_mask; /* gpii instances assigned statically */
	u32 ev_factor; /* ev ring length factor */
	u32 smmu_cfg;
	dma_addr_t iova_base;
@@ -445,6 +451,7 @@ struct gpi_dev {
	u32 ipc_log_lvl;
	u32 klog_lvl;
	struct dentry *dentry;
	bool is_le_vm;
};

static struct gpi_dev *gpi_dev_dbg[5];
@@ -544,6 +551,8 @@ struct gpii_chan {
	u32 dir;
	struct gpi_ring ch_ring;
	struct gpi_client_info client_info;
	u32 lock_tre_set;
	u32 num_tre;
};

struct gpii {
@@ -1663,6 +1672,7 @@ static void gpi_process_xfer_compl_event(struct gpii_chan *gpii_chan,
			return;
		}
	} else if (compl_event->code == MSM_GPI_TCE_EOB) {
		if (!(gpii_chan->num_tre == 1 && gpii_chan->lock_tre_set))
			goto gpi_free_desc;
	}

@@ -2199,6 +2209,7 @@ int gpi_terminate_all(struct dma_chan *chan)
{
	struct gpii_chan *gpii_chan = to_gpii_chan(chan);
	struct gpii *gpii = gpii_chan->gpii;
	struct gpi_dev *gpi_dev = gpii->gpi_dev;
	int schid, echid, i;
	int ret = 0;

@@ -2213,6 +2224,7 @@ int gpi_terminate_all(struct dma_chan *chan)
	echid = (gpii->protocol == SE_PROTOCOL_UART) ? schid + 1 :
		MAX_CHANNELS_PER_GPII;

	if (!gpi_dev->is_le_vm) {
		/* stop the channel */
		for (i = schid; i < echid; i++) {
			gpii_chan = &gpii->gpii_chan[i];
@@ -2226,8 +2238,8 @@ int gpi_terminate_all(struct dma_chan *chan)
			ret = gpi_send_cmd(gpii, gpii_chan, GPI_CH_CMD_STOP);
			if (ret)
				GPII_ERR(gpii, gpii_chan->chid,
				 "Error Stopping Channel:%d resetting anyway\n",
				 ret);
				"Error Stopping Chan:%d resetting\n", ret);
		}
	}

	/* reset the channels (clears any pending tre) */
@@ -2267,6 +2279,44 @@ int gpi_terminate_all(struct dma_chan *chan)
	return ret;
}

static void gpi_noop_tre(struct gpii_chan *gpii_chan)
{
	struct gpii *gpii = gpii_chan->gpii;
	struct gpi_ring *ch_ring = &gpii_chan->ch_ring;
	phys_addr_t local_rp, local_wp;
	void *cntxt_rp;
	u32 noop_mask, noop_tre;
	struct msm_gpi_tre *tre;

	GPII_INFO(gpii, gpii_chan->chid, "Enter\n");

	local_rp = to_physical(ch_ring, ch_ring->rp);
	local_wp = to_physical(ch_ring, ch_ring->wp);
	cntxt_rp = ch_ring->rp;

	GPII_INFO(gpii, gpii_chan->chid,
		"local_rp:0x%0llx local_wp:0x%0llx\n", local_rp, local_wp);

	noop_mask = NOOP_TRE_MASK(1, 0, 0, 0, 1);
	noop_tre = NOOP_TRE;

	while (local_rp != local_wp) {
		tre = (struct msm_gpi_tre *)cntxt_rp;
		tre->dword[3] &= noop_mask;
		tre->dword[3] |= noop_tre;
		local_rp += ch_ring->el_size;
		cntxt_rp += ch_ring->el_size;
		if (cntxt_rp >= (ch_ring->base + ch_ring->len)) {
			cntxt_rp = ch_ring->base;
			local_rp = to_physical(ch_ring, ch_ring->base);
		}
		GPII_INFO(gpii, gpii_chan->chid,
			"local_rp:0x%0llx\n", local_rp);
	}

	GPII_INFO(gpii, gpii_chan->chid, "exit\n");
}

/* pause dma transfer for all channels */
static int gpi_pause(struct dma_chan *chan)
{
@@ -2277,38 +2327,41 @@ static int gpi_pause(struct dma_chan *chan)
	GPII_INFO(gpii, gpii_chan->chid, "Enter\n");
	mutex_lock(&gpii->ctrl_lock);

	/*
	 * pause/resume are per gpii not per channel, so
	 * client needs to call pause only once
	 */
	if (gpii->pm_state == PAUSE_STATE) {
		GPII_INFO(gpii, gpii_chan->chid,
			  "channel is already paused\n");
		mutex_unlock(&gpii->ctrl_lock);
		return 0;
	}

	/* send stop command to stop the channels */
	for (i = 0; i < MAX_CHANNELS_PER_GPII; i++) {
		ret = gpi_send_cmd(gpii, &gpii->gpii_chan[i], GPI_CH_CMD_STOP);
		gpii_chan = &gpii->gpii_chan[i];
		/* disable ch state so no more TRE processing */
		write_lock_irq(&gpii->pm_lock);
		gpii_chan->pm_state = PREPARE_TERMINATE;
		write_unlock_irq(&gpii->pm_lock);
			/* send command to Stop the channel */
		ret = gpi_send_cmd(gpii, gpii_chan, GPI_CH_CMD_STOP);
		if (ret) {
			GPII_ERR(gpii, gpii->gpii_chan[i].chid,
				 "Error stopping chan, ret:%d\n", ret);
			mutex_unlock(&gpii->ctrl_lock);
			return ret;
			return -ECONNRESET;
		}
	}

	disable_irq(gpii->irq);
	for (i = 0; i < MAX_CHANNELS_PER_GPII; i++) {
		gpii_chan = &gpii->gpii_chan[i];
		gpi_noop_tre(gpii_chan);
	}

	/* Wait for threads to complete out */
	tasklet_kill(&gpii->ev_task);
	for (i = 0; i < MAX_CHANNELS_PER_GPII; i++) {
		gpii_chan = &gpii->gpii_chan[i];

	write_lock_irq(&gpii->pm_lock);
	gpii->pm_state = PAUSE_STATE;
	write_unlock_irq(&gpii->pm_lock);
		ret = gpi_start_chan(gpii_chan);
		if (ret) {
			GPII_ERR(gpii, gpii_chan->chid,
				 "Error Starting Channel ret:%d\n", ret);
			mutex_unlock(&gpii->ctrl_lock);
			return ret;
		}
	}

	mutex_unlock(&gpii->ctrl_lock);
	return 0;
}

@@ -2378,6 +2431,7 @@ struct dma_async_tx_descriptor *gpi_prep_slave_sg(struct dma_chan *chan,
	const gfp_t gfp = GFP_ATOMIC;
	struct gpi_desc *gpi_desc;
	u32 tre_type;
	gpii_chan->num_tre = sg_len;

	GPII_VERB(gpii, gpii_chan->chid, "enter\n");

@@ -2414,6 +2468,12 @@ struct dma_async_tx_descriptor *gpi_prep_slave_sg(struct dma_chan *chan,
	for_each_sg(sgl, sg, sg_len, i) {
		tre = sg_virt(sg);

		if (sg_len == 1) {
			tre_type =
			MSM_GPI_TRE_TYPE(((struct msm_gpi_tre *)tre));
			gpii_chan->lock_tre_set =
			tre_type == MSM_GPI_TRE_LOCK ? true : false;
		}
		/* Check if last tre is an unlock tre */
		if (i == sg_len - 1) {
			tre_type =
@@ -2718,14 +2778,17 @@ static int gpi_alloc_chan_resources(struct dma_chan *chan)
	return ret;
}

static int gpi_find_avail_gpii(struct gpi_dev *gpi_dev, u32 seid)
static int gpi_find_avail_gpii(struct gpi_dev *gpi_dev, u32 seid,
		bool static_gpii)
{
	int gpii;
	struct gpii_chan *tx_chan, *rx_chan;
	u32 gpii_mask =
		static_gpii ? gpi_dev->static_gpii_mask : gpi_dev->gpii_mask;

	/* check if same seid is already configured for another chid */
	for (gpii = 0; gpii < gpi_dev->max_gpii; gpii++) {
		if (!((1 << gpii) & gpi_dev->gpii_mask))
		if (!((1 << gpii) & gpii_mask))
			continue;

		tx_chan = &gpi_dev->gpiis[gpii].gpii_chan[GPI_TX_CHAN];
@@ -2739,7 +2802,7 @@ static int gpi_find_avail_gpii(struct gpi_dev *gpi_dev, u32 seid)

	/* no channels configured with same seid, return next avail gpii */
	for (gpii = 0; gpii < gpi_dev->max_gpii; gpii++) {
		if (!((1 << gpii) & gpi_dev->gpii_mask))
		if (!((1 << gpii) & gpii_mask))
			continue;

		tx_chan = &gpi_dev->gpiis[gpii].gpii_chan[GPI_TX_CHAN];
@@ -2764,8 +2827,9 @@ static struct dma_chan *gpi_of_dma_xlate(struct of_phandle_args *args,
{
	struct gpi_dev *gpi_dev = (struct gpi_dev *)of_dma->of_dma_data;
	u32 seid, chid;
	int gpii;
	int gpii, val;
	struct gpii_chan *gpii_chan;
	bool static_gpii;

	if (args->args_count < REQ_OF_DMA_ARGS) {
		GPI_ERR(gpi_dev,
@@ -2781,9 +2845,11 @@ static struct dma_chan *gpi_of_dma_xlate(struct of_phandle_args *args,
	}

	seid = args->args[1];
	val = (args->args[4] & STATIC_GPII_BMSK) >> STATIC_GPII_SHFT;
	static_gpii = (val == 1) ? true : false;

	/* find next available gpii to use */
	gpii = gpi_find_avail_gpii(gpi_dev, seid);
	gpii = gpi_find_avail_gpii(gpi_dev, seid, static_gpii);
	if (gpii < 0) {
		GPI_ERR(gpi_dev, "no available gpii instances\n");
		return NULL;
@@ -2800,7 +2866,7 @@ static struct dma_chan *gpi_of_dma_xlate(struct of_phandle_args *args,
	gpii_chan->seid = seid;
	gpii_chan->protocol = args->args[2];
	gpii_chan->req_tres = args->args[3];
	gpii_chan->priority = args->args[4];
	gpii_chan->priority = args->args[4] & GPI_EV_PRIORITY_BMSK;

	GPI_LOG(gpi_dev,
		"client req. gpii:%u chid:%u #_tre:%u priority:%u protocol:%u\n",
@@ -2838,7 +2904,8 @@ static void gpi_setup_debug(struct gpi_dev *gpi_dev)
	for (i = 0; i < gpi_dev->max_gpii; i++) {
		struct gpii *gpii;

		if (!((1 << i) & gpi_dev->gpii_mask))
		if (!(((1 << i) & gpi_dev->gpii_mask)  ||
				((1 << i) & gpi_dev->static_gpii_mask)))
			continue;

		gpii = &gpi_dev->gpiis[i];
@@ -2910,6 +2977,11 @@ static int gpi_probe(struct platform_device *pdev)
		return ret;
	}

	ret = of_property_read_u32(gpi_dev->dev->of_node,
		"qcom,static-gpii-mask", &gpi_dev->static_gpii_mask);
	if (!ret)
		GPI_LOG(gpi_dev, "static GPII usecase\n");

	ret = of_property_read_u32(gpi_dev->dev->of_node,
					"qcom,gpi-ee-offset", &gpi_ee_offset);
	if (ret)
@@ -2941,13 +3013,19 @@ static int gpi_probe(struct platform_device *pdev)
	if (!gpi_dev->gpiis)
		return -ENOMEM;

	gpi_dev->is_le_vm = of_property_read_bool(pdev->dev.of_node,
			"qcom,le-vm");
	if (gpi_dev->is_le_vm)
		GPI_LOG(gpi_dev, "LE-VM usecase\n");

	/* setup all the supported gpii */
	INIT_LIST_HEAD(&gpi_dev->dma_device.channels);
	for (i = 0; i < gpi_dev->max_gpii; i++) {
		struct gpii *gpii = &gpi_dev->gpiis[i];
		int chan;

		if (!((1 << i) & gpi_dev->gpii_mask))
		if (!(((1 << i) & gpi_dev->gpii_mask)  ||
				((1 << i) & gpi_dev->static_gpii_mask)))
			continue;

		/* set up ev cntxt register map */
@@ -3075,7 +3153,8 @@ static int gpi_remove(struct platform_device *pdev)
		struct gpii *gpii = &gpi_dev->gpiis[i];
		int chan;

		if (!((1 << i) & gpi_dev->gpii_mask))
		if (!(((1 << i) & gpi_dev->gpii_mask)  ||
				((1 << i) & gpi_dev->static_gpii_mask)))
			continue;

		for (chan = 0; chan < MAX_CHANNELS_PER_GPII; chan++) {
+374 −159

File changed.

Preview size limit exceeded, changes collapsed.

+5 −0
Original line number Diff line number Diff line
@@ -179,6 +179,11 @@ enum msm_gpi_tre_type {
#define MSM_GPI_RING_PHYS_ADDR_UPPER(ptr) 0
#endif

/* Static GPII */
#define STATIC_GPII_BMSK (0x2)
#define STATIC_GPII_SHFT (0x1)
#define GPI_EV_PRIORITY_BMSK (0x1)

/* cmds to perform by using dmaengine_slave_config() */
enum msm_gpi_ctrl_cmd {
	MSM_GPI_INIT,