diff options
| author | Alexandre Bailon <abailon@baylibre.com> | 2017-02-06 22:53:56 -0600 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-02-09 13:35:05 +0100 | 
| commit | 255348289f714b96e0e95f9b702f435a638e6fd4 (patch) | |
| tree | 8582ea828878ab62ba768725eccf809897e2f07d | |
| parent | a96ca0d20636b594f28772454eedb2b7d8da5a1b (diff) | |
usb: musb: dsps: Manage CPPI 4.1 DMA interrupt in DSPS
Despite the CPPI 4.1 is a generic DMA, it is tied to USB.
On the DSPS, CPPI 4.1 interrupt's registers are in USBSS (the MUSB glue).
Currently, to enable / disable and clear interrupts, the CPPI 4.1 driver
maps and accesses to USBSS's register, which making CPPI 4.1 driver not
really generic.
Move the interrupt management to DSPS driver.
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Bin Liu <b-liu@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | drivers/dma/cppi41.c | 28 | ||||
| -rw-r--r-- | drivers/usb/musb/musb_dsps.c | 81 | 
2 files changed, 86 insertions, 23 deletions
diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index 200828c60db9..d74cee077842 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c @@ -79,14 +79,6 @@  #define QMGR_QUEUE_C(n)	(0x2008 + (n) * 0x10)  #define QMGR_QUEUE_D(n)	(0x200c + (n) * 0x10) -/* Glue layer specific */ -/* USBSS  / USB AM335x */ -#define USBSS_IRQ_STATUS	0x28 -#define USBSS_IRQ_ENABLER	0x2c -#define USBSS_IRQ_CLEARR	0x30 - -#define USBSS_IRQ_PD_COMP	(1 <<  2) -  /* Packet Descriptor */  #define PD2_ZERO_LENGTH		(1 << 19) @@ -294,14 +286,8 @@ static irqreturn_t cppi41_irq(int irq, void *data)  {  	struct cppi41_dd *cdd = data;  	struct cppi41_channel *c; -	u32 status;  	int i; -	status = cppi_readl(cdd->usbss_mem + USBSS_IRQ_STATUS); -	if (!(status & USBSS_IRQ_PD_COMP)) -		return IRQ_NONE; -	cppi_writel(status, cdd->usbss_mem + USBSS_IRQ_STATUS); -  	for (i = QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE); i < QMGR_NUM_PEND;  			i++) {  		u32 val; @@ -618,6 +604,7 @@ static void cppi41_compute_td_desc(struct cppi41_desc *d)  static int cppi41_tear_down_chan(struct cppi41_channel *c)  { +	struct dmaengine_result abort_result;  	struct cppi41_dd *cdd = c->cdd;  	struct cppi41_desc *td;  	u32 reg; @@ -701,6 +688,12 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c)  	c->td_seen = 0;  	c->td_desc_seen = 0;  	cppi_writel(0, c->gcr_reg); + +	/* Invoke the callback to do the necessary clean-up */ +	abort_result.result = DMA_TRANS_ABORTED; +	dma_cookie_complete(&c->txd); +	dmaengine_desc_get_callback_invoke(&c->txd, &abort_result); +  	return 0;  } @@ -1066,8 +1059,6 @@ static int cppi41_dma_probe(struct platform_device *pdev)  		goto err_irq;  	} -	cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER); -  	ret = devm_request_irq(&pdev->dev, irq, glue_info->isr, IRQF_SHARED,  			dev_name(dev), cdd);  	if (ret) @@ -1091,7 +1082,6 @@ err_of:  	dma_async_device_unregister(&cdd->ddev);  err_dma_reg:  err_irq: -	cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);  	cleanup_chans(cdd);  err_chans:  	deinit_cppi41(dev, cdd); @@ -1119,7 +1109,6 @@ static int cppi41_dma_remove(struct platform_device *pdev)  	of_dma_controller_free(pdev->dev.of_node);  	dma_async_device_unregister(&cdd->ddev); -	cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);  	devm_free_irq(&pdev->dev, cdd->irq, cdd);  	cleanup_chans(cdd);  	deinit_cppi41(&pdev->dev, cdd); @@ -1138,7 +1127,6 @@ static int __maybe_unused cppi41_suspend(struct device *dev)  	struct cppi41_dd *cdd = dev_get_drvdata(dev);  	cdd->dma_tdfdq = cppi_readl(cdd->ctrl_mem + DMA_TDFDQ); -	cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);  	disable_sched(cdd);  	return 0; @@ -1164,8 +1152,6 @@ static int __maybe_unused cppi41_resume(struct device *dev)  	cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE);  	cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE); -	cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER); -  	return 0;  } diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index c171a0f13bc3..7c047c4a2565 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -122,6 +122,7 @@ struct dsps_glue {  	struct timer_list timer;	/* otg_workaround timer */  	unsigned long last_timer;    /* last timer data for each instance */  	bool sw_babble_enabled; +	void __iomem *usbss_base;  	struct dsps_context context;  	struct debugfs_regset32 regset; @@ -169,6 +170,13 @@ static void dsps_mod_timer_optional(struct dsps_glue *glue)  	dsps_mod_timer(glue, -1);  } +/* USBSS  / USB AM335x */ +#define USBSS_IRQ_STATUS	0x28 +#define USBSS_IRQ_ENABLER	0x2c +#define USBSS_IRQ_CLEARR	0x30 + +#define USBSS_IRQ_PD_COMP	(1 << 2) +  /**   * dsps_musb_enable - enable interrupts   */ @@ -641,14 +649,76 @@ static void dsps_read_fifo32(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)  	}  } +#ifdef CONFIG_USB_TI_CPPI41_DMA +static void dsps_dma_controller_callback(struct dma_controller *c) +{ +	struct musb *musb = c->musb; +	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent); +	void __iomem *usbss_base = glue->usbss_base; +	u32 status; + +	status = musb_readl(usbss_base, USBSS_IRQ_STATUS); +	if (status & USBSS_IRQ_PD_COMP) +		musb_writel(usbss_base, USBSS_IRQ_STATUS, USBSS_IRQ_PD_COMP); +} + +static struct dma_controller * +dsps_dma_controller_create(struct musb *musb, void __iomem *base) +{ +	struct dma_controller *controller; +	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent); +	void __iomem *usbss_base = glue->usbss_base; + +	controller = cppi41_dma_controller_create(musb, base); +	if (IS_ERR_OR_NULL(controller)) +		return controller; + +	musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP); +	controller->dma_callback = dsps_dma_controller_callback; + +	return controller; +} + +static void dsps_dma_controller_destroy(struct dma_controller *c) +{ +	struct musb *musb = c->musb; +	struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent); +	void __iomem *usbss_base = glue->usbss_base; + +	musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP); +	cppi41_dma_controller_destroy(c); +} + +#ifdef CONFIG_PM_SLEEP +static void dsps_dma_controller_suspend(struct dsps_glue *glue) +{ +	void __iomem *usbss_base = glue->usbss_base; + +	musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP); +} + +static void dsps_dma_controller_resume(struct dsps_glue *glue) +{ +	void __iomem *usbss_base = glue->usbss_base; + +	musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP); +} +#endif +#else /* CONFIG_USB_TI_CPPI41_DMA */ +#ifdef CONFIG_PM_SLEEP +static void dsps_dma_controller_suspend(struct dsps_glue *glue) {} +static void dsps_dma_controller_resume(struct dsps_glue *glue) {} +#endif +#endif /* CONFIG_USB_TI_CPPI41_DMA */ +  static struct musb_platform_ops dsps_ops = {  	.quirks		= MUSB_DMA_CPPI41 | MUSB_INDEXED_EP,  	.init		= dsps_musb_init,  	.exit		= dsps_musb_exit,  #ifdef CONFIG_USB_TI_CPPI41_DMA -	.dma_init	= cppi41_dma_controller_create, -	.dma_exit	= cppi41_dma_controller_destroy, +	.dma_init	= dsps_dma_controller_create, +	.dma_exit	= dsps_dma_controller_destroy,  #endif  	.enable		= dsps_musb_enable,  	.disable	= dsps_musb_disable, @@ -856,6 +926,9 @@ static int dsps_probe(struct platform_device *pdev)  	glue->dev = &pdev->dev;  	glue->wrp = wrp; +	glue->usbss_base = of_iomap(pdev->dev.parent->of_node, 0); +	if (!glue->usbss_base) +		return -ENXIO;  	if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) {  		ret = dsps_setup_optional_vbus_irq(pdev, glue); @@ -950,6 +1023,8 @@ static int dsps_suspend(struct device *dev)  	glue->context.tx_mode = musb_readl(mbase, wrp->tx_mode);  	glue->context.rx_mode = musb_readl(mbase, wrp->rx_mode); +	dsps_dma_controller_suspend(glue); +  	return 0;  } @@ -963,6 +1038,8 @@ static int dsps_resume(struct device *dev)  	if (!musb)  		return 0; +	dsps_dma_controller_resume(glue); +  	mbase = musb->ctrl_base;  	musb_writel(mbase, wrp->control, glue->context.control);  	musb_writel(mbase, wrp->epintr_set, glue->context.epintr);  | 
