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

Commit 3a5e23cf authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'davinci-for-v3.16/edma' of...

Merge tag 'davinci-for-v3.16/edma' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into next/drivers

Merge "DaVinci EDMA clean-up for v3.16" from Sekhar Nori:

This series makes edma use configuration information available within
the IP instead of reading it from platform data or DT. Some other useful
clean-ups are included too.

* tag 'davinci-for-v3.16/edma' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci

: (34 commits)
  ARM: edma: Remove redundant/unused parameters from edma_soc_info
  ARM: davinci: Remove redundant/unused parameters for edma
  ARM: dts: am4372: Remove obsolete properties from edma node
  ARM: dts: am33xx: Remove obsolete properties from edma node
  dt/bindings: ti,edma: Remove redundant properties from documentation
  ARM: edma: Get IP configuration from HW (number of channels, tc, etc)
  ARM: edma: Save number of regions from pdata to struct edma
  ARM: edma: Remove num_cc member from struct edma
  ARM: edma: Remove queue_tc_mapping data from edma_soc_info
  ARM: davinci: Remove eDMA3 queue_tc_mapping data from edma_soc_info
  ARM: edma: Do not change TC -> Queue mapping, leave it to default.
  ARM: edma: Take the number of tc from edma_soc_info (pdata)
  ARM: edma: No need to clean the pdata in edma_of_parse_dt()
  ARM: edma: Clean up and simplify the code around irq request
  dmaengine: edma: update DMA memcpy to use new param element
  dmaengine: edma: Document variables used for residue accounting
  dmaengine: edma: Provide granular accounting
  dmaengine: edma: Make reading the position of active channels work
  dmaengine: edma: Store transfer data in edma_desc and edma_pset
  dmaengine: edma: Create private pset struct
  ...

Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 7741fa19 903ed491
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -2,11 +2,8 @@ TI EDMA

Required properties:
- compatible : "ti,edma3"
- ti,edma-regions: Number of regions
- ti,edma-slots: Number of slots
- #dma-cells: Should be set to <1>
              Clients should use a single channel number per DMA request.
- dma-channels: Specify total DMA channels per CC
- reg: Memory map for accessing module
- interrupt-parent: Interrupt controller the interrupt is routed through
- interrupts: Exactly 3 interrupts need to be specified in the order:
@@ -17,6 +14,13 @@ Optional properties:
- ti,hwmods: Name of the hwmods associated to the EDMA
- ti,edma-xbar-event-map: Crossbar event to channel map

Deprecated properties:
Listed here in case one wants to boot an old kernel with new DTB. These
properties might need to be added to the new DTS files.
- ti,edma-regions: Number of regions
- ti,edma-slots: Number of slots
- dma-channels: Specify total DMA channels per CC

Example:

edma: edma@49000000 {
@@ -26,9 +30,6 @@ edma: edma@49000000 {
	compatible = "ti,edma3";
	ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
	#dma-cells = <1>;
	dma-channels = <64>;
	ti,edma-regions = <4>;
	ti,edma-slots = <256>;
	ti,edma-xbar-event-map = /bits/ 16 <1 12
					    2 13>;
};
+0 −3
Original line number Diff line number Diff line
@@ -147,9 +147,6 @@
				<0x44e10f90 0x40>;
			interrupts = <12 13 14>;
			#dma-cells = <1>;
			dma-channels = <64>;
			ti,edma-regions = <4>;
			ti,edma-slots = <256>;
		};

		gpio0: gpio@44e07000 {
+0 −3
Original line number Diff line number Diff line
@@ -108,9 +108,6 @@
					<GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
					<GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
			#dma-cells = <1>;
			dma-channels = <64>;
			ti,edma-regions = <4>;
			ti,edma-slots = <256>;
		};

		uart0: serial@44e09000 {
+96 −101
Original line number Diff line number Diff line
@@ -102,6 +102,12 @@
#define PARM_OFFSET(param_no)	(EDMA_PARM + ((param_no) << 5))

#define EDMA_DCHMAP	0x0100  /* 64 registers */

/* CCCFG register */
#define GET_NUM_DMACH(x)	(x & 0x7) /* bits 0-2 */
#define GET_NUM_PAENTRY(x)	((x & 0x7000) >> 12) /* bits 12-14 */
#define GET_NUM_EVQUE(x)	((x & 0x70000) >> 16) /* bits 16-18 */
#define GET_NUM_REGN(x)		((x & 0x300000) >> 20) /* bits 20-21 */
#define CHMAP_EXIST		BIT(24)

#define EDMA_MAX_DMACH           64
@@ -233,7 +239,6 @@ struct edma {
	unsigned	num_region;
	unsigned	num_slots;
	unsigned	num_tc;
	unsigned	num_cc;
	enum dma_event_q 	default_queue;

	/* list of channels with no even trigger; terminated by "-1" */
@@ -290,12 +295,6 @@ static void map_dmach_queue(unsigned ctlr, unsigned ch_no,
			~(0x7 << bit), queue_no << bit);
}

static void __init map_queue_tc(unsigned ctlr, int queue_no, int tc_no)
{
	int bit = queue_no * 4;
	edma_modify(ctlr, EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit));
}

static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,
		int priority)
{
@@ -994,29 +993,23 @@ void edma_set_dest(unsigned slot, dma_addr_t dest_port,
EXPORT_SYMBOL(edma_set_dest);

/**
 * edma_get_position - returns the current transfer points
 * edma_get_position - returns the current transfer point
 * @slot: parameter RAM slot being examined
 * @src: pointer to source port position
 * @dst: pointer to destination port position
 * @dst:  true selects the dest position, false the source
 *
 * Returns current source and destination addresses for a particular
 * parameter RAM slot.  Its channel should not be active when this is called.
 * Returns the position of the current active slot
 */
void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst)
dma_addr_t edma_get_position(unsigned slot, bool dst)
{
	struct edmacc_param temp;
	unsigned ctlr;
	u32 offs, ctlr = EDMA_CTLR(slot);

	ctlr = EDMA_CTLR(slot);
	slot = EDMA_CHAN_SLOT(slot);

	edma_read_slot(EDMA_CTLR_CHAN(ctlr, slot), &temp);
	if (src != NULL)
		*src = temp.src;
	if (dst != NULL)
		*dst = temp.dst;
	offs = PARM_OFFSET(slot);
	offs += dst ? PARM_DST : PARM_SRC;

	return edma_read(ctlr, offs);
}
EXPORT_SYMBOL(edma_get_position);

/**
 * edma_set_src_index - configure DMA source address indexing
@@ -1421,6 +1414,67 @@ void edma_clear_event(unsigned channel)
}
EXPORT_SYMBOL(edma_clear_event);

static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,
			      struct edma *edma_cc)
{
	int i;
	u32 value, cccfg;
	s8 (*queue_priority_map)[2];

	/* Decode the eDMA3 configuration from CCCFG register */
	cccfg = edma_read(0, EDMA_CCCFG);

	value = GET_NUM_REGN(cccfg);
	edma_cc->num_region = BIT(value);

	value = GET_NUM_DMACH(cccfg);
	edma_cc->num_channels = BIT(value + 1);

	value = GET_NUM_PAENTRY(cccfg);
	edma_cc->num_slots = BIT(value + 4);

	value = GET_NUM_EVQUE(cccfg);
	edma_cc->num_tc = value + 1;

	dev_dbg(dev, "eDMA3 HW configuration (cccfg: 0x%08x):\n", cccfg);
	dev_dbg(dev, "num_region: %u\n", edma_cc->num_region);
	dev_dbg(dev, "num_channel: %u\n", edma_cc->num_channels);
	dev_dbg(dev, "num_slot: %u\n", edma_cc->num_slots);
	dev_dbg(dev, "num_tc: %u\n", edma_cc->num_tc);

	/* Nothing need to be done if queue priority is provided */
	if (pdata->queue_priority_mapping)
		return 0;

	/*
	 * Configure TC/queue priority as follows:
	 * Q0 - priority 0
	 * Q1 - priority 1
	 * Q2 - priority 2
	 * ...
	 * The meaning of priority numbers: 0 highest priority, 7 lowest
	 * priority. So Q0 is the highest priority queue and the last queue has
	 * the lowest priority.
	 */
	queue_priority_map = devm_kzalloc(dev,
					  (edma_cc->num_tc + 1) * sizeof(s8),
					  GFP_KERNEL);
	if (!queue_priority_map)
		return -ENOMEM;

	for (i = 0; i < edma_cc->num_tc; i++) {
		queue_priority_map[i][0] = i;
		queue_priority_map[i][1] = i;
	}
	queue_priority_map[i][0] = -1;
	queue_priority_map[i][1] = -1;

	pdata->queue_priority_mapping = queue_priority_map;
	pdata->default_queue = 0;

	return 0;
}

#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES)

static int edma_xbar_event_map(struct device *dev, struct device_node *node,
@@ -1471,65 +1525,16 @@ static int edma_of_parse_dt(struct device *dev,
			    struct device_node *node,
			    struct edma_soc_info *pdata)
{
	int ret = 0, i;
	u32 value;
	int ret = 0;
	struct property *prop;
	size_t sz;
	struct edma_rsv_info *rsv_info;
	s8 (*queue_tc_map)[2], (*queue_priority_map)[2];

	memset(pdata, 0, sizeof(struct edma_soc_info));

	ret = of_property_read_u32(node, "dma-channels", &value);
	if (ret < 0)
		return ret;
	pdata->n_channel = value;

	ret = of_property_read_u32(node, "ti,edma-regions", &value);
	if (ret < 0)
		return ret;
	pdata->n_region = value;

	ret = of_property_read_u32(node, "ti,edma-slots", &value);
	if (ret < 0)
		return ret;
	pdata->n_slot = value;

	pdata->n_cc = 1;

	rsv_info = devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL);
	if (!rsv_info)
		return -ENOMEM;
	pdata->rsv = rsv_info;

	queue_tc_map = devm_kzalloc(dev, 8*sizeof(s8), GFP_KERNEL);
	if (!queue_tc_map)
		return -ENOMEM;

	for (i = 0; i < 3; i++) {
		queue_tc_map[i][0] = i;
		queue_tc_map[i][1] = i;
	}
	queue_tc_map[i][0] = -1;
	queue_tc_map[i][1] = -1;

	pdata->queue_tc_mapping = queue_tc_map;

	queue_priority_map = devm_kzalloc(dev, 8*sizeof(s8), GFP_KERNEL);
	if (!queue_priority_map)
		return -ENOMEM;

	for (i = 0; i < 3; i++) {
		queue_priority_map[i][0] = i;
		queue_priority_map[i][1] = i;
	}
	queue_priority_map[i][0] = -1;
	queue_priority_map[i][1] = -1;

	pdata->queue_priority_mapping = queue_priority_map;

	pdata->default_queue = 0;

	prop = of_find_property(node, "ti,edma-xbar-event-map", &sz);
	if (prop)
		ret = edma_xbar_event_map(dev, node, pdata, sz);
@@ -1556,6 +1561,7 @@ static struct edma_soc_info *edma_setup_info_from_dt(struct device *dev,
		return ERR_PTR(ret);

	dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap);
	dma_cap_set(DMA_CYCLIC, edma_filter_info.dma_cap);
	of_dma_controller_register(dev->of_node, of_dma_simple_xlate,
				   &edma_filter_info);

@@ -1574,7 +1580,6 @@ static int edma_probe(struct platform_device *pdev)
	struct edma_soc_info	**info = pdev->dev.platform_data;
	struct edma_soc_info    *ninfo[EDMA_MAX_CC] = {NULL};
	s8		(*queue_priority_mapping)[2];
	s8		(*queue_tc_mapping)[2];
	int			i, j, off, ln, found = 0;
	int			status = -1;
	const s16		(*rsv_chans)[2];
@@ -1585,7 +1590,6 @@ static int edma_probe(struct platform_device *pdev)
	struct resource		*r[EDMA_MAX_CC] = {NULL};
	struct resource		res[EDMA_MAX_CC];
	char			res_name[10];
	char			irq_name[10];
	struct device_node	*node = pdev->dev.of_node;
	struct device		*dev = &pdev->dev;
	int			ret;
@@ -1650,12 +1654,10 @@ static int edma_probe(struct platform_device *pdev)
		if (!edma_cc[j])
			return -ENOMEM;

		edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
							EDMA_MAX_DMACH);
		edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot,
							EDMA_MAX_PARAMENTRY);
		edma_cc[j]->num_cc = min_t(unsigned, info[j]->n_cc,
							EDMA_MAX_CC);
		/* Get eDMA3 configuration from IP */
		ret = edma_setup_from_hw(dev, info[j], edma_cc[j]);
		if (ret)
			return ret;

		edma_cc[j]->default_queue = info[j]->default_queue;

@@ -1707,14 +1709,21 @@ static int edma_probe(struct platform_device *pdev)

		if (node) {
			irq[j] = irq_of_parse_and_map(node, 0);
			err_irq[j] = irq_of_parse_and_map(node, 2);
		} else {
			char irq_name[10];

			sprintf(irq_name, "edma%d", j);
			irq[j] = platform_get_irq_byname(pdev, irq_name);

			sprintf(irq_name, "edma%d_err", j);
			err_irq[j] = platform_get_irq_byname(pdev, irq_name);
		}
		edma_cc[j]->irq_res_start = irq[j];
		status = devm_request_irq(&pdev->dev, irq[j],
					  dma_irq_handler, 0, "edma",
					  &pdev->dev);
		edma_cc[j]->irq_res_end = err_irq[j];

		status = devm_request_irq(dev, irq[j], dma_irq_handler, 0,
					  "edma", dev);
		if (status < 0) {
			dev_dbg(&pdev->dev,
				"devm_request_irq %d failed --> %d\n",
@@ -1722,16 +1731,8 @@ static int edma_probe(struct platform_device *pdev)
			return status;
		}

		if (node) {
			err_irq[j] = irq_of_parse_and_map(node, 2);
		} else {
			sprintf(irq_name, "edma%d_err", j);
			err_irq[j] = platform_get_irq_byname(pdev, irq_name);
		}
		edma_cc[j]->irq_res_end = err_irq[j];
		status = devm_request_irq(&pdev->dev, err_irq[j],
					  dma_ccerr_handler, 0,
					  "edma_error", &pdev->dev);
		status = devm_request_irq(dev, err_irq[j], dma_ccerr_handler, 0,
					  "edma_error", dev);
		if (status < 0) {
			dev_dbg(&pdev->dev,
				"devm_request_irq %d failed --> %d\n",
@@ -1742,14 +1743,8 @@ static int edma_probe(struct platform_device *pdev)
		for (i = 0; i < edma_cc[j]->num_channels; i++)
			map_dmach_queue(j, i, info[j]->default_queue);

		queue_tc_mapping = info[j]->queue_tc_mapping;
		queue_priority_mapping = info[j]->queue_priority_mapping;

		/* Event queue to TC mapping */
		for (i = 0; queue_tc_mapping[i][0] != -1; i++)
			map_queue_tc(j, queue_tc_mapping[i][0],
					queue_tc_mapping[i][1]);

		/* Event queue priority mapping */
		for (i = 0; queue_priority_mapping[i][0] != -1; i++)
			assign_priority_to_queue(j,
@@ -1762,7 +1757,7 @@ static int edma_probe(struct platform_device *pdev)
		if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
			map_dmach_param(j);

		for (i = 0; i < info[j]->n_region; i++) {
		for (i = 0; i < edma_cc[j]->num_region; i++) {
			edma_write_array2(j, EDMA_DRAE, i, 0, 0x0);
			edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
			edma_write_array(j, EDMA_QRAE, i, 0x0);
+0 −31
Original line number Diff line number Diff line
@@ -134,13 +134,6 @@ struct platform_device da8xx_serial_device[] = {
	}
};

static s8 da8xx_queue_tc_mapping[][2] = {
	/* {event queue no, TC no} */
	{0, 0},
	{1, 1},
	{-1, -1}
};

static s8 da8xx_queue_priority_mapping[][2] = {
	/* {event queue no, Priority} */
	{0, 3},
@@ -148,12 +141,6 @@ static s8 da8xx_queue_priority_mapping[][2] = {
	{-1, -1}
};

static s8 da850_queue_tc_mapping[][2] = {
	/* {event queue no, TC no} */
	{0, 0},
	{-1, -1}
};

static s8 da850_queue_priority_mapping[][2] = {
	/* {event queue no, Priority} */
	{0, 3},
@@ -161,12 +148,6 @@ static s8 da850_queue_priority_mapping[][2] = {
};

static struct edma_soc_info da830_edma_cc0_info = {
	.n_channel		= 32,
	.n_region		= 4,
	.n_slot			= 128,
	.n_tc			= 2,
	.n_cc			= 1,
	.queue_tc_mapping	= da8xx_queue_tc_mapping,
	.queue_priority_mapping	= da8xx_queue_priority_mapping,
	.default_queue		= EVENTQ_1,
};
@@ -177,22 +158,10 @@ static struct edma_soc_info *da830_edma_info[EDMA_MAX_CC] = {

static struct edma_soc_info da850_edma_cc_info[] = {
	{
		.n_channel		= 32,
		.n_region		= 4,
		.n_slot			= 128,
		.n_tc			= 2,
		.n_cc			= 1,
		.queue_tc_mapping	= da8xx_queue_tc_mapping,
		.queue_priority_mapping	= da8xx_queue_priority_mapping,
		.default_queue		= EVENTQ_1,
	},
	{
		.n_channel		= 32,
		.n_region		= 4,
		.n_slot			= 128,
		.n_tc			= 1,
		.n_cc			= 1,
		.queue_tc_mapping	= da850_queue_tc_mapping,
		.queue_priority_mapping	= da850_queue_priority_mapping,
		.default_queue		= EVENTQ_0,
	},
Loading