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