1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2015 MediaTek Inc.
5 * Zhigang.Wei <zhigang.wei@mediatek.com>
6 * Chunfeng.Yun <chunfeng.yun@mediatek.com>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/slab.h>
16 #define SS_BW_BOUNDARY 51000
17 /* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */
18 #define HS_BW_BOUNDARY 6144
19 /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
20 #define FS_PAYLOAD_MAX 188
22 /* mtk scheduler bitmasks */
23 #define EP_BPKTS(p) ((p) & 0x3f)
24 #define EP_BCSCOUNT(p) (((p) & 0x7) << 8)
25 #define EP_BBM(p) ((p) << 11)
26 #define EP_BOFFSET(p) ((p) & 0x3fff)
27 #define EP_BREPEAT(p) (((p) & 0x7fff) << 16)
29 static int is_fs_or_ls(enum usb_device_speed speed
)
31 return speed
== USB_SPEED_FULL
|| speed
== USB_SPEED_LOW
;
35 * get the index of bandwidth domains array which @ep belongs to.
37 * the bandwidth domain array is saved to @sch_array of struct xhci_hcd_mtk,
38 * each HS root port is treated as a single bandwidth domain,
39 * but each SS root port is treated as two bandwidth domains, one for IN eps,
41 * @real_port value is defined as follow according to xHCI spec:
42 * 1 for SSport0, ..., N+1 for SSportN, N+2 for HSport0, N+3 for HSport1, etc
43 * so the bandwidth domain array is organized as follow for simplification:
44 * SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY
46 static int get_bw_index(struct xhci_hcd
*xhci
, struct usb_device
*udev
,
47 struct usb_host_endpoint
*ep
)
49 struct xhci_virt_device
*virt_dev
;
52 virt_dev
= xhci
->devs
[udev
->slot_id
];
54 if (udev
->speed
== USB_SPEED_SUPER
) {
55 if (usb_endpoint_dir_out(&ep
->desc
))
56 bw_index
= (virt_dev
->real_port
- 1) * 2;
58 bw_index
= (virt_dev
->real_port
- 1) * 2 + 1;
60 /* add one more for each SS port */
61 bw_index
= virt_dev
->real_port
+ xhci
->usb3_rhub
.num_ports
- 1;
67 static void setup_sch_info(struct usb_device
*udev
,
68 struct xhci_ep_ctx
*ep_ctx
, struct mu3h_sch_ep_info
*sch_ep
)
77 ep_type
= CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx
->ep_info2
));
78 ep_interval
= CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx
->ep_info
));
79 max_packet_size
= MAX_PACKET_DECODED(le32_to_cpu(ep_ctx
->ep_info2
));
80 max_burst
= CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx
->ep_info2
));
81 mult
= CTX_TO_EP_MULT(le32_to_cpu(ep_ctx
->ep_info
));
83 sch_ep
->esit
= 1 << ep_interval
;
85 sch_ep
->burst_mode
= 0;
87 if (udev
->speed
== USB_SPEED_HIGH
) {
91 * usb_20 spec section5.9
92 * a single microframe is enough for HS synchromous endpoints
95 sch_ep
->num_budget_microframes
= 1;
99 * xHCI spec section6.2.3.4
100 * @max_burst is the number of additional transactions
101 * opportunities per microframe
103 sch_ep
->pkts
= max_burst
+ 1;
104 sch_ep
->bw_cost_per_microframe
= max_packet_size
* sch_ep
->pkts
;
105 } else if (udev
->speed
== USB_SPEED_SUPER
) {
106 /* usb3_r1 spec section4.4.7 & 4.4.8 */
107 sch_ep
->cs_count
= 0;
108 esit_pkts
= (mult
+ 1) * (max_burst
+ 1);
109 if (ep_type
== INT_IN_EP
|| ep_type
== INT_OUT_EP
) {
110 sch_ep
->pkts
= esit_pkts
;
111 sch_ep
->num_budget_microframes
= 1;
115 if (ep_type
== ISOC_IN_EP
|| ep_type
== ISOC_OUT_EP
) {
116 if (sch_ep
->esit
== 1)
117 sch_ep
->pkts
= esit_pkts
;
118 else if (esit_pkts
<= sch_ep
->esit
)
121 sch_ep
->pkts
= roundup_pow_of_two(esit_pkts
)
124 sch_ep
->num_budget_microframes
=
125 DIV_ROUND_UP(esit_pkts
, sch_ep
->pkts
);
127 if (sch_ep
->num_budget_microframes
> 1)
132 sch_ep
->bw_cost_per_microframe
= max_packet_size
* sch_ep
->pkts
;
133 } else if (is_fs_or_ls(udev
->speed
)) {
136 * usb_20 spec section11.18.4
140 sch_ep
->pkts
= 1; /* at most one packet for each microframe */
141 if (ep_type
== INT_IN_EP
|| ep_type
== INT_OUT_EP
) {
142 sch_ep
->cs_count
= 3; /* at most need 3 CS*/
143 /* one for SS and one for budgeted transaction */
144 sch_ep
->num_budget_microframes
= sch_ep
->cs_count
+ 2;
145 sch_ep
->bw_cost_per_microframe
= max_packet_size
;
147 if (ep_type
== ISOC_OUT_EP
) {
150 * the best case FS budget assumes that 188 FS bytes
151 * occur in each microframe
153 sch_ep
->num_budget_microframes
= DIV_ROUND_UP(
154 max_packet_size
, FS_PAYLOAD_MAX
);
155 sch_ep
->bw_cost_per_microframe
= FS_PAYLOAD_MAX
;
156 sch_ep
->cs_count
= sch_ep
->num_budget_microframes
;
158 if (ep_type
== ISOC_IN_EP
) {
159 /* at most need additional two CS. */
160 sch_ep
->cs_count
= DIV_ROUND_UP(
161 max_packet_size
, FS_PAYLOAD_MAX
) + 2;
162 sch_ep
->num_budget_microframes
= sch_ep
->cs_count
+ 2;
163 sch_ep
->bw_cost_per_microframe
= FS_PAYLOAD_MAX
;
168 /* Get maximum bandwidth when we schedule at offset slot. */
169 static u32
get_max_bw(struct mu3h_sch_bw_info
*sch_bw
,
170 struct mu3h_sch_ep_info
*sch_ep
, u32 offset
)
177 num_esit
= XHCI_MTK_MAX_ESIT
/ sch_ep
->esit
;
178 for (i
= 0; i
< num_esit
; i
++) {
179 u32 base
= offset
+ i
* sch_ep
->esit
;
181 for (j
= 0; j
< sch_ep
->num_budget_microframes
; j
++) {
182 if (sch_bw
->bus_bw
[base
+ j
] > max_bw
)
183 max_bw
= sch_bw
->bus_bw
[base
+ j
];
189 static void update_bus_bw(struct mu3h_sch_bw_info
*sch_bw
,
190 struct mu3h_sch_ep_info
*sch_ep
, int bw_cost
)
197 num_esit
= XHCI_MTK_MAX_ESIT
/ sch_ep
->esit
;
198 for (i
= 0; i
< num_esit
; i
++) {
199 base
= sch_ep
->offset
+ i
* sch_ep
->esit
;
200 for (j
= 0; j
< sch_ep
->num_budget_microframes
; j
++)
201 sch_bw
->bus_bw
[base
+ j
] += bw_cost
;
205 static int check_sch_bw(struct usb_device
*udev
,
206 struct mu3h_sch_bw_info
*sch_bw
, struct mu3h_sch_ep_info
*sch_ep
)
210 u32 num_budget_microframes
;
216 if (sch_ep
->esit
> XHCI_MTK_MAX_ESIT
)
217 sch_ep
->esit
= XHCI_MTK_MAX_ESIT
;
220 num_budget_microframes
= sch_ep
->num_budget_microframes
;
223 * Search through all possible schedule microframes.
224 * and find a microframe where its worst bandwidth is minimum.
228 for (offset
= 0; offset
< esit
; offset
++) {
229 if ((offset
+ num_budget_microframes
) > sch_ep
->esit
)
233 * usb_20 spec section11.18:
234 * must never schedule Start-Split in Y6
236 if (is_fs_or_ls(udev
->speed
) && (offset
% 8 == 6))
239 worst_bw
= get_max_bw(sch_bw
, sch_ep
, offset
);
240 if (min_bw
> worst_bw
) {
247 sch_ep
->offset
= min_index
;
249 bw_boundary
= (udev
->speed
== USB_SPEED_SUPER
)
250 ? SS_BW_BOUNDARY
: HS_BW_BOUNDARY
;
252 /* check bandwidth */
253 if (min_bw
+ sch_ep
->bw_cost_per_microframe
> bw_boundary
)
256 /* update bus bandwidth info */
257 update_bus_bw(sch_bw
, sch_ep
, sch_ep
->bw_cost_per_microframe
);
262 static bool need_bw_sch(struct usb_host_endpoint
*ep
,
263 enum usb_device_speed speed
, int has_tt
)
265 /* only for periodic endpoints */
266 if (usb_endpoint_xfer_control(&ep
->desc
)
267 || usb_endpoint_xfer_bulk(&ep
->desc
))
271 * for LS & FS periodic endpoints which its device is not behind
272 * a TT are also ignored, root-hub will schedule them directly,
273 * but need set @bpkts field of endpoint context to 1.
275 if (is_fs_or_ls(speed
) && !has_tt
)
281 int xhci_mtk_sch_init(struct xhci_hcd_mtk
*mtk
)
283 struct xhci_hcd
*xhci
= hcd_to_xhci(mtk
->hcd
);
284 struct mu3h_sch_bw_info
*sch_array
;
288 /* ss IN and OUT are separated */
289 num_usb_bus
= xhci
->usb3_rhub
.num_ports
* 2 + xhci
->usb2_rhub
.num_ports
;
291 sch_array
= kcalloc(num_usb_bus
, sizeof(*sch_array
), GFP_KERNEL
);
292 if (sch_array
== NULL
)
295 for (i
= 0; i
< num_usb_bus
; i
++)
296 INIT_LIST_HEAD(&sch_array
[i
].bw_ep_list
);
298 mtk
->sch_array
= sch_array
;
302 EXPORT_SYMBOL_GPL(xhci_mtk_sch_init
);
304 void xhci_mtk_sch_exit(struct xhci_hcd_mtk
*mtk
)
306 kfree(mtk
->sch_array
);
308 EXPORT_SYMBOL_GPL(xhci_mtk_sch_exit
);
310 int xhci_mtk_add_ep_quirk(struct usb_hcd
*hcd
, struct usb_device
*udev
,
311 struct usb_host_endpoint
*ep
)
313 struct xhci_hcd_mtk
*mtk
= hcd_to_mtk(hcd
);
314 struct xhci_hcd
*xhci
;
315 struct xhci_ep_ctx
*ep_ctx
;
316 struct xhci_slot_ctx
*slot_ctx
;
317 struct xhci_virt_device
*virt_dev
;
318 struct mu3h_sch_bw_info
*sch_bw
;
319 struct mu3h_sch_ep_info
*sch_ep
;
320 struct mu3h_sch_bw_info
*sch_array
;
321 unsigned int ep_index
;
325 xhci
= hcd_to_xhci(hcd
);
326 virt_dev
= xhci
->devs
[udev
->slot_id
];
327 ep_index
= xhci_get_endpoint_index(&ep
->desc
);
328 slot_ctx
= xhci_get_slot_ctx(xhci
, virt_dev
->in_ctx
);
329 ep_ctx
= xhci_get_ep_ctx(xhci
, virt_dev
->in_ctx
, ep_index
);
330 sch_array
= mtk
->sch_array
;
332 xhci_dbg(xhci
, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n",
333 __func__
, usb_endpoint_type(&ep
->desc
), udev
->speed
,
334 usb_endpoint_maxp(&ep
->desc
),
335 usb_endpoint_dir_in(&ep
->desc
), ep
);
337 if (!need_bw_sch(ep
, udev
->speed
, slot_ctx
->tt_info
& TT_SLOT
)) {
339 * set @bpkts to 1 if it is LS or FS periodic endpoint, and its
340 * device does not connected through an external HS hub
342 if (usb_endpoint_xfer_int(&ep
->desc
)
343 || usb_endpoint_xfer_isoc(&ep
->desc
))
344 ep_ctx
->reserved
[0] |= cpu_to_le32(EP_BPKTS(1));
349 bw_index
= get_bw_index(xhci
, udev
, ep
);
350 sch_bw
= &sch_array
[bw_index
];
352 sch_ep
= kzalloc(sizeof(struct mu3h_sch_ep_info
), GFP_NOIO
);
356 setup_sch_info(udev
, ep_ctx
, sch_ep
);
358 ret
= check_sch_bw(udev
, sch_bw
, sch_ep
);
360 xhci_err(xhci
, "Not enough bandwidth!\n");
365 list_add_tail(&sch_ep
->endpoint
, &sch_bw
->bw_ep_list
);
368 ep_ctx
->reserved
[0] |= cpu_to_le32(EP_BPKTS(sch_ep
->pkts
)
369 | EP_BCSCOUNT(sch_ep
->cs_count
) | EP_BBM(sch_ep
->burst_mode
));
370 ep_ctx
->reserved
[1] |= cpu_to_le32(EP_BOFFSET(sch_ep
->offset
)
371 | EP_BREPEAT(sch_ep
->repeat
));
373 xhci_dbg(xhci
, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
374 sch_ep
->pkts
, sch_ep
->cs_count
, sch_ep
->burst_mode
,
375 sch_ep
->offset
, sch_ep
->repeat
);
379 EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk
);
381 void xhci_mtk_drop_ep_quirk(struct usb_hcd
*hcd
, struct usb_device
*udev
,
382 struct usb_host_endpoint
*ep
)
384 struct xhci_hcd_mtk
*mtk
= hcd_to_mtk(hcd
);
385 struct xhci_hcd
*xhci
;
386 struct xhci_slot_ctx
*slot_ctx
;
387 struct xhci_virt_device
*virt_dev
;
388 struct mu3h_sch_bw_info
*sch_array
;
389 struct mu3h_sch_bw_info
*sch_bw
;
390 struct mu3h_sch_ep_info
*sch_ep
;
393 xhci
= hcd_to_xhci(hcd
);
394 virt_dev
= xhci
->devs
[udev
->slot_id
];
395 slot_ctx
= xhci_get_slot_ctx(xhci
, virt_dev
->in_ctx
);
396 sch_array
= mtk
->sch_array
;
398 xhci_dbg(xhci
, "%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n",
399 __func__
, usb_endpoint_type(&ep
->desc
), udev
->speed
,
400 usb_endpoint_maxp(&ep
->desc
),
401 usb_endpoint_dir_in(&ep
->desc
), ep
);
403 if (!need_bw_sch(ep
, udev
->speed
, slot_ctx
->tt_info
& TT_SLOT
))
406 bw_index
= get_bw_index(xhci
, udev
, ep
);
407 sch_bw
= &sch_array
[bw_index
];
409 list_for_each_entry(sch_ep
, &sch_bw
->bw_ep_list
, endpoint
) {
410 if (sch_ep
->ep
== ep
) {
411 update_bus_bw(sch_bw
, sch_ep
,
412 -sch_ep
->bw_cost_per_microframe
);
413 list_del(&sch_ep
->endpoint
);
419 EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk
);