diff options
Diffstat (limited to 'arch/arm/common/edma.c')
| -rw-r--r-- | arch/arm/common/edma.c | 54 | 
1 files changed, 52 insertions, 2 deletions
diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c index 72041f002b7e..5662a872689b 100644 --- a/arch/arm/common/edma.c +++ b/arch/arm/common/edma.c @@ -245,6 +245,8 @@ struct edma {  	/* list of channels with no even trigger; terminated by "-1" */  	const s8	*noevent; +	struct edma_soc_info *info; +  	/* The edma_inuse bit for each PaRAM slot is clear unless the  	 * channel is in use ... by ARM or DSP, for QDMA, or whatever.  	 */ @@ -296,7 +298,7 @@ static void map_dmach_queue(unsigned ctlr, unsigned ch_no,  			~(0x7 << bit), queue_no << bit);  } -static void __init assign_priority_to_queue(unsigned ctlr, int queue_no, +static void assign_priority_to_queue(unsigned ctlr, int queue_no,  		int priority)  {  	int bit = queue_no * 4; @@ -315,7 +317,7 @@ static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,   * included in that particular EDMA variant (Eg : dm646x)   *   */ -static void __init map_dmach_param(unsigned ctlr) +static void map_dmach_param(unsigned ctlr)  {  	int i;  	for (i = 0; i < EDMA_MAX_DMACH; i++) @@ -1798,6 +1800,7 @@ static int edma_probe(struct platform_device *pdev)  			edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);  			edma_write_array(j, EDMA_QRAE, i, 0x0);  		} +		edma_cc[j]->info = info[j];  		arch_num_cc++;  		edma_dev_info.id = j; @@ -1807,9 +1810,56 @@ static int edma_probe(struct platform_device *pdev)  	return 0;  } +#ifdef CONFIG_PM_SLEEP +static int edma_pm_resume(struct device *dev) +{ +	int i, j; + +	for (j = 0; j < arch_num_cc; j++) { +		struct edma *cc = edma_cc[j]; + +		s8 (*queue_priority_mapping)[2]; + +		queue_priority_mapping = cc->info->queue_priority_mapping; + +		/* Event queue priority mapping */ +		for (i = 0; queue_priority_mapping[i][0] != -1; i++) +			assign_priority_to_queue(j, +						 queue_priority_mapping[i][0], +						 queue_priority_mapping[i][1]); + +		/* +		 * Map the channel to param entry if channel mapping logic +		 * exist +		 */ +		if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST) +			map_dmach_param(j); + +		for (i = 0; i < cc->num_channels; i++) { +			if (test_bit(i, cc->edma_inuse)) { +				/* ensure access through shadow region 0 */ +				edma_or_array2(j, EDMA_DRAE, 0, i >> 5, +					       BIT(i & 0x1f)); + +				setup_dma_interrupt(i, +						    cc->intr_data[i].callback, +						    cc->intr_data[i].data); +			} +		} +	} + +	return 0; +} +#endif + +static const struct dev_pm_ops edma_pm_ops = { +	SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, edma_pm_resume) +}; +  static struct platform_driver edma_driver = {  	.driver = {  		.name	= "edma", +		.pm	= &edma_pm_ops,  		.of_match_table = edma_of_ids,  	},  	.probe = edma_probe,  |