162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/device.h>
362306a36Sopenharmony_ci#include <linux/dma-mapping.h>
462306a36Sopenharmony_ci#include <linux/dmaengine.h>
562306a36Sopenharmony_ci#include <linux/sizes.h>
662306a36Sopenharmony_ci#include <linux/platform_device.h>
762306a36Sopenharmony_ci#include <linux/of.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include "cppi_dma.h"
1062306a36Sopenharmony_ci#include "musb_core.h"
1162306a36Sopenharmony_ci#include "musb_trace.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#define RNDIS_REG(x) (0x80 + ((x - 1) * 4))
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define EP_MODE_AUTOREQ_NONE		0
1662306a36Sopenharmony_ci#define EP_MODE_AUTOREQ_ALL_NEOP	1
1762306a36Sopenharmony_ci#define EP_MODE_AUTOREQ_ALWAYS		3
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define EP_MODE_DMA_TRANSPARENT		0
2062306a36Sopenharmony_ci#define EP_MODE_DMA_RNDIS		1
2162306a36Sopenharmony_ci#define EP_MODE_DMA_GEN_RNDIS		3
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define USB_CTRL_TX_MODE	0x70
2462306a36Sopenharmony_ci#define USB_CTRL_RX_MODE	0x74
2562306a36Sopenharmony_ci#define USB_CTRL_AUTOREQ	0xd0
2662306a36Sopenharmony_ci#define USB_TDOWN		0xd8
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define MUSB_DMA_NUM_CHANNELS 15
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define DA8XX_USB_MODE		0x10
3162306a36Sopenharmony_ci#define DA8XX_USB_AUTOREQ	0x14
3262306a36Sopenharmony_ci#define DA8XX_USB_TEARDOWN	0x1c
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define DA8XX_DMA_NUM_CHANNELS 4
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistruct cppi41_dma_controller {
3762306a36Sopenharmony_ci	struct dma_controller controller;
3862306a36Sopenharmony_ci	struct cppi41_dma_channel *rx_channel;
3962306a36Sopenharmony_ci	struct cppi41_dma_channel *tx_channel;
4062306a36Sopenharmony_ci	struct hrtimer early_tx;
4162306a36Sopenharmony_ci	struct list_head early_tx_list;
4262306a36Sopenharmony_ci	u32 rx_mode;
4362306a36Sopenharmony_ci	u32 tx_mode;
4462306a36Sopenharmony_ci	u32 auto_req;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	u32 tdown_reg;
4762306a36Sopenharmony_ci	u32 autoreq_reg;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	void (*set_dma_mode)(struct cppi41_dma_channel *cppi41_channel,
5062306a36Sopenharmony_ci			     unsigned int mode);
5162306a36Sopenharmony_ci	u8 num_channels;
5262306a36Sopenharmony_ci};
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	u16 csr;
5762306a36Sopenharmony_ci	u8 toggle;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	if (cppi41_channel->is_tx)
6062306a36Sopenharmony_ci		return;
6162306a36Sopenharmony_ci	if (!is_host_active(cppi41_channel->controller->controller.musb))
6262306a36Sopenharmony_ci		return;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
6562306a36Sopenharmony_ci	toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	cppi41_channel->usb_toggle = toggle;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
7362306a36Sopenharmony_ci	struct musb *musb = hw_ep->musb;
7462306a36Sopenharmony_ci	u16 csr;
7562306a36Sopenharmony_ci	u8 toggle;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	if (cppi41_channel->is_tx)
7862306a36Sopenharmony_ci		return;
7962306a36Sopenharmony_ci	if (!is_host_active(musb))
8062306a36Sopenharmony_ci		return;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	musb_ep_select(musb->mregs, hw_ep->epnum);
8362306a36Sopenharmony_ci	csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
8462306a36Sopenharmony_ci	toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	/*
8762306a36Sopenharmony_ci	 * AM335x Advisory 1.0.13: Due to internal synchronisation error the
8862306a36Sopenharmony_ci	 * data toggle may reset from DATA1 to DATA0 during receiving data from
8962306a36Sopenharmony_ci	 * more than one endpoint.
9062306a36Sopenharmony_ci	 */
9162306a36Sopenharmony_ci	if (!toggle && toggle == cppi41_channel->usb_toggle) {
9262306a36Sopenharmony_ci		csr |= MUSB_RXCSR_H_DATATOGGLE | MUSB_RXCSR_H_WR_DATATOGGLE;
9362306a36Sopenharmony_ci		musb_writew(cppi41_channel->hw_ep->regs, MUSB_RXCSR, csr);
9462306a36Sopenharmony_ci		musb_dbg(musb, "Restoring DATA1 toggle.");
9562306a36Sopenharmony_ci	}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	cppi41_channel->usb_toggle = toggle;
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	u8		epnum = hw_ep->epnum;
10362306a36Sopenharmony_ci	struct musb	*musb = hw_ep->musb;
10462306a36Sopenharmony_ci	void __iomem	*epio = musb->endpoints[epnum].regs;
10562306a36Sopenharmony_ci	u16		csr;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	musb_ep_select(musb->mregs, hw_ep->epnum);
10862306a36Sopenharmony_ci	csr = musb_readw(epio, MUSB_TXCSR);
10962306a36Sopenharmony_ci	if (csr & MUSB_TXCSR_TXPKTRDY)
11062306a36Sopenharmony_ci		return false;
11162306a36Sopenharmony_ci	return true;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistatic void cppi41_dma_callback(void *private_data,
11562306a36Sopenharmony_ci				const struct dmaengine_result *result);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
12062306a36Sopenharmony_ci	struct musb *musb = hw_ep->musb;
12162306a36Sopenharmony_ci	void __iomem *epio = hw_ep->regs;
12262306a36Sopenharmony_ci	u16 csr;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	if (!cppi41_channel->prog_len ||
12562306a36Sopenharmony_ci	    (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)) {
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci		/* done, complete */
12862306a36Sopenharmony_ci		cppi41_channel->channel.actual_len =
12962306a36Sopenharmony_ci			cppi41_channel->transferred;
13062306a36Sopenharmony_ci		cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
13162306a36Sopenharmony_ci		cppi41_channel->channel.rx_packet_done = true;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci		/*
13462306a36Sopenharmony_ci		 * transmit ZLP using PIO mode for transfers which size is
13562306a36Sopenharmony_ci		 * multiple of EP packet size.
13662306a36Sopenharmony_ci		 */
13762306a36Sopenharmony_ci		if (cppi41_channel->tx_zlp && (cppi41_channel->transferred %
13862306a36Sopenharmony_ci					cppi41_channel->packet_sz) == 0) {
13962306a36Sopenharmony_ci			musb_ep_select(musb->mregs, hw_ep->epnum);
14062306a36Sopenharmony_ci			csr = MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY;
14162306a36Sopenharmony_ci			musb_writew(epio, MUSB_TXCSR, csr);
14262306a36Sopenharmony_ci		}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci		trace_musb_cppi41_done(cppi41_channel);
14562306a36Sopenharmony_ci		musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
14662306a36Sopenharmony_ci	} else {
14762306a36Sopenharmony_ci		/* next iteration, reload */
14862306a36Sopenharmony_ci		struct dma_chan *dc = cppi41_channel->dc;
14962306a36Sopenharmony_ci		struct dma_async_tx_descriptor *dma_desc;
15062306a36Sopenharmony_ci		enum dma_transfer_direction direction;
15162306a36Sopenharmony_ci		u32 remain_bytes;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci		cppi41_channel->buf_addr += cppi41_channel->packet_sz;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci		remain_bytes = cppi41_channel->total_len;
15662306a36Sopenharmony_ci		remain_bytes -= cppi41_channel->transferred;
15762306a36Sopenharmony_ci		remain_bytes = min(remain_bytes, cppi41_channel->packet_sz);
15862306a36Sopenharmony_ci		cppi41_channel->prog_len = remain_bytes;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci		direction = cppi41_channel->is_tx ? DMA_MEM_TO_DEV
16162306a36Sopenharmony_ci			: DMA_DEV_TO_MEM;
16262306a36Sopenharmony_ci		dma_desc = dmaengine_prep_slave_single(dc,
16362306a36Sopenharmony_ci				cppi41_channel->buf_addr,
16462306a36Sopenharmony_ci				remain_bytes,
16562306a36Sopenharmony_ci				direction,
16662306a36Sopenharmony_ci				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
16762306a36Sopenharmony_ci		if (WARN_ON(!dma_desc))
16862306a36Sopenharmony_ci			return;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci		dma_desc->callback_result = cppi41_dma_callback;
17162306a36Sopenharmony_ci		dma_desc->callback_param = &cppi41_channel->channel;
17262306a36Sopenharmony_ci		cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
17362306a36Sopenharmony_ci		trace_musb_cppi41_cont(cppi41_channel);
17462306a36Sopenharmony_ci		dma_async_issue_pending(dc);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci		if (!cppi41_channel->is_tx) {
17762306a36Sopenharmony_ci			musb_ep_select(musb->mregs, hw_ep->epnum);
17862306a36Sopenharmony_ci			csr = musb_readw(epio, MUSB_RXCSR);
17962306a36Sopenharmony_ci			csr |= MUSB_RXCSR_H_REQPKT;
18062306a36Sopenharmony_ci			musb_writew(epio, MUSB_RXCSR, csr);
18162306a36Sopenharmony_ci		}
18262306a36Sopenharmony_ci	}
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	struct cppi41_dma_controller *controller;
18862306a36Sopenharmony_ci	struct cppi41_dma_channel *cppi41_channel, *n;
18962306a36Sopenharmony_ci	struct musb *musb;
19062306a36Sopenharmony_ci	unsigned long flags;
19162306a36Sopenharmony_ci	enum hrtimer_restart ret = HRTIMER_NORESTART;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	controller = container_of(timer, struct cppi41_dma_controller,
19462306a36Sopenharmony_ci			early_tx);
19562306a36Sopenharmony_ci	musb = controller->controller.musb;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	spin_lock_irqsave(&musb->lock, flags);
19862306a36Sopenharmony_ci	list_for_each_entry_safe(cppi41_channel, n, &controller->early_tx_list,
19962306a36Sopenharmony_ci			tx_check) {
20062306a36Sopenharmony_ci		bool empty;
20162306a36Sopenharmony_ci		struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci		empty = musb_is_tx_fifo_empty(hw_ep);
20462306a36Sopenharmony_ci		if (empty) {
20562306a36Sopenharmony_ci			list_del_init(&cppi41_channel->tx_check);
20662306a36Sopenharmony_ci			cppi41_trans_done(cppi41_channel);
20762306a36Sopenharmony_ci		}
20862306a36Sopenharmony_ci	}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	if (!list_empty(&controller->early_tx_list) &&
21162306a36Sopenharmony_ci	    !hrtimer_is_queued(&controller->early_tx)) {
21262306a36Sopenharmony_ci		ret = HRTIMER_RESTART;
21362306a36Sopenharmony_ci		hrtimer_forward_now(&controller->early_tx, 20 * NSEC_PER_USEC);
21462306a36Sopenharmony_ci	}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	spin_unlock_irqrestore(&musb->lock, flags);
21762306a36Sopenharmony_ci	return ret;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cistatic void cppi41_dma_callback(void *private_data,
22162306a36Sopenharmony_ci				const struct dmaengine_result *result)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	struct dma_channel *channel = private_data;
22462306a36Sopenharmony_ci	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
22562306a36Sopenharmony_ci	struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
22662306a36Sopenharmony_ci	struct cppi41_dma_controller *controller;
22762306a36Sopenharmony_ci	struct musb *musb = hw_ep->musb;
22862306a36Sopenharmony_ci	unsigned long flags;
22962306a36Sopenharmony_ci	struct dma_tx_state txstate;
23062306a36Sopenharmony_ci	u32 transferred;
23162306a36Sopenharmony_ci	int is_hs = 0;
23262306a36Sopenharmony_ci	bool empty;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	controller = cppi41_channel->controller;
23562306a36Sopenharmony_ci	if (controller->controller.dma_callback)
23662306a36Sopenharmony_ci		controller->controller.dma_callback(&controller->controller);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	if (result->result == DMA_TRANS_ABORTED)
23962306a36Sopenharmony_ci		return;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	spin_lock_irqsave(&musb->lock, flags);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
24462306a36Sopenharmony_ci			&txstate);
24562306a36Sopenharmony_ci	transferred = cppi41_channel->prog_len - txstate.residue;
24662306a36Sopenharmony_ci	cppi41_channel->transferred += transferred;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	trace_musb_cppi41_gb(cppi41_channel);
24962306a36Sopenharmony_ci	update_rx_toggle(cppi41_channel);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	if (cppi41_channel->transferred == cppi41_channel->total_len ||
25262306a36Sopenharmony_ci			transferred < cppi41_channel->packet_sz)
25362306a36Sopenharmony_ci		cppi41_channel->prog_len = 0;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	if (cppi41_channel->is_tx) {
25662306a36Sopenharmony_ci		u8 type;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci		if (is_host_active(musb))
25962306a36Sopenharmony_ci			type = hw_ep->out_qh->type;
26062306a36Sopenharmony_ci		else
26162306a36Sopenharmony_ci			type = hw_ep->ep_in.type;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci		if (type == USB_ENDPOINT_XFER_ISOC)
26462306a36Sopenharmony_ci			/*
26562306a36Sopenharmony_ci			 * Don't use the early-TX-interrupt workaround below
26662306a36Sopenharmony_ci			 * for Isoch transfter. Since Isoch are periodic
26762306a36Sopenharmony_ci			 * transfer, by the time the next transfer is
26862306a36Sopenharmony_ci			 * scheduled, the current one should be done already.
26962306a36Sopenharmony_ci			 *
27062306a36Sopenharmony_ci			 * This avoids audio playback underrun issue.
27162306a36Sopenharmony_ci			 */
27262306a36Sopenharmony_ci			empty = true;
27362306a36Sopenharmony_ci		else
27462306a36Sopenharmony_ci			empty = musb_is_tx_fifo_empty(hw_ep);
27562306a36Sopenharmony_ci	}
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	if (!cppi41_channel->is_tx || empty) {
27862306a36Sopenharmony_ci		cppi41_trans_done(cppi41_channel);
27962306a36Sopenharmony_ci		goto out;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	/*
28362306a36Sopenharmony_ci	 * On AM335x it has been observed that the TX interrupt fires
28462306a36Sopenharmony_ci	 * too early that means the TXFIFO is not yet empty but the DMA
28562306a36Sopenharmony_ci	 * engine says that it is done with the transfer. We don't
28662306a36Sopenharmony_ci	 * receive a FIFO empty interrupt so the only thing we can do is
28762306a36Sopenharmony_ci	 * to poll for the bit. On HS it usually takes 2us, on FS around
28862306a36Sopenharmony_ci	 * 110us - 150us depending on the transfer size.
28962306a36Sopenharmony_ci	 * We spin on HS (no longer than 25us and setup a timer on
29062306a36Sopenharmony_ci	 * FS to check for the bit and complete the transfer.
29162306a36Sopenharmony_ci	 */
29262306a36Sopenharmony_ci	if (is_host_active(musb)) {
29362306a36Sopenharmony_ci		if (musb->port1_status & USB_PORT_STAT_HIGH_SPEED)
29462306a36Sopenharmony_ci			is_hs = 1;
29562306a36Sopenharmony_ci	} else {
29662306a36Sopenharmony_ci		if (musb->g.speed == USB_SPEED_HIGH)
29762306a36Sopenharmony_ci			is_hs = 1;
29862306a36Sopenharmony_ci	}
29962306a36Sopenharmony_ci	if (is_hs) {
30062306a36Sopenharmony_ci		unsigned wait = 25;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci		do {
30362306a36Sopenharmony_ci			empty = musb_is_tx_fifo_empty(hw_ep);
30462306a36Sopenharmony_ci			if (empty) {
30562306a36Sopenharmony_ci				cppi41_trans_done(cppi41_channel);
30662306a36Sopenharmony_ci				goto out;
30762306a36Sopenharmony_ci			}
30862306a36Sopenharmony_ci			wait--;
30962306a36Sopenharmony_ci			if (!wait)
31062306a36Sopenharmony_ci				break;
31162306a36Sopenharmony_ci			cpu_relax();
31262306a36Sopenharmony_ci		} while (1);
31362306a36Sopenharmony_ci	}
31462306a36Sopenharmony_ci	list_add_tail(&cppi41_channel->tx_check,
31562306a36Sopenharmony_ci			&controller->early_tx_list);
31662306a36Sopenharmony_ci	if (!hrtimer_is_queued(&controller->early_tx)) {
31762306a36Sopenharmony_ci		unsigned long usecs = cppi41_channel->total_len / 10;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci		hrtimer_start_range_ns(&controller->early_tx,
32062306a36Sopenharmony_ci				       usecs * NSEC_PER_USEC,
32162306a36Sopenharmony_ci				       20 * NSEC_PER_USEC,
32262306a36Sopenharmony_ci				       HRTIMER_MODE_REL);
32362306a36Sopenharmony_ci	}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ciout:
32662306a36Sopenharmony_ci	spin_unlock_irqrestore(&musb->lock, flags);
32762306a36Sopenharmony_ci}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_cistatic u32 update_ep_mode(unsigned ep, unsigned mode, u32 old)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	unsigned shift;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	shift = (ep - 1) * 2;
33462306a36Sopenharmony_ci	old &= ~(3 << shift);
33562306a36Sopenharmony_ci	old |= mode << shift;
33662306a36Sopenharmony_ci	return old;
33762306a36Sopenharmony_ci}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_cistatic void cppi41_set_dma_mode(struct cppi41_dma_channel *cppi41_channel,
34062306a36Sopenharmony_ci		unsigned mode)
34162306a36Sopenharmony_ci{
34262306a36Sopenharmony_ci	struct cppi41_dma_controller *controller = cppi41_channel->controller;
34362306a36Sopenharmony_ci	struct musb *musb = controller->controller.musb;
34462306a36Sopenharmony_ci	u32 port;
34562306a36Sopenharmony_ci	u32 new_mode;
34662306a36Sopenharmony_ci	u32 old_mode;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	if (cppi41_channel->is_tx)
34962306a36Sopenharmony_ci		old_mode = controller->tx_mode;
35062306a36Sopenharmony_ci	else
35162306a36Sopenharmony_ci		old_mode = controller->rx_mode;
35262306a36Sopenharmony_ci	port = cppi41_channel->port_num;
35362306a36Sopenharmony_ci	new_mode = update_ep_mode(port, mode, old_mode);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	if (new_mode == old_mode)
35662306a36Sopenharmony_ci		return;
35762306a36Sopenharmony_ci	if (cppi41_channel->is_tx) {
35862306a36Sopenharmony_ci		controller->tx_mode = new_mode;
35962306a36Sopenharmony_ci		musb_writel(musb->ctrl_base, USB_CTRL_TX_MODE, new_mode);
36062306a36Sopenharmony_ci	} else {
36162306a36Sopenharmony_ci		controller->rx_mode = new_mode;
36262306a36Sopenharmony_ci		musb_writel(musb->ctrl_base, USB_CTRL_RX_MODE, new_mode);
36362306a36Sopenharmony_ci	}
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_cistatic void da8xx_set_dma_mode(struct cppi41_dma_channel *cppi41_channel,
36762306a36Sopenharmony_ci		unsigned int mode)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	struct cppi41_dma_controller *controller = cppi41_channel->controller;
37062306a36Sopenharmony_ci	struct musb *musb = controller->controller.musb;
37162306a36Sopenharmony_ci	unsigned int shift;
37262306a36Sopenharmony_ci	u32 port;
37362306a36Sopenharmony_ci	u32 new_mode;
37462306a36Sopenharmony_ci	u32 old_mode;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	old_mode = controller->tx_mode;
37762306a36Sopenharmony_ci	port = cppi41_channel->port_num;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	shift = (port - 1) * 4;
38062306a36Sopenharmony_ci	if (!cppi41_channel->is_tx)
38162306a36Sopenharmony_ci		shift += 16;
38262306a36Sopenharmony_ci	new_mode = old_mode & ~(3 << shift);
38362306a36Sopenharmony_ci	new_mode |= mode << shift;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	if (new_mode == old_mode)
38662306a36Sopenharmony_ci		return;
38762306a36Sopenharmony_ci	controller->tx_mode = new_mode;
38862306a36Sopenharmony_ci	musb_writel(musb->ctrl_base, DA8XX_USB_MODE, new_mode);
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_cistatic void cppi41_set_autoreq_mode(struct cppi41_dma_channel *cppi41_channel,
39362306a36Sopenharmony_ci		unsigned mode)
39462306a36Sopenharmony_ci{
39562306a36Sopenharmony_ci	struct cppi41_dma_controller *controller = cppi41_channel->controller;
39662306a36Sopenharmony_ci	u32 port;
39762306a36Sopenharmony_ci	u32 new_mode;
39862306a36Sopenharmony_ci	u32 old_mode;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	old_mode = controller->auto_req;
40162306a36Sopenharmony_ci	port = cppi41_channel->port_num;
40262306a36Sopenharmony_ci	new_mode = update_ep_mode(port, mode, old_mode);
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	if (new_mode == old_mode)
40562306a36Sopenharmony_ci		return;
40662306a36Sopenharmony_ci	controller->auto_req = new_mode;
40762306a36Sopenharmony_ci	musb_writel(controller->controller.musb->ctrl_base,
40862306a36Sopenharmony_ci		    controller->autoreq_reg, new_mode);
40962306a36Sopenharmony_ci}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_cistatic bool cppi41_configure_channel(struct dma_channel *channel,
41262306a36Sopenharmony_ci				u16 packet_sz, u8 mode,
41362306a36Sopenharmony_ci				dma_addr_t dma_addr, u32 len)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
41662306a36Sopenharmony_ci	struct cppi41_dma_controller *controller = cppi41_channel->controller;
41762306a36Sopenharmony_ci	struct dma_chan *dc = cppi41_channel->dc;
41862306a36Sopenharmony_ci	struct dma_async_tx_descriptor *dma_desc;
41962306a36Sopenharmony_ci	enum dma_transfer_direction direction;
42062306a36Sopenharmony_ci	struct musb *musb = cppi41_channel->controller->controller.musb;
42162306a36Sopenharmony_ci	unsigned use_gen_rndis = 0;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	cppi41_channel->buf_addr = dma_addr;
42462306a36Sopenharmony_ci	cppi41_channel->total_len = len;
42562306a36Sopenharmony_ci	cppi41_channel->transferred = 0;
42662306a36Sopenharmony_ci	cppi41_channel->packet_sz = packet_sz;
42762306a36Sopenharmony_ci	cppi41_channel->tx_zlp = (cppi41_channel->is_tx && mode) ? 1 : 0;
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	/*
43062306a36Sopenharmony_ci	 * Due to AM335x' Advisory 1.0.13 we are not allowed to transfer more
43162306a36Sopenharmony_ci	 * than max packet size at a time.
43262306a36Sopenharmony_ci	 */
43362306a36Sopenharmony_ci	if (cppi41_channel->is_tx)
43462306a36Sopenharmony_ci		use_gen_rndis = 1;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	if (use_gen_rndis) {
43762306a36Sopenharmony_ci		/* RNDIS mode */
43862306a36Sopenharmony_ci		if (len > packet_sz) {
43962306a36Sopenharmony_ci			musb_writel(musb->ctrl_base,
44062306a36Sopenharmony_ci				RNDIS_REG(cppi41_channel->port_num), len);
44162306a36Sopenharmony_ci			/* gen rndis */
44262306a36Sopenharmony_ci			controller->set_dma_mode(cppi41_channel,
44362306a36Sopenharmony_ci					EP_MODE_DMA_GEN_RNDIS);
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci			/* auto req */
44662306a36Sopenharmony_ci			cppi41_set_autoreq_mode(cppi41_channel,
44762306a36Sopenharmony_ci					EP_MODE_AUTOREQ_ALL_NEOP);
44862306a36Sopenharmony_ci		} else {
44962306a36Sopenharmony_ci			musb_writel(musb->ctrl_base,
45062306a36Sopenharmony_ci					RNDIS_REG(cppi41_channel->port_num), 0);
45162306a36Sopenharmony_ci			controller->set_dma_mode(cppi41_channel,
45262306a36Sopenharmony_ci					EP_MODE_DMA_TRANSPARENT);
45362306a36Sopenharmony_ci			cppi41_set_autoreq_mode(cppi41_channel,
45462306a36Sopenharmony_ci					EP_MODE_AUTOREQ_NONE);
45562306a36Sopenharmony_ci		}
45662306a36Sopenharmony_ci	} else {
45762306a36Sopenharmony_ci		/* fallback mode */
45862306a36Sopenharmony_ci		controller->set_dma_mode(cppi41_channel,
45962306a36Sopenharmony_ci				EP_MODE_DMA_TRANSPARENT);
46062306a36Sopenharmony_ci		cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE);
46162306a36Sopenharmony_ci		len = min_t(u32, packet_sz, len);
46262306a36Sopenharmony_ci	}
46362306a36Sopenharmony_ci	cppi41_channel->prog_len = len;
46462306a36Sopenharmony_ci	direction = cppi41_channel->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
46562306a36Sopenharmony_ci	dma_desc = dmaengine_prep_slave_single(dc, dma_addr, len, direction,
46662306a36Sopenharmony_ci			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
46762306a36Sopenharmony_ci	if (!dma_desc)
46862306a36Sopenharmony_ci		return false;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	dma_desc->callback_result = cppi41_dma_callback;
47162306a36Sopenharmony_ci	dma_desc->callback_param = channel;
47262306a36Sopenharmony_ci	cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
47362306a36Sopenharmony_ci	cppi41_channel->channel.rx_packet_done = false;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	trace_musb_cppi41_config(cppi41_channel);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	save_rx_toggle(cppi41_channel);
47862306a36Sopenharmony_ci	dma_async_issue_pending(dc);
47962306a36Sopenharmony_ci	return true;
48062306a36Sopenharmony_ci}
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_cistatic struct dma_channel *cppi41_dma_channel_allocate(struct dma_controller *c,
48362306a36Sopenharmony_ci				struct musb_hw_ep *hw_ep, u8 is_tx)
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	struct cppi41_dma_controller *controller = container_of(c,
48662306a36Sopenharmony_ci			struct cppi41_dma_controller, controller);
48762306a36Sopenharmony_ci	struct cppi41_dma_channel *cppi41_channel = NULL;
48862306a36Sopenharmony_ci	u8 ch_num = hw_ep->epnum - 1;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	if (ch_num >= controller->num_channels)
49162306a36Sopenharmony_ci		return NULL;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	if (is_tx)
49462306a36Sopenharmony_ci		cppi41_channel = &controller->tx_channel[ch_num];
49562306a36Sopenharmony_ci	else
49662306a36Sopenharmony_ci		cppi41_channel = &controller->rx_channel[ch_num];
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	if (!cppi41_channel->dc)
49962306a36Sopenharmony_ci		return NULL;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	if (cppi41_channel->is_allocated)
50262306a36Sopenharmony_ci		return NULL;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	cppi41_channel->hw_ep = hw_ep;
50562306a36Sopenharmony_ci	cppi41_channel->is_allocated = 1;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	trace_musb_cppi41_alloc(cppi41_channel);
50862306a36Sopenharmony_ci	return &cppi41_channel->channel;
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_cistatic void cppi41_dma_channel_release(struct dma_channel *channel)
51262306a36Sopenharmony_ci{
51362306a36Sopenharmony_ci	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	trace_musb_cppi41_free(cppi41_channel);
51662306a36Sopenharmony_ci	if (cppi41_channel->is_allocated) {
51762306a36Sopenharmony_ci		cppi41_channel->is_allocated = 0;
51862306a36Sopenharmony_ci		channel->status = MUSB_DMA_STATUS_FREE;
51962306a36Sopenharmony_ci		channel->actual_len = 0;
52062306a36Sopenharmony_ci	}
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_cistatic int cppi41_dma_channel_program(struct dma_channel *channel,
52462306a36Sopenharmony_ci				u16 packet_sz, u8 mode,
52562306a36Sopenharmony_ci				dma_addr_t dma_addr, u32 len)
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	int ret;
52862306a36Sopenharmony_ci	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
52962306a36Sopenharmony_ci	int hb_mult = 0;
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN ||
53262306a36Sopenharmony_ci		channel->status == MUSB_DMA_STATUS_BUSY);
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	if (is_host_active(cppi41_channel->controller->controller.musb)) {
53562306a36Sopenharmony_ci		if (cppi41_channel->is_tx)
53662306a36Sopenharmony_ci			hb_mult = cppi41_channel->hw_ep->out_qh->hb_mult;
53762306a36Sopenharmony_ci		else
53862306a36Sopenharmony_ci			hb_mult = cppi41_channel->hw_ep->in_qh->hb_mult;
53962306a36Sopenharmony_ci	}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	channel->status = MUSB_DMA_STATUS_BUSY;
54262306a36Sopenharmony_ci	channel->actual_len = 0;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	if (hb_mult)
54562306a36Sopenharmony_ci		packet_sz = hb_mult * (packet_sz & 0x7FF);
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	ret = cppi41_configure_channel(channel, packet_sz, mode, dma_addr, len);
54862306a36Sopenharmony_ci	if (!ret)
54962306a36Sopenharmony_ci		channel->status = MUSB_DMA_STATUS_FREE;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	return ret;
55262306a36Sopenharmony_ci}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_cistatic int cppi41_is_compatible(struct dma_channel *channel, u16 maxpacket,
55562306a36Sopenharmony_ci		void *buf, u32 length)
55662306a36Sopenharmony_ci{
55762306a36Sopenharmony_ci	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
55862306a36Sopenharmony_ci	struct cppi41_dma_controller *controller = cppi41_channel->controller;
55962306a36Sopenharmony_ci	struct musb *musb = controller->controller.musb;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	if (is_host_active(musb)) {
56262306a36Sopenharmony_ci		WARN_ON(1);
56362306a36Sopenharmony_ci		return 1;
56462306a36Sopenharmony_ci	}
56562306a36Sopenharmony_ci	if (cppi41_channel->hw_ep->ep_in.type != USB_ENDPOINT_XFER_BULK)
56662306a36Sopenharmony_ci		return 0;
56762306a36Sopenharmony_ci	if (cppi41_channel->is_tx)
56862306a36Sopenharmony_ci		return 1;
56962306a36Sopenharmony_ci	/* AM335x Advisory 1.0.13. No workaround for device RX mode */
57062306a36Sopenharmony_ci	return 0;
57162306a36Sopenharmony_ci}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_cistatic int cppi41_dma_channel_abort(struct dma_channel *channel)
57462306a36Sopenharmony_ci{
57562306a36Sopenharmony_ci	struct cppi41_dma_channel *cppi41_channel = channel->private_data;
57662306a36Sopenharmony_ci	struct cppi41_dma_controller *controller = cppi41_channel->controller;
57762306a36Sopenharmony_ci	struct musb *musb = controller->controller.musb;
57862306a36Sopenharmony_ci	void __iomem *epio = cppi41_channel->hw_ep->regs;
57962306a36Sopenharmony_ci	int tdbit;
58062306a36Sopenharmony_ci	int ret;
58162306a36Sopenharmony_ci	unsigned is_tx;
58262306a36Sopenharmony_ci	u16 csr;
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	is_tx = cppi41_channel->is_tx;
58562306a36Sopenharmony_ci	trace_musb_cppi41_abort(cppi41_channel);
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	if (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)
58862306a36Sopenharmony_ci		return 0;
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	list_del_init(&cppi41_channel->tx_check);
59162306a36Sopenharmony_ci	if (is_tx) {
59262306a36Sopenharmony_ci		csr = musb_readw(epio, MUSB_TXCSR);
59362306a36Sopenharmony_ci		csr &= ~MUSB_TXCSR_DMAENAB;
59462306a36Sopenharmony_ci		musb_writew(epio, MUSB_TXCSR, csr);
59562306a36Sopenharmony_ci	} else {
59662306a36Sopenharmony_ci		cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE);
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci		/* delay to drain to cppi dma pipeline for isoch */
59962306a36Sopenharmony_ci		udelay(250);
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci		csr = musb_readw(epio, MUSB_RXCSR);
60262306a36Sopenharmony_ci		csr &= ~(MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_DMAENAB);
60362306a36Sopenharmony_ci		musb_writew(epio, MUSB_RXCSR, csr);
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci		/* wait to drain cppi dma pipe line */
60662306a36Sopenharmony_ci		udelay(50);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci		csr = musb_readw(epio, MUSB_RXCSR);
60962306a36Sopenharmony_ci		if (csr & MUSB_RXCSR_RXPKTRDY) {
61062306a36Sopenharmony_ci			csr |= MUSB_RXCSR_FLUSHFIFO;
61162306a36Sopenharmony_ci			musb_writew(epio, MUSB_RXCSR, csr);
61262306a36Sopenharmony_ci			musb_writew(epio, MUSB_RXCSR, csr);
61362306a36Sopenharmony_ci		}
61462306a36Sopenharmony_ci	}
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	/* DA8xx Advisory 2.3.27: wait 250 ms before to start the teardown */
61762306a36Sopenharmony_ci	if (musb->ops->quirks & MUSB_DA8XX)
61862306a36Sopenharmony_ci		mdelay(250);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	tdbit = 1 << cppi41_channel->port_num;
62162306a36Sopenharmony_ci	if (is_tx)
62262306a36Sopenharmony_ci		tdbit <<= 16;
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	do {
62562306a36Sopenharmony_ci		if (is_tx)
62662306a36Sopenharmony_ci			musb_writel(musb->ctrl_base, controller->tdown_reg,
62762306a36Sopenharmony_ci				    tdbit);
62862306a36Sopenharmony_ci		ret = dmaengine_terminate_all(cppi41_channel->dc);
62962306a36Sopenharmony_ci	} while (ret == -EAGAIN);
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	if (is_tx) {
63262306a36Sopenharmony_ci		musb_writel(musb->ctrl_base, controller->tdown_reg, tdbit);
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci		csr = musb_readw(epio, MUSB_TXCSR);
63562306a36Sopenharmony_ci		if (csr & MUSB_TXCSR_TXPKTRDY) {
63662306a36Sopenharmony_ci			csr |= MUSB_TXCSR_FLUSHFIFO;
63762306a36Sopenharmony_ci			musb_writew(epio, MUSB_TXCSR, csr);
63862306a36Sopenharmony_ci		}
63962306a36Sopenharmony_ci	}
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
64262306a36Sopenharmony_ci	return 0;
64362306a36Sopenharmony_ci}
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_cistatic void cppi41_release_all_dma_chans(struct cppi41_dma_controller *ctrl)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	struct dma_chan *dc;
64862306a36Sopenharmony_ci	int i;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	for (i = 0; i < ctrl->num_channels; i++) {
65162306a36Sopenharmony_ci		dc = ctrl->tx_channel[i].dc;
65262306a36Sopenharmony_ci		if (dc)
65362306a36Sopenharmony_ci			dma_release_channel(dc);
65462306a36Sopenharmony_ci		dc = ctrl->rx_channel[i].dc;
65562306a36Sopenharmony_ci		if (dc)
65662306a36Sopenharmony_ci			dma_release_channel(dc);
65762306a36Sopenharmony_ci	}
65862306a36Sopenharmony_ci}
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_cistatic void cppi41_dma_controller_stop(struct cppi41_dma_controller *controller)
66162306a36Sopenharmony_ci{
66262306a36Sopenharmony_ci	cppi41_release_all_dma_chans(controller);
66362306a36Sopenharmony_ci}
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_cistatic int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	struct musb *musb = controller->controller.musb;
66862306a36Sopenharmony_ci	struct device *dev = musb->controller;
66962306a36Sopenharmony_ci	struct device_node *np = dev->parent->of_node;
67062306a36Sopenharmony_ci	struct cppi41_dma_channel *cppi41_channel;
67162306a36Sopenharmony_ci	int count;
67262306a36Sopenharmony_ci	int i;
67362306a36Sopenharmony_ci	int ret;
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	count = of_property_count_strings(np, "dma-names");
67662306a36Sopenharmony_ci	if (count < 0)
67762306a36Sopenharmony_ci		return count;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	for (i = 0; i < count; i++) {
68062306a36Sopenharmony_ci		struct dma_chan *dc;
68162306a36Sopenharmony_ci		struct dma_channel *musb_dma;
68262306a36Sopenharmony_ci		const char *str;
68362306a36Sopenharmony_ci		unsigned is_tx;
68462306a36Sopenharmony_ci		unsigned int port;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci		ret = of_property_read_string_index(np, "dma-names", i, &str);
68762306a36Sopenharmony_ci		if (ret)
68862306a36Sopenharmony_ci			goto err;
68962306a36Sopenharmony_ci		if (strstarts(str, "tx"))
69062306a36Sopenharmony_ci			is_tx = 1;
69162306a36Sopenharmony_ci		else if (strstarts(str, "rx"))
69262306a36Sopenharmony_ci			is_tx = 0;
69362306a36Sopenharmony_ci		else {
69462306a36Sopenharmony_ci			dev_err(dev, "Wrong dmatype %s\n", str);
69562306a36Sopenharmony_ci			goto err;
69662306a36Sopenharmony_ci		}
69762306a36Sopenharmony_ci		ret = kstrtouint(str + 2, 0, &port);
69862306a36Sopenharmony_ci		if (ret)
69962306a36Sopenharmony_ci			goto err;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci		ret = -EINVAL;
70262306a36Sopenharmony_ci		if (port > controller->num_channels || !port)
70362306a36Sopenharmony_ci			goto err;
70462306a36Sopenharmony_ci		if (is_tx)
70562306a36Sopenharmony_ci			cppi41_channel = &controller->tx_channel[port - 1];
70662306a36Sopenharmony_ci		else
70762306a36Sopenharmony_ci			cppi41_channel = &controller->rx_channel[port - 1];
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci		cppi41_channel->controller = controller;
71062306a36Sopenharmony_ci		cppi41_channel->port_num = port;
71162306a36Sopenharmony_ci		cppi41_channel->is_tx = is_tx;
71262306a36Sopenharmony_ci		INIT_LIST_HEAD(&cppi41_channel->tx_check);
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci		musb_dma = &cppi41_channel->channel;
71562306a36Sopenharmony_ci		musb_dma->private_data = cppi41_channel;
71662306a36Sopenharmony_ci		musb_dma->status = MUSB_DMA_STATUS_FREE;
71762306a36Sopenharmony_ci		musb_dma->max_len = SZ_4M;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci		dc = dma_request_chan(dev->parent, str);
72062306a36Sopenharmony_ci		if (IS_ERR(dc)) {
72162306a36Sopenharmony_ci			ret = dev_err_probe(dev, PTR_ERR(dc),
72262306a36Sopenharmony_ci					    "Failed to request %s.\n", str);
72362306a36Sopenharmony_ci			goto err;
72462306a36Sopenharmony_ci		}
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci		cppi41_channel->dc = dc;
72762306a36Sopenharmony_ci	}
72862306a36Sopenharmony_ci	return 0;
72962306a36Sopenharmony_cierr:
73062306a36Sopenharmony_ci	cppi41_release_all_dma_chans(controller);
73162306a36Sopenharmony_ci	return ret;
73262306a36Sopenharmony_ci}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_civoid cppi41_dma_controller_destroy(struct dma_controller *c)
73562306a36Sopenharmony_ci{
73662306a36Sopenharmony_ci	struct cppi41_dma_controller *controller = container_of(c,
73762306a36Sopenharmony_ci			struct cppi41_dma_controller, controller);
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	hrtimer_cancel(&controller->early_tx);
74062306a36Sopenharmony_ci	cppi41_dma_controller_stop(controller);
74162306a36Sopenharmony_ci	kfree(controller->rx_channel);
74262306a36Sopenharmony_ci	kfree(controller->tx_channel);
74362306a36Sopenharmony_ci	kfree(controller);
74462306a36Sopenharmony_ci}
74562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cppi41_dma_controller_destroy);
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_cistruct dma_controller *
74862306a36Sopenharmony_cicppi41_dma_controller_create(struct musb *musb, void __iomem *base)
74962306a36Sopenharmony_ci{
75062306a36Sopenharmony_ci	struct cppi41_dma_controller *controller;
75162306a36Sopenharmony_ci	int channel_size;
75262306a36Sopenharmony_ci	int ret = 0;
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	if (!musb->controller->parent->of_node) {
75562306a36Sopenharmony_ci		dev_err(musb->controller, "Need DT for the DMA engine.\n");
75662306a36Sopenharmony_ci		return NULL;
75762306a36Sopenharmony_ci	}
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	controller = kzalloc(sizeof(*controller), GFP_KERNEL);
76062306a36Sopenharmony_ci	if (!controller)
76162306a36Sopenharmony_ci		goto kzalloc_fail;
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	hrtimer_init(&controller->early_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
76462306a36Sopenharmony_ci	controller->early_tx.function = cppi41_recheck_tx_req;
76562306a36Sopenharmony_ci	INIT_LIST_HEAD(&controller->early_tx_list);
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci	controller->controller.channel_alloc = cppi41_dma_channel_allocate;
76862306a36Sopenharmony_ci	controller->controller.channel_release = cppi41_dma_channel_release;
76962306a36Sopenharmony_ci	controller->controller.channel_program = cppi41_dma_channel_program;
77062306a36Sopenharmony_ci	controller->controller.channel_abort = cppi41_dma_channel_abort;
77162306a36Sopenharmony_ci	controller->controller.is_compatible = cppi41_is_compatible;
77262306a36Sopenharmony_ci	controller->controller.musb = musb;
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	if (musb->ops->quirks & MUSB_DA8XX) {
77562306a36Sopenharmony_ci		controller->tdown_reg = DA8XX_USB_TEARDOWN;
77662306a36Sopenharmony_ci		controller->autoreq_reg = DA8XX_USB_AUTOREQ;
77762306a36Sopenharmony_ci		controller->set_dma_mode = da8xx_set_dma_mode;
77862306a36Sopenharmony_ci		controller->num_channels = DA8XX_DMA_NUM_CHANNELS;
77962306a36Sopenharmony_ci	} else {
78062306a36Sopenharmony_ci		controller->tdown_reg = USB_TDOWN;
78162306a36Sopenharmony_ci		controller->autoreq_reg = USB_CTRL_AUTOREQ;
78262306a36Sopenharmony_ci		controller->set_dma_mode = cppi41_set_dma_mode;
78362306a36Sopenharmony_ci		controller->num_channels = MUSB_DMA_NUM_CHANNELS;
78462306a36Sopenharmony_ci	}
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	channel_size = controller->num_channels *
78762306a36Sopenharmony_ci			sizeof(struct cppi41_dma_channel);
78862306a36Sopenharmony_ci	controller->rx_channel = kzalloc(channel_size, GFP_KERNEL);
78962306a36Sopenharmony_ci	if (!controller->rx_channel)
79062306a36Sopenharmony_ci		goto rx_channel_alloc_fail;
79162306a36Sopenharmony_ci	controller->tx_channel = kzalloc(channel_size, GFP_KERNEL);
79262306a36Sopenharmony_ci	if (!controller->tx_channel)
79362306a36Sopenharmony_ci		goto tx_channel_alloc_fail;
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	ret = cppi41_dma_controller_start(controller);
79662306a36Sopenharmony_ci	if (ret)
79762306a36Sopenharmony_ci		goto plat_get_fail;
79862306a36Sopenharmony_ci	return &controller->controller;
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ciplat_get_fail:
80162306a36Sopenharmony_ci	kfree(controller->tx_channel);
80262306a36Sopenharmony_citx_channel_alloc_fail:
80362306a36Sopenharmony_ci	kfree(controller->rx_channel);
80462306a36Sopenharmony_cirx_channel_alloc_fail:
80562306a36Sopenharmony_ci	kfree(controller);
80662306a36Sopenharmony_cikzalloc_fail:
80762306a36Sopenharmony_ci	if (ret == -EPROBE_DEFER)
80862306a36Sopenharmony_ci		return ERR_PTR(ret);
80962306a36Sopenharmony_ci	return NULL;
81062306a36Sopenharmony_ci}
81162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cppi41_dma_controller_create);
812