hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
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
// 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)