diff options
author | Ashwini Pahuja <ashwini.linux@gmail.com> | 2014-11-13 13:22:32 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2014-11-18 09:47:23 -0500 |
commit | efed421a94e62a7ddbc76acba4312b70e4be958f (patch) | |
tree | ed4dcf52d59c2ff3db2ee3f20777abaff4b887ee | |
parent | 5ee80705a5339270538119d1e8721b365eac5202 (diff) |
usb: gadget: Add UDC driver for Broadcom USB3.0 device controller IP BDC
This patch adds a UDC driver for Broadcom's USB3.0 Peripheral core named BDC.
BDC supports control traffic on ep0 and bulk/Int/Isoch traffic on all other
endpoints.
[ balbi@ti.com : fix build error on randconfig due to lack of
<linux/dmapool.h> ]
Signed-off-by: Ashwini Pahuja <ashwini.linux@gmail.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r-- | drivers/usb/gadget/udc/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/Kconfig | 21 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/Makefile | 8 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/bdc.h | 490 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/bdc_cmd.c | 376 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/bdc_cmd.h | 29 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/bdc_core.c | 533 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/bdc_dbg.c | 123 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/bdc_dbg.h | 37 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/bdc_ep.c | 2023 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/bdc_ep.h | 22 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/bdc_pci.c | 132 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/bdc/bdc_udc.c | 587 |
14 files changed, 4384 insertions, 0 deletions
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 217365d35a25..b8e213eb36cc 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig | |||
@@ -241,6 +241,8 @@ config USB_M66592 | |||
241 | dynamically linked module called "m66592_udc" and force all | 241 | dynamically linked module called "m66592_udc" and force all |
242 | gadget drivers to also be dynamically linked. | 242 | gadget drivers to also be dynamically linked. |
243 | 243 | ||
244 | source "drivers/usb/gadget/udc/bdc/Kconfig" | ||
245 | |||
244 | # | 246 | # |
245 | # Controllers available only in discrete form (and all PCI controllers) | 247 | # Controllers available only in discrete form (and all PCI controllers) |
246 | # | 248 | # |
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile index a7f4491593f1..fba2049bf985 100644 --- a/drivers/usb/gadget/udc/Makefile +++ b/drivers/usb/gadget/udc/Makefile | |||
@@ -30,3 +30,4 @@ obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o | |||
30 | obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o | 30 | obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o |
31 | obj-$(CONFIG_USB_GR_UDC) += gr_udc.o | 31 | obj-$(CONFIG_USB_GR_UDC) += gr_udc.o |
32 | obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o | 32 | obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o |
33 | obj-$(CONFIG_USB_BDC_UDC) += bdc/ | ||
diff --git a/drivers/usb/gadget/udc/bdc/Kconfig b/drivers/usb/gadget/udc/bdc/Kconfig new file mode 100644 index 000000000000..0d7b8c9f72fd --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/Kconfig | |||
@@ -0,0 +1,21 @@ | |||
1 | config USB_BDC_UDC | ||
2 | tristate "Broadcom USB3.0 device controller IP driver(BDC)" | ||
3 | depends on USB_GADGET && HAS_DMA | ||
4 | |||
5 | help | ||
6 | BDC is Broadcom's USB3.0 device controller IP. If your SOC has a BDC IP | ||
7 | then select this driver. | ||
8 | |||
9 | Say "y" here to link the driver statically, or "m" to build a dynamically | ||
10 | linked module called "bdc". | ||
11 | |||
12 | if USB_BDC_UDC | ||
13 | |||
14 | comment "Platform Support" | ||
15 | config USB_BDC_PCI | ||
16 | tristate "BDC support for PCIe based platforms" | ||
17 | depends on PCI | ||
18 | default USB_BDC_UDC | ||
19 | help | ||
20 | Enable support for platforms which have BDC connected through PCIe, such as Lego3 FPGA platform. | ||
21 | endif | ||
diff --git a/drivers/usb/gadget/udc/bdc/Makefile b/drivers/usb/gadget/udc/bdc/Makefile new file mode 100644 index 000000000000..5cf6a3bcdf0f --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | obj-$(CONFIG_USB_BDC_UDC) += bdc.o | ||
2 | bdc-y := bdc_core.o bdc_cmd.o bdc_ep.o bdc_udc.o | ||
3 | |||
4 | ifneq ($(CONFIG_USB_GADGET_VERBOSE),) | ||
5 | bdc-y += bdc_dbg.o | ||
6 | endif | ||
7 | |||
8 | obj-$(CONFIG_USB_BDC_PCI) += bdc_pci.o | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc.h b/drivers/usb/gadget/udc/bdc/bdc.h new file mode 100644 index 000000000000..dc18a20bf040 --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/bdc.h | |||
@@ -0,0 +1,490 @@ | |||
1 | /* | ||
2 | * bdc.h - header for the BRCM BDC USB3.0 device controller | ||
3 | * | ||
4 | * Copyright (C) 2014 Broadcom Corporation | ||
5 | * | ||
6 | * Author: Ashwini Pahuja | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #ifndef __LINUX_BDC_H__ | ||
16 | #define __LINUX_BDC_H__ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/usb.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | #include <linux/list.h> | ||
23 | #include <linux/dma-mapping.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/debugfs.h> | ||
26 | #include <linux/usb/ch9.h> | ||
27 | #include <linux/usb/gadget.h> | ||
28 | #include <asm/unaligned.h> | ||
29 | |||
30 | #define BRCM_BDC_NAME "bdc_usb3" | ||
31 | #define BRCM_BDC_DESC "BDC device controller driver" | ||
32 | |||
33 | #define DMA_ADDR_INVALID (~(dma_addr_t)0) | ||
34 | |||
35 | /* BDC command operation timeout in usec*/ | ||
36 | #define BDC_CMD_TIMEOUT 1000 | ||
37 | /* BDC controller operation timeout in usec*/ | ||
38 | #define BDC_COP_TIMEOUT 500 | ||
39 | |||
40 | /* | ||
41 | * Maximum size of ep0 response buffer for ch9 requests, | ||
42 | * the set_sel request uses 6 so far, the max. | ||
43 | */ | ||
44 | #define EP0_RESPONSE_BUFF 6 | ||
45 | /* Start with SS as default */ | ||
46 | #define EP0_MAX_PKT_SIZE 512 | ||
47 | |||
48 | /* 64 entries in a SRR */ | ||
49 | #define NUM_SR_ENTRIES 64 | ||
50 | |||
51 | /* Num of bds per table */ | ||
52 | #define NUM_BDS_PER_TABLE 32 | ||
53 | |||
54 | /* Num of tables in bd list for control,bulk and Int ep */ | ||
55 | #define NUM_TABLES 2 | ||
56 | |||
57 | /* Num of tables in bd list for Isoch ep */ | ||
58 | #define NUM_TABLES_ISOCH 6 | ||
59 | |||
60 | /* U1 Timeout default: 248usec */ | ||
61 | #define U1_TIMEOUT 0xf8 | ||
62 | |||
63 | /* Interrupt coalescence in usec */ | ||
64 | #define INT_CLS 500 | ||
65 | |||
66 | /* Register offsets */ | ||
67 | /* Configuration and Capability registers */ | ||
68 | #define BDC_BDCCFG0 0x00 | ||
69 | #define BDC_BDCCFG1 0x04 | ||
70 | #define BDC_BDCCAP0 0x08 | ||
71 | #define BDC_BDCCAP1 0x0c | ||
72 | #define BDC_CMDPAR0 0x10 | ||
73 | #define BDC_CMDPAR1 0x14 | ||
74 | #define BDC_CMDPAR2 0x18 | ||
75 | #define BDC_CMDSC 0x1c | ||
76 | #define BDC_USPC 0x20 | ||
77 | #define BDC_USPPMS 0x28 | ||
78 | #define BDC_USPPM2 0x2c | ||
79 | #define BDC_SPBBAL 0x38 | ||
80 | #define BDC_SPBBAH 0x3c | ||
81 | #define BDC_BDCSC 0x40 | ||
82 | #define BDC_XSFNTF 0x4c | ||
83 | |||
84 | #define BDC_DVCSA 0x50 | ||
85 | #define BDC_DVCSB 0x54 | ||
86 | #define BDC_EPSTS0(n) (0x60 + (n * 0x10)) | ||
87 | #define BDC_EPSTS1(n) (0x64 + (n * 0x10)) | ||
88 | #define BDC_EPSTS2(n) (0x68 + (n * 0x10)) | ||
89 | #define BDC_EPSTS3(n) (0x6c + (n * 0x10)) | ||
90 | #define BDC_EPSTS4(n) (0x70 + (n * 0x10)) | ||
91 | #define BDC_EPSTS5(n) (0x74 + (n * 0x10)) | ||
92 | #define BDC_EPSTS6(n) (0x78 + (n * 0x10)) | ||
93 | #define BDC_EPSTS7(n) (0x7c + (n * 0x10)) | ||
94 | #define BDC_SRRBAL(n) (0x200 + (n * 0x10)) | ||
95 | #define BDC_SRRBAH(n) (0x204 + (n * 0x10)) | ||
96 | #define BDC_SRRINT(n) (0x208 + (n * 0x10)) | ||
97 | #define BDC_INTCTLS(n) (0x20c + (n * 0x10)) | ||
98 | |||
99 | /* Extended capability regs */ | ||
100 | #define BDC_FSCNOC 0xcd4 | ||
101 | #define BDC_FSCNIC 0xce4 | ||
102 | #define NUM_NCS(p) (p >> 28) | ||
103 | |||
104 | /* Register bit fields and Masks */ | ||
105 | /* BDC Configuration 0 */ | ||
106 | #define BDC_PGS(p) (((p) & (0x7 << 8)) >> 8) | ||
107 | #define BDC_SPB(p) (p & 0x7) | ||
108 | |||
109 | /* BDC Capability1 */ | ||
110 | #define BDC_P64 (1 << 0) | ||
111 | |||
112 | /* BDC Command register */ | ||
113 | #define BDC_CMD_FH 0xe | ||
114 | #define BDC_CMD_DNC 0x6 | ||
115 | #define BDC_CMD_EPO 0x4 | ||
116 | #define BDC_CMD_BLA 0x3 | ||
117 | #define BDC_CMD_EPC 0x2 | ||
118 | #define BDC_CMD_DVC 0x1 | ||
119 | #define BDC_CMD_CWS (0x1 << 5) | ||
120 | #define BDC_CMD_CST(p) (((p) & (0xf << 6))>>6) | ||
121 | #define BDC_CMD_EPN(p) ((p & 0x1f) << 10) | ||
122 | #define BDC_SUB_CMD_ADD (0x1 << 17) | ||
123 | #define BDC_SUB_CMD_FWK (0x4 << 17) | ||
124 | /* Reset sequence number */ | ||
125 | #define BDC_CMD_EPO_RST_SN (0x1 << 16) | ||
126 | #define BDC_CMD_EP0_XSD (0x1 << 16) | ||
127 | #define BDC_SUB_CMD_ADD_EP (0x1 << 17) | ||
128 | #define BDC_SUB_CMD_DRP_EP (0x2 << 17) | ||
129 | #define BDC_SUB_CMD_EP_STP (0x2 << 17) | ||
130 | #define BDC_SUB_CMD_EP_STL (0x4 << 17) | ||
131 | #define BDC_SUB_CMD_EP_RST (0x1 << 17) | ||
132 | #define BDC_CMD_SRD (1 << 27) | ||
133 | |||
134 | /* CMD completion status */ | ||
135 | #define BDC_CMDS_SUCC 0x1 | ||
136 | #define BDC_CMDS_PARA 0x3 | ||
137 | #define BDC_CMDS_STAT 0x4 | ||
138 | #define BDC_CMDS_FAIL 0x5 | ||
139 | #define BDC_CMDS_INTL 0x6 | ||
140 | #define BDC_CMDS_BUSY 0xf | ||
141 | |||
142 | /* CMDSC Param 2 shifts */ | ||
143 | #define EPT_SHIFT 22 | ||
144 | #define MP_SHIFT 10 | ||
145 | #define MB_SHIFT 6 | ||
146 | #define EPM_SHIFT 4 | ||
147 | |||
148 | /* BDC USPSC */ | ||
149 | #define BDC_VBC (1 << 31) | ||
150 | #define BDC_PRC (1 << 30) | ||
151 | #define BDC_PCE (1 << 29) | ||
152 | #define BDC_CFC (1 << 28) | ||
153 | #define BDC_PCC (1 << 27) | ||
154 | #define BDC_PSC (1 << 26) | ||
155 | #define BDC_VBS (1 << 25) | ||
156 | #define BDC_PRS (1 << 24) | ||
157 | #define BDC_PCS (1 << 23) | ||
158 | #define BDC_PSP(p) (((p) & (0x7 << 20))>>20) | ||
159 | #define BDC_SCN (1 << 8) | ||
160 | #define BDC_SDC (1 << 7) | ||
161 | #define BDC_SWS (1 << 4) | ||
162 | |||
163 | #define BDC_USPSC_RW (BDC_SCN|BDC_SDC|BDC_SWS|0xf) | ||
164 | #define BDC_PSP(p) (((p) & (0x7 << 20))>>20) | ||
165 | |||
166 | #define BDC_SPEED_FS 0x1 | ||
167 | #define BDC_SPEED_LS 0x2 | ||
168 | #define BDC_SPEED_HS 0x3 | ||
169 | #define BDC_SPEED_SS 0x4 | ||
170 | |||
171 | #define BDC_PST(p) (p & 0xf) | ||
172 | #define BDC_PST_MASK 0xf | ||
173 | |||
174 | /* USPPMS */ | ||
175 | #define BDC_U2E (0x1 << 31) | ||
176 | #define BDC_U1E (0x1 << 30) | ||
177 | #define BDC_U2A (0x1 << 29) | ||
178 | #define BDC_PORT_W1S (0x1 << 17) | ||
179 | #define BDC_U1T(p) ((p) & 0xff) | ||
180 | #define BDC_U2T(p) (((p) & 0xff) << 8) | ||
181 | #define BDC_U1T_MASK 0xff | ||
182 | |||
183 | /* USBPM2 */ | ||
184 | /* Hardware LPM Enable */ | ||
185 | #define BDC_HLE (1 << 16) | ||
186 | |||
187 | /* BDC Status and Control */ | ||
188 | #define BDC_COP_RST (1 << 29) | ||
189 | #define BDC_COP_RUN (2 << 29) | ||
190 | #define BDC_COP_STP (4 << 29) | ||
191 | |||
192 | #define BDC_COP_MASK (BDC_COP_RST|BDC_COP_RUN|BDC_COP_STP) | ||
193 | |||
194 | #define BDC_COS (1 << 28) | ||
195 | #define BDC_CSTS(p) (((p) & (0x7 << 20)) >> 20) | ||
196 | #define BDC_MASK_MCW (1 << 7) | ||
197 | #define BDC_GIE (1 << 1) | ||
198 | #define BDC_GIP (1 << 0) | ||
199 | |||
200 | #define BDC_HLT 1 | ||
201 | #define BDC_NOR 2 | ||
202 | #define BDC_OIP 7 | ||
203 | |||
204 | /* Buffer descriptor and Status report bit fields and masks */ | ||
205 | #define BD_TYPE_BITMASK (0xf) | ||
206 | #define BD_CHAIN 0xf | ||
207 | |||
208 | #define BD_TFS_SHIFT 4 | ||
209 | #define BD_SOT (1 << 26) | ||
210 | #define BD_EOT (1 << 27) | ||
211 | #define BD_ISP (1 << 29) | ||
212 | #define BD_IOC (1 << 30) | ||
213 | #define BD_SBF (1 << 31) | ||
214 | |||
215 | #define BD_INTR_TARGET(p) (((p) & 0x1f) << 27) | ||
216 | |||
217 | #define BDC_SRR_RWS (1 << 4) | ||
218 | #define BDC_SRR_RST (1 << 3) | ||
219 | #define BDC_SRR_ISR (1 << 2) | ||
220 | #define BDC_SRR_IE (1 << 1) | ||
221 | #define BDC_SRR_IP (1 << 0) | ||
222 | #define BDC_SRR_EPI(p) (((p) & (0xff << 24)) >> 24) | ||
223 | #define BDC_SRR_DPI(p) (((p) & (0xff << 16)) >> 16) | ||
224 | #define BDC_SRR_DPI_MASK 0x00ff0000 | ||
225 | |||
226 | #define MARK_CHAIN_BD (BD_CHAIN|BD_EOT|BD_SOT) | ||
227 | |||
228 | /* Control transfer BD specific fields */ | ||
229 | #define BD_DIR_IN (1 << 25) | ||
230 | |||
231 | #define BDC_PTC_MASK 0xf0000000 | ||
232 | |||
233 | /* status report defines */ | ||
234 | #define SR_XSF 0 | ||
235 | #define SR_USPC 4 | ||
236 | #define SR_BD_LEN(p) (p & 0xffffff) | ||
237 | |||
238 | #define XSF_SUCC 0x1 | ||
239 | #define XSF_SHORT 0x3 | ||
240 | #define XSF_BABB 0x4 | ||
241 | #define XSF_SETUP_RECV 0x6 | ||
242 | #define XSF_DATA_START 0x7 | ||
243 | #define XSF_STATUS_START 0x8 | ||
244 | |||
245 | #define XSF_STS(p) (((p) >> 28) & 0xf) | ||
246 | |||
247 | /* Transfer BD fields */ | ||
248 | #define BD_LEN(p) ((p) & 0x1ffff) | ||
249 | #define BD_LTF (1 << 25) | ||
250 | #define BD_TYPE_DS 0x1 | ||
251 | #define BD_TYPE_SS 0x2 | ||
252 | |||
253 | #define BDC_EP_ENABLED (1 << 0) | ||
254 | #define BDC_EP_STALL (1 << 1) | ||
255 | #define BDC_EP_STOP (1 << 2) | ||
256 | |||
257 | /* One BD can transfer max 65536 bytes */ | ||
258 | #define BD_MAX_BUFF_SIZE (1 << 16) | ||
259 | /* Maximum bytes in one XFR, Refer to BDC spec */ | ||
260 | #define MAX_XFR_LEN 16777215 | ||
261 | |||
262 | /* defines for Force Header command */ | ||
263 | #define DEV_NOTF_TYPE 6 | ||
264 | #define FWK_SUBTYPE 1 | ||
265 | #define TRA_PACKET 4 | ||
266 | |||
267 | #define to_bdc_ep(e) container_of(e, struct bdc_ep, usb_ep) | ||
268 | #define to_bdc_req(r) container_of(r, struct bdc_req, usb_req) | ||
269 | #define gadget_to_bdc(g) container_of(g, struct bdc, gadget) | ||
270 | |||
271 | /* FUNCTION WAKE DEV NOTIFICATION interval, USB3 spec table 8.13 */ | ||
272 | #define BDC_TNOTIFY 2500 /*in ms*/ | ||
273 | /* Devstatus bitfields */ | ||
274 | #define REMOTE_WAKEUP_ISSUED (1 << 16) | ||
275 | #define DEVICE_SUSPENDED (1 << 17) | ||
276 | #define FUNC_WAKE_ISSUED (1 << 18) | ||
277 | #define REMOTE_WAKE_ENABLE (1 << USB_DEVICE_REMOTE_WAKEUP) | ||
278 | |||
279 | /* On disconnect, preserve these bits and clear rest */ | ||
280 | #define DEVSTATUS_CLEAR (1 << USB_DEVICE_SELF_POWERED) | ||
281 | /* Hardware and software Data structures */ | ||
282 | |||
283 | /* Endpoint bd: buffer descriptor */ | ||
284 | struct bdc_bd { | ||
285 | __le32 offset[4]; | ||
286 | }; | ||
287 | |||
288 | /* Status report in Status report ring(srr) */ | ||
289 | struct bdc_sr { | ||
290 | __le32 offset[4]; | ||
291 | }; | ||
292 | |||
293 | /* bd_table: contigous bd's in a table */ | ||
294 | struct bd_table { | ||
295 | struct bdc_bd *start_bd; | ||
296 | /* dma address of start bd of table*/ | ||
297 | dma_addr_t dma; | ||
298 | }; | ||
299 | |||
300 | /* | ||
301 | * Each endpoint has a bdl(buffer descriptor list), bdl consists of 1 or more bd | ||
302 | * table's chained to each other through a chain bd, every table has equal | ||
303 | * number of bds. the software uses bdi(bd index) to refer to particular bd in | ||
304 | * the list. | ||
305 | */ | ||
306 | struct bd_list { | ||
307 | /* Array of bd table pointers*/ | ||
308 | struct bd_table **bd_table_array; | ||
309 | /* How many tables chained to each other */ | ||
310 | int num_tabs; | ||
311 | /* Max_bdi = num_tabs * num_bds_table - 1 */ | ||
312 | int max_bdi; | ||
313 | /* current enq bdi from sw point of view */ | ||
314 | int eqp_bdi; | ||
315 | /* current deq bdi from sw point of view */ | ||
316 | int hwd_bdi; | ||
317 | /* numbers of bds per table */ | ||
318 | int num_bds_table; | ||
319 | }; | ||
320 | |||
321 | struct bdc_req; | ||
322 | |||
323 | /* Representation of a transfer, one transfer can have multiple bd's */ | ||
324 | struct bd_transfer { | ||
325 | struct bdc_req *req; | ||
326 | /* start bd index */ | ||
327 | int start_bdi; | ||
328 | /* this will be the next hw dqp when this transfer completes */ | ||
329 | int next_hwd_bdi; | ||
330 | /* number of bds in this transfer */ | ||
331 | int num_bds; | ||
332 | }; | ||
333 | |||
334 | /* | ||
335 | * Representation of a gadget request, every gadget request is contained | ||
336 | * by 1 bd_transfer. | ||
337 | */ | ||
338 | struct bdc_req { | ||
339 | struct usb_request usb_req; | ||
340 | struct list_head queue; | ||
341 | struct bdc_ep *ep; | ||
342 | /* only one Transfer per request */ | ||
343 | struct bd_transfer bd_xfr; | ||
344 | int epnum; | ||
345 | }; | ||
346 | |||
347 | /* scratchpad buffer needed by bdc hardware */ | ||
348 | struct bdc_scratchpad { | ||
349 | dma_addr_t sp_dma; | ||
350 | void *buff; | ||
351 | u32 size; | ||
352 | }; | ||
353 | |||
354 | /* endpoint representation */ | ||
355 | struct bdc_ep { | ||
356 | struct usb_ep usb_ep; | ||
357 | struct list_head queue; | ||
358 | struct bdc *bdc; | ||
359 | u8 ep_type; | ||
360 | u8 dir; | ||
361 | u8 ep_num; | ||
362 | const struct usb_ss_ep_comp_descriptor *comp_desc; | ||
363 | const struct usb_endpoint_descriptor *desc; | ||
364 | unsigned int flags; | ||
365 | char name[20]; | ||
366 | /* endpoint bd list*/ | ||
367 | struct bd_list bd_list; | ||
368 | /* | ||
369 | * HW generates extra event for multi bd tranfers, this flag helps in | ||
370 | * ignoring the extra event | ||
371 | */ | ||
372 | bool ignore_next_sr; | ||
373 | }; | ||
374 | |||
375 | /* bdc cmmand parameter structure */ | ||
376 | struct bdc_cmd_params { | ||
377 | u32 param2; | ||
378 | u32 param1; | ||
379 | u32 param0; | ||
380 | }; | ||
381 | |||
382 | /* status report ring(srr), currently one srr is supported for entire system */ | ||
383 | struct srr { | ||
384 | struct bdc_sr *sr_bds; | ||
385 | u16 eqp_index; | ||
386 | u16 dqp_index; | ||
387 | dma_addr_t dma_addr; | ||
388 | }; | ||
389 | |||
390 | /* EP0 states */ | ||
391 | enum bdc_ep0_state { | ||
392 | WAIT_FOR_SETUP = 0, | ||
393 | WAIT_FOR_DATA_START, | ||
394 | WAIT_FOR_DATA_XMIT, | ||
395 | WAIT_FOR_STATUS_START, | ||
396 | WAIT_FOR_STATUS_XMIT, | ||
397 | STATUS_PENDING | ||
398 | }; | ||
399 | |||
400 | /* Link states */ | ||
401 | enum bdc_link_state { | ||
402 | BDC_LINK_STATE_U0 = 0x00, | ||
403 | BDC_LINK_STATE_U3 = 0x03, | ||
404 | BDC_LINK_STATE_RX_DET = 0x05, | ||
405 | BDC_LINK_STATE_RESUME = 0x0f | ||
406 | }; | ||
407 | |||
408 | /* representation of bdc */ | ||
409 | struct bdc { | ||
410 | struct usb_gadget gadget; | ||
411 | struct usb_gadget_driver *gadget_driver; | ||
412 | struct device *dev; | ||
413 | /* device lock */ | ||
414 | spinlock_t lock; | ||
415 | |||
416 | /* num of endpoints for a particular instantiation of IP */ | ||
417 | unsigned int num_eps; | ||
418 | /* | ||
419 | * Array of ep's, it uses the same index covention as bdc hw i.e. | ||
420 | * 1 for ep0, 2 for 1out,3 for 1in .... | ||
421 | */ | ||
422 | struct bdc_ep **bdc_ep_array; | ||
423 | void __iomem *regs; | ||
424 | struct bdc_scratchpad scratchpad; | ||
425 | u32 sp_buff_size; | ||
426 | /* current driver supports 1 status ring */ | ||
427 | struct srr srr; | ||
428 | /* Last received setup packet */ | ||
429 | struct usb_ctrlrequest setup_pkt; | ||
430 | struct bdc_req ep0_req; | ||
431 | struct bdc_req status_req; | ||
432 | enum bdc_ep0_state ep0_state; | ||
433 | bool delayed_status; | ||
434 | bool zlp_needed; | ||
435 | bool reinit; | ||
436 | bool pullup; | ||
437 | /* Bits 0-15 are standard and 16-31 for proprietary information */ | ||
438 | u32 devstatus; | ||
439 | int irq; | ||
440 | void *mem; | ||
441 | u32 dev_addr; | ||
442 | /* DMA pools */ | ||
443 | struct dma_pool *bd_table_pool; | ||
444 | u8 test_mode; | ||
445 | /* array of callbacks for various status report handlers */ | ||
446 | void (*sr_handler[2])(struct bdc *, struct bdc_sr *); | ||
447 | /* ep0 callback handlers */ | ||
448 | void (*sr_xsf_ep0[3])(struct bdc *, struct bdc_sr *); | ||
449 | /* ep0 response buffer for ch9 requests like GET_STATUS and SET_SEL */ | ||
450 | unsigned char ep0_response_buff[EP0_RESPONSE_BUFF]; | ||
451 | /* | ||
452 | * Timer to check if host resumed transfer after bdc sent Func wake | ||
453 | * notification packet after a remote wakeup. if not, then resend the | ||
454 | * Func Wake packet every 2.5 secs. Refer to USB3 spec section 8.5.6.4 | ||
455 | */ | ||
456 | struct delayed_work func_wake_notify; | ||
457 | }; | ||
458 | |||
459 | static inline u32 bdc_readl(void __iomem *base, u32 offset) | ||
460 | { | ||
461 | return readl(base + offset); | ||
462 | } | ||
463 | |||
464 | static inline void bdc_writel(void __iomem *base, u32 offset, u32 value) | ||
465 | { | ||
466 | writel(value, base + offset); | ||
467 | } | ||
468 | |||
469 | /* Buffer descriptor list operations */ | ||
470 | void bdc_notify_xfr(struct bdc *, u32); | ||
471 | void bdc_softconn(struct bdc *); | ||
472 | void bdc_softdisconn(struct bdc *); | ||
473 | int bdc_run(struct bdc *); | ||
474 | int bdc_stop(struct bdc *); | ||
475 | int bdc_reset(struct bdc *); | ||
476 | int bdc_udc_init(struct bdc *); | ||
477 | void bdc_udc_exit(struct bdc *); | ||
478 | int bdc_reinit(struct bdc *); | ||
479 | |||
480 | /* Status report handlers */ | ||
481 | /* Upstream port status change sr */ | ||
482 | void bdc_sr_uspc(struct bdc *, struct bdc_sr *); | ||
483 | /* transfer sr */ | ||
484 | void bdc_sr_xsf(struct bdc *, struct bdc_sr *); | ||
485 | /* EP0 XSF handlers */ | ||
486 | void bdc_xsf_ep0_setup_recv(struct bdc *, struct bdc_sr *); | ||
487 | void bdc_xsf_ep0_data_start(struct bdc *, struct bdc_sr *); | ||
488 | void bdc_xsf_ep0_status_start(struct bdc *, struct bdc_sr *); | ||
489 | |||
490 | #endif /* __LINUX_BDC_H__ */ | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc_cmd.c b/drivers/usb/gadget/udc/bdc/bdc_cmd.c new file mode 100644 index 000000000000..6a4155c4bd86 --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/bdc_cmd.c | |||
@@ -0,0 +1,376 @@ | |||
1 | /* | ||
2 | * bdc_cmd.c - BRCM BDC USB3.0 device controller | ||
3 | * | ||
4 | * Copyright (C) 2014 Broadcom Corporation | ||
5 | * | ||
6 | * Author: Ashwini Pahuja | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/scatterlist.h> | ||
15 | #include <linux/slab.h> | ||
16 | |||
17 | #include "bdc.h" | ||
18 | #include "bdc_cmd.h" | ||
19 | #include "bdc_dbg.h" | ||
20 | |||
21 | /* Issues a cmd to cmd processor and waits for cmd completion */ | ||
22 | static int bdc_issue_cmd(struct bdc *bdc, u32 cmd_sc, u32 param0, | ||
23 | u32 param1, u32 param2) | ||
24 | { | ||
25 | u32 timeout = BDC_CMD_TIMEOUT; | ||
26 | u32 cmd_status; | ||
27 | u32 temp; | ||
28 | |||
29 | bdc_writel(bdc->regs, BDC_CMDPAR0, param0); | ||
30 | bdc_writel(bdc->regs, BDC_CMDPAR1, param1); | ||
31 | bdc_writel(bdc->regs, BDC_CMDPAR2, param2); | ||
32 | |||
33 | /* Issue the cmd */ | ||
34 | /* Make sure the cmd params are written before asking HW to exec cmd */ | ||
35 | wmb(); | ||
36 | bdc_writel(bdc->regs, BDC_CMDSC, cmd_sc | BDC_CMD_CWS | BDC_CMD_SRD); | ||
37 | do { | ||
38 | temp = bdc_readl(bdc->regs, BDC_CMDSC); | ||
39 | dev_dbg_ratelimited(bdc->dev, "cmdsc=%x", temp); | ||
40 | cmd_status = BDC_CMD_CST(temp); | ||
41 | if (cmd_status != BDC_CMDS_BUSY) { | ||
42 | dev_dbg(bdc->dev, | ||
43 | "command completed cmd_sts:%x\n", cmd_status); | ||
44 | return cmd_status; | ||
45 | } | ||
46 | udelay(1); | ||
47 | } while (timeout--); | ||
48 | |||
49 | dev_err(bdc->dev, | ||
50 | "command operation timedout cmd_status=%d\n", cmd_status); | ||
51 | |||
52 | return cmd_status; | ||
53 | } | ||
54 | |||
55 | /* Submits cmd and analyze the return value of bdc_issue_cmd */ | ||
56 | static int bdc_submit_cmd(struct bdc *bdc, u32 cmd_sc, | ||
57 | u32 param0, u32 param1, u32 param2) | ||
58 | { | ||
59 | u32 temp, cmd_status; | ||
60 | int reset_bdc = 0; | ||
61 | int ret; | ||
62 | |||
63 | temp = bdc_readl(bdc->regs, BDC_CMDSC); | ||
64 | dev_dbg(bdc->dev, | ||
65 | "%s:CMDSC:%08x cmdsc:%08x param0=%08x param1=%08x param2=%08x\n", | ||
66 | __func__, temp, cmd_sc, param0, param1, param2); | ||
67 | |||
68 | cmd_status = BDC_CMD_CST(temp); | ||
69 | if (cmd_status == BDC_CMDS_BUSY) { | ||
70 | dev_err(bdc->dev, "command processor busy: %x\n", cmd_status); | ||
71 | return -EBUSY; | ||
72 | } | ||
73 | ret = bdc_issue_cmd(bdc, cmd_sc, param0, param1, param2); | ||
74 | switch (ret) { | ||
75 | case BDC_CMDS_SUCC: | ||
76 | dev_dbg(bdc->dev, "command completed successfully\n"); | ||
77 | ret = 0; | ||
78 | break; | ||
79 | |||
80 | case BDC_CMDS_PARA: | ||
81 | dev_err(bdc->dev, "command parameter error\n"); | ||
82 | ret = -EINVAL; | ||
83 | break; | ||
84 | |||
85 | case BDC_CMDS_STAT: | ||
86 | dev_err(bdc->dev, "Invalid device/ep state\n"); | ||
87 | ret = -EINVAL; | ||
88 | break; | ||
89 | |||
90 | case BDC_CMDS_FAIL: | ||
91 | dev_err(bdc->dev, "Command failed?\n"); | ||
92 | ret = -EAGAIN; | ||
93 | break; | ||
94 | |||
95 | case BDC_CMDS_INTL: | ||
96 | dev_err(bdc->dev, "BDC Internal error\n"); | ||
97 | reset_bdc = 1; | ||
98 | ret = -ECONNRESET; | ||
99 | break; | ||
100 | |||
101 | case BDC_CMDS_BUSY: | ||
102 | dev_err(bdc->dev, | ||
103 | "command timedout waited for %dusec\n", | ||
104 | BDC_CMD_TIMEOUT); | ||
105 | reset_bdc = 1; | ||
106 | ret = -ECONNRESET; | ||
107 | break; | ||
108 | default: | ||
109 | dev_dbg(bdc->dev, "Unknown command completion code:%x\n", ret); | ||
110 | } | ||
111 | |||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | /* Deconfigure the endpoint from HW */ | ||
116 | int bdc_dconfig_ep(struct bdc *bdc, struct bdc_ep *ep) | ||
117 | { | ||
118 | u32 cmd_sc; | ||
119 | |||
120 | cmd_sc = BDC_SUB_CMD_DRP_EP|BDC_CMD_EPN(ep->ep_num)|BDC_CMD_EPC; | ||
121 | dev_dbg(bdc->dev, "%s ep->ep_num =%d cmd_sc=%x\n", __func__, | ||
122 | ep->ep_num, cmd_sc); | ||
123 | |||
124 | return bdc_submit_cmd(bdc, cmd_sc, 0, 0, 0); | ||
125 | } | ||
126 | |||
127 | /* Reinitalize the bdlist after config ep command */ | ||
128 | static void ep_bd_list_reinit(struct bdc_ep *ep) | ||
129 | { | ||
130 | struct bdc *bdc = ep->bdc; | ||
131 | struct bdc_bd *bd; | ||
132 | |||
133 | ep->bd_list.eqp_bdi = 0; | ||
134 | ep->bd_list.hwd_bdi = 0; | ||
135 | bd = ep->bd_list.bd_table_array[0]->start_bd; | ||
136 | dev_dbg(bdc->dev, "%s ep:%p bd:%p\n", __func__, ep, bd); | ||
137 | memset(bd, 0, sizeof(struct bdc_bd)); | ||
138 | bd->offset[3] |= cpu_to_le32(BD_SBF); | ||
139 | } | ||
140 | |||
141 | /* Configure an endpoint */ | ||
142 | int bdc_config_ep(struct bdc *bdc, struct bdc_ep *ep) | ||
143 | { | ||
144 | const struct usb_ss_ep_comp_descriptor *comp_desc; | ||
145 | const struct usb_endpoint_descriptor *desc; | ||
146 | u32 param0, param1, param2, cmd_sc; | ||
147 | u32 mps, mbs, mul, si; | ||
148 | int ret; | ||
149 | |||
150 | desc = ep->desc; | ||
151 | comp_desc = ep->comp_desc; | ||
152 | cmd_sc = mul = mbs = param2 = 0; | ||
153 | param0 = lower_32_bits(ep->bd_list.bd_table_array[0]->dma); | ||
154 | param1 = upper_32_bits(ep->bd_list.bd_table_array[0]->dma); | ||
155 | cpu_to_le32s(¶m0); | ||
156 | cpu_to_le32s(¶m1); | ||
157 | |||
158 | dev_dbg(bdc->dev, "%s: param0=%08x param1=%08x", | ||
159 | __func__, param0, param1); | ||
160 | si = desc->bInterval; | ||
161 | si = clamp_val(si, 1, 16) - 1; | ||
162 | |||
163 | mps = usb_endpoint_maxp(desc); | ||
164 | mps &= 0x7ff; | ||
165 | param2 |= mps << MP_SHIFT; | ||
166 | param2 |= usb_endpoint_type(desc) << EPT_SHIFT; | ||
167 | |||
168 | switch (bdc->gadget.speed) { | ||
169 | case USB_SPEED_SUPER: | ||
170 | if (usb_endpoint_xfer_int(desc) || | ||
171 | usb_endpoint_xfer_isoc(desc)) { | ||
172 | param2 |= si; | ||
173 | if (usb_endpoint_xfer_isoc(desc) && comp_desc) | ||
174 | mul = comp_desc->bmAttributes; | ||
175 | |||
176 | } | ||
177 | param2 |= mul << EPM_SHIFT; | ||
178 | if (comp_desc) | ||
179 | mbs = comp_desc->bMaxBurst; | ||
180 | param2 |= mbs << MB_SHIFT; | ||
181 | break; | ||
182 | |||
183 | case USB_SPEED_HIGH: | ||
184 | if (usb_endpoint_xfer_isoc(desc) || | ||
185 | usb_endpoint_xfer_int(desc)) { | ||
186 | param2 |= si; | ||
187 | |||
188 | mbs = (usb_endpoint_maxp(desc) & 0x1800) >> 11; | ||
189 | param2 |= mbs << MB_SHIFT; | ||
190 | } | ||
191 | break; | ||
192 | |||
193 | case USB_SPEED_FULL: | ||
194 | case USB_SPEED_LOW: | ||
195 | /* the hardware accepts SI in 125usec range */ | ||
196 | if (usb_endpoint_xfer_isoc(desc)) | ||
197 | si += 3; | ||
198 | |||
199 | /* | ||
200 | * FS Int endpoints can have si of 1-255ms but the controller | ||
201 | * accepts 2^bInterval*125usec, so convert ms to nearest power | ||
202 | * of 2 | ||
203 | */ | ||
204 | if (usb_endpoint_xfer_int(desc)) | ||
205 | si = fls(desc->bInterval * 8) - 1; | ||
206 | |||
207 | param2 |= si; | ||
208 | break; | ||
209 | default: | ||
210 | dev_err(bdc->dev, "UNKNOWN speed ERR\n"); | ||
211 | return -EINVAL; | ||
212 | } | ||
213 | |||
214 | cmd_sc |= BDC_CMD_EPC|BDC_CMD_EPN(ep->ep_num)|BDC_SUB_CMD_ADD_EP; | ||
215 | |||
216 | dev_dbg(bdc->dev, "cmd_sc=%x param2=%08x\n", cmd_sc, param2); | ||
217 | ret = bdc_submit_cmd(bdc, cmd_sc, param0, param1, param2); | ||
218 | if (ret) { | ||
219 | dev_err(bdc->dev, "command failed :%x\n", ret); | ||
220 | return ret; | ||
221 | } | ||
222 | ep_bd_list_reinit(ep); | ||
223 | |||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | /* | ||
228 | * Change the HW deq pointer, if this command is successful, HW will start | ||
229 | * fetching the next bd from address dma_addr. | ||
230 | */ | ||
231 | int bdc_ep_bla(struct bdc *bdc, struct bdc_ep *ep, dma_addr_t dma_addr) | ||
232 | { | ||
233 | u32 param0, param1; | ||
234 | u32 cmd_sc = 0; | ||
235 | |||
236 | dev_dbg(bdc->dev, "%s: add=%08llx\n", __func__, | ||
237 | (unsigned long long)(dma_addr)); | ||
238 | param0 = lower_32_bits(dma_addr); | ||
239 | param1 = upper_32_bits(dma_addr); | ||
240 | cpu_to_le32s(¶m0); | ||
241 | cpu_to_le32s(¶m1); | ||
242 | |||
243 | cmd_sc |= BDC_CMD_EPN(ep->ep_num)|BDC_CMD_BLA; | ||
244 | dev_dbg(bdc->dev, "cmd_sc=%x\n", cmd_sc); | ||
245 | |||
246 | return bdc_submit_cmd(bdc, cmd_sc, param0, param1, 0); | ||
247 | } | ||
248 | |||
249 | /* Set the address sent bu Host in SET_ADD request */ | ||
250 | int bdc_address_device(struct bdc *bdc, u32 add) | ||
251 | { | ||
252 | u32 cmd_sc = 0; | ||
253 | u32 param2; | ||
254 | |||
255 | dev_dbg(bdc->dev, "%s: add=%d\n", __func__, add); | ||
256 | cmd_sc |= BDC_SUB_CMD_ADD|BDC_CMD_DVC; | ||
257 | param2 = add & 0x7f; | ||
258 | |||
259 | return bdc_submit_cmd(bdc, cmd_sc, 0, 0, param2); | ||
260 | } | ||
261 | |||
262 | /* Send a Function Wake notification packet using FH command */ | ||
263 | int bdc_function_wake_fh(struct bdc *bdc, u8 intf) | ||
264 | { | ||
265 | u32 param0, param1; | ||
266 | u32 cmd_sc = 0; | ||
267 | |||
268 | param0 = param1 = 0; | ||
269 | dev_dbg(bdc->dev, "%s intf=%d\n", __func__, intf); | ||
270 | cmd_sc |= BDC_CMD_FH; | ||
271 | param0 |= TRA_PACKET; | ||
272 | param0 |= (bdc->dev_addr << 25); | ||
273 | param1 |= DEV_NOTF_TYPE; | ||
274 | param1 |= (FWK_SUBTYPE<<4); | ||
275 | dev_dbg(bdc->dev, "param0=%08x param1=%08x\n", param0, param1); | ||
276 | |||
277 | return bdc_submit_cmd(bdc, cmd_sc, param0, param1, 0); | ||
278 | } | ||
279 | |||
280 | /* Send a Function Wake notification packet using DNC command */ | ||
281 | int bdc_function_wake(struct bdc *bdc, u8 intf) | ||
282 | { | ||
283 | u32 cmd_sc = 0; | ||
284 | u32 param2 = 0; | ||
285 | |||
286 | dev_dbg(bdc->dev, "%s intf=%d", __func__, intf); | ||
287 | param2 |= intf; | ||
288 | cmd_sc |= BDC_SUB_CMD_FWK|BDC_CMD_DNC; | ||
289 | |||
290 | return bdc_submit_cmd(bdc, cmd_sc, 0, 0, param2); | ||
291 | } | ||
292 | |||
293 | /* Stall the endpoint */ | ||
294 | int bdc_ep_set_stall(struct bdc *bdc, int epnum) | ||
295 | { | ||
296 | u32 cmd_sc = 0; | ||
297 | |||
298 | dev_dbg(bdc->dev, "%s epnum=%d\n", __func__, epnum); | ||
299 | /* issue a stall endpoint command */ | ||
300 | cmd_sc |= BDC_SUB_CMD_EP_STL | BDC_CMD_EPN(epnum) | BDC_CMD_EPO; | ||
301 | |||
302 | return bdc_submit_cmd(bdc, cmd_sc, 0, 0, 0); | ||
303 | } | ||
304 | |||
305 | /* resets the endpoint, called when host sends CLEAR_FEATURE(HALT) */ | ||
306 | int bdc_ep_clear_stall(struct bdc *bdc, int epnum) | ||
307 | { | ||
308 | struct bdc_ep *ep; | ||
309 | u32 cmd_sc = 0; | ||
310 | int ret; | ||
311 | |||
312 | dev_dbg(bdc->dev, "%s: epnum=%d\n", __func__, epnum); | ||
313 | ep = bdc->bdc_ep_array[epnum]; | ||
314 | /* | ||
315 | * If we are not in stalled then stall Endpoint and issue clear stall, | ||
316 | * his will reset the seq number for non EP0. | ||
317 | */ | ||
318 | if (epnum != 1) { | ||
319 | /* if the endpoint it not stallled */ | ||
320 | if (!(ep->flags & BDC_EP_STALL)) { | ||
321 | ret = bdc_ep_set_stall(bdc, epnum); | ||
322 | if (ret) | ||
323 | return ret; | ||
324 | } | ||
325 | } | ||
326 | /* Preserve the seq number for ep0 only */ | ||
327 | if (epnum != 1) | ||
328 | cmd_sc |= BDC_CMD_EPO_RST_SN; | ||
329 | |||
330 | /* issue a reset endpoint command */ | ||
331 | cmd_sc |= BDC_SUB_CMD_EP_RST | BDC_CMD_EPN(epnum) | BDC_CMD_EPO; | ||
332 | |||
333 | ret = bdc_submit_cmd(bdc, cmd_sc, 0, 0, 0); | ||
334 | if (ret) { | ||
335 | dev_err(bdc->dev, "command failed:%x\n", ret); | ||
336 | return ret; | ||
337 | } | ||
338 | bdc_notify_xfr(bdc, epnum); | ||
339 | |||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | /* Stop the endpoint, called when software wants to dequeue some request */ | ||
344 | int bdc_stop_ep(struct bdc *bdc, int epnum) | ||
345 | { | ||
346 | struct bdc_ep *ep; | ||
347 | u32 cmd_sc = 0; | ||
348 | int ret; | ||
349 | |||
350 | ep = bdc->bdc_ep_array[epnum]; | ||
351 | dev_dbg(bdc->dev, "%s: ep:%s ep->flags:%08x\n", __func__, | ||
352 | ep->name, ep->flags); | ||
353 | /* Endpoint has to be in running state to execute stop ep command */ | ||
354 | if (!(ep->flags & BDC_EP_ENABLED)) { | ||
355 | dev_err(bdc->dev, "stop endpoint called for disabled ep\n"); | ||
356 | return -EINVAL; | ||
357 | } | ||
358 | if ((ep->flags & BDC_EP_STALL) || (ep->flags & BDC_EP_STOP)) | ||
359 | return 0; | ||
360 | |||
361 | /* issue a stop endpoint command */ | ||
362 | cmd_sc |= BDC_CMD_EP0_XSD | BDC_SUB_CMD_EP_STP | ||
363 | | BDC_CMD_EPN(epnum) | BDC_CMD_EPO; | ||
364 | |||
365 | ret = bdc_submit_cmd(bdc, cmd_sc, 0, 0, 0); | ||
366 | if (ret) { | ||
367 | dev_err(bdc->dev, | ||
368 | "stop endpoint command didn't complete:%d ep:%s\n", | ||
369 | ret, ep->name); | ||
370 | return ret; | ||
371 | } | ||
372 | ep->flags |= BDC_EP_STOP; | ||
373 | bdc_dump_epsts(bdc); | ||
374 | |||
375 | return ret; | ||
376 | } | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc_cmd.h b/drivers/usb/gadget/udc/bdc/bdc_cmd.h new file mode 100644 index 000000000000..61d0e3bf9853 --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/bdc_cmd.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * bdc_cmd.h - header for the BDC debug functions | ||
3 | * | ||
4 | * Copyright (C) 2014 Broadcom Corporation | ||
5 | * | ||
6 | * Author: Ashwini Pahuja | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | #ifndef __LINUX_BDC_CMD_H__ | ||
15 | #define __LINUX_BDC_CMD_H__ | ||
16 | |||
17 | /* Command operations */ | ||
18 | int bdc_address_device(struct bdc *, u32); | ||
19 | int bdc_config_ep(struct bdc *, struct bdc_ep *); | ||
20 | int bdc_dconfig_ep(struct bdc *, struct bdc_ep *); | ||
21 | int bdc_stop_ep(struct bdc *, int); | ||
22 | int bdc_ep_set_stall(struct bdc *, int); | ||
23 | int bdc_ep_clear_stall(struct bdc *, int); | ||
24 | int bdc_ep_set_halt(struct bdc_ep *, u32 , int); | ||
25 | int bdc_ep_bla(struct bdc *, struct bdc_ep *, dma_addr_t); | ||
26 | int bdc_function_wake(struct bdc*, u8); | ||
27 | int bdc_function_wake_fh(struct bdc*, u8); | ||
28 | |||
29 | #endif /* __LINUX_BDC_CMD_H__ */ | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c new file mode 100644 index 000000000000..c6dfef8c7bbc --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/bdc_core.c | |||
@@ -0,0 +1,533 @@ | |||
1 | /* | ||
2 | * bdc_core.c - BRCM BDC USB3.0 device controller core operations | ||
3 | * | ||
4 | * Copyright (C) 2014 Broadcom Corporation | ||
5 | * | ||
6 | * Author: Ashwini Pahuja | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/ioport.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/list.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/dmapool.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/usb/ch9.h> | ||
29 | #include <linux/usb/gadget.h> | ||
30 | |||
31 | #include "bdc.h" | ||
32 | #include "bdc_dbg.h" | ||
33 | |||
34 | /* Poll till controller status is not OIP */ | ||
35 | static int poll_oip(struct bdc *bdc, int usec) | ||
36 | { | ||
37 | u32 status; | ||
38 | /* Poll till STS!= OIP */ | ||
39 | while (usec) { | ||
40 | status = bdc_readl(bdc->regs, BDC_BDCSC); | ||
41 | if (BDC_CSTS(status) != BDC_OIP) { | ||
42 | dev_dbg(bdc->dev, | ||
43 | "poll_oip complete status=%d", | ||
44 | BDC_CSTS(status)); | ||
45 | return 0; | ||
46 | } | ||
47 | udelay(10); | ||
48 | usec -= 10; | ||
49 | } | ||
50 | dev_err(bdc->dev, "Err: operation timedout BDCSC: 0x%08x\n", status); | ||
51 | |||
52 | return -ETIMEDOUT; | ||
53 | } | ||
54 | |||
55 | /* Stop the BDC controller */ | ||
56 | int bdc_stop(struct bdc *bdc) | ||
57 | { | ||
58 | int ret; | ||
59 | u32 temp; | ||
60 | |||
61 | dev_dbg(bdc->dev, "%s ()\n\n", __func__); | ||
62 | temp = bdc_readl(bdc->regs, BDC_BDCSC); | ||
63 | /* Check if BDC is already halted */ | ||
64 | if (BDC_CSTS(temp) == BDC_HLT) { | ||
65 | dev_vdbg(bdc->dev, "BDC already halted\n"); | ||
66 | return 0; | ||
67 | } | ||
68 | temp &= ~BDC_COP_MASK; | ||
69 | temp |= BDC_COS|BDC_COP_STP; | ||
70 | bdc_writel(bdc->regs, BDC_BDCSC, temp); | ||
71 | |||
72 | ret = poll_oip(bdc, BDC_COP_TIMEOUT); | ||
73 | if (ret) | ||
74 | dev_err(bdc->dev, "bdc stop operation failed"); | ||
75 | |||
76 | return ret; | ||
77 | } | ||
78 | |||
79 | /* Issue a reset to BDC controller */ | ||
80 | int bdc_reset(struct bdc *bdc) | ||
81 | { | ||
82 | u32 temp; | ||
83 | int ret; | ||
84 | |||
85 | dev_dbg(bdc->dev, "%s ()\n", __func__); | ||
86 | /* First halt the controller */ | ||
87 | ret = bdc_stop(bdc); | ||
88 | if (ret) | ||
89 | return ret; | ||
90 | |||
91 | temp = bdc_readl(bdc->regs, BDC_BDCSC); | ||
92 | temp &= ~BDC_COP_MASK; | ||
93 | temp |= BDC_COS|BDC_COP_RST; | ||
94 | bdc_writel(bdc->regs, BDC_BDCSC, temp); | ||
95 | ret = poll_oip(bdc, BDC_COP_TIMEOUT); | ||
96 | if (ret) | ||
97 | dev_err(bdc->dev, "bdc reset operation failed"); | ||
98 | |||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | /* Run the BDC controller */ | ||
103 | int bdc_run(struct bdc *bdc) | ||
104 | { | ||
105 | u32 temp; | ||
106 | int ret; | ||
107 | |||
108 | dev_dbg(bdc->dev, "%s ()\n", __func__); | ||
109 | temp = bdc_readl(bdc->regs, BDC_BDCSC); | ||
110 | /* if BDC is already in running state then do not do anything */ | ||
111 | if (BDC_CSTS(temp) == BDC_NOR) { | ||
112 | dev_warn(bdc->dev, "bdc is already in running state\n"); | ||
113 | return 0; | ||
114 | } | ||
115 | temp &= ~BDC_COP_MASK; | ||
116 | temp |= BDC_COP_RUN; | ||
117 | temp |= BDC_COS; | ||
118 | bdc_writel(bdc->regs, BDC_BDCSC, temp); | ||
119 | ret = poll_oip(bdc, BDC_COP_TIMEOUT); | ||
120 | if (ret) { | ||
121 | dev_err(bdc->dev, "bdc run operation failed:%d", ret); | ||
122 | return ret; | ||
123 | } | ||
124 | temp = bdc_readl(bdc->regs, BDC_BDCSC); | ||
125 | if (BDC_CSTS(temp) != BDC_NOR) { | ||
126 | dev_err(bdc->dev, "bdc not in normal mode after RUN op :%d\n", | ||
127 | BDC_CSTS(temp)); | ||
128 | return -ESHUTDOWN; | ||
129 | } | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Present the termination to the host, typically called from upstream port | ||
136 | * event with Vbus present =1 | ||
137 | */ | ||
138 | void bdc_softconn(struct bdc *bdc) | ||
139 | { | ||
140 | u32 uspc; | ||
141 | |||
142 | uspc = bdc_readl(bdc->regs, BDC_USPC); | ||
143 | uspc &= ~BDC_PST_MASK; | ||
144 | uspc |= BDC_LINK_STATE_RX_DET; | ||
145 | uspc |= BDC_SWS; | ||
146 | dev_dbg(bdc->dev, "%s () uspc=%08x\n", __func__, uspc); | ||
147 | bdc_writel(bdc->regs, BDC_USPC, uspc); | ||
148 | } | ||
149 | |||
150 | /* Remove the termination */ | ||
151 | void bdc_softdisconn(struct bdc *bdc) | ||
152 | { | ||
153 | u32 uspc; | ||
154 | |||
155 | uspc = bdc_readl(bdc->regs, BDC_USPC); | ||
156 | uspc |= BDC_SDC; | ||
157 | uspc &= ~BDC_SCN; | ||
158 | dev_dbg(bdc->dev, "%s () uspc=%x\n", __func__, uspc); | ||
159 | bdc_writel(bdc->regs, BDC_USPC, uspc); | ||
160 | } | ||
161 | |||
162 | /* Set up the scratchpad buffer array and scratchpad buffers, if needed. */ | ||
163 | static int scratchpad_setup(struct bdc *bdc) | ||
164 | { | ||
165 | int sp_buff_size; | ||
166 | u32 low32; | ||
167 | u32 upp32; | ||
168 | |||
169 | sp_buff_size = BDC_SPB(bdc_readl(bdc->regs, BDC_BDCCFG0)); | ||
170 | dev_dbg(bdc->dev, "%s() sp_buff_size=%d\n", __func__, sp_buff_size); | ||
171 | if (!sp_buff_size) { | ||
172 | dev_dbg(bdc->dev, "Scratchpad buffer not needed\n"); | ||
173 | return 0; | ||
174 | } | ||
175 | /* Refer to BDC spec, Table 4 for description of SPB */ | ||
176 | sp_buff_size = 1 << (sp_buff_size + 5); | ||
177 | dev_dbg(bdc->dev, "Allocating %d bytes for scratchpad\n", sp_buff_size); | ||
178 | bdc->scratchpad.buff = dma_zalloc_coherent(bdc->dev, sp_buff_size, | ||
179 | &bdc->scratchpad.sp_dma, GFP_KERNEL); | ||
180 | |||
181 | if (!bdc->scratchpad.buff) | ||
182 | goto fail; | ||
183 | |||
184 | bdc->sp_buff_size = sp_buff_size; | ||
185 | bdc->scratchpad.size = sp_buff_size; | ||
186 | low32 = lower_32_bits(bdc->scratchpad.sp_dma); | ||
187 | upp32 = upper_32_bits(bdc->scratchpad.sp_dma); | ||
188 | cpu_to_le32s(&low32); | ||
189 | cpu_to_le32s(&upp32); | ||
190 | bdc_writel(bdc->regs, BDC_SPBBAL, low32); | ||
191 | bdc_writel(bdc->regs, BDC_SPBBAH, upp32); | ||
192 | return 0; | ||
193 | |||
194 | fail: | ||
195 | bdc->scratchpad.buff = NULL; | ||
196 | |||
197 | return -ENOMEM; | ||
198 | } | ||
199 | |||
200 | /* Allocate the status report ring */ | ||
201 | static int setup_srr(struct bdc *bdc, int interrupter) | ||
202 | { | ||
203 | dev_dbg(bdc->dev, "%s() NUM_SR_ENTRIES:%d\n", __func__, NUM_SR_ENTRIES); | ||
204 | /* Reset the SRR */ | ||
205 | bdc_writel(bdc->regs, BDC_SRRINT(0), BDC_SRR_RWS | BDC_SRR_RST); | ||
206 | bdc->srr.dqp_index = 0; | ||
207 | /* allocate the status report descriptors */ | ||
208 | bdc->srr.sr_bds = dma_zalloc_coherent( | ||
209 | bdc->dev, | ||
210 | NUM_SR_ENTRIES * sizeof(struct bdc_bd), | ||
211 | &bdc->srr.dma_addr, | ||
212 | GFP_KERNEL); | ||
213 | if (!bdc->srr.sr_bds) | ||
214 | return -ENOMEM; | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | /* Initialize the HW regs and internal data structures */ | ||
220 | static void bdc_mem_init(struct bdc *bdc, bool reinit) | ||
221 | { | ||
222 | u8 size = 0; | ||
223 | u32 usb2_pm; | ||
224 | u32 low32; | ||
225 | u32 upp32; | ||
226 | u32 temp; | ||
227 | |||
228 | dev_dbg(bdc->dev, "%s ()\n", __func__); | ||
229 | bdc->ep0_state = WAIT_FOR_SETUP; | ||
230 | bdc->dev_addr = 0; | ||
231 | bdc->srr.eqp_index = 0; | ||
232 | bdc->srr.dqp_index = 0; | ||
233 | bdc->zlp_needed = false; | ||
234 | bdc->delayed_status = false; | ||
235 | |||
236 | bdc_writel(bdc->regs, BDC_SPBBAL, bdc->scratchpad.sp_dma); | ||
237 | /* Init the SRR */ | ||
238 | temp = BDC_SRR_RWS | BDC_SRR_RST; | ||
239 | /* Reset the SRR */ | ||
240 | bdc_writel(bdc->regs, BDC_SRRINT(0), temp); | ||
241 | dev_dbg(bdc->dev, "bdc->srr.sr_bds =%p\n", bdc->srr.sr_bds); | ||
242 | temp = lower_32_bits(bdc->srr.dma_addr); | ||
243 | size = fls(NUM_SR_ENTRIES) - 2; | ||
244 | temp |= size; | ||
245 | dev_dbg(bdc->dev, "SRRBAL[0]=%08x NUM_SR_ENTRIES:%d size:%d\n", | ||
246 | temp, NUM_SR_ENTRIES, size); | ||
247 | |||
248 | low32 = lower_32_bits(temp); | ||
249 | upp32 = upper_32_bits(bdc->srr.dma_addr); | ||
250 | cpu_to_le32s(&low32); | ||
251 | cpu_to_le32s(&upp32); | ||
252 | |||
253 | /* Write the dma addresses into regs*/ | ||
254 | bdc_writel(bdc->regs, BDC_SRRBAL(0), low32); | ||
255 | bdc_writel(bdc->regs, BDC_SRRBAH(0), upp32); | ||
256 | |||
257 | temp = bdc_readl(bdc->regs, BDC_SRRINT(0)); | ||
258 | temp |= BDC_SRR_IE; | ||
259 | temp &= ~(BDC_SRR_RST | BDC_SRR_RWS); | ||
260 | bdc_writel(bdc->regs, BDC_SRRINT(0), temp); | ||
261 | |||
262 | /* Set the Interrupt Coalescence ~500 usec */ | ||
263 | temp = bdc_readl(bdc->regs, BDC_INTCTLS(0)); | ||
264 | temp &= ~0xffff; | ||
265 | temp |= INT_CLS; | ||
266 | bdc_writel(bdc->regs, BDC_INTCTLS(0), temp); | ||
267 | |||
268 | usb2_pm = bdc_readl(bdc->regs, BDC_USPPM2); | ||
269 | dev_dbg(bdc->dev, "usb2_pm=%08x", usb2_pm); | ||
270 | /* Enable hardware LPM Enable */ | ||
271 | usb2_pm |= BDC_HLE; | ||
272 | bdc_writel(bdc->regs, BDC_USPPM2, usb2_pm); | ||
273 | |||
274 | /* readback for debug */ | ||
275 | usb2_pm = bdc_readl(bdc->regs, BDC_USPPM2); | ||
276 | dev_dbg(bdc->dev, "usb2_pm=%08x\n", usb2_pm); | ||
277 | |||
278 | /* Disable any unwanted SR's on SRR */ | ||
279 | temp = bdc_readl(bdc->regs, BDC_BDCSC); | ||
280 | /* We don't want Microframe counter wrap SR */ | ||
281 | temp |= BDC_MASK_MCW; | ||
282 | bdc_writel(bdc->regs, BDC_BDCSC, temp); | ||
283 | |||
284 | /* | ||
285 | * In some error cases, driver has to reset the entire BDC controller | ||
286 | * in that case reinit is passed as 1 | ||
287 | */ | ||
288 | if (reinit) { | ||
289 | /* Enable interrupts */ | ||
290 | temp = bdc_readl(bdc->regs, BDC_BDCSC); | ||
291 | temp |= BDC_GIE; | ||
292 | bdc_writel(bdc->regs, BDC_BDCSC, temp); | ||
293 | /* Init scratchpad to 0 */ | ||
294 | memset(bdc->scratchpad.buff, 0, bdc->sp_buff_size); | ||
295 | /* Initialize SRR to 0 */ | ||
296 | memset(bdc->srr.sr_bds, 0, | ||
297 | NUM_SR_ENTRIES * sizeof(struct bdc_bd)); | ||
298 | } else { | ||
299 | /* One time initiaization only */ | ||
300 | /* Enable status report function pointers */ | ||
301 | bdc->sr_handler[0] = bdc_sr_xsf; | ||
302 | bdc->sr_handler[1] = bdc_sr_uspc; | ||
303 | |||
304 | /* EP0 status report function pointers */ | ||
305 | bdc->sr_xsf_ep0[0] = bdc_xsf_ep0_setup_recv; | ||
306 | bdc->sr_xsf_ep0[1] = bdc_xsf_ep0_data_start; | ||
307 | bdc->sr_xsf_ep0[2] = bdc_xsf_ep0_status_start; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /* Free the dynamic memory */ | ||
312 | static void bdc_mem_free(struct bdc *bdc) | ||
313 | { | ||
314 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
315 | /* Free SRR */ | ||
316 | if (bdc->srr.sr_bds) | ||
317 | dma_free_coherent(bdc->dev, | ||
318 | NUM_SR_ENTRIES * sizeof(struct bdc_bd), | ||
319 | bdc->srr.sr_bds, bdc->srr.dma_addr); | ||
320 | |||
321 | /* Free scratchpad */ | ||
322 | if (bdc->scratchpad.buff) | ||
323 | dma_free_coherent(bdc->dev, bdc->sp_buff_size, | ||
324 | bdc->scratchpad.buff, bdc->scratchpad.sp_dma); | ||
325 | |||
326 | /* Destroy the dma pools */ | ||
327 | if (bdc->bd_table_pool) | ||
328 | dma_pool_destroy(bdc->bd_table_pool); | ||
329 | |||
330 | /* Free the bdc_ep array */ | ||
331 | kfree(bdc->bdc_ep_array); | ||
332 | |||
333 | bdc->srr.sr_bds = NULL; | ||
334 | bdc->scratchpad.buff = NULL; | ||
335 | bdc->bd_table_pool = NULL; | ||
336 | bdc->bdc_ep_array = NULL; | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * bdc reinit gives a controller reset and reinitialize the registers, | ||
341 | * called from disconnect/bus reset scenario's, to ensure proper HW cleanup | ||
342 | */ | ||
343 | int bdc_reinit(struct bdc *bdc) | ||
344 | { | ||
345 | int ret; | ||
346 | |||
347 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
348 | ret = bdc_stop(bdc); | ||
349 | if (ret) | ||
350 | goto out; | ||
351 | |||
352 | ret = bdc_reset(bdc); | ||
353 | if (ret) | ||
354 | goto out; | ||
355 | |||
356 | /* the reinit flag is 1 */ | ||
357 | bdc_mem_init(bdc, true); | ||
358 | ret = bdc_run(bdc); | ||
359 | out: | ||
360 | bdc->reinit = false; | ||
361 | |||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | /* Allocate all the dyanmic memory */ | ||
366 | static int bdc_mem_alloc(struct bdc *bdc) | ||
367 | { | ||
368 | u32 page_size; | ||
369 | unsigned int num_ieps, num_oeps; | ||
370 | |||
371 | dev_dbg(bdc->dev, | ||
372 | "%s() NUM_BDS_PER_TABLE:%d\n", __func__, | ||
373 | NUM_BDS_PER_TABLE); | ||
374 | page_size = BDC_PGS(bdc_readl(bdc->regs, BDC_BDCCFG0)); | ||
375 | /* page size is 2^pgs KB */ | ||
376 | page_size = 1 << page_size; | ||
377 | /* KB */ | ||
378 | page_size <<= 10; | ||
379 | dev_dbg(bdc->dev, "page_size=%d\n", page_size); | ||
380 | |||
381 | /* Create a pool of bd tables */ | ||
382 | bdc->bd_table_pool = | ||
383 | dma_pool_create("BDC BD tables", bdc->dev, NUM_BDS_PER_TABLE * 16, | ||
384 | 16, page_size); | ||
385 | |||
386 | if (!bdc->bd_table_pool) | ||
387 | goto fail; | ||
388 | |||
389 | if (scratchpad_setup(bdc)) | ||
390 | goto fail; | ||
391 | |||
392 | /* read from regs */ | ||
393 | num_ieps = NUM_NCS(bdc_readl(bdc->regs, BDC_FSCNIC)); | ||
394 | num_oeps = NUM_NCS(bdc_readl(bdc->regs, BDC_FSCNOC)); | ||
395 | /* +2: 1 for ep0 and the other is rsvd i.e. bdc_ep[0] is rsvd */ | ||
396 | bdc->num_eps = num_ieps + num_oeps + 2; | ||
397 | dev_dbg(bdc->dev, | ||
398 | "ieps:%d eops:%d num_eps:%d\n", | ||
399 | num_ieps, num_oeps, bdc->num_eps); | ||
400 | /* allocate array of ep pointers */ | ||
401 | bdc->bdc_ep_array = kcalloc(bdc->num_eps, sizeof(struct bdc_ep *), | ||
402 | GFP_KERNEL); | ||
403 | if (!bdc->bdc_ep_array) | ||
404 | goto fail; | ||
405 | |||
406 | dev_dbg(bdc->dev, "Allocating sr report0\n"); | ||
407 | if (setup_srr(bdc, 0)) | ||
408 | goto fail; | ||
409 | |||
410 | return 0; | ||
411 | fail: | ||
412 | dev_warn(bdc->dev, "Couldn't initialize memory\n"); | ||
413 | bdc_mem_free(bdc); | ||
414 | |||
415 | return -ENOMEM; | ||
416 | } | ||
417 | |||
418 | /* opposite to bdc_hw_init */ | ||
419 | static void bdc_hw_exit(struct bdc *bdc) | ||
420 | { | ||
421 | dev_dbg(bdc->dev, "%s ()\n", __func__); | ||
422 | bdc_mem_free(bdc); | ||
423 | } | ||
424 | |||
425 | /* Initialize the bdc HW and memory */ | ||
426 | static int bdc_hw_init(struct bdc *bdc) | ||
427 | { | ||
428 | int ret; | ||
429 | |||
430 | dev_dbg(bdc->dev, "%s ()\n", __func__); | ||
431 | ret = bdc_reset(bdc); | ||
432 | if (ret) { | ||
433 | dev_err(bdc->dev, "err resetting bdc abort bdc init%d\n", ret); | ||
434 | return ret; | ||
435 | } | ||
436 | ret = bdc_mem_alloc(bdc); | ||
437 | if (ret) { | ||
438 | dev_err(bdc->dev, "Mem alloc failed, aborting\n"); | ||
439 | return -ENOMEM; | ||
440 | } | ||
441 | bdc_mem_init(bdc, 0); | ||
442 | bdc_dbg_regs(bdc); | ||
443 | dev_dbg(bdc->dev, "HW Init done\n"); | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | static int bdc_probe(struct platform_device *pdev) | ||
449 | { | ||
450 | struct bdc *bdc; | ||
451 | struct resource *res; | ||
452 | int ret = -ENOMEM; | ||
453 | int irq; | ||
454 | u32 temp; | ||
455 | struct device *dev = &pdev->dev; | ||
456 | |||
457 | dev_dbg(dev, "%s()\n", __func__); | ||
458 | bdc = devm_kzalloc(dev, sizeof(*bdc), GFP_KERNEL); | ||
459 | if (!bdc) | ||
460 | return -ENOMEM; | ||
461 | |||
462 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
463 | bdc->regs = devm_ioremap_resource(dev, res); | ||
464 | if (IS_ERR(bdc->regs)) { | ||
465 | dev_err(dev, "ioremap error\n"); | ||
466 | return -ENOMEM; | ||
467 | } | ||
468 | irq = platform_get_irq(pdev, 0); | ||
469 | if (irq < 0) { | ||
470 | dev_err(dev, "platform_get_irq failed:%d\n", irq); | ||
471 | return irq; | ||
472 | } | ||
473 | spin_lock_init(&bdc->lock); | ||
474 | platform_set_drvdata(pdev, bdc); | ||
475 | bdc->irq = irq; | ||
476 | bdc->dev = dev; | ||
477 | dev_dbg(bdc->dev, "bdc->regs: %p irq=%d\n", bdc->regs, bdc->irq); | ||
478 | |||
479 | temp = bdc_readl(bdc->regs, BDC_BDCSC); | ||
480 | if ((temp & BDC_P64) && | ||
481 | !dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) { | ||
482 | dev_dbg(bdc->dev, "Using 64-bit address\n"); | ||
483 | } else { | ||
484 | ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); | ||
485 | if (ret) { | ||
486 | dev_err(bdc->dev, "No suitable DMA config available, abort\n"); | ||
487 | return -ENOTSUPP; | ||
488 | } | ||
489 | dev_dbg(bdc->dev, "Using 32-bit address\n"); | ||
490 | } | ||
491 | ret = bdc_hw_init(bdc); | ||
492 | if (ret) { | ||
493 | dev_err(bdc->dev, "BDC init failure:%d\n", ret); | ||
494 | return ret; | ||
495 | } | ||
496 | ret = bdc_udc_init(bdc); | ||
497 | if (ret) { | ||
498 | dev_err(bdc->dev, "BDC Gadget init failure:%d\n", ret); | ||
499 | goto cleanup; | ||
500 | } | ||
501 | return 0; | ||
502 | |||
503 | cleanup: | ||
504 | bdc_hw_exit(bdc); | ||
505 | |||
506 | return ret; | ||
507 | } | ||
508 | |||
509 | static int bdc_remove(struct platform_device *pdev) | ||
510 | { | ||
511 | struct bdc *bdc; | ||
512 | |||
513 | bdc = platform_get_drvdata(pdev); | ||
514 | dev_dbg(bdc->dev, "%s ()\n", __func__); | ||
515 | bdc_udc_exit(bdc); | ||
516 | bdc_hw_exit(bdc); | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static struct platform_driver bdc_driver = { | ||
522 | .driver = { | ||
523 | .name = BRCM_BDC_NAME, | ||
524 | .owner = THIS_MODULE | ||
525 | }, | ||
526 | .probe = bdc_probe, | ||
527 | .remove = bdc_remove, | ||
528 | }; | ||
529 | |||
530 | module_platform_driver(bdc_driver); | ||
531 | MODULE_AUTHOR("Ashwini Pahuja <ashwini.linux@gmail.com>"); | ||
532 | MODULE_LICENSE("GPL"); | ||
533 | MODULE_DESCRIPTION(BRCM_BDC_DESC); | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc_dbg.c b/drivers/usb/gadget/udc/bdc/bdc_dbg.c new file mode 100644 index 000000000000..5945dbc47825 --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/bdc_dbg.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * bdc_dbg.c - BRCM BDC USB3.0 device controller debug functions | ||
3 | * | ||
4 | * Copyright (C) 2014 Broadcom Corporation | ||
5 | * | ||
6 | * Author: Ashwini Pahuja | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include "bdc.h" | ||
16 | #include "bdc_dbg.h" | ||
17 | |||
18 | void bdc_dbg_regs(struct bdc *bdc) | ||
19 | { | ||
20 | u32 temp; | ||
21 | |||
22 | dev_vdbg(bdc->dev, "bdc->regs:%p\n", bdc->regs); | ||
23 | temp = bdc_readl(bdc->regs, BDC_BDCCFG0); | ||
24 | dev_vdbg(bdc->dev, "bdccfg0:0x%08x\n", temp); | ||
25 | temp = bdc_readl(bdc->regs, BDC_BDCCFG1); | ||
26 | dev_vdbg(bdc->dev, "bdccfg1:0x%08x\n", temp); | ||
27 | temp = bdc_readl(bdc->regs, BDC_BDCCAP0); | ||
28 | dev_vdbg(bdc->dev, "bdccap0:0x%08x\n", temp); | ||
29 | temp = bdc_readl(bdc->regs, BDC_BDCCAP1); | ||
30 | dev_vdbg(bdc->dev, "bdccap1:0x%08x\n", temp); | ||
31 | temp = bdc_readl(bdc->regs, BDC_USPC); | ||
32 | dev_vdbg(bdc->dev, "uspc:0x%08x\n", temp); | ||
33 | temp = bdc_readl(bdc->regs, BDC_DVCSA); | ||
34 | dev_vdbg(bdc->dev, "dvcsa:0x%08x\n", temp); | ||
35 | temp = bdc_readl(bdc->regs, BDC_DVCSB); | ||
36 | dev_vdbg(bdc->dev, "dvcsb:0x%x08\n", temp); | ||
37 | } | ||
38 | |||
39 | void bdc_dump_epsts(struct bdc *bdc) | ||
40 | { | ||
41 | u32 temp; | ||
42 | |||
43 | temp = bdc_readl(bdc->regs, BDC_EPSTS0(0)); | ||
44 | dev_vdbg(bdc->dev, "BDC_EPSTS0:0x%08x\n", temp); | ||
45 | |||
46 | temp = bdc_readl(bdc->regs, BDC_EPSTS1(0)); | ||
47 | dev_vdbg(bdc->dev, "BDC_EPSTS1:0x%x\n", temp); | ||
48 | |||
49 | temp = bdc_readl(bdc->regs, BDC_EPSTS2(0)); | ||
50 | dev_vdbg(bdc->dev, "BDC_EPSTS2:0x%08x\n", temp); | ||
51 | |||
52 | temp = bdc_readl(bdc->regs, BDC_EPSTS3(0)); | ||
53 | dev_vdbg(bdc->dev, "BDC_EPSTS3:0x%08x\n", temp); | ||
54 | |||
55 | temp = bdc_readl(bdc->regs, BDC_EPSTS4(0)); | ||
56 | dev_vdbg(bdc->dev, "BDC_EPSTS4:0x%08x\n", temp); | ||
57 | |||
58 | temp = bdc_readl(bdc->regs, BDC_EPSTS5(0)); | ||
59 | dev_vdbg(bdc->dev, "BDC_EPSTS5:0x%08x\n", temp); | ||
60 | |||
61 | temp = bdc_readl(bdc->regs, BDC_EPSTS6(0)); | ||
62 | dev_vdbg(bdc->dev, "BDC_EPSTS6:0x%08x\n", temp); | ||
63 | |||
64 | temp = bdc_readl(bdc->regs, BDC_EPSTS7(0)); | ||
65 | dev_vdbg(bdc->dev, "BDC_EPSTS7:0x%08x\n", temp); | ||
66 | } | ||
67 | |||
68 | void bdc_dbg_srr(struct bdc *bdc, u32 srr_num) | ||
69 | { | ||
70 | struct bdc_sr *sr; | ||
71 | dma_addr_t addr; | ||
72 | int i; | ||
73 | |||
74 | sr = bdc->srr.sr_bds; | ||
75 | addr = bdc->srr.dma_addr; | ||
76 | dev_vdbg(bdc->dev, "bdc_dbg_srr sr:%p dqp_index:%d\n", | ||
77 | sr, bdc->srr.dqp_index); | ||
78 | for (i = 0; i < NUM_SR_ENTRIES; i++) { | ||
79 | sr = &bdc->srr.sr_bds[i]; | ||
80 | dev_vdbg(bdc->dev, "%llx %08x %08x %08x %08x\n", | ||
81 | (unsigned long long)addr, | ||
82 | le32_to_cpu(sr->offset[0]), | ||
83 | le32_to_cpu(sr->offset[1]), | ||
84 | le32_to_cpu(sr->offset[2]), | ||
85 | le32_to_cpu(sr->offset[3])); | ||
86 | addr += sizeof(*sr); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | void bdc_dbg_bd_list(struct bdc *bdc, struct bdc_ep *ep) | ||
91 | { | ||
92 | struct bd_list *bd_list = &ep->bd_list; | ||
93 | struct bd_table *bd_table; | ||
94 | struct bdc_bd *bd; | ||
95 | int tbi, bdi, gbdi; | ||
96 | dma_addr_t dma; | ||
97 | |||
98 | gbdi = 0; | ||
99 | dev_vdbg(bdc->dev, | ||
100 | "Dump bd list for %s epnum:%d\n", | ||
101 | ep->name, ep->ep_num); | ||
102 | |||
103 | dev_vdbg(bdc->dev, | ||
104 | "tabs:%d max_bdi:%d eqp_bdi:%d hwd_bdi:%d num_bds_table:%d\n", | ||
105 | bd_list->num_tabs, bd_list->max_bdi, bd_list->eqp_bdi, | ||
106 | bd_list->hwd_bdi, bd_list->num_bds_table); | ||
107 | |||
108 | for (tbi = 0; tbi < bd_list->num_tabs; tbi++) { | ||
109 | bd_table = bd_list->bd_table_array[tbi]; | ||
110 | for (bdi = 0; bdi < bd_list->num_bds_table; bdi++) { | ||
111 | bd = bd_table->start_bd + bdi; | ||
112 | dma = bd_table->dma + (sizeof(struct bdc_bd) * bdi); | ||
113 | dev_vdbg(bdc->dev, | ||
114 | "tbi:%2d bdi:%2d gbdi:%2d virt:%p phys:%llx %08x %08x %08x %08x\n", | ||
115 | tbi, bdi, gbdi++, bd, (unsigned long long)dma, | ||
116 | le32_to_cpu(bd->offset[0]), | ||
117 | le32_to_cpu(bd->offset[1]), | ||
118 | le32_to_cpu(bd->offset[2]), | ||
119 | le32_to_cpu(bd->offset[3])); | ||
120 | } | ||
121 | dev_vdbg(bdc->dev, "\n\n"); | ||
122 | } | ||
123 | } | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc_dbg.h b/drivers/usb/gadget/udc/bdc/bdc_dbg.h new file mode 100644 index 000000000000..338a6c701315 --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/bdc_dbg.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * bdc_dbg.h - header for the BDC debug functions | ||
3 | * | ||
4 | * Copyright (C) 2014 Broadcom Corporation | ||
5 | * | ||
6 | * Author: Ashwini Pahuja | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | #ifndef __LINUX_BDC_DBG_H__ | ||
15 | #define __LINUX_BDC_DBG_H__ | ||
16 | |||
17 | #include "bdc.h" | ||
18 | |||
19 | #ifdef CONFIG_USB_GADGET_VERBOSE | ||
20 | void bdc_dbg_bd_list(struct bdc *, struct bdc_ep*); | ||
21 | void bdc_dbg_srr(struct bdc *, u32); | ||
22 | void bdc_dbg_regs(struct bdc *); | ||
23 | void bdc_dump_epsts(struct bdc *); | ||
24 | #else | ||
25 | static inline void bdc_dbg_regs(struct bdc *bdc) | ||
26 | { } | ||
27 | |||
28 | static inline void bdc_dbg_srr(struct bdc *bdc, u32 srr_num) | ||
29 | { } | ||
30 | |||
31 | static inline void bdc_dbg_bd_list(struct bdc *bdc, struct bdc_ep *ep) | ||
32 | { } | ||
33 | |||
34 | static inline void bdc_dump_epsts(struct bdc *bdc) | ||
35 | { } | ||
36 | #endif /* CONFIG_USB_GADGET_VERBOSE */ | ||
37 | #endif /* __LINUX_BDC_DBG_H__ */ | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c new file mode 100644 index 000000000000..15da5b1e76c0 --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c | |||
@@ -0,0 +1,2023 @@ | |||
1 | /* | ||
2 | * bdc_ep.c - BRCM BDC USB3.0 device controller endpoint related functions | ||
3 | * | ||
4 | * Copyright (C) 2014 Broadcom Corporation | ||
5 | * | ||
6 | * Author: Ashwini Pahuja | ||
7 | * | ||
8 | * Based on drivers under drivers/usb/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/dmapool.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/timer.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/moduleparam.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/usb/ch9.h> | ||
33 | #include <linux/usb/gadget.h> | ||
34 | #include <linux/usb/otg.h> | ||
35 | #include <linux/pm.h> | ||
36 | #include <linux/io.h> | ||
37 | #include <linux/irq.h> | ||
38 | #include <asm/unaligned.h> | ||
39 | #include <linux/platform_device.h> | ||
40 | #include <linux/usb/composite.h> | ||
41 | |||
42 | #include "bdc.h" | ||
43 | #include "bdc_ep.h" | ||
44 | #include "bdc_cmd.h" | ||
45 | #include "bdc_dbg.h" | ||
46 | |||
47 | static const char * const ep0_state_string[] = { | ||
48 | "WAIT_FOR_SETUP", | ||
49 | "WAIT_FOR_DATA_START", | ||
50 | "WAIT_FOR_DATA_XMIT", | ||
51 | "WAIT_FOR_STATUS_START", | ||
52 | "WAIT_FOR_STATUS_XMIT", | ||
53 | "STATUS_PENDING" | ||
54 | }; | ||
55 | |||
56 | /* Free the bdl during ep disable */ | ||
57 | static void ep_bd_list_free(struct bdc_ep *ep, u32 num_tabs) | ||
58 | { | ||
59 | struct bd_list *bd_list = &ep->bd_list; | ||
60 | struct bdc *bdc = ep->bdc; | ||
61 | struct bd_table *bd_table; | ||
62 | int index; | ||
63 | |||
64 | dev_dbg(bdc->dev, "%s ep:%s num_tabs:%d\n", | ||
65 | __func__, ep->name, num_tabs); | ||
66 | |||
67 | if (!bd_list->bd_table_array) { | ||
68 | dev_dbg(bdc->dev, "%s already freed\n", ep->name); | ||
69 | return; | ||
70 | } | ||
71 | for (index = 0; index < num_tabs; index++) { | ||
72 | /* | ||
73 | * check if the bd_table struct is allocated ? | ||
74 | * if yes, then check if bd memory has been allocated, then | ||
75 | * free the dma_pool and also the bd_table struct memory | ||
76 | */ | ||
77 | bd_table = bd_list->bd_table_array[index]; | ||
78 | dev_dbg(bdc->dev, "bd_table:%p index:%d\n", bd_table, index); | ||
79 | if (!bd_table) { | ||
80 | dev_dbg(bdc->dev, "bd_table not allocated\n"); | ||
81 | continue; | ||
82 | } | ||
83 | if (!bd_table->start_bd) { | ||
84 | dev_dbg(bdc->dev, "bd dma pool not allocted\n"); | ||
85 | continue; | ||
86 | } | ||
87 | |||
88 | dev_dbg(bdc->dev, | ||
89 | "Free dma pool start_bd:%p dma:%llx\n", | ||
90 | bd_table->start_bd, | ||
91 | (unsigned long long)bd_table->dma); | ||
92 | |||
93 | dma_pool_free(bdc->bd_table_pool, | ||
94 | bd_table->start_bd, | ||
95 | bd_table->dma); | ||
96 | /* Free the bd_table structure */ | ||
97 | kfree(bd_table); | ||
98 | } | ||
99 | /* Free the bd table array */ | ||
100 | kfree(ep->bd_list.bd_table_array); | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * chain the tables, by insteting a chain bd at the end of prev_table, pointing | ||
105 | * to next_table | ||
106 | */ | ||
107 | static inline void chain_table(struct bd_table *prev_table, | ||
108 | struct bd_table *next_table, | ||
109 | u32 bd_p_tab) | ||
110 | { | ||
111 | /* Chain the prev table to next table */ | ||
112 | prev_table->start_bd[bd_p_tab-1].offset[0] = | ||
113 | cpu_to_le32(lower_32_bits(next_table->dma)); | ||
114 | |||
115 | prev_table->start_bd[bd_p_tab-1].offset[1] = | ||
116 | cpu_to_le32(upper_32_bits(next_table->dma)); | ||
117 | |||
118 | prev_table->start_bd[bd_p_tab-1].offset[2] = | ||
119 | 0x0; | ||
120 | |||
121 | prev_table->start_bd[bd_p_tab-1].offset[3] = | ||
122 | cpu_to_le32(MARK_CHAIN_BD); | ||
123 | } | ||
124 | |||
125 | /* Allocate the bdl for ep, during config ep */ | ||
126 | static int ep_bd_list_alloc(struct bdc_ep *ep) | ||
127 | { | ||
128 | struct bd_table *prev_table = NULL; | ||
129 | int index, num_tabs, bd_p_tab; | ||
130 | struct bdc *bdc = ep->bdc; | ||
131 | struct bd_table *bd_table; | ||
132 | dma_addr_t dma; | ||
133 | |||
134 | if (usb_endpoint_xfer_isoc(ep->desc)) | ||
135 | num_tabs = NUM_TABLES_ISOCH; | ||
136 | else | ||
137 | num_tabs = NUM_TABLES; | ||
138 | |||
139 | bd_p_tab = NUM_BDS_PER_TABLE; | ||
140 | /* if there is only 1 table in bd list then loop chain to self */ | ||
141 | dev_dbg(bdc->dev, | ||
142 | "%s ep:%p num_tabs:%d\n", | ||
143 | __func__, ep, num_tabs); | ||
144 | |||
145 | /* Allocate memory for table array */ | ||
146 | ep->bd_list.bd_table_array = kzalloc( | ||
147 | num_tabs * sizeof(struct bd_table *), | ||
148 | GFP_ATOMIC); | ||
149 | if (!ep->bd_list.bd_table_array) | ||
150 | return -ENOMEM; | ||
151 | |||
152 | /* Allocate memory for each table */ | ||
153 | for (index = 0; index < num_tabs; index++) { | ||
154 | /* Allocate memory for bd_table structure */ | ||
155 | bd_table = kzalloc(sizeof(struct bd_table), GFP_ATOMIC); | ||
156 | if (!bd_table) | ||
157 | goto fail; | ||
158 | |||
159 | bd_table->start_bd = dma_pool_alloc(bdc->bd_table_pool, | ||
160 | GFP_ATOMIC, | ||
161 | &dma); | ||
162 | if (!bd_table->start_bd) | ||
163 | goto fail; | ||
164 | |||
165 | bd_table->dma = dma; | ||
166 | |||
167 | dev_dbg(bdc->dev, | ||
168 | "index:%d start_bd:%p dma=%08llx prev_table:%p\n", | ||
169 | index, bd_table->start_bd, | ||
170 | (unsigned long long)bd_table->dma, prev_table); | ||
171 | |||
172 | ep->bd_list.bd_table_array[index] = bd_table; | ||
173 | memset(bd_table->start_bd, 0, bd_p_tab * sizeof(struct bdc_bd)); | ||
174 | if (prev_table) | ||
175 | chain_table(prev_table, bd_table, bd_p_tab); | ||
176 | |||
177 | prev_table = bd_table; | ||
178 | } | ||
179 | chain_table(prev_table, ep->bd_list.bd_table_array[0], bd_p_tab); | ||
180 | /* Memory allocation is successful, now init the internal fields */ | ||
181 | ep->bd_list.num_tabs = num_tabs; | ||
182 | ep->bd_list.max_bdi = (num_tabs * bd_p_tab) - 1; | ||
183 | ep->bd_list.num_tabs = num_tabs; | ||
184 | ep->bd_list.num_bds_table = bd_p_tab; | ||
185 | ep->bd_list.eqp_bdi = 0; | ||
186 | ep->bd_list.hwd_bdi = 0; | ||
187 | |||
188 | return 0; | ||
189 | fail: | ||
190 | /* Free the bd_table_array, bd_table struct, bd's */ | ||
191 | ep_bd_list_free(ep, num_tabs); | ||
192 | |||
193 | return -ENOMEM; | ||
194 | } | ||
195 | |||
196 | /* returns how many bd's are need for this transfer */ | ||
197 | static inline int bd_needed_req(struct bdc_req *req) | ||
198 | { | ||
199 | int bd_needed = 0; | ||
200 | int remaining; | ||
201 | |||
202 | /* 1 bd needed for 0 byte transfer */ | ||
203 | if (req->usb_req.length == 0) | ||
204 | return 1; | ||
205 | |||
206 | /* remaining bytes after tranfering all max BD size BD's */ | ||
207 | remaining = req->usb_req.length % BD_MAX_BUFF_SIZE; | ||
208 | if (remaining) | ||
209 | bd_needed++; | ||
210 | |||
211 | /* How many maximum BUFF size BD's ? */ | ||
212 | remaining = req->usb_req.length / BD_MAX_BUFF_SIZE; | ||
213 | bd_needed += remaining; | ||
214 | |||
215 | return bd_needed; | ||
216 | } | ||
217 | |||
218 | /* returns the bd index(bdi) corresponding to bd dma address */ | ||
219 | static int bd_add_to_bdi(struct bdc_ep *ep, dma_addr_t bd_dma_addr) | ||
220 | { | ||
221 | struct bd_list *bd_list = &ep->bd_list; | ||
222 | dma_addr_t dma_first_bd, dma_last_bd; | ||
223 | struct bdc *bdc = ep->bdc; | ||
224 | struct bd_table *bd_table; | ||
225 | bool found = false; | ||
226 | int tbi, bdi; | ||
227 | |||
228 | dma_first_bd = dma_last_bd = 0; | ||
229 | dev_dbg(bdc->dev, "%s %llx\n", | ||
230 | __func__, (unsigned long long)bd_dma_addr); | ||
231 | /* | ||
232 | * Find in which table this bd_dma_addr belongs?, go through the table | ||
233 | * array and compare addresses of first and last address of bd of each | ||
234 | * table | ||
235 | */ | ||
236 | for (tbi = 0; tbi < bd_list->num_tabs; tbi++) { | ||
237 | bd_table = bd_list->bd_table_array[tbi]; | ||
238 | dma_first_bd = bd_table->dma; | ||
239 | dma_last_bd = bd_table->dma + | ||
240 | (sizeof(struct bdc_bd) * | ||
241 | (bd_list->num_bds_table - 1)); | ||
242 | dev_dbg(bdc->dev, "dma_first_bd:%llx dma_last_bd:%llx\n", | ||
243 | (unsigned long long)dma_first_bd, | ||
244 | (unsigned long long)dma_last_bd); | ||
245 | if (bd_dma_addr >= dma_first_bd && bd_dma_addr <= dma_last_bd) { | ||
246 | found = true; | ||
247 | break; | ||
248 | } | ||
249 | } | ||
250 | if (unlikely(!found)) { | ||
251 | dev_err(bdc->dev, "%s FATAL err, bd not found\n", __func__); | ||
252 | return -EINVAL; | ||
253 | } | ||
254 | /* Now we know the table, find the bdi */ | ||
255 | bdi = (bd_dma_addr - dma_first_bd) / sizeof(struct bdc_bd); | ||
256 | |||
257 | /* return the global bdi, to compare with ep eqp_bdi */ | ||
258 | return (bdi + (tbi * bd_list->num_bds_table)); | ||
259 | } | ||
260 | |||
261 | /* returns the table index(tbi) of the given bdi */ | ||
262 | static int bdi_to_tbi(struct bdc_ep *ep, int bdi) | ||
263 | { | ||
264 | int tbi; | ||
265 | |||
266 | tbi = bdi / ep->bd_list.num_bds_table; | ||
267 | dev_vdbg(ep->bdc->dev, | ||
268 | "bdi:%d num_bds_table:%d tbi:%d\n", | ||
269 | bdi, ep->bd_list.num_bds_table, tbi); | ||
270 | |||
271 | return tbi; | ||
272 | } | ||
273 | |||
274 | /* Find the bdi last bd in the transfer */ | ||
275 | static inline int find_end_bdi(struct bdc_ep *ep, int next_hwd_bdi) | ||
276 | { | ||
277 | int end_bdi; | ||
278 | |||
279 | end_bdi = next_hwd_bdi - 1; | ||
280 | if (end_bdi < 0) | ||
281 | end_bdi = ep->bd_list.max_bdi - 1; | ||
282 | else if ((end_bdi % (ep->bd_list.num_bds_table-1)) == 0) | ||
283 | end_bdi--; | ||
284 | |||
285 | return end_bdi; | ||
286 | } | ||
287 | |||
288 | /* | ||
289 | * How many transfer bd's are available on this ep bdl, chain bds are not | ||
290 | * counted in available bds | ||
291 | */ | ||
292 | static int bd_available_ep(struct bdc_ep *ep) | ||
293 | { | ||
294 | struct bd_list *bd_list = &ep->bd_list; | ||
295 | int available1, available2; | ||
296 | struct bdc *bdc = ep->bdc; | ||
297 | int chain_bd1, chain_bd2; | ||
298 | int available_bd = 0; | ||
299 | |||
300 | available1 = available2 = chain_bd1 = chain_bd2 = 0; | ||
301 | /* if empty then we have all bd's available - number of chain bd's */ | ||
302 | if (bd_list->eqp_bdi == bd_list->hwd_bdi) | ||
303 | return bd_list->max_bdi - bd_list->num_tabs; | ||
304 | |||
305 | /* | ||
306 | * Depending upon where eqp and dqp pointers are, caculate number | ||
307 | * of avaialble bd's | ||
308 | */ | ||
309 | if (bd_list->hwd_bdi < bd_list->eqp_bdi) { | ||
310 | /* available bd's are from eqp..max_bds + 0..dqp - chain_bds */ | ||
311 | available1 = bd_list->max_bdi - bd_list->eqp_bdi; | ||
312 | available2 = bd_list->hwd_bdi; | ||
313 | chain_bd1 = available1 / bd_list->num_bds_table; | ||
314 | chain_bd2 = available2 / bd_list->num_bds_table; | ||
315 | dev_vdbg(bdc->dev, "chain_bd1:%d chain_bd2:%d\n", | ||
316 | chain_bd1, chain_bd2); | ||
317 | available_bd = available1 + available2 - chain_bd1 - chain_bd2; | ||
318 | } else { | ||
319 | /* available bd's are from eqp..dqp - number of chain bd's */ | ||
320 | available1 = bd_list->hwd_bdi - bd_list->eqp_bdi; | ||
321 | /* if gap between eqp and dqp is less than NUM_BDS_PER_TABLE */ | ||
322 | if ((bd_list->hwd_bdi - bd_list->eqp_bdi) | ||
323 | <= bd_list->num_bds_table) { | ||
324 | /* If there any chain bd in between */ | ||
325 | if (!(bdi_to_tbi(ep, bd_list->hwd_bdi) | ||
326 | == bdi_to_tbi(ep, bd_list->eqp_bdi))) { | ||
327 | available_bd = available1 - 1; | ||
328 | } | ||
329 | } else { | ||
330 | chain_bd1 = available1 / bd_list->num_bds_table; | ||
331 | available_bd = available1 - chain_bd1; | ||
332 | } | ||
333 | } | ||
334 | /* | ||
335 | * we need to keep one extra bd to check if ring is full or empty so | ||
336 | * reduce by 1 | ||
337 | */ | ||
338 | available_bd--; | ||
339 | dev_vdbg(bdc->dev, "available_bd:%d\n", available_bd); | ||
340 | |||
341 | return available_bd; | ||
342 | } | ||
343 | |||
344 | /* Notify the hardware after queueing the bd to bdl */ | ||
345 | void bdc_notify_xfr(struct bdc *bdc, u32 epnum) | ||
346 | { | ||
347 | struct bdc_ep *ep = bdc->bdc_ep_array[epnum]; | ||
348 | |||
349 | dev_vdbg(bdc->dev, "%s epnum:%d\n", __func__, epnum); | ||
350 | /* | ||
351 | * We don't have anyway to check if ep state is running, | ||
352 | * except the software flags. | ||
353 | */ | ||
354 | if (unlikely(ep->flags & BDC_EP_STOP)) | ||
355 | ep->flags &= ~BDC_EP_STOP; | ||
356 | |||
357 | bdc_writel(bdc->regs, BDC_XSFNTF, epnum); | ||
358 | } | ||
359 | |||
360 | /* returns the bd corresponding to bdi */ | ||
361 | static struct bdc_bd *bdi_to_bd(struct bdc_ep *ep, int bdi) | ||
362 | { | ||
363 | int tbi = bdi_to_tbi(ep, bdi); | ||
364 | int local_bdi = 0; | ||
365 | |||
366 | local_bdi = bdi - (tbi * ep->bd_list.num_bds_table); | ||
367 | dev_vdbg(ep->bdc->dev, | ||
368 | "%s bdi:%d local_bdi:%d\n", | ||
369 | __func__, bdi, local_bdi); | ||
370 | |||
371 | return (ep->bd_list.bd_table_array[tbi]->start_bd + local_bdi); | ||
372 | } | ||
373 | |||
374 | /* Advance the enqueue pointer */ | ||
375 | static void ep_bdlist_eqp_adv(struct bdc_ep *ep) | ||
376 | { | ||
377 | ep->bd_list.eqp_bdi++; | ||
378 | /* if it's chain bd, then move to next */ | ||
379 | if (((ep->bd_list.eqp_bdi + 1) % ep->bd_list.num_bds_table) == 0) | ||
380 | ep->bd_list.eqp_bdi++; | ||
381 | |||
382 | /* if the eqp is pointing to last + 1 then move back to 0 */ | ||
383 | if (ep->bd_list.eqp_bdi == (ep->bd_list.max_bdi + 1)) | ||
384 | ep->bd_list.eqp_bdi = 0; | ||
385 | } | ||
386 | |||
387 | /* Setup the first bd for ep0 transfer */ | ||
388 | static int setup_first_bd_ep0(struct bdc *bdc, struct bdc_req *req, u32 *dword3) | ||
389 | { | ||
390 | u16 wValue; | ||
391 | u32 req_len; | ||
392 | |||
393 | req->ep->dir = 0; | ||
394 | req_len = req->usb_req.length; | ||
395 | switch (bdc->ep0_state) { | ||
396 | case WAIT_FOR_DATA_START: | ||
397 | *dword3 |= BD_TYPE_DS; | ||
398 | if (bdc->setup_pkt.bRequestType & USB_DIR_IN) | ||
399 | *dword3 |= BD_DIR_IN; | ||
400 | |||
401 | /* check if zlp will be needed */ | ||
402 | wValue = le16_to_cpu(bdc->setup_pkt.wValue); | ||
403 | if ((wValue > req_len) && | ||
404 | (req_len % bdc->gadget.ep0->maxpacket == 0)) { | ||
405 | dev_dbg(bdc->dev, "ZLP needed wVal:%d len:%d MaxP:%d\n", | ||
406 | wValue, req_len, | ||
407 | bdc->gadget.ep0->maxpacket); | ||
408 | bdc->zlp_needed = true; | ||
409 | } | ||
410 | break; | ||
411 | |||
412 | case WAIT_FOR_STATUS_START: | ||
413 | *dword3 |= BD_TYPE_SS; | ||
414 | if (!le16_to_cpu(bdc->setup_pkt.wLength) || | ||
415 | !(bdc->setup_pkt.bRequestType & USB_DIR_IN)) | ||
416 | *dword3 |= BD_DIR_IN; | ||
417 | break; | ||
418 | default: | ||
419 | dev_err(bdc->dev, | ||
420 | "Unknown ep0 state for queueing bd ep0_state:%s\n", | ||
421 | ep0_state_string[bdc->ep0_state]); | ||
422 | return -EINVAL; | ||
423 | } | ||
424 | |||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | /* Setup the bd dma descriptor for a given request */ | ||
429 | static int setup_bd_list_xfr(struct bdc *bdc, struct bdc_req *req, int num_bds) | ||
430 | { | ||
431 | dma_addr_t buf_add = req->usb_req.dma; | ||
432 | u32 maxp, tfs, dword2, dword3; | ||
433 | struct bd_transfer *bd_xfr; | ||
434 | struct bd_list *bd_list; | ||
435 | struct bdc_ep *ep; | ||
436 | struct bdc_bd *bd; | ||
437 | int ret, bdnum; | ||
438 | u32 req_len; | ||
439 | |||
440 | ep = req->ep; | ||
441 | bd_list = &ep->bd_list; | ||
442 | bd_xfr = &req->bd_xfr; | ||
443 | bd_xfr->req = req; | ||
444 | bd_xfr->start_bdi = bd_list->eqp_bdi; | ||
445 | bd = bdi_to_bd(ep, bd_list->eqp_bdi); | ||
446 | req_len = req->usb_req.length; | ||
447 | maxp = usb_endpoint_maxp(ep->desc) & 0x7ff; | ||
448 | tfs = roundup(req->usb_req.length, maxp); | ||
449 | tfs = tfs/maxp; | ||
450 | dev_vdbg(bdc->dev, "%s ep:%s num_bds:%d tfs:%d r_len:%d bd:%p\n", | ||
451 | __func__, ep->name, num_bds, tfs, req_len, bd); | ||
452 | |||
453 | for (bdnum = 0; bdnum < num_bds; bdnum++) { | ||
454 | dword2 = dword3 = 0; | ||
455 | /* First bd */ | ||
456 | if (!bdnum) { | ||
457 | dword3 |= BD_SOT|BD_SBF|(tfs<<BD_TFS_SHIFT); | ||
458 | dword2 |= BD_LTF; | ||
459 | /* format of first bd for ep0 is different than other */ | ||
460 | if (ep->ep_num == 1) | ||
461 | ret = setup_first_bd_ep0(bdc, req, &dword3); | ||
462 | if (ret) | ||
463 | return ret; | ||
464 | } | ||
465 | if (!req->ep->dir) | ||
466 | dword3 |= BD_ISP; | ||
467 | |||
468 | if (req_len > BD_MAX_BUFF_SIZE) { | ||
469 | dword2 |= BD_MAX_BUFF_SIZE; | ||
470 | req_len -= BD_MAX_BUFF_SIZE; | ||
471 | } else { | ||
472 | /* this should be the last bd */ | ||
473 | dword2 |= req_len; | ||
474 | dword3 |= BD_IOC; | ||
475 | dword3 |= BD_EOT; | ||
476 | } | ||
477 | /* Currently only 1 INT target is supported */ | ||
478 | dword2 |= BD_INTR_TARGET(0); | ||
479 | bd = bdi_to_bd(ep, ep->bd_list.eqp_bdi); | ||
480 | if (unlikely(!bd)) { | ||
481 | dev_err(bdc->dev, "Err bd pointing to wrong addr\n"); | ||
482 | return -EINVAL; | ||
483 | } | ||
484 | /* write bd */ | ||
485 | bd->offset[0] = cpu_to_le32(lower_32_bits(buf_add)); | ||
486 | bd->offset[1] = cpu_to_le32(upper_32_bits(buf_add)); | ||
487 | bd->offset[2] = cpu_to_le32(dword2); | ||
488 | bd->offset[3] = cpu_to_le32(dword3); | ||
489 | /* advance eqp pointer */ | ||
490 | ep_bdlist_eqp_adv(ep); | ||
491 | /* advance the buff pointer */ | ||
492 | buf_add += BD_MAX_BUFF_SIZE; | ||
493 | dev_vdbg(bdc->dev, "buf_add:%08llx req_len:%d bd:%p eqp:%d\n", | ||
494 | (unsigned long long)buf_add, req_len, bd, | ||
495 | ep->bd_list.eqp_bdi); | ||
496 | bd = bdi_to_bd(ep, ep->bd_list.eqp_bdi); | ||
497 | bd->offset[3] = cpu_to_le32(BD_SBF); | ||
498 | } | ||
499 | /* clear the STOP BD fetch bit from the first bd of this xfr */ | ||
500 | bd = bdi_to_bd(ep, bd_xfr->start_bdi); | ||
501 | bd->offset[3] &= cpu_to_le32(~BD_SBF); | ||
502 | /* the new eqp will be next hw dqp */ | ||
503 | bd_xfr->num_bds = num_bds; | ||
504 | bd_xfr->next_hwd_bdi = ep->bd_list.eqp_bdi; | ||
505 | /* everything is written correctly before notifying the HW */ | ||
506 | wmb(); | ||
507 | |||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | /* Queue the xfr */ | ||
512 | static int bdc_queue_xfr(struct bdc *bdc, struct bdc_req *req) | ||
513 | { | ||
514 | int num_bds, bd_available; | ||
515 | struct bdc_ep *ep; | ||
516 | int ret; | ||
517 | |||
518 | ep = req->ep; | ||
519 | dev_dbg(bdc->dev, "%s req:%p\n", __func__, req); | ||
520 | dev_dbg(bdc->dev, "eqp_bdi:%d hwd_bdi:%d\n", | ||
521 | ep->bd_list.eqp_bdi, ep->bd_list.hwd_bdi); | ||
522 | |||
523 | num_bds = bd_needed_req(req); | ||
524 | bd_available = bd_available_ep(ep); | ||
525 | |||
526 | /* how many bd's are avaialble on ep */ | ||
527 | if (num_bds > bd_available) | ||
528 | return -ENOMEM; | ||
529 | |||
530 | ret = setup_bd_list_xfr(bdc, req, num_bds); | ||
531 | if (ret) | ||
532 | return ret; | ||
533 | list_add_tail(&req->queue, &ep->queue); | ||
534 | bdc_dbg_bd_list(bdc, ep); | ||
535 | bdc_notify_xfr(bdc, ep->ep_num); | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | /* callback to gadget layer when xfr completes */ | ||
541 | static void bdc_req_complete(struct bdc_ep *ep, struct bdc_req *req, | ||
542 | int status) | ||
543 | { | ||
544 | struct bdc *bdc = ep->bdc; | ||
545 | |||
546 | if (req == NULL || &req->queue == NULL || &req->usb_req == NULL) | ||
547 | return; | ||
548 | |||
549 | dev_dbg(bdc->dev, "%s ep:%s status:%d\n", __func__, ep->name, status); | ||
550 | list_del(&req->queue); | ||
551 | req->usb_req.status = status; | ||
552 | usb_gadget_unmap_request(&bdc->gadget, &req->usb_req, ep->dir); | ||
553 | if (req->usb_req.complete) { | ||
554 | spin_unlock(&bdc->lock); | ||
555 | usb_gadget_giveback_request(&ep->usb_ep, &req->usb_req); | ||
556 | spin_lock(&bdc->lock); | ||
557 | } | ||
558 | } | ||
559 | |||
560 | /* Disable the endpoint */ | ||
561 | int bdc_ep_disable(struct bdc_ep *ep) | ||
562 | { | ||
563 | struct bdc_req *req; | ||
564 | struct bdc *bdc; | ||
565 | int ret; | ||
566 | |||
567 | ret = 0; | ||
568 | bdc = ep->bdc; | ||
569 | dev_dbg(bdc->dev, "%s() ep->ep_num=%d\n", __func__, ep->ep_num); | ||
570 | /* Stop the endpoint */ | ||
571 | ret = bdc_stop_ep(bdc, ep->ep_num); | ||
572 | |||
573 | /* | ||
574 | * Intentionally don't check the ret value of stop, it can fail in | ||
575 | * disconnect scenarios, continue with dconfig | ||
576 | */ | ||
577 | /* de-queue any pending requests */ | ||
578 | while (!list_empty(&ep->queue)) { | ||
579 | req = list_entry(ep->queue.next, struct bdc_req, | ||
580 | queue); | ||
581 | bdc_req_complete(ep, req, -ESHUTDOWN); | ||
582 | } | ||
583 | /* deconfigure the endpoint */ | ||
584 | ret = bdc_dconfig_ep(bdc, ep); | ||
585 | if (ret) | ||
586 | dev_warn(bdc->dev, | ||
587 | "dconfig fail but continue with memory free"); | ||
588 | |||
589 | ep->flags = 0; | ||
590 | /* ep0 memory is not freed, but reused on next connect sr */ | ||
591 | if (ep->ep_num == 1) | ||
592 | return 0; | ||
593 | |||
594 | /* Free the bdl memory */ | ||
595 | ep_bd_list_free(ep, ep->bd_list.num_tabs); | ||
596 | ep->desc = NULL; | ||
597 | ep->comp_desc = NULL; | ||
598 | ep->usb_ep.desc = NULL; | ||
599 | ep->ep_type = 0; | ||
600 | |||
601 | return ret; | ||
602 | } | ||
603 | |||
604 | /* Enable the ep */ | ||
605 | int bdc_ep_enable(struct bdc_ep *ep) | ||
606 | { | ||
607 | struct bdc *bdc; | ||
608 | int ret = 0; | ||
609 | |||
610 | bdc = ep->bdc; | ||
611 | dev_dbg(bdc->dev, "%s NUM_TABLES:%d %d\n", | ||
612 | __func__, NUM_TABLES, NUM_TABLES_ISOCH); | ||
613 | |||
614 | ret = ep_bd_list_alloc(ep); | ||
615 | if (ret) { | ||
616 | dev_err(bdc->dev, "ep bd list allocation failed:%d\n", ret); | ||
617 | return -ENOMEM; | ||
618 | } | ||
619 | bdc_dbg_bd_list(bdc, ep); | ||
620 | /* only for ep0: config ep is called for ep0 from connect event */ | ||
621 | ep->flags |= BDC_EP_ENABLED; | ||
622 | if (ep->ep_num == 1) | ||
623 | return ret; | ||
624 | |||
625 | /* Issue a configure endpoint command */ | ||
626 | ret = bdc_config_ep(bdc, ep); | ||
627 | if (ret) | ||
628 | return ret; | ||
629 | |||
630 | ep->usb_ep.maxpacket = usb_endpoint_maxp(ep->desc); | ||
631 | ep->usb_ep.desc = ep->desc; | ||
632 | ep->usb_ep.comp_desc = ep->comp_desc; | ||
633 | ep->ep_type = usb_endpoint_type(ep->desc); | ||
634 | ep->flags |= BDC_EP_ENABLED; | ||
635 | |||
636 | return 0; | ||
637 | } | ||
638 | |||
639 | /* EP0 related code */ | ||
640 | |||
641 | /* Queue a status stage BD */ | ||
642 | static int ep0_queue_status_stage(struct bdc *bdc) | ||
643 | { | ||
644 | struct bdc_req *status_req; | ||
645 | struct bdc_ep *ep; | ||
646 | |||
647 | status_req = &bdc->status_req; | ||
648 | ep = bdc->bdc_ep_array[1]; | ||
649 | status_req->ep = ep; | ||
650 | status_req->usb_req.length = 0; | ||
651 | status_req->usb_req.status = -EINPROGRESS; | ||
652 | status_req->usb_req.actual = 0; | ||
653 | status_req->usb_req.complete = NULL; | ||
654 | bdc_queue_xfr(bdc, status_req); | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | /* Queue xfr on ep0 */ | ||
660 | static int ep0_queue(struct bdc_ep *ep, struct bdc_req *req) | ||
661 | { | ||
662 | struct bdc *bdc; | ||
663 | int ret; | ||
664 | |||
665 | bdc = ep->bdc; | ||
666 | dev_dbg(bdc->dev, "%s()\n", __func__); | ||
667 | req->usb_req.actual = 0; | ||
668 | req->usb_req.status = -EINPROGRESS; | ||
669 | req->epnum = ep->ep_num; | ||
670 | |||
671 | if (bdc->delayed_status) { | ||
672 | bdc->delayed_status = false; | ||
673 | /* if status stage was delayed? */ | ||
674 | if (bdc->ep0_state == WAIT_FOR_STATUS_START) { | ||
675 | /* Queue a status stage BD */ | ||
676 | ep0_queue_status_stage(bdc); | ||
677 | bdc->ep0_state = WAIT_FOR_STATUS_XMIT; | ||
678 | return 0; | ||
679 | } | ||
680 | } else { | ||
681 | /* | ||
682 | * if delayed status is false and 0 length transfer is requested | ||
683 | * i.e. for status stage of some setup request, then just | ||
684 | * return from here the status stage is queued independently | ||
685 | */ | ||
686 | if (req->usb_req.length == 0) | ||
687 | return 0; | ||
688 | |||
689 | } | ||
690 | ret = usb_gadget_map_request(&bdc->gadget, &req->usb_req, ep->dir); | ||
691 | if (ret) { | ||
692 | dev_err(bdc->dev, "dma mapping failed %s\n", ep->name); | ||
693 | return ret; | ||
694 | } | ||
695 | |||
696 | return bdc_queue_xfr(bdc, req); | ||
697 | } | ||
698 | |||
699 | /* Queue data stage */ | ||
700 | static int ep0_queue_data_stage(struct bdc *bdc) | ||
701 | { | ||
702 | struct usb_request *ep0_usb_req; | ||
703 | struct bdc_ep *ep; | ||
704 | |||
705 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
706 | ep0_usb_req = &bdc->ep0_req.usb_req; | ||
707 | ep = bdc->bdc_ep_array[1]; | ||
708 | bdc->ep0_req.ep = ep; | ||
709 | bdc->ep0_req.usb_req.complete = NULL; | ||
710 | |||
711 | return ep0_queue(ep, &bdc->ep0_req); | ||
712 | } | ||
713 | |||
714 | /* Queue req on ep */ | ||
715 | static int ep_queue(struct bdc_ep *ep, struct bdc_req *req) | ||
716 | { | ||
717 | struct bdc *bdc; | ||
718 | int ret = 0; | ||
719 | |||
720 | bdc = ep->bdc; | ||
721 | if (!req || !ep || !ep->usb_ep.desc) | ||
722 | return -EINVAL; | ||
723 | |||
724 | req->usb_req.actual = 0; | ||
725 | req->usb_req.status = -EINPROGRESS; | ||
726 | req->epnum = ep->ep_num; | ||
727 | |||
728 | ret = usb_gadget_map_request(&bdc->gadget, &req->usb_req, ep->dir); | ||
729 | if (ret) { | ||
730 | dev_err(bdc->dev, "dma mapping failed\n"); | ||
731 | return ret; | ||
732 | } | ||
733 | |||
734 | return bdc_queue_xfr(bdc, req); | ||
735 | } | ||
736 | |||
737 | /* Dequeue a request from ep */ | ||
738 | static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req) | ||
739 | { | ||
740 | int start_bdi, end_bdi, tbi, eqp_bdi, curr_hw_dqpi; | ||
741 | bool start_pending, end_pending; | ||
742 | bool first_remove = false; | ||
743 | struct bdc_req *first_req; | ||
744 | struct bdc_bd *bd_start; | ||
745 | struct bd_table *table; | ||
746 | dma_addr_t next_bd_dma; | ||
747 | u64 deq_ptr_64 = 0; | ||
748 | struct bdc *bdc; | ||
749 | u32 tmp_32; | ||
750 | int ret; | ||
751 | |||
752 | bdc = ep->bdc; | ||
753 | start_pending = end_pending = false; | ||
754 | eqp_bdi = ep->bd_list.eqp_bdi - 1; | ||
755 | |||
756 | if (eqp_bdi < 0) | ||
757 | eqp_bdi = ep->bd_list.max_bdi; | ||
758 | |||
759 | start_bdi = req->bd_xfr.start_bdi; | ||
760 | end_bdi = find_end_bdi(ep, req->bd_xfr.next_hwd_bdi); | ||
761 | |||
762 | dev_dbg(bdc->dev, "%s ep:%s start:%d end:%d\n", | ||
763 | __func__, ep->name, start_bdi, end_bdi); | ||
764 | dev_dbg(bdc->dev, "ep_dequeue ep=%p ep->desc=%p\n", | ||
765 | ep, (void *)ep->usb_ep.desc); | ||
766 | /* Stop the ep to see where the HW is ? */ | ||
767 | ret = bdc_stop_ep(bdc, ep->ep_num); | ||
768 | /* if there is an issue with stopping ep, then no need to go further */ | ||
769 | if (ret) | ||
770 | return 0; | ||
771 | |||
772 | /* | ||
773 | * After endpoint is stopped, there can be 3 cases, the request | ||
774 | * is processed, pending or in the middle of processing | ||
775 | */ | ||
776 | |||
777 | /* The current hw dequeue pointer */ | ||
778 | tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(0)); | ||
779 | deq_ptr_64 = tmp_32; | ||
780 | tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(1)); | ||
781 | deq_ptr_64 |= ((u64)tmp_32 << 32); | ||
782 | |||
783 | /* we have the dma addr of next bd that will be fetched by hardware */ | ||
784 | curr_hw_dqpi = bd_add_to_bdi(ep, deq_ptr_64); | ||
785 | if (curr_hw_dqpi < 0) | ||
786 | return curr_hw_dqpi; | ||
787 | |||
788 | /* | ||
789 | * curr_hw_dqpi points to actual dqp of HW and HW owns bd's from | ||
790 | * curr_hw_dqbdi..eqp_bdi. | ||
791 | */ | ||
792 | |||
793 | /* Check if start_bdi and end_bdi are in range of HW owned BD's */ | ||
794 | if (curr_hw_dqpi > eqp_bdi) { | ||
795 | /* there is a wrap from last to 0 */ | ||
796 | if (start_bdi >= curr_hw_dqpi || start_bdi <= eqp_bdi) { | ||
797 | start_pending = true; | ||
798 | end_pending = true; | ||
799 | } else if (end_bdi >= curr_hw_dqpi || end_bdi <= eqp_bdi) { | ||
800 | end_pending = true; | ||
801 | } | ||
802 | } else { | ||
803 | if (start_bdi >= curr_hw_dqpi) { | ||
804 | start_pending = true; | ||
805 | end_pending = true; | ||
806 | } else if (end_bdi >= curr_hw_dqpi) { | ||
807 | end_pending = true; | ||
808 | } | ||
809 | } | ||
810 | dev_dbg(bdc->dev, | ||
811 | "start_pending:%d end_pending:%d speed:%d\n", | ||
812 | start_pending, end_pending, bdc->gadget.speed); | ||
813 | |||
814 | /* If both start till end are processes, we cannot deq req */ | ||
815 | if (!start_pending && !end_pending) | ||
816 | return -EINVAL; | ||
817 | |||
818 | /* | ||
819 | * if ep_dequeue is called after disconnect then just return | ||
820 | * success from here | ||
821 | */ | ||
822 | if (bdc->gadget.speed == USB_SPEED_UNKNOWN) | ||
823 | return 0; | ||
824 | tbi = bdi_to_tbi(ep, req->bd_xfr.next_hwd_bdi); | ||
825 | table = ep->bd_list.bd_table_array[tbi]; | ||
826 | next_bd_dma = table->dma + | ||
827 | sizeof(struct bdc_bd)*(req->bd_xfr.next_hwd_bdi - | ||
828 | tbi * ep->bd_list.num_bds_table); | ||
829 | |||
830 | first_req = list_first_entry(&ep->queue, struct bdc_req, | ||
831 | queue); | ||
832 | |||
833 | if (req == first_req) | ||
834 | first_remove = true; | ||
835 | |||
836 | /* | ||
837 | * Due to HW limitation we need to bypadd chain bd's and issue ep_bla, | ||
838 | * incase if start is pending this is the first request in the list | ||
839 | * then issue ep_bla instead of marking as chain bd | ||
840 | */ | ||
841 | if (start_pending && !first_remove) { | ||
842 | /* | ||
843 | * Mark the start bd as Chain bd, and point the chain | ||
844 | * bd to next_bd_dma | ||
845 | */ | ||
846 | bd_start = bdi_to_bd(ep, start_bdi); | ||
847 | bd_start->offset[0] = cpu_to_le32(lower_32_bits(next_bd_dma)); | ||
848 | bd_start->offset[1] = cpu_to_le32(upper_32_bits(next_bd_dma)); | ||
849 | bd_start->offset[2] = 0x0; | ||
850 | bd_start->offset[3] = cpu_to_le32(MARK_CHAIN_BD); | ||
851 | bdc_dbg_bd_list(bdc, ep); | ||
852 | } else if (end_pending) { | ||
853 | /* | ||
854 | * The transfer is stopped in the middle, move the | ||
855 | * HW deq pointer to next_bd_dma | ||
856 | */ | ||
857 | ret = bdc_ep_bla(bdc, ep, next_bd_dma); | ||
858 | if (ret) { | ||
859 | dev_err(bdc->dev, "error in ep_bla:%d\n", ret); | ||
860 | return ret; | ||
861 | } | ||
862 | } | ||
863 | |||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | /* Halt/Clear the ep based on value */ | ||
868 | static int ep_set_halt(struct bdc_ep *ep, u32 value) | ||
869 | { | ||
870 | struct bdc *bdc; | ||
871 | int ret; | ||
872 | |||
873 | bdc = ep->bdc; | ||
874 | dev_dbg(bdc->dev, "%s ep:%s value=%d\n", __func__, ep->name, value); | ||
875 | |||
876 | if (value) { | ||
877 | dev_dbg(bdc->dev, "Halt\n"); | ||
878 | if (ep->ep_num == 1) | ||
879 | bdc->ep0_state = WAIT_FOR_SETUP; | ||
880 | |||
881 | ret = bdc_ep_set_stall(bdc, ep->ep_num); | ||
882 | if (ret) | ||
883 | dev_err(bdc->dev, "failed to %s STALL on %s\n", | ||
884 | value ? "set" : "clear", ep->name); | ||
885 | else | ||
886 | ep->flags |= BDC_EP_STALL; | ||
887 | } else { | ||
888 | /* Clear */ | ||
889 | dev_dbg(bdc->dev, "Before Clear\n"); | ||
890 | ret = bdc_ep_clear_stall(bdc, ep->ep_num); | ||
891 | if (ret) | ||
892 | dev_err(bdc->dev, "failed to %s STALL on %s\n", | ||
893 | value ? "set" : "clear", ep->name); | ||
894 | else | ||
895 | ep->flags &= ~BDC_EP_STALL; | ||
896 | dev_dbg(bdc->dev, "After Clear\n"); | ||
897 | } | ||
898 | |||
899 | return ret; | ||
900 | } | ||
901 | |||
902 | /* Free all the ep */ | ||
903 | void bdc_free_ep(struct bdc *bdc) | ||
904 | { | ||
905 | struct bdc_ep *ep; | ||
906 | u8 epnum; | ||
907 | |||
908 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
909 | for (epnum = 1; epnum < bdc->num_eps; epnum++) { | ||
910 | ep = bdc->bdc_ep_array[epnum]; | ||
911 | if (!ep) | ||
912 | continue; | ||
913 | |||
914 | if (ep->flags & BDC_EP_ENABLED) | ||
915 | ep_bd_list_free(ep, ep->bd_list.num_tabs); | ||
916 | |||
917 | /* ep0 is not in this gadget list */ | ||
918 | if (epnum != 1) | ||
919 | list_del(&ep->usb_ep.ep_list); | ||
920 | |||
921 | kfree(ep); | ||
922 | } | ||
923 | } | ||
924 | |||
925 | /* USB2 spec, section 7.1.20 */ | ||
926 | static int bdc_set_test_mode(struct bdc *bdc) | ||
927 | { | ||
928 | u32 usb2_pm; | ||
929 | |||
930 | usb2_pm = bdc_readl(bdc->regs, BDC_USPPM2); | ||
931 | usb2_pm &= ~BDC_PTC_MASK; | ||
932 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
933 | switch (bdc->test_mode) { | ||
934 | case TEST_J: | ||
935 | case TEST_K: | ||
936 | case TEST_SE0_NAK: | ||
937 | case TEST_PACKET: | ||
938 | case TEST_FORCE_EN: | ||
939 | usb2_pm |= bdc->test_mode << 28; | ||
940 | break; | ||
941 | default: | ||
942 | return -EINVAL; | ||
943 | } | ||
944 | dev_dbg(bdc->dev, "usb2_pm=%08x", usb2_pm); | ||
945 | bdc_writel(bdc->regs, BDC_USPPM2, usb2_pm); | ||
946 | |||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | /* | ||
951 | * Helper function to handle Transfer status report with status as either | ||
952 | * success or short | ||
953 | */ | ||
954 | static void handle_xsr_succ_status(struct bdc *bdc, struct bdc_ep *ep, | ||
955 | struct bdc_sr *sreport) | ||
956 | { | ||
957 | int short_bdi, start_bdi, end_bdi, max_len_bds, chain_bds; | ||
958 | struct bd_list *bd_list = &ep->bd_list; | ||
959 | int actual_length, length_short; | ||
960 | struct bd_transfer *bd_xfr; | ||
961 | struct bdc_bd *short_bd; | ||
962 | struct bdc_req *req; | ||
963 | u64 deq_ptr_64 = 0; | ||
964 | int status = 0; | ||
965 | int sr_status; | ||
966 | u32 tmp_32; | ||
967 | |||
968 | dev_dbg(bdc->dev, "%s ep:%p\n", __func__, ep); | ||
969 | bdc_dbg_srr(bdc, 0); | ||
970 | /* do not process thie sr if ignore flag is set */ | ||
971 | if (ep->ignore_next_sr) { | ||
972 | ep->ignore_next_sr = false; | ||
973 | return; | ||
974 | } | ||
975 | |||
976 | if (unlikely(list_empty(&ep->queue))) { | ||
977 | dev_warn(bdc->dev, "xfr srr with no BD's queued\n"); | ||
978 | return; | ||
979 | } | ||
980 | req = list_entry(ep->queue.next, struct bdc_req, | ||
981 | queue); | ||
982 | |||
983 | bd_xfr = &req->bd_xfr; | ||
984 | sr_status = XSF_STS(le32_to_cpu(sreport->offset[3])); | ||
985 | |||
986 | /* | ||
987 | * sr_status is short and this transfer has more than 1 bd then it needs | ||
988 | * special handling, this is only applicable for bulk and ctrl | ||
989 | */ | ||
990 | if (sr_status == XSF_SHORT && bd_xfr->num_bds > 1) { | ||
991 | /* | ||
992 | * This is multi bd xfr, lets see which bd | ||
993 | * caused short transfer and how many bytes have been | ||
994 | * transferred so far. | ||
995 | */ | ||
996 | tmp_32 = le32_to_cpu(sreport->offset[0]); | ||
997 | deq_ptr_64 = tmp_32; | ||
998 | tmp_32 = le32_to_cpu(sreport->offset[1]); | ||
999 | deq_ptr_64 |= ((u64)tmp_32 << 32); | ||
1000 | short_bdi = bd_add_to_bdi(ep, deq_ptr_64); | ||
1001 | if (unlikely(short_bdi < 0)) | ||
1002 | dev_warn(bdc->dev, "bd doesn't exist?\n"); | ||
1003 | |||
1004 | start_bdi = bd_xfr->start_bdi; | ||
1005 | /* | ||
1006 | * We know the start_bdi and short_bdi, how many xfr | ||
1007 | * bds in between | ||
1008 | */ | ||
1009 | if (start_bdi <= short_bdi) { | ||
1010 | max_len_bds = short_bdi - start_bdi; | ||
1011 | if (max_len_bds <= bd_list->num_bds_table) { | ||
1012 | if (!(bdi_to_tbi(ep, start_bdi) == | ||
1013 | bdi_to_tbi(ep, short_bdi))) | ||
1014 | max_len_bds--; | ||
1015 | } else { | ||
1016 | chain_bds = max_len_bds/bd_list->num_bds_table; | ||
1017 | max_len_bds -= chain_bds; | ||
1018 | } | ||
1019 | } else { | ||
1020 | /* there is a wrap in the ring within a xfr */ | ||
1021 | chain_bds = (bd_list->max_bdi - start_bdi)/ | ||
1022 | bd_list->num_bds_table; | ||
1023 | chain_bds += short_bdi/bd_list->num_bds_table; | ||
1024 | max_len_bds = bd_list->max_bdi - start_bdi; | ||
1025 | max_len_bds += short_bdi; | ||
1026 | max_len_bds -= chain_bds; | ||
1027 | } | ||
1028 | /* max_len_bds is the number of full length bds */ | ||
1029 | end_bdi = find_end_bdi(ep, bd_xfr->next_hwd_bdi); | ||
1030 | if (!(end_bdi == short_bdi)) | ||
1031 | ep->ignore_next_sr = true; | ||
1032 | |||
1033 | actual_length = max_len_bds * BD_MAX_BUFF_SIZE; | ||
1034 | short_bd = bdi_to_bd(ep, short_bdi); | ||
1035 | /* length queued */ | ||
1036 | length_short = le32_to_cpu(short_bd->offset[2]) & 0x1FFFFF; | ||
1037 | /* actual length trensfered */ | ||
1038 | length_short -= SR_BD_LEN(le32_to_cpu(sreport->offset[2])); | ||
1039 | actual_length += length_short; | ||
1040 | req->usb_req.actual = actual_length; | ||
1041 | } else { | ||
1042 | req->usb_req.actual = req->usb_req.length - | ||
1043 | SR_BD_LEN(le32_to_cpu(sreport->offset[2])); | ||
1044 | dev_dbg(bdc->dev, | ||
1045 | "len=%d actual=%d bd_xfr->next_hwd_bdi:%d\n", | ||
1046 | req->usb_req.length, req->usb_req.actual, | ||
1047 | bd_xfr->next_hwd_bdi); | ||
1048 | } | ||
1049 | |||
1050 | /* Update the dequeue pointer */ | ||
1051 | ep->bd_list.hwd_bdi = bd_xfr->next_hwd_bdi; | ||
1052 | if (req->usb_req.actual < req->usb_req.length) { | ||
1053 | dev_dbg(bdc->dev, "short xfr on %d\n", ep->ep_num); | ||
1054 | if (req->usb_req.short_not_ok) | ||
1055 | status = -EREMOTEIO; | ||
1056 | } | ||
1057 | bdc_req_complete(ep, bd_xfr->req, status); | ||
1058 | } | ||
1059 | |||
1060 | /* EP0 setup related packet handlers */ | ||
1061 | |||
1062 | /* | ||
1063 | * Setup packet received, just store the packet and process on next DS or SS | ||
1064 | * started SR | ||
1065 | */ | ||
1066 | void bdc_xsf_ep0_setup_recv(struct bdc *bdc, struct bdc_sr *sreport) | ||
1067 | { | ||
1068 | struct usb_ctrlrequest *setup_pkt; | ||
1069 | u32 len; | ||
1070 | |||
1071 | dev_dbg(bdc->dev, | ||
1072 | "%s ep0_state:%s\n", | ||
1073 | __func__, ep0_state_string[bdc->ep0_state]); | ||
1074 | /* Store received setup packet */ | ||
1075 | setup_pkt = &bdc->setup_pkt; | ||
1076 | memcpy(setup_pkt, &sreport->offset[0], sizeof(*setup_pkt)); | ||
1077 | len = le16_to_cpu(setup_pkt->wLength); | ||
1078 | if (!len) | ||
1079 | bdc->ep0_state = WAIT_FOR_STATUS_START; | ||
1080 | else | ||
1081 | bdc->ep0_state = WAIT_FOR_DATA_START; | ||
1082 | |||
1083 | |||
1084 | dev_dbg(bdc->dev, | ||
1085 | "%s exit ep0_state:%s\n", | ||
1086 | __func__, ep0_state_string[bdc->ep0_state]); | ||
1087 | } | ||
1088 | |||
1089 | /* Stall ep0 */ | ||
1090 | static void ep0_stall(struct bdc *bdc) | ||
1091 | { | ||
1092 | struct bdc_ep *ep = bdc->bdc_ep_array[1]; | ||
1093 | struct bdc_req *req; | ||
1094 | |||
1095 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
1096 | bdc->delayed_status = false; | ||
1097 | ep_set_halt(ep, 1); | ||
1098 | |||
1099 | /* de-queue any pendig requests */ | ||
1100 | while (!list_empty(&ep->queue)) { | ||
1101 | req = list_entry(ep->queue.next, struct bdc_req, | ||
1102 | queue); | ||
1103 | bdc_req_complete(ep, req, -ESHUTDOWN); | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1107 | /* SET_ADD handlers */ | ||
1108 | static int ep0_set_address(struct bdc *bdc, struct usb_ctrlrequest *ctrl) | ||
1109 | { | ||
1110 | enum usb_device_state state = bdc->gadget.state; | ||
1111 | int ret = 0; | ||
1112 | u32 addr; | ||
1113 | |||
1114 | addr = le16_to_cpu(ctrl->wValue); | ||
1115 | dev_dbg(bdc->dev, | ||
1116 | "%s addr:%d dev state:%d\n", | ||
1117 | __func__, addr, state); | ||
1118 | |||
1119 | if (addr > 127) | ||
1120 | return -EINVAL; | ||
1121 | |||
1122 | switch (state) { | ||
1123 | case USB_STATE_DEFAULT: | ||
1124 | case USB_STATE_ADDRESS: | ||
1125 | /* Issue Address device command */ | ||
1126 | ret = bdc_address_device(bdc, addr); | ||
1127 | if (ret) | ||
1128 | return ret; | ||
1129 | |||
1130 | if (addr) | ||
1131 | usb_gadget_set_state(&bdc->gadget, USB_STATE_ADDRESS); | ||
1132 | else | ||
1133 | usb_gadget_set_state(&bdc->gadget, USB_STATE_DEFAULT); | ||
1134 | |||
1135 | bdc->dev_addr = addr; | ||
1136 | break; | ||
1137 | default: | ||
1138 | dev_warn(bdc->dev, | ||
1139 | "SET Address in wrong device state %d\n", | ||
1140 | state); | ||
1141 | ret = -EINVAL; | ||
1142 | } | ||
1143 | |||
1144 | return ret; | ||
1145 | } | ||
1146 | |||
1147 | /* Handler for SET/CLEAR FEATURE requests for device */ | ||
1148 | static int ep0_handle_feature_dev(struct bdc *bdc, u16 wValue, | ||
1149 | u16 wIndex, bool set) | ||
1150 | { | ||
1151 | enum usb_device_state state = bdc->gadget.state; | ||
1152 | u32 usppms = 0; | ||
1153 | |||
1154 | dev_dbg(bdc->dev, "%s set:%d dev state:%d\n", | ||
1155 | __func__, set, state); | ||
1156 | switch (wValue) { | ||
1157 | case USB_DEVICE_REMOTE_WAKEUP: | ||
1158 | dev_dbg(bdc->dev, "USB_DEVICE_REMOTE_WAKEUP\n"); | ||
1159 | if (set) | ||
1160 | bdc->devstatus |= REMOTE_WAKE_ENABLE; | ||
1161 | else | ||
1162 | bdc->devstatus &= ~REMOTE_WAKE_ENABLE; | ||
1163 | break; | ||
1164 | |||
1165 | case USB_DEVICE_TEST_MODE: | ||
1166 | dev_dbg(bdc->dev, "USB_DEVICE_TEST_MODE\n"); | ||
1167 | if ((wIndex & 0xFF) || | ||
1168 | (bdc->gadget.speed != USB_SPEED_HIGH) || !set) | ||
1169 | return -EINVAL; | ||
1170 | |||
1171 | bdc->test_mode = wIndex >> 8; | ||
1172 | break; | ||
1173 | |||
1174 | case USB_DEVICE_U1_ENABLE: | ||
1175 | dev_dbg(bdc->dev, "USB_DEVICE_U1_ENABLE\n"); | ||
1176 | |||
1177 | if (bdc->gadget.speed != USB_SPEED_SUPER || | ||
1178 | state != USB_STATE_CONFIGURED) | ||
1179 | return -EINVAL; | ||
1180 | |||
1181 | usppms = bdc_readl(bdc->regs, BDC_USPPMS); | ||
1182 | if (set) { | ||
1183 | /* clear previous u1t */ | ||
1184 | usppms &= ~BDC_U1T(BDC_U1T_MASK); | ||
1185 | usppms |= BDC_U1T(U1_TIMEOUT); | ||
1186 | usppms |= BDC_U1E | BDC_PORT_W1S; | ||
1187 | bdc->devstatus |= (1 << USB_DEV_STAT_U1_ENABLED); | ||
1188 | } else { | ||
1189 | usppms &= ~BDC_U1E; | ||
1190 | usppms |= BDC_PORT_W1S; | ||
1191 | bdc->devstatus &= ~(1 << USB_DEV_STAT_U1_ENABLED); | ||
1192 | } | ||
1193 | bdc_writel(bdc->regs, BDC_USPPMS, usppms); | ||
1194 | break; | ||
1195 | |||
1196 | case USB_DEVICE_U2_ENABLE: | ||
1197 | dev_dbg(bdc->dev, "USB_DEVICE_U2_ENABLE\n"); | ||
1198 | |||
1199 | if (bdc->gadget.speed != USB_SPEED_SUPER || | ||
1200 | state != USB_STATE_CONFIGURED) | ||
1201 | return -EINVAL; | ||
1202 | |||
1203 | usppms = bdc_readl(bdc->regs, BDC_USPPMS); | ||
1204 | if (set) { | ||
1205 | usppms |= BDC_U2E; | ||
1206 | usppms |= BDC_U2A; | ||
1207 | bdc->devstatus |= (1 << USB_DEV_STAT_U2_ENABLED); | ||
1208 | } else { | ||
1209 | usppms &= ~BDC_U2E; | ||
1210 | usppms &= ~BDC_U2A; | ||
1211 | bdc->devstatus &= ~(1 << USB_DEV_STAT_U2_ENABLED); | ||
1212 | } | ||
1213 | bdc_writel(bdc->regs, BDC_USPPMS, usppms); | ||
1214 | break; | ||
1215 | |||
1216 | case USB_DEVICE_LTM_ENABLE: | ||
1217 | dev_dbg(bdc->dev, "USB_DEVICE_LTM_ENABLE?\n"); | ||
1218 | if (bdc->gadget.speed != USB_SPEED_SUPER || | ||
1219 | state != USB_STATE_CONFIGURED) | ||
1220 | return -EINVAL; | ||
1221 | break; | ||
1222 | default: | ||
1223 | dev_err(bdc->dev, "Unknown wValue:%d\n", wValue); | ||
1224 | return -EOPNOTSUPP; | ||
1225 | } /* USB_RECIP_DEVICE end */ | ||
1226 | |||
1227 | return 0; | ||
1228 | } | ||
1229 | |||
1230 | /* SET/CLEAR FEATURE handler */ | ||
1231 | static int ep0_handle_feature(struct bdc *bdc, | ||
1232 | struct usb_ctrlrequest *setup_pkt, bool set) | ||
1233 | { | ||
1234 | enum usb_device_state state = bdc->gadget.state; | ||
1235 | struct bdc_ep *ep; | ||
1236 | u16 wValue; | ||
1237 | u16 wIndex; | ||
1238 | int epnum; | ||
1239 | |||
1240 | wValue = le16_to_cpu(setup_pkt->wValue); | ||
1241 | wIndex = le16_to_cpu(setup_pkt->wIndex); | ||
1242 | |||
1243 | dev_dbg(bdc->dev, | ||
1244 | "%s wValue=%d wIndex=%d devstate=%08x speed=%d set=%d", | ||
1245 | __func__, wValue, wIndex, state, | ||
1246 | bdc->gadget.speed, set); | ||
1247 | |||
1248 | switch (setup_pkt->bRequestType & USB_RECIP_MASK) { | ||
1249 | case USB_RECIP_DEVICE: | ||
1250 | return ep0_handle_feature_dev(bdc, wValue, wIndex, set); | ||
1251 | case USB_RECIP_INTERFACE: | ||
1252 | dev_dbg(bdc->dev, "USB_RECIP_INTERFACE\n"); | ||
1253 | /* USB3 spec, sec 9.4.9 */ | ||
1254 | if (wValue != USB_INTRF_FUNC_SUSPEND) | ||
1255 | return -EINVAL; | ||
1256 | /* USB3 spec, Table 9-8 */ | ||
1257 | if (set) { | ||
1258 | if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) { | ||
1259 | dev_dbg(bdc->dev, "SET REMOTE_WAKEUP\n"); | ||
1260 | bdc->devstatus |= REMOTE_WAKE_ENABLE; | ||
1261 | } else { | ||
1262 | dev_dbg(bdc->dev, "CLEAR REMOTE_WAKEUP\n"); | ||
1263 | bdc->devstatus &= ~REMOTE_WAKE_ENABLE; | ||
1264 | } | ||
1265 | } | ||
1266 | break; | ||
1267 | |||
1268 | case USB_RECIP_ENDPOINT: | ||
1269 | dev_dbg(bdc->dev, "USB_RECIP_ENDPOINT\n"); | ||
1270 | if (wValue != USB_ENDPOINT_HALT) | ||
1271 | return -EINVAL; | ||
1272 | |||
1273 | epnum = wIndex & USB_ENDPOINT_NUMBER_MASK; | ||
1274 | if (epnum) { | ||
1275 | if ((wIndex & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) | ||
1276 | epnum = epnum * 2 + 1; | ||
1277 | else | ||
1278 | epnum *= 2; | ||
1279 | } else { | ||
1280 | epnum = 1; /*EP0*/ | ||
1281 | } | ||
1282 | /* | ||
1283 | * If CLEAR_FEATURE on ep0 then don't do anything as the stall | ||
1284 | * condition on ep0 has already been cleared when SETUP packet | ||
1285 | * was received. | ||
1286 | */ | ||
1287 | if (epnum == 1 && !set) { | ||
1288 | dev_dbg(bdc->dev, "ep0 stall already cleared\n"); | ||
1289 | return 0; | ||
1290 | } | ||
1291 | dev_dbg(bdc->dev, "epnum=%d\n", epnum); | ||
1292 | ep = bdc->bdc_ep_array[epnum]; | ||
1293 | if (!ep) | ||
1294 | return -EINVAL; | ||
1295 | |||
1296 | return ep_set_halt(ep, set); | ||
1297 | default: | ||
1298 | dev_err(bdc->dev, "Unknown recipient\n"); | ||
1299 | return -EINVAL; | ||
1300 | } | ||
1301 | |||
1302 | return 0; | ||
1303 | } | ||
1304 | |||
1305 | /* GET_STATUS request handler */ | ||
1306 | static int ep0_handle_status(struct bdc *bdc, | ||
1307 | struct usb_ctrlrequest *setup_pkt) | ||
1308 | { | ||
1309 | enum usb_device_state state = bdc->gadget.state; | ||
1310 | struct bdc_ep *ep; | ||
1311 | u16 usb_status = 0; | ||
1312 | u32 epnum; | ||
1313 | u16 wIndex; | ||
1314 | |||
1315 | /* USB2.0 spec sec 9.4.5 */ | ||
1316 | if (state == USB_STATE_DEFAULT) | ||
1317 | return -EINVAL; | ||
1318 | wIndex = le16_to_cpu(setup_pkt->wIndex); | ||
1319 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
1320 | usb_status = bdc->devstatus; | ||
1321 | switch (setup_pkt->bRequestType & USB_RECIP_MASK) { | ||
1322 | case USB_RECIP_DEVICE: | ||
1323 | dev_dbg(bdc->dev, | ||
1324 | "USB_RECIP_DEVICE devstatus:%08x\n", | ||
1325 | bdc->devstatus); | ||
1326 | /* USB3 spec, sec 9.4.5 */ | ||
1327 | if (bdc->gadget.speed == USB_SPEED_SUPER) | ||
1328 | usb_status &= ~REMOTE_WAKE_ENABLE; | ||
1329 | break; | ||
1330 | |||
1331 | case USB_RECIP_INTERFACE: | ||
1332 | dev_dbg(bdc->dev, "USB_RECIP_INTERFACE\n"); | ||
1333 | if (bdc->gadget.speed == USB_SPEED_SUPER) { | ||
1334 | /* | ||
1335 | * This should come from func for Func remote wkup | ||
1336 | * usb_status |=1; | ||
1337 | */ | ||
1338 | if (bdc->devstatus & REMOTE_WAKE_ENABLE) | ||
1339 | usb_status |= REMOTE_WAKE_ENABLE; | ||
1340 | } else { | ||
1341 | usb_status = 0; | ||
1342 | } | ||
1343 | |||
1344 | break; | ||
1345 | |||
1346 | case USB_RECIP_ENDPOINT: | ||
1347 | dev_dbg(bdc->dev, "USB_RECIP_ENDPOINT\n"); | ||
1348 | epnum = wIndex & USB_ENDPOINT_NUMBER_MASK; | ||
1349 | if (epnum) { | ||
1350 | if ((wIndex & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) | ||
1351 | epnum = epnum*2 + 1; | ||
1352 | else | ||
1353 | epnum *= 2; | ||
1354 | } else { | ||
1355 | epnum = 1; /* EP0 */ | ||
1356 | } | ||
1357 | |||
1358 | ep = bdc->bdc_ep_array[epnum]; | ||
1359 | if (!ep) { | ||
1360 | dev_err(bdc->dev, "ISSUE, GET_STATUS for invalid EP ?"); | ||
1361 | return -EINVAL; | ||
1362 | } | ||
1363 | if (ep->flags & BDC_EP_STALL) | ||
1364 | usb_status |= 1 << USB_ENDPOINT_HALT; | ||
1365 | |||
1366 | break; | ||
1367 | default: | ||
1368 | dev_err(bdc->dev, "Unknown recipient for get_status\n"); | ||
1369 | return -EINVAL; | ||
1370 | } | ||
1371 | /* prepare a data stage for GET_STATUS */ | ||
1372 | dev_dbg(bdc->dev, "usb_status=%08x\n", usb_status); | ||
1373 | *(__le16 *)bdc->ep0_response_buff = cpu_to_le16(usb_status); | ||
1374 | bdc->ep0_req.usb_req.length = 2; | ||
1375 | bdc->ep0_req.usb_req.buf = &bdc->ep0_response_buff; | ||
1376 | ep0_queue_data_stage(bdc); | ||
1377 | |||
1378 | return 0; | ||
1379 | } | ||
1380 | |||
1381 | static void ep0_set_sel_cmpl(struct usb_ep *_ep, struct usb_request *_req) | ||
1382 | { | ||
1383 | /* ep0_set_sel_cmpl */ | ||
1384 | } | ||
1385 | |||
1386 | /* Queue data stage to handle 6 byte SET_SEL request */ | ||
1387 | static int ep0_set_sel(struct bdc *bdc, | ||
1388 | struct usb_ctrlrequest *setup_pkt) | ||
1389 | { | ||
1390 | struct bdc_ep *ep; | ||
1391 | u16 wLength; | ||
1392 | u16 wValue; | ||
1393 | |||
1394 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
1395 | wValue = le16_to_cpu(setup_pkt->wValue); | ||
1396 | wLength = le16_to_cpu(setup_pkt->wLength); | ||
1397 | if (unlikely(wLength != 6)) { | ||
1398 | dev_err(bdc->dev, "%s Wrong wLength:%d\n", __func__, wLength); | ||
1399 | return -EINVAL; | ||
1400 | } | ||
1401 | ep = bdc->bdc_ep_array[1]; | ||
1402 | bdc->ep0_req.ep = ep; | ||
1403 | bdc->ep0_req.usb_req.length = 6; | ||
1404 | bdc->ep0_req.usb_req.buf = bdc->ep0_response_buff; | ||
1405 | bdc->ep0_req.usb_req.complete = ep0_set_sel_cmpl; | ||
1406 | ep0_queue_data_stage(bdc); | ||
1407 | |||
1408 | return 0; | ||
1409 | } | ||
1410 | |||
1411 | /* | ||
1412 | * Queue a 0 byte bd only if wLength is more than the length and and length is | ||
1413 | * a multiple of MaxPacket then queue 0 byte BD | ||
1414 | */ | ||
1415 | static int ep0_queue_zlp(struct bdc *bdc) | ||
1416 | { | ||
1417 | int ret; | ||
1418 | |||
1419 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
1420 | bdc->ep0_req.ep = bdc->bdc_ep_array[1]; | ||
1421 | bdc->ep0_req.usb_req.length = 0; | ||
1422 | bdc->ep0_req.usb_req.complete = NULL; | ||
1423 | bdc->ep0_state = WAIT_FOR_DATA_START; | ||
1424 | ret = bdc_queue_xfr(bdc, &bdc->ep0_req); | ||
1425 | if (ret) { | ||
1426 | dev_err(bdc->dev, "err queueing zlp :%d\n", ret); | ||
1427 | return ret; | ||
1428 | } | ||
1429 | bdc->ep0_state = WAIT_FOR_DATA_XMIT; | ||
1430 | |||
1431 | return 0; | ||
1432 | } | ||
1433 | |||
1434 | /* Control request handler */ | ||
1435 | static int handle_control_request(struct bdc *bdc) | ||
1436 | { | ||
1437 | enum usb_device_state state = bdc->gadget.state; | ||
1438 | struct usb_ctrlrequest *setup_pkt; | ||
1439 | int delegate_setup = 0; | ||
1440 | int ret = 0; | ||
1441 | int config = 0; | ||
1442 | |||
1443 | setup_pkt = &bdc->setup_pkt; | ||
1444 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
1445 | if ((setup_pkt->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { | ||
1446 | switch (setup_pkt->bRequest) { | ||
1447 | case USB_REQ_SET_ADDRESS: | ||
1448 | dev_dbg(bdc->dev, "USB_REQ_SET_ADDRESS\n"); | ||
1449 | ret = ep0_set_address(bdc, setup_pkt); | ||
1450 | bdc->devstatus &= DEVSTATUS_CLEAR; | ||
1451 | break; | ||
1452 | |||
1453 | case USB_REQ_SET_CONFIGURATION: | ||
1454 | dev_dbg(bdc->dev, "USB_REQ_SET_CONFIGURATION\n"); | ||
1455 | if (state == USB_STATE_ADDRESS) { | ||
1456 | usb_gadget_set_state(&bdc->gadget, | ||
1457 | USB_STATE_CONFIGURED); | ||
1458 | } else if (state == USB_STATE_CONFIGURED) { | ||
1459 | /* | ||
1460 | * USB2 spec sec 9.4.7, if wValue is 0 then dev | ||
1461 | * is moved to addressed state | ||
1462 | */ | ||
1463 | config = le16_to_cpu(setup_pkt->wValue); | ||
1464 | if (!config) | ||
1465 | usb_gadget_set_state( | ||
1466 | &bdc->gadget, | ||
1467 | USB_STATE_ADDRESS); | ||
1468 | } | ||
1469 | delegate_setup = 1; | ||
1470 | break; | ||
1471 | |||
1472 | case USB_REQ_SET_FEATURE: | ||
1473 | dev_dbg(bdc->dev, "USB_REQ_SET_FEATURE\n"); | ||
1474 | ret = ep0_handle_feature(bdc, setup_pkt, 1); | ||
1475 | break; | ||
1476 | |||
1477 | case USB_REQ_CLEAR_FEATURE: | ||
1478 | dev_dbg(bdc->dev, "USB_REQ_CLEAR_FEATURE\n"); | ||
1479 | ret = ep0_handle_feature(bdc, setup_pkt, 0); | ||
1480 | break; | ||
1481 | |||
1482 | case USB_REQ_GET_STATUS: | ||
1483 | dev_dbg(bdc->dev, "USB_REQ_GET_STATUS\n"); | ||
1484 | ret = ep0_handle_status(bdc, setup_pkt); | ||
1485 | break; | ||
1486 | |||
1487 | case USB_REQ_SET_SEL: | ||
1488 | dev_dbg(bdc->dev, "USB_REQ_SET_SEL\n"); | ||
1489 | ret = ep0_set_sel(bdc, setup_pkt); | ||
1490 | break; | ||
1491 | |||
1492 | case USB_REQ_SET_ISOCH_DELAY: | ||
1493 | dev_warn(bdc->dev, | ||
1494 | "USB_REQ_SET_ISOCH_DELAY not handled\n"); | ||
1495 | ret = 0; | ||
1496 | break; | ||
1497 | default: | ||
1498 | delegate_setup = 1; | ||
1499 | } | ||
1500 | } else { | ||
1501 | delegate_setup = 1; | ||
1502 | } | ||
1503 | |||
1504 | if (delegate_setup) { | ||
1505 | spin_unlock(&bdc->lock); | ||
1506 | ret = bdc->gadget_driver->setup(&bdc->gadget, setup_pkt); | ||
1507 | spin_lock(&bdc->lock); | ||
1508 | } | ||
1509 | |||
1510 | return ret; | ||
1511 | } | ||
1512 | |||
1513 | /* EP0: Data stage started */ | ||
1514 | void bdc_xsf_ep0_data_start(struct bdc *bdc, struct bdc_sr *sreport) | ||
1515 | { | ||
1516 | struct bdc_ep *ep; | ||
1517 | int ret = 0; | ||
1518 | |||
1519 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
1520 | ep = bdc->bdc_ep_array[1]; | ||
1521 | /* If ep0 was stalled, the clear it first */ | ||
1522 | if (ep->flags & BDC_EP_STALL) { | ||
1523 | ret = ep_set_halt(ep, 0); | ||
1524 | if (ret) | ||
1525 | goto err; | ||
1526 | } | ||
1527 | if (bdc->ep0_state != WAIT_FOR_DATA_START) | ||
1528 | dev_warn(bdc->dev, | ||
1529 | "Data stage not expected ep0_state:%s\n", | ||
1530 | ep0_state_string[bdc->ep0_state]); | ||
1531 | |||
1532 | ret = handle_control_request(bdc); | ||
1533 | if (ret == USB_GADGET_DELAYED_STATUS) { | ||
1534 | /* | ||
1535 | * The ep0 state will remain WAIT_FOR_DATA_START till | ||
1536 | * we received ep_queue on ep0 | ||
1537 | */ | ||
1538 | bdc->delayed_status = true; | ||
1539 | return; | ||
1540 | } | ||
1541 | if (!ret) { | ||
1542 | bdc->ep0_state = WAIT_FOR_DATA_XMIT; | ||
1543 | dev_dbg(bdc->dev, | ||
1544 | "ep0_state:%s", ep0_state_string[bdc->ep0_state]); | ||
1545 | return; | ||
1546 | } | ||
1547 | err: | ||
1548 | ep0_stall(bdc); | ||
1549 | } | ||
1550 | |||
1551 | /* EP0: status stage started */ | ||
1552 | void bdc_xsf_ep0_status_start(struct bdc *bdc, struct bdc_sr *sreport) | ||
1553 | { | ||
1554 | struct usb_ctrlrequest *setup_pkt; | ||
1555 | struct bdc_ep *ep; | ||
1556 | int ret = 0; | ||
1557 | |||
1558 | dev_dbg(bdc->dev, | ||
1559 | "%s ep0_state:%s", | ||
1560 | __func__, ep0_state_string[bdc->ep0_state]); | ||
1561 | ep = bdc->bdc_ep_array[1]; | ||
1562 | |||
1563 | /* check if ZLP was queued? */ | ||
1564 | if (bdc->zlp_needed) | ||
1565 | bdc->zlp_needed = false; | ||
1566 | |||
1567 | if (ep->flags & BDC_EP_STALL) { | ||
1568 | ret = ep_set_halt(ep, 0); | ||
1569 | if (ret) | ||
1570 | goto err; | ||
1571 | } | ||
1572 | |||
1573 | if ((bdc->ep0_state != WAIT_FOR_STATUS_START) && | ||
1574 | (bdc->ep0_state != WAIT_FOR_DATA_XMIT)) | ||
1575 | dev_err(bdc->dev, | ||
1576 | "Status stage recv but ep0_state:%s\n", | ||
1577 | ep0_state_string[bdc->ep0_state]); | ||
1578 | |||
1579 | /* check if data stage is in progress ? */ | ||
1580 | if (bdc->ep0_state == WAIT_FOR_DATA_XMIT) { | ||
1581 | bdc->ep0_state = STATUS_PENDING; | ||
1582 | /* Status stage will be queued upon Data stage transmit event */ | ||
1583 | dev_dbg(bdc->dev, | ||
1584 | "status started but data not transmitted yet\n"); | ||
1585 | return; | ||
1586 | } | ||
1587 | setup_pkt = &bdc->setup_pkt; | ||
1588 | |||
1589 | /* | ||
1590 | * 2 stage setup then only process the setup, for 3 stage setup the date | ||
1591 | * stage is already handled | ||
1592 | */ | ||
1593 | if (!le16_to_cpu(setup_pkt->wLength)) { | ||
1594 | ret = handle_control_request(bdc); | ||
1595 | if (ret == USB_GADGET_DELAYED_STATUS) { | ||
1596 | bdc->delayed_status = true; | ||
1597 | /* ep0_state will remain WAIT_FOR_STATUS_START */ | ||
1598 | return; | ||
1599 | } | ||
1600 | } | ||
1601 | if (!ret) { | ||
1602 | /* Queue a status stage BD */ | ||
1603 | ep0_queue_status_stage(bdc); | ||
1604 | bdc->ep0_state = WAIT_FOR_STATUS_XMIT; | ||
1605 | dev_dbg(bdc->dev, | ||
1606 | "ep0_state:%s", ep0_state_string[bdc->ep0_state]); | ||
1607 | return; | ||
1608 | } | ||
1609 | err: | ||
1610 | ep0_stall(bdc); | ||
1611 | } | ||
1612 | |||
1613 | /* Helper function to update ep0 upon SR with xsf_succ or xsf_short */ | ||
1614 | static void ep0_xsf_complete(struct bdc *bdc, struct bdc_sr *sreport) | ||
1615 | { | ||
1616 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
1617 | switch (bdc->ep0_state) { | ||
1618 | case WAIT_FOR_DATA_XMIT: | ||
1619 | bdc->ep0_state = WAIT_FOR_STATUS_START; | ||
1620 | break; | ||
1621 | case WAIT_FOR_STATUS_XMIT: | ||
1622 | bdc->ep0_state = WAIT_FOR_SETUP; | ||
1623 | if (bdc->test_mode) { | ||
1624 | int ret; | ||
1625 | |||
1626 | dev_dbg(bdc->dev, "test_mode:%d\n", bdc->test_mode); | ||
1627 | ret = bdc_set_test_mode(bdc); | ||
1628 | if (ret < 0) { | ||
1629 | dev_err(bdc->dev, "Err in setting Test mode\n"); | ||
1630 | return; | ||
1631 | } | ||
1632 | bdc->test_mode = 0; | ||
1633 | } | ||
1634 | break; | ||
1635 | case STATUS_PENDING: | ||
1636 | bdc_xsf_ep0_status_start(bdc, sreport); | ||
1637 | break; | ||
1638 | |||
1639 | default: | ||
1640 | dev_err(bdc->dev, | ||
1641 | "Unknown ep0_state:%s\n", | ||
1642 | ep0_state_string[bdc->ep0_state]); | ||
1643 | |||
1644 | } | ||
1645 | } | ||
1646 | |||
1647 | /* xfr completion status report handler */ | ||
1648 | void bdc_sr_xsf(struct bdc *bdc, struct bdc_sr *sreport) | ||
1649 | { | ||
1650 | struct bdc_ep *ep; | ||
1651 | u32 sr_status; | ||
1652 | u8 ep_num; | ||
1653 | |||
1654 | ep_num = (le32_to_cpu(sreport->offset[3])>>4) & 0x1f; | ||
1655 | ep = bdc->bdc_ep_array[ep_num]; | ||
1656 | if (!ep || !(ep->flags & BDC_EP_ENABLED)) { | ||
1657 | dev_err(bdc->dev, "xsf for ep not enabled\n"); | ||
1658 | return; | ||
1659 | } | ||
1660 | /* | ||
1661 | * check if this transfer is after link went from U3->U0 due | ||
1662 | * to remote wakeup | ||
1663 | */ | ||
1664 | if (bdc->devstatus & FUNC_WAKE_ISSUED) { | ||
1665 | bdc->devstatus &= ~(FUNC_WAKE_ISSUED); | ||
1666 | dev_dbg(bdc->dev, "%s clearing FUNC_WAKE_ISSUED flag\n", | ||
1667 | __func__); | ||
1668 | } | ||
1669 | sr_status = XSF_STS(le32_to_cpu(sreport->offset[3])); | ||
1670 | dev_dbg_ratelimited(bdc->dev, "%s sr_status=%d ep:%s\n", | ||
1671 | __func__, sr_status, ep->name); | ||
1672 | |||
1673 | switch (sr_status) { | ||
1674 | case XSF_SUCC: | ||
1675 | case XSF_SHORT: | ||
1676 | handle_xsr_succ_status(bdc, ep, sreport); | ||
1677 | if (ep_num == 1) | ||
1678 | ep0_xsf_complete(bdc, sreport); | ||
1679 | break; | ||
1680 | |||
1681 | case XSF_SETUP_RECV: | ||
1682 | case XSF_DATA_START: | ||
1683 | case XSF_STATUS_START: | ||
1684 | if (ep_num != 1) { | ||
1685 | dev_err(bdc->dev, | ||
1686 | "ep0 related packets on non ep0 endpoint"); | ||
1687 | return; | ||
1688 | } | ||
1689 | bdc->sr_xsf_ep0[sr_status - XSF_SETUP_RECV](bdc, sreport); | ||
1690 | break; | ||
1691 | |||
1692 | case XSF_BABB: | ||
1693 | if (ep_num == 1) { | ||
1694 | dev_dbg(bdc->dev, "Babble on ep0 zlp_need:%d\n", | ||
1695 | bdc->zlp_needed); | ||
1696 | /* | ||
1697 | * If the last completed transfer had wLength >Data Len, | ||
1698 | * and Len is multiple of MaxPacket,then queue ZLP | ||
1699 | */ | ||
1700 | if (bdc->zlp_needed) { | ||
1701 | /* queue 0 length bd */ | ||
1702 | ep0_queue_zlp(bdc); | ||
1703 | return; | ||
1704 | } | ||
1705 | } | ||
1706 | dev_warn(bdc->dev, "Babble on ep not handled\n"); | ||
1707 | break; | ||
1708 | default: | ||
1709 | dev_warn(bdc->dev, "sr status not handled:%x\n", sr_status); | ||
1710 | break; | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1714 | static int bdc_gadget_ep_queue(struct usb_ep *_ep, | ||
1715 | struct usb_request *_req, gfp_t gfp_flags) | ||
1716 | { | ||
1717 | struct bdc_req *req; | ||
1718 | unsigned long flags; | ||
1719 | struct bdc_ep *ep; | ||
1720 | struct bdc *bdc; | ||
1721 | int ret; | ||
1722 | |||
1723 | if (!_ep || !_ep->desc) | ||
1724 | return -ESHUTDOWN; | ||
1725 | |||
1726 | if (!_req || !_req->complete || !_req->buf) | ||
1727 | return -EINVAL; | ||
1728 | |||
1729 | ep = to_bdc_ep(_ep); | ||
1730 | req = to_bdc_req(_req); | ||
1731 | bdc = ep->bdc; | ||
1732 | dev_dbg(bdc->dev, "%s ep:%p req:%p\n", __func__, ep, req); | ||
1733 | dev_dbg(bdc->dev, "queuing request %p to %s length %d zero:%d\n", | ||
1734 | _req, ep->name, _req->length, _req->zero); | ||
1735 | |||
1736 | if (!ep->usb_ep.desc) { | ||
1737 | dev_warn(bdc->dev, | ||
1738 | "trying to queue req %p to disabled %s\n", | ||
1739 | _req, ep->name); | ||
1740 | return -ESHUTDOWN; | ||
1741 | } | ||
1742 | |||
1743 | if (_req->length > MAX_XFR_LEN) { | ||
1744 | dev_warn(bdc->dev, | ||
1745 | "req length > supported MAX:%d requested:%d\n", | ||
1746 | MAX_XFR_LEN, _req->length); | ||
1747 | return -EOPNOTSUPP; | ||
1748 | } | ||
1749 | spin_lock_irqsave(&bdc->lock, flags); | ||
1750 | if (ep == bdc->bdc_ep_array[1]) | ||
1751 | ret = ep0_queue(ep, req); | ||
1752 | else | ||
1753 | ret = ep_queue(ep, req); | ||
1754 | |||
1755 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
1756 | |||
1757 | return ret; | ||
1758 | } | ||
1759 | |||
1760 | static int bdc_gadget_ep_dequeue(struct usb_ep *_ep, | ||
1761 | struct usb_request *_req) | ||
1762 | { | ||
1763 | struct bdc_req *req; | ||
1764 | unsigned long flags; | ||
1765 | struct bdc_ep *ep; | ||
1766 | struct bdc *bdc; | ||
1767 | int ret; | ||
1768 | |||
1769 | if (!_ep || !_req) | ||
1770 | return -EINVAL; | ||
1771 | |||
1772 | ep = to_bdc_ep(_ep); | ||
1773 | req = to_bdc_req(_req); | ||
1774 | bdc = ep->bdc; | ||
1775 | dev_dbg(bdc->dev, "%s ep:%s req:%p\n", __func__, ep->name, req); | ||
1776 | bdc_dbg_bd_list(bdc, ep); | ||
1777 | spin_lock_irqsave(&bdc->lock, flags); | ||
1778 | /* make sure it's still queued on this endpoint */ | ||
1779 | list_for_each_entry(req, &ep->queue, queue) { | ||
1780 | if (&req->usb_req == _req) | ||
1781 | break; | ||
1782 | } | ||
1783 | if (&req->usb_req != _req) { | ||
1784 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
1785 | dev_err(bdc->dev, "usb_req !=req n"); | ||
1786 | return -EINVAL; | ||
1787 | } | ||
1788 | ret = ep_dequeue(ep, req); | ||
1789 | if (ret) { | ||
1790 | ret = -EOPNOTSUPP; | ||
1791 | goto err; | ||
1792 | } | ||
1793 | bdc_req_complete(ep, req, -ECONNRESET); | ||
1794 | |||
1795 | err: | ||
1796 | bdc_dbg_bd_list(bdc, ep); | ||
1797 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
1798 | |||
1799 | return ret; | ||
1800 | } | ||
1801 | |||
1802 | static int bdc_gadget_ep_set_halt(struct usb_ep *_ep, int value) | ||
1803 | { | ||
1804 | unsigned long flags; | ||
1805 | struct bdc_ep *ep; | ||
1806 | struct bdc *bdc; | ||
1807 | int ret; | ||
1808 | |||
1809 | ep = to_bdc_ep(_ep); | ||
1810 | bdc = ep->bdc; | ||
1811 | dev_dbg(bdc->dev, "%s ep:%s value=%d\n", __func__, ep->name, value); | ||
1812 | spin_lock_irqsave(&bdc->lock, flags); | ||
1813 | if (usb_endpoint_xfer_isoc(ep->usb_ep.desc)) | ||
1814 | ret = -EINVAL; | ||
1815 | else if (!list_empty(&ep->queue)) | ||
1816 | ret = -EAGAIN; | ||
1817 | else | ||
1818 | ret = ep_set_halt(ep, value); | ||
1819 | |||
1820 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
1821 | |||
1822 | return ret; | ||
1823 | } | ||
1824 | |||
1825 | static struct usb_request *bdc_gadget_alloc_request(struct usb_ep *_ep, | ||
1826 | gfp_t gfp_flags) | ||
1827 | { | ||
1828 | struct bdc_req *req; | ||
1829 | struct bdc_ep *ep; | ||
1830 | |||
1831 | req = kzalloc(sizeof(*req), gfp_flags); | ||
1832 | if (!req) | ||
1833 | return NULL; | ||
1834 | |||
1835 | ep = to_bdc_ep(_ep); | ||
1836 | req->ep = ep; | ||
1837 | req->epnum = ep->ep_num; | ||
1838 | req->usb_req.dma = DMA_ADDR_INVALID; | ||
1839 | dev_dbg(ep->bdc->dev, "%s ep:%s req:%p\n", __func__, ep->name, req); | ||
1840 | |||
1841 | return &req->usb_req; | ||
1842 | } | ||
1843 | |||
1844 | static void bdc_gadget_free_request(struct usb_ep *_ep, | ||
1845 | struct usb_request *_req) | ||
1846 | { | ||
1847 | struct bdc_req *req; | ||
1848 | |||
1849 | req = to_bdc_req(_req); | ||
1850 | kfree(req); | ||
1851 | } | ||
1852 | |||
1853 | /* endpoint operations */ | ||
1854 | |||
1855 | /* configure endpoint and also allocate resources */ | ||
1856 | static int bdc_gadget_ep_enable(struct usb_ep *_ep, | ||
1857 | const struct usb_endpoint_descriptor *desc) | ||
1858 | { | ||
1859 | unsigned long flags; | ||
1860 | struct bdc_ep *ep; | ||
1861 | struct bdc *bdc; | ||
1862 | int ret; | ||
1863 | |||
1864 | if (!_ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) { | ||
1865 | pr_debug("bdc_gadget_ep_enable invalid parameters\n"); | ||
1866 | return -EINVAL; | ||
1867 | } | ||
1868 | |||
1869 | if (!desc->wMaxPacketSize) { | ||
1870 | pr_debug("bdc_gadget_ep_enable missing wMaxPacketSize\n"); | ||
1871 | return -EINVAL; | ||
1872 | } | ||
1873 | |||
1874 | ep = to_bdc_ep(_ep); | ||
1875 | bdc = ep->bdc; | ||
1876 | |||
1877 | /* Sanity check, upper layer will not send enable for ep0 */ | ||
1878 | if (ep == bdc->bdc_ep_array[1]) | ||
1879 | return -EINVAL; | ||
1880 | |||
1881 | if (!bdc->gadget_driver | ||
1882 | || bdc->gadget.speed == USB_SPEED_UNKNOWN) { | ||
1883 | return -ESHUTDOWN; | ||
1884 | } | ||
1885 | |||
1886 | dev_dbg(bdc->dev, "%s Enabling %s\n", __func__, ep->name); | ||
1887 | spin_lock_irqsave(&bdc->lock, flags); | ||
1888 | ep->desc = desc; | ||
1889 | ep->comp_desc = _ep->comp_desc; | ||
1890 | ret = bdc_ep_enable(ep); | ||
1891 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
1892 | |||
1893 | return ret; | ||
1894 | } | ||
1895 | |||
1896 | static int bdc_gadget_ep_disable(struct usb_ep *_ep) | ||
1897 | { | ||
1898 | unsigned long flags; | ||
1899 | struct bdc_ep *ep; | ||
1900 | struct bdc *bdc; | ||
1901 | int ret; | ||
1902 | |||
1903 | if (!_ep) { | ||
1904 | pr_debug("bdc: invalid parameters\n"); | ||
1905 | return -EINVAL; | ||
1906 | } | ||
1907 | ep = to_bdc_ep(_ep); | ||
1908 | bdc = ep->bdc; | ||
1909 | |||
1910 | /* Upper layer will not call this for ep0, but do a sanity check */ | ||
1911 | if (ep == bdc->bdc_ep_array[1]) { | ||
1912 | dev_warn(bdc->dev, "%s called for ep0\n", __func__); | ||
1913 | return -EINVAL; | ||
1914 | } | ||
1915 | dev_dbg(bdc->dev, | ||
1916 | "%s() ep:%s ep->flags:%08x\n", | ||
1917 | __func__, ep->name, ep->flags); | ||
1918 | |||
1919 | if (!(ep->flags & BDC_EP_ENABLED)) { | ||
1920 | dev_warn(bdc->dev, "%s is already disabled\n", ep->name); | ||
1921 | return 0; | ||
1922 | } | ||
1923 | spin_lock_irqsave(&bdc->lock, flags); | ||
1924 | ret = bdc_ep_disable(ep); | ||
1925 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
1926 | |||
1927 | return ret; | ||
1928 | } | ||
1929 | |||
1930 | static const struct usb_ep_ops bdc_gadget_ep_ops = { | ||
1931 | .enable = bdc_gadget_ep_enable, | ||
1932 | .disable = bdc_gadget_ep_disable, | ||
1933 | .alloc_request = bdc_gadget_alloc_request, | ||
1934 | .free_request = bdc_gadget_free_request, | ||
1935 | .queue = bdc_gadget_ep_queue, | ||
1936 | .dequeue = bdc_gadget_ep_dequeue, | ||
1937 | .set_halt = bdc_gadget_ep_set_halt | ||
1938 | }; | ||
1939 | |||
1940 | /* dir = 1 is IN */ | ||
1941 | static int init_ep(struct bdc *bdc, u32 epnum, u32 dir) | ||
1942 | { | ||
1943 | struct bdc_ep *ep; | ||
1944 | |||
1945 | dev_dbg(bdc->dev, "%s epnum=%d dir=%d\n", __func__, epnum, dir); | ||
1946 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); | ||
1947 | if (!ep) | ||
1948 | return -ENOMEM; | ||
1949 | |||
1950 | ep->bdc = bdc; | ||
1951 | ep->dir = dir; | ||
1952 | |||
1953 | /* ep->ep_num is the index inside bdc_ep */ | ||
1954 | if (epnum == 1) { | ||
1955 | ep->ep_num = 1; | ||
1956 | bdc->bdc_ep_array[ep->ep_num] = ep; | ||
1957 | snprintf(ep->name, sizeof(ep->name), "ep%d", epnum - 1); | ||
1958 | usb_ep_set_maxpacket_limit(&ep->usb_ep, EP0_MAX_PKT_SIZE); | ||
1959 | ep->comp_desc = NULL; | ||
1960 | bdc->gadget.ep0 = &ep->usb_ep; | ||
1961 | } else { | ||
1962 | if (dir) | ||
1963 | ep->ep_num = epnum * 2 - 1; | ||
1964 | else | ||
1965 | ep->ep_num = epnum * 2 - 2; | ||
1966 | |||
1967 | bdc->bdc_ep_array[ep->ep_num] = ep; | ||
1968 | snprintf(ep->name, sizeof(ep->name), "ep%d%s", epnum - 1, | ||
1969 | dir & 1 ? "in" : "out"); | ||
1970 | |||
1971 | usb_ep_set_maxpacket_limit(&ep->usb_ep, 1024); | ||
1972 | ep->usb_ep.max_streams = 0; | ||
1973 | list_add_tail(&ep->usb_ep.ep_list, &bdc->gadget.ep_list); | ||
1974 | } | ||
1975 | ep->usb_ep.ops = &bdc_gadget_ep_ops; | ||
1976 | ep->usb_ep.name = ep->name; | ||
1977 | ep->flags = 0; | ||
1978 | ep->ignore_next_sr = false; | ||
1979 | dev_dbg(bdc->dev, "ep=%p ep->usb_ep.name=%s epnum=%d ep->epnum=%d\n", | ||
1980 | ep, ep->usb_ep.name, epnum, ep->ep_num); | ||
1981 | |||
1982 | INIT_LIST_HEAD(&ep->queue); | ||
1983 | |||
1984 | return 0; | ||
1985 | } | ||
1986 | |||
1987 | /* Init all ep */ | ||
1988 | int bdc_init_ep(struct bdc *bdc) | ||
1989 | { | ||
1990 | u8 epnum; | ||
1991 | int ret; | ||
1992 | |||
1993 | dev_dbg(bdc->dev, "%s()\n", __func__); | ||
1994 | INIT_LIST_HEAD(&bdc->gadget.ep_list); | ||
1995 | /* init ep0 */ | ||
1996 | ret = init_ep(bdc, 1, 0); | ||
1997 | if (ret) { | ||
1998 | dev_err(bdc->dev, "init ep ep0 fail %d\n", ret); | ||
1999 | return ret; | ||
2000 | } | ||
2001 | |||
2002 | for (epnum = 2; epnum <= bdc->num_eps / 2; epnum++) { | ||
2003 | /* OUT */ | ||
2004 | ret = init_ep(bdc, epnum, 0); | ||
2005 | if (ret) { | ||
2006 | dev_err(bdc->dev, | ||
2007 | "init ep failed for:%d error: %d\n", | ||
2008 | epnum, ret); | ||
2009 | return ret; | ||
2010 | } | ||
2011 | |||
2012 | /* IN */ | ||
2013 | ret = init_ep(bdc, epnum, 1); | ||
2014 | if (ret) { | ||
2015 | dev_err(bdc->dev, | ||
2016 | "init ep failed for:%d error: %d\n", | ||
2017 | epnum, ret); | ||
2018 | return ret; | ||
2019 | } | ||
2020 | } | ||
2021 | |||
2022 | return 0; | ||
2023 | } | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.h b/drivers/usb/gadget/udc/bdc/bdc_ep.h new file mode 100644 index 000000000000..8a6b36cbf2ea --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * bdc_ep.h - header for the BDC debug functions | ||
3 | * | ||
4 | * Copyright (C) 2014 Broadcom Corporation | ||
5 | * | ||
6 | * Author: Ashwini Pahuja | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | #ifndef __LINUX_BDC_EP_H__ | ||
15 | #define __LINUX_BDC_EP_H__ | ||
16 | |||
17 | int bdc_init_ep(struct bdc *); | ||
18 | int bdc_ep_disable(struct bdc_ep *); | ||
19 | int bdc_ep_enable(struct bdc_ep *); | ||
20 | void bdc_free_ep(struct bdc *); | ||
21 | |||
22 | #endif /* __LINUX_BDC_EP_H__ */ | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc_pci.c b/drivers/usb/gadget/udc/bdc/bdc_pci.c new file mode 100644 index 000000000000..02968842b359 --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/bdc_pci.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * bdc_pci.c - BRCM BDC USB3.0 device controller PCI interface file. | ||
3 | * | ||
4 | * Copyright (C) 2014 Broadcom Corporation | ||
5 | * | ||
6 | * Author: Ashwini Pahuja | ||
7 | * | ||
8 | * Based on drivers under drivers/usb/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/pci_ids.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | |||
24 | #include "bdc.h" | ||
25 | |||
26 | #define BDC_PCI_PID 0x1570 | ||
27 | |||
28 | struct bdc_pci { | ||
29 | struct device *dev; | ||
30 | struct platform_device *bdc; | ||
31 | }; | ||
32 | |||
33 | static int bdc_setup_msi(struct pci_dev *pci) | ||
34 | { | ||
35 | int ret; | ||
36 | |||
37 | ret = pci_enable_msi(pci); | ||
38 | if (ret) { | ||
39 | pr_err("failed to allocate MSI entry\n"); | ||
40 | return ret; | ||
41 | } | ||
42 | |||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | static int bdc_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) | ||
47 | { | ||
48 | struct resource res[2]; | ||
49 | struct platform_device *bdc; | ||
50 | struct bdc_pci *glue; | ||
51 | int ret = -ENOMEM; | ||
52 | |||
53 | glue = devm_kzalloc(&pci->dev, sizeof(*glue), GFP_KERNEL); | ||
54 | if (!glue) | ||
55 | return -ENOMEM; | ||
56 | |||
57 | glue->dev = &pci->dev; | ||
58 | ret = pci_enable_device(pci); | ||
59 | if (ret) { | ||
60 | dev_err(&pci->dev, "failed to enable pci device\n"); | ||
61 | return -ENODEV; | ||
62 | } | ||
63 | pci_set_master(pci); | ||
64 | |||
65 | bdc = platform_device_alloc(BRCM_BDC_NAME, PLATFORM_DEVID_AUTO); | ||
66 | if (!bdc) | ||
67 | return -ENOMEM; | ||
68 | |||
69 | memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); | ||
70 | bdc_setup_msi(pci); | ||
71 | |||
72 | res[0].start = pci_resource_start(pci, 0); | ||
73 | res[0].end = pci_resource_end(pci, 0); | ||
74 | res[0].name = BRCM_BDC_NAME; | ||
75 | res[0].flags = IORESOURCE_MEM; | ||
76 | |||
77 | res[1].start = pci->irq; | ||
78 | res[1].name = BRCM_BDC_NAME; | ||
79 | res[1].flags = IORESOURCE_IRQ; | ||
80 | |||
81 | ret = platform_device_add_resources(bdc, res, ARRAY_SIZE(res)); | ||
82 | if (ret) { | ||
83 | dev_err(&pci->dev, | ||
84 | "couldn't add resources to bdc device\n"); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | pci_set_drvdata(pci, glue); | ||
89 | |||
90 | dma_set_coherent_mask(&bdc->dev, pci->dev.coherent_dma_mask); | ||
91 | |||
92 | bdc->dev.dma_mask = pci->dev.dma_mask; | ||
93 | bdc->dev.dma_parms = pci->dev.dma_parms; | ||
94 | bdc->dev.parent = &pci->dev; | ||
95 | glue->bdc = bdc; | ||
96 | |||
97 | ret = platform_device_add(bdc); | ||
98 | if (ret) { | ||
99 | dev_err(&pci->dev, "failed to register bdc device\n"); | ||
100 | platform_device_put(bdc); | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static void bdc_pci_remove(struct pci_dev *pci) | ||
108 | { | ||
109 | struct bdc_pci *glue = pci_get_drvdata(pci); | ||
110 | |||
111 | platform_device_unregister(glue->bdc); | ||
112 | pci_disable_msi(pci); | ||
113 | } | ||
114 | |||
115 | static struct pci_device_id bdc_pci_id_table[] = { | ||
116 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, BDC_PCI_PID), }, | ||
117 | {} /* Terminating Entry */ | ||
118 | }; | ||
119 | |||
120 | MODULE_DEVICE_TABLE(pci, bdc_pci_id_table); | ||
121 | |||
122 | static struct pci_driver bdc_pci_driver = { | ||
123 | .name = "bdc-pci", | ||
124 | .id_table = bdc_pci_id_table, | ||
125 | .probe = bdc_pci_probe, | ||
126 | .remove = bdc_pci_remove, | ||
127 | }; | ||
128 | |||
129 | MODULE_AUTHOR("Ashwini Pahuja <ashwini.linux@gmail.com>"); | ||
130 | MODULE_LICENSE("GPL"); | ||
131 | MODULE_DESCRIPTION("BRCM BDC USB3 PCI Glue layer"); | ||
132 | module_pci_driver(bdc_pci_driver); | ||
diff --git a/drivers/usb/gadget/udc/bdc/bdc_udc.c b/drivers/usb/gadget/udc/bdc/bdc_udc.c new file mode 100644 index 000000000000..3700ce70b0be --- /dev/null +++ b/drivers/usb/gadget/udc/bdc/bdc_udc.c | |||
@@ -0,0 +1,587 @@ | |||
1 | /* | ||
2 | * bdc_udc.c - BRCM BDC USB3.0 device controller gagdet ops | ||
3 | * | ||
4 | * Copyright (C) 2014 Broadcom Corporation | ||
5 | * | ||
6 | * Author: Ashwini Pahuja | ||
7 | * | ||
8 | * Based on drivers under drivers/usb/gadget/udc/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/ioport.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/timer.h> | ||
27 | #include <linux/list.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/moduleparam.h> | ||
30 | #include <linux/device.h> | ||
31 | #include <linux/usb/ch9.h> | ||
32 | #include <linux/usb/gadget.h> | ||
33 | #include <linux/usb/otg.h> | ||
34 | #include <linux/pm.h> | ||
35 | #include <linux/io.h> | ||
36 | #include <linux/irq.h> | ||
37 | #include <asm/unaligned.h> | ||
38 | #include <linux/platform_device.h> | ||
39 | |||
40 | #include "bdc.h" | ||
41 | #include "bdc_ep.h" | ||
42 | #include "bdc_cmd.h" | ||
43 | #include "bdc_dbg.h" | ||
44 | |||
45 | static const struct usb_gadget_ops bdc_gadget_ops; | ||
46 | |||
47 | static const char * const conn_speed_str[] = { | ||
48 | "Not connected", | ||
49 | "Full Speed", | ||
50 | "Low Speed", | ||
51 | "High Speed", | ||
52 | "Super Speed", | ||
53 | }; | ||
54 | |||
55 | /* EP0 initial descripror */ | ||
56 | static struct usb_endpoint_descriptor bdc_gadget_ep0_desc = { | ||
57 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
58 | .bDescriptorType = USB_DT_ENDPOINT, | ||
59 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | ||
60 | .bEndpointAddress = 0, | ||
61 | .wMaxPacketSize = cpu_to_le16(EP0_MAX_PKT_SIZE), | ||
62 | }; | ||
63 | |||
64 | /* Advance the srr dqp maintained by SW */ | ||
65 | static void srr_dqp_index_advc(struct bdc *bdc, u32 srr_num) | ||
66 | { | ||
67 | struct srr *srr; | ||
68 | |||
69 | srr = &bdc->srr; | ||
70 | dev_dbg_ratelimited(bdc->dev, "srr->dqp_index:%d\n", srr->dqp_index); | ||
71 | srr->dqp_index++; | ||
72 | /* rollback to 0 if we are past the last */ | ||
73 | if (srr->dqp_index == NUM_SR_ENTRIES) | ||
74 | srr->dqp_index = 0; | ||
75 | } | ||
76 | |||
77 | /* connect sr */ | ||
78 | static void bdc_uspc_connected(struct bdc *bdc) | ||
79 | { | ||
80 | u32 speed, temp; | ||
81 | u32 usppms; | ||
82 | int ret; | ||
83 | |||
84 | temp = bdc_readl(bdc->regs, BDC_USPC); | ||
85 | speed = BDC_PSP(temp); | ||
86 | dev_dbg(bdc->dev, "%s speed=%x\n", __func__, speed); | ||
87 | switch (speed) { | ||
88 | case BDC_SPEED_SS: | ||
89 | bdc_gadget_ep0_desc.wMaxPacketSize = | ||
90 | cpu_to_le16(EP0_MAX_PKT_SIZE); | ||
91 | bdc->gadget.ep0->maxpacket = EP0_MAX_PKT_SIZE; | ||
92 | bdc->gadget.speed = USB_SPEED_SUPER; | ||
93 | /* Enable U1T in SS mode */ | ||
94 | usppms = bdc_readl(bdc->regs, BDC_USPPMS); | ||
95 | usppms &= ~BDC_U1T(0xff); | ||
96 | usppms |= BDC_U1T(U1_TIMEOUT); | ||
97 | usppms |= BDC_PORT_W1S; | ||
98 | bdc_writel(bdc->regs, BDC_USPPMS, usppms); | ||
99 | break; | ||
100 | |||
101 | case BDC_SPEED_HS: | ||
102 | bdc_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); | ||
103 | bdc->gadget.ep0->maxpacket = 64; | ||
104 | bdc->gadget.speed = USB_SPEED_HIGH; | ||
105 | break; | ||
106 | |||
107 | case BDC_SPEED_FS: | ||
108 | bdc_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); | ||
109 | bdc->gadget.ep0->maxpacket = 64; | ||
110 | bdc->gadget.speed = USB_SPEED_FULL; | ||
111 | break; | ||
112 | |||
113 | case BDC_SPEED_LS: | ||
114 | bdc_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(8); | ||
115 | bdc->gadget.ep0->maxpacket = 8; | ||
116 | bdc->gadget.speed = USB_SPEED_LOW; | ||
117 | break; | ||
118 | default: | ||
119 | dev_err(bdc->dev, "UNDEFINED SPEED\n"); | ||
120 | return; | ||
121 | } | ||
122 | dev_dbg(bdc->dev, "connected at %s\n", conn_speed_str[speed]); | ||
123 | /* Now we know the speed, configure ep0 */ | ||
124 | bdc->bdc_ep_array[1]->desc = &bdc_gadget_ep0_desc; | ||
125 | ret = bdc_config_ep(bdc, bdc->bdc_ep_array[1]); | ||
126 | if (ret) | ||
127 | dev_err(bdc->dev, "EP0 config failed\n"); | ||
128 | bdc->bdc_ep_array[1]->usb_ep.desc = &bdc_gadget_ep0_desc; | ||
129 | bdc->bdc_ep_array[1]->flags |= BDC_EP_ENABLED; | ||
130 | usb_gadget_set_state(&bdc->gadget, USB_STATE_DEFAULT); | ||
131 | } | ||
132 | |||
133 | /* device got disconnected */ | ||
134 | static void bdc_uspc_disconnected(struct bdc *bdc, bool reinit) | ||
135 | { | ||
136 | struct bdc_ep *ep; | ||
137 | |||
138 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
139 | /* | ||
140 | * Only stop ep0 from here, rest of the endpoints will be disabled | ||
141 | * from gadget_disconnect | ||
142 | */ | ||
143 | ep = bdc->bdc_ep_array[1]; | ||
144 | if (ep && (ep->flags & BDC_EP_ENABLED)) | ||
145 | /* if enabled then stop and remove requests */ | ||
146 | bdc_ep_disable(ep); | ||
147 | |||
148 | if (bdc->gadget_driver && bdc->gadget_driver->disconnect) { | ||
149 | spin_unlock(&bdc->lock); | ||
150 | bdc->gadget_driver->disconnect(&bdc->gadget); | ||
151 | spin_lock(&bdc->lock); | ||
152 | } | ||
153 | /* Set Unknown speed */ | ||
154 | bdc->gadget.speed = USB_SPEED_UNKNOWN; | ||
155 | bdc->devstatus &= DEVSTATUS_CLEAR; | ||
156 | bdc->delayed_status = false; | ||
157 | bdc->reinit = reinit; | ||
158 | bdc->test_mode = false; | ||
159 | } | ||
160 | |||
161 | /* TNotify wkaeup timer */ | ||
162 | static void bdc_func_wake_timer(struct work_struct *work) | ||
163 | { | ||
164 | struct bdc *bdc = container_of(work, struct bdc, func_wake_notify.work); | ||
165 | unsigned long flags; | ||
166 | |||
167 | dev_dbg(bdc->dev, "%s\n", __func__); | ||
168 | spin_lock_irqsave(&bdc->lock, flags); | ||
169 | /* | ||
170 | * Check if host has started transferring on endpoints | ||
171 | * FUNC_WAKE_ISSUED is cleared when transfer has started after resume | ||
172 | */ | ||
173 | if (bdc->devstatus & FUNC_WAKE_ISSUED) { | ||
174 | dev_dbg(bdc->dev, "FUNC_WAKE_ISSUED FLAG IS STILL SET\n"); | ||
175 | /* flag is still set, so again send func wake */ | ||
176 | bdc_function_wake_fh(bdc, 0); | ||
177 | schedule_delayed_work(&bdc->func_wake_notify, | ||
178 | msecs_to_jiffies(BDC_TNOTIFY)); | ||
179 | } | ||
180 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
181 | } | ||
182 | |||
183 | /* handler for Link state change condition */ | ||
184 | static void handle_link_state_change(struct bdc *bdc, u32 uspc) | ||
185 | { | ||
186 | u32 link_state; | ||
187 | |||
188 | dev_dbg(bdc->dev, "Link state change"); | ||
189 | link_state = BDC_PST(uspc); | ||
190 | switch (link_state) { | ||
191 | case BDC_LINK_STATE_U3: | ||
192 | if ((bdc->gadget.speed != USB_SPEED_UNKNOWN) && | ||
193 | bdc->gadget_driver->suspend) { | ||
194 | dev_dbg(bdc->dev, "Entered Suspend mode\n"); | ||
195 | spin_unlock(&bdc->lock); | ||
196 | bdc->devstatus |= DEVICE_SUSPENDED; | ||
197 | bdc->gadget_driver->suspend(&bdc->gadget); | ||
198 | spin_lock(&bdc->lock); | ||
199 | } | ||
200 | break; | ||
201 | case BDC_LINK_STATE_U0: | ||
202 | if (bdc->devstatus & REMOTE_WAKEUP_ISSUED) { | ||
203 | bdc->devstatus &= ~REMOTE_WAKEUP_ISSUED; | ||
204 | if (bdc->gadget.speed == USB_SPEED_SUPER) { | ||
205 | bdc_function_wake_fh(bdc, 0); | ||
206 | bdc->devstatus |= FUNC_WAKE_ISSUED; | ||
207 | /* | ||
208 | * Start a Notification timer and check if the | ||
209 | * Host transferred anything on any of the EPs, | ||
210 | * if not then send function wake again every | ||
211 | * TNotification secs until host initiates | ||
212 | * transfer to BDC, USB3 spec Table 8.13 | ||
213 | */ | ||
214 | schedule_delayed_work( | ||
215 | &bdc->func_wake_notify, | ||
216 | msecs_to_jiffies(BDC_TNOTIFY)); | ||
217 | dev_dbg(bdc->dev, "sched func_wake_notify\n"); | ||
218 | } | ||
219 | } | ||
220 | break; | ||
221 | |||
222 | case BDC_LINK_STATE_RESUME: | ||
223 | dev_dbg(bdc->dev, "Resumed from Suspend\n"); | ||
224 | if (bdc->devstatus & DEVICE_SUSPENDED) { | ||
225 | bdc->gadget_driver->resume(&bdc->gadget); | ||
226 | bdc->devstatus &= ~DEVICE_SUSPENDED; | ||
227 | } | ||
228 | break; | ||
229 | default: | ||
230 | dev_dbg(bdc->dev, "link state:%d\n", link_state); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | /* something changes on upstream port, handle it here */ | ||
235 | void bdc_sr_uspc(struct bdc *bdc, struct bdc_sr *sreport) | ||
236 | { | ||
237 | u32 clear_flags = 0; | ||
238 | u32 uspc; | ||
239 | bool connected = false; | ||
240 | bool disconn = false; | ||
241 | |||
242 | uspc = bdc_readl(bdc->regs, BDC_USPC); | ||
243 | dev_dbg(bdc->dev, "%s uspc=0x%08x\n", __func__, uspc); | ||
244 | |||
245 | /* Port connect changed */ | ||
246 | if (uspc & BDC_PCC) { | ||
247 | /* Vbus not present, and not connected to Downstream port */ | ||
248 | if ((uspc & BDC_VBC) && !(uspc & BDC_VBS) && !(uspc & BDC_PCS)) | ||
249 | disconn = true; | ||
250 | else if ((uspc & BDC_PCS) && !BDC_PST(uspc)) | ||
251 | connected = true; | ||
252 | } | ||
253 | |||
254 | /* Change in VBus and VBus is present */ | ||
255 | if ((uspc & BDC_VBC) && (uspc & BDC_VBS)) { | ||
256 | if (bdc->pullup) { | ||
257 | dev_dbg(bdc->dev, "Do a softconnect\n"); | ||
258 | /* Attached state, do a softconnect */ | ||
259 | bdc_softconn(bdc); | ||
260 | usb_gadget_set_state(&bdc->gadget, USB_STATE_POWERED); | ||
261 | } | ||
262 | clear_flags = BDC_VBC; | ||
263 | } else if ((uspc & BDC_PRS) || (uspc & BDC_PRC) || disconn) { | ||
264 | /* Hot reset, warm reset, 2.0 bus reset or disconn */ | ||
265 | dev_dbg(bdc->dev, "Port reset or disconn\n"); | ||
266 | bdc_uspc_disconnected(bdc, disconn); | ||
267 | clear_flags = BDC_PCC|BDC_PCS|BDC_PRS|BDC_PRC; | ||
268 | } else if ((uspc & BDC_PSC) && (uspc & BDC_PCS)) { | ||
269 | /* Change in Link state */ | ||
270 | handle_link_state_change(bdc, uspc); | ||
271 | clear_flags = BDC_PSC|BDC_PCS; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * In SS we might not have PRC bit set before connection, but in 2.0 | ||
276 | * the PRC bit is set before connection, so moving this condition out | ||
277 | * of bus reset to handle both SS/2.0 speeds. | ||
278 | */ | ||
279 | if (connected) { | ||
280 | /* This is the connect event for U0/L0 */ | ||
281 | dev_dbg(bdc->dev, "Connected\n"); | ||
282 | bdc_uspc_connected(bdc); | ||
283 | bdc->devstatus &= ~(DEVICE_SUSPENDED); | ||
284 | } | ||
285 | uspc = bdc_readl(bdc->regs, BDC_USPC); | ||
286 | uspc &= (~BDC_USPSC_RW); | ||
287 | dev_dbg(bdc->dev, "uspc=%x\n", uspc); | ||
288 | bdc_writel(bdc->regs, BDC_USPC, clear_flags); | ||
289 | } | ||
290 | |||
291 | /* Main interrupt handler for bdc */ | ||
292 | static irqreturn_t bdc_udc_interrupt(int irq, void *_bdc) | ||
293 | { | ||
294 | u32 eqp_index, dqp_index, sr_type, srr_int; | ||
295 | struct bdc_sr *sreport; | ||
296 | struct bdc *bdc = _bdc; | ||
297 | u32 status; | ||
298 | int ret; | ||
299 | |||
300 | spin_lock(&bdc->lock); | ||
301 | status = bdc_readl(bdc->regs, BDC_BDCSC); | ||
302 | if (!(status & BDC_GIP)) { | ||
303 | spin_unlock(&bdc->lock); | ||
304 | return IRQ_NONE; | ||
305 | } | ||
306 | srr_int = bdc_readl(bdc->regs, BDC_SRRINT(0)); | ||
307 | /* Check if the SRR IP bit it set? */ | ||
308 | if (!(srr_int & BDC_SRR_IP)) { | ||
309 | dev_warn(bdc->dev, "Global irq pending but SRR IP is 0\n"); | ||
310 | spin_unlock(&bdc->lock); | ||
311 | return IRQ_NONE; | ||
312 | } | ||
313 | eqp_index = BDC_SRR_EPI(srr_int); | ||
314 | dqp_index = BDC_SRR_DPI(srr_int); | ||
315 | dev_dbg(bdc->dev, | ||
316 | "%s eqp_index=%d dqp_index=%d srr.dqp_index=%d\n\n", | ||
317 | __func__, eqp_index, dqp_index, bdc->srr.dqp_index); | ||
318 | |||
319 | /* check for ring empty condition */ | ||
320 | if (eqp_index == dqp_index) { | ||
321 | dev_dbg(bdc->dev, "SRR empty?\n"); | ||
322 | spin_unlock(&bdc->lock); | ||
323 | return IRQ_HANDLED; | ||
324 | } | ||
325 | |||
326 | while (bdc->srr.dqp_index != eqp_index) { | ||
327 | sreport = &bdc->srr.sr_bds[bdc->srr.dqp_index]; | ||
328 | /* sreport is read before using it */ | ||
329 | rmb(); | ||
330 | sr_type = le32_to_cpu(sreport->offset[3]) & BD_TYPE_BITMASK; | ||
331 | dev_dbg_ratelimited(bdc->dev, "sr_type=%d\n", sr_type); | ||
332 | switch (sr_type) { | ||
333 | case SR_XSF: | ||
334 | bdc->sr_handler[0](bdc, sreport); | ||
335 | break; | ||
336 | |||
337 | case SR_USPC: | ||
338 | bdc->sr_handler[1](bdc, sreport); | ||
339 | break; | ||
340 | default: | ||
341 | dev_warn(bdc->dev, "SR:%d not handled\n", sr_type); | ||
342 | } | ||
343 | /* Advance the srr dqp index */ | ||
344 | srr_dqp_index_advc(bdc, 0); | ||
345 | } | ||
346 | /* update the hw dequeue pointer */ | ||
347 | srr_int = bdc_readl(bdc->regs, BDC_SRRINT(0)); | ||
348 | srr_int &= ~BDC_SRR_DPI_MASK; | ||
349 | srr_int &= ~(BDC_SRR_RWS|BDC_SRR_RST|BDC_SRR_ISR); | ||
350 | srr_int |= ((bdc->srr.dqp_index) << 16); | ||
351 | srr_int |= BDC_SRR_IP; | ||
352 | bdc_writel(bdc->regs, BDC_SRRINT(0), srr_int); | ||
353 | srr_int = bdc_readl(bdc->regs, BDC_SRRINT(0)); | ||
354 | if (bdc->reinit) { | ||
355 | ret = bdc_reinit(bdc); | ||
356 | if (ret) | ||
357 | dev_err(bdc->dev, "err in bdc reinit\n"); | ||
358 | } | ||
359 | |||
360 | spin_unlock(&bdc->lock); | ||
361 | |||
362 | return IRQ_HANDLED; | ||
363 | } | ||
364 | |||
365 | /* Gadget ops */ | ||
366 | static int bdc_udc_start(struct usb_gadget *gadget, | ||
367 | struct usb_gadget_driver *driver) | ||
368 | { | ||
369 | struct bdc *bdc = gadget_to_bdc(gadget); | ||
370 | unsigned long flags; | ||
371 | int ret = 0; | ||
372 | |||
373 | dev_dbg(bdc->dev, "%s()\n", __func__); | ||
374 | spin_lock_irqsave(&bdc->lock, flags); | ||
375 | if (bdc->gadget_driver) { | ||
376 | dev_err(bdc->dev, "%s is already bound to %s\n", | ||
377 | bdc->gadget.name, | ||
378 | bdc->gadget_driver->driver.name); | ||
379 | ret = -EBUSY; | ||
380 | goto err; | ||
381 | } | ||
382 | /* | ||
383 | * Run the controller from here and when BDC is connected to | ||
384 | * Host then driver will receive a USPC SR with VBUS present | ||
385 | * and then driver will do a softconnect. | ||
386 | */ | ||
387 | ret = bdc_run(bdc); | ||
388 | if (ret) { | ||
389 | dev_err(bdc->dev, "%s bdc run fail\n", __func__); | ||
390 | goto err; | ||
391 | } | ||
392 | bdc->gadget_driver = driver; | ||
393 | bdc->gadget.dev.driver = &driver->driver; | ||
394 | err: | ||
395 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
396 | |||
397 | return ret; | ||
398 | } | ||
399 | |||
400 | static int bdc_udc_stop(struct usb_gadget *gadget) | ||
401 | { | ||
402 | struct bdc *bdc = gadget_to_bdc(gadget); | ||
403 | unsigned long flags; | ||
404 | |||
405 | dev_dbg(bdc->dev, "%s()\n", __func__); | ||
406 | spin_lock_irqsave(&bdc->lock, flags); | ||
407 | bdc_stop(bdc); | ||
408 | bdc->gadget_driver = NULL; | ||
409 | bdc->gadget.dev.driver = NULL; | ||
410 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static int bdc_udc_pullup(struct usb_gadget *gadget, int is_on) | ||
416 | { | ||
417 | struct bdc *bdc = gadget_to_bdc(gadget); | ||
418 | unsigned long flags; | ||
419 | u32 uspc; | ||
420 | |||
421 | dev_dbg(bdc->dev, "%s() is_on:%d\n", __func__, is_on); | ||
422 | if (!gadget) | ||
423 | return -EINVAL; | ||
424 | |||
425 | spin_lock_irqsave(&bdc->lock, flags); | ||
426 | if (!is_on) { | ||
427 | bdc_softdisconn(bdc); | ||
428 | bdc->pullup = false; | ||
429 | } else { | ||
430 | /* | ||
431 | * For a self powered device, we need to wait till we receive | ||
432 | * a VBUS change and Vbus present event, then if pullup flag | ||
433 | * is set, then only we present the Termintation. | ||
434 | */ | ||
435 | bdc->pullup = true; | ||
436 | /* | ||
437 | * Check if BDC is already connected to Host i.e Vbus=1, | ||
438 | * if yes, then present TERM now, this is typical for bus | ||
439 | * powered devices. | ||
440 | */ | ||
441 | uspc = bdc_readl(bdc->regs, BDC_USPC); | ||
442 | if (uspc & BDC_VBS) | ||
443 | bdc_softconn(bdc); | ||
444 | } | ||
445 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static int bdc_udc_set_selfpowered(struct usb_gadget *gadget, | ||
451 | int is_self) | ||
452 | { | ||
453 | struct bdc *bdc = gadget_to_bdc(gadget); | ||
454 | unsigned long flags; | ||
455 | |||
456 | dev_dbg(bdc->dev, "%s()\n", __func__); | ||
457 | spin_lock_irqsave(&bdc->lock, flags); | ||
458 | if (!is_self) | ||
459 | bdc->devstatus |= 1 << USB_DEVICE_SELF_POWERED; | ||
460 | else | ||
461 | bdc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED); | ||
462 | |||
463 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static int bdc_udc_wakeup(struct usb_gadget *gadget) | ||
469 | { | ||
470 | struct bdc *bdc = gadget_to_bdc(gadget); | ||
471 | unsigned long flags; | ||
472 | u8 link_state; | ||
473 | u32 uspc; | ||
474 | int ret = 0; | ||
475 | |||
476 | dev_dbg(bdc->dev, | ||
477 | "%s() bdc->devstatus=%08x\n", | ||
478 | __func__, bdc->devstatus); | ||
479 | |||
480 | if (!(bdc->devstatus & REMOTE_WAKE_ENABLE)) | ||
481 | return -EOPNOTSUPP; | ||
482 | |||
483 | spin_lock_irqsave(&bdc->lock, flags); | ||
484 | uspc = bdc_readl(bdc->regs, BDC_USPC); | ||
485 | link_state = BDC_PST(uspc); | ||
486 | dev_dbg(bdc->dev, "link_state =%d portsc=%x", link_state, uspc); | ||
487 | if (link_state != BDC_LINK_STATE_U3) { | ||
488 | dev_warn(bdc->dev, | ||
489 | "can't wakeup from link state %d\n", | ||
490 | link_state); | ||
491 | ret = -EINVAL; | ||
492 | goto out; | ||
493 | } | ||
494 | if (bdc->gadget.speed == USB_SPEED_SUPER) | ||
495 | bdc->devstatus |= REMOTE_WAKEUP_ISSUED; | ||
496 | |||
497 | uspc &= ~BDC_PST_MASK; | ||
498 | uspc &= (~BDC_USPSC_RW); | ||
499 | uspc |= BDC_PST(BDC_LINK_STATE_U0); | ||
500 | uspc |= BDC_SWS; | ||
501 | bdc_writel(bdc->regs, BDC_USPC, uspc); | ||
502 | uspc = bdc_readl(bdc->regs, BDC_USPC); | ||
503 | link_state = BDC_PST(uspc); | ||
504 | dev_dbg(bdc->dev, "link_state =%d portsc=%x", link_state, uspc); | ||
505 | out: | ||
506 | spin_unlock_irqrestore(&bdc->lock, flags); | ||
507 | |||
508 | return ret; | ||
509 | } | ||
510 | |||
511 | static const struct usb_gadget_ops bdc_gadget_ops = { | ||
512 | .wakeup = bdc_udc_wakeup, | ||
513 | .set_selfpowered = bdc_udc_set_selfpowered, | ||
514 | .pullup = bdc_udc_pullup, | ||
515 | .udc_start = bdc_udc_start, | ||
516 | .udc_stop = bdc_udc_stop, | ||
517 | }; | ||
518 | |||
519 | /* Init the gadget interface and register the udc */ | ||
520 | int bdc_udc_init(struct bdc *bdc) | ||
521 | { | ||
522 | u32 temp; | ||
523 | int ret; | ||
524 | |||
525 | dev_dbg(bdc->dev, "%s()\n", __func__); | ||
526 | bdc->gadget.ops = &bdc_gadget_ops; | ||
527 | bdc->gadget.max_speed = USB_SPEED_SUPER; | ||
528 | bdc->gadget.speed = USB_SPEED_UNKNOWN; | ||
529 | bdc->gadget.dev.parent = bdc->dev; | ||
530 | |||
531 | bdc->gadget.sg_supported = false; | ||
532 | |||
533 | |||
534 | bdc->gadget.name = BRCM_BDC_NAME; | ||
535 | ret = devm_request_irq(bdc->dev, bdc->irq, bdc_udc_interrupt, | ||
536 | IRQF_SHARED , BRCM_BDC_NAME, bdc); | ||
537 | if (ret) { | ||
538 | dev_err(bdc->dev, | ||
539 | "failed to request irq #%d %d\n", | ||
540 | bdc->irq, ret); | ||
541 | return ret; | ||
542 | } | ||
543 | |||
544 | ret = bdc_init_ep(bdc); | ||
545 | if (ret) { | ||
546 | dev_err(bdc->dev, "bdc init ep fail: %d\n", ret); | ||
547 | return ret; | ||
548 | } | ||
549 | |||
550 | ret = usb_add_gadget_udc(bdc->dev, &bdc->gadget); | ||
551 | if (ret) { | ||
552 | dev_err(bdc->dev, "failed to register udc\n"); | ||
553 | goto err0; | ||
554 | } | ||
555 | usb_gadget_set_state(&bdc->gadget, USB_STATE_NOTATTACHED); | ||
556 | bdc->bdc_ep_array[1]->desc = &bdc_gadget_ep0_desc; | ||
557 | /* | ||
558 | * Allocate bd list for ep0 only, ep0 will be enabled on connect | ||
559 | * status report when the speed is known | ||
560 | */ | ||
561 | ret = bdc_ep_enable(bdc->bdc_ep_array[1]); | ||
562 | if (ret) { | ||
563 | dev_err(bdc->dev, "fail to enable %s\n", | ||
564 | bdc->bdc_ep_array[1]->name); | ||
565 | goto err1; | ||
566 | } | ||
567 | INIT_DELAYED_WORK(&bdc->func_wake_notify, bdc_func_wake_timer); | ||
568 | /* Enable Interrupts */ | ||
569 | temp = bdc_readl(bdc->regs, BDC_BDCSC); | ||
570 | temp |= BDC_GIE; | ||
571 | bdc_writel(bdc->regs, BDC_BDCSC, temp); | ||
572 | return 0; | ||
573 | err1: | ||
574 | usb_del_gadget_udc(&bdc->gadget); | ||
575 | err0: | ||
576 | bdc_free_ep(bdc); | ||
577 | |||
578 | return ret; | ||
579 | } | ||
580 | |||
581 | void bdc_udc_exit(struct bdc *bdc) | ||
582 | { | ||
583 | dev_dbg(bdc->dev, "%s()\n", __func__); | ||
584 | bdc_ep_disable(bdc->bdc_ep_array[1]); | ||
585 | usb_del_gadget_udc(&bdc->gadget); | ||
586 | bdc_free_ep(bdc); | ||
587 | } | ||