xref: /openbmc/linux/drivers/dma/sh/usb-dmac.c (revision 0c1c8ff3)
10c1c8ff3SYoshihiro Shimoda /*
20c1c8ff3SYoshihiro Shimoda  * Renesas USB DMA Controller Driver
30c1c8ff3SYoshihiro Shimoda  *
40c1c8ff3SYoshihiro Shimoda  * Copyright (C) 2015 Renesas Electronics Corporation
50c1c8ff3SYoshihiro Shimoda  *
60c1c8ff3SYoshihiro Shimoda  * based on rcar-dmac.c
70c1c8ff3SYoshihiro Shimoda  * Copyright (C) 2014 Renesas Electronics Inc.
80c1c8ff3SYoshihiro Shimoda  * Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
90c1c8ff3SYoshihiro Shimoda  *
100c1c8ff3SYoshihiro Shimoda  * This is free software; you can redistribute it and/or modify
110c1c8ff3SYoshihiro Shimoda  * it under the terms of version 2 of the GNU General Public License as
120c1c8ff3SYoshihiro Shimoda  * published by the Free Software Foundation.
130c1c8ff3SYoshihiro Shimoda  */
140c1c8ff3SYoshihiro Shimoda 
150c1c8ff3SYoshihiro Shimoda #include <linux/delay.h>
160c1c8ff3SYoshihiro Shimoda #include <linux/dma-mapping.h>
170c1c8ff3SYoshihiro Shimoda #include <linux/dmaengine.h>
180c1c8ff3SYoshihiro Shimoda #include <linux/interrupt.h>
190c1c8ff3SYoshihiro Shimoda #include <linux/list.h>
200c1c8ff3SYoshihiro Shimoda #include <linux/module.h>
210c1c8ff3SYoshihiro Shimoda #include <linux/of.h>
220c1c8ff3SYoshihiro Shimoda #include <linux/of_dma.h>
230c1c8ff3SYoshihiro Shimoda #include <linux/of_platform.h>
240c1c8ff3SYoshihiro Shimoda #include <linux/platform_device.h>
250c1c8ff3SYoshihiro Shimoda #include <linux/pm_runtime.h>
260c1c8ff3SYoshihiro Shimoda #include <linux/slab.h>
270c1c8ff3SYoshihiro Shimoda #include <linux/spinlock.h>
280c1c8ff3SYoshihiro Shimoda 
290c1c8ff3SYoshihiro Shimoda #include "../dmaengine.h"
300c1c8ff3SYoshihiro Shimoda #include "../virt-dma.h"
310c1c8ff3SYoshihiro Shimoda 
320c1c8ff3SYoshihiro Shimoda /*
330c1c8ff3SYoshihiro Shimoda  * struct usb_dmac_sg - Descriptor for a hardware transfer
340c1c8ff3SYoshihiro Shimoda  * @mem_addr: memory address
350c1c8ff3SYoshihiro Shimoda  * @size: transfer size in bytes
360c1c8ff3SYoshihiro Shimoda  */
370c1c8ff3SYoshihiro Shimoda struct usb_dmac_sg {
380c1c8ff3SYoshihiro Shimoda 	dma_addr_t mem_addr;
390c1c8ff3SYoshihiro Shimoda 	u32 size;
400c1c8ff3SYoshihiro Shimoda };
410c1c8ff3SYoshihiro Shimoda 
420c1c8ff3SYoshihiro Shimoda /*
430c1c8ff3SYoshihiro Shimoda  * struct usb_dmac_desc - USB DMA Transfer Descriptor
440c1c8ff3SYoshihiro Shimoda  * @vd: base virtual channel DMA transaction descriptor
450c1c8ff3SYoshihiro Shimoda  * @direction: direction of the DMA transfer
460c1c8ff3SYoshihiro Shimoda  * @sg_allocated_len: length of allocated sg
470c1c8ff3SYoshihiro Shimoda  * @sg_len: length of sg
480c1c8ff3SYoshihiro Shimoda  * @sg_index: index of sg
490c1c8ff3SYoshihiro Shimoda  * @residue: residue after the DMAC completed a transfer
500c1c8ff3SYoshihiro Shimoda  * @node: node for desc_got and desc_freed
510c1c8ff3SYoshihiro Shimoda  * @done_cookie: cookie after the DMAC completed a transfer
520c1c8ff3SYoshihiro Shimoda  * @sg: information for the transfer
530c1c8ff3SYoshihiro Shimoda  */
540c1c8ff3SYoshihiro Shimoda struct usb_dmac_desc {
550c1c8ff3SYoshihiro Shimoda 	struct virt_dma_desc vd;
560c1c8ff3SYoshihiro Shimoda 	enum dma_transfer_direction direction;
570c1c8ff3SYoshihiro Shimoda 	unsigned int sg_allocated_len;
580c1c8ff3SYoshihiro Shimoda 	unsigned int sg_len;
590c1c8ff3SYoshihiro Shimoda 	unsigned int sg_index;
600c1c8ff3SYoshihiro Shimoda 	u32 residue;
610c1c8ff3SYoshihiro Shimoda 	struct list_head node;
620c1c8ff3SYoshihiro Shimoda 	dma_cookie_t done_cookie;
630c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_sg sg[0];
640c1c8ff3SYoshihiro Shimoda };
650c1c8ff3SYoshihiro Shimoda 
660c1c8ff3SYoshihiro Shimoda #define to_usb_dmac_desc(vd)	container_of(vd, struct usb_dmac_desc, vd)
670c1c8ff3SYoshihiro Shimoda 
680c1c8ff3SYoshihiro Shimoda /*
690c1c8ff3SYoshihiro Shimoda  * struct usb_dmac_chan - USB DMA Controller Channel
700c1c8ff3SYoshihiro Shimoda  * @vc: base virtual DMA channel object
710c1c8ff3SYoshihiro Shimoda  * @iomem: channel I/O memory base
720c1c8ff3SYoshihiro Shimoda  * @index: index of this channel in the controller
730c1c8ff3SYoshihiro Shimoda  * @irq: irq number of this channel
740c1c8ff3SYoshihiro Shimoda  * @desc: the current descriptor
750c1c8ff3SYoshihiro Shimoda  * @descs_allocated: number of descriptors allocated
760c1c8ff3SYoshihiro Shimoda  * @desc_got: got descriptors
770c1c8ff3SYoshihiro Shimoda  * @desc_freed: freed descriptors after the DMAC completed a transfer
780c1c8ff3SYoshihiro Shimoda  */
790c1c8ff3SYoshihiro Shimoda struct usb_dmac_chan {
800c1c8ff3SYoshihiro Shimoda 	struct virt_dma_chan vc;
810c1c8ff3SYoshihiro Shimoda 	void __iomem *iomem;
820c1c8ff3SYoshihiro Shimoda 	unsigned int index;
830c1c8ff3SYoshihiro Shimoda 	int irq;
840c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc;
850c1c8ff3SYoshihiro Shimoda 	int descs_allocated;
860c1c8ff3SYoshihiro Shimoda 	struct list_head desc_got;
870c1c8ff3SYoshihiro Shimoda 	struct list_head desc_freed;
880c1c8ff3SYoshihiro Shimoda };
890c1c8ff3SYoshihiro Shimoda 
900c1c8ff3SYoshihiro Shimoda #define to_usb_dmac_chan(c) container_of(c, struct usb_dmac_chan, vc.chan)
910c1c8ff3SYoshihiro Shimoda 
920c1c8ff3SYoshihiro Shimoda /*
930c1c8ff3SYoshihiro Shimoda  * struct usb_dmac - USB DMA Controller
940c1c8ff3SYoshihiro Shimoda  * @engine: base DMA engine object
950c1c8ff3SYoshihiro Shimoda  * @dev: the hardware device
960c1c8ff3SYoshihiro Shimoda  * @iomem: remapped I/O memory base
970c1c8ff3SYoshihiro Shimoda  * @n_channels: number of available channels
980c1c8ff3SYoshihiro Shimoda  * @channels: array of DMAC channels
990c1c8ff3SYoshihiro Shimoda  */
1000c1c8ff3SYoshihiro Shimoda struct usb_dmac {
1010c1c8ff3SYoshihiro Shimoda 	struct dma_device engine;
1020c1c8ff3SYoshihiro Shimoda 	struct device *dev;
1030c1c8ff3SYoshihiro Shimoda 	void __iomem *iomem;
1040c1c8ff3SYoshihiro Shimoda 
1050c1c8ff3SYoshihiro Shimoda 	unsigned int n_channels;
1060c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *channels;
1070c1c8ff3SYoshihiro Shimoda };
1080c1c8ff3SYoshihiro Shimoda 
1090c1c8ff3SYoshihiro Shimoda #define to_usb_dmac(d)		container_of(d, struct usb_dmac, engine)
1100c1c8ff3SYoshihiro Shimoda 
1110c1c8ff3SYoshihiro Shimoda /* -----------------------------------------------------------------------------
1120c1c8ff3SYoshihiro Shimoda  * Registers
1130c1c8ff3SYoshihiro Shimoda  */
1140c1c8ff3SYoshihiro Shimoda 
1150c1c8ff3SYoshihiro Shimoda #define USB_DMAC_CHAN_OFFSET(i)		(0x20 + 0x20 * (i))
1160c1c8ff3SYoshihiro Shimoda 
1170c1c8ff3SYoshihiro Shimoda #define USB_DMASWR			0x0008
1180c1c8ff3SYoshihiro Shimoda #define USB_DMASWR_SWR			(1 << 0)
1190c1c8ff3SYoshihiro Shimoda #define USB_DMAOR			0x0060
1200c1c8ff3SYoshihiro Shimoda #define USB_DMAOR_AE			(1 << 2)
1210c1c8ff3SYoshihiro Shimoda #define USB_DMAOR_DME			(1 << 0)
1220c1c8ff3SYoshihiro Shimoda 
1230c1c8ff3SYoshihiro Shimoda #define USB_DMASAR			0x0000
1240c1c8ff3SYoshihiro Shimoda #define USB_DMADAR			0x0004
1250c1c8ff3SYoshihiro Shimoda #define USB_DMATCR			0x0008
1260c1c8ff3SYoshihiro Shimoda #define USB_DMATCR_MASK			0x00ffffff
1270c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR			0x0014
1280c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR_FTE			(1 << 24)
1290c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR_NULLE		(1 << 16)
1300c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR_NULL		(1 << 12)
1310c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR_TS_8B		((0 << 7) | (0 << 6))
1320c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR_TS_16B		((0 << 7) | (1 << 6))
1330c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR_TS_32B		((1 << 7) | (0 << 6))
1340c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR_IE			(1 << 5)
1350c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR_SP			(1 << 2)
1360c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR_TE			(1 << 1)
1370c1c8ff3SYoshihiro Shimoda #define USB_DMACHCR_DE			(1 << 0)
1380c1c8ff3SYoshihiro Shimoda #define USB_DMATEND			0x0018
1390c1c8ff3SYoshihiro Shimoda 
1400c1c8ff3SYoshihiro Shimoda /* Hardcode the xfer_shift to 5 (32bytes) */
1410c1c8ff3SYoshihiro Shimoda #define USB_DMAC_XFER_SHIFT	5
1420c1c8ff3SYoshihiro Shimoda #define USB_DMAC_XFER_SIZE	(1 << USB_DMAC_XFER_SHIFT)
1430c1c8ff3SYoshihiro Shimoda #define USB_DMAC_CHCR_TS	USB_DMACHCR_TS_32B
1440c1c8ff3SYoshihiro Shimoda #define USB_DMAC_SLAVE_BUSWIDTH	DMA_SLAVE_BUSWIDTH_32_BYTES
1450c1c8ff3SYoshihiro Shimoda 
1460c1c8ff3SYoshihiro Shimoda /* for descriptors */
1470c1c8ff3SYoshihiro Shimoda #define USB_DMAC_INITIAL_NR_DESC	16
1480c1c8ff3SYoshihiro Shimoda #define USB_DMAC_INITIAL_NR_SG		8
1490c1c8ff3SYoshihiro Shimoda 
1500c1c8ff3SYoshihiro Shimoda /* -----------------------------------------------------------------------------
1510c1c8ff3SYoshihiro Shimoda  * Device access
1520c1c8ff3SYoshihiro Shimoda  */
1530c1c8ff3SYoshihiro Shimoda 
1540c1c8ff3SYoshihiro Shimoda static void usb_dmac_write(struct usb_dmac *dmac, u32 reg, u32 data)
1550c1c8ff3SYoshihiro Shimoda {
1560c1c8ff3SYoshihiro Shimoda 	writel(data, dmac->iomem + reg);
1570c1c8ff3SYoshihiro Shimoda }
1580c1c8ff3SYoshihiro Shimoda 
1590c1c8ff3SYoshihiro Shimoda static u32 usb_dmac_read(struct usb_dmac *dmac, u32 reg)
1600c1c8ff3SYoshihiro Shimoda {
1610c1c8ff3SYoshihiro Shimoda 	return readl(dmac->iomem + reg);
1620c1c8ff3SYoshihiro Shimoda }
1630c1c8ff3SYoshihiro Shimoda 
1640c1c8ff3SYoshihiro Shimoda static u32 usb_dmac_chan_read(struct usb_dmac_chan *chan, u32 reg)
1650c1c8ff3SYoshihiro Shimoda {
1660c1c8ff3SYoshihiro Shimoda 	return readl(chan->iomem + reg);
1670c1c8ff3SYoshihiro Shimoda }
1680c1c8ff3SYoshihiro Shimoda 
1690c1c8ff3SYoshihiro Shimoda static void usb_dmac_chan_write(struct usb_dmac_chan *chan, u32 reg, u32 data)
1700c1c8ff3SYoshihiro Shimoda {
1710c1c8ff3SYoshihiro Shimoda 	writel(data, chan->iomem + reg);
1720c1c8ff3SYoshihiro Shimoda }
1730c1c8ff3SYoshihiro Shimoda 
1740c1c8ff3SYoshihiro Shimoda /* -----------------------------------------------------------------------------
1750c1c8ff3SYoshihiro Shimoda  * Initialization and configuration
1760c1c8ff3SYoshihiro Shimoda  */
1770c1c8ff3SYoshihiro Shimoda 
1780c1c8ff3SYoshihiro Shimoda static bool usb_dmac_chan_is_busy(struct usb_dmac_chan *chan)
1790c1c8ff3SYoshihiro Shimoda {
1800c1c8ff3SYoshihiro Shimoda 	u32 chcr = usb_dmac_chan_read(chan, USB_DMACHCR);
1810c1c8ff3SYoshihiro Shimoda 
1820c1c8ff3SYoshihiro Shimoda 	return (chcr & (USB_DMACHCR_DE | USB_DMACHCR_TE)) == USB_DMACHCR_DE;
1830c1c8ff3SYoshihiro Shimoda }
1840c1c8ff3SYoshihiro Shimoda 
1850c1c8ff3SYoshihiro Shimoda static u32 usb_dmac_calc_tend(u32 size)
1860c1c8ff3SYoshihiro Shimoda {
1870c1c8ff3SYoshihiro Shimoda 	/*
1880c1c8ff3SYoshihiro Shimoda 	 * Please refer to the Figure "Example of Final Transaction Valid
1890c1c8ff3SYoshihiro Shimoda 	 * Data Transfer Enable (EDTEN) Setting" in the data sheet.
1900c1c8ff3SYoshihiro Shimoda 	 */
1910c1c8ff3SYoshihiro Shimoda 	return 0xffffffff << (32 - (size % USB_DMAC_XFER_SIZE ?	:
1920c1c8ff3SYoshihiro Shimoda 						USB_DMAC_XFER_SIZE));
1930c1c8ff3SYoshihiro Shimoda }
1940c1c8ff3SYoshihiro Shimoda 
1950c1c8ff3SYoshihiro Shimoda /* This function is already held by vc.lock */
1960c1c8ff3SYoshihiro Shimoda static void usb_dmac_chan_start_sg(struct usb_dmac_chan *chan,
1970c1c8ff3SYoshihiro Shimoda 				   unsigned int index)
1980c1c8ff3SYoshihiro Shimoda {
1990c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc = chan->desc;
2000c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_sg *sg = desc->sg + index;
2010c1c8ff3SYoshihiro Shimoda 	dma_addr_t src_addr = 0, dst_addr = 0;
2020c1c8ff3SYoshihiro Shimoda 
2030c1c8ff3SYoshihiro Shimoda 	WARN_ON_ONCE(usb_dmac_chan_is_busy(chan));
2040c1c8ff3SYoshihiro Shimoda 
2050c1c8ff3SYoshihiro Shimoda 	if (desc->direction == DMA_DEV_TO_MEM)
2060c1c8ff3SYoshihiro Shimoda 		dst_addr = sg->mem_addr;
2070c1c8ff3SYoshihiro Shimoda 	else
2080c1c8ff3SYoshihiro Shimoda 		src_addr = sg->mem_addr;
2090c1c8ff3SYoshihiro Shimoda 
2100c1c8ff3SYoshihiro Shimoda 	dev_dbg(chan->vc.chan.device->dev,
2110c1c8ff3SYoshihiro Shimoda 		"chan%u: queue sg %p: %u@%pad -> %pad\n",
2120c1c8ff3SYoshihiro Shimoda 		chan->index, sg, sg->size, &src_addr, &dst_addr);
2130c1c8ff3SYoshihiro Shimoda 
2140c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_write(chan, USB_DMASAR, src_addr & 0xffffffff);
2150c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_write(chan, USB_DMADAR, dst_addr & 0xffffffff);
2160c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_write(chan, USB_DMATCR,
2170c1c8ff3SYoshihiro Shimoda 			    DIV_ROUND_UP(sg->size, USB_DMAC_XFER_SIZE));
2180c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_write(chan, USB_DMATEND, usb_dmac_calc_tend(sg->size));
2190c1c8ff3SYoshihiro Shimoda 
2200c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_write(chan, USB_DMACHCR, USB_DMAC_CHCR_TS |
2210c1c8ff3SYoshihiro Shimoda 			USB_DMACHCR_NULLE | USB_DMACHCR_IE | USB_DMACHCR_DE);
2220c1c8ff3SYoshihiro Shimoda }
2230c1c8ff3SYoshihiro Shimoda 
2240c1c8ff3SYoshihiro Shimoda /* This function is already held by vc.lock */
2250c1c8ff3SYoshihiro Shimoda static void usb_dmac_chan_start_desc(struct usb_dmac_chan *chan)
2260c1c8ff3SYoshihiro Shimoda {
2270c1c8ff3SYoshihiro Shimoda 	struct virt_dma_desc *vd;
2280c1c8ff3SYoshihiro Shimoda 
2290c1c8ff3SYoshihiro Shimoda 	vd = vchan_next_desc(&chan->vc);
2300c1c8ff3SYoshihiro Shimoda 	if (!vd) {
2310c1c8ff3SYoshihiro Shimoda 		chan->desc = NULL;
2320c1c8ff3SYoshihiro Shimoda 		return;
2330c1c8ff3SYoshihiro Shimoda 	}
2340c1c8ff3SYoshihiro Shimoda 
2350c1c8ff3SYoshihiro Shimoda 	/*
2360c1c8ff3SYoshihiro Shimoda 	 * Remove this request from vc->desc_issued. Otherwise, this driver
2370c1c8ff3SYoshihiro Shimoda 	 * will get the previous value from vchan_next_desc() after a transfer
2380c1c8ff3SYoshihiro Shimoda 	 * was completed.
2390c1c8ff3SYoshihiro Shimoda 	 */
2400c1c8ff3SYoshihiro Shimoda 	list_del(&vd->node);
2410c1c8ff3SYoshihiro Shimoda 
2420c1c8ff3SYoshihiro Shimoda 	chan->desc = to_usb_dmac_desc(vd);
2430c1c8ff3SYoshihiro Shimoda 	chan->desc->sg_index = 0;
2440c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_start_sg(chan, 0);
2450c1c8ff3SYoshihiro Shimoda }
2460c1c8ff3SYoshihiro Shimoda 
2470c1c8ff3SYoshihiro Shimoda static int usb_dmac_init(struct usb_dmac *dmac)
2480c1c8ff3SYoshihiro Shimoda {
2490c1c8ff3SYoshihiro Shimoda 	u16 dmaor;
2500c1c8ff3SYoshihiro Shimoda 
2510c1c8ff3SYoshihiro Shimoda 	/* Clear all channels and enable the DMAC globally. */
2520c1c8ff3SYoshihiro Shimoda 	usb_dmac_write(dmac, USB_DMAOR, USB_DMAOR_DME);
2530c1c8ff3SYoshihiro Shimoda 
2540c1c8ff3SYoshihiro Shimoda 	dmaor = usb_dmac_read(dmac, USB_DMAOR);
2550c1c8ff3SYoshihiro Shimoda 	if ((dmaor & (USB_DMAOR_AE | USB_DMAOR_DME)) != USB_DMAOR_DME) {
2560c1c8ff3SYoshihiro Shimoda 		dev_warn(dmac->dev, "DMAOR initialization failed.\n");
2570c1c8ff3SYoshihiro Shimoda 		return -EIO;
2580c1c8ff3SYoshihiro Shimoda 	}
2590c1c8ff3SYoshihiro Shimoda 
2600c1c8ff3SYoshihiro Shimoda 	return 0;
2610c1c8ff3SYoshihiro Shimoda }
2620c1c8ff3SYoshihiro Shimoda 
2630c1c8ff3SYoshihiro Shimoda /* -----------------------------------------------------------------------------
2640c1c8ff3SYoshihiro Shimoda  * Descriptors allocation and free
2650c1c8ff3SYoshihiro Shimoda  */
2660c1c8ff3SYoshihiro Shimoda static int usb_dmac_desc_alloc(struct usb_dmac_chan *chan, unsigned int sg_len,
2670c1c8ff3SYoshihiro Shimoda 			       gfp_t gfp)
2680c1c8ff3SYoshihiro Shimoda {
2690c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc;
2700c1c8ff3SYoshihiro Shimoda 	unsigned long flags;
2710c1c8ff3SYoshihiro Shimoda 
2720c1c8ff3SYoshihiro Shimoda 	desc = kzalloc(sizeof(*desc) + sg_len * sizeof(desc->sg[0]), gfp);
2730c1c8ff3SYoshihiro Shimoda 	if (!desc)
2740c1c8ff3SYoshihiro Shimoda 		return -ENOMEM;
2750c1c8ff3SYoshihiro Shimoda 
2760c1c8ff3SYoshihiro Shimoda 	desc->sg_allocated_len = sg_len;
2770c1c8ff3SYoshihiro Shimoda 	INIT_LIST_HEAD(&desc->node);
2780c1c8ff3SYoshihiro Shimoda 
2790c1c8ff3SYoshihiro Shimoda 	spin_lock_irqsave(&chan->vc.lock, flags);
2800c1c8ff3SYoshihiro Shimoda 	list_add_tail(&desc->node, &chan->desc_freed);
2810c1c8ff3SYoshihiro Shimoda 	spin_unlock_irqrestore(&chan->vc.lock, flags);
2820c1c8ff3SYoshihiro Shimoda 
2830c1c8ff3SYoshihiro Shimoda 	return 0;
2840c1c8ff3SYoshihiro Shimoda }
2850c1c8ff3SYoshihiro Shimoda 
2860c1c8ff3SYoshihiro Shimoda static void usb_dmac_desc_free(struct usb_dmac_chan *chan)
2870c1c8ff3SYoshihiro Shimoda {
2880c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc;
2890c1c8ff3SYoshihiro Shimoda 	LIST_HEAD(list);
2900c1c8ff3SYoshihiro Shimoda 
2910c1c8ff3SYoshihiro Shimoda 	list_splice_init(&chan->desc_freed, &list);
2920c1c8ff3SYoshihiro Shimoda 	list_splice_init(&chan->desc_got, &list);
2930c1c8ff3SYoshihiro Shimoda 
2940c1c8ff3SYoshihiro Shimoda 	list_for_each_entry(desc, &list, node) {
2950c1c8ff3SYoshihiro Shimoda 		list_del(&desc->node);
2960c1c8ff3SYoshihiro Shimoda 		kfree(desc);
2970c1c8ff3SYoshihiro Shimoda 	}
2980c1c8ff3SYoshihiro Shimoda 	chan->descs_allocated = 0;
2990c1c8ff3SYoshihiro Shimoda }
3000c1c8ff3SYoshihiro Shimoda 
3010c1c8ff3SYoshihiro Shimoda static struct usb_dmac_desc *usb_dmac_desc_get(struct usb_dmac_chan *chan,
3020c1c8ff3SYoshihiro Shimoda 					       unsigned int sg_len, gfp_t gfp)
3030c1c8ff3SYoshihiro Shimoda {
3040c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc = NULL;
3050c1c8ff3SYoshihiro Shimoda 	unsigned long flags;
3060c1c8ff3SYoshihiro Shimoda 
3070c1c8ff3SYoshihiro Shimoda 	/* Get a freed descritpor */
3080c1c8ff3SYoshihiro Shimoda 	spin_lock_irqsave(&chan->vc.lock, flags);
3090c1c8ff3SYoshihiro Shimoda 	list_for_each_entry(desc, &chan->desc_freed, node) {
3100c1c8ff3SYoshihiro Shimoda 		if (sg_len <= desc->sg_allocated_len) {
3110c1c8ff3SYoshihiro Shimoda 			list_move_tail(&desc->node, &chan->desc_got);
3120c1c8ff3SYoshihiro Shimoda 			spin_unlock_irqrestore(&chan->vc.lock, flags);
3130c1c8ff3SYoshihiro Shimoda 			return desc;
3140c1c8ff3SYoshihiro Shimoda 		}
3150c1c8ff3SYoshihiro Shimoda 	}
3160c1c8ff3SYoshihiro Shimoda 	spin_unlock_irqrestore(&chan->vc.lock, flags);
3170c1c8ff3SYoshihiro Shimoda 
3180c1c8ff3SYoshihiro Shimoda 	/* Allocate a new descriptor */
3190c1c8ff3SYoshihiro Shimoda 	if (!usb_dmac_desc_alloc(chan, sg_len, gfp)) {
3200c1c8ff3SYoshihiro Shimoda 		/* If allocated the desc, it was added to tail of the list */
3210c1c8ff3SYoshihiro Shimoda 		spin_lock_irqsave(&chan->vc.lock, flags);
3220c1c8ff3SYoshihiro Shimoda 		desc = list_last_entry(&chan->desc_freed, struct usb_dmac_desc,
3230c1c8ff3SYoshihiro Shimoda 				       node);
3240c1c8ff3SYoshihiro Shimoda 		list_move_tail(&desc->node, &chan->desc_got);
3250c1c8ff3SYoshihiro Shimoda 		spin_unlock_irqrestore(&chan->vc.lock, flags);
3260c1c8ff3SYoshihiro Shimoda 		return desc;
3270c1c8ff3SYoshihiro Shimoda 	}
3280c1c8ff3SYoshihiro Shimoda 
3290c1c8ff3SYoshihiro Shimoda 	return NULL;
3300c1c8ff3SYoshihiro Shimoda }
3310c1c8ff3SYoshihiro Shimoda 
3320c1c8ff3SYoshihiro Shimoda static void usb_dmac_desc_put(struct usb_dmac_chan *chan,
3330c1c8ff3SYoshihiro Shimoda 			      struct usb_dmac_desc *desc)
3340c1c8ff3SYoshihiro Shimoda {
3350c1c8ff3SYoshihiro Shimoda 	unsigned long flags;
3360c1c8ff3SYoshihiro Shimoda 
3370c1c8ff3SYoshihiro Shimoda 	spin_lock_irqsave(&chan->vc.lock, flags);
3380c1c8ff3SYoshihiro Shimoda 	list_move_tail(&desc->node, &chan->desc_freed);
3390c1c8ff3SYoshihiro Shimoda 	spin_unlock_irqrestore(&chan->vc.lock, flags);
3400c1c8ff3SYoshihiro Shimoda }
3410c1c8ff3SYoshihiro Shimoda 
3420c1c8ff3SYoshihiro Shimoda /* -----------------------------------------------------------------------------
3430c1c8ff3SYoshihiro Shimoda  * Stop and reset
3440c1c8ff3SYoshihiro Shimoda  */
3450c1c8ff3SYoshihiro Shimoda 
3460c1c8ff3SYoshihiro Shimoda static void usb_dmac_soft_reset(struct usb_dmac_chan *uchan)
3470c1c8ff3SYoshihiro Shimoda {
3480c1c8ff3SYoshihiro Shimoda 	struct dma_chan *chan = &uchan->vc.chan;
3490c1c8ff3SYoshihiro Shimoda 	struct usb_dmac *dmac = to_usb_dmac(chan->device);
3500c1c8ff3SYoshihiro Shimoda 	int i;
3510c1c8ff3SYoshihiro Shimoda 
3520c1c8ff3SYoshihiro Shimoda 	/* Don't issue soft reset if any one of channels is busy */
3530c1c8ff3SYoshihiro Shimoda 	for (i = 0; i < dmac->n_channels; ++i) {
3540c1c8ff3SYoshihiro Shimoda 		if (usb_dmac_chan_is_busy(uchan))
3550c1c8ff3SYoshihiro Shimoda 			return;
3560c1c8ff3SYoshihiro Shimoda 	}
3570c1c8ff3SYoshihiro Shimoda 
3580c1c8ff3SYoshihiro Shimoda 	usb_dmac_write(dmac, USB_DMAOR, 0);
3590c1c8ff3SYoshihiro Shimoda 	usb_dmac_write(dmac, USB_DMASWR, USB_DMASWR_SWR);
3600c1c8ff3SYoshihiro Shimoda 	udelay(100);
3610c1c8ff3SYoshihiro Shimoda 	usb_dmac_write(dmac, USB_DMASWR, 0);
3620c1c8ff3SYoshihiro Shimoda 	usb_dmac_write(dmac, USB_DMAOR, 1);
3630c1c8ff3SYoshihiro Shimoda }
3640c1c8ff3SYoshihiro Shimoda 
3650c1c8ff3SYoshihiro Shimoda static void usb_dmac_chan_halt(struct usb_dmac_chan *chan)
3660c1c8ff3SYoshihiro Shimoda {
3670c1c8ff3SYoshihiro Shimoda 	u32 chcr = usb_dmac_chan_read(chan, USB_DMACHCR);
3680c1c8ff3SYoshihiro Shimoda 
3690c1c8ff3SYoshihiro Shimoda 	chcr &= ~(USB_DMACHCR_IE | USB_DMACHCR_TE | USB_DMACHCR_DE);
3700c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_write(chan, USB_DMACHCR, chcr);
3710c1c8ff3SYoshihiro Shimoda 
3720c1c8ff3SYoshihiro Shimoda 	usb_dmac_soft_reset(chan);
3730c1c8ff3SYoshihiro Shimoda }
3740c1c8ff3SYoshihiro Shimoda 
3750c1c8ff3SYoshihiro Shimoda static void usb_dmac_stop(struct usb_dmac *dmac)
3760c1c8ff3SYoshihiro Shimoda {
3770c1c8ff3SYoshihiro Shimoda 	usb_dmac_write(dmac, USB_DMAOR, 0);
3780c1c8ff3SYoshihiro Shimoda }
3790c1c8ff3SYoshihiro Shimoda 
3800c1c8ff3SYoshihiro Shimoda /* -----------------------------------------------------------------------------
3810c1c8ff3SYoshihiro Shimoda  * DMA engine operations
3820c1c8ff3SYoshihiro Shimoda  */
3830c1c8ff3SYoshihiro Shimoda 
3840c1c8ff3SYoshihiro Shimoda static int usb_dmac_alloc_chan_resources(struct dma_chan *chan)
3850c1c8ff3SYoshihiro Shimoda {
3860c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
3870c1c8ff3SYoshihiro Shimoda 	int ret;
3880c1c8ff3SYoshihiro Shimoda 
3890c1c8ff3SYoshihiro Shimoda 	while (uchan->descs_allocated < USB_DMAC_INITIAL_NR_DESC) {
3900c1c8ff3SYoshihiro Shimoda 		ret = usb_dmac_desc_alloc(uchan, USB_DMAC_INITIAL_NR_SG,
3910c1c8ff3SYoshihiro Shimoda 					  GFP_KERNEL);
3920c1c8ff3SYoshihiro Shimoda 		if (ret < 0) {
3930c1c8ff3SYoshihiro Shimoda 			usb_dmac_desc_free(uchan);
3940c1c8ff3SYoshihiro Shimoda 			return ret;
3950c1c8ff3SYoshihiro Shimoda 		}
3960c1c8ff3SYoshihiro Shimoda 		uchan->descs_allocated++;
3970c1c8ff3SYoshihiro Shimoda 	}
3980c1c8ff3SYoshihiro Shimoda 
3990c1c8ff3SYoshihiro Shimoda 	return pm_runtime_get_sync(chan->device->dev);
4000c1c8ff3SYoshihiro Shimoda }
4010c1c8ff3SYoshihiro Shimoda 
4020c1c8ff3SYoshihiro Shimoda static void usb_dmac_free_chan_resources(struct dma_chan *chan)
4030c1c8ff3SYoshihiro Shimoda {
4040c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
4050c1c8ff3SYoshihiro Shimoda 	unsigned long flags;
4060c1c8ff3SYoshihiro Shimoda 
4070c1c8ff3SYoshihiro Shimoda 	/* Protect against ISR */
4080c1c8ff3SYoshihiro Shimoda 	spin_lock_irqsave(&uchan->vc.lock, flags);
4090c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_halt(uchan);
4100c1c8ff3SYoshihiro Shimoda 	spin_unlock_irqrestore(&uchan->vc.lock, flags);
4110c1c8ff3SYoshihiro Shimoda 
4120c1c8ff3SYoshihiro Shimoda 	usb_dmac_desc_free(uchan);
4130c1c8ff3SYoshihiro Shimoda 	vchan_free_chan_resources(&uchan->vc);
4140c1c8ff3SYoshihiro Shimoda 
4150c1c8ff3SYoshihiro Shimoda 	pm_runtime_put(chan->device->dev);
4160c1c8ff3SYoshihiro Shimoda }
4170c1c8ff3SYoshihiro Shimoda 
4180c1c8ff3SYoshihiro Shimoda static struct dma_async_tx_descriptor *
4190c1c8ff3SYoshihiro Shimoda usb_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
4200c1c8ff3SYoshihiro Shimoda 		       unsigned int sg_len, enum dma_transfer_direction dir,
4210c1c8ff3SYoshihiro Shimoda 		       unsigned long dma_flags, void *context)
4220c1c8ff3SYoshihiro Shimoda {
4230c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
4240c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc;
4250c1c8ff3SYoshihiro Shimoda 	struct scatterlist *sg;
4260c1c8ff3SYoshihiro Shimoda 	int i;
4270c1c8ff3SYoshihiro Shimoda 
4280c1c8ff3SYoshihiro Shimoda 	if (!sg_len) {
4290c1c8ff3SYoshihiro Shimoda 		dev_warn(chan->device->dev,
4300c1c8ff3SYoshihiro Shimoda 			 "%s: bad parameter: len=%d\n", __func__, sg_len);
4310c1c8ff3SYoshihiro Shimoda 		return NULL;
4320c1c8ff3SYoshihiro Shimoda 	}
4330c1c8ff3SYoshihiro Shimoda 
4340c1c8ff3SYoshihiro Shimoda 	desc = usb_dmac_desc_get(uchan, sg_len, GFP_NOWAIT);
4350c1c8ff3SYoshihiro Shimoda 	if (!desc)
4360c1c8ff3SYoshihiro Shimoda 		return NULL;
4370c1c8ff3SYoshihiro Shimoda 
4380c1c8ff3SYoshihiro Shimoda 	desc->direction = dir;
4390c1c8ff3SYoshihiro Shimoda 	desc->sg_len = sg_len;
4400c1c8ff3SYoshihiro Shimoda 	for_each_sg(sgl, sg, sg_len, i) {
4410c1c8ff3SYoshihiro Shimoda 		desc->sg[i].mem_addr = sg_dma_address(sg);
4420c1c8ff3SYoshihiro Shimoda 		desc->sg[i].size = sg_dma_len(sg);
4430c1c8ff3SYoshihiro Shimoda 	}
4440c1c8ff3SYoshihiro Shimoda 
4450c1c8ff3SYoshihiro Shimoda 	return vchan_tx_prep(&uchan->vc, &desc->vd, dma_flags);
4460c1c8ff3SYoshihiro Shimoda }
4470c1c8ff3SYoshihiro Shimoda 
4480c1c8ff3SYoshihiro Shimoda static int usb_dmac_chan_terminate_all(struct dma_chan *chan)
4490c1c8ff3SYoshihiro Shimoda {
4500c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
4510c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc;
4520c1c8ff3SYoshihiro Shimoda 	unsigned long flags;
4530c1c8ff3SYoshihiro Shimoda 	LIST_HEAD(head);
4540c1c8ff3SYoshihiro Shimoda 	LIST_HEAD(list);
4550c1c8ff3SYoshihiro Shimoda 
4560c1c8ff3SYoshihiro Shimoda 	spin_lock_irqsave(&uchan->vc.lock, flags);
4570c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_halt(uchan);
4580c1c8ff3SYoshihiro Shimoda 	vchan_get_all_descriptors(&uchan->vc, &head);
4590c1c8ff3SYoshihiro Shimoda 	if (uchan->desc)
4600c1c8ff3SYoshihiro Shimoda 		uchan->desc = NULL;
4610c1c8ff3SYoshihiro Shimoda 	list_splice_init(&uchan->desc_got, &list);
4620c1c8ff3SYoshihiro Shimoda 	list_for_each_entry(desc, &list, node)
4630c1c8ff3SYoshihiro Shimoda 		list_move_tail(&desc->node, &uchan->desc_freed);
4640c1c8ff3SYoshihiro Shimoda 	spin_unlock_irqrestore(&uchan->vc.lock, flags);
4650c1c8ff3SYoshihiro Shimoda 	vchan_dma_desc_free_list(&uchan->vc, &head);
4660c1c8ff3SYoshihiro Shimoda 
4670c1c8ff3SYoshihiro Shimoda 	return 0;
4680c1c8ff3SYoshihiro Shimoda }
4690c1c8ff3SYoshihiro Shimoda 
4700c1c8ff3SYoshihiro Shimoda static unsigned int usb_dmac_get_current_residue(struct usb_dmac_chan *chan,
4710c1c8ff3SYoshihiro Shimoda 						 struct usb_dmac_desc *desc,
4720c1c8ff3SYoshihiro Shimoda 						 int sg_index)
4730c1c8ff3SYoshihiro Shimoda {
4740c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_sg *sg = desc->sg + sg_index;
4750c1c8ff3SYoshihiro Shimoda 	u32 mem_addr = sg->mem_addr & 0xffffffff;
4760c1c8ff3SYoshihiro Shimoda 	unsigned int residue = sg->size;
4770c1c8ff3SYoshihiro Shimoda 
4780c1c8ff3SYoshihiro Shimoda 	/*
4790c1c8ff3SYoshihiro Shimoda 	 * We cannot use USB_DMATCR to calculate residue because USB_DMATCR
4800c1c8ff3SYoshihiro Shimoda 	 * has unsuited value to calculate.
4810c1c8ff3SYoshihiro Shimoda 	 */
4820c1c8ff3SYoshihiro Shimoda 	if (desc->direction == DMA_DEV_TO_MEM)
4830c1c8ff3SYoshihiro Shimoda 		residue -= usb_dmac_chan_read(chan, USB_DMADAR) - mem_addr;
4840c1c8ff3SYoshihiro Shimoda 	else
4850c1c8ff3SYoshihiro Shimoda 		residue -= usb_dmac_chan_read(chan, USB_DMASAR) - mem_addr;
4860c1c8ff3SYoshihiro Shimoda 
4870c1c8ff3SYoshihiro Shimoda 	return residue;
4880c1c8ff3SYoshihiro Shimoda }
4890c1c8ff3SYoshihiro Shimoda 
4900c1c8ff3SYoshihiro Shimoda static u32 usb_dmac_chan_get_residue_if_complete(struct usb_dmac_chan *chan,
4910c1c8ff3SYoshihiro Shimoda 						 dma_cookie_t cookie)
4920c1c8ff3SYoshihiro Shimoda {
4930c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc;
4940c1c8ff3SYoshihiro Shimoda 	u32 residue = 0;
4950c1c8ff3SYoshihiro Shimoda 
4960c1c8ff3SYoshihiro Shimoda 	list_for_each_entry_reverse(desc, &chan->desc_freed, node) {
4970c1c8ff3SYoshihiro Shimoda 		if (desc->done_cookie == cookie) {
4980c1c8ff3SYoshihiro Shimoda 			residue = desc->residue;
4990c1c8ff3SYoshihiro Shimoda 			break;
5000c1c8ff3SYoshihiro Shimoda 		}
5010c1c8ff3SYoshihiro Shimoda 	}
5020c1c8ff3SYoshihiro Shimoda 
5030c1c8ff3SYoshihiro Shimoda 	return residue;
5040c1c8ff3SYoshihiro Shimoda }
5050c1c8ff3SYoshihiro Shimoda 
5060c1c8ff3SYoshihiro Shimoda static u32 usb_dmac_chan_get_residue(struct usb_dmac_chan *chan,
5070c1c8ff3SYoshihiro Shimoda 				     dma_cookie_t cookie)
5080c1c8ff3SYoshihiro Shimoda {
5090c1c8ff3SYoshihiro Shimoda 	u32 residue = 0;
5100c1c8ff3SYoshihiro Shimoda 	struct virt_dma_desc *vd;
5110c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc = chan->desc;
5120c1c8ff3SYoshihiro Shimoda 	int i;
5130c1c8ff3SYoshihiro Shimoda 
5140c1c8ff3SYoshihiro Shimoda 	if (!desc) {
5150c1c8ff3SYoshihiro Shimoda 		vd = vchan_find_desc(&chan->vc, cookie);
5160c1c8ff3SYoshihiro Shimoda 		if (!vd)
5170c1c8ff3SYoshihiro Shimoda 			return 0;
5180c1c8ff3SYoshihiro Shimoda 		desc = to_usb_dmac_desc(vd);
5190c1c8ff3SYoshihiro Shimoda 	}
5200c1c8ff3SYoshihiro Shimoda 
5210c1c8ff3SYoshihiro Shimoda 	/* Compute the size of all usb_dmac_sg still to be transferred */
5220c1c8ff3SYoshihiro Shimoda 	for (i = desc->sg_index + 1; i < desc->sg_len; i++)
5230c1c8ff3SYoshihiro Shimoda 		residue += desc->sg[i].size;
5240c1c8ff3SYoshihiro Shimoda 
5250c1c8ff3SYoshihiro Shimoda 	/* Add the residue for the current sg */
5260c1c8ff3SYoshihiro Shimoda 	residue += usb_dmac_get_current_residue(chan, desc, desc->sg_index);
5270c1c8ff3SYoshihiro Shimoda 
5280c1c8ff3SYoshihiro Shimoda 	return residue;
5290c1c8ff3SYoshihiro Shimoda }
5300c1c8ff3SYoshihiro Shimoda 
5310c1c8ff3SYoshihiro Shimoda static enum dma_status usb_dmac_tx_status(struct dma_chan *chan,
5320c1c8ff3SYoshihiro Shimoda 					  dma_cookie_t cookie,
5330c1c8ff3SYoshihiro Shimoda 					  struct dma_tx_state *txstate)
5340c1c8ff3SYoshihiro Shimoda {
5350c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
5360c1c8ff3SYoshihiro Shimoda 	enum dma_status status;
5370c1c8ff3SYoshihiro Shimoda 	unsigned int residue = 0;
5380c1c8ff3SYoshihiro Shimoda 	unsigned long flags;
5390c1c8ff3SYoshihiro Shimoda 
5400c1c8ff3SYoshihiro Shimoda 	status = dma_cookie_status(chan, cookie, txstate);
5410c1c8ff3SYoshihiro Shimoda 	/* a client driver will get residue after DMA_COMPLETE */
5420c1c8ff3SYoshihiro Shimoda 	if (!txstate)
5430c1c8ff3SYoshihiro Shimoda 		return status;
5440c1c8ff3SYoshihiro Shimoda 
5450c1c8ff3SYoshihiro Shimoda 	spin_lock_irqsave(&uchan->vc.lock, flags);
5460c1c8ff3SYoshihiro Shimoda 	if (status == DMA_COMPLETE)
5470c1c8ff3SYoshihiro Shimoda 		residue = usb_dmac_chan_get_residue_if_complete(uchan, cookie);
5480c1c8ff3SYoshihiro Shimoda 	else
5490c1c8ff3SYoshihiro Shimoda 		residue = usb_dmac_chan_get_residue(uchan, cookie);
5500c1c8ff3SYoshihiro Shimoda 	spin_unlock_irqrestore(&uchan->vc.lock, flags);
5510c1c8ff3SYoshihiro Shimoda 
5520c1c8ff3SYoshihiro Shimoda 	dma_set_residue(txstate, residue);
5530c1c8ff3SYoshihiro Shimoda 
5540c1c8ff3SYoshihiro Shimoda 	return status;
5550c1c8ff3SYoshihiro Shimoda }
5560c1c8ff3SYoshihiro Shimoda 
5570c1c8ff3SYoshihiro Shimoda static void usb_dmac_issue_pending(struct dma_chan *chan)
5580c1c8ff3SYoshihiro Shimoda {
5590c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
5600c1c8ff3SYoshihiro Shimoda 	unsigned long flags;
5610c1c8ff3SYoshihiro Shimoda 
5620c1c8ff3SYoshihiro Shimoda 	spin_lock_irqsave(&uchan->vc.lock, flags);
5630c1c8ff3SYoshihiro Shimoda 	if (vchan_issue_pending(&uchan->vc) && !uchan->desc)
5640c1c8ff3SYoshihiro Shimoda 		usb_dmac_chan_start_desc(uchan);
5650c1c8ff3SYoshihiro Shimoda 	spin_unlock_irqrestore(&uchan->vc.lock, flags);
5660c1c8ff3SYoshihiro Shimoda }
5670c1c8ff3SYoshihiro Shimoda 
5680c1c8ff3SYoshihiro Shimoda static void usb_dmac_virt_desc_free(struct virt_dma_desc *vd)
5690c1c8ff3SYoshihiro Shimoda {
5700c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc = to_usb_dmac_desc(vd);
5710c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *chan = to_usb_dmac_chan(vd->tx.chan);
5720c1c8ff3SYoshihiro Shimoda 
5730c1c8ff3SYoshihiro Shimoda 	usb_dmac_desc_put(chan, desc);
5740c1c8ff3SYoshihiro Shimoda }
5750c1c8ff3SYoshihiro Shimoda 
5760c1c8ff3SYoshihiro Shimoda /* -----------------------------------------------------------------------------
5770c1c8ff3SYoshihiro Shimoda  * IRQ handling
5780c1c8ff3SYoshihiro Shimoda  */
5790c1c8ff3SYoshihiro Shimoda 
5800c1c8ff3SYoshihiro Shimoda static void usb_dmac_isr_transfer_end(struct usb_dmac_chan *chan)
5810c1c8ff3SYoshihiro Shimoda {
5820c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_desc *desc = chan->desc;
5830c1c8ff3SYoshihiro Shimoda 
5840c1c8ff3SYoshihiro Shimoda 	BUG_ON(!desc);
5850c1c8ff3SYoshihiro Shimoda 
5860c1c8ff3SYoshihiro Shimoda 	if (++desc->sg_index < desc->sg_len) {
5870c1c8ff3SYoshihiro Shimoda 		usb_dmac_chan_start_sg(chan, desc->sg_index);
5880c1c8ff3SYoshihiro Shimoda 	} else {
5890c1c8ff3SYoshihiro Shimoda 		desc->residue = usb_dmac_get_current_residue(chan, desc,
5900c1c8ff3SYoshihiro Shimoda 							desc->sg_index - 1);
5910c1c8ff3SYoshihiro Shimoda 		desc->done_cookie = desc->vd.tx.cookie;
5920c1c8ff3SYoshihiro Shimoda 		vchan_cookie_complete(&desc->vd);
5930c1c8ff3SYoshihiro Shimoda 
5940c1c8ff3SYoshihiro Shimoda 		/* Restart the next transfer if this driver has a next desc */
5950c1c8ff3SYoshihiro Shimoda 		usb_dmac_chan_start_desc(chan);
5960c1c8ff3SYoshihiro Shimoda 	}
5970c1c8ff3SYoshihiro Shimoda }
5980c1c8ff3SYoshihiro Shimoda 
5990c1c8ff3SYoshihiro Shimoda static irqreturn_t usb_dmac_isr_channel(int irq, void *dev)
6000c1c8ff3SYoshihiro Shimoda {
6010c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *chan = dev;
6020c1c8ff3SYoshihiro Shimoda 	irqreturn_t ret = IRQ_NONE;
6030c1c8ff3SYoshihiro Shimoda 	u32 mask = USB_DMACHCR_TE;
6040c1c8ff3SYoshihiro Shimoda 	u32 check_bits = USB_DMACHCR_TE | USB_DMACHCR_SP;
6050c1c8ff3SYoshihiro Shimoda 	u32 chcr;
6060c1c8ff3SYoshihiro Shimoda 
6070c1c8ff3SYoshihiro Shimoda 	spin_lock(&chan->vc.lock);
6080c1c8ff3SYoshihiro Shimoda 
6090c1c8ff3SYoshihiro Shimoda 	chcr = usb_dmac_chan_read(chan, USB_DMACHCR);
6100c1c8ff3SYoshihiro Shimoda 	if (chcr & check_bits)
6110c1c8ff3SYoshihiro Shimoda 		mask |= USB_DMACHCR_DE | check_bits;
6120c1c8ff3SYoshihiro Shimoda 	if (chcr & USB_DMACHCR_NULL) {
6130c1c8ff3SYoshihiro Shimoda 		/* An interruption of TE will happen after we set FTE */
6140c1c8ff3SYoshihiro Shimoda 		mask |= USB_DMACHCR_NULL;
6150c1c8ff3SYoshihiro Shimoda 		chcr |= USB_DMACHCR_FTE;
6160c1c8ff3SYoshihiro Shimoda 		ret |= IRQ_HANDLED;
6170c1c8ff3SYoshihiro Shimoda 	}
6180c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_write(chan, USB_DMACHCR, chcr & ~mask);
6190c1c8ff3SYoshihiro Shimoda 
6200c1c8ff3SYoshihiro Shimoda 	if (chcr & check_bits) {
6210c1c8ff3SYoshihiro Shimoda 		usb_dmac_isr_transfer_end(chan);
6220c1c8ff3SYoshihiro Shimoda 		ret |= IRQ_HANDLED;
6230c1c8ff3SYoshihiro Shimoda 	}
6240c1c8ff3SYoshihiro Shimoda 
6250c1c8ff3SYoshihiro Shimoda 	spin_unlock(&chan->vc.lock);
6260c1c8ff3SYoshihiro Shimoda 
6270c1c8ff3SYoshihiro Shimoda 	return ret;
6280c1c8ff3SYoshihiro Shimoda }
6290c1c8ff3SYoshihiro Shimoda 
6300c1c8ff3SYoshihiro Shimoda /* -----------------------------------------------------------------------------
6310c1c8ff3SYoshihiro Shimoda  * OF xlate and channel filter
6320c1c8ff3SYoshihiro Shimoda  */
6330c1c8ff3SYoshihiro Shimoda 
6340c1c8ff3SYoshihiro Shimoda static bool usb_dmac_chan_filter(struct dma_chan *chan, void *arg)
6350c1c8ff3SYoshihiro Shimoda {
6360c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
6370c1c8ff3SYoshihiro Shimoda 	struct of_phandle_args *dma_spec = arg;
6380c1c8ff3SYoshihiro Shimoda 
6390c1c8ff3SYoshihiro Shimoda 	if (dma_spec->np != chan->device->dev->of_node)
6400c1c8ff3SYoshihiro Shimoda 		return false;
6410c1c8ff3SYoshihiro Shimoda 
6420c1c8ff3SYoshihiro Shimoda 	/* USB-DMAC should be used with fixed usb controller's FIFO */
6430c1c8ff3SYoshihiro Shimoda 	if (uchan->index != dma_spec->args[0])
6440c1c8ff3SYoshihiro Shimoda 		return false;
6450c1c8ff3SYoshihiro Shimoda 
6460c1c8ff3SYoshihiro Shimoda 	return true;
6470c1c8ff3SYoshihiro Shimoda }
6480c1c8ff3SYoshihiro Shimoda 
6490c1c8ff3SYoshihiro Shimoda static struct dma_chan *usb_dmac_of_xlate(struct of_phandle_args *dma_spec,
6500c1c8ff3SYoshihiro Shimoda 					  struct of_dma *ofdma)
6510c1c8ff3SYoshihiro Shimoda {
6520c1c8ff3SYoshihiro Shimoda 	struct usb_dmac_chan *uchan;
6530c1c8ff3SYoshihiro Shimoda 	struct dma_chan *chan;
6540c1c8ff3SYoshihiro Shimoda 	dma_cap_mask_t mask;
6550c1c8ff3SYoshihiro Shimoda 
6560c1c8ff3SYoshihiro Shimoda 	if (dma_spec->args_count != 1)
6570c1c8ff3SYoshihiro Shimoda 		return NULL;
6580c1c8ff3SYoshihiro Shimoda 
6590c1c8ff3SYoshihiro Shimoda 	/* Only slave DMA channels can be allocated via DT */
6600c1c8ff3SYoshihiro Shimoda 	dma_cap_zero(mask);
6610c1c8ff3SYoshihiro Shimoda 	dma_cap_set(DMA_SLAVE, mask);
6620c1c8ff3SYoshihiro Shimoda 
6630c1c8ff3SYoshihiro Shimoda 	chan = dma_request_channel(mask, usb_dmac_chan_filter, dma_spec);
6640c1c8ff3SYoshihiro Shimoda 	if (!chan)
6650c1c8ff3SYoshihiro Shimoda 		return NULL;
6660c1c8ff3SYoshihiro Shimoda 
6670c1c8ff3SYoshihiro Shimoda 	uchan = to_usb_dmac_chan(chan);
6680c1c8ff3SYoshihiro Shimoda 
6690c1c8ff3SYoshihiro Shimoda 	return chan;
6700c1c8ff3SYoshihiro Shimoda }
6710c1c8ff3SYoshihiro Shimoda 
6720c1c8ff3SYoshihiro Shimoda /* -----------------------------------------------------------------------------
6730c1c8ff3SYoshihiro Shimoda  * Power management
6740c1c8ff3SYoshihiro Shimoda  */
6750c1c8ff3SYoshihiro Shimoda 
6760c1c8ff3SYoshihiro Shimoda static int usb_dmac_runtime_suspend(struct device *dev)
6770c1c8ff3SYoshihiro Shimoda {
6780c1c8ff3SYoshihiro Shimoda 	struct usb_dmac *dmac = dev_get_drvdata(dev);
6790c1c8ff3SYoshihiro Shimoda 	int i;
6800c1c8ff3SYoshihiro Shimoda 
6810c1c8ff3SYoshihiro Shimoda 	for (i = 0; i < dmac->n_channels; ++i)
6820c1c8ff3SYoshihiro Shimoda 		usb_dmac_chan_halt(&dmac->channels[i]);
6830c1c8ff3SYoshihiro Shimoda 
6840c1c8ff3SYoshihiro Shimoda 	return 0;
6850c1c8ff3SYoshihiro Shimoda }
6860c1c8ff3SYoshihiro Shimoda 
6870c1c8ff3SYoshihiro Shimoda static int usb_dmac_runtime_resume(struct device *dev)
6880c1c8ff3SYoshihiro Shimoda {
6890c1c8ff3SYoshihiro Shimoda 	struct usb_dmac *dmac = dev_get_drvdata(dev);
6900c1c8ff3SYoshihiro Shimoda 
6910c1c8ff3SYoshihiro Shimoda 	return usb_dmac_init(dmac);
6920c1c8ff3SYoshihiro Shimoda }
6930c1c8ff3SYoshihiro Shimoda 
6940c1c8ff3SYoshihiro Shimoda static const struct dev_pm_ops usb_dmac_pm = {
6950c1c8ff3SYoshihiro Shimoda 	SET_RUNTIME_PM_OPS(usb_dmac_runtime_suspend, usb_dmac_runtime_resume,
6960c1c8ff3SYoshihiro Shimoda 			   NULL)
6970c1c8ff3SYoshihiro Shimoda };
6980c1c8ff3SYoshihiro Shimoda 
6990c1c8ff3SYoshihiro Shimoda /* -----------------------------------------------------------------------------
7000c1c8ff3SYoshihiro Shimoda  * Probe and remove
7010c1c8ff3SYoshihiro Shimoda  */
7020c1c8ff3SYoshihiro Shimoda 
7030c1c8ff3SYoshihiro Shimoda static int usb_dmac_chan_probe(struct usb_dmac *dmac,
7040c1c8ff3SYoshihiro Shimoda 			       struct usb_dmac_chan *uchan,
7050c1c8ff3SYoshihiro Shimoda 			       unsigned int index)
7060c1c8ff3SYoshihiro Shimoda {
7070c1c8ff3SYoshihiro Shimoda 	struct platform_device *pdev = to_platform_device(dmac->dev);
7080c1c8ff3SYoshihiro Shimoda 	char pdev_irqname[5];
7090c1c8ff3SYoshihiro Shimoda 	char *irqname;
7100c1c8ff3SYoshihiro Shimoda 	int ret;
7110c1c8ff3SYoshihiro Shimoda 
7120c1c8ff3SYoshihiro Shimoda 	uchan->index = index;
7130c1c8ff3SYoshihiro Shimoda 	uchan->iomem = dmac->iomem + USB_DMAC_CHAN_OFFSET(index);
7140c1c8ff3SYoshihiro Shimoda 
7150c1c8ff3SYoshihiro Shimoda 	/* Request the channel interrupt. */
7160c1c8ff3SYoshihiro Shimoda 	sprintf(pdev_irqname, "ch%u", index);
7170c1c8ff3SYoshihiro Shimoda 	uchan->irq = platform_get_irq_byname(pdev, pdev_irqname);
7180c1c8ff3SYoshihiro Shimoda 	if (uchan->irq < 0) {
7190c1c8ff3SYoshihiro Shimoda 		dev_err(dmac->dev, "no IRQ specified for channel %u\n", index);
7200c1c8ff3SYoshihiro Shimoda 		return -ENODEV;
7210c1c8ff3SYoshihiro Shimoda 	}
7220c1c8ff3SYoshihiro Shimoda 
7230c1c8ff3SYoshihiro Shimoda 	irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
7240c1c8ff3SYoshihiro Shimoda 				 dev_name(dmac->dev), index);
7250c1c8ff3SYoshihiro Shimoda 	if (!irqname)
7260c1c8ff3SYoshihiro Shimoda 		return -ENOMEM;
7270c1c8ff3SYoshihiro Shimoda 
7280c1c8ff3SYoshihiro Shimoda 	ret = devm_request_irq(dmac->dev, uchan->irq, usb_dmac_isr_channel,
7290c1c8ff3SYoshihiro Shimoda 			       IRQF_SHARED, irqname, uchan);
7300c1c8ff3SYoshihiro Shimoda 	if (ret) {
7310c1c8ff3SYoshihiro Shimoda 		dev_err(dmac->dev, "failed to request IRQ %u (%d)\n",
7320c1c8ff3SYoshihiro Shimoda 			uchan->irq, ret);
7330c1c8ff3SYoshihiro Shimoda 		return ret;
7340c1c8ff3SYoshihiro Shimoda 	}
7350c1c8ff3SYoshihiro Shimoda 
7360c1c8ff3SYoshihiro Shimoda 	uchan->vc.desc_free = usb_dmac_virt_desc_free;
7370c1c8ff3SYoshihiro Shimoda 	vchan_init(&uchan->vc, &dmac->engine);
7380c1c8ff3SYoshihiro Shimoda 	INIT_LIST_HEAD(&uchan->desc_freed);
7390c1c8ff3SYoshihiro Shimoda 	INIT_LIST_HEAD(&uchan->desc_got);
7400c1c8ff3SYoshihiro Shimoda 
7410c1c8ff3SYoshihiro Shimoda 	return 0;
7420c1c8ff3SYoshihiro Shimoda }
7430c1c8ff3SYoshihiro Shimoda 
7440c1c8ff3SYoshihiro Shimoda static int usb_dmac_parse_of(struct device *dev, struct usb_dmac *dmac)
7450c1c8ff3SYoshihiro Shimoda {
7460c1c8ff3SYoshihiro Shimoda 	struct device_node *np = dev->of_node;
7470c1c8ff3SYoshihiro Shimoda 	int ret;
7480c1c8ff3SYoshihiro Shimoda 
7490c1c8ff3SYoshihiro Shimoda 	ret = of_property_read_u32(np, "dma-channels", &dmac->n_channels);
7500c1c8ff3SYoshihiro Shimoda 	if (ret < 0) {
7510c1c8ff3SYoshihiro Shimoda 		dev_err(dev, "unable to read dma-channels property\n");
7520c1c8ff3SYoshihiro Shimoda 		return ret;
7530c1c8ff3SYoshihiro Shimoda 	}
7540c1c8ff3SYoshihiro Shimoda 
7550c1c8ff3SYoshihiro Shimoda 	if (dmac->n_channels <= 0 || dmac->n_channels >= 100) {
7560c1c8ff3SYoshihiro Shimoda 		dev_err(dev, "invalid number of channels %u\n",
7570c1c8ff3SYoshihiro Shimoda 			dmac->n_channels);
7580c1c8ff3SYoshihiro Shimoda 		return -EINVAL;
7590c1c8ff3SYoshihiro Shimoda 	}
7600c1c8ff3SYoshihiro Shimoda 
7610c1c8ff3SYoshihiro Shimoda 	return 0;
7620c1c8ff3SYoshihiro Shimoda }
7630c1c8ff3SYoshihiro Shimoda 
7640c1c8ff3SYoshihiro Shimoda static int usb_dmac_probe(struct platform_device *pdev)
7650c1c8ff3SYoshihiro Shimoda {
7660c1c8ff3SYoshihiro Shimoda 	const enum dma_slave_buswidth widths = USB_DMAC_SLAVE_BUSWIDTH;
7670c1c8ff3SYoshihiro Shimoda 	struct dma_device *engine;
7680c1c8ff3SYoshihiro Shimoda 	struct usb_dmac *dmac;
7690c1c8ff3SYoshihiro Shimoda 	struct resource *mem;
7700c1c8ff3SYoshihiro Shimoda 	unsigned int i;
7710c1c8ff3SYoshihiro Shimoda 	int ret;
7720c1c8ff3SYoshihiro Shimoda 
7730c1c8ff3SYoshihiro Shimoda 	dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL);
7740c1c8ff3SYoshihiro Shimoda 	if (!dmac)
7750c1c8ff3SYoshihiro Shimoda 		return -ENOMEM;
7760c1c8ff3SYoshihiro Shimoda 
7770c1c8ff3SYoshihiro Shimoda 	dmac->dev = &pdev->dev;
7780c1c8ff3SYoshihiro Shimoda 	platform_set_drvdata(pdev, dmac);
7790c1c8ff3SYoshihiro Shimoda 
7800c1c8ff3SYoshihiro Shimoda 	ret = usb_dmac_parse_of(&pdev->dev, dmac);
7810c1c8ff3SYoshihiro Shimoda 	if (ret < 0)
7820c1c8ff3SYoshihiro Shimoda 		return ret;
7830c1c8ff3SYoshihiro Shimoda 
7840c1c8ff3SYoshihiro Shimoda 	dmac->channels = devm_kcalloc(&pdev->dev, dmac->n_channels,
7850c1c8ff3SYoshihiro Shimoda 				      sizeof(*dmac->channels), GFP_KERNEL);
7860c1c8ff3SYoshihiro Shimoda 	if (!dmac->channels)
7870c1c8ff3SYoshihiro Shimoda 		return -ENOMEM;
7880c1c8ff3SYoshihiro Shimoda 
7890c1c8ff3SYoshihiro Shimoda 	/* Request resources. */
7900c1c8ff3SYoshihiro Shimoda 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
7910c1c8ff3SYoshihiro Shimoda 	dmac->iomem = devm_ioremap_resource(&pdev->dev, mem);
7920c1c8ff3SYoshihiro Shimoda 	if (IS_ERR(dmac->iomem))
7930c1c8ff3SYoshihiro Shimoda 		return PTR_ERR(dmac->iomem);
7940c1c8ff3SYoshihiro Shimoda 
7950c1c8ff3SYoshihiro Shimoda 	/* Enable runtime PM and initialize the device. */
7960c1c8ff3SYoshihiro Shimoda 	pm_runtime_enable(&pdev->dev);
7970c1c8ff3SYoshihiro Shimoda 	ret = pm_runtime_get_sync(&pdev->dev);
7980c1c8ff3SYoshihiro Shimoda 	if (ret < 0) {
7990c1c8ff3SYoshihiro Shimoda 		dev_err(&pdev->dev, "runtime PM get sync failed (%d)\n", ret);
8000c1c8ff3SYoshihiro Shimoda 		return ret;
8010c1c8ff3SYoshihiro Shimoda 	}
8020c1c8ff3SYoshihiro Shimoda 
8030c1c8ff3SYoshihiro Shimoda 	ret = usb_dmac_init(dmac);
8040c1c8ff3SYoshihiro Shimoda 	pm_runtime_put(&pdev->dev);
8050c1c8ff3SYoshihiro Shimoda 
8060c1c8ff3SYoshihiro Shimoda 	if (ret) {
8070c1c8ff3SYoshihiro Shimoda 		dev_err(&pdev->dev, "failed to reset device\n");
8080c1c8ff3SYoshihiro Shimoda 		goto error;
8090c1c8ff3SYoshihiro Shimoda 	}
8100c1c8ff3SYoshihiro Shimoda 
8110c1c8ff3SYoshihiro Shimoda 	/* Initialize the channels. */
8120c1c8ff3SYoshihiro Shimoda 	INIT_LIST_HEAD(&dmac->engine.channels);
8130c1c8ff3SYoshihiro Shimoda 
8140c1c8ff3SYoshihiro Shimoda 	for (i = 0; i < dmac->n_channels; ++i) {
8150c1c8ff3SYoshihiro Shimoda 		ret = usb_dmac_chan_probe(dmac, &dmac->channels[i], i);
8160c1c8ff3SYoshihiro Shimoda 		if (ret < 0)
8170c1c8ff3SYoshihiro Shimoda 			goto error;
8180c1c8ff3SYoshihiro Shimoda 	}
8190c1c8ff3SYoshihiro Shimoda 
8200c1c8ff3SYoshihiro Shimoda 	/* Register the DMAC as a DMA provider for DT. */
8210c1c8ff3SYoshihiro Shimoda 	ret = of_dma_controller_register(pdev->dev.of_node, usb_dmac_of_xlate,
8220c1c8ff3SYoshihiro Shimoda 					 NULL);
8230c1c8ff3SYoshihiro Shimoda 	if (ret < 0)
8240c1c8ff3SYoshihiro Shimoda 		goto error;
8250c1c8ff3SYoshihiro Shimoda 
8260c1c8ff3SYoshihiro Shimoda 	/*
8270c1c8ff3SYoshihiro Shimoda 	 * Register the DMA engine device.
8280c1c8ff3SYoshihiro Shimoda 	 *
8290c1c8ff3SYoshihiro Shimoda 	 * Default transfer size of 32 bytes requires 32-byte alignment.
8300c1c8ff3SYoshihiro Shimoda 	 */
8310c1c8ff3SYoshihiro Shimoda 	engine = &dmac->engine;
8320c1c8ff3SYoshihiro Shimoda 	dma_cap_set(DMA_SLAVE, engine->cap_mask);
8330c1c8ff3SYoshihiro Shimoda 
8340c1c8ff3SYoshihiro Shimoda 	engine->dev = &pdev->dev;
8350c1c8ff3SYoshihiro Shimoda 
8360c1c8ff3SYoshihiro Shimoda 	engine->src_addr_widths = widths;
8370c1c8ff3SYoshihiro Shimoda 	engine->dst_addr_widths = widths;
8380c1c8ff3SYoshihiro Shimoda 	engine->directions = BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM);
8390c1c8ff3SYoshihiro Shimoda 	engine->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
8400c1c8ff3SYoshihiro Shimoda 
8410c1c8ff3SYoshihiro Shimoda 	engine->device_alloc_chan_resources = usb_dmac_alloc_chan_resources;
8420c1c8ff3SYoshihiro Shimoda 	engine->device_free_chan_resources = usb_dmac_free_chan_resources;
8430c1c8ff3SYoshihiro Shimoda 	engine->device_prep_slave_sg = usb_dmac_prep_slave_sg;
8440c1c8ff3SYoshihiro Shimoda 	engine->device_terminate_all = usb_dmac_chan_terminate_all;
8450c1c8ff3SYoshihiro Shimoda 	engine->device_tx_status = usb_dmac_tx_status;
8460c1c8ff3SYoshihiro Shimoda 	engine->device_issue_pending = usb_dmac_issue_pending;
8470c1c8ff3SYoshihiro Shimoda 
8480c1c8ff3SYoshihiro Shimoda 	ret = dma_async_device_register(engine);
8490c1c8ff3SYoshihiro Shimoda 	if (ret < 0)
8500c1c8ff3SYoshihiro Shimoda 		goto error;
8510c1c8ff3SYoshihiro Shimoda 
8520c1c8ff3SYoshihiro Shimoda 	return 0;
8530c1c8ff3SYoshihiro Shimoda 
8540c1c8ff3SYoshihiro Shimoda error:
8550c1c8ff3SYoshihiro Shimoda 	of_dma_controller_free(pdev->dev.of_node);
8560c1c8ff3SYoshihiro Shimoda 	pm_runtime_disable(&pdev->dev);
8570c1c8ff3SYoshihiro Shimoda 	return ret;
8580c1c8ff3SYoshihiro Shimoda }
8590c1c8ff3SYoshihiro Shimoda 
8600c1c8ff3SYoshihiro Shimoda static void usb_dmac_chan_remove(struct usb_dmac *dmac,
8610c1c8ff3SYoshihiro Shimoda 				 struct usb_dmac_chan *uchan)
8620c1c8ff3SYoshihiro Shimoda {
8630c1c8ff3SYoshihiro Shimoda 	usb_dmac_chan_halt(uchan);
8640c1c8ff3SYoshihiro Shimoda 	devm_free_irq(dmac->dev, uchan->irq, uchan);
8650c1c8ff3SYoshihiro Shimoda }
8660c1c8ff3SYoshihiro Shimoda 
8670c1c8ff3SYoshihiro Shimoda static int usb_dmac_remove(struct platform_device *pdev)
8680c1c8ff3SYoshihiro Shimoda {
8690c1c8ff3SYoshihiro Shimoda 	struct usb_dmac *dmac = platform_get_drvdata(pdev);
8700c1c8ff3SYoshihiro Shimoda 	int i;
8710c1c8ff3SYoshihiro Shimoda 
8720c1c8ff3SYoshihiro Shimoda 	for (i = 0; i < dmac->n_channels; ++i)
8730c1c8ff3SYoshihiro Shimoda 		usb_dmac_chan_remove(dmac, &dmac->channels[i]);
8740c1c8ff3SYoshihiro Shimoda 	of_dma_controller_free(pdev->dev.of_node);
8750c1c8ff3SYoshihiro Shimoda 	dma_async_device_unregister(&dmac->engine);
8760c1c8ff3SYoshihiro Shimoda 
8770c1c8ff3SYoshihiro Shimoda 	pm_runtime_disable(&pdev->dev);
8780c1c8ff3SYoshihiro Shimoda 
8790c1c8ff3SYoshihiro Shimoda 	return 0;
8800c1c8ff3SYoshihiro Shimoda }
8810c1c8ff3SYoshihiro Shimoda 
8820c1c8ff3SYoshihiro Shimoda static void usb_dmac_shutdown(struct platform_device *pdev)
8830c1c8ff3SYoshihiro Shimoda {
8840c1c8ff3SYoshihiro Shimoda 	struct usb_dmac *dmac = platform_get_drvdata(pdev);
8850c1c8ff3SYoshihiro Shimoda 
8860c1c8ff3SYoshihiro Shimoda 	usb_dmac_stop(dmac);
8870c1c8ff3SYoshihiro Shimoda }
8880c1c8ff3SYoshihiro Shimoda 
8890c1c8ff3SYoshihiro Shimoda static const struct of_device_id usb_dmac_of_ids[] = {
8900c1c8ff3SYoshihiro Shimoda 	{ .compatible = "renesas,usb-dmac", },
8910c1c8ff3SYoshihiro Shimoda 	{ /* Sentinel */ }
8920c1c8ff3SYoshihiro Shimoda };
8930c1c8ff3SYoshihiro Shimoda MODULE_DEVICE_TABLE(of, usb_dmac_of_ids);
8940c1c8ff3SYoshihiro Shimoda 
8950c1c8ff3SYoshihiro Shimoda static struct platform_driver usb_dmac_driver = {
8960c1c8ff3SYoshihiro Shimoda 	.driver		= {
8970c1c8ff3SYoshihiro Shimoda 		.pm	= &usb_dmac_pm,
8980c1c8ff3SYoshihiro Shimoda 		.name	= "usb-dmac",
8990c1c8ff3SYoshihiro Shimoda 		.of_match_table = usb_dmac_of_ids,
9000c1c8ff3SYoshihiro Shimoda 	},
9010c1c8ff3SYoshihiro Shimoda 	.probe		= usb_dmac_probe,
9020c1c8ff3SYoshihiro Shimoda 	.remove		= usb_dmac_remove,
9030c1c8ff3SYoshihiro Shimoda 	.shutdown	= usb_dmac_shutdown,
9040c1c8ff3SYoshihiro Shimoda };
9050c1c8ff3SYoshihiro Shimoda 
9060c1c8ff3SYoshihiro Shimoda module_platform_driver(usb_dmac_driver);
9070c1c8ff3SYoshihiro Shimoda 
9080c1c8ff3SYoshihiro Shimoda MODULE_DESCRIPTION("Renesas USB DMA Controller Driver");
9090c1c8ff3SYoshihiro Shimoda MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");
9100c1c8ff3SYoshihiro Shimoda MODULE_LICENSE("GPL v2");
911