2 * bdc_cmd.c - BRCM BDC USB3.0 device controller
4 * Copyright (C) 2014 Broadcom Corporation
6 * Author: Ashwini Pahuja
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.
14 #include <linux/scatterlist.h>
15 #include <linux/slab.h>
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
)
25 u32 timeout
= BDC_CMD_TIMEOUT
;
29 bdc_writel(bdc
->regs
, BDC_CMDPAR0
, param0
);
30 bdc_writel(bdc
->regs
, BDC_CMDPAR1
, param1
);
31 bdc_writel(bdc
->regs
, BDC_CMDPAR2
, param2
);
34 /* Make sure the cmd params are written before asking HW to exec cmd */
36 bdc_writel(bdc
->regs
, BDC_CMDSC
, cmd_sc
| BDC_CMD_CWS
| BDC_CMD_SRD
);
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
) {
43 "command completed cmd_sts:%x\n", cmd_status
);
50 "command operation timedout cmd_status=%d\n", cmd_status
);
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
)
63 temp
= bdc_readl(bdc
->regs
, BDC_CMDSC
);
65 "%s:CMDSC:%08x cmdsc:%08x param0=%08x param1=%08x param2=%08x\n",
66 __func__
, temp
, cmd_sc
, param0
, param1
, param2
);
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
);
73 ret
= bdc_issue_cmd(bdc
, cmd_sc
, param0
, param1
, param2
);
76 dev_dbg(bdc
->dev
, "command completed successfully\n");
81 dev_err(bdc
->dev
, "command parameter error\n");
86 dev_err(bdc
->dev
, "Invalid device/ep state\n");
91 dev_err(bdc
->dev
, "Command failed?\n");
96 dev_err(bdc
->dev
, "BDC Internal error\n");
103 "command timedout waited for %dusec\n",
109 dev_dbg(bdc
->dev
, "Unknown command completion code:%x\n", ret
);
115 /* Deconfigure the endpoint from HW */
116 int bdc_dconfig_ep(struct bdc
*bdc
, struct bdc_ep
*ep
)
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__
,
124 return bdc_submit_cmd(bdc
, cmd_sc
, 0, 0, 0);
127 /* Reinitalize the bdlist after config ep command */
128 static void ep_bd_list_reinit(struct bdc_ep
*ep
)
130 struct bdc
*bdc
= ep
->bdc
;
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
);
141 /* Configure an endpoint */
142 int bdc_config_ep(struct bdc
*bdc
, struct bdc_ep
*ep
)
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
;
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
);
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;
163 mps
= usb_endpoint_maxp(desc
);
165 param2
|= mps
<< MP_SHIFT
;
166 param2
|= usb_endpoint_type(desc
) << EPT_SHIFT
;
168 switch (bdc
->gadget
.speed
) {
169 case USB_SPEED_SUPER
:
170 if (usb_endpoint_xfer_int(desc
) ||
171 usb_endpoint_xfer_isoc(desc
)) {
173 if (usb_endpoint_xfer_isoc(desc
) && comp_desc
)
174 mul
= comp_desc
->bmAttributes
;
177 param2
|= mul
<< EPM_SHIFT
;
179 mbs
= comp_desc
->bMaxBurst
;
180 param2
|= mbs
<< MB_SHIFT
;
184 if (usb_endpoint_xfer_isoc(desc
) ||
185 usb_endpoint_xfer_int(desc
)) {
188 mbs
= (usb_endpoint_maxp(desc
) & 0x1800) >> 11;
189 param2
|= mbs
<< MB_SHIFT
;
195 /* the hardware accepts SI in 125usec range */
196 if (usb_endpoint_xfer_isoc(desc
))
200 * FS Int endpoints can have si of 1-255ms but the controller
201 * accepts 2^bInterval*125usec, so convert ms to nearest power
204 if (usb_endpoint_xfer_int(desc
))
205 si
= fls(desc
->bInterval
* 8) - 1;
210 dev_err(bdc
->dev
, "UNKNOWN speed ERR\n");
214 cmd_sc
|= BDC_CMD_EPC
|BDC_CMD_EPN(ep
->ep_num
)|BDC_SUB_CMD_ADD_EP
;
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
);
219 dev_err(bdc
->dev
, "command failed :%x\n", ret
);
222 ep_bd_list_reinit(ep
);
228 * Change the HW deq pointer, if this command is successful, HW will start
229 * fetching the next bd from address dma_addr.
231 int bdc_ep_bla(struct bdc
*bdc
, struct bdc_ep
*ep
, dma_addr_t dma_addr
)
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
);
243 cmd_sc
|= BDC_CMD_EPN(ep
->ep_num
)|BDC_CMD_BLA
;
244 dev_dbg(bdc
->dev
, "cmd_sc=%x\n", cmd_sc
);
246 return bdc_submit_cmd(bdc
, cmd_sc
, param0
, param1
, 0);
249 /* Set the address sent bu Host in SET_ADD request */
250 int bdc_address_device(struct bdc
*bdc
, u32 add
)
255 dev_dbg(bdc
->dev
, "%s: add=%d\n", __func__
, add
);
256 cmd_sc
|= BDC_SUB_CMD_ADD
|BDC_CMD_DVC
;
259 return bdc_submit_cmd(bdc
, cmd_sc
, 0, 0, param2
);
262 /* Send a Function Wake notification packet using FH command */
263 int bdc_function_wake_fh(struct bdc
*bdc
, u8 intf
)
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
);
277 return bdc_submit_cmd(bdc
, cmd_sc
, param0
, param1
, 0);
280 /* Send a Function Wake notification packet using DNC command */
281 int bdc_function_wake(struct bdc
*bdc
, u8 intf
)
286 dev_dbg(bdc
->dev
, "%s intf=%d", __func__
, intf
);
288 cmd_sc
|= BDC_SUB_CMD_FWK
|BDC_CMD_DNC
;
290 return bdc_submit_cmd(bdc
, cmd_sc
, 0, 0, param2
);
293 /* Stall the endpoint */
294 int bdc_ep_set_stall(struct bdc
*bdc
, int epnum
)
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
;
302 return bdc_submit_cmd(bdc
, cmd_sc
, 0, 0, 0);
305 /* resets the endpoint, called when host sends CLEAR_FEATURE(HALT) */
306 int bdc_ep_clear_stall(struct bdc
*bdc
, int epnum
)
312 dev_dbg(bdc
->dev
, "%s: epnum=%d\n", __func__
, epnum
);
313 ep
= bdc
->bdc_ep_array
[epnum
];
315 * If we are not in stalled then stall Endpoint and issue clear stall,
316 * his will reset the seq number for non EP0.
319 /* if the endpoint it not stallled */
320 if (!(ep
->flags
& BDC_EP_STALL
)) {
321 ret
= bdc_ep_set_stall(bdc
, epnum
);
326 /* Preserve the seq number for ep0 only */
328 cmd_sc
|= BDC_CMD_EPO_RST_SN
;
330 /* issue a reset endpoint command */
331 cmd_sc
|= BDC_SUB_CMD_EP_RST
| BDC_CMD_EPN(epnum
) | BDC_CMD_EPO
;
333 ret
= bdc_submit_cmd(bdc
, cmd_sc
, 0, 0, 0);
335 dev_err(bdc
->dev
, "command failed:%x\n", ret
);
338 bdc_notify_xfr(bdc
, epnum
);
343 /* Stop the endpoint, called when software wants to dequeue some request */
344 int bdc_stop_ep(struct bdc
*bdc
, int epnum
)
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");
358 if ((ep
->flags
& BDC_EP_STALL
) || (ep
->flags
& BDC_EP_STOP
))
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
;
365 ret
= bdc_submit_cmd(bdc
, cmd_sc
, 0, 0, 0);
368 "stop endpoint command didn't complete:%d ep:%s\n",
372 ep
->flags
|= BDC_EP_STOP
;