18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */
28c2ecf20Sopenharmony_ci#ifndef __ASPEED_VHUB_H
38c2ecf20Sopenharmony_ci#define __ASPEED_VHUB_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <linux/usb.h>
68c2ecf20Sopenharmony_ci#include <linux/usb/ch11.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/*****************************
98c2ecf20Sopenharmony_ci *                           *
108c2ecf20Sopenharmony_ci * VHUB register definitions *
118c2ecf20Sopenharmony_ci *                           *
128c2ecf20Sopenharmony_ci *****************************/
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define	AST_VHUB_CTRL		0x00	/* Root Function Control & Status Register */
158c2ecf20Sopenharmony_ci#define	AST_VHUB_CONF		0x04	/* Root Configuration Setting Register */
168c2ecf20Sopenharmony_ci#define	AST_VHUB_IER		0x08	/* Interrupt Ctrl Register */
178c2ecf20Sopenharmony_ci#define	AST_VHUB_ISR		0x0C	/* Interrupt Status Register */
188c2ecf20Sopenharmony_ci#define	AST_VHUB_EP_ACK_IER	0x10	/* Programmable Endpoint Pool ACK Interrupt Enable Register */
198c2ecf20Sopenharmony_ci#define	AST_VHUB_EP_NACK_IER	0x14	/* Programmable Endpoint Pool NACK Interrupt Enable Register  */
208c2ecf20Sopenharmony_ci#define AST_VHUB_EP_ACK_ISR	0x18	/* Programmable Endpoint Pool ACK Interrupt Status Register  */
218c2ecf20Sopenharmony_ci#define AST_VHUB_EP_NACK_ISR	0x1C	/* Programmable Endpoint Pool NACK Interrupt Status Register  */
228c2ecf20Sopenharmony_ci#define AST_VHUB_SW_RESET	0x20	/* Device Controller Soft Reset Enable Register */
238c2ecf20Sopenharmony_ci#define AST_VHUB_USBSTS		0x24	/* USB Status Register */
248c2ecf20Sopenharmony_ci#define AST_VHUB_EP_TOGGLE	0x28	/* Programmable Endpoint Pool Data Toggle Value Set */
258c2ecf20Sopenharmony_ci#define AST_VHUB_ISO_FAIL_ACC	0x2C	/* Isochronous Transaction Fail Accumulator */
268c2ecf20Sopenharmony_ci#define AST_VHUB_EP0_CTRL	0x30	/* Endpoint 0 Contrl/Status Register */
278c2ecf20Sopenharmony_ci#define AST_VHUB_EP0_DATA	0x34	/* Base Address of Endpoint 0 In/OUT Data Buffer Register */
288c2ecf20Sopenharmony_ci#define AST_VHUB_EP1_CTRL	0x38	/* Endpoint 1 Contrl/Status Register */
298c2ecf20Sopenharmony_ci#define AST_VHUB_EP1_STS_CHG	0x3C	/* Endpoint 1 Status Change Bitmap Data */
308c2ecf20Sopenharmony_ci#define AST_VHUB_SETUP0		0x80	/* Root Device Setup Data Buffer0 */
318c2ecf20Sopenharmony_ci#define AST_VHUB_SETUP1		0x84	/* Root Device Setup Data Buffer1 */
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/* Main control reg */
348c2ecf20Sopenharmony_ci#define VHUB_CTRL_PHY_CLK			(1 << 31)
358c2ecf20Sopenharmony_ci#define VHUB_CTRL_PHY_LOOP_TEST			(1 << 25)
368c2ecf20Sopenharmony_ci#define VHUB_CTRL_DN_PWN			(1 << 24)
378c2ecf20Sopenharmony_ci#define VHUB_CTRL_DP_PWN			(1 << 23)
388c2ecf20Sopenharmony_ci#define VHUB_CTRL_LONG_DESC			(1 << 18)
398c2ecf20Sopenharmony_ci#define VHUB_CTRL_ISO_RSP_CTRL			(1 << 17)
408c2ecf20Sopenharmony_ci#define VHUB_CTRL_SPLIT_IN			(1 << 16)
418c2ecf20Sopenharmony_ci#define VHUB_CTRL_LOOP_T_RESULT			(1 << 15)
428c2ecf20Sopenharmony_ci#define VHUB_CTRL_LOOP_T_STS			(1 << 14)
438c2ecf20Sopenharmony_ci#define VHUB_CTRL_PHY_BIST_RESULT		(1 << 13)
448c2ecf20Sopenharmony_ci#define VHUB_CTRL_PHY_BIST_CTRL			(1 << 12)
458c2ecf20Sopenharmony_ci#define VHUB_CTRL_PHY_RESET_DIS			(1 << 11)
468c2ecf20Sopenharmony_ci#define VHUB_CTRL_SET_TEST_MODE(x)		((x) << 8)
478c2ecf20Sopenharmony_ci#define VHUB_CTRL_MANUAL_REMOTE_WAKEUP		(1 << 4)
488c2ecf20Sopenharmony_ci#define VHUB_CTRL_AUTO_REMOTE_WAKEUP		(1 << 3)
498c2ecf20Sopenharmony_ci#define VHUB_CTRL_CLK_STOP_SUSPEND		(1 << 2)
508c2ecf20Sopenharmony_ci#define VHUB_CTRL_FULL_SPEED_ONLY		(1 << 1)
518c2ecf20Sopenharmony_ci#define VHUB_CTRL_UPSTREAM_CONNECT		(1 << 0)
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/* IER & ISR */
548c2ecf20Sopenharmony_ci#define VHUB_IRQ_DEV1_BIT			9
558c2ecf20Sopenharmony_ci#define VHUB_IRQ_USB_CMD_DEADLOCK		(1 << 18)
568c2ecf20Sopenharmony_ci#define VHUB_IRQ_EP_POOL_NAK			(1 << 17)
578c2ecf20Sopenharmony_ci#define VHUB_IRQ_EP_POOL_ACK_STALL		(1 << 16)
588c2ecf20Sopenharmony_ci#define VHUB_IRQ_DEVICE1			(1 << (VHUB_IRQ_DEV1_BIT))
598c2ecf20Sopenharmony_ci#define VHUB_IRQ_BUS_RESUME			(1 << 8)
608c2ecf20Sopenharmony_ci#define VHUB_IRQ_BUS_SUSPEND 			(1 << 7)
618c2ecf20Sopenharmony_ci#define VHUB_IRQ_BUS_RESET 			(1 << 6)
628c2ecf20Sopenharmony_ci#define VHUB_IRQ_HUB_EP1_IN_DATA_ACK		(1 << 5)
638c2ecf20Sopenharmony_ci#define VHUB_IRQ_HUB_EP0_IN_DATA_NAK		(1 << 4)
648c2ecf20Sopenharmony_ci#define VHUB_IRQ_HUB_EP0_IN_ACK_STALL		(1 << 3)
658c2ecf20Sopenharmony_ci#define VHUB_IRQ_HUB_EP0_OUT_NAK		(1 << 2)
668c2ecf20Sopenharmony_ci#define VHUB_IRQ_HUB_EP0_OUT_ACK_STALL		(1 << 1)
678c2ecf20Sopenharmony_ci#define VHUB_IRQ_HUB_EP0_SETUP			(1 << 0)
688c2ecf20Sopenharmony_ci#define VHUB_IRQ_ACK_ALL			0x1ff
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/* Downstream device IRQ mask. */
718c2ecf20Sopenharmony_ci#define VHUB_DEV_IRQ(n)				(VHUB_IRQ_DEVICE1 << (n))
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* SW reset reg */
748c2ecf20Sopenharmony_ci#define VHUB_SW_RESET_EP_POOL			(1 << 9)
758c2ecf20Sopenharmony_ci#define VHUB_SW_RESET_DMA_CONTROLLER		(1 << 8)
768c2ecf20Sopenharmony_ci#define VHUB_SW_RESET_DEVICE5			(1 << 5)
778c2ecf20Sopenharmony_ci#define VHUB_SW_RESET_DEVICE4			(1 << 4)
788c2ecf20Sopenharmony_ci#define VHUB_SW_RESET_DEVICE3			(1 << 3)
798c2ecf20Sopenharmony_ci#define VHUB_SW_RESET_DEVICE2			(1 << 2)
808c2ecf20Sopenharmony_ci#define VHUB_SW_RESET_DEVICE1			(1 << 1)
818c2ecf20Sopenharmony_ci#define VHUB_SW_RESET_ROOT_HUB			(1 << 0)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci/* EP ACK/NACK IRQ masks */
848c2ecf20Sopenharmony_ci#define VHUB_EP_IRQ(n)				(1 << (n))
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci/* USB status reg */
878c2ecf20Sopenharmony_ci#define VHUB_USBSTS_HISPEED			(1 << 27)
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci/* EP toggle */
908c2ecf20Sopenharmony_ci#define VHUB_EP_TOGGLE_VALUE			(1 << 8)
918c2ecf20Sopenharmony_ci#define VHUB_EP_TOGGLE_SET_EPNUM(x)		((x) & 0x1f)
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/* HUB EP0 control */
948c2ecf20Sopenharmony_ci#define VHUB_EP0_CTRL_STALL			(1 << 0)
958c2ecf20Sopenharmony_ci#define VHUB_EP0_TX_BUFF_RDY			(1 << 1)
968c2ecf20Sopenharmony_ci#define VHUB_EP0_RX_BUFF_RDY			(1 << 2)
978c2ecf20Sopenharmony_ci#define VHUB_EP0_RX_LEN(x)			(((x) >> 16) & 0x7f)
988c2ecf20Sopenharmony_ci#define VHUB_EP0_SET_TX_LEN(x)			(((x) & 0x7f) << 8)
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/* HUB EP1 control */
1018c2ecf20Sopenharmony_ci#define VHUB_EP1_CTRL_RESET_TOGGLE		(1 << 2)
1028c2ecf20Sopenharmony_ci#define VHUB_EP1_CTRL_STALL			(1 << 1)
1038c2ecf20Sopenharmony_ci#define VHUB_EP1_CTRL_ENABLE			(1 << 0)
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/***********************************
1068c2ecf20Sopenharmony_ci *                                 *
1078c2ecf20Sopenharmony_ci * per-device register definitions *
1088c2ecf20Sopenharmony_ci *                                 *
1098c2ecf20Sopenharmony_ci ***********************************/
1108c2ecf20Sopenharmony_ci#define AST_VHUB_DEV_EN_CTRL		0x00
1118c2ecf20Sopenharmony_ci#define AST_VHUB_DEV_ISR		0x04
1128c2ecf20Sopenharmony_ci#define AST_VHUB_DEV_EP0_CTRL		0x08
1138c2ecf20Sopenharmony_ci#define AST_VHUB_DEV_EP0_DATA		0x0c
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/* Device enable control */
1168c2ecf20Sopenharmony_ci#define VHUB_DEV_EN_SET_ADDR(x)			((x) << 8)
1178c2ecf20Sopenharmony_ci#define VHUB_DEV_EN_ADDR_MASK			((0xff) << 8)
1188c2ecf20Sopenharmony_ci#define VHUB_DEV_EN_EP0_NAK_IRQEN		(1 << 6)
1198c2ecf20Sopenharmony_ci#define VHUB_DEV_EN_EP0_IN_ACK_IRQEN		(1 << 5)
1208c2ecf20Sopenharmony_ci#define VHUB_DEV_EN_EP0_OUT_NAK_IRQEN		(1 << 4)
1218c2ecf20Sopenharmony_ci#define VHUB_DEV_EN_EP0_OUT_ACK_IRQEN		(1 << 3)
1228c2ecf20Sopenharmony_ci#define VHUB_DEV_EN_EP0_SETUP_IRQEN		(1 << 2)
1238c2ecf20Sopenharmony_ci#define VHUB_DEV_EN_SPEED_SEL_HIGH		(1 << 1)
1248c2ecf20Sopenharmony_ci#define VHUB_DEV_EN_ENABLE_PORT			(1 << 0)
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci/* Interrupt status */
1278c2ecf20Sopenharmony_ci#define VHUV_DEV_IRQ_EP0_IN_DATA_NACK		(1 << 4)
1288c2ecf20Sopenharmony_ci#define VHUV_DEV_IRQ_EP0_IN_ACK_STALL		(1 << 3)
1298c2ecf20Sopenharmony_ci#define VHUV_DEV_IRQ_EP0_OUT_DATA_NACK		(1 << 2)
1308c2ecf20Sopenharmony_ci#define VHUV_DEV_IRQ_EP0_OUT_ACK_STALL		(1 << 1)
1318c2ecf20Sopenharmony_ci#define VHUV_DEV_IRQ_EP0_SETUP			(1 << 0)
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci/* Control bits.
1348c2ecf20Sopenharmony_ci *
1358c2ecf20Sopenharmony_ci * Note: The driver relies on the bulk of those bits
1368c2ecf20Sopenharmony_ci *       matching corresponding vHub EP0 control bits
1378c2ecf20Sopenharmony_ci */
1388c2ecf20Sopenharmony_ci#define VHUB_DEV_EP0_CTRL_STALL			VHUB_EP0_CTRL_STALL
1398c2ecf20Sopenharmony_ci#define VHUB_DEV_EP0_TX_BUFF_RDY		VHUB_EP0_TX_BUFF_RDY
1408c2ecf20Sopenharmony_ci#define VHUB_DEV_EP0_RX_BUFF_RDY		VHUB_EP0_RX_BUFF_RDY
1418c2ecf20Sopenharmony_ci#define VHUB_DEV_EP0_RX_LEN(x)			VHUB_EP0_RX_LEN(x)
1428c2ecf20Sopenharmony_ci#define VHUB_DEV_EP0_SET_TX_LEN(x)		VHUB_EP0_SET_TX_LEN(x)
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/*************************************
1458c2ecf20Sopenharmony_ci *                                   *
1468c2ecf20Sopenharmony_ci * per-endpoint register definitions *
1478c2ecf20Sopenharmony_ci *                                   *
1488c2ecf20Sopenharmony_ci *************************************/
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci#define AST_VHUB_EP_CONFIG		0x00
1518c2ecf20Sopenharmony_ci#define AST_VHUB_EP_DMA_CTLSTAT		0x04
1528c2ecf20Sopenharmony_ci#define AST_VHUB_EP_DESC_BASE		0x08
1538c2ecf20Sopenharmony_ci#define AST_VHUB_EP_DESC_STATUS		0x0C
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/* EP config reg */
1568c2ecf20Sopenharmony_ci#define VHUB_EP_CFG_SET_MAX_PKT(x)	(((x) & 0x3ff) << 16)
1578c2ecf20Sopenharmony_ci#define VHUB_EP_CFG_AUTO_DATA_DISABLE	(1 << 13)
1588c2ecf20Sopenharmony_ci#define VHUB_EP_CFG_STALL_CTRL		(1 << 12)
1598c2ecf20Sopenharmony_ci#define VHUB_EP_CFG_SET_EP_NUM(x)	(((x) & 0xf) << 8)
1608c2ecf20Sopenharmony_ci#define VHUB_EP_CFG_SET_TYPE(x)		((x) << 5)
1618c2ecf20Sopenharmony_ci#define   EP_TYPE_OFF			0
1628c2ecf20Sopenharmony_ci#define   EP_TYPE_BULK			1
1638c2ecf20Sopenharmony_ci#define   EP_TYPE_INT			2
1648c2ecf20Sopenharmony_ci#define   EP_TYPE_ISO			3
1658c2ecf20Sopenharmony_ci#define VHUB_EP_CFG_DIR_OUT		(1 << 4)
1668c2ecf20Sopenharmony_ci#define VHUB_EP_CFG_SET_DEV(x)		((x) << 1)
1678c2ecf20Sopenharmony_ci#define VHUB_EP_CFG_ENABLE		(1 << 0)
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci/* EP DMA control */
1708c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_PROC_STATUS(x)	(((x) >> 4) & 0xf)
1718c2ecf20Sopenharmony_ci#define   EP_DMA_PROC_RX_IDLE		0
1728c2ecf20Sopenharmony_ci#define   EP_DMA_PROC_TX_IDLE		8
1738c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_IN_LONG_MODE	(1 << 3)
1748c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_OUT_CONTIG_MODE	(1 << 3)
1758c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_CTRL_RESET		(1 << 2)
1768c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_SINGLE_STAGE	(1 << 1)
1778c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_DESC_MODE		(1 << 0)
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci/* EP DMA status */
1808c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_SET_TX_SIZE(x)	((x) << 16)
1818c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_TX_SIZE(x)		(((x) >> 16) & 0x7ff)
1828c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_RPTR(x)		(((x) >> 8) & 0xff)
1838c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_SET_RPTR(x)		(((x) & 0xff) << 8)
1848c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_SET_CPU_WPTR(x)	(x)
1858c2ecf20Sopenharmony_ci#define VHUB_EP_DMA_SINGLE_KICK		(1 << 0) /* WPTR = 1 for single mode */
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci/*******************************
1888c2ecf20Sopenharmony_ci *                             *
1898c2ecf20Sopenharmony_ci * DMA descriptors definitions *
1908c2ecf20Sopenharmony_ci *                             *
1918c2ecf20Sopenharmony_ci *******************************/
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci/* Desc W1 IN */
1948c2ecf20Sopenharmony_ci#define VHUB_DSC1_IN_INTERRUPT		(1 << 31)
1958c2ecf20Sopenharmony_ci#define VHUB_DSC1_IN_SPID_DATA0		(0 << 14)
1968c2ecf20Sopenharmony_ci#define VHUB_DSC1_IN_SPID_DATA2		(1 << 14)
1978c2ecf20Sopenharmony_ci#define VHUB_DSC1_IN_SPID_DATA1		(2 << 14)
1988c2ecf20Sopenharmony_ci#define VHUB_DSC1_IN_SPID_MDATA		(3 << 14)
1998c2ecf20Sopenharmony_ci#define VHUB_DSC1_IN_SET_LEN(x)		((x) & 0xfff)
2008c2ecf20Sopenharmony_ci#define VHUB_DSC1_IN_LEN(x)		((x) & 0xfff)
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci/****************************************
2038c2ecf20Sopenharmony_ci *                                      *
2048c2ecf20Sopenharmony_ci * Data structures and misc definitions *
2058c2ecf20Sopenharmony_ci *                                      *
2068c2ecf20Sopenharmony_ci ****************************************/
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci/*
2098c2ecf20Sopenharmony_ci * AST_VHUB_NUM_GEN_EPs and AST_VHUB_NUM_PORTS are kept to avoid breaking
2108c2ecf20Sopenharmony_ci * existing AST2400/AST2500 platforms. AST2600 and future vhub revisions
2118c2ecf20Sopenharmony_ci * should define number of downstream ports and endpoints in device tree.
2128c2ecf20Sopenharmony_ci */
2138c2ecf20Sopenharmony_ci#define AST_VHUB_NUM_GEN_EPs	15	/* Generic non-0 EPs */
2148c2ecf20Sopenharmony_ci#define AST_VHUB_NUM_PORTS	5	/* vHub ports */
2158c2ecf20Sopenharmony_ci#define AST_VHUB_EP0_MAX_PACKET	64	/* EP0's max packet size */
2168c2ecf20Sopenharmony_ci#define AST_VHUB_EPn_MAX_PACKET	1024	/* Generic EPs max packet size */
2178c2ecf20Sopenharmony_ci#define AST_VHUB_DESCS_COUNT	256	/* Use 256 descriptor mode (valid
2188c2ecf20Sopenharmony_ci					 * values are 256 and 32)
2198c2ecf20Sopenharmony_ci					 */
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistruct ast_vhub;
2228c2ecf20Sopenharmony_cistruct ast_vhub_dev;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci/*
2258c2ecf20Sopenharmony_ci * DMA descriptor (generic EPs only, currently only used
2268c2ecf20Sopenharmony_ci * for IN endpoints
2278c2ecf20Sopenharmony_ci */
2288c2ecf20Sopenharmony_cistruct ast_vhub_desc {
2298c2ecf20Sopenharmony_ci	__le32	w0;
2308c2ecf20Sopenharmony_ci	__le32	w1;
2318c2ecf20Sopenharmony_ci};
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci/* A transfer request, either core-originated or internal */
2348c2ecf20Sopenharmony_cistruct ast_vhub_req {
2358c2ecf20Sopenharmony_ci	struct usb_request	req;
2368c2ecf20Sopenharmony_ci	struct list_head	queue;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	/* Actual count written to descriptors (desc mode only) */
2398c2ecf20Sopenharmony_ci	unsigned int		act_count;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	/*
2428c2ecf20Sopenharmony_ci	 * Desc number of the final packet or -1. For non-desc
2438c2ecf20Sopenharmony_ci	 * mode (or ep0), any >= 0 value means "last packet"
2448c2ecf20Sopenharmony_ci	 */
2458c2ecf20Sopenharmony_ci	int			last_desc;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	/* Request active (pending DMAs) */
2488c2ecf20Sopenharmony_ci	bool			active  : 1;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	/* Internal request (don't call back core) */
2518c2ecf20Sopenharmony_ci	bool			internal : 1;
2528c2ecf20Sopenharmony_ci};
2538c2ecf20Sopenharmony_ci#define to_ast_req(__ureq) container_of(__ureq, struct ast_vhub_req, req)
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci/* Current state of an EP0 */
2568c2ecf20Sopenharmony_cienum ep0_state {
2578c2ecf20Sopenharmony_ci	ep0_state_token,
2588c2ecf20Sopenharmony_ci	ep0_state_data,
2598c2ecf20Sopenharmony_ci	ep0_state_status,
2608c2ecf20Sopenharmony_ci	ep0_state_stall,
2618c2ecf20Sopenharmony_ci};
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci/*
2648c2ecf20Sopenharmony_ci * An endpoint, either generic, ep0, actual gadget EP
2658c2ecf20Sopenharmony_ci * or internal use vhub EP0. vhub EP1 doesn't have an
2668c2ecf20Sopenharmony_ci * associated structure as it's mostly HW managed.
2678c2ecf20Sopenharmony_ci */
2688c2ecf20Sopenharmony_cistruct ast_vhub_ep {
2698c2ecf20Sopenharmony_ci	struct usb_ep		ep;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	/* Request queue */
2728c2ecf20Sopenharmony_ci	struct list_head	queue;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	/* EP index in the device, 0 means this is an EP0 */
2758c2ecf20Sopenharmony_ci	unsigned int		d_idx;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	/* Dev pointer or NULL for vHub EP0 */
2788c2ecf20Sopenharmony_ci	struct ast_vhub_dev	*dev;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	/* vHub itself */
2818c2ecf20Sopenharmony_ci	struct ast_vhub		*vhub;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	/*
2848c2ecf20Sopenharmony_ci	 * DMA buffer for EP0, fallback DMA buffer for misaligned
2858c2ecf20Sopenharmony_ci	 * OUT transfers for generic EPs
2868c2ecf20Sopenharmony_ci	 */
2878c2ecf20Sopenharmony_ci	void			*buf;
2888c2ecf20Sopenharmony_ci	dma_addr_t		buf_dma;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	/* The rest depends on the EP type */
2918c2ecf20Sopenharmony_ci	union {
2928c2ecf20Sopenharmony_ci		/* EP0 (either device or vhub) */
2938c2ecf20Sopenharmony_ci		struct {
2948c2ecf20Sopenharmony_ci			/*
2958c2ecf20Sopenharmony_ci			 * EP0 registers are "similar" for
2968c2ecf20Sopenharmony_ci			 * vHub and devices but located in
2978c2ecf20Sopenharmony_ci			 * different places.
2988c2ecf20Sopenharmony_ci			 */
2998c2ecf20Sopenharmony_ci			void __iomem		*ctlstat;
3008c2ecf20Sopenharmony_ci			void __iomem		*setup;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci			/* Current state & direction */
3038c2ecf20Sopenharmony_ci			enum ep0_state		state;
3048c2ecf20Sopenharmony_ci			bool			dir_in;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci			/* Internal use request */
3078c2ecf20Sopenharmony_ci			struct ast_vhub_req	req;
3088c2ecf20Sopenharmony_ci		} ep0;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci		/* Generic endpoint (aka EPn) */
3118c2ecf20Sopenharmony_ci		struct {
3128c2ecf20Sopenharmony_ci			/* Registers */
3138c2ecf20Sopenharmony_ci			void __iomem   		*regs;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci			/* Index in global pool (zero-based) */
3168c2ecf20Sopenharmony_ci			unsigned int		g_idx;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci			/* DMA Descriptors */
3198c2ecf20Sopenharmony_ci			struct ast_vhub_desc	*descs;
3208c2ecf20Sopenharmony_ci			dma_addr_t		descs_dma;
3218c2ecf20Sopenharmony_ci			unsigned int		d_next;
3228c2ecf20Sopenharmony_ci			unsigned int		d_last;
3238c2ecf20Sopenharmony_ci			unsigned int		dma_conf;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci			/* Max chunk size for IN EPs */
3268c2ecf20Sopenharmony_ci			unsigned int		chunk_max;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci			/* State flags */
3298c2ecf20Sopenharmony_ci			bool			is_in :  1;
3308c2ecf20Sopenharmony_ci			bool			is_iso : 1;
3318c2ecf20Sopenharmony_ci			bool			stalled : 1;
3328c2ecf20Sopenharmony_ci			bool			wedged : 1;
3338c2ecf20Sopenharmony_ci			bool			enabled : 1;
3348c2ecf20Sopenharmony_ci			bool			desc_mode : 1;
3358c2ecf20Sopenharmony_ci		} epn;
3368c2ecf20Sopenharmony_ci	};
3378c2ecf20Sopenharmony_ci};
3388c2ecf20Sopenharmony_ci#define to_ast_ep(__uep) container_of(__uep, struct ast_vhub_ep, ep)
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci/* A device attached to a vHub port */
3418c2ecf20Sopenharmony_cistruct ast_vhub_dev {
3428c2ecf20Sopenharmony_ci	struct ast_vhub			*vhub;
3438c2ecf20Sopenharmony_ci	void __iomem			*regs;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	/* Device index (zero-based) and name string */
3468c2ecf20Sopenharmony_ci	unsigned int			index;
3478c2ecf20Sopenharmony_ci	const char			*name;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	/* sysfs enclosure for the gadget gunk */
3508c2ecf20Sopenharmony_ci	struct device			*port_dev;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	/* Link to gadget core */
3538c2ecf20Sopenharmony_ci	struct usb_gadget		gadget;
3548c2ecf20Sopenharmony_ci	struct usb_gadget_driver	*driver;
3558c2ecf20Sopenharmony_ci	bool				registered : 1;
3568c2ecf20Sopenharmony_ci	bool				wakeup_en : 1;
3578c2ecf20Sopenharmony_ci	bool				enabled : 1;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	/* Endpoint structures */
3608c2ecf20Sopenharmony_ci	struct ast_vhub_ep		ep0;
3618c2ecf20Sopenharmony_ci	struct ast_vhub_ep		**epns;
3628c2ecf20Sopenharmony_ci	u32				max_epns;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci};
3658c2ecf20Sopenharmony_ci#define to_ast_dev(__g) container_of(__g, struct ast_vhub_dev, gadget)
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci/* Per vhub port stateinfo structure */
3688c2ecf20Sopenharmony_cistruct ast_vhub_port {
3698c2ecf20Sopenharmony_ci	/* Port status & status change registers */
3708c2ecf20Sopenharmony_ci	u16			status;
3718c2ecf20Sopenharmony_ci	u16			change;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	/* Associated device slot */
3748c2ecf20Sopenharmony_ci	struct ast_vhub_dev	dev;
3758c2ecf20Sopenharmony_ci};
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_cistruct ast_vhub_full_cdesc {
3788c2ecf20Sopenharmony_ci	struct usb_config_descriptor	cfg;
3798c2ecf20Sopenharmony_ci	struct usb_interface_descriptor intf;
3808c2ecf20Sopenharmony_ci	struct usb_endpoint_descriptor	ep;
3818c2ecf20Sopenharmony_ci} __packed;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci/* Global vhub structure */
3848c2ecf20Sopenharmony_cistruct ast_vhub {
3858c2ecf20Sopenharmony_ci	struct platform_device		*pdev;
3868c2ecf20Sopenharmony_ci	void __iomem			*regs;
3878c2ecf20Sopenharmony_ci	int				irq;
3888c2ecf20Sopenharmony_ci	spinlock_t			lock;
3898c2ecf20Sopenharmony_ci	struct work_struct		wake_work;
3908c2ecf20Sopenharmony_ci	struct clk			*clk;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	/* EP0 DMA buffers allocated in one chunk */
3938c2ecf20Sopenharmony_ci	void				*ep0_bufs;
3948c2ecf20Sopenharmony_ci	dma_addr_t			ep0_bufs_dma;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	/* EP0 of the vhub itself */
3978c2ecf20Sopenharmony_ci	struct ast_vhub_ep		ep0;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	/* State of vhub ep1 */
4008c2ecf20Sopenharmony_ci	bool				ep1_stalled : 1;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	/* Per-port info */
4038c2ecf20Sopenharmony_ci	struct ast_vhub_port		*ports;
4048c2ecf20Sopenharmony_ci	u32				max_ports;
4058c2ecf20Sopenharmony_ci	u32				port_irq_mask;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	/* Generic EP data structures */
4088c2ecf20Sopenharmony_ci	struct ast_vhub_ep		*epns;
4098c2ecf20Sopenharmony_ci	u32				max_epns;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	/* Upstream bus is suspended ? */
4128c2ecf20Sopenharmony_ci	bool				suspended : 1;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	/* Hub itself can signal remote wakeup */
4158c2ecf20Sopenharmony_ci	bool				wakeup_en : 1;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	/* Force full speed only */
4188c2ecf20Sopenharmony_ci	bool				force_usb1 : 1;
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	/* Upstream bus speed captured at bus reset */
4218c2ecf20Sopenharmony_ci	unsigned int			speed;
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	/* Standard USB Descriptors of the vhub. */
4248c2ecf20Sopenharmony_ci	struct usb_device_descriptor	vhub_dev_desc;
4258c2ecf20Sopenharmony_ci	struct ast_vhub_full_cdesc	vhub_conf_desc;
4268c2ecf20Sopenharmony_ci	struct usb_hub_descriptor	vhub_hub_desc;
4278c2ecf20Sopenharmony_ci	struct list_head		vhub_str_desc;
4288c2ecf20Sopenharmony_ci};
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci/* Standard request handlers result codes */
4318c2ecf20Sopenharmony_cienum std_req_rc {
4328c2ecf20Sopenharmony_ci	std_req_stall = -1,	/* Stall requested */
4338c2ecf20Sopenharmony_ci	std_req_complete = 0,	/* Request completed with no data */
4348c2ecf20Sopenharmony_ci	std_req_data = 1,	/* Request completed with data */
4358c2ecf20Sopenharmony_ci	std_req_driver = 2,	/* Pass to driver pls */
4368c2ecf20Sopenharmony_ci};
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci#ifdef CONFIG_USB_GADGET_VERBOSE
4398c2ecf20Sopenharmony_ci#define UDCVDBG(u, fmt...)	dev_dbg(&(u)->pdev->dev, fmt)
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci#define EPVDBG(ep, fmt, ...)	do {			\
4428c2ecf20Sopenharmony_ci	dev_dbg(&(ep)->vhub->pdev->dev,			\
4438c2ecf20Sopenharmony_ci		"%s:EP%d " fmt,				\
4448c2ecf20Sopenharmony_ci		(ep)->dev ? (ep)->dev->name : "hub",	\
4458c2ecf20Sopenharmony_ci		(ep)->d_idx, ##__VA_ARGS__);		\
4468c2ecf20Sopenharmony_ci	} while(0)
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci#define DVDBG(d, fmt, ...)	do {			\
4498c2ecf20Sopenharmony_ci	dev_dbg(&(d)->vhub->pdev->dev,			\
4508c2ecf20Sopenharmony_ci		"%s " fmt, (d)->name,			\
4518c2ecf20Sopenharmony_ci		##__VA_ARGS__);				\
4528c2ecf20Sopenharmony_ci	} while(0)
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci#else
4558c2ecf20Sopenharmony_ci#define UDCVDBG(u, fmt...)	do { } while(0)
4568c2ecf20Sopenharmony_ci#define EPVDBG(ep, fmt, ...)	do { } while(0)
4578c2ecf20Sopenharmony_ci#define DVDBG(d, fmt, ...)	do { } while(0)
4588c2ecf20Sopenharmony_ci#endif
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci#ifdef CONFIG_USB_GADGET_DEBUG
4618c2ecf20Sopenharmony_ci#define UDCDBG(u, fmt...)	dev_dbg(&(u)->pdev->dev, fmt)
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci#define EPDBG(ep, fmt, ...)	do {			\
4648c2ecf20Sopenharmony_ci	dev_dbg(&(ep)->vhub->pdev->dev,			\
4658c2ecf20Sopenharmony_ci		"%s:EP%d " fmt,				\
4668c2ecf20Sopenharmony_ci		(ep)->dev ? (ep)->dev->name : "hub",	\
4678c2ecf20Sopenharmony_ci		(ep)->d_idx, ##__VA_ARGS__);		\
4688c2ecf20Sopenharmony_ci	} while(0)
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci#define DDBG(d, fmt, ...)	do {			\
4718c2ecf20Sopenharmony_ci	dev_dbg(&(d)->vhub->pdev->dev,			\
4728c2ecf20Sopenharmony_ci		"%s " fmt, (d)->name,			\
4738c2ecf20Sopenharmony_ci		##__VA_ARGS__);				\
4748c2ecf20Sopenharmony_ci	} while(0)
4758c2ecf20Sopenharmony_ci#else
4768c2ecf20Sopenharmony_ci#define UDCDBG(u, fmt...)	do { } while(0)
4778c2ecf20Sopenharmony_ci#define EPDBG(ep, fmt, ...)	do { } while(0)
4788c2ecf20Sopenharmony_ci#define DDBG(d, fmt, ...)	do { } while(0)
4798c2ecf20Sopenharmony_ci#endif
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic inline void vhub_dma_workaround(void *addr)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	/*
4848c2ecf20Sopenharmony_ci	 * This works around a confirmed HW issue with the Aspeed chip.
4858c2ecf20Sopenharmony_ci	 *
4868c2ecf20Sopenharmony_ci	 * The core uses a different bus to memory than the AHB going to
4878c2ecf20Sopenharmony_ci	 * the USB device controller. Due to the latter having a higher
4888c2ecf20Sopenharmony_ci	 * priority than the core for arbitration on that bus, it's
4898c2ecf20Sopenharmony_ci	 * possible for an MMIO to the device, followed by a DMA by the
4908c2ecf20Sopenharmony_ci	 * device from memory to all be performed and services before
4918c2ecf20Sopenharmony_ci	 * a previous store to memory gets completed.
4928c2ecf20Sopenharmony_ci	 *
4938c2ecf20Sopenharmony_ci	 * This the following scenario can happen:
4948c2ecf20Sopenharmony_ci	 *
4958c2ecf20Sopenharmony_ci	 *    - Driver writes to a DMA descriptor (Mbus)
4968c2ecf20Sopenharmony_ci	 *    - Driver writes to the MMIO register to start the DMA (AHB)
4978c2ecf20Sopenharmony_ci	 *    - The gadget sees the second write and sends a read of the
4988c2ecf20Sopenharmony_ci	 *      descriptor to the memory controller (Mbus)
4998c2ecf20Sopenharmony_ci	 *    - The gadget hits memory before the descriptor write
5008c2ecf20Sopenharmony_ci	 *      causing it to read an obsolete value.
5018c2ecf20Sopenharmony_ci	 *
5028c2ecf20Sopenharmony_ci	 * Thankfully the problem is limited to the USB gadget device, other
5038c2ecf20Sopenharmony_ci	 * masters in the SoC all have a lower priority than the core, thus
5048c2ecf20Sopenharmony_ci	 * ensuring that the store by the core arrives first.
5058c2ecf20Sopenharmony_ci	 *
5068c2ecf20Sopenharmony_ci	 * The workaround consists of using a dummy read of the memory before
5078c2ecf20Sopenharmony_ci	 * doing the MMIO writes. This will ensure that the previous writes
5088c2ecf20Sopenharmony_ci	 * have been "pushed out".
5098c2ecf20Sopenharmony_ci	 */
5108c2ecf20Sopenharmony_ci	mb();
5118c2ecf20Sopenharmony_ci	(void)__raw_readl((void __iomem *)addr);
5128c2ecf20Sopenharmony_ci}
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci/* core.c */
5158c2ecf20Sopenharmony_civoid ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req,
5168c2ecf20Sopenharmony_ci		   int status);
5178c2ecf20Sopenharmony_civoid ast_vhub_nuke(struct ast_vhub_ep *ep, int status);
5188c2ecf20Sopenharmony_cistruct usb_request *ast_vhub_alloc_request(struct usb_ep *u_ep,
5198c2ecf20Sopenharmony_ci					   gfp_t gfp_flags);
5208c2ecf20Sopenharmony_civoid ast_vhub_free_request(struct usb_ep *u_ep, struct usb_request *u_req);
5218c2ecf20Sopenharmony_civoid ast_vhub_init_hw(struct ast_vhub *vhub);
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci/* ep0.c */
5248c2ecf20Sopenharmony_civoid ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack);
5258c2ecf20Sopenharmony_civoid ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep);
5268c2ecf20Sopenharmony_civoid ast_vhub_reset_ep0(struct ast_vhub_dev *dev);
5278c2ecf20Sopenharmony_civoid ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep,
5288c2ecf20Sopenharmony_ci		       struct ast_vhub_dev *dev);
5298c2ecf20Sopenharmony_ciint ast_vhub_reply(struct ast_vhub_ep *ep, char *ptr, int len);
5308c2ecf20Sopenharmony_ciint __ast_vhub_simple_reply(struct ast_vhub_ep *ep, int len, ...);
5318c2ecf20Sopenharmony_ci#define ast_vhub_simple_reply(udc, ...)					       \
5328c2ecf20Sopenharmony_ci	__ast_vhub_simple_reply((udc),					       \
5338c2ecf20Sopenharmony_ci			       sizeof((u8[]) { __VA_ARGS__ })/sizeof(u8),      \
5348c2ecf20Sopenharmony_ci			       __VA_ARGS__)
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci/* hub.c */
5378c2ecf20Sopenharmony_ciint ast_vhub_init_hub(struct ast_vhub *vhub);
5388c2ecf20Sopenharmony_cienum std_req_rc ast_vhub_std_hub_request(struct ast_vhub_ep *ep,
5398c2ecf20Sopenharmony_ci					 struct usb_ctrlrequest *crq);
5408c2ecf20Sopenharmony_cienum std_req_rc ast_vhub_class_hub_request(struct ast_vhub_ep *ep,
5418c2ecf20Sopenharmony_ci					   struct usb_ctrlrequest *crq);
5428c2ecf20Sopenharmony_civoid ast_vhub_device_connect(struct ast_vhub *vhub, unsigned int port,
5438c2ecf20Sopenharmony_ci			     bool on);
5448c2ecf20Sopenharmony_civoid ast_vhub_hub_suspend(struct ast_vhub *vhub);
5458c2ecf20Sopenharmony_civoid ast_vhub_hub_resume(struct ast_vhub *vhub);
5468c2ecf20Sopenharmony_civoid ast_vhub_hub_reset(struct ast_vhub *vhub);
5478c2ecf20Sopenharmony_civoid ast_vhub_hub_wake_all(struct ast_vhub *vhub);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci/* dev.c */
5508c2ecf20Sopenharmony_ciint ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx);
5518c2ecf20Sopenharmony_civoid ast_vhub_del_dev(struct ast_vhub_dev *d);
5528c2ecf20Sopenharmony_civoid ast_vhub_dev_irq(struct ast_vhub_dev *d);
5538c2ecf20Sopenharmony_ciint ast_vhub_std_dev_request(struct ast_vhub_ep *ep,
5548c2ecf20Sopenharmony_ci			     struct usb_ctrlrequest *crq);
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci/* epn.c */
5578c2ecf20Sopenharmony_civoid ast_vhub_epn_ack_irq(struct ast_vhub_ep *ep);
5588c2ecf20Sopenharmony_civoid ast_vhub_update_epn_stall(struct ast_vhub_ep *ep);
5598c2ecf20Sopenharmony_cistruct ast_vhub_ep *ast_vhub_alloc_epn(struct ast_vhub_dev *d, u8 addr);
5608c2ecf20Sopenharmony_civoid ast_vhub_dev_suspend(struct ast_vhub_dev *d);
5618c2ecf20Sopenharmony_civoid ast_vhub_dev_resume(struct ast_vhub_dev *d);
5628c2ecf20Sopenharmony_civoid ast_vhub_dev_reset(struct ast_vhub_dev *d);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci#endif /* __ASPEED_VHUB_H */
565