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

Commit dfe09e14 authored by Sujeev Dias's avatar Sujeev Dias
Browse files

dmaengine: gpi: Dynamically assign gpii instance to clients



GPI dmaengine driver already has a list of supported gpii
instances. Also, all gpii instances are identical, support
all protocols, and operate on any serial engine. To reduce
configuration conflicts with clients, dynamically assign
next available gpii instance to clients.

CRs-Fixed: 2102800
Change-Id: I608f4a21bea372fe3641cf6c7dd0b4cdece44f2b
Signed-off-by: default avatarSujeev Dias <sdias@codeaurora.org>
parent 1d9aee75
Loading
Loading
Loading
Loading
+7 −8
Original line number Diff line number Diff line
@@ -12,13 +12,12 @@ Main node properties:
- #dma-cells
  Usage: required
  Value type: <u32>
  Definition: Number of parameters client will provide.  Must be set to 6.
	1st parameter: gpii index
	2nd parameter: channel index
	3rd parameter: serial engine index
	4th parameter: bus protocol, 1 for SPI, 2 for UART, 3 for I2C
	5th parameter: channel ring length in transfer ring elements
	6th parameter: event processing priority, set to 0 for lowest latency
  Definition: Number of parameters client will provide.  Must be set to 5.
	1st parameter: channel index, 0 for TX, 1 for RX
	2nd parameter: serial engine index
	3rd parameter: bus protocol, 1 for SPI, 2 for UART, 3 for I2C
	4th parameter: channel ring length in transfer ring elements
	5th parameter: event processing priority, set to 0 for lowest latency

- compatible
  Usage: required
@@ -68,7 +67,7 @@ Main node properties:
Example:
========
gpi_dma0: qcom,gpi-dma@0x800000 {
	#dma-cells = <6>;
	#dma-cells = <5>;
	compatible = "qcom,gpi-dma";
	reg = <0x800000 0x60000>;
	reg-names = "gpi-top";
+2 −2
Original line number Diff line number Diff line
@@ -3552,7 +3552,7 @@
	};

	gpi_dma0: qcom,gpi-dma@0x800000 {
		#dma-cells = <6>;
		#dma-cells = <5>;
		compatible = "qcom,gpi-dma";
		reg = <0x800000 0x60000>;
		reg-names = "gpi-top";
@@ -3568,7 +3568,7 @@
	};

	gpi_dma1: qcom,gpi-dma@0xa00000 {
		#dma-cells = <6>;
		#dma-cells = <5>;
		compatible = "qcom,gpi-dma";
		reg = <0xa00000 0x60000>;
		reg-names = "gpi-top";
+65 −14
Original line number Diff line number Diff line
@@ -131,9 +131,11 @@ enum EV_PRIORITY {
#define GPI_LABEL_SIZE (256)
#define GPI_DBG_COMMON (99)
#define MAX_CHANNELS_PER_GPII (2)
#define GPI_TX_CHAN (0)
#define GPI_RX_CHAN (1)
#define CMD_TIMEOUT_MS (50)
#define STATE_IGNORE (U32_MAX)
#define REQ_OF_DMA_ARGS (6) /* # of arguments required from client */
#define REQ_OF_DMA_ARGS (5) /* # of arguments required from client */

struct __packed gpi_error_log_entry {
	u32 routine : 4;
@@ -2464,12 +2466,53 @@ 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)
{
	int gpii;
	struct gpii_chan *tx_chan, *rx_chan;

	/* 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))
			continue;

		tx_chan = &gpi_dev->gpiis[gpii].gpii_chan[GPI_TX_CHAN];
		rx_chan = &gpi_dev->gpiis[gpii].gpii_chan[GPI_RX_CHAN];

		if (rx_chan->vc.chan.client_count && rx_chan->seid == seid)
			return gpii;
		if (tx_chan->vc.chan.client_count && tx_chan->seid == seid)
			return gpii;
	}

	/* 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))
			continue;

		tx_chan = &gpi_dev->gpiis[gpii].gpii_chan[GPI_TX_CHAN];
		rx_chan = &gpi_dev->gpiis[gpii].gpii_chan[GPI_RX_CHAN];

		/* check if gpii is configured */
		if (tx_chan->vc.chan.client_count ||
		    rx_chan->vc.chan.client_count)
			continue;

		/* found a free gpii */
		return gpii;
	}

	/* no gpii instance available to use */
	return -EIO;
}

/* gpi_of_dma_xlate: open client requested channel */
static struct dma_chan *gpi_of_dma_xlate(struct of_phandle_args *args,
					 struct of_dma *of_dma)
{
	struct gpi_dev *gpi_dev = (struct gpi_dev *)of_dma->of_dma_data;
	u32 gpii, chid;
	u32 seid, chid;
	int gpii;
	struct gpii_chan *gpii_chan;

	if (args->args_count < REQ_OF_DMA_ARGS) {
@@ -2479,25 +2522,33 @@ static struct dma_chan *gpi_of_dma_xlate(struct of_phandle_args *args,
		return NULL;
	}

	/* Check if valid gpii instance */
	gpii = args->args[0];
	if (!((1 << gpii) & gpi_dev->gpii_mask)) {
		GPI_ERR(gpi_dev, "gpii instance:%d is not supported\n", gpii);
	chid = args->args[0];
	if (chid >= MAX_CHANNELS_PER_GPII) {
		GPI_ERR(gpi_dev, "gpii channel:%d not valid\n", chid);
		return NULL;
	}

	chid = args->args[1];
	if (chid >= MAX_CHANNELS_PER_GPII) {
		GPI_ERR(gpi_dev, "gpii channel:%d not valid\n", chid);
	seid = args->args[1];

	/* find next available gpii to use */
	gpii = gpi_find_avail_gpii(gpi_dev, seid);
	if (gpii < 0) {
		GPI_ERR(gpi_dev, "no available gpii instances\n");
		return NULL;
	}

	/* get ring size, protocol, se_id, and priority */
	gpii_chan = &gpi_dev->gpiis[gpii].gpii_chan[chid];
	gpii_chan->seid = args->args[2];
	gpii_chan->protocol = args->args[3];
	gpii_chan->req_tres = args->args[4];
	gpii_chan->priority = args->args[5];
	if (gpii_chan->vc.chan.client_count) {
		GPI_ERR(gpi_dev, "gpii:%d chid:%d seid:%d already configured\n",
			gpii, chid, gpii_chan->seid);
		return NULL;
	}

	/* get ring size, protocol, se_id, and priority */
	gpii_chan->seid = seid;
	gpii_chan->protocol = args->args[2];
	gpii_chan->req_tres = args->args[3];
	gpii_chan->priority = args->args[4];

	GPI_LOG(gpi_dev,
		"client req. gpii:%u chid:%u #_tre:%u priority:%u protocol:%u\n",