Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | // SPDX-License-Identifier: GPL-2.0 /* * Toshiba TC86C001 ("Goku-S") USB Device Controller driver * * Copyright (C) 2000-2002 Lineo * by Stuart Lynne, Tom Rushworth, and Bruce Balden * Copyright (C) 2002 Toshiba Corporation * Copyright (C) 2003 MontaVista Software (source@mvista.com) */ /* * PCI BAR 0 points to these registers. */ struct goku_udc_regs { /* irq management */ u32 int_status; /* 0x000 */ u32 int_enable; #define INT_SUSPEND 0x00001 /* or resume */ #define INT_USBRESET 0x00002 #define INT_ENDPOINT0 0x00004 #define INT_SETUP 0x00008 #define INT_STATUS 0x00010 #define INT_STATUSNAK 0x00020 #define INT_EPxDATASET(n) (0x00020 << (n)) /* 0 < n < 4 */ # define INT_EP1DATASET 0x00040 # define INT_EP2DATASET 0x00080 # define INT_EP3DATASET 0x00100 #define INT_EPnNAK(n) (0x00100 << (n)) /* 0 < n < 4 */ # define INT_EP1NAK 0x00200 # define INT_EP2NAK 0x00400 # define INT_EP3NAK 0x00800 #define INT_SOF 0x01000 #define INT_ERR 0x02000 #define INT_MSTWRSET 0x04000 #define INT_MSTWREND 0x08000 #define INT_MSTWRTMOUT 0x10000 #define INT_MSTRDEND 0x20000 #define INT_SYSERROR 0x40000 #define INT_PWRDETECT 0x80000 #define INT_DEVWIDE \ (INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND) #define INT_EP0 \ (INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK) u32 dma_master; #define MST_EOPB_DIS 0x0800 #define MST_EOPB_ENA 0x0400 #define MST_TIMEOUT_DIS 0x0200 #define MST_TIMEOUT_ENA 0x0100 #define MST_RD_EOPB 0x0080 /* write-only */ #define MST_RD_RESET 0x0040 #define MST_WR_RESET 0x0020 #define MST_RD_ENA 0x0004 /* 1:start, 0:ignore */ #define MST_WR_ENA 0x0002 /* 1:start, 0:ignore */ #define MST_CONNECTION 0x0001 /* 0 for ep1out/ep2in */ #define MST_R_BITS (MST_EOPB_DIS|MST_EOPB_ENA \ |MST_RD_ENA|MST_RD_RESET) #define MST_W_BITS (MST_TIMEOUT_DIS|MST_TIMEOUT_ENA \ |MST_WR_ENA|MST_WR_RESET) #define MST_RW_BITS (MST_R_BITS|MST_W_BITS \ |MST_CONNECTION) /* these values assume (dma_master & MST_CONNECTION) == 0 */ #define UDC_MSTWR_ENDPOINT 1 #define UDC_MSTRD_ENDPOINT 2 /* dma master write */ u32 out_dma_start; u32 out_dma_end; u32 out_dma_current; /* dma master read */ u32 in_dma_start; u32 in_dma_end; u32 in_dma_current; u32 power_detect; #define PW_DETECT 0x04 #define PW_RESETB 0x02 #define PW_PULLUP 0x01 u8 _reserved0 [0x1d8]; /* endpoint registers */ u32 ep_fifo [4]; /* 0x200 */ u8 _reserved1 [0x10]; u32 ep_mode [4]; /* only 1-3 valid */ u8 _reserved2 [0x10]; u32 ep_status [4]; #define EPxSTATUS_TOGGLE 0x40 #define EPxSTATUS_SUSPEND 0x20 #define EPxSTATUS_EP_MASK (0x07<<2) # define EPxSTATUS_EP_READY (0<<2) # define EPxSTATUS_EP_DATAIN (1<<2) # define EPxSTATUS_EP_FULL (2<<2) # define EPxSTATUS_EP_TX_ERR (3<<2) # define EPxSTATUS_EP_RX_ERR (4<<2) # define EPxSTATUS_EP_BUSY (5<<2) # define EPxSTATUS_EP_STALL (6<<2) # define EPxSTATUS_EP_INVALID (7<<2) #define EPxSTATUS_FIFO_DISABLE 0x02 #define EPxSTATUS_STAGE_ERROR 0x01 u8 _reserved3 [0x10]; u32 EPxSizeLA[4]; #define PACKET_ACTIVE (1<<7) #define DATASIZE 0x7f u8 _reserved3a [0x10]; u32 EPxSizeLB[4]; /* only 1,2 valid */ u8 _reserved3b [0x10]; u32 EPxSizeHA[4]; /* only 1-3 valid */ u8 _reserved3c [0x10]; u32 EPxSizeHB[4]; /* only 1,2 valid */ u8 _reserved4[0x30]; /* SETUP packet contents */ u32 bRequestType; /* 0x300 */ u32 bRequest; u32 wValueL; u32 wValueH; u32 wIndexL; u32 wIndexH; u32 wLengthL; u32 wLengthH; /* command interaction/handshaking */ u32 SetupRecv; /* 0x320 */ u32 CurrConfig; u32 StdRequest; u32 Request; u32 DataSet; #define DATASET_A(epnum) (1<<(2*(epnum))) #define DATASET_B(epnum) (2<<(2*(epnum))) #define DATASET_AB(epnum) (3<<(2*(epnum))) u8 _reserved5[4]; u32 UsbState; #define USBSTATE_CONFIGURED 0x04 #define USBSTATE_ADDRESSED 0x02 #define USBSTATE_DEFAULT 0x01 u32 EOP; u32 Command; /* 0x340 */ #define COMMAND_SETDATA0 2 #define COMMAND_RESET 3 #define COMMAND_STALL 4 #define COMMAND_INVALID 5 #define COMMAND_FIFO_DISABLE 7 #define COMMAND_FIFO_ENABLE 8 #define COMMAND_INIT_DESCRIPTOR 9 #define COMMAND_FIFO_CLEAR 10 /* also stall */ #define COMMAND_STALL_CLEAR 11 #define COMMAND_EP(n) ((n) << 4) u32 EPxSingle; u8 _reserved6[4]; u32 EPxBCS; u8 _reserved7[8]; u32 IntControl; #define ICONTROL_STATUSNAK 1 u8 _reserved8[4]; u32 reqmode; // 0x360 standard request mode, low 8 bits #define G_REQMODE_SET_INTF (1<<7) #define G_REQMODE_GET_INTF (1<<6) #define G_REQMODE_SET_CONF (1<<5) #define G_REQMODE_GET_CONF (1<<4) #define G_REQMODE_GET_DESC (1<<3) #define G_REQMODE_SET_FEAT (1<<2) #define G_REQMODE_CLEAR_FEAT (1<<1) #define G_REQMODE_GET_STATUS (1<<0) u32 ReqMode; u8 _reserved9[0x18]; u32 PortStatus; /* 0x380 */ u8 _reserved10[8]; u32 address; u32 buff_test; u8 _reserved11[4]; u32 UsbReady; u8 _reserved12[4]; u32 SetDescStall; /* 0x3a0 */ u8 _reserved13[0x45c]; /* hardware could handle limited GET_DESCRIPTOR duties */ #define DESC_LEN 0x80 u32 descriptors[DESC_LEN]; /* 0x800 */ u8 _reserved14[0x600]; } __attribute__ ((packed)); #define MAX_FIFO_SIZE 64 #define MAX_EP0_SIZE 8 /* ep0 fifo is bigger, though */ /*-------------------------------------------------------------------------*/ /* DRIVER DATA STRUCTURES and UTILITIES */ struct goku_ep { struct usb_ep ep; struct goku_udc *dev; unsigned long irqs; unsigned num:8, dma:1, is_in:1, stopped:1; /* analogous to a host-side qh */ struct list_head queue; u32 __iomem *reg_fifo; u32 __iomem *reg_mode; u32 __iomem *reg_status; }; struct goku_request { struct usb_request req; struct list_head queue; unsigned mapped:1; }; enum ep0state { EP0_DISCONNECT, /* no host */ EP0_IDLE, /* between STATUS ack and SETUP report */ EP0_IN, EP0_OUT, /* data stage */ EP0_STATUS, /* status stage */ EP0_STALL, /* data or status stages */ EP0_SUSPEND, /* usb suspend */ }; struct goku_udc { /* each pci device provides one gadget, several endpoints */ struct usb_gadget gadget; spinlock_t lock; struct goku_ep ep[4]; struct usb_gadget_driver *driver; enum ep0state ep0state; unsigned got_irq:1, got_region:1, req_config:1, configured:1, enabled:1; /* pci state used to access those endpoints */ struct pci_dev *pdev; struct goku_udc_regs __iomem *regs; u32 int_enable; /* statistics... */ unsigned long irqs; }; #define to_goku_udc(g) (container_of((g), struct goku_udc, gadget)) /*-------------------------------------------------------------------------*/ #define xprintk(dev,level,fmt,args...) \ printk(level "%s %s: " fmt , driver_name , \ pci_name(dev->pdev) , ## args) #ifdef DEBUG #define DBG(dev,fmt,args...) \ xprintk(dev , KERN_DEBUG , fmt , ## args) #else #define DBG(dev,fmt,args...) \ do { } while (0) #endif /* DEBUG */ #ifdef VERBOSE #define VDBG DBG #else #define VDBG(dev,fmt,args...) \ do { } while (0) #endif /* VERBOSE */ #define ERROR(dev,fmt,args...) \ xprintk(dev , KERN_ERR , fmt , ## args) #define WARNING(dev,fmt,args...) \ xprintk(dev , KERN_WARNING , fmt , ## args) #define INFO(dev,fmt,args...) \ xprintk(dev , KERN_INFO , fmt , ## args) |