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