1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021, STMicroelectronics - All Rights Reserved 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <stdint.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <arch_helpers.h> 11*91f16700Schasinglulu #include <common/debug.h> 12*91f16700Schasinglulu #include <drivers/delay_timer.h> 13*91f16700Schasinglulu #include <drivers/st/stm32mp1_usb.h> 14*91f16700Schasinglulu #include <lib/mmio.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #include <platform_def.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #define USB_OTG_MODE_DEVICE 0U 19*91f16700Schasinglulu #define USB_OTG_MODE_HOST 1U 20*91f16700Schasinglulu #define USB_OTG_MODE_DRD 2U 21*91f16700Schasinglulu 22*91f16700Schasinglulu #define EP_TYPE_CTRL 0U 23*91f16700Schasinglulu #define EP_TYPE_ISOC 1U 24*91f16700Schasinglulu #define EP_TYPE_BULK 2U 25*91f16700Schasinglulu #define EP_TYPE_INTR 3U 26*91f16700Schasinglulu 27*91f16700Schasinglulu #define USBD_FIFO_FLUSH_TIMEOUT_US 1000U 28*91f16700Schasinglulu #define EP0_FIFO_SIZE 64U 29*91f16700Schasinglulu 30*91f16700Schasinglulu /* OTG registers offsets */ 31*91f16700Schasinglulu #define OTG_GOTGINT 0x004U 32*91f16700Schasinglulu #define OTG_GAHBCFG 0x008U 33*91f16700Schasinglulu #define OTG_GUSBCFG 0x00CU 34*91f16700Schasinglulu #define OTG_GRSTCTL 0x010U 35*91f16700Schasinglulu #define OTG_GINTSTS 0x014U 36*91f16700Schasinglulu #define OTG_GINTMSK 0x018U 37*91f16700Schasinglulu #define OTG_GRXSTSP 0x020U 38*91f16700Schasinglulu #define OTG_GLPMCFG 0x054U 39*91f16700Schasinglulu #define OTG_DCFG 0x800U 40*91f16700Schasinglulu #define OTG_DCTL 0x804U 41*91f16700Schasinglulu #define OTG_DSTS 0x808U 42*91f16700Schasinglulu #define OTG_DIEPMSK 0x810U 43*91f16700Schasinglulu #define OTG_DOEPMSK 0x814U 44*91f16700Schasinglulu #define OTG_DAINT 0x818U 45*91f16700Schasinglulu #define OTG_DAINTMSK 0x81CU 46*91f16700Schasinglulu #define OTG_DIEPEMPMSK 0x834U 47*91f16700Schasinglulu 48*91f16700Schasinglulu /* Definitions for OTG_DIEPx registers */ 49*91f16700Schasinglulu #define OTG_DIEP_BASE 0x900U 50*91f16700Schasinglulu #define OTG_DIEP_SIZE 0x20U 51*91f16700Schasinglulu #define OTG_DIEPCTL 0x00U 52*91f16700Schasinglulu #define OTG_DIEPINT 0x08U 53*91f16700Schasinglulu #define OTG_DIEPTSIZ 0x10U 54*91f16700Schasinglulu #define OTG_DIEPDMA 0x14U 55*91f16700Schasinglulu #define OTG_DTXFSTS 0x18U 56*91f16700Schasinglulu #define OTG_DIEP_MAX_NB 9U 57*91f16700Schasinglulu 58*91f16700Schasinglulu /* Definitions for OTG_DOEPx registers */ 59*91f16700Schasinglulu #define OTG_DOEP_BASE 0xB00U 60*91f16700Schasinglulu #define OTG_DOEP_SIZE 0x20U 61*91f16700Schasinglulu #define OTG_DOEPCTL 0x00U 62*91f16700Schasinglulu #define OTG_DOEPINT 0x08U 63*91f16700Schasinglulu #define OTG_DOEPTSIZ 0x10U 64*91f16700Schasinglulu #define OTG_DOEPDMA 0x14U 65*91f16700Schasinglulu #define OTG_D0EP_MAX_NB 9U 66*91f16700Schasinglulu 67*91f16700Schasinglulu /* Definitions for OTG_DAINT registers */ 68*91f16700Schasinglulu #define OTG_DAINT_OUT_MASK GENMASK(31, 16) 69*91f16700Schasinglulu #define OTG_DAINT_OUT_SHIFT 16U 70*91f16700Schasinglulu #define OTG_DAINT_IN_MASK GENMASK(15, 0) 71*91f16700Schasinglulu #define OTG_DAINT_IN_SHIFT 0U 72*91f16700Schasinglulu 73*91f16700Schasinglulu #define OTG_DAINT_EP0_IN BIT(16) 74*91f16700Schasinglulu #define OTG_DAINT_EP0_OUT BIT(0) 75*91f16700Schasinglulu 76*91f16700Schasinglulu /* Definitions for FIFOs */ 77*91f16700Schasinglulu #define OTG_FIFO_BASE 0x1000U 78*91f16700Schasinglulu #define OTG_FIFO_SIZE 0x1000U 79*91f16700Schasinglulu 80*91f16700Schasinglulu /* Bit definitions for OTG_GOTGINT register */ 81*91f16700Schasinglulu #define OTG_GOTGINT_SEDET BIT(2) 82*91f16700Schasinglulu 83*91f16700Schasinglulu /* Bit definitions for OTG_GAHBCFG register */ 84*91f16700Schasinglulu #define OTG_GAHBCFG_GINT BIT(0) 85*91f16700Schasinglulu 86*91f16700Schasinglulu /* Bit definitions for OTG_GUSBCFG register */ 87*91f16700Schasinglulu #define OTG_GUSBCFG_TRDT GENMASK(13, 10) 88*91f16700Schasinglulu #define OTG_GUSBCFG_TRDT_SHIFT 10U 89*91f16700Schasinglulu 90*91f16700Schasinglulu #define USBD_HS_TRDT_VALUE 9U 91*91f16700Schasinglulu 92*91f16700Schasinglulu /* Bit definitions for OTG_GRSTCTL register */ 93*91f16700Schasinglulu #define OTG_GRSTCTL_RXFFLSH BIT(4) 94*91f16700Schasinglulu #define OTG_GRSTCTL_TXFFLSH BIT(5) 95*91f16700Schasinglulu #define OTG_GRSTCTL_TXFNUM_SHIFT 6U 96*91f16700Schasinglulu 97*91f16700Schasinglulu /* Bit definitions for OTG_GINTSTS register */ 98*91f16700Schasinglulu #define OTG_GINTSTS_CMOD BIT(0) 99*91f16700Schasinglulu #define OTG_GINTSTS_MMIS BIT(1) 100*91f16700Schasinglulu #define OTG_GINTSTS_OTGINT BIT(2) 101*91f16700Schasinglulu #define OTG_GINTSTS_SOF BIT(3) 102*91f16700Schasinglulu #define OTG_GINTSTS_RXFLVL BIT(4) 103*91f16700Schasinglulu #define OTG_GINTSTS_USBSUSP BIT(11) 104*91f16700Schasinglulu #define OTG_GINTSTS_USBRST BIT(12) 105*91f16700Schasinglulu #define OTG_GINTSTS_ENUMDNE BIT(13) 106*91f16700Schasinglulu #define OTG_GINTSTS_IEPINT BIT(18) 107*91f16700Schasinglulu #define OTG_GINTSTS_OEPINT BIT(19) 108*91f16700Schasinglulu #define OTG_GINTSTS_IISOIXFR BIT(20) 109*91f16700Schasinglulu #define OTG_GINTSTS_IPXFR_INCOMPISOOUT BIT(21) 110*91f16700Schasinglulu #define OTG_GINTSTS_LPMINT BIT(27) 111*91f16700Schasinglulu #define OTG_GINTSTS_SRQINT BIT(30) 112*91f16700Schasinglulu #define OTG_GINTSTS_WKUPINT BIT(31) 113*91f16700Schasinglulu 114*91f16700Schasinglulu /* Bit definitions for OTG_GRXSTSP register */ 115*91f16700Schasinglulu #define OTG_GRXSTSP_EPNUM GENMASK(3, 0) 116*91f16700Schasinglulu #define OTG_GRXSTSP_BCNT GENMASK(14, 4) 117*91f16700Schasinglulu #define OTG_GRXSTSP_BCNT_SHIFT 4U 118*91f16700Schasinglulu #define OTG_GRXSTSP_PKTSTS GENMASK(20, 17) 119*91f16700Schasinglulu #define OTG_GRXSTSP_PKTSTS_SHIFT 17U 120*91f16700Schasinglulu 121*91f16700Schasinglulu #define STS_GOUT_NAK 1U 122*91f16700Schasinglulu #define STS_DATA_UPDT 2U 123*91f16700Schasinglulu #define STS_XFER_COMP 3U 124*91f16700Schasinglulu #define STS_SETUP_COMP 4U 125*91f16700Schasinglulu #define STS_SETUP_UPDT 6U 126*91f16700Schasinglulu 127*91f16700Schasinglulu /* Bit definitions for OTG_GLPMCFG register */ 128*91f16700Schasinglulu #define OTG_GLPMCFG_BESL GENMASK(5, 2) 129*91f16700Schasinglulu 130*91f16700Schasinglulu /* Bit definitions for OTG_DCFG register */ 131*91f16700Schasinglulu #define OTG_DCFG_DAD GENMASK(10, 4) 132*91f16700Schasinglulu #define OTG_DCFG_DAD_SHIFT 4U 133*91f16700Schasinglulu 134*91f16700Schasinglulu /* Bit definitions for OTG_DCTL register */ 135*91f16700Schasinglulu #define OTG_DCTL_RWUSIG BIT(0) 136*91f16700Schasinglulu #define OTG_DCTL_SDIS BIT(1) 137*91f16700Schasinglulu #define OTG_DCTL_CGINAK BIT(8) 138*91f16700Schasinglulu 139*91f16700Schasinglulu /* Bit definitions for OTG_DSTS register */ 140*91f16700Schasinglulu #define OTG_DSTS_SUSPSTS BIT(0) 141*91f16700Schasinglulu #define OTG_DSTS_ENUMSPD_MASK GENMASK(2, 1) 142*91f16700Schasinglulu #define OTG_DSTS_FNSOF0 BIT(8) 143*91f16700Schasinglulu 144*91f16700Schasinglulu #define OTG_DSTS_ENUMSPD(val) ((val) << 1) 145*91f16700Schasinglulu #define OTG_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ OTG_DSTS_ENUMSPD(0U) 146*91f16700Schasinglulu #define OTG_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ OTG_DSTS_ENUMSPD(1U) 147*91f16700Schasinglulu #define OTG_DSTS_ENUMSPD_LS_PHY_6MHZ OTG_DSTS_ENUMSPD(2U) 148*91f16700Schasinglulu #define OTG_DSTS_ENUMSPD_FS_PHY_48MHZ OTG_DSTS_ENUMSPD(3U) 149*91f16700Schasinglulu 150*91f16700Schasinglulu /* Bit definitions for OTG_DIEPMSK register */ 151*91f16700Schasinglulu #define OTG_DIEPMSK_XFRCM BIT(0) 152*91f16700Schasinglulu #define OTG_DIEPMSK_EPDM BIT(1) 153*91f16700Schasinglulu #define OTG_DIEPMSK_TOM BIT(3) 154*91f16700Schasinglulu 155*91f16700Schasinglulu /* Bit definitions for OTG_DOEPMSK register */ 156*91f16700Schasinglulu #define OTG_DOEPMSK_XFRCM BIT(0) 157*91f16700Schasinglulu #define OTG_DOEPMSK_EPDM BIT(1) 158*91f16700Schasinglulu #define OTG_DOEPMSK_STUPM BIT(3) 159*91f16700Schasinglulu 160*91f16700Schasinglulu /* Bit definitions for OTG_DIEPCTLx registers */ 161*91f16700Schasinglulu #define OTG_DIEPCTL_MPSIZ GENMASK(10, 0) 162*91f16700Schasinglulu #define OTG_DIEPCTL_STALL BIT(21) 163*91f16700Schasinglulu #define OTG_DIEPCTL_CNAK BIT(26) 164*91f16700Schasinglulu #define OTG_DIEPCTL_SD0PID_SEVNFRM BIT(28) 165*91f16700Schasinglulu #define OTG_DIEPCTL_SODDFRM BIT(29) 166*91f16700Schasinglulu #define OTG_DIEPCTL_EPDIS BIT(30) 167*91f16700Schasinglulu #define OTG_DIEPCTL_EPENA BIT(31) 168*91f16700Schasinglulu 169*91f16700Schasinglulu /* Bit definitions for OTG_DIEPINTx registers */ 170*91f16700Schasinglulu #define OTG_DIEPINT_XFRC BIT(0) 171*91f16700Schasinglulu #define OTG_DIEPINT_EPDISD BIT(1) 172*91f16700Schasinglulu #define OTG_DIEPINT_TOC BIT(3) 173*91f16700Schasinglulu #define OTG_DIEPINT_ITTXFE BIT(4) 174*91f16700Schasinglulu #define OTG_DIEPINT_INEPNE BIT(6) 175*91f16700Schasinglulu #define OTG_DIEPINT_TXFE BIT(7) 176*91f16700Schasinglulu #define OTG_DIEPINT_TXFE_SHIFT 7U 177*91f16700Schasinglulu 178*91f16700Schasinglulu #define OTG_DIEPINT_MASK (BIT(13) | BIT(11) | GENMASK(9, 0)) 179*91f16700Schasinglulu 180*91f16700Schasinglulu /* Bit definitions for OTG_DIEPTSIZx registers */ 181*91f16700Schasinglulu #define OTG_DIEPTSIZ_XFRSIZ GENMASK(18, 0) 182*91f16700Schasinglulu #define OTG_DIEPTSIZ_PKTCNT GENMASK(28, 19) 183*91f16700Schasinglulu #define OTG_DIEPTSIZ_PKTCNT_SHIFT 19U 184*91f16700Schasinglulu #define OTG_DIEPTSIZ_MCNT_MASK GENMASK(30, 29) 185*91f16700Schasinglulu #define OTG_DIEPTSIZ_MCNT_DATA0 BIT(29) 186*91f16700Schasinglulu 187*91f16700Schasinglulu #define OTG_DIEPTSIZ_PKTCNT_1 BIT(19) 188*91f16700Schasinglulu 189*91f16700Schasinglulu /* Bit definitions for OTG_DTXFSTSx registers */ 190*91f16700Schasinglulu #define OTG_DTXFSTS_INEPTFSAV GENMASK(15, 0) 191*91f16700Schasinglulu 192*91f16700Schasinglulu /* Bit definitions for OTG_DOEPCTLx registers */ 193*91f16700Schasinglulu #define OTG_DOEPCTL_STALL BIT(21) 194*91f16700Schasinglulu #define OTG_DOEPCTL_CNAK BIT(26) 195*91f16700Schasinglulu #define OTG_DOEPCTL_SD0PID_SEVNFRM BIT(28) /* other than endpoint 0 */ 196*91f16700Schasinglulu #define OTG_DOEPCTL_SD1PID_SODDFRM BIT(29) /* other than endpoint 0 */ 197*91f16700Schasinglulu #define OTG_DOEPCTL_EPDIS BIT(30) 198*91f16700Schasinglulu #define OTG_DOEPCTL_EPENA BIT(31) 199*91f16700Schasinglulu 200*91f16700Schasinglulu /* Bit definitions for OTG_DOEPTSIZx registers */ 201*91f16700Schasinglulu #define OTG_DOEPTSIZ_XFRSIZ GENMASK(18, 0) 202*91f16700Schasinglulu #define OTG_DOEPTSIZ_PKTCNT GENMASK(28, 19) 203*91f16700Schasinglulu #define OTG_DOEPTSIZ_RXDPID_STUPCNT GENMASK(30, 29) 204*91f16700Schasinglulu 205*91f16700Schasinglulu /* Bit definitions for OTG_DOEPINTx registers */ 206*91f16700Schasinglulu #define OTG_DOEPINT_XFRC BIT(0) 207*91f16700Schasinglulu #define OTG_DOEPINT_STUP BIT(3) 208*91f16700Schasinglulu #define OTG_DOEPINT_OTEPDIS BIT(4) 209*91f16700Schasinglulu 210*91f16700Schasinglulu #define OTG_DOEPINT_MASK (GENMASK(15, 12) | GENMASK(9, 8) | GENMASK(6, 0)) 211*91f16700Schasinglulu 212*91f16700Schasinglulu #define EP_NB 15U 213*91f16700Schasinglulu #define EP_ALL 0x10U 214*91f16700Schasinglulu 215*91f16700Schasinglulu /* 216*91f16700Schasinglulu * Flush TX FIFO. 217*91f16700Schasinglulu * handle: PCD handle. 218*91f16700Schasinglulu * num: FIFO number. 219*91f16700Schasinglulu * This parameter can be a value from 1 to 15 or EP_ALL. 220*91f16700Schasinglulu * EP_ALL= 0x10 means Flush all TX FIFOs 221*91f16700Schasinglulu * return: USB status. 222*91f16700Schasinglulu */ 223*91f16700Schasinglulu static enum usb_status usb_dwc2_flush_tx_fifo(void *handle, uint32_t num) 224*91f16700Schasinglulu { 225*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 226*91f16700Schasinglulu uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US); 227*91f16700Schasinglulu 228*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GRSTCTL, 229*91f16700Schasinglulu OTG_GRSTCTL_TXFFLSH | (uint32_t)(num << OTG_GRSTCTL_TXFNUM_SHIFT)); 230*91f16700Schasinglulu 231*91f16700Schasinglulu while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) & 232*91f16700Schasinglulu OTG_GRSTCTL_TXFFLSH) == OTG_GRSTCTL_TXFFLSH) { 233*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 234*91f16700Schasinglulu return USBD_TIMEOUT; 235*91f16700Schasinglulu } 236*91f16700Schasinglulu } 237*91f16700Schasinglulu 238*91f16700Schasinglulu return USBD_OK; 239*91f16700Schasinglulu } 240*91f16700Schasinglulu 241*91f16700Schasinglulu /* 242*91f16700Schasinglulu * Flush RX FIFO. 243*91f16700Schasinglulu * handle: PCD handle. 244*91f16700Schasinglulu * return: USB status. 245*91f16700Schasinglulu */ 246*91f16700Schasinglulu static enum usb_status usb_dwc2_flush_rx_fifo(void *handle) 247*91f16700Schasinglulu { 248*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 249*91f16700Schasinglulu uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US); 250*91f16700Schasinglulu 251*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GRSTCTL, OTG_GRSTCTL_RXFFLSH); 252*91f16700Schasinglulu 253*91f16700Schasinglulu while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) & 254*91f16700Schasinglulu OTG_GRSTCTL_RXFFLSH) == OTG_GRSTCTL_RXFFLSH) { 255*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 256*91f16700Schasinglulu return USBD_TIMEOUT; 257*91f16700Schasinglulu } 258*91f16700Schasinglulu } 259*91f16700Schasinglulu 260*91f16700Schasinglulu return USBD_OK; 261*91f16700Schasinglulu } 262*91f16700Schasinglulu 263*91f16700Schasinglulu /* 264*91f16700Schasinglulu * Return the global USB interrupt status. 265*91f16700Schasinglulu * handle: PCD handle. 266*91f16700Schasinglulu * return: Interrupt register value. 267*91f16700Schasinglulu */ 268*91f16700Schasinglulu static uint32_t usb_dwc2_read_int(void *handle) 269*91f16700Schasinglulu { 270*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 271*91f16700Schasinglulu 272*91f16700Schasinglulu return mmio_read_32(usb_base_addr + OTG_GINTSTS) & 273*91f16700Schasinglulu mmio_read_32(usb_base_addr + OTG_GINTMSK); 274*91f16700Schasinglulu } 275*91f16700Schasinglulu 276*91f16700Schasinglulu /* 277*91f16700Schasinglulu * Return the USB device OUT endpoints interrupt. 278*91f16700Schasinglulu * handle: PCD handle. 279*91f16700Schasinglulu * return: Device OUT endpoint interrupts. 280*91f16700Schasinglulu */ 281*91f16700Schasinglulu static uint32_t usb_dwc2_all_out_ep_int(void *handle) 282*91f16700Schasinglulu { 283*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 284*91f16700Schasinglulu 285*91f16700Schasinglulu return ((mmio_read_32(usb_base_addr + OTG_DAINT) & 286*91f16700Schasinglulu mmio_read_32(usb_base_addr + OTG_DAINTMSK)) & 287*91f16700Schasinglulu OTG_DAINT_OUT_MASK) >> OTG_DAINT_OUT_SHIFT; 288*91f16700Schasinglulu } 289*91f16700Schasinglulu 290*91f16700Schasinglulu /* 291*91f16700Schasinglulu * Return the USB device IN endpoints interrupt. 292*91f16700Schasinglulu * handle: PCD handle. 293*91f16700Schasinglulu * return: Device IN endpoint interrupts. 294*91f16700Schasinglulu */ 295*91f16700Schasinglulu static uint32_t usb_dwc2_all_in_ep_int(void *handle) 296*91f16700Schasinglulu { 297*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 298*91f16700Schasinglulu 299*91f16700Schasinglulu return ((mmio_read_32(usb_base_addr + OTG_DAINT) & 300*91f16700Schasinglulu mmio_read_32(usb_base_addr + OTG_DAINTMSK)) & 301*91f16700Schasinglulu OTG_DAINT_IN_MASK) >> OTG_DAINT_IN_SHIFT; 302*91f16700Schasinglulu } 303*91f16700Schasinglulu 304*91f16700Schasinglulu /* 305*91f16700Schasinglulu * Return Device OUT EP interrupt register. 306*91f16700Schasinglulu * handle: PCD handle. 307*91f16700Schasinglulu * epnum: Endpoint number. 308*91f16700Schasinglulu * This parameter can be a value from 0 to 15. 309*91f16700Schasinglulu * return: Device OUT EP Interrupt register. 310*91f16700Schasinglulu */ 311*91f16700Schasinglulu static uint32_t usb_dwc2_out_ep_int(void *handle, uint8_t epnum) 312*91f16700Schasinglulu { 313*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 314*91f16700Schasinglulu 315*91f16700Schasinglulu return mmio_read_32(usb_base_addr + OTG_DOEP_BASE + 316*91f16700Schasinglulu (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT) & 317*91f16700Schasinglulu mmio_read_32(usb_base_addr + OTG_DOEPMSK); 318*91f16700Schasinglulu } 319*91f16700Schasinglulu 320*91f16700Schasinglulu /* 321*91f16700Schasinglulu * Return Device IN EP interrupt register. 322*91f16700Schasinglulu * handle: PCD handle. 323*91f16700Schasinglulu * epnum: Endpoint number. 324*91f16700Schasinglulu * This parameter can be a value from 0 to 15. 325*91f16700Schasinglulu * return: Device IN EP Interrupt register. 326*91f16700Schasinglulu */ 327*91f16700Schasinglulu static uint32_t usb_dwc2_in_ep_int(void *handle, uint8_t epnum) 328*91f16700Schasinglulu { 329*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 330*91f16700Schasinglulu uint32_t msk; 331*91f16700Schasinglulu uint32_t emp; 332*91f16700Schasinglulu 333*91f16700Schasinglulu msk = mmio_read_32(usb_base_addr + OTG_DIEPMSK); 334*91f16700Schasinglulu emp = mmio_read_32(usb_base_addr + OTG_DIEPEMPMSK); 335*91f16700Schasinglulu msk |= ((emp >> epnum) << OTG_DIEPINT_TXFE_SHIFT) & OTG_DIEPINT_TXFE; 336*91f16700Schasinglulu 337*91f16700Schasinglulu return mmio_read_32(usb_base_addr + OTG_DIEP_BASE + 338*91f16700Schasinglulu (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT) & msk; 339*91f16700Schasinglulu } 340*91f16700Schasinglulu 341*91f16700Schasinglulu /* 342*91f16700Schasinglulu * Return USB core mode. 343*91f16700Schasinglulu * handle: PCD handle. 344*91f16700Schasinglulu * return: Core mode. 345*91f16700Schasinglulu * This parameter can be 0 (host) or 1 (device). 346*91f16700Schasinglulu */ 347*91f16700Schasinglulu static uint32_t usb_dwc2_get_mode(void *handle) 348*91f16700Schasinglulu { 349*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 350*91f16700Schasinglulu 351*91f16700Schasinglulu return mmio_read_32(usb_base_addr + OTG_GINTSTS) & OTG_GINTSTS_CMOD; 352*91f16700Schasinglulu } 353*91f16700Schasinglulu 354*91f16700Schasinglulu /* 355*91f16700Schasinglulu * Activate EP0 for detup transactions. 356*91f16700Schasinglulu * handle: PCD handle. 357*91f16700Schasinglulu * return: USB status. 358*91f16700Schasinglulu */ 359*91f16700Schasinglulu static enum usb_status usb_dwc2_activate_setup(void *handle) 360*91f16700Schasinglulu { 361*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 362*91f16700Schasinglulu uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE; 363*91f16700Schasinglulu 364*91f16700Schasinglulu /* Set the MPS of the IN EP based on the enumeration speed */ 365*91f16700Schasinglulu mmio_clrbits_32(reg_offset + OTG_DIEPCTL, OTG_DIEPCTL_MPSIZ); 366*91f16700Schasinglulu 367*91f16700Schasinglulu if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_ENUMSPD_MASK) == 368*91f16700Schasinglulu OTG_DSTS_ENUMSPD_LS_PHY_6MHZ) { 369*91f16700Schasinglulu mmio_setbits_32(reg_offset + OTG_DIEPCTL, 3U); 370*91f16700Schasinglulu } 371*91f16700Schasinglulu 372*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_CGINAK); 373*91f16700Schasinglulu 374*91f16700Schasinglulu return USBD_OK; 375*91f16700Schasinglulu } 376*91f16700Schasinglulu 377*91f16700Schasinglulu /* 378*91f16700Schasinglulu * Prepare the EP0 to start the first control setup. 379*91f16700Schasinglulu * handle: Selected device. 380*91f16700Schasinglulu * return: USB status. 381*91f16700Schasinglulu */ 382*91f16700Schasinglulu static enum usb_status usb_dwc2_ep0_out_start(void *handle) 383*91f16700Schasinglulu { 384*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 385*91f16700Schasinglulu uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE + OTG_DIEPTSIZ; 386*91f16700Schasinglulu uint32_t reg_value = 0U; 387*91f16700Schasinglulu 388*91f16700Schasinglulu /* PKTCNT = 1 and XFRSIZ = 24 bytes for endpoint 0 */ 389*91f16700Schasinglulu reg_value |= OTG_DIEPTSIZ_PKTCNT_1; 390*91f16700Schasinglulu reg_value |= (EP0_FIFO_SIZE & OTG_DIEPTSIZ_XFRSIZ); 391*91f16700Schasinglulu reg_value |= OTG_DOEPTSIZ_RXDPID_STUPCNT; 392*91f16700Schasinglulu 393*91f16700Schasinglulu mmio_write_32(reg_offset, reg_value); 394*91f16700Schasinglulu 395*91f16700Schasinglulu return USBD_OK; 396*91f16700Schasinglulu } 397*91f16700Schasinglulu 398*91f16700Schasinglulu /* 399*91f16700Schasinglulu * Write a packet into the TX FIFO associated with the EP/channel. 400*91f16700Schasinglulu * handle: Selected device. 401*91f16700Schasinglulu * src: Pointer to source buffer. 402*91f16700Schasinglulu * ch_ep_num: Endpoint or host channel number. 403*91f16700Schasinglulu * len: Number of bytes to write. 404*91f16700Schasinglulu * return: USB status. 405*91f16700Schasinglulu */ 406*91f16700Schasinglulu static enum usb_status usb_dwc2_write_packet(void *handle, uint8_t *src, 407*91f16700Schasinglulu uint8_t ch_ep_num, uint16_t len) 408*91f16700Schasinglulu { 409*91f16700Schasinglulu uint32_t reg_offset; 410*91f16700Schasinglulu uint32_t count32b = (len + 3U) / 4U; 411*91f16700Schasinglulu uint32_t i; 412*91f16700Schasinglulu 413*91f16700Schasinglulu reg_offset = (uintptr_t)handle + OTG_FIFO_BASE + 414*91f16700Schasinglulu (ch_ep_num * OTG_FIFO_SIZE); 415*91f16700Schasinglulu 416*91f16700Schasinglulu for (i = 0U; i < count32b; i++) { 417*91f16700Schasinglulu uint32_t src_copy = 0U; 418*91f16700Schasinglulu uint32_t j; 419*91f16700Schasinglulu 420*91f16700Schasinglulu /* Data written to FIFO need to be 4 bytes aligned */ 421*91f16700Schasinglulu for (j = 0U; j < 4U; j++) { 422*91f16700Schasinglulu src_copy += (*(src + j)) << (8U * j); 423*91f16700Schasinglulu } 424*91f16700Schasinglulu 425*91f16700Schasinglulu mmio_write_32(reg_offset, src_copy); 426*91f16700Schasinglulu src += 4U; 427*91f16700Schasinglulu } 428*91f16700Schasinglulu 429*91f16700Schasinglulu return USBD_OK; 430*91f16700Schasinglulu } 431*91f16700Schasinglulu 432*91f16700Schasinglulu /* 433*91f16700Schasinglulu * Read a packet from the RX FIFO associated with the EP/channel. 434*91f16700Schasinglulu * handle: Selected device. 435*91f16700Schasinglulu * dst: Destination pointer. 436*91f16700Schasinglulu * len: Number of bytes to read. 437*91f16700Schasinglulu * return: Pointer to destination buffer. 438*91f16700Schasinglulu */ 439*91f16700Schasinglulu static void *usb_dwc2_read_packet(void *handle, uint8_t *dest, uint16_t len) 440*91f16700Schasinglulu { 441*91f16700Schasinglulu uint32_t reg_offset; 442*91f16700Schasinglulu uint32_t count32b = (len + 3U) / 4U; 443*91f16700Schasinglulu uint32_t i; 444*91f16700Schasinglulu 445*91f16700Schasinglulu VERBOSE("read packet length %i to 0x%lx\n", len, (uintptr_t)dest); 446*91f16700Schasinglulu 447*91f16700Schasinglulu reg_offset = (uintptr_t)handle + OTG_FIFO_BASE; 448*91f16700Schasinglulu 449*91f16700Schasinglulu for (i = 0U; i < count32b; i++) { 450*91f16700Schasinglulu *(uint32_t *)dest = mmio_read_32(reg_offset); 451*91f16700Schasinglulu dest += 4U; 452*91f16700Schasinglulu dsb(); 453*91f16700Schasinglulu } 454*91f16700Schasinglulu 455*91f16700Schasinglulu return (void *)dest; 456*91f16700Schasinglulu } 457*91f16700Schasinglulu 458*91f16700Schasinglulu /* 459*91f16700Schasinglulu * Setup and start a transfer over an EP. 460*91f16700Schasinglulu * handle: Selected device 461*91f16700Schasinglulu * ep: Pointer to endpoint structure. 462*91f16700Schasinglulu * return: USB status. 463*91f16700Schasinglulu */ 464*91f16700Schasinglulu static enum usb_status usb_dwc2_ep_start_xfer(void *handle, struct usbd_ep *ep) 465*91f16700Schasinglulu { 466*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 467*91f16700Schasinglulu uint32_t reg_offset; 468*91f16700Schasinglulu uint32_t reg_value; 469*91f16700Schasinglulu uint32_t clear_value; 470*91f16700Schasinglulu 471*91f16700Schasinglulu if (ep->is_in) { 472*91f16700Schasinglulu reg_offset = usb_base_addr + OTG_DIEP_BASE + (ep->num * OTG_DIEP_SIZE); 473*91f16700Schasinglulu clear_value = OTG_DIEPTSIZ_PKTCNT | OTG_DIEPTSIZ_XFRSIZ; 474*91f16700Schasinglulu if (ep->xfer_len == 0U) { 475*91f16700Schasinglulu reg_value = OTG_DIEPTSIZ_PKTCNT_1; 476*91f16700Schasinglulu } else { 477*91f16700Schasinglulu /* 478*91f16700Schasinglulu * Program the transfer size and packet count 479*91f16700Schasinglulu * as follows: 480*91f16700Schasinglulu * xfersize = N * maxpacket + short_packet 481*91f16700Schasinglulu * pktcnt = N + (short_packet exist ? 1 : 0) 482*91f16700Schasinglulu */ 483*91f16700Schasinglulu reg_value = (OTG_DIEPTSIZ_PKTCNT & 484*91f16700Schasinglulu (((ep->xfer_len + ep->maxpacket - 1U) / 485*91f16700Schasinglulu ep->maxpacket) << OTG_DIEPTSIZ_PKTCNT_SHIFT)) 486*91f16700Schasinglulu | ep->xfer_len; 487*91f16700Schasinglulu 488*91f16700Schasinglulu if (ep->type == EP_TYPE_ISOC) { 489*91f16700Schasinglulu clear_value |= OTG_DIEPTSIZ_MCNT_MASK; 490*91f16700Schasinglulu reg_value |= OTG_DIEPTSIZ_MCNT_DATA0; 491*91f16700Schasinglulu } 492*91f16700Schasinglulu } 493*91f16700Schasinglulu 494*91f16700Schasinglulu mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, clear_value, reg_value); 495*91f16700Schasinglulu 496*91f16700Schasinglulu if ((ep->type != EP_TYPE_ISOC) && (ep->xfer_len > 0U)) { 497*91f16700Schasinglulu /* Enable the TX FIFO empty interrupt for this EP */ 498*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(ep->num)); 499*91f16700Schasinglulu } 500*91f16700Schasinglulu 501*91f16700Schasinglulu /* EP enable, IN data in FIFO */ 502*91f16700Schasinglulu reg_value = OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA; 503*91f16700Schasinglulu 504*91f16700Schasinglulu if (ep->type == EP_TYPE_ISOC) { 505*91f16700Schasinglulu if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) { 506*91f16700Schasinglulu reg_value |= OTG_DIEPCTL_SODDFRM; 507*91f16700Schasinglulu } else { 508*91f16700Schasinglulu reg_value |= OTG_DIEPCTL_SD0PID_SEVNFRM; 509*91f16700Schasinglulu } 510*91f16700Schasinglulu } 511*91f16700Schasinglulu 512*91f16700Schasinglulu mmio_setbits_32(reg_offset + OTG_DIEPCTL, reg_value); 513*91f16700Schasinglulu 514*91f16700Schasinglulu if (ep->type == EP_TYPE_ISOC) { 515*91f16700Schasinglulu usb_dwc2_write_packet(handle, ep->xfer_buff, ep->num, ep->xfer_len); 516*91f16700Schasinglulu } 517*91f16700Schasinglulu } else { 518*91f16700Schasinglulu reg_offset = usb_base_addr + OTG_DOEP_BASE + (ep->num * OTG_DOEP_SIZE); 519*91f16700Schasinglulu /* 520*91f16700Schasinglulu * Program the transfer size and packet count as follows: 521*91f16700Schasinglulu * pktcnt = N 522*91f16700Schasinglulu * xfersize = N * maxpacket 523*91f16700Schasinglulu */ 524*91f16700Schasinglulu if (ep->xfer_len == 0U) { 525*91f16700Schasinglulu reg_value = ep->maxpacket | OTG_DIEPTSIZ_PKTCNT_1; 526*91f16700Schasinglulu } else { 527*91f16700Schasinglulu uint16_t pktcnt = (ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket; 528*91f16700Schasinglulu 529*91f16700Schasinglulu reg_value = (pktcnt << OTG_DIEPTSIZ_PKTCNT_SHIFT) | 530*91f16700Schasinglulu (ep->maxpacket * pktcnt); 531*91f16700Schasinglulu } 532*91f16700Schasinglulu 533*91f16700Schasinglulu mmio_clrsetbits_32(reg_offset + OTG_DOEPTSIZ, 534*91f16700Schasinglulu OTG_DOEPTSIZ_XFRSIZ & OTG_DOEPTSIZ_PKTCNT, 535*91f16700Schasinglulu reg_value); 536*91f16700Schasinglulu 537*91f16700Schasinglulu /* EP enable */ 538*91f16700Schasinglulu reg_value = OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA; 539*91f16700Schasinglulu 540*91f16700Schasinglulu if (ep->type == EP_TYPE_ISOC) { 541*91f16700Schasinglulu if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) { 542*91f16700Schasinglulu reg_value |= OTG_DOEPCTL_SD1PID_SODDFRM; 543*91f16700Schasinglulu } else { 544*91f16700Schasinglulu reg_value |= OTG_DOEPCTL_SD0PID_SEVNFRM; 545*91f16700Schasinglulu } 546*91f16700Schasinglulu } 547*91f16700Schasinglulu 548*91f16700Schasinglulu mmio_setbits_32(reg_offset + OTG_DOEPCTL, reg_value); 549*91f16700Schasinglulu } 550*91f16700Schasinglulu 551*91f16700Schasinglulu return USBD_OK; 552*91f16700Schasinglulu } 553*91f16700Schasinglulu 554*91f16700Schasinglulu /* 555*91f16700Schasinglulu * Setup and start a transfer over the EP0. 556*91f16700Schasinglulu * handle: Selected device. 557*91f16700Schasinglulu * ep: Pointer to endpoint structure. 558*91f16700Schasinglulu * return: USB status. 559*91f16700Schasinglulu */ 560*91f16700Schasinglulu static enum usb_status usb_dwc2_ep0_start_xfer(void *handle, struct usbd_ep *ep) 561*91f16700Schasinglulu { 562*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 563*91f16700Schasinglulu uint32_t reg_offset; 564*91f16700Schasinglulu uint32_t reg_value; 565*91f16700Schasinglulu 566*91f16700Schasinglulu if (ep->is_in) { 567*91f16700Schasinglulu reg_offset = usb_base_addr + OTG_DIEP_BASE + 568*91f16700Schasinglulu (ep->num * OTG_DIEP_SIZE); 569*91f16700Schasinglulu 570*91f16700Schasinglulu if (ep->xfer_len == 0U) { 571*91f16700Schasinglulu reg_value = OTG_DIEPTSIZ_PKTCNT_1; 572*91f16700Schasinglulu } else { 573*91f16700Schasinglulu /* 574*91f16700Schasinglulu * Program the transfer size and packet count 575*91f16700Schasinglulu * as follows: 576*91f16700Schasinglulu * xfersize = N * maxpacket + short_packet 577*91f16700Schasinglulu * pktcnt = N + (short_packet exist ? 1 : 0) 578*91f16700Schasinglulu */ 579*91f16700Schasinglulu 580*91f16700Schasinglulu if (ep->xfer_len > ep->maxpacket) { 581*91f16700Schasinglulu ep->xfer_len = ep->maxpacket; 582*91f16700Schasinglulu } 583*91f16700Schasinglulu 584*91f16700Schasinglulu reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->xfer_len; 585*91f16700Schasinglulu } 586*91f16700Schasinglulu 587*91f16700Schasinglulu mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, 588*91f16700Schasinglulu OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT, 589*91f16700Schasinglulu reg_value); 590*91f16700Schasinglulu 591*91f16700Schasinglulu /* Enable the TX FIFO empty interrupt for this EP */ 592*91f16700Schasinglulu if (ep->xfer_len > 0U) { 593*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, 594*91f16700Schasinglulu BIT(ep->num)); 595*91f16700Schasinglulu } 596*91f16700Schasinglulu 597*91f16700Schasinglulu /* EP enable, IN data in FIFO */ 598*91f16700Schasinglulu mmio_setbits_32(reg_offset + OTG_DIEPCTL, 599*91f16700Schasinglulu OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA); 600*91f16700Schasinglulu } else { 601*91f16700Schasinglulu reg_offset = usb_base_addr + OTG_DOEP_BASE + 602*91f16700Schasinglulu (ep->num * OTG_DOEP_SIZE); 603*91f16700Schasinglulu 604*91f16700Schasinglulu /* 605*91f16700Schasinglulu * Program the transfer size and packet count as follows: 606*91f16700Schasinglulu * pktcnt = N 607*91f16700Schasinglulu * xfersize = N * maxpacket 608*91f16700Schasinglulu */ 609*91f16700Schasinglulu if (ep->xfer_len > 0U) { 610*91f16700Schasinglulu ep->xfer_len = ep->maxpacket; 611*91f16700Schasinglulu } 612*91f16700Schasinglulu 613*91f16700Schasinglulu reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->maxpacket; 614*91f16700Schasinglulu 615*91f16700Schasinglulu mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, 616*91f16700Schasinglulu OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT, 617*91f16700Schasinglulu reg_value); 618*91f16700Schasinglulu 619*91f16700Schasinglulu /* EP enable */ 620*91f16700Schasinglulu mmio_setbits_32(reg_offset + OTG_DOEPCTL, 621*91f16700Schasinglulu OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA); 622*91f16700Schasinglulu } 623*91f16700Schasinglulu 624*91f16700Schasinglulu return USBD_OK; 625*91f16700Schasinglulu } 626*91f16700Schasinglulu 627*91f16700Schasinglulu /* 628*91f16700Schasinglulu * Set a stall condition over an EP. 629*91f16700Schasinglulu * handle: Selected device. 630*91f16700Schasinglulu * ep: Pointer to endpoint structure. 631*91f16700Schasinglulu * return: USB status. 632*91f16700Schasinglulu */ 633*91f16700Schasinglulu static enum usb_status usb_dwc2_ep_set_stall(void *handle, struct usbd_ep *ep) 634*91f16700Schasinglulu { 635*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 636*91f16700Schasinglulu uint32_t reg_offset; 637*91f16700Schasinglulu uint32_t reg_value; 638*91f16700Schasinglulu 639*91f16700Schasinglulu if (ep->is_in) { 640*91f16700Schasinglulu reg_offset = usb_base_addr + OTG_DIEP_BASE + 641*91f16700Schasinglulu (ep->num * OTG_DIEP_SIZE); 642*91f16700Schasinglulu reg_value = mmio_read_32(reg_offset + OTG_DIEPCTL); 643*91f16700Schasinglulu 644*91f16700Schasinglulu if ((reg_value & OTG_DIEPCTL_EPENA) == 0U) { 645*91f16700Schasinglulu reg_value &= ~OTG_DIEPCTL_EPDIS; 646*91f16700Schasinglulu } 647*91f16700Schasinglulu 648*91f16700Schasinglulu reg_value |= OTG_DIEPCTL_STALL; 649*91f16700Schasinglulu 650*91f16700Schasinglulu mmio_write_32(reg_offset + OTG_DIEPCTL, reg_value); 651*91f16700Schasinglulu } else { 652*91f16700Schasinglulu reg_offset = usb_base_addr + OTG_DOEP_BASE + 653*91f16700Schasinglulu (ep->num * OTG_DOEP_SIZE); 654*91f16700Schasinglulu reg_value = mmio_read_32(reg_offset + OTG_DOEPCTL); 655*91f16700Schasinglulu 656*91f16700Schasinglulu if ((reg_value & OTG_DOEPCTL_EPENA) == 0U) { 657*91f16700Schasinglulu reg_value &= ~OTG_DOEPCTL_EPDIS; 658*91f16700Schasinglulu } 659*91f16700Schasinglulu 660*91f16700Schasinglulu reg_value |= OTG_DOEPCTL_STALL; 661*91f16700Schasinglulu 662*91f16700Schasinglulu mmio_write_32(reg_offset + OTG_DOEPCTL, reg_value); 663*91f16700Schasinglulu } 664*91f16700Schasinglulu 665*91f16700Schasinglulu return USBD_OK; 666*91f16700Schasinglulu } 667*91f16700Schasinglulu 668*91f16700Schasinglulu /* 669*91f16700Schasinglulu * Stop the USB device mode. 670*91f16700Schasinglulu * handle: Selected device. 671*91f16700Schasinglulu * return: USB status. 672*91f16700Schasinglulu */ 673*91f16700Schasinglulu static enum usb_status usb_dwc2_stop_device(void *handle) 674*91f16700Schasinglulu { 675*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 676*91f16700Schasinglulu uint32_t i; 677*91f16700Schasinglulu 678*91f16700Schasinglulu /* Disable Int */ 679*91f16700Schasinglulu mmio_clrbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT); 680*91f16700Schasinglulu 681*91f16700Schasinglulu /* Clear pending interrupts */ 682*91f16700Schasinglulu for (i = 0U; i < EP_NB; i++) { 683*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_DIEP_BASE + (i * OTG_DIEP_SIZE) + OTG_DIEPINT, 684*91f16700Schasinglulu OTG_DIEPINT_MASK); 685*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_DOEP_BASE + (i * OTG_DOEP_SIZE) + OTG_DOEPINT, 686*91f16700Schasinglulu OTG_DOEPINT_MASK); 687*91f16700Schasinglulu } 688*91f16700Schasinglulu 689*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK); 690*91f16700Schasinglulu 691*91f16700Schasinglulu /* Clear interrupt masks */ 692*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_DIEPMSK, 0U); 693*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_DOEPMSK, 0U); 694*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_DAINTMSK, 0U); 695*91f16700Schasinglulu 696*91f16700Schasinglulu /* Flush the FIFO */ 697*91f16700Schasinglulu usb_dwc2_flush_rx_fifo(handle); 698*91f16700Schasinglulu usb_dwc2_flush_tx_fifo(handle, EP_ALL); 699*91f16700Schasinglulu 700*91f16700Schasinglulu /* Disconnect the USB device by disabling the pull-up/pull-down */ 701*91f16700Schasinglulu mmio_setbits_32((uintptr_t)handle + OTG_DCTL, OTG_DCTL_SDIS); 702*91f16700Schasinglulu 703*91f16700Schasinglulu return USBD_OK; 704*91f16700Schasinglulu } 705*91f16700Schasinglulu 706*91f16700Schasinglulu /* 707*91f16700Schasinglulu * Stop the USB device mode. 708*91f16700Schasinglulu * handle: Selected device. 709*91f16700Schasinglulu * address: New device address to be assigned. 710*91f16700Schasinglulu * This parameter can be a value from 0 to 255. 711*91f16700Schasinglulu * return: USB status. 712*91f16700Schasinglulu */ 713*91f16700Schasinglulu static enum usb_status usb_dwc2_set_address(void *handle, uint8_t address) 714*91f16700Schasinglulu { 715*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 716*91f16700Schasinglulu 717*91f16700Schasinglulu mmio_clrsetbits_32(usb_base_addr + OTG_DCFG, 718*91f16700Schasinglulu OTG_DCFG_DAD, 719*91f16700Schasinglulu address << OTG_DCFG_DAD_SHIFT); 720*91f16700Schasinglulu 721*91f16700Schasinglulu return USBD_OK; 722*91f16700Schasinglulu } 723*91f16700Schasinglulu 724*91f16700Schasinglulu /* 725*91f16700Schasinglulu * Check FIFO for the next packet to be loaded. 726*91f16700Schasinglulu * handle: Selected device. 727*91f16700Schasinglulu * epnum : Endpoint number. 728*91f16700Schasinglulu * xfer_len: Block length. 729*91f16700Schasinglulu * xfer_count: Number of blocks. 730*91f16700Schasinglulu * maxpacket: Max packet length. 731*91f16700Schasinglulu * xfer_buff: Buffer pointer. 732*91f16700Schasinglulu * return: USB status. 733*91f16700Schasinglulu */ 734*91f16700Schasinglulu static enum usb_status usb_dwc2_write_empty_tx_fifo(void *handle, 735*91f16700Schasinglulu uint32_t epnum, 736*91f16700Schasinglulu uint32_t xfer_len, 737*91f16700Schasinglulu uint32_t *xfer_count, 738*91f16700Schasinglulu uint32_t maxpacket, 739*91f16700Schasinglulu uint8_t **xfer_buff) 740*91f16700Schasinglulu { 741*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 742*91f16700Schasinglulu uint32_t reg_offset; 743*91f16700Schasinglulu int32_t len; 744*91f16700Schasinglulu uint32_t len32b; 745*91f16700Schasinglulu enum usb_status ret; 746*91f16700Schasinglulu 747*91f16700Schasinglulu len = xfer_len - *xfer_count; 748*91f16700Schasinglulu 749*91f16700Schasinglulu if ((len > 0) && ((uint32_t)len > maxpacket)) { 750*91f16700Schasinglulu len = maxpacket; 751*91f16700Schasinglulu } 752*91f16700Schasinglulu 753*91f16700Schasinglulu len32b = (len + 3U) / 4U; 754*91f16700Schasinglulu 755*91f16700Schasinglulu reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE); 756*91f16700Schasinglulu 757*91f16700Schasinglulu while (((mmio_read_32(reg_offset + OTG_DTXFSTS) & 758*91f16700Schasinglulu OTG_DTXFSTS_INEPTFSAV) > len32b) && 759*91f16700Schasinglulu (*xfer_count < xfer_len) && (xfer_len != 0U)) { 760*91f16700Schasinglulu /* Write the FIFO */ 761*91f16700Schasinglulu len = xfer_len - *xfer_count; 762*91f16700Schasinglulu 763*91f16700Schasinglulu if ((len > 0) && ((uint32_t)len > maxpacket)) { 764*91f16700Schasinglulu len = maxpacket; 765*91f16700Schasinglulu } 766*91f16700Schasinglulu 767*91f16700Schasinglulu len32b = (len + 3U) / 4U; 768*91f16700Schasinglulu 769*91f16700Schasinglulu ret = usb_dwc2_write_packet(handle, *xfer_buff, epnum, len); 770*91f16700Schasinglulu if (ret != USBD_OK) { 771*91f16700Schasinglulu return ret; 772*91f16700Schasinglulu } 773*91f16700Schasinglulu 774*91f16700Schasinglulu *xfer_buff += len; 775*91f16700Schasinglulu *xfer_count += len; 776*91f16700Schasinglulu } 777*91f16700Schasinglulu 778*91f16700Schasinglulu if (len <= 0) { 779*91f16700Schasinglulu mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum)); 780*91f16700Schasinglulu } 781*91f16700Schasinglulu 782*91f16700Schasinglulu return USBD_OK; 783*91f16700Schasinglulu } 784*91f16700Schasinglulu 785*91f16700Schasinglulu /* 786*91f16700Schasinglulu * Handle PCD interrupt request. 787*91f16700Schasinglulu * handle: PCD handle. 788*91f16700Schasinglulu * param: Pointer to information updated by the IT handling. 789*91f16700Schasinglulu * return: Action to do after IT handling. 790*91f16700Schasinglulu */ 791*91f16700Schasinglulu static enum usb_action usb_dwc2_it_handler(void *handle, uint32_t *param) 792*91f16700Schasinglulu { 793*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 794*91f16700Schasinglulu uint32_t ep_intr; 795*91f16700Schasinglulu uint32_t epint; 796*91f16700Schasinglulu uint32_t epnum; 797*91f16700Schasinglulu uint32_t temp; 798*91f16700Schasinglulu enum usb_status __unused ret; 799*91f16700Schasinglulu 800*91f16700Schasinglulu if (usb_dwc2_get_mode(handle) != USB_OTG_MODE_DEVICE) { 801*91f16700Schasinglulu return USB_NOTHING; 802*91f16700Schasinglulu } 803*91f16700Schasinglulu 804*91f16700Schasinglulu /* Avoid spurious interrupt */ 805*91f16700Schasinglulu if (usb_dwc2_read_int(handle) == 0U) { 806*91f16700Schasinglulu return USB_NOTHING; 807*91f16700Schasinglulu } 808*91f16700Schasinglulu 809*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_MMIS) != 0U) { 810*91f16700Schasinglulu /* Incorrect mode, acknowledge the interrupt */ 811*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_MMIS); 812*91f16700Schasinglulu } 813*91f16700Schasinglulu 814*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OEPINT) != 0U) { 815*91f16700Schasinglulu uint32_t reg_offset; 816*91f16700Schasinglulu 817*91f16700Schasinglulu /* Read in the device interrupt bits */ 818*91f16700Schasinglulu ep_intr = usb_dwc2_all_out_ep_int(handle); 819*91f16700Schasinglulu epnum = 0U; 820*91f16700Schasinglulu while ((ep_intr & BIT(0)) != BIT(0)) { 821*91f16700Schasinglulu epnum++; 822*91f16700Schasinglulu ep_intr >>= 1; 823*91f16700Schasinglulu } 824*91f16700Schasinglulu 825*91f16700Schasinglulu reg_offset = usb_base_addr + OTG_DOEP_BASE + (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT; 826*91f16700Schasinglulu 827*91f16700Schasinglulu epint = usb_dwc2_out_ep_int(handle, epnum); 828*91f16700Schasinglulu 829*91f16700Schasinglulu if ((epint & OTG_DOEPINT_XFRC) == OTG_DOEPINT_XFRC) { 830*91f16700Schasinglulu mmio_write_32(reg_offset, OTG_DOEPINT_XFRC); 831*91f16700Schasinglulu *param = epnum; 832*91f16700Schasinglulu 833*91f16700Schasinglulu return USB_DATA_OUT; 834*91f16700Schasinglulu } 835*91f16700Schasinglulu 836*91f16700Schasinglulu if ((epint & OTG_DOEPINT_STUP) == OTG_DOEPINT_STUP) { 837*91f16700Schasinglulu /* Inform that a setup packet is available */ 838*91f16700Schasinglulu mmio_write_32(reg_offset, OTG_DOEPINT_STUP); 839*91f16700Schasinglulu 840*91f16700Schasinglulu return USB_SETUP; 841*91f16700Schasinglulu } 842*91f16700Schasinglulu 843*91f16700Schasinglulu if ((epint & OTG_DOEPINT_OTEPDIS) == OTG_DOEPINT_OTEPDIS) { 844*91f16700Schasinglulu mmio_write_32(reg_offset, OTG_DOEPINT_OTEPDIS); 845*91f16700Schasinglulu } 846*91f16700Schasinglulu } 847*91f16700Schasinglulu 848*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IEPINT) != 0U) { 849*91f16700Schasinglulu uint32_t reg_offset; 850*91f16700Schasinglulu 851*91f16700Schasinglulu /* Read in the device interrupt bits */ 852*91f16700Schasinglulu ep_intr = usb_dwc2_all_in_ep_int(handle); 853*91f16700Schasinglulu epnum = 0U; 854*91f16700Schasinglulu while ((ep_intr & BIT(0)) != BIT(0)) { 855*91f16700Schasinglulu epnum++; 856*91f16700Schasinglulu ep_intr >>= 1; 857*91f16700Schasinglulu } 858*91f16700Schasinglulu 859*91f16700Schasinglulu reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT; 860*91f16700Schasinglulu 861*91f16700Schasinglulu epint = usb_dwc2_in_ep_int(handle, epnum); 862*91f16700Schasinglulu 863*91f16700Schasinglulu if ((epint & OTG_DIEPINT_XFRC) == OTG_DIEPINT_XFRC) { 864*91f16700Schasinglulu mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum)); 865*91f16700Schasinglulu mmio_write_32(reg_offset, OTG_DIEPINT_XFRC); 866*91f16700Schasinglulu *param = epnum; 867*91f16700Schasinglulu 868*91f16700Schasinglulu return USB_DATA_IN; 869*91f16700Schasinglulu } 870*91f16700Schasinglulu 871*91f16700Schasinglulu if ((epint & OTG_DIEPINT_TOC) == OTG_DIEPINT_TOC) { 872*91f16700Schasinglulu mmio_write_32(reg_offset, OTG_DIEPINT_TOC); 873*91f16700Schasinglulu } 874*91f16700Schasinglulu 875*91f16700Schasinglulu if ((epint & OTG_DIEPINT_ITTXFE) == OTG_DIEPINT_ITTXFE) { 876*91f16700Schasinglulu mmio_write_32(reg_offset, OTG_DIEPINT_ITTXFE); 877*91f16700Schasinglulu } 878*91f16700Schasinglulu 879*91f16700Schasinglulu if ((epint & OTG_DIEPINT_INEPNE) == OTG_DIEPINT_INEPNE) { 880*91f16700Schasinglulu mmio_write_32(reg_offset, OTG_DIEPINT_INEPNE); 881*91f16700Schasinglulu } 882*91f16700Schasinglulu 883*91f16700Schasinglulu if ((epint & OTG_DIEPINT_EPDISD) == OTG_DIEPINT_EPDISD) { 884*91f16700Schasinglulu mmio_write_32(reg_offset, OTG_DIEPINT_EPDISD); 885*91f16700Schasinglulu } 886*91f16700Schasinglulu 887*91f16700Schasinglulu if ((epint & OTG_DIEPINT_TXFE) == OTG_DIEPINT_TXFE) { 888*91f16700Schasinglulu *param = epnum; 889*91f16700Schasinglulu 890*91f16700Schasinglulu return USB_WRITE_EMPTY; 891*91f16700Schasinglulu } 892*91f16700Schasinglulu } 893*91f16700Schasinglulu 894*91f16700Schasinglulu /* Handle resume interrupt */ 895*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_WKUPINT) != 0U) { 896*91f16700Schasinglulu INFO("handle USB : Resume\n"); 897*91f16700Schasinglulu 898*91f16700Schasinglulu /* Clear the remote wake-up signaling */ 899*91f16700Schasinglulu mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG); 900*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_WKUPINT); 901*91f16700Schasinglulu 902*91f16700Schasinglulu return USB_RESUME; 903*91f16700Schasinglulu } 904*91f16700Schasinglulu 905*91f16700Schasinglulu /* Handle suspend interrupt */ 906*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBSUSP) != 0U) { 907*91f16700Schasinglulu INFO("handle USB : Suspend int\n"); 908*91f16700Schasinglulu 909*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBSUSP); 910*91f16700Schasinglulu 911*91f16700Schasinglulu if ((mmio_read_32(usb_base_addr + OTG_DSTS) & 912*91f16700Schasinglulu OTG_DSTS_SUSPSTS) == OTG_DSTS_SUSPSTS) { 913*91f16700Schasinglulu return USB_SUSPEND; 914*91f16700Schasinglulu } 915*91f16700Schasinglulu } 916*91f16700Schasinglulu 917*91f16700Schasinglulu /* Handle LPM interrupt */ 918*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_LPMINT) != 0U) { 919*91f16700Schasinglulu INFO("handle USB : LPM int enter in suspend\n"); 920*91f16700Schasinglulu 921*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_LPMINT); 922*91f16700Schasinglulu *param = (mmio_read_32(usb_base_addr + OTG_GLPMCFG) & 923*91f16700Schasinglulu OTG_GLPMCFG_BESL) >> 2; 924*91f16700Schasinglulu 925*91f16700Schasinglulu return USB_LPM; 926*91f16700Schasinglulu } 927*91f16700Schasinglulu 928*91f16700Schasinglulu /* Handle reset interrupt */ 929*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBRST) != 0U) { 930*91f16700Schasinglulu INFO("handle USB : Reset\n"); 931*91f16700Schasinglulu 932*91f16700Schasinglulu mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG); 933*91f16700Schasinglulu 934*91f16700Schasinglulu usb_dwc2_flush_tx_fifo(handle, 0U); 935*91f16700Schasinglulu 936*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK); 937*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_DAINTMSK, OTG_DAINT_EP0_IN | OTG_DAINT_EP0_OUT); 938*91f16700Schasinglulu 939*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_DOEPMSK, OTG_DOEPMSK_STUPM | 940*91f16700Schasinglulu OTG_DOEPMSK_XFRCM | 941*91f16700Schasinglulu OTG_DOEPMSK_EPDM); 942*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_DIEPMSK, OTG_DIEPMSK_TOM | 943*91f16700Schasinglulu OTG_DIEPMSK_XFRCM | 944*91f16700Schasinglulu OTG_DIEPMSK_EPDM); 945*91f16700Schasinglulu 946*91f16700Schasinglulu /* Set default address to 0 */ 947*91f16700Schasinglulu mmio_clrbits_32(usb_base_addr + OTG_DCFG, OTG_DCFG_DAD); 948*91f16700Schasinglulu 949*91f16700Schasinglulu /* Setup EP0 to receive SETUP packets */ 950*91f16700Schasinglulu ret = usb_dwc2_ep0_out_start(handle); 951*91f16700Schasinglulu assert(ret == USBD_OK); 952*91f16700Schasinglulu 953*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBRST); 954*91f16700Schasinglulu 955*91f16700Schasinglulu return USB_RESET; 956*91f16700Schasinglulu } 957*91f16700Schasinglulu 958*91f16700Schasinglulu /* Handle enumeration done interrupt */ 959*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_ENUMDNE) != 0U) { 960*91f16700Schasinglulu ret = usb_dwc2_activate_setup(handle); 961*91f16700Schasinglulu assert(ret == USBD_OK); 962*91f16700Schasinglulu 963*91f16700Schasinglulu mmio_clrbits_32(usb_base_addr + OTG_GUSBCFG, OTG_GUSBCFG_TRDT); 964*91f16700Schasinglulu 965*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_GUSBCFG, 966*91f16700Schasinglulu (USBD_HS_TRDT_VALUE << OTG_GUSBCFG_TRDT_SHIFT) & OTG_GUSBCFG_TRDT); 967*91f16700Schasinglulu 968*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_ENUMDNE); 969*91f16700Schasinglulu 970*91f16700Schasinglulu return USB_ENUM_DONE; 971*91f16700Schasinglulu } 972*91f16700Schasinglulu 973*91f16700Schasinglulu /* Handle RXQLevel interrupt */ 974*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_RXFLVL) != 0U) { 975*91f16700Schasinglulu mmio_clrbits_32(usb_base_addr + OTG_GINTMSK, 976*91f16700Schasinglulu OTG_GINTSTS_RXFLVL); 977*91f16700Schasinglulu 978*91f16700Schasinglulu temp = mmio_read_32(usb_base_addr + OTG_GRXSTSP); 979*91f16700Schasinglulu 980*91f16700Schasinglulu *param = temp & OTG_GRXSTSP_EPNUM; 981*91f16700Schasinglulu *param |= (temp & OTG_GRXSTSP_BCNT) << (USBD_OUT_COUNT_SHIFT - 982*91f16700Schasinglulu OTG_GRXSTSP_BCNT_SHIFT); 983*91f16700Schasinglulu 984*91f16700Schasinglulu if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == STS_DATA_UPDT) { 985*91f16700Schasinglulu if ((temp & OTG_GRXSTSP_BCNT) != 0U) { 986*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); 987*91f16700Schasinglulu 988*91f16700Schasinglulu return USB_READ_DATA_PACKET; 989*91f16700Schasinglulu } 990*91f16700Schasinglulu } else if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == 991*91f16700Schasinglulu STS_SETUP_UPDT) { 992*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); 993*91f16700Schasinglulu 994*91f16700Schasinglulu return USB_READ_SETUP_PACKET; 995*91f16700Schasinglulu } 996*91f16700Schasinglulu 997*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); 998*91f16700Schasinglulu } 999*91f16700Schasinglulu 1000*91f16700Schasinglulu /* Handle SOF interrupt */ 1001*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SOF) != 0U) { 1002*91f16700Schasinglulu INFO("handle USB : SOF\n"); 1003*91f16700Schasinglulu 1004*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SOF); 1005*91f16700Schasinglulu 1006*91f16700Schasinglulu return USB_SOF; 1007*91f16700Schasinglulu } 1008*91f16700Schasinglulu 1009*91f16700Schasinglulu /* Handle incomplete ISO IN interrupt */ 1010*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IISOIXFR) != 0U) { 1011*91f16700Schasinglulu INFO("handle USB : ISO IN\n"); 1012*91f16700Schasinglulu 1013*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GINTSTS, 1014*91f16700Schasinglulu OTG_GINTSTS_IISOIXFR); 1015*91f16700Schasinglulu } 1016*91f16700Schasinglulu 1017*91f16700Schasinglulu /* Handle incomplete ISO OUT interrupt */ 1018*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IPXFR_INCOMPISOOUT) != 1019*91f16700Schasinglulu 0U) { 1020*91f16700Schasinglulu INFO("handle USB : ISO OUT\n"); 1021*91f16700Schasinglulu 1022*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GINTSTS, 1023*91f16700Schasinglulu OTG_GINTSTS_IPXFR_INCOMPISOOUT); 1024*91f16700Schasinglulu } 1025*91f16700Schasinglulu 1026*91f16700Schasinglulu /* Handle connection event interrupt */ 1027*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SRQINT) != 0U) { 1028*91f16700Schasinglulu INFO("handle USB : Connect\n"); 1029*91f16700Schasinglulu 1030*91f16700Schasinglulu mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SRQINT); 1031*91f16700Schasinglulu } 1032*91f16700Schasinglulu 1033*91f16700Schasinglulu /* Handle disconnection event interrupt */ 1034*91f16700Schasinglulu if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OTGINT) != 0U) { 1035*91f16700Schasinglulu INFO("handle USB : Disconnect\n"); 1036*91f16700Schasinglulu 1037*91f16700Schasinglulu temp = mmio_read_32(usb_base_addr + OTG_GOTGINT); 1038*91f16700Schasinglulu 1039*91f16700Schasinglulu if ((temp & OTG_GOTGINT_SEDET) == OTG_GOTGINT_SEDET) { 1040*91f16700Schasinglulu return USB_DISCONNECT; 1041*91f16700Schasinglulu } 1042*91f16700Schasinglulu } 1043*91f16700Schasinglulu 1044*91f16700Schasinglulu return USB_NOTHING; 1045*91f16700Schasinglulu } 1046*91f16700Schasinglulu 1047*91f16700Schasinglulu /* 1048*91f16700Schasinglulu * Start the usb device mode 1049*91f16700Schasinglulu * usb_core_handle: USB core driver handle. 1050*91f16700Schasinglulu * return USB status. 1051*91f16700Schasinglulu */ 1052*91f16700Schasinglulu static enum usb_status usb_dwc2_start_device(void *handle) 1053*91f16700Schasinglulu { 1054*91f16700Schasinglulu uintptr_t usb_base_addr = (uintptr_t)handle; 1055*91f16700Schasinglulu 1056*91f16700Schasinglulu mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_SDIS); 1057*91f16700Schasinglulu mmio_setbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT); 1058*91f16700Schasinglulu 1059*91f16700Schasinglulu return USBD_OK; 1060*91f16700Schasinglulu } 1061*91f16700Schasinglulu 1062*91f16700Schasinglulu static const struct usb_driver usb_dwc2driver = { 1063*91f16700Schasinglulu .ep0_out_start = usb_dwc2_ep0_out_start, 1064*91f16700Schasinglulu .ep_start_xfer = usb_dwc2_ep_start_xfer, 1065*91f16700Schasinglulu .ep0_start_xfer = usb_dwc2_ep0_start_xfer, 1066*91f16700Schasinglulu .write_packet = usb_dwc2_write_packet, 1067*91f16700Schasinglulu .read_packet = usb_dwc2_read_packet, 1068*91f16700Schasinglulu .ep_set_stall = usb_dwc2_ep_set_stall, 1069*91f16700Schasinglulu .start_device = usb_dwc2_start_device, 1070*91f16700Schasinglulu .stop_device = usb_dwc2_stop_device, 1071*91f16700Schasinglulu .set_address = usb_dwc2_set_address, 1072*91f16700Schasinglulu .write_empty_tx_fifo = usb_dwc2_write_empty_tx_fifo, 1073*91f16700Schasinglulu .it_handler = usb_dwc2_it_handler 1074*91f16700Schasinglulu }; 1075*91f16700Schasinglulu 1076*91f16700Schasinglulu /* 1077*91f16700Schasinglulu * Initialize USB DWC2 driver. 1078*91f16700Schasinglulu * usb_core_handle: USB core driver handle. 1079*91f16700Schasinglulu * pcd_handle: PCD handle. 1080*91f16700Schasinglulu * base_register: USB global register base address. 1081*91f16700Schasinglulu */ 1082*91f16700Schasinglulu void stm32mp1_usb_init_driver(struct usb_handle *usb_core_handle, 1083*91f16700Schasinglulu struct pcd_handle *pcd_handle, 1084*91f16700Schasinglulu void *base_register) 1085*91f16700Schasinglulu { 1086*91f16700Schasinglulu register_usb_driver(usb_core_handle, pcd_handle, &usb_dwc2driver, 1087*91f16700Schasinglulu base_register); 1088*91f16700Schasinglulu } 1089