162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Renesas USB3.0 Peripheral driver (USB gadget)
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2015-2017  Renesas Electronics Corporation
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/debugfs.h>
962306a36Sopenharmony_ci#include <linux/delay.h>
1062306a36Sopenharmony_ci#include <linux/device.h>
1162306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1262306a36Sopenharmony_ci#include <linux/err.h>
1362306a36Sopenharmony_ci#include <linux/extcon-provider.h>
1462306a36Sopenharmony_ci#include <linux/interrupt.h>
1562306a36Sopenharmony_ci#include <linux/io.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <linux/of.h>
1862306a36Sopenharmony_ci#include <linux/phy/phy.h>
1962306a36Sopenharmony_ci#include <linux/platform_device.h>
2062306a36Sopenharmony_ci#include <linux/pm_runtime.h>
2162306a36Sopenharmony_ci#include <linux/reset.h>
2262306a36Sopenharmony_ci#include <linux/sizes.h>
2362306a36Sopenharmony_ci#include <linux/slab.h>
2462306a36Sopenharmony_ci#include <linux/string.h>
2562306a36Sopenharmony_ci#include <linux/uaccess.h>
2662306a36Sopenharmony_ci#include <linux/usb/ch9.h>
2762306a36Sopenharmony_ci#include <linux/usb/gadget.h>
2862306a36Sopenharmony_ci#include <linux/usb/of.h>
2962306a36Sopenharmony_ci#include <linux/usb/role.h>
3062306a36Sopenharmony_ci#include <linux/usb/rzv2m_usb3drd.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/* register definitions */
3362306a36Sopenharmony_ci#define USB3_AXI_INT_STA	0x008
3462306a36Sopenharmony_ci#define USB3_AXI_INT_ENA	0x00c
3562306a36Sopenharmony_ci#define USB3_DMA_INT_STA	0x010
3662306a36Sopenharmony_ci#define USB3_DMA_INT_ENA	0x014
3762306a36Sopenharmony_ci#define USB3_DMA_CH0_CON(n)	(0x030 + ((n) - 1) * 0x10) /* n = 1 to 4 */
3862306a36Sopenharmony_ci#define USB3_DMA_CH0_PRD_ADR(n)	(0x034 + ((n) - 1) * 0x10) /* n = 1 to 4 */
3962306a36Sopenharmony_ci#define USB3_USB_COM_CON	0x200
4062306a36Sopenharmony_ci#define USB3_USB20_CON		0x204
4162306a36Sopenharmony_ci#define USB3_USB30_CON		0x208
4262306a36Sopenharmony_ci#define USB3_USB_STA		0x210
4362306a36Sopenharmony_ci#define USB3_DRD_CON(p)		((p)->is_rzv2m ? 0x400 : 0x218)
4462306a36Sopenharmony_ci#define USB3_USB_INT_STA_1	0x220
4562306a36Sopenharmony_ci#define USB3_USB_INT_STA_2	0x224
4662306a36Sopenharmony_ci#define USB3_USB_INT_ENA_1	0x228
4762306a36Sopenharmony_ci#define USB3_USB_INT_ENA_2	0x22c
4862306a36Sopenharmony_ci#define USB3_STUP_DAT_0		0x230
4962306a36Sopenharmony_ci#define USB3_STUP_DAT_1		0x234
5062306a36Sopenharmony_ci#define USB3_USB_OTG_STA(p)	((p)->is_rzv2m ? 0x410 : 0x268)
5162306a36Sopenharmony_ci#define USB3_USB_OTG_INT_STA(p)	((p)->is_rzv2m ? 0x414 : 0x26c)
5262306a36Sopenharmony_ci#define USB3_USB_OTG_INT_ENA(p)	((p)->is_rzv2m ? 0x418 : 0x270)
5362306a36Sopenharmony_ci#define USB3_P0_MOD		0x280
5462306a36Sopenharmony_ci#define USB3_P0_CON		0x288
5562306a36Sopenharmony_ci#define USB3_P0_STA		0x28c
5662306a36Sopenharmony_ci#define USB3_P0_INT_STA		0x290
5762306a36Sopenharmony_ci#define USB3_P0_INT_ENA		0x294
5862306a36Sopenharmony_ci#define USB3_P0_LNG		0x2a0
5962306a36Sopenharmony_ci#define USB3_P0_READ		0x2a4
6062306a36Sopenharmony_ci#define USB3_P0_WRITE		0x2a8
6162306a36Sopenharmony_ci#define USB3_PIPE_COM		0x2b0
6262306a36Sopenharmony_ci#define USB3_PN_MOD		0x2c0
6362306a36Sopenharmony_ci#define USB3_PN_RAMMAP		0x2c4
6462306a36Sopenharmony_ci#define USB3_PN_CON		0x2c8
6562306a36Sopenharmony_ci#define USB3_PN_STA		0x2cc
6662306a36Sopenharmony_ci#define USB3_PN_INT_STA		0x2d0
6762306a36Sopenharmony_ci#define USB3_PN_INT_ENA		0x2d4
6862306a36Sopenharmony_ci#define USB3_PN_LNG		0x2e0
6962306a36Sopenharmony_ci#define USB3_PN_READ		0x2e4
7062306a36Sopenharmony_ci#define USB3_PN_WRITE		0x2e8
7162306a36Sopenharmony_ci#define USB3_SSIFCMD		0x340
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* AXI_INT_ENA and AXI_INT_STA */
7462306a36Sopenharmony_ci#define AXI_INT_DMAINT		BIT(31)
7562306a36Sopenharmony_ci#define AXI_INT_EPCINT		BIT(30)
7662306a36Sopenharmony_ci/* PRD's n = from 1 to 4 */
7762306a36Sopenharmony_ci#define AXI_INT_PRDEN_CLR_STA_SHIFT(n)	(16 + (n) - 1)
7862306a36Sopenharmony_ci#define AXI_INT_PRDERR_STA_SHIFT(n)	(0 + (n) - 1)
7962306a36Sopenharmony_ci#define AXI_INT_PRDEN_CLR_STA(n)	(1 << AXI_INT_PRDEN_CLR_STA_SHIFT(n))
8062306a36Sopenharmony_ci#define AXI_INT_PRDERR_STA(n)		(1 << AXI_INT_PRDERR_STA_SHIFT(n))
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/* DMA_INT_ENA and DMA_INT_STA */
8362306a36Sopenharmony_ci#define DMA_INT(n)		BIT(n)
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci/* DMA_CH0_CONn */
8662306a36Sopenharmony_ci#define DMA_CON_PIPE_DIR	BIT(15)		/* 1: In Transfer */
8762306a36Sopenharmony_ci#define DMA_CON_PIPE_NO_SHIFT	8
8862306a36Sopenharmony_ci#define DMA_CON_PIPE_NO_MASK	GENMASK(12, DMA_CON_PIPE_NO_SHIFT)
8962306a36Sopenharmony_ci#define DMA_COM_PIPE_NO(n)	(((n) << DMA_CON_PIPE_NO_SHIFT) & \
9062306a36Sopenharmony_ci					 DMA_CON_PIPE_NO_MASK)
9162306a36Sopenharmony_ci#define DMA_CON_PRD_EN		BIT(0)
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci/* LCLKSEL */
9462306a36Sopenharmony_ci#define LCLKSEL_LSEL		BIT(18)
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* USB_COM_CON */
9762306a36Sopenharmony_ci#define USB_COM_CON_CONF		BIT(24)
9862306a36Sopenharmony_ci#define USB_COM_CON_PN_WDATAIF_NL	BIT(23)
9962306a36Sopenharmony_ci#define USB_COM_CON_PN_RDATAIF_NL	BIT(22)
10062306a36Sopenharmony_ci#define USB_COM_CON_PN_LSTTR_PP		BIT(21)
10162306a36Sopenharmony_ci#define USB_COM_CON_SPD_MODE		BIT(17)
10262306a36Sopenharmony_ci#define USB_COM_CON_EP0_EN		BIT(16)
10362306a36Sopenharmony_ci#define USB_COM_CON_DEV_ADDR_SHIFT	8
10462306a36Sopenharmony_ci#define USB_COM_CON_DEV_ADDR_MASK	GENMASK(14, USB_COM_CON_DEV_ADDR_SHIFT)
10562306a36Sopenharmony_ci#define USB_COM_CON_DEV_ADDR(n)		(((n) << USB_COM_CON_DEV_ADDR_SHIFT) & \
10662306a36Sopenharmony_ci					 USB_COM_CON_DEV_ADDR_MASK)
10762306a36Sopenharmony_ci#define USB_COM_CON_RX_DETECTION	BIT(1)
10862306a36Sopenharmony_ci#define USB_COM_CON_PIPE_CLR		BIT(0)
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci/* USB20_CON */
11162306a36Sopenharmony_ci#define USB20_CON_B2_PUE		BIT(31)
11262306a36Sopenharmony_ci#define USB20_CON_B2_SUSPEND		BIT(24)
11362306a36Sopenharmony_ci#define USB20_CON_B2_CONNECT		BIT(17)
11462306a36Sopenharmony_ci#define USB20_CON_B2_TSTMOD_SHIFT	8
11562306a36Sopenharmony_ci#define USB20_CON_B2_TSTMOD_MASK	GENMASK(10, USB20_CON_B2_TSTMOD_SHIFT)
11662306a36Sopenharmony_ci#define USB20_CON_B2_TSTMOD(n)		(((n) << USB20_CON_B2_TSTMOD_SHIFT) & \
11762306a36Sopenharmony_ci					 USB20_CON_B2_TSTMOD_MASK)
11862306a36Sopenharmony_ci#define USB20_CON_B2_TSTMOD_EN		BIT(0)
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/* USB30_CON */
12162306a36Sopenharmony_ci#define USB30_CON_POW_SEL_SHIFT		24
12262306a36Sopenharmony_ci#define USB30_CON_POW_SEL_MASK		GENMASK(26, USB30_CON_POW_SEL_SHIFT)
12362306a36Sopenharmony_ci#define USB30_CON_POW_SEL_IN_U3		BIT(26)
12462306a36Sopenharmony_ci#define USB30_CON_POW_SEL_IN_DISCON	0
12562306a36Sopenharmony_ci#define USB30_CON_POW_SEL_P2_TO_P0	BIT(25)
12662306a36Sopenharmony_ci#define USB30_CON_POW_SEL_P0_TO_P3	BIT(24)
12762306a36Sopenharmony_ci#define USB30_CON_POW_SEL_P0_TO_P2	0
12862306a36Sopenharmony_ci#define USB30_CON_B3_PLLWAKE		BIT(23)
12962306a36Sopenharmony_ci#define USB30_CON_B3_CONNECT		BIT(17)
13062306a36Sopenharmony_ci#define USB30_CON_B3_HOTRST_CMP		BIT(1)
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci/* USB_STA */
13362306a36Sopenharmony_ci#define USB_STA_SPEED_MASK	(BIT(2) | BIT(1))
13462306a36Sopenharmony_ci#define USB_STA_SPEED_HS	BIT(2)
13562306a36Sopenharmony_ci#define USB_STA_SPEED_FS	BIT(1)
13662306a36Sopenharmony_ci#define USB_STA_SPEED_SS	0
13762306a36Sopenharmony_ci#define USB_STA_VBUS_STA	BIT(0)
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci/* DRD_CON */
14062306a36Sopenharmony_ci#define DRD_CON_PERI_RST	BIT(31)		/* rzv2m only */
14162306a36Sopenharmony_ci#define DRD_CON_HOST_RST	BIT(30)		/* rzv2m only */
14262306a36Sopenharmony_ci#define DRD_CON_PERI_CON	BIT(24)
14362306a36Sopenharmony_ci#define DRD_CON_VBOUT		BIT(0)
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/* USB_INT_ENA_1 and USB_INT_STA_1 */
14662306a36Sopenharmony_ci#define USB_INT_1_B3_PLLWKUP	BIT(31)
14762306a36Sopenharmony_ci#define USB_INT_1_B3_LUPSUCS	BIT(30)
14862306a36Sopenharmony_ci#define USB_INT_1_B3_DISABLE	BIT(27)
14962306a36Sopenharmony_ci#define USB_INT_1_B3_WRMRST	BIT(21)
15062306a36Sopenharmony_ci#define USB_INT_1_B3_HOTRST	BIT(20)
15162306a36Sopenharmony_ci#define USB_INT_1_B2_USBRST	BIT(12)
15262306a36Sopenharmony_ci#define USB_INT_1_B2_L1SPND	BIT(11)
15362306a36Sopenharmony_ci#define USB_INT_1_B2_SPND	BIT(9)
15462306a36Sopenharmony_ci#define USB_INT_1_B2_RSUM	BIT(8)
15562306a36Sopenharmony_ci#define USB_INT_1_SPEED		BIT(1)
15662306a36Sopenharmony_ci#define USB_INT_1_VBUS_CNG	BIT(0)
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci/* USB_INT_ENA_2 and USB_INT_STA_2 */
15962306a36Sopenharmony_ci#define USB_INT_2_PIPE(n)	BIT(n)
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci/* USB_OTG_STA, USB_OTG_INT_STA and USB_OTG_INT_ENA */
16262306a36Sopenharmony_ci#define USB_OTG_IDMON(p)	((p)->is_rzv2m ? BIT(0) : BIT(4))
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci/* P0_MOD */
16562306a36Sopenharmony_ci#define P0_MOD_DIR		BIT(6)
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci/* P0_CON and PN_CON */
16862306a36Sopenharmony_ci#define PX_CON_BYTE_EN_MASK		(BIT(10) | BIT(9))
16962306a36Sopenharmony_ci#define PX_CON_BYTE_EN_SHIFT		9
17062306a36Sopenharmony_ci#define PX_CON_BYTE_EN_BYTES(n)		(((n) << PX_CON_BYTE_EN_SHIFT) & \
17162306a36Sopenharmony_ci					 PX_CON_BYTE_EN_MASK)
17262306a36Sopenharmony_ci#define PX_CON_SEND			BIT(8)
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/* P0_CON */
17562306a36Sopenharmony_ci#define P0_CON_ST_RES_MASK		(BIT(27) | BIT(26))
17662306a36Sopenharmony_ci#define P0_CON_ST_RES_FORCE_STALL	BIT(27)
17762306a36Sopenharmony_ci#define P0_CON_ST_RES_NORMAL		BIT(26)
17862306a36Sopenharmony_ci#define P0_CON_ST_RES_FORCE_NRDY	0
17962306a36Sopenharmony_ci#define P0_CON_OT_RES_MASK		(BIT(25) | BIT(24))
18062306a36Sopenharmony_ci#define P0_CON_OT_RES_FORCE_STALL	BIT(25)
18162306a36Sopenharmony_ci#define P0_CON_OT_RES_NORMAL		BIT(24)
18262306a36Sopenharmony_ci#define P0_CON_OT_RES_FORCE_NRDY	0
18362306a36Sopenharmony_ci#define P0_CON_IN_RES_MASK		(BIT(17) | BIT(16))
18462306a36Sopenharmony_ci#define P0_CON_IN_RES_FORCE_STALL	BIT(17)
18562306a36Sopenharmony_ci#define P0_CON_IN_RES_NORMAL		BIT(16)
18662306a36Sopenharmony_ci#define P0_CON_IN_RES_FORCE_NRDY	0
18762306a36Sopenharmony_ci#define P0_CON_RES_WEN			BIT(7)
18862306a36Sopenharmony_ci#define P0_CON_BCLR			BIT(1)
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci/* P0_STA and PN_STA */
19162306a36Sopenharmony_ci#define PX_STA_BUFSTS		BIT(0)
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci/* P0_INT_ENA and P0_INT_STA */
19462306a36Sopenharmony_ci#define P0_INT_STSED		BIT(18)
19562306a36Sopenharmony_ci#define P0_INT_STSST		BIT(17)
19662306a36Sopenharmony_ci#define P0_INT_SETUP		BIT(16)
19762306a36Sopenharmony_ci#define P0_INT_RCVNL		BIT(8)
19862306a36Sopenharmony_ci#define P0_INT_ERDY		BIT(7)
19962306a36Sopenharmony_ci#define P0_INT_FLOW		BIT(6)
20062306a36Sopenharmony_ci#define P0_INT_STALL		BIT(2)
20162306a36Sopenharmony_ci#define P0_INT_NRDY		BIT(1)
20262306a36Sopenharmony_ci#define P0_INT_BFRDY		BIT(0)
20362306a36Sopenharmony_ci#define P0_INT_ALL_BITS		(P0_INT_STSED | P0_INT_SETUP | P0_INT_BFRDY)
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci/* PN_MOD */
20662306a36Sopenharmony_ci#define PN_MOD_DIR		BIT(6)
20762306a36Sopenharmony_ci#define PN_MOD_TYPE_SHIFT	4
20862306a36Sopenharmony_ci#define PN_MOD_TYPE_MASK	GENMASK(5, PN_MOD_TYPE_SHIFT)
20962306a36Sopenharmony_ci#define PN_MOD_TYPE(n)		(((n) << PN_MOD_TYPE_SHIFT) & \
21062306a36Sopenharmony_ci				 PN_MOD_TYPE_MASK)
21162306a36Sopenharmony_ci#define PN_MOD_EPNUM_MASK	GENMASK(3, 0)
21262306a36Sopenharmony_ci#define PN_MOD_EPNUM(n)		((n) & PN_MOD_EPNUM_MASK)
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci/* PN_RAMMAP */
21562306a36Sopenharmony_ci#define PN_RAMMAP_RAMAREA_SHIFT	29
21662306a36Sopenharmony_ci#define PN_RAMMAP_RAMAREA_MASK	GENMASK(31, PN_RAMMAP_RAMAREA_SHIFT)
21762306a36Sopenharmony_ci#define PN_RAMMAP_RAMAREA_16KB	BIT(31)
21862306a36Sopenharmony_ci#define PN_RAMMAP_RAMAREA_8KB	(BIT(30) | BIT(29))
21962306a36Sopenharmony_ci#define PN_RAMMAP_RAMAREA_4KB	BIT(30)
22062306a36Sopenharmony_ci#define PN_RAMMAP_RAMAREA_2KB	BIT(29)
22162306a36Sopenharmony_ci#define PN_RAMMAP_RAMAREA_1KB	0
22262306a36Sopenharmony_ci#define PN_RAMMAP_MPKT_SHIFT	16
22362306a36Sopenharmony_ci#define PN_RAMMAP_MPKT_MASK	GENMASK(26, PN_RAMMAP_MPKT_SHIFT)
22462306a36Sopenharmony_ci#define PN_RAMMAP_MPKT(n)	(((n) << PN_RAMMAP_MPKT_SHIFT) & \
22562306a36Sopenharmony_ci				 PN_RAMMAP_MPKT_MASK)
22662306a36Sopenharmony_ci#define PN_RAMMAP_RAMIF_SHIFT	14
22762306a36Sopenharmony_ci#define PN_RAMMAP_RAMIF_MASK	GENMASK(15, PN_RAMMAP_RAMIF_SHIFT)
22862306a36Sopenharmony_ci#define PN_RAMMAP_RAMIF(n)	(((n) << PN_RAMMAP_RAMIF_SHIFT) & \
22962306a36Sopenharmony_ci				 PN_RAMMAP_RAMIF_MASK)
23062306a36Sopenharmony_ci#define PN_RAMMAP_BASEAD_MASK	GENMASK(13, 0)
23162306a36Sopenharmony_ci#define PN_RAMMAP_BASEAD(offs)	(((offs) >> 3) & PN_RAMMAP_BASEAD_MASK)
23262306a36Sopenharmony_ci#define PN_RAMMAP_DATA(area, ramif, basead)	((PN_RAMMAP_##area) | \
23362306a36Sopenharmony_ci						 (PN_RAMMAP_RAMIF(ramif)) | \
23462306a36Sopenharmony_ci						 (PN_RAMMAP_BASEAD(basead)))
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci/* PN_CON */
23762306a36Sopenharmony_ci#define PN_CON_EN		BIT(31)
23862306a36Sopenharmony_ci#define PN_CON_DATAIF_EN	BIT(30)
23962306a36Sopenharmony_ci#define PN_CON_RES_MASK		(BIT(17) | BIT(16))
24062306a36Sopenharmony_ci#define PN_CON_RES_FORCE_STALL	BIT(17)
24162306a36Sopenharmony_ci#define PN_CON_RES_NORMAL	BIT(16)
24262306a36Sopenharmony_ci#define PN_CON_RES_FORCE_NRDY	0
24362306a36Sopenharmony_ci#define PN_CON_LAST		BIT(11)
24462306a36Sopenharmony_ci#define PN_CON_RES_WEN		BIT(7)
24562306a36Sopenharmony_ci#define PN_CON_CLR		BIT(0)
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci/* PN_INT_STA and PN_INT_ENA */
24862306a36Sopenharmony_ci#define PN_INT_LSTTR	BIT(4)
24962306a36Sopenharmony_ci#define PN_INT_BFRDY	BIT(0)
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci/* USB3_SSIFCMD */
25262306a36Sopenharmony_ci#define SSIFCMD_URES_U2		BIT(9)
25362306a36Sopenharmony_ci#define SSIFCMD_URES_U1		BIT(8)
25462306a36Sopenharmony_ci#define SSIFCMD_UDIR_U2		BIT(7)
25562306a36Sopenharmony_ci#define SSIFCMD_UDIR_U1		BIT(6)
25662306a36Sopenharmony_ci#define SSIFCMD_UREQ_U2		BIT(5)
25762306a36Sopenharmony_ci#define SSIFCMD_UREQ_U1		BIT(4)
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci#define USB3_EP0_SS_MAX_PACKET_SIZE	512
26062306a36Sopenharmony_ci#define USB3_EP0_HSFS_MAX_PACKET_SIZE	64
26162306a36Sopenharmony_ci#define USB3_EP0_BUF_SIZE		8
26262306a36Sopenharmony_ci#define USB3_MAX_NUM_PIPES(p)		((p)->is_rzv2m ? 16 : 6)	/* This includes PIPE 0 */
26362306a36Sopenharmony_ci#define USB3_WAIT_US			3
26462306a36Sopenharmony_ci#define USB3_DMA_NUM_SETTING_AREA	4
26562306a36Sopenharmony_ci/*
26662306a36Sopenharmony_ci * To avoid double-meaning of "0" (xferred 65536 bytes or received zlp if
26762306a36Sopenharmony_ci * buffer size is 65536), this driver uses the maximum size per a entry is
26862306a36Sopenharmony_ci * 32768 bytes.
26962306a36Sopenharmony_ci */
27062306a36Sopenharmony_ci#define USB3_DMA_MAX_XFER_SIZE		32768
27162306a36Sopenharmony_ci#define USB3_DMA_PRD_SIZE		4096
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistruct renesas_usb3;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci/* Physical Region Descriptor Table */
27662306a36Sopenharmony_cistruct renesas_usb3_prd {
27762306a36Sopenharmony_ci	u32 word1;
27862306a36Sopenharmony_ci#define USB3_PRD1_E		BIT(30)		/* the end of chain */
27962306a36Sopenharmony_ci#define USB3_PRD1_U		BIT(29)		/* completion of transfer */
28062306a36Sopenharmony_ci#define USB3_PRD1_D		BIT(28)		/* Error occurred */
28162306a36Sopenharmony_ci#define USB3_PRD1_INT		BIT(27)		/* Interrupt occurred */
28262306a36Sopenharmony_ci#define USB3_PRD1_LST		BIT(26)		/* Last Packet */
28362306a36Sopenharmony_ci#define USB3_PRD1_B_INC		BIT(24)
28462306a36Sopenharmony_ci#define USB3_PRD1_MPS_8		0
28562306a36Sopenharmony_ci#define USB3_PRD1_MPS_16	BIT(21)
28662306a36Sopenharmony_ci#define USB3_PRD1_MPS_32	BIT(22)
28762306a36Sopenharmony_ci#define USB3_PRD1_MPS_64	(BIT(22) | BIT(21))
28862306a36Sopenharmony_ci#define USB3_PRD1_MPS_512	BIT(23)
28962306a36Sopenharmony_ci#define USB3_PRD1_MPS_1024	(BIT(23) | BIT(21))
29062306a36Sopenharmony_ci#define USB3_PRD1_MPS_RESERVED	(BIT(23) | BIT(22) | BIT(21))
29162306a36Sopenharmony_ci#define USB3_PRD1_SIZE_MASK	GENMASK(15, 0)
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	u32 bap;
29462306a36Sopenharmony_ci};
29562306a36Sopenharmony_ci#define USB3_DMA_NUM_PRD_ENTRIES	(USB3_DMA_PRD_SIZE / \
29662306a36Sopenharmony_ci					  sizeof(struct renesas_usb3_prd))
29762306a36Sopenharmony_ci#define USB3_DMA_MAX_XFER_SIZE_ALL_PRDS	(USB3_DMA_PRD_SIZE / \
29862306a36Sopenharmony_ci					 sizeof(struct renesas_usb3_prd) * \
29962306a36Sopenharmony_ci					 USB3_DMA_MAX_XFER_SIZE)
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_cistruct renesas_usb3_dma {
30262306a36Sopenharmony_ci	struct renesas_usb3_prd *prd;
30362306a36Sopenharmony_ci	dma_addr_t prd_dma;
30462306a36Sopenharmony_ci	int num;	/* Setting area number (from 1 to 4) */
30562306a36Sopenharmony_ci	bool used;
30662306a36Sopenharmony_ci};
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistruct renesas_usb3_request {
30962306a36Sopenharmony_ci	struct usb_request	req;
31062306a36Sopenharmony_ci	struct list_head	queue;
31162306a36Sopenharmony_ci};
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci#define USB3_EP_NAME_SIZE	8
31462306a36Sopenharmony_cistruct renesas_usb3_ep {
31562306a36Sopenharmony_ci	struct usb_ep ep;
31662306a36Sopenharmony_ci	struct renesas_usb3 *usb3;
31762306a36Sopenharmony_ci	struct renesas_usb3_dma *dma;
31862306a36Sopenharmony_ci	int num;
31962306a36Sopenharmony_ci	char ep_name[USB3_EP_NAME_SIZE];
32062306a36Sopenharmony_ci	struct list_head queue;
32162306a36Sopenharmony_ci	u32 rammap_val;
32262306a36Sopenharmony_ci	bool dir_in;
32362306a36Sopenharmony_ci	bool halt;
32462306a36Sopenharmony_ci	bool wedge;
32562306a36Sopenharmony_ci	bool started;
32662306a36Sopenharmony_ci};
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistruct renesas_usb3_priv {
32962306a36Sopenharmony_ci	int ramsize_per_ramif;		/* unit = bytes */
33062306a36Sopenharmony_ci	int num_ramif;
33162306a36Sopenharmony_ci	int ramsize_per_pipe;		/* unit = bytes */
33262306a36Sopenharmony_ci	bool workaround_for_vbus;	/* if true, don't check vbus signal */
33362306a36Sopenharmony_ci	bool is_rzv2m;			/* if true, RZ/V2M SoC */
33462306a36Sopenharmony_ci};
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistruct renesas_usb3 {
33762306a36Sopenharmony_ci	void __iomem *reg;
33862306a36Sopenharmony_ci	void __iomem *drd_reg;
33962306a36Sopenharmony_ci	struct reset_control *usbp_rstc;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	struct usb_gadget gadget;
34262306a36Sopenharmony_ci	struct usb_gadget_driver *driver;
34362306a36Sopenharmony_ci	struct extcon_dev *extcon;
34462306a36Sopenharmony_ci	struct work_struct extcon_work;
34562306a36Sopenharmony_ci	struct phy *phy;
34662306a36Sopenharmony_ci	struct dentry *dentry;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	struct usb_role_switch *role_sw;
34962306a36Sopenharmony_ci	struct device *host_dev;
35062306a36Sopenharmony_ci	struct work_struct role_work;
35162306a36Sopenharmony_ci	enum usb_role role;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep;
35462306a36Sopenharmony_ci	int num_usb3_eps;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	struct renesas_usb3_dma dma[USB3_DMA_NUM_SETTING_AREA];
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	spinlock_t lock;
35962306a36Sopenharmony_ci	int disabled_count;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	struct usb_request *ep0_req;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	enum usb_role connection_state;
36462306a36Sopenharmony_ci	u16 test_mode;
36562306a36Sopenharmony_ci	u8 ep0_buf[USB3_EP0_BUF_SIZE];
36662306a36Sopenharmony_ci	bool softconnect;
36762306a36Sopenharmony_ci	bool workaround_for_vbus;
36862306a36Sopenharmony_ci	bool extcon_host;		/* check id and set EXTCON_USB_HOST */
36962306a36Sopenharmony_ci	bool extcon_usb;		/* check vbus and set EXTCON_USB */
37062306a36Sopenharmony_ci	bool forced_b_device;
37162306a36Sopenharmony_ci	bool start_to_connect;
37262306a36Sopenharmony_ci	bool role_sw_by_connector;
37362306a36Sopenharmony_ci	bool is_rzv2m;
37462306a36Sopenharmony_ci};
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci#define gadget_to_renesas_usb3(_gadget)	\
37762306a36Sopenharmony_ci		container_of(_gadget, struct renesas_usb3, gadget)
37862306a36Sopenharmony_ci#define renesas_usb3_to_gadget(renesas_usb3) (&renesas_usb3->gadget)
37962306a36Sopenharmony_ci#define usb3_to_dev(_usb3)	(_usb3->gadget.dev.parent)
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci#define usb_ep_to_usb3_ep(_ep) container_of(_ep, struct renesas_usb3_ep, ep)
38262306a36Sopenharmony_ci#define usb3_ep_to_usb3(_usb3_ep) (_usb3_ep->usb3)
38362306a36Sopenharmony_ci#define usb_req_to_usb3_req(_req) container_of(_req, \
38462306a36Sopenharmony_ci					    struct renesas_usb3_request, req)
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci#define usb3_get_ep(usb3, n) ((usb3)->usb3_ep + (n))
38762306a36Sopenharmony_ci#define usb3_for_each_ep(usb3_ep, usb3, i)			\
38862306a36Sopenharmony_ci		for ((i) = 0, usb3_ep = usb3_get_ep(usb3, (i));	\
38962306a36Sopenharmony_ci		     (i) < (usb3)->num_usb3_eps;		\
39062306a36Sopenharmony_ci		     (i)++, usb3_ep = usb3_get_ep(usb3, (i)))
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci#define usb3_get_dma(usb3, i)	(&(usb3)->dma[i])
39362306a36Sopenharmony_ci#define usb3_for_each_dma(usb3, dma, i)				\
39462306a36Sopenharmony_ci		for ((i) = 0, dma = usb3_get_dma((usb3), (i));	\
39562306a36Sopenharmony_ci		     (i) < USB3_DMA_NUM_SETTING_AREA;		\
39662306a36Sopenharmony_ci		     (i)++, dma = usb3_get_dma((usb3), (i)))
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cistatic const char udc_name[] = "renesas_usb3";
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_cistatic bool use_dma = 1;
40162306a36Sopenharmony_cimodule_param(use_dma, bool, 0644);
40262306a36Sopenharmony_ciMODULE_PARM_DESC(use_dma, "use dedicated DMAC");
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic void usb3_write(struct renesas_usb3 *usb3, u32 data, u32 offs)
40562306a36Sopenharmony_ci{
40662306a36Sopenharmony_ci	iowrite32(data, usb3->reg + offs);
40762306a36Sopenharmony_ci}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_cistatic u32 usb3_read(struct renesas_usb3 *usb3, u32 offs)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	return ioread32(usb3->reg + offs);
41262306a36Sopenharmony_ci}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_cistatic void usb3_set_bit(struct renesas_usb3 *usb3, u32 bits, u32 offs)
41562306a36Sopenharmony_ci{
41662306a36Sopenharmony_ci	u32 val = usb3_read(usb3, offs);
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	val |= bits;
41962306a36Sopenharmony_ci	usb3_write(usb3, val, offs);
42062306a36Sopenharmony_ci}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_cistatic void usb3_clear_bit(struct renesas_usb3 *usb3, u32 bits, u32 offs)
42362306a36Sopenharmony_ci{
42462306a36Sopenharmony_ci	u32 val = usb3_read(usb3, offs);
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	val &= ~bits;
42762306a36Sopenharmony_ci	usb3_write(usb3, val, offs);
42862306a36Sopenharmony_ci}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_cistatic void usb3_drd_write(struct renesas_usb3 *usb3, u32 data, u32 offs)
43162306a36Sopenharmony_ci{
43262306a36Sopenharmony_ci	void __iomem *reg;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	if (usb3->is_rzv2m)
43562306a36Sopenharmony_ci		reg = usb3->drd_reg + offs - USB3_DRD_CON(usb3);
43662306a36Sopenharmony_ci	else
43762306a36Sopenharmony_ci		reg = usb3->reg + offs;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	iowrite32(data, reg);
44062306a36Sopenharmony_ci}
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_cistatic u32 usb3_drd_read(struct renesas_usb3 *usb3, u32 offs)
44362306a36Sopenharmony_ci{
44462306a36Sopenharmony_ci	void __iomem *reg;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	if (usb3->is_rzv2m)
44762306a36Sopenharmony_ci		reg = usb3->drd_reg + offs - USB3_DRD_CON(usb3);
44862306a36Sopenharmony_ci	else
44962306a36Sopenharmony_ci		reg = usb3->reg + offs;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	return ioread32(reg);
45262306a36Sopenharmony_ci}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_cistatic void usb3_drd_set_bit(struct renesas_usb3 *usb3, u32 bits, u32 offs)
45562306a36Sopenharmony_ci{
45662306a36Sopenharmony_ci	u32 val = usb3_drd_read(usb3, offs);
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	val |= bits;
45962306a36Sopenharmony_ci	usb3_drd_write(usb3, val, offs);
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cistatic void usb3_drd_clear_bit(struct renesas_usb3 *usb3, u32 bits, u32 offs)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	u32 val = usb3_drd_read(usb3, offs);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	val &= ~bits;
46762306a36Sopenharmony_ci	usb3_drd_write(usb3, val, offs);
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_cistatic int usb3_wait(struct renesas_usb3 *usb3, u32 reg, u32 mask,
47162306a36Sopenharmony_ci		     u32 expected)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	int i;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	for (i = 0; i < USB3_WAIT_US; i++) {
47662306a36Sopenharmony_ci		if ((usb3_read(usb3, reg) & mask) == expected)
47762306a36Sopenharmony_ci			return 0;
47862306a36Sopenharmony_ci		udelay(1);
47962306a36Sopenharmony_ci	}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	dev_dbg(usb3_to_dev(usb3), "%s: timed out (%8x, %08x, %08x)\n",
48262306a36Sopenharmony_ci		__func__, reg, mask, expected);
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	return -EBUSY;
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic void renesas_usb3_extcon_work(struct work_struct *work)
48862306a36Sopenharmony_ci{
48962306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = container_of(work, struct renesas_usb3,
49062306a36Sopenharmony_ci						 extcon_work);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	extcon_set_state_sync(usb3->extcon, EXTCON_USB_HOST, usb3->extcon_host);
49362306a36Sopenharmony_ci	extcon_set_state_sync(usb3->extcon, EXTCON_USB, usb3->extcon_usb);
49462306a36Sopenharmony_ci}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_cistatic void usb3_enable_irq_1(struct renesas_usb3 *usb3, u32 bits)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci	usb3_set_bit(usb3, bits, USB3_USB_INT_ENA_1);
49962306a36Sopenharmony_ci}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_cistatic void usb3_disable_irq_1(struct renesas_usb3 *usb3, u32 bits)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	usb3_clear_bit(usb3, bits, USB3_USB_INT_ENA_1);
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_cistatic void usb3_enable_pipe_irq(struct renesas_usb3 *usb3, int num)
50762306a36Sopenharmony_ci{
50862306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2);
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_cistatic void usb3_disable_pipe_irq(struct renesas_usb3 *usb3, int num)
51262306a36Sopenharmony_ci{
51362306a36Sopenharmony_ci	usb3_clear_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2);
51462306a36Sopenharmony_ci}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_cistatic bool usb3_is_host(struct renesas_usb3 *usb3)
51762306a36Sopenharmony_ci{
51862306a36Sopenharmony_ci	return !(usb3_drd_read(usb3, USB3_DRD_CON(usb3)) & DRD_CON_PERI_CON);
51962306a36Sopenharmony_ci}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_cistatic void usb3_init_axi_bridge(struct renesas_usb3 *usb3)
52262306a36Sopenharmony_ci{
52362306a36Sopenharmony_ci	/* Set AXI_INT */
52462306a36Sopenharmony_ci	usb3_write(usb3, ~0, USB3_DMA_INT_STA);
52562306a36Sopenharmony_ci	usb3_write(usb3, 0, USB3_DMA_INT_ENA);
52662306a36Sopenharmony_ci	usb3_set_bit(usb3, AXI_INT_DMAINT | AXI_INT_EPCINT, USB3_AXI_INT_ENA);
52762306a36Sopenharmony_ci}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_cistatic void usb3_init_epc_registers(struct renesas_usb3 *usb3)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	usb3_write(usb3, ~0, USB3_USB_INT_STA_1);
53262306a36Sopenharmony_ci	if (!usb3->workaround_for_vbus)
53362306a36Sopenharmony_ci		usb3_enable_irq_1(usb3, USB_INT_1_VBUS_CNG);
53462306a36Sopenharmony_ci}
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_cistatic bool usb3_wakeup_usb2_phy(struct renesas_usb3 *usb3)
53762306a36Sopenharmony_ci{
53862306a36Sopenharmony_ci	if (!(usb3_read(usb3, USB3_USB20_CON) & USB20_CON_B2_SUSPEND))
53962306a36Sopenharmony_ci		return true;	/* already waked it up */
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	usb3_clear_bit(usb3, USB20_CON_B2_SUSPEND, USB3_USB20_CON);
54262306a36Sopenharmony_ci	usb3_enable_irq_1(usb3, USB_INT_1_B2_RSUM);
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	return false;
54562306a36Sopenharmony_ci}
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_cistatic void usb3_usb2_pullup(struct renesas_usb3 *usb3, int pullup)
54862306a36Sopenharmony_ci{
54962306a36Sopenharmony_ci	u32 bits = USB20_CON_B2_PUE | USB20_CON_B2_CONNECT;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	if (usb3->softconnect && pullup)
55262306a36Sopenharmony_ci		usb3_set_bit(usb3, bits, USB3_USB20_CON);
55362306a36Sopenharmony_ci	else
55462306a36Sopenharmony_ci		usb3_clear_bit(usb3, bits, USB3_USB20_CON);
55562306a36Sopenharmony_ci}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_cistatic void usb3_set_test_mode(struct renesas_usb3 *usb3)
55862306a36Sopenharmony_ci{
55962306a36Sopenharmony_ci	u32 val = usb3_read(usb3, USB3_USB20_CON);
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	val &= ~USB20_CON_B2_TSTMOD_MASK;
56262306a36Sopenharmony_ci	val |= USB20_CON_B2_TSTMOD(usb3->test_mode);
56362306a36Sopenharmony_ci	usb3_write(usb3, val | USB20_CON_B2_TSTMOD_EN, USB3_USB20_CON);
56462306a36Sopenharmony_ci	if (!usb3->test_mode)
56562306a36Sopenharmony_ci		usb3_clear_bit(usb3, USB20_CON_B2_TSTMOD_EN, USB3_USB20_CON);
56662306a36Sopenharmony_ci}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_cistatic void usb3_start_usb2_connection(struct renesas_usb3 *usb3)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	usb3->disabled_count++;
57162306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON);
57262306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON);
57362306a36Sopenharmony_ci	usb3_usb2_pullup(usb3, 1);
57462306a36Sopenharmony_ci}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_cistatic int usb3_is_usb3_phy_in_u3(struct renesas_usb3 *usb3)
57762306a36Sopenharmony_ci{
57862306a36Sopenharmony_ci	return usb3_read(usb3, USB3_USB30_CON) & USB30_CON_POW_SEL_IN_U3;
57962306a36Sopenharmony_ci}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_cistatic bool usb3_wakeup_usb3_phy(struct renesas_usb3 *usb3)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	if (!usb3_is_usb3_phy_in_u3(usb3))
58462306a36Sopenharmony_ci		return true;	/* already waked it up */
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	usb3_set_bit(usb3, USB30_CON_B3_PLLWAKE, USB3_USB30_CON);
58762306a36Sopenharmony_ci	usb3_enable_irq_1(usb3, USB_INT_1_B3_PLLWKUP);
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	return false;
59062306a36Sopenharmony_ci}
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_cistatic u16 usb3_feature_get_un_enabled(struct renesas_usb3 *usb3)
59362306a36Sopenharmony_ci{
59462306a36Sopenharmony_ci	u32 mask_u2 = SSIFCMD_UDIR_U2 | SSIFCMD_UREQ_U2;
59562306a36Sopenharmony_ci	u32 mask_u1 = SSIFCMD_UDIR_U1 | SSIFCMD_UREQ_U1;
59662306a36Sopenharmony_ci	u32 val = usb3_read(usb3, USB3_SSIFCMD);
59762306a36Sopenharmony_ci	u16 ret = 0;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	/* Enables {U2,U1} if the bits of UDIR and UREQ are set to 0 */
60062306a36Sopenharmony_ci	if (!(val & mask_u2))
60162306a36Sopenharmony_ci		ret |= 1 << USB_DEV_STAT_U2_ENABLED;
60262306a36Sopenharmony_ci	if (!(val & mask_u1))
60362306a36Sopenharmony_ci		ret |= 1 << USB_DEV_STAT_U1_ENABLED;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	return ret;
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_cistatic void usb3_feature_u2_enable(struct renesas_usb3 *usb3, bool enable)
60962306a36Sopenharmony_ci{
61062306a36Sopenharmony_ci	u32 bits = SSIFCMD_UDIR_U2 | SSIFCMD_UREQ_U2;
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	/* Enables U2 if the bits of UDIR and UREQ are set to 0 */
61362306a36Sopenharmony_ci	if (enable)
61462306a36Sopenharmony_ci		usb3_clear_bit(usb3, bits, USB3_SSIFCMD);
61562306a36Sopenharmony_ci	else
61662306a36Sopenharmony_ci		usb3_set_bit(usb3, bits, USB3_SSIFCMD);
61762306a36Sopenharmony_ci}
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_cistatic void usb3_feature_u1_enable(struct renesas_usb3 *usb3, bool enable)
62062306a36Sopenharmony_ci{
62162306a36Sopenharmony_ci	u32 bits = SSIFCMD_UDIR_U1 | SSIFCMD_UREQ_U1;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	/* Enables U1 if the bits of UDIR and UREQ are set to 0 */
62462306a36Sopenharmony_ci	if (enable)
62562306a36Sopenharmony_ci		usb3_clear_bit(usb3, bits, USB3_SSIFCMD);
62662306a36Sopenharmony_ci	else
62762306a36Sopenharmony_ci		usb3_set_bit(usb3, bits, USB3_SSIFCMD);
62862306a36Sopenharmony_ci}
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_cistatic void usb3_start_operation_for_usb3(struct renesas_usb3 *usb3)
63162306a36Sopenharmony_ci{
63262306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON);
63362306a36Sopenharmony_ci	usb3_clear_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON);
63462306a36Sopenharmony_ci	usb3_set_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON);
63562306a36Sopenharmony_ci}
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_cistatic void usb3_start_usb3_connection(struct renesas_usb3 *usb3)
63862306a36Sopenharmony_ci{
63962306a36Sopenharmony_ci	usb3_start_operation_for_usb3(usb3);
64062306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_COM_CON_RX_DETECTION, USB3_USB_COM_CON);
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	usb3_enable_irq_1(usb3, USB_INT_1_B3_LUPSUCS | USB_INT_1_B3_DISABLE |
64362306a36Sopenharmony_ci			  USB_INT_1_SPEED);
64462306a36Sopenharmony_ci}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_cistatic void usb3_stop_usb3_connection(struct renesas_usb3 *usb3)
64762306a36Sopenharmony_ci{
64862306a36Sopenharmony_ci	usb3_clear_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON);
64962306a36Sopenharmony_ci}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_cistatic void usb3_transition_to_default_state(struct renesas_usb3 *usb3,
65262306a36Sopenharmony_ci					     bool is_usb3)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_INT_2_PIPE(0), USB3_USB_INT_ENA_2);
65562306a36Sopenharmony_ci	usb3_write(usb3, P0_INT_ALL_BITS, USB3_P0_INT_STA);
65662306a36Sopenharmony_ci	usb3_set_bit(usb3, P0_INT_ALL_BITS, USB3_P0_INT_ENA);
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	if (is_usb3)
65962306a36Sopenharmony_ci		usb3_enable_irq_1(usb3, USB_INT_1_B3_WRMRST |
66062306a36Sopenharmony_ci				  USB_INT_1_B3_HOTRST);
66162306a36Sopenharmony_ci	else
66262306a36Sopenharmony_ci		usb3_enable_irq_1(usb3, USB_INT_1_B2_SPND |
66362306a36Sopenharmony_ci				  USB_INT_1_B2_L1SPND | USB_INT_1_B2_USBRST);
66462306a36Sopenharmony_ci}
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_cistatic void usb3_connect(struct renesas_usb3 *usb3)
66762306a36Sopenharmony_ci{
66862306a36Sopenharmony_ci	if (usb3_wakeup_usb3_phy(usb3))
66962306a36Sopenharmony_ci		usb3_start_usb3_connection(usb3);
67062306a36Sopenharmony_ci}
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_cistatic void usb3_reset_epc(struct renesas_usb3 *usb3)
67362306a36Sopenharmony_ci{
67462306a36Sopenharmony_ci	usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
67562306a36Sopenharmony_ci	usb3_clear_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON);
67662306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_COM_CON_PIPE_CLR, USB3_USB_COM_CON);
67762306a36Sopenharmony_ci	usb3->test_mode = 0;
67862306a36Sopenharmony_ci	usb3_set_test_mode(usb3);
67962306a36Sopenharmony_ci}
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_cistatic void usb3_disconnect(struct renesas_usb3 *usb3)
68262306a36Sopenharmony_ci{
68362306a36Sopenharmony_ci	usb3->disabled_count = 0;
68462306a36Sopenharmony_ci	usb3_usb2_pullup(usb3, 0);
68562306a36Sopenharmony_ci	usb3_clear_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON);
68662306a36Sopenharmony_ci	usb3_reset_epc(usb3);
68762306a36Sopenharmony_ci	usb3_disable_irq_1(usb3, USB_INT_1_B2_RSUM | USB_INT_1_B3_PLLWKUP |
68862306a36Sopenharmony_ci			   USB_INT_1_B3_LUPSUCS | USB_INT_1_B3_DISABLE |
68962306a36Sopenharmony_ci			   USB_INT_1_SPEED | USB_INT_1_B3_WRMRST |
69062306a36Sopenharmony_ci			   USB_INT_1_B3_HOTRST | USB_INT_1_B2_SPND |
69162306a36Sopenharmony_ci			   USB_INT_1_B2_L1SPND | USB_INT_1_B2_USBRST);
69262306a36Sopenharmony_ci	usb3_clear_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON);
69362306a36Sopenharmony_ci	usb3_init_epc_registers(usb3);
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	if (usb3->driver)
69662306a36Sopenharmony_ci		usb3->driver->disconnect(&usb3->gadget);
69762306a36Sopenharmony_ci}
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_cistatic void usb3_check_vbus(struct renesas_usb3 *usb3)
70062306a36Sopenharmony_ci{
70162306a36Sopenharmony_ci	if (usb3->workaround_for_vbus) {
70262306a36Sopenharmony_ci		usb3_connect(usb3);
70362306a36Sopenharmony_ci	} else {
70462306a36Sopenharmony_ci		usb3->extcon_usb = !!(usb3_read(usb3, USB3_USB_STA) &
70562306a36Sopenharmony_ci							USB_STA_VBUS_STA);
70662306a36Sopenharmony_ci		if (usb3->extcon_usb)
70762306a36Sopenharmony_ci			usb3_connect(usb3);
70862306a36Sopenharmony_ci		else
70962306a36Sopenharmony_ci			usb3_disconnect(usb3);
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci		schedule_work(&usb3->extcon_work);
71262306a36Sopenharmony_ci	}
71362306a36Sopenharmony_ci}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_cistatic void renesas_usb3_role_work(struct work_struct *work)
71662306a36Sopenharmony_ci{
71762306a36Sopenharmony_ci	struct renesas_usb3 *usb3 =
71862306a36Sopenharmony_ci			container_of(work, struct renesas_usb3, role_work);
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	usb_role_switch_set_role(usb3->role_sw, usb3->role);
72162306a36Sopenharmony_ci}
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_cistatic void usb3_set_mode(struct renesas_usb3 *usb3, bool host)
72462306a36Sopenharmony_ci{
72562306a36Sopenharmony_ci	if (usb3->is_rzv2m) {
72662306a36Sopenharmony_ci		if (host) {
72762306a36Sopenharmony_ci			usb3_drd_set_bit(usb3, DRD_CON_PERI_RST, USB3_DRD_CON(usb3));
72862306a36Sopenharmony_ci			usb3_drd_clear_bit(usb3, DRD_CON_HOST_RST, USB3_DRD_CON(usb3));
72962306a36Sopenharmony_ci		} else {
73062306a36Sopenharmony_ci			usb3_drd_set_bit(usb3, DRD_CON_HOST_RST, USB3_DRD_CON(usb3));
73162306a36Sopenharmony_ci			usb3_drd_clear_bit(usb3, DRD_CON_PERI_RST, USB3_DRD_CON(usb3));
73262306a36Sopenharmony_ci		}
73362306a36Sopenharmony_ci	}
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	if (host)
73662306a36Sopenharmony_ci		usb3_drd_clear_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON(usb3));
73762306a36Sopenharmony_ci	else
73862306a36Sopenharmony_ci		usb3_drd_set_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON(usb3));
73962306a36Sopenharmony_ci}
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_cistatic void usb3_set_mode_by_role_sw(struct renesas_usb3 *usb3, bool host)
74262306a36Sopenharmony_ci{
74362306a36Sopenharmony_ci	if (usb3->role_sw) {
74462306a36Sopenharmony_ci		usb3->role = host ? USB_ROLE_HOST : USB_ROLE_DEVICE;
74562306a36Sopenharmony_ci		schedule_work(&usb3->role_work);
74662306a36Sopenharmony_ci	} else {
74762306a36Sopenharmony_ci		usb3_set_mode(usb3, host);
74862306a36Sopenharmony_ci	}
74962306a36Sopenharmony_ci}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_cistatic void usb3_vbus_out(struct renesas_usb3 *usb3, bool enable)
75262306a36Sopenharmony_ci{
75362306a36Sopenharmony_ci	if (enable)
75462306a36Sopenharmony_ci		usb3_drd_set_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON(usb3));
75562306a36Sopenharmony_ci	else
75662306a36Sopenharmony_ci		usb3_drd_clear_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON(usb3));
75762306a36Sopenharmony_ci}
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_cistatic void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev)
76062306a36Sopenharmony_ci{
76162306a36Sopenharmony_ci	unsigned long flags;
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	spin_lock_irqsave(&usb3->lock, flags);
76462306a36Sopenharmony_ci	if (!usb3->role_sw_by_connector ||
76562306a36Sopenharmony_ci	    usb3->connection_state != USB_ROLE_NONE) {
76662306a36Sopenharmony_ci		usb3_set_mode_by_role_sw(usb3, host);
76762306a36Sopenharmony_ci		usb3_vbus_out(usb3, a_dev);
76862306a36Sopenharmony_ci	}
76962306a36Sopenharmony_ci	/* for A-Peripheral or forced B-device mode */
77062306a36Sopenharmony_ci	if ((!host && a_dev) || usb3->start_to_connect)
77162306a36Sopenharmony_ci		usb3_connect(usb3);
77262306a36Sopenharmony_ci	spin_unlock_irqrestore(&usb3->lock, flags);
77362306a36Sopenharmony_ci}
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_cistatic bool usb3_is_a_device(struct renesas_usb3 *usb3)
77662306a36Sopenharmony_ci{
77762306a36Sopenharmony_ci	return !(usb3_drd_read(usb3, USB3_USB_OTG_STA(usb3)) & USB_OTG_IDMON(usb3));
77862306a36Sopenharmony_ci}
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_cistatic void usb3_check_id(struct renesas_usb3 *usb3)
78162306a36Sopenharmony_ci{
78262306a36Sopenharmony_ci	usb3->extcon_host = usb3_is_a_device(usb3);
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci	if ((!usb3->role_sw_by_connector && usb3->extcon_host &&
78562306a36Sopenharmony_ci	     !usb3->forced_b_device) || usb3->connection_state == USB_ROLE_HOST)
78662306a36Sopenharmony_ci		usb3_mode_config(usb3, true, true);
78762306a36Sopenharmony_ci	else
78862306a36Sopenharmony_ci		usb3_mode_config(usb3, false, false);
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	schedule_work(&usb3->extcon_work);
79162306a36Sopenharmony_ci}
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_cistatic void renesas_usb3_init_controller(struct renesas_usb3 *usb3)
79462306a36Sopenharmony_ci{
79562306a36Sopenharmony_ci	usb3_init_axi_bridge(usb3);
79662306a36Sopenharmony_ci	usb3_init_epc_registers(usb3);
79762306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_COM_CON_PN_WDATAIF_NL |
79862306a36Sopenharmony_ci		     USB_COM_CON_PN_RDATAIF_NL | USB_COM_CON_PN_LSTTR_PP,
79962306a36Sopenharmony_ci		     USB3_USB_COM_CON);
80062306a36Sopenharmony_ci	usb3_drd_write(usb3, USB_OTG_IDMON(usb3), USB3_USB_OTG_INT_STA(usb3));
80162306a36Sopenharmony_ci	usb3_drd_write(usb3, USB_OTG_IDMON(usb3), USB3_USB_OTG_INT_ENA(usb3));
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	usb3_check_id(usb3);
80462306a36Sopenharmony_ci	usb3_check_vbus(usb3);
80562306a36Sopenharmony_ci}
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_cistatic void renesas_usb3_stop_controller(struct renesas_usb3 *usb3)
80862306a36Sopenharmony_ci{
80962306a36Sopenharmony_ci	usb3_disconnect(usb3);
81062306a36Sopenharmony_ci	usb3_write(usb3, 0, USB3_P0_INT_ENA);
81162306a36Sopenharmony_ci	usb3_drd_write(usb3, 0, USB3_USB_OTG_INT_ENA(usb3));
81262306a36Sopenharmony_ci	usb3_write(usb3, 0, USB3_USB_INT_ENA_1);
81362306a36Sopenharmony_ci	usb3_write(usb3, 0, USB3_USB_INT_ENA_2);
81462306a36Sopenharmony_ci	usb3_write(usb3, 0, USB3_AXI_INT_ENA);
81562306a36Sopenharmony_ci}
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_cistatic void usb3_irq_epc_int_1_pll_wakeup(struct renesas_usb3 *usb3)
81862306a36Sopenharmony_ci{
81962306a36Sopenharmony_ci	usb3_disable_irq_1(usb3, USB_INT_1_B3_PLLWKUP);
82062306a36Sopenharmony_ci	usb3_clear_bit(usb3, USB30_CON_B3_PLLWAKE, USB3_USB30_CON);
82162306a36Sopenharmony_ci	usb3_start_usb3_connection(usb3);
82262306a36Sopenharmony_ci}
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_cistatic void usb3_irq_epc_int_1_linkup_success(struct renesas_usb3 *usb3)
82562306a36Sopenharmony_ci{
82662306a36Sopenharmony_ci	usb3_transition_to_default_state(usb3, true);
82762306a36Sopenharmony_ci}
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_cistatic void usb3_irq_epc_int_1_resume(struct renesas_usb3 *usb3)
83062306a36Sopenharmony_ci{
83162306a36Sopenharmony_ci	usb3_disable_irq_1(usb3, USB_INT_1_B2_RSUM);
83262306a36Sopenharmony_ci	usb3_start_usb2_connection(usb3);
83362306a36Sopenharmony_ci	usb3_transition_to_default_state(usb3, false);
83462306a36Sopenharmony_ci}
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_cistatic void usb3_irq_epc_int_1_suspend(struct renesas_usb3 *usb3)
83762306a36Sopenharmony_ci{
83862306a36Sopenharmony_ci	usb3_disable_irq_1(usb3, USB_INT_1_B2_SPND);
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	if (usb3->gadget.speed != USB_SPEED_UNKNOWN &&
84162306a36Sopenharmony_ci	    usb3->gadget.state != USB_STATE_NOTATTACHED) {
84262306a36Sopenharmony_ci		if (usb3->driver && usb3->driver->suspend)
84362306a36Sopenharmony_ci			usb3->driver->suspend(&usb3->gadget);
84462306a36Sopenharmony_ci		usb_gadget_set_state(&usb3->gadget, USB_STATE_SUSPENDED);
84562306a36Sopenharmony_ci	}
84662306a36Sopenharmony_ci}
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_cistatic void usb3_irq_epc_int_1_disable(struct renesas_usb3 *usb3)
84962306a36Sopenharmony_ci{
85062306a36Sopenharmony_ci	usb3_stop_usb3_connection(usb3);
85162306a36Sopenharmony_ci	if (usb3_wakeup_usb2_phy(usb3))
85262306a36Sopenharmony_ci		usb3_irq_epc_int_1_resume(usb3);
85362306a36Sopenharmony_ci}
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_cistatic void usb3_irq_epc_int_1_bus_reset(struct renesas_usb3 *usb3)
85662306a36Sopenharmony_ci{
85762306a36Sopenharmony_ci	usb3_reset_epc(usb3);
85862306a36Sopenharmony_ci	if (usb3->disabled_count < 3)
85962306a36Sopenharmony_ci		usb3_start_usb3_connection(usb3);
86062306a36Sopenharmony_ci	else
86162306a36Sopenharmony_ci		usb3_start_usb2_connection(usb3);
86262306a36Sopenharmony_ci}
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_cistatic void usb3_irq_epc_int_1_vbus_change(struct renesas_usb3 *usb3)
86562306a36Sopenharmony_ci{
86662306a36Sopenharmony_ci	usb3_check_vbus(usb3);
86762306a36Sopenharmony_ci}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_cistatic void usb3_irq_epc_int_1_hot_reset(struct renesas_usb3 *usb3)
87062306a36Sopenharmony_ci{
87162306a36Sopenharmony_ci	usb3_reset_epc(usb3);
87262306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON);
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	/* This bit shall be set within 12ms from the start of HotReset */
87562306a36Sopenharmony_ci	usb3_set_bit(usb3, USB30_CON_B3_HOTRST_CMP, USB3_USB30_CON);
87662306a36Sopenharmony_ci}
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_cistatic void usb3_irq_epc_int_1_warm_reset(struct renesas_usb3 *usb3)
87962306a36Sopenharmony_ci{
88062306a36Sopenharmony_ci	usb3_reset_epc(usb3);
88162306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_COM_CON_EP0_EN, USB3_USB_COM_CON);
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	usb3_start_operation_for_usb3(usb3);
88462306a36Sopenharmony_ci	usb3_enable_irq_1(usb3, USB_INT_1_SPEED);
88562306a36Sopenharmony_ci}
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_cistatic void usb3_irq_epc_int_1_speed(struct renesas_usb3 *usb3)
88862306a36Sopenharmony_ci{
88962306a36Sopenharmony_ci	u32 speed = usb3_read(usb3, USB3_USB_STA) & USB_STA_SPEED_MASK;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	switch (speed) {
89262306a36Sopenharmony_ci	case USB_STA_SPEED_SS:
89362306a36Sopenharmony_ci		usb3->gadget.speed = USB_SPEED_SUPER;
89462306a36Sopenharmony_ci		usb3->gadget.ep0->maxpacket = USB3_EP0_SS_MAX_PACKET_SIZE;
89562306a36Sopenharmony_ci		break;
89662306a36Sopenharmony_ci	case USB_STA_SPEED_HS:
89762306a36Sopenharmony_ci		usb3->gadget.speed = USB_SPEED_HIGH;
89862306a36Sopenharmony_ci		usb3->gadget.ep0->maxpacket = USB3_EP0_HSFS_MAX_PACKET_SIZE;
89962306a36Sopenharmony_ci		break;
90062306a36Sopenharmony_ci	case USB_STA_SPEED_FS:
90162306a36Sopenharmony_ci		usb3->gadget.speed = USB_SPEED_FULL;
90262306a36Sopenharmony_ci		usb3->gadget.ep0->maxpacket = USB3_EP0_HSFS_MAX_PACKET_SIZE;
90362306a36Sopenharmony_ci		break;
90462306a36Sopenharmony_ci	default:
90562306a36Sopenharmony_ci		usb3->gadget.speed = USB_SPEED_UNKNOWN;
90662306a36Sopenharmony_ci		break;
90762306a36Sopenharmony_ci	}
90862306a36Sopenharmony_ci}
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_cistatic void usb3_irq_epc_int_1(struct renesas_usb3 *usb3, u32 int_sta_1)
91162306a36Sopenharmony_ci{
91262306a36Sopenharmony_ci	if (int_sta_1 & USB_INT_1_B3_PLLWKUP)
91362306a36Sopenharmony_ci		usb3_irq_epc_int_1_pll_wakeup(usb3);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	if (int_sta_1 & USB_INT_1_B3_LUPSUCS)
91662306a36Sopenharmony_ci		usb3_irq_epc_int_1_linkup_success(usb3);
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	if (int_sta_1 & USB_INT_1_B3_HOTRST)
91962306a36Sopenharmony_ci		usb3_irq_epc_int_1_hot_reset(usb3);
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	if (int_sta_1 & USB_INT_1_B3_WRMRST)
92262306a36Sopenharmony_ci		usb3_irq_epc_int_1_warm_reset(usb3);
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	if (int_sta_1 & USB_INT_1_B3_DISABLE)
92562306a36Sopenharmony_ci		usb3_irq_epc_int_1_disable(usb3);
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	if (int_sta_1 & USB_INT_1_B2_USBRST)
92862306a36Sopenharmony_ci		usb3_irq_epc_int_1_bus_reset(usb3);
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	if (int_sta_1 & USB_INT_1_B2_RSUM)
93162306a36Sopenharmony_ci		usb3_irq_epc_int_1_resume(usb3);
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	if (int_sta_1 & USB_INT_1_B2_SPND)
93462306a36Sopenharmony_ci		usb3_irq_epc_int_1_suspend(usb3);
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	if (int_sta_1 & USB_INT_1_SPEED)
93762306a36Sopenharmony_ci		usb3_irq_epc_int_1_speed(usb3);
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	if (int_sta_1 & USB_INT_1_VBUS_CNG)
94062306a36Sopenharmony_ci		usb3_irq_epc_int_1_vbus_change(usb3);
94162306a36Sopenharmony_ci}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_cistatic struct renesas_usb3_request *__usb3_get_request(struct renesas_usb3_ep
94462306a36Sopenharmony_ci						       *usb3_ep)
94562306a36Sopenharmony_ci{
94662306a36Sopenharmony_ci	return list_first_entry_or_null(&usb3_ep->queue,
94762306a36Sopenharmony_ci					struct renesas_usb3_request, queue);
94862306a36Sopenharmony_ci}
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_cistatic struct renesas_usb3_request *usb3_get_request(struct renesas_usb3_ep
95162306a36Sopenharmony_ci						     *usb3_ep)
95262306a36Sopenharmony_ci{
95362306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
95462306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req;
95562306a36Sopenharmony_ci	unsigned long flags;
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	spin_lock_irqsave(&usb3->lock, flags);
95862306a36Sopenharmony_ci	usb3_req = __usb3_get_request(usb3_ep);
95962306a36Sopenharmony_ci	spin_unlock_irqrestore(&usb3->lock, flags);
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	return usb3_req;
96262306a36Sopenharmony_ci}
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_cistatic void __usb3_request_done(struct renesas_usb3_ep *usb3_ep,
96562306a36Sopenharmony_ci				struct renesas_usb3_request *usb3_req,
96662306a36Sopenharmony_ci				int status)
96762306a36Sopenharmony_ci{
96862306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	dev_dbg(usb3_to_dev(usb3), "giveback: ep%2d, %u, %u, %d\n",
97162306a36Sopenharmony_ci		usb3_ep->num, usb3_req->req.length, usb3_req->req.actual,
97262306a36Sopenharmony_ci		status);
97362306a36Sopenharmony_ci	usb3_req->req.status = status;
97462306a36Sopenharmony_ci	usb3_ep->started = false;
97562306a36Sopenharmony_ci	list_del_init(&usb3_req->queue);
97662306a36Sopenharmony_ci	spin_unlock(&usb3->lock);
97762306a36Sopenharmony_ci	usb_gadget_giveback_request(&usb3_ep->ep, &usb3_req->req);
97862306a36Sopenharmony_ci	spin_lock(&usb3->lock);
97962306a36Sopenharmony_ci}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_cistatic void usb3_request_done(struct renesas_usb3_ep *usb3_ep,
98262306a36Sopenharmony_ci			      struct renesas_usb3_request *usb3_req, int status)
98362306a36Sopenharmony_ci{
98462306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
98562306a36Sopenharmony_ci	unsigned long flags;
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	spin_lock_irqsave(&usb3->lock, flags);
98862306a36Sopenharmony_ci	__usb3_request_done(usb3_ep, usb3_req, status);
98962306a36Sopenharmony_ci	spin_unlock_irqrestore(&usb3->lock, flags);
99062306a36Sopenharmony_ci}
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_cistatic void usb3_irq_epc_pipe0_status_end(struct renesas_usb3 *usb3)
99362306a36Sopenharmony_ci{
99462306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0);
99562306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	if (usb3_req)
99862306a36Sopenharmony_ci		usb3_request_done(usb3_ep, usb3_req, 0);
99962306a36Sopenharmony_ci	if (usb3->test_mode)
100062306a36Sopenharmony_ci		usb3_set_test_mode(usb3);
100162306a36Sopenharmony_ci}
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_cistatic void usb3_get_setup_data(struct renesas_usb3 *usb3,
100462306a36Sopenharmony_ci				struct usb_ctrlrequest *ctrl)
100562306a36Sopenharmony_ci{
100662306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0);
100762306a36Sopenharmony_ci	u32 *data = (u32 *)ctrl;
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	*data++ = usb3_read(usb3, USB3_STUP_DAT_0);
101062306a36Sopenharmony_ci	*data = usb3_read(usb3, USB3_STUP_DAT_1);
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	/* update this driver's flag */
101362306a36Sopenharmony_ci	usb3_ep->dir_in = !!(ctrl->bRequestType & USB_DIR_IN);
101462306a36Sopenharmony_ci}
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_cistatic void usb3_set_p0_con_update_res(struct renesas_usb3 *usb3, u32 res)
101762306a36Sopenharmony_ci{
101862306a36Sopenharmony_ci	u32 val = usb3_read(usb3, USB3_P0_CON);
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	val &= ~(P0_CON_ST_RES_MASK | P0_CON_OT_RES_MASK | P0_CON_IN_RES_MASK);
102162306a36Sopenharmony_ci	val |= res | P0_CON_RES_WEN;
102262306a36Sopenharmony_ci	usb3_write(usb3, val, USB3_P0_CON);
102362306a36Sopenharmony_ci}
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_cistatic void usb3_set_p0_con_for_ctrl_read_data(struct renesas_usb3 *usb3)
102662306a36Sopenharmony_ci{
102762306a36Sopenharmony_ci	usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_NRDY |
102862306a36Sopenharmony_ci				   P0_CON_OT_RES_FORCE_STALL |
102962306a36Sopenharmony_ci				   P0_CON_IN_RES_NORMAL);
103062306a36Sopenharmony_ci}
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_cistatic void usb3_set_p0_con_for_ctrl_read_status(struct renesas_usb3 *usb3)
103362306a36Sopenharmony_ci{
103462306a36Sopenharmony_ci	usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_NORMAL |
103562306a36Sopenharmony_ci				   P0_CON_OT_RES_FORCE_STALL |
103662306a36Sopenharmony_ci				   P0_CON_IN_RES_NORMAL);
103762306a36Sopenharmony_ci}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_cistatic void usb3_set_p0_con_for_ctrl_write_data(struct renesas_usb3 *usb3)
104062306a36Sopenharmony_ci{
104162306a36Sopenharmony_ci	usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_NRDY |
104262306a36Sopenharmony_ci				   P0_CON_OT_RES_NORMAL |
104362306a36Sopenharmony_ci				   P0_CON_IN_RES_FORCE_STALL);
104462306a36Sopenharmony_ci}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_cistatic void usb3_set_p0_con_for_ctrl_write_status(struct renesas_usb3 *usb3)
104762306a36Sopenharmony_ci{
104862306a36Sopenharmony_ci	usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_NORMAL |
104962306a36Sopenharmony_ci				   P0_CON_OT_RES_NORMAL |
105062306a36Sopenharmony_ci				   P0_CON_IN_RES_FORCE_STALL);
105162306a36Sopenharmony_ci}
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_cistatic void usb3_set_p0_con_for_no_data(struct renesas_usb3 *usb3)
105462306a36Sopenharmony_ci{
105562306a36Sopenharmony_ci	usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_NORMAL |
105662306a36Sopenharmony_ci				   P0_CON_OT_RES_FORCE_STALL |
105762306a36Sopenharmony_ci				   P0_CON_IN_RES_FORCE_STALL);
105862306a36Sopenharmony_ci}
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_cistatic void usb3_set_p0_con_stall(struct renesas_usb3 *usb3)
106162306a36Sopenharmony_ci{
106262306a36Sopenharmony_ci	usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_STALL |
106362306a36Sopenharmony_ci				   P0_CON_OT_RES_FORCE_STALL |
106462306a36Sopenharmony_ci				   P0_CON_IN_RES_FORCE_STALL);
106562306a36Sopenharmony_ci}
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_cistatic void usb3_set_p0_con_stop(struct renesas_usb3 *usb3)
106862306a36Sopenharmony_ci{
106962306a36Sopenharmony_ci	usb3_set_p0_con_update_res(usb3, P0_CON_ST_RES_FORCE_NRDY |
107062306a36Sopenharmony_ci				   P0_CON_OT_RES_FORCE_NRDY |
107162306a36Sopenharmony_ci				   P0_CON_IN_RES_FORCE_NRDY);
107262306a36Sopenharmony_ci}
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_cistatic int usb3_pn_change(struct renesas_usb3 *usb3, int num)
107562306a36Sopenharmony_ci{
107662306a36Sopenharmony_ci	if (num == 0 || num > usb3->num_usb3_eps)
107762306a36Sopenharmony_ci		return -ENXIO;
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	usb3_write(usb3, num, USB3_PIPE_COM);
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	return 0;
108262306a36Sopenharmony_ci}
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_cistatic void usb3_set_pn_con_update_res(struct renesas_usb3 *usb3, u32 res)
108562306a36Sopenharmony_ci{
108662306a36Sopenharmony_ci	u32 val = usb3_read(usb3, USB3_PN_CON);
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	val &= ~PN_CON_RES_MASK;
108962306a36Sopenharmony_ci	val |= res & PN_CON_RES_MASK;
109062306a36Sopenharmony_ci	val |= PN_CON_RES_WEN;
109162306a36Sopenharmony_ci	usb3_write(usb3, val, USB3_PN_CON);
109262306a36Sopenharmony_ci}
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_cistatic void usb3_pn_start(struct renesas_usb3 *usb3)
109562306a36Sopenharmony_ci{
109662306a36Sopenharmony_ci	usb3_set_pn_con_update_res(usb3, PN_CON_RES_NORMAL);
109762306a36Sopenharmony_ci}
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_cistatic void usb3_pn_stop(struct renesas_usb3 *usb3)
110062306a36Sopenharmony_ci{
110162306a36Sopenharmony_ci	usb3_set_pn_con_update_res(usb3, PN_CON_RES_FORCE_NRDY);
110262306a36Sopenharmony_ci}
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_cistatic void usb3_pn_stall(struct renesas_usb3 *usb3)
110562306a36Sopenharmony_ci{
110662306a36Sopenharmony_ci	usb3_set_pn_con_update_res(usb3, PN_CON_RES_FORCE_STALL);
110762306a36Sopenharmony_ci}
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_cistatic int usb3_pn_con_clear(struct renesas_usb3 *usb3)
111062306a36Sopenharmony_ci{
111162306a36Sopenharmony_ci	usb3_set_bit(usb3, PN_CON_CLR, USB3_PN_CON);
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	return usb3_wait(usb3, USB3_PN_CON, PN_CON_CLR, 0);
111462306a36Sopenharmony_ci}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_cistatic bool usb3_is_transfer_complete(struct renesas_usb3_ep *usb3_ep,
111762306a36Sopenharmony_ci				      struct renesas_usb3_request *usb3_req)
111862306a36Sopenharmony_ci{
111962306a36Sopenharmony_ci	struct usb_request *req = &usb3_req->req;
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	if ((!req->zero && req->actual == req->length) ||
112262306a36Sopenharmony_ci	    (req->actual % usb3_ep->ep.maxpacket) || (req->length == 0))
112362306a36Sopenharmony_ci		return true;
112462306a36Sopenharmony_ci	else
112562306a36Sopenharmony_ci		return false;
112662306a36Sopenharmony_ci}
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_cistatic int usb3_wait_pipe_status(struct renesas_usb3_ep *usb3_ep, u32 mask)
112962306a36Sopenharmony_ci{
113062306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
113162306a36Sopenharmony_ci	u32 sta_reg = usb3_ep->num ? USB3_PN_STA : USB3_P0_STA;
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci	return usb3_wait(usb3, sta_reg, mask, mask);
113462306a36Sopenharmony_ci}
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_cistatic void usb3_set_px_con_send(struct renesas_usb3_ep *usb3_ep, int bytes,
113762306a36Sopenharmony_ci				 bool last)
113862306a36Sopenharmony_ci{
113962306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
114062306a36Sopenharmony_ci	u32 con_reg = usb3_ep->num ? USB3_PN_CON : USB3_P0_CON;
114162306a36Sopenharmony_ci	u32 val = usb3_read(usb3, con_reg);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	val |= PX_CON_SEND | PX_CON_BYTE_EN_BYTES(bytes);
114462306a36Sopenharmony_ci	val |= (usb3_ep->num && last) ? PN_CON_LAST : 0;
114562306a36Sopenharmony_ci	usb3_write(usb3, val, con_reg);
114662306a36Sopenharmony_ci}
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_cistatic int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep,
114962306a36Sopenharmony_ci			   struct renesas_usb3_request *usb3_req,
115062306a36Sopenharmony_ci			   u32 fifo_reg)
115162306a36Sopenharmony_ci{
115262306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
115362306a36Sopenharmony_ci	int i;
115462306a36Sopenharmony_ci	int len = min_t(unsigned, usb3_req->req.length - usb3_req->req.actual,
115562306a36Sopenharmony_ci			usb3_ep->ep.maxpacket);
115662306a36Sopenharmony_ci	u8 *buf = usb3_req->req.buf + usb3_req->req.actual;
115762306a36Sopenharmony_ci	u32 tmp = 0;
115862306a36Sopenharmony_ci	bool is_last = !len ? true : false;
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	if (usb3_wait_pipe_status(usb3_ep, PX_STA_BUFSTS) < 0)
116162306a36Sopenharmony_ci		return -EBUSY;
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	/* Update gadget driver parameter */
116462306a36Sopenharmony_ci	usb3_req->req.actual += len;
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	/* Write data to the register */
116762306a36Sopenharmony_ci	if (len >= 4) {
116862306a36Sopenharmony_ci		iowrite32_rep(usb3->reg + fifo_reg, buf, len / 4);
116962306a36Sopenharmony_ci		buf += (len / 4) * 4;
117062306a36Sopenharmony_ci		len %= 4;	/* update len to use usb3_set_pX_con_send() */
117162306a36Sopenharmony_ci	}
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	if (len) {
117462306a36Sopenharmony_ci		for (i = 0; i < len; i++)
117562306a36Sopenharmony_ci			tmp |= buf[i] << (8 * i);
117662306a36Sopenharmony_ci		usb3_write(usb3, tmp, fifo_reg);
117762306a36Sopenharmony_ci	}
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	if (!is_last)
118062306a36Sopenharmony_ci		is_last = usb3_is_transfer_complete(usb3_ep, usb3_req);
118162306a36Sopenharmony_ci	/* Send the data */
118262306a36Sopenharmony_ci	usb3_set_px_con_send(usb3_ep, len, is_last);
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci	return is_last ? 0 : -EAGAIN;
118562306a36Sopenharmony_ci}
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_cistatic u32 usb3_get_received_length(struct renesas_usb3_ep *usb3_ep)
118862306a36Sopenharmony_ci{
118962306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
119062306a36Sopenharmony_ci	u32 lng_reg = usb3_ep->num ? USB3_PN_LNG : USB3_P0_LNG;
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	return usb3_read(usb3, lng_reg);
119362306a36Sopenharmony_ci}
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_cistatic int usb3_read_pipe(struct renesas_usb3_ep *usb3_ep,
119662306a36Sopenharmony_ci			  struct renesas_usb3_request *usb3_req, u32 fifo_reg)
119762306a36Sopenharmony_ci{
119862306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
119962306a36Sopenharmony_ci	int i;
120062306a36Sopenharmony_ci	int len = min_t(unsigned, usb3_req->req.length - usb3_req->req.actual,
120162306a36Sopenharmony_ci			usb3_get_received_length(usb3_ep));
120262306a36Sopenharmony_ci	u8 *buf = usb3_req->req.buf + usb3_req->req.actual;
120362306a36Sopenharmony_ci	u32 tmp = 0;
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	if (!len)
120662306a36Sopenharmony_ci		return 0;
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	/* Update gadget driver parameter */
120962306a36Sopenharmony_ci	usb3_req->req.actual += len;
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci	/* Read data from the register */
121262306a36Sopenharmony_ci	if (len >= 4) {
121362306a36Sopenharmony_ci		ioread32_rep(usb3->reg + fifo_reg, buf, len / 4);
121462306a36Sopenharmony_ci		buf += (len / 4) * 4;
121562306a36Sopenharmony_ci		len %= 4;
121662306a36Sopenharmony_ci	}
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	if (len) {
121962306a36Sopenharmony_ci		tmp = usb3_read(usb3, fifo_reg);
122062306a36Sopenharmony_ci		for (i = 0; i < len; i++)
122162306a36Sopenharmony_ci			buf[i] = (tmp >> (8 * i)) & 0xff;
122262306a36Sopenharmony_ci	}
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	return usb3_is_transfer_complete(usb3_ep, usb3_req) ? 0 : -EAGAIN;
122562306a36Sopenharmony_ci}
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_cistatic void usb3_set_status_stage(struct renesas_usb3_ep *usb3_ep,
122862306a36Sopenharmony_ci				  struct renesas_usb3_request *usb3_req)
122962306a36Sopenharmony_ci{
123062306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	if (usb3_ep->dir_in) {
123362306a36Sopenharmony_ci		usb3_set_p0_con_for_ctrl_read_status(usb3);
123462306a36Sopenharmony_ci	} else {
123562306a36Sopenharmony_ci		if (!usb3_req->req.length)
123662306a36Sopenharmony_ci			usb3_set_p0_con_for_no_data(usb3);
123762306a36Sopenharmony_ci		else
123862306a36Sopenharmony_ci			usb3_set_p0_con_for_ctrl_write_status(usb3);
123962306a36Sopenharmony_ci	}
124062306a36Sopenharmony_ci}
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_cistatic void usb3_p0_xfer(struct renesas_usb3_ep *usb3_ep,
124362306a36Sopenharmony_ci			 struct renesas_usb3_request *usb3_req)
124462306a36Sopenharmony_ci{
124562306a36Sopenharmony_ci	int ret;
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	if (usb3_ep->dir_in)
124862306a36Sopenharmony_ci		ret = usb3_write_pipe(usb3_ep, usb3_req, USB3_P0_WRITE);
124962306a36Sopenharmony_ci	else
125062306a36Sopenharmony_ci		ret = usb3_read_pipe(usb3_ep, usb3_req, USB3_P0_READ);
125162306a36Sopenharmony_ci
125262306a36Sopenharmony_ci	if (!ret)
125362306a36Sopenharmony_ci		usb3_set_status_stage(usb3_ep, usb3_req);
125462306a36Sopenharmony_ci}
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_cistatic void usb3_start_pipe0(struct renesas_usb3_ep *usb3_ep,
125762306a36Sopenharmony_ci			     struct renesas_usb3_request *usb3_req)
125862306a36Sopenharmony_ci{
125962306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	if (usb3_ep->started)
126262306a36Sopenharmony_ci		return;
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	usb3_ep->started = true;
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	if (usb3_ep->dir_in) {
126762306a36Sopenharmony_ci		usb3_set_bit(usb3, P0_MOD_DIR, USB3_P0_MOD);
126862306a36Sopenharmony_ci		usb3_set_p0_con_for_ctrl_read_data(usb3);
126962306a36Sopenharmony_ci	} else {
127062306a36Sopenharmony_ci		usb3_clear_bit(usb3, P0_MOD_DIR, USB3_P0_MOD);
127162306a36Sopenharmony_ci		if (usb3_req->req.length)
127262306a36Sopenharmony_ci			usb3_set_p0_con_for_ctrl_write_data(usb3);
127362306a36Sopenharmony_ci	}
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci	usb3_p0_xfer(usb3_ep, usb3_req);
127662306a36Sopenharmony_ci}
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_cistatic void usb3_enable_dma_pipen(struct renesas_usb3 *usb3)
127962306a36Sopenharmony_ci{
128062306a36Sopenharmony_ci	usb3_set_bit(usb3, PN_CON_DATAIF_EN, USB3_PN_CON);
128162306a36Sopenharmony_ci}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_cistatic void usb3_disable_dma_pipen(struct renesas_usb3 *usb3)
128462306a36Sopenharmony_ci{
128562306a36Sopenharmony_ci	usb3_clear_bit(usb3, PN_CON_DATAIF_EN, USB3_PN_CON);
128662306a36Sopenharmony_ci}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_cistatic void usb3_enable_dma_irq(struct renesas_usb3 *usb3, int num)
128962306a36Sopenharmony_ci{
129062306a36Sopenharmony_ci	usb3_set_bit(usb3, DMA_INT(num), USB3_DMA_INT_ENA);
129162306a36Sopenharmony_ci}
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_cistatic void usb3_disable_dma_irq(struct renesas_usb3 *usb3, int num)
129462306a36Sopenharmony_ci{
129562306a36Sopenharmony_ci	usb3_clear_bit(usb3, DMA_INT(num), USB3_DMA_INT_ENA);
129662306a36Sopenharmony_ci}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_cistatic u32 usb3_dma_mps_to_prd_word1(struct renesas_usb3_ep *usb3_ep)
129962306a36Sopenharmony_ci{
130062306a36Sopenharmony_ci	switch (usb3_ep->ep.maxpacket) {
130162306a36Sopenharmony_ci	case 8:
130262306a36Sopenharmony_ci		return USB3_PRD1_MPS_8;
130362306a36Sopenharmony_ci	case 16:
130462306a36Sopenharmony_ci		return USB3_PRD1_MPS_16;
130562306a36Sopenharmony_ci	case 32:
130662306a36Sopenharmony_ci		return USB3_PRD1_MPS_32;
130762306a36Sopenharmony_ci	case 64:
130862306a36Sopenharmony_ci		return USB3_PRD1_MPS_64;
130962306a36Sopenharmony_ci	case 512:
131062306a36Sopenharmony_ci		return USB3_PRD1_MPS_512;
131162306a36Sopenharmony_ci	case 1024:
131262306a36Sopenharmony_ci		return USB3_PRD1_MPS_1024;
131362306a36Sopenharmony_ci	default:
131462306a36Sopenharmony_ci		return USB3_PRD1_MPS_RESERVED;
131562306a36Sopenharmony_ci	}
131662306a36Sopenharmony_ci}
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_cistatic bool usb3_dma_get_setting_area(struct renesas_usb3_ep *usb3_ep,
131962306a36Sopenharmony_ci				      struct renesas_usb3_request *usb3_req)
132062306a36Sopenharmony_ci{
132162306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
132262306a36Sopenharmony_ci	struct renesas_usb3_dma *dma;
132362306a36Sopenharmony_ci	int i;
132462306a36Sopenharmony_ci	bool ret = false;
132562306a36Sopenharmony_ci
132662306a36Sopenharmony_ci	if (usb3_req->req.length > USB3_DMA_MAX_XFER_SIZE_ALL_PRDS) {
132762306a36Sopenharmony_ci		dev_dbg(usb3_to_dev(usb3), "%s: the length is too big (%d)\n",
132862306a36Sopenharmony_ci			__func__, usb3_req->req.length);
132962306a36Sopenharmony_ci		return false;
133062306a36Sopenharmony_ci	}
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci	/* The driver doesn't handle zero-length packet via dmac */
133362306a36Sopenharmony_ci	if (!usb3_req->req.length)
133462306a36Sopenharmony_ci		return false;
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	if (usb3_dma_mps_to_prd_word1(usb3_ep) == USB3_PRD1_MPS_RESERVED)
133762306a36Sopenharmony_ci		return false;
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci	usb3_for_each_dma(usb3, dma, i) {
134062306a36Sopenharmony_ci		if (dma->used)
134162306a36Sopenharmony_ci			continue;
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci		if (usb_gadget_map_request(&usb3->gadget, &usb3_req->req,
134462306a36Sopenharmony_ci					   usb3_ep->dir_in) < 0)
134562306a36Sopenharmony_ci			break;
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci		dma->used = true;
134862306a36Sopenharmony_ci		usb3_ep->dma = dma;
134962306a36Sopenharmony_ci		ret = true;
135062306a36Sopenharmony_ci		break;
135162306a36Sopenharmony_ci	}
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	return ret;
135462306a36Sopenharmony_ci}
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_cistatic void usb3_dma_put_setting_area(struct renesas_usb3_ep *usb3_ep,
135762306a36Sopenharmony_ci				      struct renesas_usb3_request *usb3_req)
135862306a36Sopenharmony_ci{
135962306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
136062306a36Sopenharmony_ci	int i;
136162306a36Sopenharmony_ci	struct renesas_usb3_dma *dma;
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	usb3_for_each_dma(usb3, dma, i) {
136462306a36Sopenharmony_ci		if (usb3_ep->dma == dma) {
136562306a36Sopenharmony_ci			usb_gadget_unmap_request(&usb3->gadget, &usb3_req->req,
136662306a36Sopenharmony_ci						 usb3_ep->dir_in);
136762306a36Sopenharmony_ci			dma->used = false;
136862306a36Sopenharmony_ci			usb3_ep->dma = NULL;
136962306a36Sopenharmony_ci			break;
137062306a36Sopenharmony_ci		}
137162306a36Sopenharmony_ci	}
137262306a36Sopenharmony_ci}
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_cistatic void usb3_dma_fill_prd(struct renesas_usb3_ep *usb3_ep,
137562306a36Sopenharmony_ci			      struct renesas_usb3_request *usb3_req)
137662306a36Sopenharmony_ci{
137762306a36Sopenharmony_ci	struct renesas_usb3_prd *cur_prd = usb3_ep->dma->prd;
137862306a36Sopenharmony_ci	u32 remain = usb3_req->req.length;
137962306a36Sopenharmony_ci	u32 dma = usb3_req->req.dma;
138062306a36Sopenharmony_ci	u32 len;
138162306a36Sopenharmony_ci	int i = 0;
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	do {
138462306a36Sopenharmony_ci		len = min_t(u32, remain, USB3_DMA_MAX_XFER_SIZE) &
138562306a36Sopenharmony_ci			    USB3_PRD1_SIZE_MASK;
138662306a36Sopenharmony_ci		cur_prd->word1 = usb3_dma_mps_to_prd_word1(usb3_ep) |
138762306a36Sopenharmony_ci				 USB3_PRD1_B_INC | len;
138862306a36Sopenharmony_ci		cur_prd->bap = dma;
138962306a36Sopenharmony_ci		remain -= len;
139062306a36Sopenharmony_ci		dma += len;
139162306a36Sopenharmony_ci		if (!remain || (i + 1) < USB3_DMA_NUM_PRD_ENTRIES)
139262306a36Sopenharmony_ci			break;
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ci		cur_prd++;
139562306a36Sopenharmony_ci		i++;
139662306a36Sopenharmony_ci	} while (1);
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	cur_prd->word1 |= USB3_PRD1_E | USB3_PRD1_INT;
139962306a36Sopenharmony_ci	if (usb3_ep->dir_in)
140062306a36Sopenharmony_ci		cur_prd->word1 |= USB3_PRD1_LST;
140162306a36Sopenharmony_ci}
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_cistatic void usb3_dma_kick_prd(struct renesas_usb3_ep *usb3_ep)
140462306a36Sopenharmony_ci{
140562306a36Sopenharmony_ci	struct renesas_usb3_dma *dma = usb3_ep->dma;
140662306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
140762306a36Sopenharmony_ci	u32 dma_con = DMA_COM_PIPE_NO(usb3_ep->num) | DMA_CON_PRD_EN;
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci	if (usb3_ep->dir_in)
141062306a36Sopenharmony_ci		dma_con |= DMA_CON_PIPE_DIR;
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci	wmb();	/* prd entries should be in system memory here */
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	usb3_write(usb3, 1 << usb3_ep->num, USB3_DMA_INT_STA);
141562306a36Sopenharmony_ci	usb3_write(usb3, AXI_INT_PRDEN_CLR_STA(dma->num) |
141662306a36Sopenharmony_ci		   AXI_INT_PRDERR_STA(dma->num), USB3_AXI_INT_STA);
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_ci	usb3_write(usb3, dma->prd_dma, USB3_DMA_CH0_PRD_ADR(dma->num));
141962306a36Sopenharmony_ci	usb3_write(usb3, dma_con, USB3_DMA_CH0_CON(dma->num));
142062306a36Sopenharmony_ci	usb3_enable_dma_irq(usb3, usb3_ep->num);
142162306a36Sopenharmony_ci}
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_cistatic void usb3_dma_stop_prd(struct renesas_usb3_ep *usb3_ep)
142462306a36Sopenharmony_ci{
142562306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
142662306a36Sopenharmony_ci	struct renesas_usb3_dma *dma = usb3_ep->dma;
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci	usb3_disable_dma_irq(usb3, usb3_ep->num);
142962306a36Sopenharmony_ci	usb3_write(usb3, 0, USB3_DMA_CH0_CON(dma->num));
143062306a36Sopenharmony_ci}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_cistatic int usb3_dma_update_status(struct renesas_usb3_ep *usb3_ep,
143362306a36Sopenharmony_ci				  struct renesas_usb3_request *usb3_req)
143462306a36Sopenharmony_ci{
143562306a36Sopenharmony_ci	struct renesas_usb3_prd *cur_prd = usb3_ep->dma->prd;
143662306a36Sopenharmony_ci	struct usb_request *req = &usb3_req->req;
143762306a36Sopenharmony_ci	u32 remain, len;
143862306a36Sopenharmony_ci	int i = 0;
143962306a36Sopenharmony_ci	int status = 0;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	rmb();	/* The controller updated prd entries */
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	do {
144462306a36Sopenharmony_ci		if (cur_prd->word1 & USB3_PRD1_D)
144562306a36Sopenharmony_ci			status = -EIO;
144662306a36Sopenharmony_ci		if (cur_prd->word1 & USB3_PRD1_E)
144762306a36Sopenharmony_ci			len = req->length % USB3_DMA_MAX_XFER_SIZE;
144862306a36Sopenharmony_ci		else
144962306a36Sopenharmony_ci			len = USB3_DMA_MAX_XFER_SIZE;
145062306a36Sopenharmony_ci		remain = cur_prd->word1 & USB3_PRD1_SIZE_MASK;
145162306a36Sopenharmony_ci		req->actual += len - remain;
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci		if (cur_prd->word1 & USB3_PRD1_E ||
145462306a36Sopenharmony_ci		    (i + 1) < USB3_DMA_NUM_PRD_ENTRIES)
145562306a36Sopenharmony_ci			break;
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci		cur_prd++;
145862306a36Sopenharmony_ci		i++;
145962306a36Sopenharmony_ci	} while (1);
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	return status;
146262306a36Sopenharmony_ci}
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_cistatic bool usb3_dma_try_start(struct renesas_usb3_ep *usb3_ep,
146562306a36Sopenharmony_ci			       struct renesas_usb3_request *usb3_req)
146662306a36Sopenharmony_ci{
146762306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	if (!use_dma)
147062306a36Sopenharmony_ci		return false;
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_ci	if (usb3_dma_get_setting_area(usb3_ep, usb3_req)) {
147362306a36Sopenharmony_ci		usb3_pn_stop(usb3);
147462306a36Sopenharmony_ci		usb3_enable_dma_pipen(usb3);
147562306a36Sopenharmony_ci		usb3_dma_fill_prd(usb3_ep, usb3_req);
147662306a36Sopenharmony_ci		usb3_dma_kick_prd(usb3_ep);
147762306a36Sopenharmony_ci		usb3_pn_start(usb3);
147862306a36Sopenharmony_ci		return true;
147962306a36Sopenharmony_ci	}
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	return false;
148262306a36Sopenharmony_ci}
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_cistatic int usb3_dma_try_stop(struct renesas_usb3_ep *usb3_ep,
148562306a36Sopenharmony_ci			     struct renesas_usb3_request *usb3_req)
148662306a36Sopenharmony_ci{
148762306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
148862306a36Sopenharmony_ci	unsigned long flags;
148962306a36Sopenharmony_ci	int status = 0;
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	spin_lock_irqsave(&usb3->lock, flags);
149262306a36Sopenharmony_ci	if (!usb3_ep->dma)
149362306a36Sopenharmony_ci		goto out;
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_ci	if (!usb3_pn_change(usb3, usb3_ep->num))
149662306a36Sopenharmony_ci		usb3_disable_dma_pipen(usb3);
149762306a36Sopenharmony_ci	usb3_dma_stop_prd(usb3_ep);
149862306a36Sopenharmony_ci	status = usb3_dma_update_status(usb3_ep, usb3_req);
149962306a36Sopenharmony_ci	usb3_dma_put_setting_area(usb3_ep, usb3_req);
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ciout:
150262306a36Sopenharmony_ci	spin_unlock_irqrestore(&usb3->lock, flags);
150362306a36Sopenharmony_ci	return status;
150462306a36Sopenharmony_ci}
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_cistatic int renesas_usb3_dma_free_prd(struct renesas_usb3 *usb3,
150762306a36Sopenharmony_ci				     struct device *dev)
150862306a36Sopenharmony_ci{
150962306a36Sopenharmony_ci	int i;
151062306a36Sopenharmony_ci	struct renesas_usb3_dma *dma;
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	usb3_for_each_dma(usb3, dma, i) {
151362306a36Sopenharmony_ci		if (dma->prd) {
151462306a36Sopenharmony_ci			dma_free_coherent(dev, USB3_DMA_PRD_SIZE,
151562306a36Sopenharmony_ci					  dma->prd, dma->prd_dma);
151662306a36Sopenharmony_ci			dma->prd = NULL;
151762306a36Sopenharmony_ci		}
151862306a36Sopenharmony_ci	}
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	return 0;
152162306a36Sopenharmony_ci}
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_cistatic int renesas_usb3_dma_alloc_prd(struct renesas_usb3 *usb3,
152462306a36Sopenharmony_ci				      struct device *dev)
152562306a36Sopenharmony_ci{
152662306a36Sopenharmony_ci	int i;
152762306a36Sopenharmony_ci	struct renesas_usb3_dma *dma;
152862306a36Sopenharmony_ci
152962306a36Sopenharmony_ci	if (!use_dma)
153062306a36Sopenharmony_ci		return 0;
153162306a36Sopenharmony_ci
153262306a36Sopenharmony_ci	usb3_for_each_dma(usb3, dma, i) {
153362306a36Sopenharmony_ci		dma->prd = dma_alloc_coherent(dev, USB3_DMA_PRD_SIZE,
153462306a36Sopenharmony_ci					      &dma->prd_dma, GFP_KERNEL);
153562306a36Sopenharmony_ci		if (!dma->prd) {
153662306a36Sopenharmony_ci			renesas_usb3_dma_free_prd(usb3, dev);
153762306a36Sopenharmony_ci			return -ENOMEM;
153862306a36Sopenharmony_ci		}
153962306a36Sopenharmony_ci		dma->num = i + 1;
154062306a36Sopenharmony_ci	}
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci	return 0;
154362306a36Sopenharmony_ci}
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_cistatic void usb3_start_pipen(struct renesas_usb3_ep *usb3_ep,
154662306a36Sopenharmony_ci			     struct renesas_usb3_request *usb3_req)
154762306a36Sopenharmony_ci{
154862306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
154962306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req_first;
155062306a36Sopenharmony_ci	unsigned long flags;
155162306a36Sopenharmony_ci	int ret = -EAGAIN;
155262306a36Sopenharmony_ci	u32 enable_bits = 0;
155362306a36Sopenharmony_ci
155462306a36Sopenharmony_ci	spin_lock_irqsave(&usb3->lock, flags);
155562306a36Sopenharmony_ci	if (usb3_ep->halt || usb3_ep->started)
155662306a36Sopenharmony_ci		goto out;
155762306a36Sopenharmony_ci	usb3_req_first = __usb3_get_request(usb3_ep);
155862306a36Sopenharmony_ci	if (!usb3_req_first || usb3_req != usb3_req_first)
155962306a36Sopenharmony_ci		goto out;
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci	if (usb3_pn_change(usb3, usb3_ep->num) < 0)
156262306a36Sopenharmony_ci		goto out;
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	usb3_ep->started = true;
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	if (usb3_dma_try_start(usb3_ep, usb3_req))
156762306a36Sopenharmony_ci		goto out;
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	usb3_pn_start(usb3);
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	if (usb3_ep->dir_in) {
157262306a36Sopenharmony_ci		ret = usb3_write_pipe(usb3_ep, usb3_req, USB3_PN_WRITE);
157362306a36Sopenharmony_ci		enable_bits |= PN_INT_LSTTR;
157462306a36Sopenharmony_ci	}
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	if (ret < 0)
157762306a36Sopenharmony_ci		enable_bits |= PN_INT_BFRDY;
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	if (enable_bits) {
158062306a36Sopenharmony_ci		usb3_set_bit(usb3, enable_bits, USB3_PN_INT_ENA);
158162306a36Sopenharmony_ci		usb3_enable_pipe_irq(usb3, usb3_ep->num);
158262306a36Sopenharmony_ci	}
158362306a36Sopenharmony_ciout:
158462306a36Sopenharmony_ci	spin_unlock_irqrestore(&usb3->lock, flags);
158562306a36Sopenharmony_ci}
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_cistatic int renesas_usb3_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
158862306a36Sopenharmony_ci				 gfp_t gfp_flags)
158962306a36Sopenharmony_ci{
159062306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
159162306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req = usb_req_to_usb3_req(_req);
159262306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
159362306a36Sopenharmony_ci	unsigned long flags;
159462306a36Sopenharmony_ci
159562306a36Sopenharmony_ci	dev_dbg(usb3_to_dev(usb3), "ep_queue: ep%2d, %u\n", usb3_ep->num,
159662306a36Sopenharmony_ci		_req->length);
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	_req->status = -EINPROGRESS;
159962306a36Sopenharmony_ci	_req->actual = 0;
160062306a36Sopenharmony_ci	spin_lock_irqsave(&usb3->lock, flags);
160162306a36Sopenharmony_ci	list_add_tail(&usb3_req->queue, &usb3_ep->queue);
160262306a36Sopenharmony_ci	spin_unlock_irqrestore(&usb3->lock, flags);
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	if (!usb3_ep->num)
160562306a36Sopenharmony_ci		usb3_start_pipe0(usb3_ep, usb3_req);
160662306a36Sopenharmony_ci	else
160762306a36Sopenharmony_ci		usb3_start_pipen(usb3_ep, usb3_req);
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	return 0;
161062306a36Sopenharmony_ci}
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_cistatic void usb3_set_device_address(struct renesas_usb3 *usb3, u16 addr)
161362306a36Sopenharmony_ci{
161462306a36Sopenharmony_ci	/* DEV_ADDR bit field is cleared by WarmReset, HotReset and BusReset */
161562306a36Sopenharmony_ci	usb3_set_bit(usb3, USB_COM_CON_DEV_ADDR(addr), USB3_USB_COM_CON);
161662306a36Sopenharmony_ci}
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_cistatic bool usb3_std_req_set_address(struct renesas_usb3 *usb3,
161962306a36Sopenharmony_ci				     struct usb_ctrlrequest *ctrl)
162062306a36Sopenharmony_ci{
162162306a36Sopenharmony_ci	if (le16_to_cpu(ctrl->wValue) >= 128)
162262306a36Sopenharmony_ci		return true;	/* stall */
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	usb3_set_device_address(usb3, le16_to_cpu(ctrl->wValue));
162562306a36Sopenharmony_ci	usb3_set_p0_con_for_no_data(usb3);
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci	return false;
162862306a36Sopenharmony_ci}
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_cistatic void usb3_pipe0_internal_xfer(struct renesas_usb3 *usb3,
163162306a36Sopenharmony_ci				     void *tx_data, size_t len,
163262306a36Sopenharmony_ci				     void (*complete)(struct usb_ep *ep,
163362306a36Sopenharmony_ci						      struct usb_request *req))
163462306a36Sopenharmony_ci{
163562306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0);
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci	if (tx_data)
163862306a36Sopenharmony_ci		memcpy(usb3->ep0_buf, tx_data,
163962306a36Sopenharmony_ci		       min_t(size_t, len, USB3_EP0_BUF_SIZE));
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	usb3->ep0_req->buf = &usb3->ep0_buf;
164262306a36Sopenharmony_ci	usb3->ep0_req->length = len;
164362306a36Sopenharmony_ci	usb3->ep0_req->complete = complete;
164462306a36Sopenharmony_ci	renesas_usb3_ep_queue(&usb3_ep->ep, usb3->ep0_req, GFP_ATOMIC);
164562306a36Sopenharmony_ci}
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_cistatic void usb3_pipe0_get_status_completion(struct usb_ep *ep,
164862306a36Sopenharmony_ci					     struct usb_request *req)
164962306a36Sopenharmony_ci{
165062306a36Sopenharmony_ci}
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_cistatic bool usb3_std_req_get_status(struct renesas_usb3 *usb3,
165362306a36Sopenharmony_ci				    struct usb_ctrlrequest *ctrl)
165462306a36Sopenharmony_ci{
165562306a36Sopenharmony_ci	bool stall = false;
165662306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep;
165762306a36Sopenharmony_ci	int num;
165862306a36Sopenharmony_ci	u16 status = 0;
165962306a36Sopenharmony_ci	__le16 tx_data;
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci	switch (ctrl->bRequestType & USB_RECIP_MASK) {
166262306a36Sopenharmony_ci	case USB_RECIP_DEVICE:
166362306a36Sopenharmony_ci		if (usb3->gadget.is_selfpowered)
166462306a36Sopenharmony_ci			status |= 1 << USB_DEVICE_SELF_POWERED;
166562306a36Sopenharmony_ci		if (usb3->gadget.speed == USB_SPEED_SUPER)
166662306a36Sopenharmony_ci			status |= usb3_feature_get_un_enabled(usb3);
166762306a36Sopenharmony_ci		break;
166862306a36Sopenharmony_ci	case USB_RECIP_INTERFACE:
166962306a36Sopenharmony_ci		break;
167062306a36Sopenharmony_ci	case USB_RECIP_ENDPOINT:
167162306a36Sopenharmony_ci		num = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
167262306a36Sopenharmony_ci		usb3_ep = usb3_get_ep(usb3, num);
167362306a36Sopenharmony_ci		if (usb3_ep->halt)
167462306a36Sopenharmony_ci			status |= 1 << USB_ENDPOINT_HALT;
167562306a36Sopenharmony_ci		break;
167662306a36Sopenharmony_ci	default:
167762306a36Sopenharmony_ci		stall = true;
167862306a36Sopenharmony_ci		break;
167962306a36Sopenharmony_ci	}
168062306a36Sopenharmony_ci
168162306a36Sopenharmony_ci	if (!stall) {
168262306a36Sopenharmony_ci		tx_data = cpu_to_le16(status);
168362306a36Sopenharmony_ci		dev_dbg(usb3_to_dev(usb3), "get_status: req = %p\n",
168462306a36Sopenharmony_ci			usb_req_to_usb3_req(usb3->ep0_req));
168562306a36Sopenharmony_ci		usb3_pipe0_internal_xfer(usb3, &tx_data, sizeof(tx_data),
168662306a36Sopenharmony_ci					 usb3_pipe0_get_status_completion);
168762306a36Sopenharmony_ci	}
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	return stall;
169062306a36Sopenharmony_ci}
169162306a36Sopenharmony_ci
169262306a36Sopenharmony_cistatic bool usb3_std_req_feature_device(struct renesas_usb3 *usb3,
169362306a36Sopenharmony_ci					struct usb_ctrlrequest *ctrl, bool set)
169462306a36Sopenharmony_ci{
169562306a36Sopenharmony_ci	bool stall = true;
169662306a36Sopenharmony_ci	u16 w_value = le16_to_cpu(ctrl->wValue);
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_ci	switch (w_value) {
169962306a36Sopenharmony_ci	case USB_DEVICE_TEST_MODE:
170062306a36Sopenharmony_ci		if (!set)
170162306a36Sopenharmony_ci			break;
170262306a36Sopenharmony_ci		usb3->test_mode = le16_to_cpu(ctrl->wIndex) >> 8;
170362306a36Sopenharmony_ci		stall = false;
170462306a36Sopenharmony_ci		break;
170562306a36Sopenharmony_ci	case USB_DEVICE_U1_ENABLE:
170662306a36Sopenharmony_ci	case USB_DEVICE_U2_ENABLE:
170762306a36Sopenharmony_ci		if (usb3->gadget.speed != USB_SPEED_SUPER)
170862306a36Sopenharmony_ci			break;
170962306a36Sopenharmony_ci		if (w_value == USB_DEVICE_U1_ENABLE)
171062306a36Sopenharmony_ci			usb3_feature_u1_enable(usb3, set);
171162306a36Sopenharmony_ci		if (w_value == USB_DEVICE_U2_ENABLE)
171262306a36Sopenharmony_ci			usb3_feature_u2_enable(usb3, set);
171362306a36Sopenharmony_ci		stall = false;
171462306a36Sopenharmony_ci		break;
171562306a36Sopenharmony_ci	default:
171662306a36Sopenharmony_ci		break;
171762306a36Sopenharmony_ci	}
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci	return stall;
172062306a36Sopenharmony_ci}
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_cistatic int usb3_set_halt_p0(struct renesas_usb3_ep *usb3_ep, bool halt)
172362306a36Sopenharmony_ci{
172462306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	if (unlikely(usb3_ep->num))
172762306a36Sopenharmony_ci		return -EINVAL;
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	usb3_ep->halt = halt;
173062306a36Sopenharmony_ci	if (halt)
173162306a36Sopenharmony_ci		usb3_set_p0_con_stall(usb3);
173262306a36Sopenharmony_ci	else
173362306a36Sopenharmony_ci		usb3_set_p0_con_stop(usb3);
173462306a36Sopenharmony_ci
173562306a36Sopenharmony_ci	return 0;
173662306a36Sopenharmony_ci}
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_cistatic int usb3_set_halt_pn(struct renesas_usb3_ep *usb3_ep, bool halt,
173962306a36Sopenharmony_ci			    bool is_clear_feature)
174062306a36Sopenharmony_ci{
174162306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
174262306a36Sopenharmony_ci	unsigned long flags;
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci	spin_lock_irqsave(&usb3->lock, flags);
174562306a36Sopenharmony_ci	if (!usb3_pn_change(usb3, usb3_ep->num)) {
174662306a36Sopenharmony_ci		usb3_ep->halt = halt;
174762306a36Sopenharmony_ci		if (halt) {
174862306a36Sopenharmony_ci			usb3_pn_stall(usb3);
174962306a36Sopenharmony_ci		} else if (!is_clear_feature || !usb3_ep->wedge) {
175062306a36Sopenharmony_ci			usb3_pn_con_clear(usb3);
175162306a36Sopenharmony_ci			usb3_set_bit(usb3, PN_CON_EN, USB3_PN_CON);
175262306a36Sopenharmony_ci			usb3_pn_stop(usb3);
175362306a36Sopenharmony_ci		}
175462306a36Sopenharmony_ci	}
175562306a36Sopenharmony_ci	spin_unlock_irqrestore(&usb3->lock, flags);
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci	return 0;
175862306a36Sopenharmony_ci}
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_cistatic int usb3_set_halt(struct renesas_usb3_ep *usb3_ep, bool halt,
176162306a36Sopenharmony_ci			 bool is_clear_feature)
176262306a36Sopenharmony_ci{
176362306a36Sopenharmony_ci	int ret = 0;
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	if (halt && usb3_ep->started)
176662306a36Sopenharmony_ci		return -EAGAIN;
176762306a36Sopenharmony_ci
176862306a36Sopenharmony_ci	if (usb3_ep->num)
176962306a36Sopenharmony_ci		ret = usb3_set_halt_pn(usb3_ep, halt, is_clear_feature);
177062306a36Sopenharmony_ci	else
177162306a36Sopenharmony_ci		ret = usb3_set_halt_p0(usb3_ep, halt);
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci	return ret;
177462306a36Sopenharmony_ci}
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_cistatic bool usb3_std_req_feature_endpoint(struct renesas_usb3 *usb3,
177762306a36Sopenharmony_ci					  struct usb_ctrlrequest *ctrl,
177862306a36Sopenharmony_ci					  bool set)
177962306a36Sopenharmony_ci{
178062306a36Sopenharmony_ci	int num = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
178162306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep;
178262306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req;
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	if (le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT)
178562306a36Sopenharmony_ci		return true;	/* stall */
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	usb3_ep = usb3_get_ep(usb3, num);
178862306a36Sopenharmony_ci	usb3_set_halt(usb3_ep, set, true);
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci	/* Restarts a queue if clear feature */
179162306a36Sopenharmony_ci	if (!set) {
179262306a36Sopenharmony_ci		usb3_ep->started = false;
179362306a36Sopenharmony_ci		usb3_req = usb3_get_request(usb3_ep);
179462306a36Sopenharmony_ci		if (usb3_req)
179562306a36Sopenharmony_ci			usb3_start_pipen(usb3_ep, usb3_req);
179662306a36Sopenharmony_ci	}
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_ci	return false;
179962306a36Sopenharmony_ci}
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_cistatic bool usb3_std_req_feature(struct renesas_usb3 *usb3,
180262306a36Sopenharmony_ci				 struct usb_ctrlrequest *ctrl, bool set)
180362306a36Sopenharmony_ci{
180462306a36Sopenharmony_ci	bool stall = false;
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ci	switch (ctrl->bRequestType & USB_RECIP_MASK) {
180762306a36Sopenharmony_ci	case USB_RECIP_DEVICE:
180862306a36Sopenharmony_ci		stall = usb3_std_req_feature_device(usb3, ctrl, set);
180962306a36Sopenharmony_ci		break;
181062306a36Sopenharmony_ci	case USB_RECIP_INTERFACE:
181162306a36Sopenharmony_ci		break;
181262306a36Sopenharmony_ci	case USB_RECIP_ENDPOINT:
181362306a36Sopenharmony_ci		stall = usb3_std_req_feature_endpoint(usb3, ctrl, set);
181462306a36Sopenharmony_ci		break;
181562306a36Sopenharmony_ci	default:
181662306a36Sopenharmony_ci		stall = true;
181762306a36Sopenharmony_ci		break;
181862306a36Sopenharmony_ci	}
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci	if (!stall)
182162306a36Sopenharmony_ci		usb3_set_p0_con_for_no_data(usb3);
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_ci	return stall;
182462306a36Sopenharmony_ci}
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_cistatic void usb3_pipe0_set_sel_completion(struct usb_ep *ep,
182762306a36Sopenharmony_ci					  struct usb_request *req)
182862306a36Sopenharmony_ci{
182962306a36Sopenharmony_ci	/* TODO */
183062306a36Sopenharmony_ci}
183162306a36Sopenharmony_ci
183262306a36Sopenharmony_cistatic bool usb3_std_req_set_sel(struct renesas_usb3 *usb3,
183362306a36Sopenharmony_ci				 struct usb_ctrlrequest *ctrl)
183462306a36Sopenharmony_ci{
183562306a36Sopenharmony_ci	u16 w_length = le16_to_cpu(ctrl->wLength);
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_ci	if (w_length != 6)
183862306a36Sopenharmony_ci		return true;	/* stall */
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_ci	dev_dbg(usb3_to_dev(usb3), "set_sel: req = %p\n",
184162306a36Sopenharmony_ci		usb_req_to_usb3_req(usb3->ep0_req));
184262306a36Sopenharmony_ci	usb3_pipe0_internal_xfer(usb3, NULL, 6, usb3_pipe0_set_sel_completion);
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci	return false;
184562306a36Sopenharmony_ci}
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_cistatic bool usb3_std_req_set_configuration(struct renesas_usb3 *usb3,
184862306a36Sopenharmony_ci					   struct usb_ctrlrequest *ctrl)
184962306a36Sopenharmony_ci{
185062306a36Sopenharmony_ci	if (le16_to_cpu(ctrl->wValue) > 0)
185162306a36Sopenharmony_ci		usb3_set_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
185262306a36Sopenharmony_ci	else
185362306a36Sopenharmony_ci		usb3_clear_bit(usb3, USB_COM_CON_CONF, USB3_USB_COM_CON);
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	return false;
185662306a36Sopenharmony_ci}
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci/**
185962306a36Sopenharmony_ci * usb3_handle_standard_request - handle some standard requests
186062306a36Sopenharmony_ci * @usb3: the renesas_usb3 pointer
186162306a36Sopenharmony_ci * @ctrl: a pointer of setup data
186262306a36Sopenharmony_ci *
186362306a36Sopenharmony_ci * Returns true if this function handled a standard request
186462306a36Sopenharmony_ci */
186562306a36Sopenharmony_cistatic bool usb3_handle_standard_request(struct renesas_usb3 *usb3,
186662306a36Sopenharmony_ci					 struct usb_ctrlrequest *ctrl)
186762306a36Sopenharmony_ci{
186862306a36Sopenharmony_ci	bool ret = false;
186962306a36Sopenharmony_ci	bool stall = false;
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
187262306a36Sopenharmony_ci		switch (ctrl->bRequest) {
187362306a36Sopenharmony_ci		case USB_REQ_SET_ADDRESS:
187462306a36Sopenharmony_ci			stall = usb3_std_req_set_address(usb3, ctrl);
187562306a36Sopenharmony_ci			ret = true;
187662306a36Sopenharmony_ci			break;
187762306a36Sopenharmony_ci		case USB_REQ_GET_STATUS:
187862306a36Sopenharmony_ci			stall = usb3_std_req_get_status(usb3, ctrl);
187962306a36Sopenharmony_ci			ret = true;
188062306a36Sopenharmony_ci			break;
188162306a36Sopenharmony_ci		case USB_REQ_CLEAR_FEATURE:
188262306a36Sopenharmony_ci			stall = usb3_std_req_feature(usb3, ctrl, false);
188362306a36Sopenharmony_ci			ret = true;
188462306a36Sopenharmony_ci			break;
188562306a36Sopenharmony_ci		case USB_REQ_SET_FEATURE:
188662306a36Sopenharmony_ci			stall = usb3_std_req_feature(usb3, ctrl, true);
188762306a36Sopenharmony_ci			ret = true;
188862306a36Sopenharmony_ci			break;
188962306a36Sopenharmony_ci		case USB_REQ_SET_SEL:
189062306a36Sopenharmony_ci			stall = usb3_std_req_set_sel(usb3, ctrl);
189162306a36Sopenharmony_ci			ret = true;
189262306a36Sopenharmony_ci			break;
189362306a36Sopenharmony_ci		case USB_REQ_SET_ISOCH_DELAY:
189462306a36Sopenharmony_ci			/* This hardware doesn't support Isochronous xfer */
189562306a36Sopenharmony_ci			stall = true;
189662306a36Sopenharmony_ci			ret = true;
189762306a36Sopenharmony_ci			break;
189862306a36Sopenharmony_ci		case USB_REQ_SET_CONFIGURATION:
189962306a36Sopenharmony_ci			usb3_std_req_set_configuration(usb3, ctrl);
190062306a36Sopenharmony_ci			break;
190162306a36Sopenharmony_ci		default:
190262306a36Sopenharmony_ci			break;
190362306a36Sopenharmony_ci		}
190462306a36Sopenharmony_ci	}
190562306a36Sopenharmony_ci
190662306a36Sopenharmony_ci	if (stall)
190762306a36Sopenharmony_ci		usb3_set_p0_con_stall(usb3);
190862306a36Sopenharmony_ci
190962306a36Sopenharmony_ci	return ret;
191062306a36Sopenharmony_ci}
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_cistatic int usb3_p0_con_clear_buffer(struct renesas_usb3 *usb3)
191362306a36Sopenharmony_ci{
191462306a36Sopenharmony_ci	usb3_set_bit(usb3, P0_CON_BCLR, USB3_P0_CON);
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci	return usb3_wait(usb3, USB3_P0_CON, P0_CON_BCLR, 0);
191762306a36Sopenharmony_ci}
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_cistatic void usb3_irq_epc_pipe0_setup(struct renesas_usb3 *usb3)
192062306a36Sopenharmony_ci{
192162306a36Sopenharmony_ci	struct usb_ctrlrequest ctrl;
192262306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0);
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci	/* Call giveback function if previous transfer is not completed */
192562306a36Sopenharmony_ci	if (usb3_ep->started)
192662306a36Sopenharmony_ci		usb3_request_done(usb3_ep, usb3_get_request(usb3_ep),
192762306a36Sopenharmony_ci				  -ECONNRESET);
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci	usb3_p0_con_clear_buffer(usb3);
193062306a36Sopenharmony_ci	usb3_get_setup_data(usb3, &ctrl);
193162306a36Sopenharmony_ci	if (!usb3_handle_standard_request(usb3, &ctrl))
193262306a36Sopenharmony_ci		if (usb3->driver->setup(&usb3->gadget, &ctrl) < 0)
193362306a36Sopenharmony_ci			usb3_set_p0_con_stall(usb3);
193462306a36Sopenharmony_ci}
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_cistatic void usb3_irq_epc_pipe0_bfrdy(struct renesas_usb3 *usb3)
193762306a36Sopenharmony_ci{
193862306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, 0);
193962306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci	if (!usb3_req)
194262306a36Sopenharmony_ci		return;
194362306a36Sopenharmony_ci
194462306a36Sopenharmony_ci	usb3_p0_xfer(usb3_ep, usb3_req);
194562306a36Sopenharmony_ci}
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_cistatic void usb3_irq_epc_pipe0(struct renesas_usb3 *usb3)
194862306a36Sopenharmony_ci{
194962306a36Sopenharmony_ci	u32 p0_int_sta = usb3_read(usb3, USB3_P0_INT_STA);
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_ci	p0_int_sta &= usb3_read(usb3, USB3_P0_INT_ENA);
195262306a36Sopenharmony_ci	usb3_write(usb3, p0_int_sta, USB3_P0_INT_STA);
195362306a36Sopenharmony_ci	if (p0_int_sta & P0_INT_STSED)
195462306a36Sopenharmony_ci		usb3_irq_epc_pipe0_status_end(usb3);
195562306a36Sopenharmony_ci	if (p0_int_sta & P0_INT_SETUP)
195662306a36Sopenharmony_ci		usb3_irq_epc_pipe0_setup(usb3);
195762306a36Sopenharmony_ci	if (p0_int_sta & P0_INT_BFRDY)
195862306a36Sopenharmony_ci		usb3_irq_epc_pipe0_bfrdy(usb3);
195962306a36Sopenharmony_ci}
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_cistatic void usb3_request_done_pipen(struct renesas_usb3 *usb3,
196262306a36Sopenharmony_ci				    struct renesas_usb3_ep *usb3_ep,
196362306a36Sopenharmony_ci				    struct renesas_usb3_request *usb3_req,
196462306a36Sopenharmony_ci				    int status)
196562306a36Sopenharmony_ci{
196662306a36Sopenharmony_ci	unsigned long flags;
196762306a36Sopenharmony_ci
196862306a36Sopenharmony_ci	spin_lock_irqsave(&usb3->lock, flags);
196962306a36Sopenharmony_ci	if (usb3_pn_change(usb3, usb3_ep->num))
197062306a36Sopenharmony_ci		usb3_pn_stop(usb3);
197162306a36Sopenharmony_ci	spin_unlock_irqrestore(&usb3->lock, flags);
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci	usb3_disable_pipe_irq(usb3, usb3_ep->num);
197462306a36Sopenharmony_ci	usb3_request_done(usb3_ep, usb3_req, status);
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci	/* get next usb3_req */
197762306a36Sopenharmony_ci	usb3_req = usb3_get_request(usb3_ep);
197862306a36Sopenharmony_ci	if (usb3_req)
197962306a36Sopenharmony_ci		usb3_start_pipen(usb3_ep, usb3_req);
198062306a36Sopenharmony_ci}
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_cistatic void usb3_irq_epc_pipen_lsttr(struct renesas_usb3 *usb3, int num)
198362306a36Sopenharmony_ci{
198462306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, num);
198562306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
198662306a36Sopenharmony_ci
198762306a36Sopenharmony_ci	if (!usb3_req)
198862306a36Sopenharmony_ci		return;
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci	if (usb3_ep->dir_in) {
199162306a36Sopenharmony_ci		dev_dbg(usb3_to_dev(usb3), "%s: len = %u, actual = %u\n",
199262306a36Sopenharmony_ci			__func__, usb3_req->req.length, usb3_req->req.actual);
199362306a36Sopenharmony_ci		usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0);
199462306a36Sopenharmony_ci	}
199562306a36Sopenharmony_ci}
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_cistatic void usb3_irq_epc_pipen_bfrdy(struct renesas_usb3 *usb3, int num)
199862306a36Sopenharmony_ci{
199962306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, num);
200062306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
200162306a36Sopenharmony_ci	bool done = false;
200262306a36Sopenharmony_ci
200362306a36Sopenharmony_ci	if (!usb3_req)
200462306a36Sopenharmony_ci		return;
200562306a36Sopenharmony_ci
200662306a36Sopenharmony_ci	spin_lock(&usb3->lock);
200762306a36Sopenharmony_ci	if (usb3_pn_change(usb3, num))
200862306a36Sopenharmony_ci		goto out;
200962306a36Sopenharmony_ci
201062306a36Sopenharmony_ci	if (usb3_ep->dir_in) {
201162306a36Sopenharmony_ci		/* Do not stop the IN pipe here to detect LSTTR interrupt */
201262306a36Sopenharmony_ci		if (!usb3_write_pipe(usb3_ep, usb3_req, USB3_PN_WRITE))
201362306a36Sopenharmony_ci			usb3_clear_bit(usb3, PN_INT_BFRDY, USB3_PN_INT_ENA);
201462306a36Sopenharmony_ci	} else {
201562306a36Sopenharmony_ci		if (!usb3_read_pipe(usb3_ep, usb3_req, USB3_PN_READ))
201662306a36Sopenharmony_ci			done = true;
201762306a36Sopenharmony_ci	}
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ciout:
202062306a36Sopenharmony_ci	/* need to unlock because usb3_request_done_pipen() locks it */
202162306a36Sopenharmony_ci	spin_unlock(&usb3->lock);
202262306a36Sopenharmony_ci
202362306a36Sopenharmony_ci	if (done)
202462306a36Sopenharmony_ci		usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0);
202562306a36Sopenharmony_ci}
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_cistatic void usb3_irq_epc_pipen(struct renesas_usb3 *usb3, int num)
202862306a36Sopenharmony_ci{
202962306a36Sopenharmony_ci	u32 pn_int_sta;
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_ci	spin_lock(&usb3->lock);
203262306a36Sopenharmony_ci	if (usb3_pn_change(usb3, num) < 0) {
203362306a36Sopenharmony_ci		spin_unlock(&usb3->lock);
203462306a36Sopenharmony_ci		return;
203562306a36Sopenharmony_ci	}
203662306a36Sopenharmony_ci
203762306a36Sopenharmony_ci	pn_int_sta = usb3_read(usb3, USB3_PN_INT_STA);
203862306a36Sopenharmony_ci	pn_int_sta &= usb3_read(usb3, USB3_PN_INT_ENA);
203962306a36Sopenharmony_ci	usb3_write(usb3, pn_int_sta, USB3_PN_INT_STA);
204062306a36Sopenharmony_ci	spin_unlock(&usb3->lock);
204162306a36Sopenharmony_ci	if (pn_int_sta & PN_INT_LSTTR)
204262306a36Sopenharmony_ci		usb3_irq_epc_pipen_lsttr(usb3, num);
204362306a36Sopenharmony_ci	if (pn_int_sta & PN_INT_BFRDY)
204462306a36Sopenharmony_ci		usb3_irq_epc_pipen_bfrdy(usb3, num);
204562306a36Sopenharmony_ci}
204662306a36Sopenharmony_ci
204762306a36Sopenharmony_cistatic void usb3_irq_epc_int_2(struct renesas_usb3 *usb3, u32 int_sta_2)
204862306a36Sopenharmony_ci{
204962306a36Sopenharmony_ci	int i;
205062306a36Sopenharmony_ci
205162306a36Sopenharmony_ci	for (i = 0; i < usb3->num_usb3_eps; i++) {
205262306a36Sopenharmony_ci		if (int_sta_2 & USB_INT_2_PIPE(i)) {
205362306a36Sopenharmony_ci			if (!i)
205462306a36Sopenharmony_ci				usb3_irq_epc_pipe0(usb3);
205562306a36Sopenharmony_ci			else
205662306a36Sopenharmony_ci				usb3_irq_epc_pipen(usb3, i);
205762306a36Sopenharmony_ci		}
205862306a36Sopenharmony_ci	}
205962306a36Sopenharmony_ci}
206062306a36Sopenharmony_ci
206162306a36Sopenharmony_cistatic void usb3_irq_idmon_change(struct renesas_usb3 *usb3)
206262306a36Sopenharmony_ci{
206362306a36Sopenharmony_ci	usb3_check_id(usb3);
206462306a36Sopenharmony_ci}
206562306a36Sopenharmony_ci
206662306a36Sopenharmony_cistatic void usb3_irq_otg_int(struct renesas_usb3 *usb3)
206762306a36Sopenharmony_ci{
206862306a36Sopenharmony_ci	u32 otg_int_sta = usb3_drd_read(usb3, USB3_USB_OTG_INT_STA(usb3));
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_ci	otg_int_sta &= usb3_drd_read(usb3, USB3_USB_OTG_INT_ENA(usb3));
207162306a36Sopenharmony_ci	if (otg_int_sta)
207262306a36Sopenharmony_ci		usb3_drd_write(usb3, otg_int_sta, USB3_USB_OTG_INT_STA(usb3));
207362306a36Sopenharmony_ci
207462306a36Sopenharmony_ci	if (otg_int_sta & USB_OTG_IDMON(usb3))
207562306a36Sopenharmony_ci		usb3_irq_idmon_change(usb3);
207662306a36Sopenharmony_ci}
207762306a36Sopenharmony_ci
207862306a36Sopenharmony_cistatic void usb3_irq_epc(struct renesas_usb3 *usb3)
207962306a36Sopenharmony_ci{
208062306a36Sopenharmony_ci	u32 int_sta_1 = usb3_read(usb3, USB3_USB_INT_STA_1);
208162306a36Sopenharmony_ci	u32 int_sta_2 = usb3_read(usb3, USB3_USB_INT_STA_2);
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	int_sta_1 &= usb3_read(usb3, USB3_USB_INT_ENA_1);
208462306a36Sopenharmony_ci	if (int_sta_1) {
208562306a36Sopenharmony_ci		usb3_write(usb3, int_sta_1, USB3_USB_INT_STA_1);
208662306a36Sopenharmony_ci		usb3_irq_epc_int_1(usb3, int_sta_1);
208762306a36Sopenharmony_ci	}
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci	int_sta_2 &= usb3_read(usb3, USB3_USB_INT_ENA_2);
209062306a36Sopenharmony_ci	if (int_sta_2)
209162306a36Sopenharmony_ci		usb3_irq_epc_int_2(usb3, int_sta_2);
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_ci	if (!usb3->is_rzv2m)
209462306a36Sopenharmony_ci		usb3_irq_otg_int(usb3);
209562306a36Sopenharmony_ci}
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_cistatic void usb3_irq_dma_int(struct renesas_usb3 *usb3, u32 dma_sta)
209862306a36Sopenharmony_ci{
209962306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep;
210062306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req;
210162306a36Sopenharmony_ci	int i, status;
210262306a36Sopenharmony_ci
210362306a36Sopenharmony_ci	for (i = 0; i < usb3->num_usb3_eps; i++) {
210462306a36Sopenharmony_ci		if (!(dma_sta & DMA_INT(i)))
210562306a36Sopenharmony_ci			continue;
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ci		usb3_ep = usb3_get_ep(usb3, i);
210862306a36Sopenharmony_ci		if (!(usb3_read(usb3, USB3_AXI_INT_STA) &
210962306a36Sopenharmony_ci		    AXI_INT_PRDEN_CLR_STA(usb3_ep->dma->num)))
211062306a36Sopenharmony_ci			continue;
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ci		usb3_req = usb3_get_request(usb3_ep);
211362306a36Sopenharmony_ci		status = usb3_dma_try_stop(usb3_ep, usb3_req);
211462306a36Sopenharmony_ci		usb3_request_done_pipen(usb3, usb3_ep, usb3_req, status);
211562306a36Sopenharmony_ci	}
211662306a36Sopenharmony_ci}
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_cistatic void usb3_irq_dma(struct renesas_usb3 *usb3)
211962306a36Sopenharmony_ci{
212062306a36Sopenharmony_ci	u32 dma_sta = usb3_read(usb3, USB3_DMA_INT_STA);
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	dma_sta &= usb3_read(usb3, USB3_DMA_INT_ENA);
212362306a36Sopenharmony_ci	if (dma_sta) {
212462306a36Sopenharmony_ci		usb3_write(usb3, dma_sta, USB3_DMA_INT_STA);
212562306a36Sopenharmony_ci		usb3_irq_dma_int(usb3, dma_sta);
212662306a36Sopenharmony_ci	}
212762306a36Sopenharmony_ci}
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_cistatic irqreturn_t renesas_usb3_irq(int irq, void *_usb3)
213062306a36Sopenharmony_ci{
213162306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = _usb3;
213262306a36Sopenharmony_ci	irqreturn_t ret = IRQ_NONE;
213362306a36Sopenharmony_ci	u32 axi_int_sta = usb3_read(usb3, USB3_AXI_INT_STA);
213462306a36Sopenharmony_ci
213562306a36Sopenharmony_ci	if (axi_int_sta & AXI_INT_DMAINT) {
213662306a36Sopenharmony_ci		usb3_irq_dma(usb3);
213762306a36Sopenharmony_ci		ret = IRQ_HANDLED;
213862306a36Sopenharmony_ci	}
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ci	if (axi_int_sta & AXI_INT_EPCINT) {
214162306a36Sopenharmony_ci		usb3_irq_epc(usb3);
214262306a36Sopenharmony_ci		ret = IRQ_HANDLED;
214362306a36Sopenharmony_ci	}
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_ci	return ret;
214662306a36Sopenharmony_ci}
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_cistatic irqreturn_t renesas_usb3_otg_irq(int irq, void *_usb3)
214962306a36Sopenharmony_ci{
215062306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = _usb3;
215162306a36Sopenharmony_ci
215262306a36Sopenharmony_ci	usb3_irq_otg_int(usb3);
215362306a36Sopenharmony_ci
215462306a36Sopenharmony_ci	return IRQ_HANDLED;
215562306a36Sopenharmony_ci}
215662306a36Sopenharmony_ci
215762306a36Sopenharmony_cistatic void usb3_write_pn_mod(struct renesas_usb3_ep *usb3_ep,
215862306a36Sopenharmony_ci			      const struct usb_endpoint_descriptor *desc)
215962306a36Sopenharmony_ci{
216062306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
216162306a36Sopenharmony_ci	u32 val = 0;
216262306a36Sopenharmony_ci
216362306a36Sopenharmony_ci	val |= usb3_ep->dir_in ? PN_MOD_DIR : 0;
216462306a36Sopenharmony_ci	val |= PN_MOD_TYPE(usb_endpoint_type(desc));
216562306a36Sopenharmony_ci	val |= PN_MOD_EPNUM(usb_endpoint_num(desc));
216662306a36Sopenharmony_ci	usb3_write(usb3, val, USB3_PN_MOD);
216762306a36Sopenharmony_ci}
216862306a36Sopenharmony_ci
216962306a36Sopenharmony_cistatic u32 usb3_calc_ramarea(int ram_size)
217062306a36Sopenharmony_ci{
217162306a36Sopenharmony_ci	WARN_ON(ram_size > SZ_16K);
217262306a36Sopenharmony_ci
217362306a36Sopenharmony_ci	if (ram_size <= SZ_1K)
217462306a36Sopenharmony_ci		return PN_RAMMAP_RAMAREA_1KB;
217562306a36Sopenharmony_ci	else if (ram_size <= SZ_2K)
217662306a36Sopenharmony_ci		return PN_RAMMAP_RAMAREA_2KB;
217762306a36Sopenharmony_ci	else if (ram_size <= SZ_4K)
217862306a36Sopenharmony_ci		return PN_RAMMAP_RAMAREA_4KB;
217962306a36Sopenharmony_ci	else if (ram_size <= SZ_8K)
218062306a36Sopenharmony_ci		return PN_RAMMAP_RAMAREA_8KB;
218162306a36Sopenharmony_ci	else
218262306a36Sopenharmony_ci		return PN_RAMMAP_RAMAREA_16KB;
218362306a36Sopenharmony_ci}
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_cistatic u32 usb3_calc_rammap_val(struct renesas_usb3_ep *usb3_ep,
218662306a36Sopenharmony_ci				const struct usb_endpoint_descriptor *desc)
218762306a36Sopenharmony_ci{
218862306a36Sopenharmony_ci	int i;
218962306a36Sopenharmony_ci	static const u32 max_packet_array[] = {8, 16, 32, 64, 512};
219062306a36Sopenharmony_ci	u32 mpkt = PN_RAMMAP_MPKT(1024);
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(max_packet_array); i++) {
219362306a36Sopenharmony_ci		if (usb_endpoint_maxp(desc) <= max_packet_array[i])
219462306a36Sopenharmony_ci			mpkt = PN_RAMMAP_MPKT(max_packet_array[i]);
219562306a36Sopenharmony_ci	}
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_ci	return usb3_ep->rammap_val | mpkt;
219862306a36Sopenharmony_ci}
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_cistatic int usb3_enable_pipe_n(struct renesas_usb3_ep *usb3_ep,
220162306a36Sopenharmony_ci			      const struct usb_endpoint_descriptor *desc)
220262306a36Sopenharmony_ci{
220362306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
220462306a36Sopenharmony_ci	unsigned long flags;
220562306a36Sopenharmony_ci
220662306a36Sopenharmony_ci	usb3_ep->dir_in = usb_endpoint_dir_in(desc);
220762306a36Sopenharmony_ci
220862306a36Sopenharmony_ci	spin_lock_irqsave(&usb3->lock, flags);
220962306a36Sopenharmony_ci	if (!usb3_pn_change(usb3, usb3_ep->num)) {
221062306a36Sopenharmony_ci		usb3_write_pn_mod(usb3_ep, desc);
221162306a36Sopenharmony_ci		usb3_write(usb3, usb3_calc_rammap_val(usb3_ep, desc),
221262306a36Sopenharmony_ci			   USB3_PN_RAMMAP);
221362306a36Sopenharmony_ci		usb3_pn_con_clear(usb3);
221462306a36Sopenharmony_ci		usb3_set_bit(usb3, PN_CON_EN, USB3_PN_CON);
221562306a36Sopenharmony_ci	}
221662306a36Sopenharmony_ci	spin_unlock_irqrestore(&usb3->lock, flags);
221762306a36Sopenharmony_ci
221862306a36Sopenharmony_ci	return 0;
221962306a36Sopenharmony_ci}
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_cistatic int usb3_disable_pipe_n(struct renesas_usb3_ep *usb3_ep)
222262306a36Sopenharmony_ci{
222362306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
222462306a36Sopenharmony_ci	unsigned long flags;
222562306a36Sopenharmony_ci
222662306a36Sopenharmony_ci	usb3_ep->halt = false;
222762306a36Sopenharmony_ci
222862306a36Sopenharmony_ci	spin_lock_irqsave(&usb3->lock, flags);
222962306a36Sopenharmony_ci	if (!usb3_pn_change(usb3, usb3_ep->num)) {
223062306a36Sopenharmony_ci		usb3_write(usb3, 0, USB3_PN_INT_ENA);
223162306a36Sopenharmony_ci		usb3_write(usb3, 0, USB3_PN_RAMMAP);
223262306a36Sopenharmony_ci		usb3_clear_bit(usb3, PN_CON_EN, USB3_PN_CON);
223362306a36Sopenharmony_ci	}
223462306a36Sopenharmony_ci	spin_unlock_irqrestore(&usb3->lock, flags);
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci	return 0;
223762306a36Sopenharmony_ci}
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ci/*------- usb_ep_ops -----------------------------------------------------*/
224062306a36Sopenharmony_cistatic int renesas_usb3_ep_enable(struct usb_ep *_ep,
224162306a36Sopenharmony_ci				  const struct usb_endpoint_descriptor *desc)
224262306a36Sopenharmony_ci{
224362306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_ci	return usb3_enable_pipe_n(usb3_ep, desc);
224662306a36Sopenharmony_ci}
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_cistatic int renesas_usb3_ep_disable(struct usb_ep *_ep)
224962306a36Sopenharmony_ci{
225062306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
225162306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req;
225262306a36Sopenharmony_ci
225362306a36Sopenharmony_ci	do {
225462306a36Sopenharmony_ci		usb3_req = usb3_get_request(usb3_ep);
225562306a36Sopenharmony_ci		if (!usb3_req)
225662306a36Sopenharmony_ci			break;
225762306a36Sopenharmony_ci		usb3_dma_try_stop(usb3_ep, usb3_req);
225862306a36Sopenharmony_ci		usb3_request_done(usb3_ep, usb3_req, -ESHUTDOWN);
225962306a36Sopenharmony_ci	} while (1);
226062306a36Sopenharmony_ci
226162306a36Sopenharmony_ci	return usb3_disable_pipe_n(usb3_ep);
226262306a36Sopenharmony_ci}
226362306a36Sopenharmony_ci
226462306a36Sopenharmony_cistatic struct usb_request *__renesas_usb3_ep_alloc_request(gfp_t gfp_flags)
226562306a36Sopenharmony_ci{
226662306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req;
226762306a36Sopenharmony_ci
226862306a36Sopenharmony_ci	usb3_req = kzalloc(sizeof(struct renesas_usb3_request), gfp_flags);
226962306a36Sopenharmony_ci	if (!usb3_req)
227062306a36Sopenharmony_ci		return NULL;
227162306a36Sopenharmony_ci
227262306a36Sopenharmony_ci	INIT_LIST_HEAD(&usb3_req->queue);
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ci	return &usb3_req->req;
227562306a36Sopenharmony_ci}
227662306a36Sopenharmony_ci
227762306a36Sopenharmony_cistatic void __renesas_usb3_ep_free_request(struct usb_request *_req)
227862306a36Sopenharmony_ci{
227962306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req = usb_req_to_usb3_req(_req);
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci	kfree(usb3_req);
228262306a36Sopenharmony_ci}
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_cistatic struct usb_request *renesas_usb3_ep_alloc_request(struct usb_ep *_ep,
228562306a36Sopenharmony_ci							 gfp_t gfp_flags)
228662306a36Sopenharmony_ci{
228762306a36Sopenharmony_ci	return __renesas_usb3_ep_alloc_request(gfp_flags);
228862306a36Sopenharmony_ci}
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_cistatic void renesas_usb3_ep_free_request(struct usb_ep *_ep,
229162306a36Sopenharmony_ci					 struct usb_request *_req)
229262306a36Sopenharmony_ci{
229362306a36Sopenharmony_ci	__renesas_usb3_ep_free_request(_req);
229462306a36Sopenharmony_ci}
229562306a36Sopenharmony_ci
229662306a36Sopenharmony_cistatic int renesas_usb3_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
229762306a36Sopenharmony_ci{
229862306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
229962306a36Sopenharmony_ci	struct renesas_usb3_request *usb3_req = usb_req_to_usb3_req(_req);
230062306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
230162306a36Sopenharmony_ci
230262306a36Sopenharmony_ci	dev_dbg(usb3_to_dev(usb3), "ep_dequeue: ep%2d, %u\n", usb3_ep->num,
230362306a36Sopenharmony_ci		_req->length);
230462306a36Sopenharmony_ci
230562306a36Sopenharmony_ci	usb3_dma_try_stop(usb3_ep, usb3_req);
230662306a36Sopenharmony_ci	usb3_request_done_pipen(usb3, usb3_ep, usb3_req, -ECONNRESET);
230762306a36Sopenharmony_ci
230862306a36Sopenharmony_ci	return 0;
230962306a36Sopenharmony_ci}
231062306a36Sopenharmony_ci
231162306a36Sopenharmony_cistatic int renesas_usb3_ep_set_halt(struct usb_ep *_ep, int value)
231262306a36Sopenharmony_ci{
231362306a36Sopenharmony_ci	return usb3_set_halt(usb_ep_to_usb3_ep(_ep), !!value, false);
231462306a36Sopenharmony_ci}
231562306a36Sopenharmony_ci
231662306a36Sopenharmony_cistatic int renesas_usb3_ep_set_wedge(struct usb_ep *_ep)
231762306a36Sopenharmony_ci{
231862306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
231962306a36Sopenharmony_ci
232062306a36Sopenharmony_ci	usb3_ep->wedge = true;
232162306a36Sopenharmony_ci	return usb3_set_halt(usb3_ep, true, false);
232262306a36Sopenharmony_ci}
232362306a36Sopenharmony_ci
232462306a36Sopenharmony_cistatic void renesas_usb3_ep_fifo_flush(struct usb_ep *_ep)
232562306a36Sopenharmony_ci{
232662306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep = usb_ep_to_usb3_ep(_ep);
232762306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
232862306a36Sopenharmony_ci	unsigned long flags;
232962306a36Sopenharmony_ci
233062306a36Sopenharmony_ci	if (usb3_ep->num) {
233162306a36Sopenharmony_ci		spin_lock_irqsave(&usb3->lock, flags);
233262306a36Sopenharmony_ci		if (!usb3_pn_change(usb3, usb3_ep->num)) {
233362306a36Sopenharmony_ci			usb3_pn_con_clear(usb3);
233462306a36Sopenharmony_ci			usb3_set_bit(usb3, PN_CON_EN, USB3_PN_CON);
233562306a36Sopenharmony_ci		}
233662306a36Sopenharmony_ci		spin_unlock_irqrestore(&usb3->lock, flags);
233762306a36Sopenharmony_ci	} else {
233862306a36Sopenharmony_ci		usb3_p0_con_clear_buffer(usb3);
233962306a36Sopenharmony_ci	}
234062306a36Sopenharmony_ci}
234162306a36Sopenharmony_ci
234262306a36Sopenharmony_cistatic const struct usb_ep_ops renesas_usb3_ep_ops = {
234362306a36Sopenharmony_ci	.enable		= renesas_usb3_ep_enable,
234462306a36Sopenharmony_ci	.disable	= renesas_usb3_ep_disable,
234562306a36Sopenharmony_ci
234662306a36Sopenharmony_ci	.alloc_request	= renesas_usb3_ep_alloc_request,
234762306a36Sopenharmony_ci	.free_request	= renesas_usb3_ep_free_request,
234862306a36Sopenharmony_ci
234962306a36Sopenharmony_ci	.queue		= renesas_usb3_ep_queue,
235062306a36Sopenharmony_ci	.dequeue	= renesas_usb3_ep_dequeue,
235162306a36Sopenharmony_ci
235262306a36Sopenharmony_ci	.set_halt	= renesas_usb3_ep_set_halt,
235362306a36Sopenharmony_ci	.set_wedge	= renesas_usb3_ep_set_wedge,
235462306a36Sopenharmony_ci	.fifo_flush	= renesas_usb3_ep_fifo_flush,
235562306a36Sopenharmony_ci};
235662306a36Sopenharmony_ci
235762306a36Sopenharmony_ci/*------- usb_gadget_ops -------------------------------------------------*/
235862306a36Sopenharmony_cistatic int renesas_usb3_start(struct usb_gadget *gadget,
235962306a36Sopenharmony_ci			      struct usb_gadget_driver *driver)
236062306a36Sopenharmony_ci{
236162306a36Sopenharmony_ci	struct renesas_usb3 *usb3;
236262306a36Sopenharmony_ci
236362306a36Sopenharmony_ci	if (!driver || driver->max_speed < USB_SPEED_FULL ||
236462306a36Sopenharmony_ci	    !driver->setup)
236562306a36Sopenharmony_ci		return -EINVAL;
236662306a36Sopenharmony_ci
236762306a36Sopenharmony_ci	usb3 = gadget_to_renesas_usb3(gadget);
236862306a36Sopenharmony_ci
236962306a36Sopenharmony_ci	if (usb3->is_rzv2m && usb3_is_a_device(usb3))
237062306a36Sopenharmony_ci		return -EBUSY;
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci	/* hook up the driver */
237362306a36Sopenharmony_ci	usb3->driver = driver;
237462306a36Sopenharmony_ci
237562306a36Sopenharmony_ci	if (usb3->phy)
237662306a36Sopenharmony_ci		phy_init(usb3->phy);
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci	pm_runtime_get_sync(usb3_to_dev(usb3));
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_ci	/* Peripheral Reset */
238162306a36Sopenharmony_ci	if (usb3->is_rzv2m)
238262306a36Sopenharmony_ci		rzv2m_usb3drd_reset(usb3_to_dev(usb3)->parent, false);
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_ci	renesas_usb3_init_controller(usb3);
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	return 0;
238762306a36Sopenharmony_ci}
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_cistatic int renesas_usb3_stop(struct usb_gadget *gadget)
239062306a36Sopenharmony_ci{
239162306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = gadget_to_renesas_usb3(gadget);
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	usb3->softconnect = false;
239462306a36Sopenharmony_ci	usb3->gadget.speed = USB_SPEED_UNKNOWN;
239562306a36Sopenharmony_ci	usb3->driver = NULL;
239662306a36Sopenharmony_ci	if (usb3->is_rzv2m)
239762306a36Sopenharmony_ci		rzv2m_usb3drd_reset(usb3_to_dev(usb3)->parent, false);
239862306a36Sopenharmony_ci
239962306a36Sopenharmony_ci	renesas_usb3_stop_controller(usb3);
240062306a36Sopenharmony_ci	if (usb3->phy)
240162306a36Sopenharmony_ci		phy_exit(usb3->phy);
240262306a36Sopenharmony_ci
240362306a36Sopenharmony_ci	pm_runtime_put(usb3_to_dev(usb3));
240462306a36Sopenharmony_ci
240562306a36Sopenharmony_ci	return 0;
240662306a36Sopenharmony_ci}
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_cistatic int renesas_usb3_get_frame(struct usb_gadget *_gadget)
240962306a36Sopenharmony_ci{
241062306a36Sopenharmony_ci	return -EOPNOTSUPP;
241162306a36Sopenharmony_ci}
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_cistatic int renesas_usb3_pullup(struct usb_gadget *gadget, int is_on)
241462306a36Sopenharmony_ci{
241562306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = gadget_to_renesas_usb3(gadget);
241662306a36Sopenharmony_ci
241762306a36Sopenharmony_ci	usb3->softconnect = !!is_on;
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ci	return 0;
242062306a36Sopenharmony_ci}
242162306a36Sopenharmony_ci
242262306a36Sopenharmony_cistatic int renesas_usb3_set_selfpowered(struct usb_gadget *gadget, int is_self)
242362306a36Sopenharmony_ci{
242462306a36Sopenharmony_ci	gadget->is_selfpowered = !!is_self;
242562306a36Sopenharmony_ci
242662306a36Sopenharmony_ci	return 0;
242762306a36Sopenharmony_ci}
242862306a36Sopenharmony_ci
242962306a36Sopenharmony_cistatic const struct usb_gadget_ops renesas_usb3_gadget_ops = {
243062306a36Sopenharmony_ci	.get_frame		= renesas_usb3_get_frame,
243162306a36Sopenharmony_ci	.udc_start		= renesas_usb3_start,
243262306a36Sopenharmony_ci	.udc_stop		= renesas_usb3_stop,
243362306a36Sopenharmony_ci	.pullup			= renesas_usb3_pullup,
243462306a36Sopenharmony_ci	.set_selfpowered	= renesas_usb3_set_selfpowered,
243562306a36Sopenharmony_ci};
243662306a36Sopenharmony_ci
243762306a36Sopenharmony_cistatic enum usb_role renesas_usb3_role_switch_get(struct usb_role_switch *sw)
243862306a36Sopenharmony_ci{
243962306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb_role_switch_get_drvdata(sw);
244062306a36Sopenharmony_ci	enum usb_role cur_role;
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	pm_runtime_get_sync(usb3_to_dev(usb3));
244362306a36Sopenharmony_ci	cur_role = usb3_is_host(usb3) ? USB_ROLE_HOST : USB_ROLE_DEVICE;
244462306a36Sopenharmony_ci	pm_runtime_put(usb3_to_dev(usb3));
244562306a36Sopenharmony_ci
244662306a36Sopenharmony_ci	return cur_role;
244762306a36Sopenharmony_ci}
244862306a36Sopenharmony_ci
244962306a36Sopenharmony_cistatic void handle_ext_role_switch_states(struct device *dev,
245062306a36Sopenharmony_ci					    enum usb_role role)
245162306a36Sopenharmony_ci{
245262306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
245362306a36Sopenharmony_ci	struct device *host = usb3->host_dev;
245462306a36Sopenharmony_ci	enum usb_role cur_role = renesas_usb3_role_switch_get(usb3->role_sw);
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	switch (role) {
245762306a36Sopenharmony_ci	case USB_ROLE_NONE:
245862306a36Sopenharmony_ci		usb3->connection_state = USB_ROLE_NONE;
245962306a36Sopenharmony_ci		if (!usb3->is_rzv2m && cur_role == USB_ROLE_HOST)
246062306a36Sopenharmony_ci			device_release_driver(host);
246162306a36Sopenharmony_ci		if (usb3->driver) {
246262306a36Sopenharmony_ci			if (usb3->is_rzv2m)
246362306a36Sopenharmony_ci				rzv2m_usb3drd_reset(dev->parent, false);
246462306a36Sopenharmony_ci			usb3_disconnect(usb3);
246562306a36Sopenharmony_ci		}
246662306a36Sopenharmony_ci		usb3_vbus_out(usb3, false);
246762306a36Sopenharmony_ci
246862306a36Sopenharmony_ci		if (usb3->is_rzv2m) {
246962306a36Sopenharmony_ci			rzv2m_usb3drd_reset(dev->parent, true);
247062306a36Sopenharmony_ci			device_release_driver(host);
247162306a36Sopenharmony_ci		}
247262306a36Sopenharmony_ci		break;
247362306a36Sopenharmony_ci	case USB_ROLE_DEVICE:
247462306a36Sopenharmony_ci		if (usb3->connection_state == USB_ROLE_NONE) {
247562306a36Sopenharmony_ci			usb3->connection_state = USB_ROLE_DEVICE;
247662306a36Sopenharmony_ci			usb3_set_mode(usb3, false);
247762306a36Sopenharmony_ci			if (usb3->driver) {
247862306a36Sopenharmony_ci				if (usb3->is_rzv2m)
247962306a36Sopenharmony_ci					renesas_usb3_init_controller(usb3);
248062306a36Sopenharmony_ci				usb3_connect(usb3);
248162306a36Sopenharmony_ci			}
248262306a36Sopenharmony_ci		} else if (cur_role == USB_ROLE_HOST)  {
248362306a36Sopenharmony_ci			device_release_driver(host);
248462306a36Sopenharmony_ci			usb3_set_mode(usb3, false);
248562306a36Sopenharmony_ci			if (usb3->driver)
248662306a36Sopenharmony_ci				usb3_connect(usb3);
248762306a36Sopenharmony_ci		}
248862306a36Sopenharmony_ci		usb3_vbus_out(usb3, false);
248962306a36Sopenharmony_ci		break;
249062306a36Sopenharmony_ci	case USB_ROLE_HOST:
249162306a36Sopenharmony_ci		if (usb3->connection_state == USB_ROLE_NONE) {
249262306a36Sopenharmony_ci			if (usb3->driver) {
249362306a36Sopenharmony_ci				if (usb3->is_rzv2m)
249462306a36Sopenharmony_ci					rzv2m_usb3drd_reset(dev->parent, false);
249562306a36Sopenharmony_ci				usb3_disconnect(usb3);
249662306a36Sopenharmony_ci			}
249762306a36Sopenharmony_ci
249862306a36Sopenharmony_ci			usb3->connection_state = USB_ROLE_HOST;
249962306a36Sopenharmony_ci			usb3_set_mode(usb3, true);
250062306a36Sopenharmony_ci			usb3_vbus_out(usb3, true);
250162306a36Sopenharmony_ci			if (device_attach(host) < 0)
250262306a36Sopenharmony_ci				dev_err(dev, "device_attach(host) failed\n");
250362306a36Sopenharmony_ci		} else if (cur_role == USB_ROLE_DEVICE) {
250462306a36Sopenharmony_ci			usb3_disconnect(usb3);
250562306a36Sopenharmony_ci			/* Must set the mode before device_attach of the host */
250662306a36Sopenharmony_ci			usb3_set_mode(usb3, true);
250762306a36Sopenharmony_ci			/* This device_attach() might sleep */
250862306a36Sopenharmony_ci			if (device_attach(host) < 0)
250962306a36Sopenharmony_ci				dev_err(dev, "device_attach(host) failed\n");
251062306a36Sopenharmony_ci		}
251162306a36Sopenharmony_ci		break;
251262306a36Sopenharmony_ci	default:
251362306a36Sopenharmony_ci		break;
251462306a36Sopenharmony_ci	}
251562306a36Sopenharmony_ci}
251662306a36Sopenharmony_ci
251762306a36Sopenharmony_cistatic void handle_role_switch_states(struct device *dev,
251862306a36Sopenharmony_ci					    enum usb_role role)
251962306a36Sopenharmony_ci{
252062306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
252162306a36Sopenharmony_ci	struct device *host = usb3->host_dev;
252262306a36Sopenharmony_ci	enum usb_role cur_role = renesas_usb3_role_switch_get(usb3->role_sw);
252362306a36Sopenharmony_ci
252462306a36Sopenharmony_ci	if (cur_role == USB_ROLE_HOST && role == USB_ROLE_DEVICE) {
252562306a36Sopenharmony_ci		device_release_driver(host);
252662306a36Sopenharmony_ci		usb3_set_mode(usb3, false);
252762306a36Sopenharmony_ci	} else if (cur_role == USB_ROLE_DEVICE && role == USB_ROLE_HOST) {
252862306a36Sopenharmony_ci		/* Must set the mode before device_attach of the host */
252962306a36Sopenharmony_ci		usb3_set_mode(usb3, true);
253062306a36Sopenharmony_ci		/* This device_attach() might sleep */
253162306a36Sopenharmony_ci		if (device_attach(host) < 0)
253262306a36Sopenharmony_ci			dev_err(dev, "device_attach(host) failed\n");
253362306a36Sopenharmony_ci	}
253462306a36Sopenharmony_ci}
253562306a36Sopenharmony_ci
253662306a36Sopenharmony_cistatic int renesas_usb3_role_switch_set(struct usb_role_switch *sw,
253762306a36Sopenharmony_ci					enum usb_role role)
253862306a36Sopenharmony_ci{
253962306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = usb_role_switch_get_drvdata(sw);
254062306a36Sopenharmony_ci
254162306a36Sopenharmony_ci	pm_runtime_get_sync(usb3_to_dev(usb3));
254262306a36Sopenharmony_ci
254362306a36Sopenharmony_ci	if (usb3->role_sw_by_connector)
254462306a36Sopenharmony_ci		handle_ext_role_switch_states(usb3_to_dev(usb3), role);
254562306a36Sopenharmony_ci	else
254662306a36Sopenharmony_ci		handle_role_switch_states(usb3_to_dev(usb3), role);
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci	pm_runtime_put(usb3_to_dev(usb3));
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci	return 0;
255162306a36Sopenharmony_ci}
255262306a36Sopenharmony_ci
255362306a36Sopenharmony_cistatic ssize_t role_store(struct device *dev, struct device_attribute *attr,
255462306a36Sopenharmony_ci			  const char *buf, size_t count)
255562306a36Sopenharmony_ci{
255662306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
255762306a36Sopenharmony_ci	bool new_mode_is_host;
255862306a36Sopenharmony_ci
255962306a36Sopenharmony_ci	if (!usb3->driver)
256062306a36Sopenharmony_ci		return -ENODEV;
256162306a36Sopenharmony_ci
256262306a36Sopenharmony_ci	if (usb3->forced_b_device)
256362306a36Sopenharmony_ci		return -EBUSY;
256462306a36Sopenharmony_ci
256562306a36Sopenharmony_ci	if (sysfs_streq(buf, "host"))
256662306a36Sopenharmony_ci		new_mode_is_host = true;
256762306a36Sopenharmony_ci	else if (sysfs_streq(buf, "peripheral"))
256862306a36Sopenharmony_ci		new_mode_is_host = false;
256962306a36Sopenharmony_ci	else
257062306a36Sopenharmony_ci		return -EINVAL;
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci	if (new_mode_is_host == usb3_is_host(usb3))
257362306a36Sopenharmony_ci		return -EINVAL;
257462306a36Sopenharmony_ci
257562306a36Sopenharmony_ci	usb3_mode_config(usb3, new_mode_is_host, usb3_is_a_device(usb3));
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_ci	return count;
257862306a36Sopenharmony_ci}
257962306a36Sopenharmony_ci
258062306a36Sopenharmony_cistatic ssize_t role_show(struct device *dev, struct device_attribute *attr,
258162306a36Sopenharmony_ci			 char *buf)
258262306a36Sopenharmony_ci{
258362306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
258462306a36Sopenharmony_ci
258562306a36Sopenharmony_ci	if (!usb3->driver)
258662306a36Sopenharmony_ci		return -ENODEV;
258762306a36Sopenharmony_ci
258862306a36Sopenharmony_ci	return sprintf(buf, "%s\n", usb3_is_host(usb3) ? "host" : "peripheral");
258962306a36Sopenharmony_ci}
259062306a36Sopenharmony_cistatic DEVICE_ATTR_RW(role);
259162306a36Sopenharmony_ci
259262306a36Sopenharmony_cistatic int renesas_usb3_b_device_show(struct seq_file *s, void *unused)
259362306a36Sopenharmony_ci{
259462306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = s->private;
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci	seq_printf(s, "%d\n", usb3->forced_b_device);
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci	return 0;
259962306a36Sopenharmony_ci}
260062306a36Sopenharmony_ci
260162306a36Sopenharmony_cistatic int renesas_usb3_b_device_open(struct inode *inode, struct file *file)
260262306a36Sopenharmony_ci{
260362306a36Sopenharmony_ci	return single_open(file, renesas_usb3_b_device_show, inode->i_private);
260462306a36Sopenharmony_ci}
260562306a36Sopenharmony_ci
260662306a36Sopenharmony_cistatic ssize_t renesas_usb3_b_device_write(struct file *file,
260762306a36Sopenharmony_ci					   const char __user *ubuf,
260862306a36Sopenharmony_ci					   size_t count, loff_t *ppos)
260962306a36Sopenharmony_ci{
261062306a36Sopenharmony_ci	struct seq_file *s = file->private_data;
261162306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = s->private;
261262306a36Sopenharmony_ci	char buf[32];
261362306a36Sopenharmony_ci
261462306a36Sopenharmony_ci	if (!usb3->driver)
261562306a36Sopenharmony_ci		return -ENODEV;
261662306a36Sopenharmony_ci
261762306a36Sopenharmony_ci	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
261862306a36Sopenharmony_ci		return -EFAULT;
261962306a36Sopenharmony_ci
262062306a36Sopenharmony_ci	usb3->start_to_connect = false;
262162306a36Sopenharmony_ci	if (usb3->workaround_for_vbus && usb3->forced_b_device &&
262262306a36Sopenharmony_ci	    !strncmp(buf, "2", 1))
262362306a36Sopenharmony_ci		usb3->start_to_connect = true;
262462306a36Sopenharmony_ci	else if (!strncmp(buf, "1", 1))
262562306a36Sopenharmony_ci		usb3->forced_b_device = true;
262662306a36Sopenharmony_ci	else
262762306a36Sopenharmony_ci		usb3->forced_b_device = false;
262862306a36Sopenharmony_ci
262962306a36Sopenharmony_ci	if (usb3->workaround_for_vbus)
263062306a36Sopenharmony_ci		usb3_disconnect(usb3);
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	/* Let this driver call usb3_connect() if needed */
263362306a36Sopenharmony_ci	usb3_check_id(usb3);
263462306a36Sopenharmony_ci
263562306a36Sopenharmony_ci	return count;
263662306a36Sopenharmony_ci}
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_cistatic const struct file_operations renesas_usb3_b_device_fops = {
263962306a36Sopenharmony_ci	.open = renesas_usb3_b_device_open,
264062306a36Sopenharmony_ci	.write = renesas_usb3_b_device_write,
264162306a36Sopenharmony_ci	.read = seq_read,
264262306a36Sopenharmony_ci	.llseek = seq_lseek,
264362306a36Sopenharmony_ci	.release = single_release,
264462306a36Sopenharmony_ci};
264562306a36Sopenharmony_ci
264662306a36Sopenharmony_cistatic void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3,
264762306a36Sopenharmony_ci				      struct device *dev)
264862306a36Sopenharmony_ci{
264962306a36Sopenharmony_ci	usb3->dentry = debugfs_create_dir(dev_name(dev), usb_debug_root);
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_ci	debugfs_create_file("b_device", 0644, usb3->dentry, usb3,
265262306a36Sopenharmony_ci			    &renesas_usb3_b_device_fops);
265362306a36Sopenharmony_ci}
265462306a36Sopenharmony_ci
265562306a36Sopenharmony_ci/*------- platform_driver ------------------------------------------------*/
265662306a36Sopenharmony_cistatic void renesas_usb3_remove(struct platform_device *pdev)
265762306a36Sopenharmony_ci{
265862306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
265962306a36Sopenharmony_ci
266062306a36Sopenharmony_ci	debugfs_remove_recursive(usb3->dentry);
266162306a36Sopenharmony_ci	device_remove_file(&pdev->dev, &dev_attr_role);
266262306a36Sopenharmony_ci
266362306a36Sopenharmony_ci	cancel_work_sync(&usb3->role_work);
266462306a36Sopenharmony_ci	usb_role_switch_unregister(usb3->role_sw);
266562306a36Sopenharmony_ci
266662306a36Sopenharmony_ci	usb_del_gadget_udc(&usb3->gadget);
266762306a36Sopenharmony_ci	reset_control_assert(usb3->usbp_rstc);
266862306a36Sopenharmony_ci	renesas_usb3_dma_free_prd(usb3, &pdev->dev);
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci	__renesas_usb3_ep_free_request(usb3->ep0_req);
267162306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
267262306a36Sopenharmony_ci}
267362306a36Sopenharmony_ci
267462306a36Sopenharmony_cistatic int renesas_usb3_init_ep(struct renesas_usb3 *usb3, struct device *dev,
267562306a36Sopenharmony_ci				const struct renesas_usb3_priv *priv)
267662306a36Sopenharmony_ci{
267762306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep;
267862306a36Sopenharmony_ci	int i;
267962306a36Sopenharmony_ci
268062306a36Sopenharmony_ci	/* calculate num_usb3_eps from renesas_usb3_priv */
268162306a36Sopenharmony_ci	usb3->num_usb3_eps = priv->ramsize_per_ramif * priv->num_ramif * 2 /
268262306a36Sopenharmony_ci			     priv->ramsize_per_pipe + 1;
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci	if (usb3->num_usb3_eps > USB3_MAX_NUM_PIPES(usb3))
268562306a36Sopenharmony_ci		usb3->num_usb3_eps = USB3_MAX_NUM_PIPES(usb3);
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_ci	usb3->usb3_ep = devm_kcalloc(dev,
268862306a36Sopenharmony_ci				     usb3->num_usb3_eps, sizeof(*usb3_ep),
268962306a36Sopenharmony_ci				     GFP_KERNEL);
269062306a36Sopenharmony_ci	if (!usb3->usb3_ep)
269162306a36Sopenharmony_ci		return -ENOMEM;
269262306a36Sopenharmony_ci
269362306a36Sopenharmony_ci	dev_dbg(dev, "%s: num_usb3_eps = %d\n", __func__, usb3->num_usb3_eps);
269462306a36Sopenharmony_ci	/*
269562306a36Sopenharmony_ci	 * This driver prepares pipes as follows:
269662306a36Sopenharmony_ci	 *  - odd pipes = IN pipe
269762306a36Sopenharmony_ci	 *  - even pipes = OUT pipe (except pipe 0)
269862306a36Sopenharmony_ci	 */
269962306a36Sopenharmony_ci	usb3_for_each_ep(usb3_ep, usb3, i) {
270062306a36Sopenharmony_ci		snprintf(usb3_ep->ep_name, sizeof(usb3_ep->ep_name), "ep%d", i);
270162306a36Sopenharmony_ci		usb3_ep->usb3 = usb3;
270262306a36Sopenharmony_ci		usb3_ep->num = i;
270362306a36Sopenharmony_ci		usb3_ep->ep.name = usb3_ep->ep_name;
270462306a36Sopenharmony_ci		usb3_ep->ep.ops = &renesas_usb3_ep_ops;
270562306a36Sopenharmony_ci		INIT_LIST_HEAD(&usb3_ep->queue);
270662306a36Sopenharmony_ci		INIT_LIST_HEAD(&usb3_ep->ep.ep_list);
270762306a36Sopenharmony_ci		if (!i) {
270862306a36Sopenharmony_ci			/* for control pipe */
270962306a36Sopenharmony_ci			usb3->gadget.ep0 = &usb3_ep->ep;
271062306a36Sopenharmony_ci			usb_ep_set_maxpacket_limit(&usb3_ep->ep,
271162306a36Sopenharmony_ci						USB3_EP0_SS_MAX_PACKET_SIZE);
271262306a36Sopenharmony_ci			usb3_ep->ep.caps.type_control = true;
271362306a36Sopenharmony_ci			usb3_ep->ep.caps.dir_in = true;
271462306a36Sopenharmony_ci			usb3_ep->ep.caps.dir_out = true;
271562306a36Sopenharmony_ci			continue;
271662306a36Sopenharmony_ci		}
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci		/* for bulk or interrupt pipe */
271962306a36Sopenharmony_ci		usb_ep_set_maxpacket_limit(&usb3_ep->ep, ~0);
272062306a36Sopenharmony_ci		list_add_tail(&usb3_ep->ep.ep_list, &usb3->gadget.ep_list);
272162306a36Sopenharmony_ci		usb3_ep->ep.caps.type_bulk = true;
272262306a36Sopenharmony_ci		usb3_ep->ep.caps.type_int = true;
272362306a36Sopenharmony_ci		if (i & 1)
272462306a36Sopenharmony_ci			usb3_ep->ep.caps.dir_in = true;
272562306a36Sopenharmony_ci		else
272662306a36Sopenharmony_ci			usb3_ep->ep.caps.dir_out = true;
272762306a36Sopenharmony_ci	}
272862306a36Sopenharmony_ci
272962306a36Sopenharmony_ci	return 0;
273062306a36Sopenharmony_ci}
273162306a36Sopenharmony_ci
273262306a36Sopenharmony_cistatic void renesas_usb3_init_ram(struct renesas_usb3 *usb3, struct device *dev,
273362306a36Sopenharmony_ci				  const struct renesas_usb3_priv *priv)
273462306a36Sopenharmony_ci{
273562306a36Sopenharmony_ci	struct renesas_usb3_ep *usb3_ep;
273662306a36Sopenharmony_ci	int i;
273762306a36Sopenharmony_ci	u32 ramif[2], basead[2];	/* index 0 = for IN pipes */
273862306a36Sopenharmony_ci	u32 *cur_ramif, *cur_basead;
273962306a36Sopenharmony_ci	u32 val;
274062306a36Sopenharmony_ci
274162306a36Sopenharmony_ci	memset(ramif, 0, sizeof(ramif));
274262306a36Sopenharmony_ci	memset(basead, 0, sizeof(basead));
274362306a36Sopenharmony_ci
274462306a36Sopenharmony_ci	/*
274562306a36Sopenharmony_ci	 * This driver prepares pipes as follows:
274662306a36Sopenharmony_ci	 *  - all pipes = the same size as "ramsize_per_pipe"
274762306a36Sopenharmony_ci	 * Please refer to the "Method of Specifying RAM Mapping"
274862306a36Sopenharmony_ci	 */
274962306a36Sopenharmony_ci	usb3_for_each_ep(usb3_ep, usb3, i) {
275062306a36Sopenharmony_ci		if (!i)
275162306a36Sopenharmony_ci			continue;	/* out of scope if ep num = 0 */
275262306a36Sopenharmony_ci		if (usb3_ep->ep.caps.dir_in) {
275362306a36Sopenharmony_ci			cur_ramif = &ramif[0];
275462306a36Sopenharmony_ci			cur_basead = &basead[0];
275562306a36Sopenharmony_ci		} else {
275662306a36Sopenharmony_ci			cur_ramif = &ramif[1];
275762306a36Sopenharmony_ci			cur_basead = &basead[1];
275862306a36Sopenharmony_ci		}
275962306a36Sopenharmony_ci
276062306a36Sopenharmony_ci		if (*cur_basead > priv->ramsize_per_ramif)
276162306a36Sopenharmony_ci			continue;	/* out of memory for IN or OUT pipe */
276262306a36Sopenharmony_ci
276362306a36Sopenharmony_ci		/* calculate rammap_val */
276462306a36Sopenharmony_ci		val = PN_RAMMAP_RAMIF(*cur_ramif);
276562306a36Sopenharmony_ci		val |= usb3_calc_ramarea(priv->ramsize_per_pipe);
276662306a36Sopenharmony_ci		val |= PN_RAMMAP_BASEAD(*cur_basead);
276762306a36Sopenharmony_ci		usb3_ep->rammap_val = val;
276862306a36Sopenharmony_ci
276962306a36Sopenharmony_ci		dev_dbg(dev, "ep%2d: val = %08x, ramif = %d, base = %x\n",
277062306a36Sopenharmony_ci			i, val, *cur_ramif, *cur_basead);
277162306a36Sopenharmony_ci
277262306a36Sopenharmony_ci		/* update current ramif */
277362306a36Sopenharmony_ci		if (*cur_ramif + 1 == priv->num_ramif) {
277462306a36Sopenharmony_ci			*cur_ramif = 0;
277562306a36Sopenharmony_ci			*cur_basead += priv->ramsize_per_pipe;
277662306a36Sopenharmony_ci		} else {
277762306a36Sopenharmony_ci			(*cur_ramif)++;
277862306a36Sopenharmony_ci		}
277962306a36Sopenharmony_ci	}
278062306a36Sopenharmony_ci}
278162306a36Sopenharmony_ci
278262306a36Sopenharmony_cistatic const struct renesas_usb3_priv renesas_usb3_priv_gen3 = {
278362306a36Sopenharmony_ci	.ramsize_per_ramif = SZ_16K,
278462306a36Sopenharmony_ci	.num_ramif = 4,
278562306a36Sopenharmony_ci	.ramsize_per_pipe = SZ_4K,
278662306a36Sopenharmony_ci};
278762306a36Sopenharmony_ci
278862306a36Sopenharmony_cistatic const struct renesas_usb3_priv renesas_usb3_priv_r8a77990 = {
278962306a36Sopenharmony_ci	.ramsize_per_ramif = SZ_16K,
279062306a36Sopenharmony_ci	.num_ramif = 4,
279162306a36Sopenharmony_ci	.ramsize_per_pipe = SZ_4K,
279262306a36Sopenharmony_ci	.workaround_for_vbus = true,
279362306a36Sopenharmony_ci};
279462306a36Sopenharmony_ci
279562306a36Sopenharmony_cistatic const struct renesas_usb3_priv renesas_usb3_priv_rzv2m = {
279662306a36Sopenharmony_ci	.ramsize_per_ramif = SZ_16K,
279762306a36Sopenharmony_ci	.num_ramif = 1,
279862306a36Sopenharmony_ci	.ramsize_per_pipe = SZ_4K,
279962306a36Sopenharmony_ci	.is_rzv2m = true,
280062306a36Sopenharmony_ci};
280162306a36Sopenharmony_ci
280262306a36Sopenharmony_cistatic const struct of_device_id usb3_of_match[] = {
280362306a36Sopenharmony_ci	{
280462306a36Sopenharmony_ci		.compatible = "renesas,r8a774c0-usb3-peri",
280562306a36Sopenharmony_ci		.data = &renesas_usb3_priv_r8a77990,
280662306a36Sopenharmony_ci	}, {
280762306a36Sopenharmony_ci		.compatible = "renesas,r8a7795-usb3-peri",
280862306a36Sopenharmony_ci		.data = &renesas_usb3_priv_gen3,
280962306a36Sopenharmony_ci	}, {
281062306a36Sopenharmony_ci		.compatible = "renesas,r8a77990-usb3-peri",
281162306a36Sopenharmony_ci		.data = &renesas_usb3_priv_r8a77990,
281262306a36Sopenharmony_ci	}, {
281362306a36Sopenharmony_ci		.compatible = "renesas,rzv2m-usb3-peri",
281462306a36Sopenharmony_ci		.data = &renesas_usb3_priv_rzv2m,
281562306a36Sopenharmony_ci	}, {
281662306a36Sopenharmony_ci		.compatible = "renesas,rcar-gen3-usb3-peri",
281762306a36Sopenharmony_ci		.data = &renesas_usb3_priv_gen3,
281862306a36Sopenharmony_ci	},
281962306a36Sopenharmony_ci	{ },
282062306a36Sopenharmony_ci};
282162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, usb3_of_match);
282262306a36Sopenharmony_ci
282362306a36Sopenharmony_cistatic const unsigned int renesas_usb3_cable[] = {
282462306a36Sopenharmony_ci	EXTCON_USB,
282562306a36Sopenharmony_ci	EXTCON_USB_HOST,
282662306a36Sopenharmony_ci	EXTCON_NONE,
282762306a36Sopenharmony_ci};
282862306a36Sopenharmony_ci
282962306a36Sopenharmony_cistatic struct usb_role_switch_desc renesas_usb3_role_switch_desc = {
283062306a36Sopenharmony_ci	.set = renesas_usb3_role_switch_set,
283162306a36Sopenharmony_ci	.get = renesas_usb3_role_switch_get,
283262306a36Sopenharmony_ci	.allow_userspace_control = true,
283362306a36Sopenharmony_ci};
283462306a36Sopenharmony_ci
283562306a36Sopenharmony_cistatic int renesas_usb3_probe(struct platform_device *pdev)
283662306a36Sopenharmony_ci{
283762306a36Sopenharmony_ci	struct renesas_usb3 *usb3;
283862306a36Sopenharmony_ci	int irq, ret;
283962306a36Sopenharmony_ci	const struct renesas_usb3_priv *priv;
284062306a36Sopenharmony_ci
284162306a36Sopenharmony_ci	priv = of_device_get_match_data(&pdev->dev);
284262306a36Sopenharmony_ci
284362306a36Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
284462306a36Sopenharmony_ci	if (irq < 0)
284562306a36Sopenharmony_ci		return irq;
284662306a36Sopenharmony_ci
284762306a36Sopenharmony_ci	usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL);
284862306a36Sopenharmony_ci	if (!usb3)
284962306a36Sopenharmony_ci		return -ENOMEM;
285062306a36Sopenharmony_ci
285162306a36Sopenharmony_ci	usb3->is_rzv2m = priv->is_rzv2m;
285262306a36Sopenharmony_ci
285362306a36Sopenharmony_ci	usb3->reg = devm_platform_ioremap_resource(pdev, 0);
285462306a36Sopenharmony_ci	if (IS_ERR(usb3->reg))
285562306a36Sopenharmony_ci		return PTR_ERR(usb3->reg);
285662306a36Sopenharmony_ci
285762306a36Sopenharmony_ci	platform_set_drvdata(pdev, usb3);
285862306a36Sopenharmony_ci	spin_lock_init(&usb3->lock);
285962306a36Sopenharmony_ci
286062306a36Sopenharmony_ci	usb3->gadget.ops = &renesas_usb3_gadget_ops;
286162306a36Sopenharmony_ci	usb3->gadget.name = udc_name;
286262306a36Sopenharmony_ci	usb3->gadget.max_speed = USB_SPEED_SUPER;
286362306a36Sopenharmony_ci	INIT_LIST_HEAD(&usb3->gadget.ep_list);
286462306a36Sopenharmony_ci	ret = renesas_usb3_init_ep(usb3, &pdev->dev, priv);
286562306a36Sopenharmony_ci	if (ret < 0)
286662306a36Sopenharmony_ci		return ret;
286762306a36Sopenharmony_ci	renesas_usb3_init_ram(usb3, &pdev->dev, priv);
286862306a36Sopenharmony_ci
286962306a36Sopenharmony_ci	ret = devm_request_irq(&pdev->dev, irq, renesas_usb3_irq, 0,
287062306a36Sopenharmony_ci			       dev_name(&pdev->dev), usb3);
287162306a36Sopenharmony_ci	if (ret < 0)
287262306a36Sopenharmony_ci		return ret;
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_ci	if (usb3->is_rzv2m) {
287562306a36Sopenharmony_ci		struct rzv2m_usb3drd *ddata = dev_get_drvdata(pdev->dev.parent);
287662306a36Sopenharmony_ci
287762306a36Sopenharmony_ci		usb3->drd_reg = ddata->reg;
287862306a36Sopenharmony_ci		ret = devm_request_irq(&pdev->dev, ddata->drd_irq,
287962306a36Sopenharmony_ci				       renesas_usb3_otg_irq, 0,
288062306a36Sopenharmony_ci				       dev_name(&pdev->dev), usb3);
288162306a36Sopenharmony_ci		if (ret < 0)
288262306a36Sopenharmony_ci			return ret;
288362306a36Sopenharmony_ci	}
288462306a36Sopenharmony_ci
288562306a36Sopenharmony_ci	INIT_WORK(&usb3->extcon_work, renesas_usb3_extcon_work);
288662306a36Sopenharmony_ci	usb3->extcon = devm_extcon_dev_allocate(&pdev->dev, renesas_usb3_cable);
288762306a36Sopenharmony_ci	if (IS_ERR(usb3->extcon))
288862306a36Sopenharmony_ci		return PTR_ERR(usb3->extcon);
288962306a36Sopenharmony_ci
289062306a36Sopenharmony_ci	ret = devm_extcon_dev_register(&pdev->dev, usb3->extcon);
289162306a36Sopenharmony_ci	if (ret < 0) {
289262306a36Sopenharmony_ci		dev_err(&pdev->dev, "Failed to register extcon\n");
289362306a36Sopenharmony_ci		return ret;
289462306a36Sopenharmony_ci	}
289562306a36Sopenharmony_ci
289662306a36Sopenharmony_ci	/* for ep0 handling */
289762306a36Sopenharmony_ci	usb3->ep0_req = __renesas_usb3_ep_alloc_request(GFP_KERNEL);
289862306a36Sopenharmony_ci	if (!usb3->ep0_req)
289962306a36Sopenharmony_ci		return -ENOMEM;
290062306a36Sopenharmony_ci
290162306a36Sopenharmony_ci	ret = renesas_usb3_dma_alloc_prd(usb3, &pdev->dev);
290262306a36Sopenharmony_ci	if (ret < 0)
290362306a36Sopenharmony_ci		goto err_alloc_prd;
290462306a36Sopenharmony_ci
290562306a36Sopenharmony_ci	/*
290662306a36Sopenharmony_ci	 * This is optional. So, if this driver cannot get a phy,
290762306a36Sopenharmony_ci	 * this driver will not handle a phy anymore.
290862306a36Sopenharmony_ci	 */
290962306a36Sopenharmony_ci	usb3->phy = devm_phy_optional_get(&pdev->dev, "usb");
291062306a36Sopenharmony_ci	if (IS_ERR(usb3->phy)) {
291162306a36Sopenharmony_ci		ret = PTR_ERR(usb3->phy);
291262306a36Sopenharmony_ci		goto err_add_udc;
291362306a36Sopenharmony_ci	}
291462306a36Sopenharmony_ci
291562306a36Sopenharmony_ci	usb3->usbp_rstc = devm_reset_control_get_optional_shared(&pdev->dev,
291662306a36Sopenharmony_ci								 NULL);
291762306a36Sopenharmony_ci	if (IS_ERR(usb3->usbp_rstc)) {
291862306a36Sopenharmony_ci		ret = PTR_ERR(usb3->usbp_rstc);
291962306a36Sopenharmony_ci		goto err_add_udc;
292062306a36Sopenharmony_ci	}
292162306a36Sopenharmony_ci
292262306a36Sopenharmony_ci	reset_control_deassert(usb3->usbp_rstc);
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_ci	pm_runtime_enable(&pdev->dev);
292562306a36Sopenharmony_ci	ret = usb_add_gadget_udc(&pdev->dev, &usb3->gadget);
292662306a36Sopenharmony_ci	if (ret < 0)
292762306a36Sopenharmony_ci		goto err_reset;
292862306a36Sopenharmony_ci
292962306a36Sopenharmony_ci	ret = device_create_file(&pdev->dev, &dev_attr_role);
293062306a36Sopenharmony_ci	if (ret < 0)
293162306a36Sopenharmony_ci		goto err_dev_create;
293262306a36Sopenharmony_ci
293362306a36Sopenharmony_ci	if (device_property_read_bool(&pdev->dev, "usb-role-switch")) {
293462306a36Sopenharmony_ci		usb3->role_sw_by_connector = true;
293562306a36Sopenharmony_ci		renesas_usb3_role_switch_desc.fwnode = dev_fwnode(&pdev->dev);
293662306a36Sopenharmony_ci	}
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci	renesas_usb3_role_switch_desc.driver_data = usb3;
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci	INIT_WORK(&usb3->role_work, renesas_usb3_role_work);
294162306a36Sopenharmony_ci	usb3->role_sw = usb_role_switch_register(&pdev->dev,
294262306a36Sopenharmony_ci					&renesas_usb3_role_switch_desc);
294362306a36Sopenharmony_ci	if (!IS_ERR(usb3->role_sw)) {
294462306a36Sopenharmony_ci		usb3->host_dev = usb_of_get_companion_dev(&pdev->dev);
294562306a36Sopenharmony_ci		if (!usb3->host_dev) {
294662306a36Sopenharmony_ci			/* If not found, this driver will not use a role sw */
294762306a36Sopenharmony_ci			usb_role_switch_unregister(usb3->role_sw);
294862306a36Sopenharmony_ci			usb3->role_sw = NULL;
294962306a36Sopenharmony_ci		}
295062306a36Sopenharmony_ci	} else {
295162306a36Sopenharmony_ci		usb3->role_sw = NULL;
295262306a36Sopenharmony_ci	}
295362306a36Sopenharmony_ci
295462306a36Sopenharmony_ci	usb3->workaround_for_vbus = priv->workaround_for_vbus;
295562306a36Sopenharmony_ci
295662306a36Sopenharmony_ci	renesas_usb3_debugfs_init(usb3, &pdev->dev);
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_ci	dev_info(&pdev->dev, "probed%s\n", usb3->phy ? " with phy" : "");
295962306a36Sopenharmony_ci
296062306a36Sopenharmony_ci	return 0;
296162306a36Sopenharmony_ci
296262306a36Sopenharmony_cierr_dev_create:
296362306a36Sopenharmony_ci	usb_del_gadget_udc(&usb3->gadget);
296462306a36Sopenharmony_ci
296562306a36Sopenharmony_cierr_reset:
296662306a36Sopenharmony_ci	reset_control_assert(usb3->usbp_rstc);
296762306a36Sopenharmony_ci
296862306a36Sopenharmony_cierr_add_udc:
296962306a36Sopenharmony_ci	renesas_usb3_dma_free_prd(usb3, &pdev->dev);
297062306a36Sopenharmony_ci
297162306a36Sopenharmony_cierr_alloc_prd:
297262306a36Sopenharmony_ci	__renesas_usb3_ep_free_request(usb3->ep0_req);
297362306a36Sopenharmony_ci
297462306a36Sopenharmony_ci	return ret;
297562306a36Sopenharmony_ci}
297662306a36Sopenharmony_ci
297762306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
297862306a36Sopenharmony_cistatic int renesas_usb3_suspend(struct device *dev)
297962306a36Sopenharmony_ci{
298062306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
298162306a36Sopenharmony_ci
298262306a36Sopenharmony_ci	/* Not started */
298362306a36Sopenharmony_ci	if (!usb3->driver)
298462306a36Sopenharmony_ci		return 0;
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci	renesas_usb3_stop_controller(usb3);
298762306a36Sopenharmony_ci	if (usb3->phy)
298862306a36Sopenharmony_ci		phy_exit(usb3->phy);
298962306a36Sopenharmony_ci	pm_runtime_put(dev);
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_ci	return 0;
299262306a36Sopenharmony_ci}
299362306a36Sopenharmony_ci
299462306a36Sopenharmony_cistatic int renesas_usb3_resume(struct device *dev)
299562306a36Sopenharmony_ci{
299662306a36Sopenharmony_ci	struct renesas_usb3 *usb3 = dev_get_drvdata(dev);
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci	/* Not started */
299962306a36Sopenharmony_ci	if (!usb3->driver)
300062306a36Sopenharmony_ci		return 0;
300162306a36Sopenharmony_ci
300262306a36Sopenharmony_ci	if (usb3->phy)
300362306a36Sopenharmony_ci		phy_init(usb3->phy);
300462306a36Sopenharmony_ci	pm_runtime_get_sync(dev);
300562306a36Sopenharmony_ci	renesas_usb3_init_controller(usb3);
300662306a36Sopenharmony_ci
300762306a36Sopenharmony_ci	return 0;
300862306a36Sopenharmony_ci}
300962306a36Sopenharmony_ci#endif
301062306a36Sopenharmony_ci
301162306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(renesas_usb3_pm_ops, renesas_usb3_suspend,
301262306a36Sopenharmony_ci			renesas_usb3_resume);
301362306a36Sopenharmony_ci
301462306a36Sopenharmony_cistatic struct platform_driver renesas_usb3_driver = {
301562306a36Sopenharmony_ci	.probe		= renesas_usb3_probe,
301662306a36Sopenharmony_ci	.remove_new	= renesas_usb3_remove,
301762306a36Sopenharmony_ci	.driver		= {
301862306a36Sopenharmony_ci		.name =	udc_name,
301962306a36Sopenharmony_ci		.pm		= &renesas_usb3_pm_ops,
302062306a36Sopenharmony_ci		.of_match_table = usb3_of_match,
302162306a36Sopenharmony_ci	},
302262306a36Sopenharmony_ci};
302362306a36Sopenharmony_cimodule_platform_driver(renesas_usb3_driver);
302462306a36Sopenharmony_ci
302562306a36Sopenharmony_ciMODULE_DESCRIPTION("Renesas USB3.0 Peripheral driver");
302662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
302762306a36Sopenharmony_ciMODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");
302862306a36Sopenharmony_ciMODULE_ALIAS("platform:renesas_usb3");
3029