[omap]: switch the am335x-evmsk to the new wlcore bindings
[openwrt/svn-archive/archive.git] / target / linux / ramips / files / drivers / usb / host / xhci-mtk-scheduler.c
1 #include "xhci-mtk-scheduler.h"
2 #include <linux/kernel.h> /* printk() */
3
4 static struct sch_ep **ss_out_eps[MAX_EP_NUM];
5 static struct sch_ep **ss_in_eps[MAX_EP_NUM];
6 static struct sch_ep **hs_eps[MAX_EP_NUM]; //including tt isoc
7 static struct sch_ep **tt_intr_eps[MAX_EP_NUM];
8
9
10 int mtk_xhci_scheduler_init(void){
11 int i;
12
13 for(i=0; i<MAX_EP_NUM; i++){
14 ss_out_eps[i] = NULL;
15 }
16 for(i=0; i<MAX_EP_NUM; i++){
17 ss_in_eps[i] = NULL;
18 }
19 for(i=0; i<MAX_EP_NUM; i++){
20 hs_eps[i] = NULL;
21 }
22 for(i=0; i<MAX_EP_NUM; i++){
23 tt_intr_eps[i] = NULL;
24 }
25 return 0;
26 }
27
28 int add_sch_ep(int dev_speed, int is_in, int isTT, int ep_type, int maxp, int interval, int burst
29 , int mult, int offset, int repeat, int pkts, int cs_count, int burst_mode
30 , int bw_cost, mtk_u32 *ep, struct sch_ep *tmp_ep){
31
32 struct sch_ep **ep_array;
33 int i;
34
35 if(is_in && dev_speed == USB_SPEED_SUPER ){
36 ep_array = (struct sch_ep **)ss_in_eps;
37 }
38 else if(dev_speed == USB_SPEED_SUPER){
39 ep_array = (struct sch_ep **)ss_out_eps;
40 }
41 else if(dev_speed == USB_SPEED_HIGH || (isTT && ep_type == USB_EP_ISOC)){
42 ep_array = (struct sch_ep **)hs_eps;
43 }
44 else{
45 ep_array = (struct sch_ep **)tt_intr_eps;
46 }
47 for(i=0; i<MAX_EP_NUM; i++){
48 if(ep_array[i] == NULL){
49 tmp_ep->dev_speed = dev_speed;
50 tmp_ep->isTT = isTT;
51 tmp_ep->is_in = is_in;
52 tmp_ep->ep_type = ep_type;
53 tmp_ep->maxp = maxp;
54 tmp_ep->interval = interval;
55 tmp_ep->burst = burst;
56 tmp_ep->mult = mult;
57 tmp_ep->offset = offset;
58 tmp_ep->repeat = repeat;
59 tmp_ep->pkts = pkts;
60 tmp_ep->cs_count = cs_count;
61 tmp_ep->burst_mode = burst_mode;
62 tmp_ep->bw_cost = bw_cost;
63 tmp_ep->ep = ep;
64 ep_array[i] = tmp_ep;
65 return SCH_SUCCESS;
66 }
67 }
68 return SCH_FAIL;
69 }
70
71 int count_ss_bw(int is_in, int ep_type, int maxp, int interval, int burst, int mult, int offset, int repeat
72 , int td_size){
73 int i, j, k;
74 int bw_required[3];
75 int final_bw_required;
76 int bw_required_per_repeat;
77 int tmp_bw_required;
78 struct sch_ep *cur_sch_ep;
79 struct sch_ep **ep_array;
80 int cur_offset;
81 int cur_ep_offset;
82 int tmp_offset;
83 int tmp_interval;
84 int ep_offset;
85 int ep_interval;
86 int ep_repeat;
87 int ep_mult;
88
89 if(is_in){
90 ep_array = (struct sch_ep **)ss_in_eps;
91 }
92 else{
93 ep_array = (struct sch_ep **)ss_out_eps;
94 }
95
96 bw_required[0] = 0;
97 bw_required[1] = 0;
98 bw_required[2] = 0;
99
100 if(repeat == 0){
101 final_bw_required = 0;
102 for(i=0; i<MAX_EP_NUM; i++){
103 cur_sch_ep = ep_array[i];
104 if(cur_sch_ep == NULL){
105 continue;
106 }
107 ep_interval = cur_sch_ep->interval;
108 ep_offset = cur_sch_ep->offset;
109 if(cur_sch_ep->repeat == 0){
110 if(ep_interval >= interval){
111 tmp_offset = ep_offset + ep_interval - offset;
112 tmp_interval = interval;
113 }
114 else{
115 tmp_offset = offset + interval - ep_offset;
116 tmp_interval = ep_interval;
117 }
118 if(tmp_offset % tmp_interval == 0){
119 final_bw_required += cur_sch_ep->bw_cost;
120 }
121 }
122 else{
123 ep_repeat = cur_sch_ep->repeat;
124 ep_mult = cur_sch_ep->mult;
125 for(k=0; k<=ep_mult; k++){
126 cur_ep_offset = ep_offset+(k*ep_mult);
127 if(ep_interval >= interval){
128 tmp_offset = cur_ep_offset + ep_interval - offset;
129 tmp_interval = interval;
130 }
131 else{
132 tmp_offset = offset + interval - cur_ep_offset;
133 tmp_interval = ep_interval;
134 }
135 if(tmp_offset % tmp_interval == 0){
136 final_bw_required += cur_sch_ep->bw_cost;
137 break;
138 }
139 }
140 }
141 }
142 final_bw_required += td_size;
143 }
144 else{
145 bw_required_per_repeat = maxp * (burst+1);
146 for(j=0; j<=mult; j++){
147 tmp_bw_required = 0;
148 cur_offset = offset+(j*repeat);
149 for(i=0; i<MAX_EP_NUM; i++){
150 cur_sch_ep = ep_array[i];
151 if(cur_sch_ep == NULL){
152 continue;
153 }
154 ep_interval = cur_sch_ep->interval;
155 ep_offset = cur_sch_ep->offset;
156 if(cur_sch_ep->repeat == 0){
157 if(ep_interval >= interval){
158 tmp_offset = ep_offset + ep_interval - cur_offset;
159 tmp_interval = interval;
160 }
161 else{
162 tmp_offset = cur_offset + interval - ep_offset;
163 tmp_interval = ep_interval;
164 }
165 if(tmp_offset % tmp_interval == 0){
166 tmp_bw_required += cur_sch_ep->bw_cost;
167 }
168 }
169 else{
170 ep_repeat = cur_sch_ep->repeat;
171 ep_mult = cur_sch_ep->mult;
172 for(k=0; k<=ep_mult; k++){
173 cur_ep_offset = ep_offset+(k*ep_repeat);
174 if(ep_interval >= interval){
175 tmp_offset = cur_ep_offset + ep_interval - cur_offset;
176 tmp_interval = interval;
177 }
178 else{
179 tmp_offset = cur_offset + interval - cur_ep_offset;
180 tmp_interval = ep_interval;
181 }
182 if(tmp_offset % tmp_interval == 0){
183 tmp_bw_required += cur_sch_ep->bw_cost;
184 break;
185 }
186 }
187 }
188 }
189 bw_required[j] = tmp_bw_required;
190 }
191 final_bw_required = SS_BW_BOUND;
192 for(j=0; j<=mult; j++){
193 if(bw_required[j] < final_bw_required){
194 final_bw_required = bw_required[j];
195 }
196 }
197 final_bw_required += bw_required_per_repeat;
198 }
199 return final_bw_required;
200 }
201
202 int count_hs_bw(int ep_type, int maxp, int interval, int offset, int td_size){
203 int i;
204 int bw_required;
205 struct sch_ep *cur_sch_ep;
206 int tmp_offset;
207 int tmp_interval;
208 int ep_offset;
209 int ep_interval;
210 int cur_tt_isoc_interval; //for isoc tt check
211
212 bw_required = 0;
213 for(i=0; i<MAX_EP_NUM; i++){
214
215 cur_sch_ep = (struct sch_ep *)hs_eps[i];
216 if(cur_sch_ep == NULL){
217 continue;
218 }
219 ep_offset = cur_sch_ep->offset;
220 ep_interval = cur_sch_ep->interval;
221
222 if(cur_sch_ep->isTT && cur_sch_ep->ep_type == USB_EP_ISOC){
223 cur_tt_isoc_interval = ep_interval<<3;
224 if(ep_interval >= interval){
225 tmp_offset = ep_offset + cur_tt_isoc_interval - offset;
226 tmp_interval = interval;
227 }
228 else{
229 tmp_offset = offset + interval - ep_offset;
230 tmp_interval = cur_tt_isoc_interval;
231 }
232 if(cur_sch_ep->is_in){
233 if((tmp_offset%tmp_interval >=2) && (tmp_offset%tmp_interval <= cur_sch_ep->cs_count)){
234 bw_required += 188;
235 }
236 }
237 else{
238 if(tmp_offset%tmp_interval <= cur_sch_ep->cs_count){
239 bw_required += 188;
240 }
241 }
242 }
243 else{
244 if(ep_interval >= interval){
245 tmp_offset = ep_offset + ep_interval - offset;
246 tmp_interval = interval;
247 }
248 else{
249 tmp_offset = offset + interval - ep_offset;
250 tmp_interval = ep_interval;
251 }
252 if(tmp_offset%tmp_interval == 0){
253 bw_required += cur_sch_ep->bw_cost;
254 }
255 }
256 }
257 bw_required += td_size;
258 return bw_required;
259 }
260
261 int count_tt_isoc_bw(int is_in, int maxp, int interval, int offset, int td_size){
262 char is_cs;
263 int mframe_idx, frame_idx, s_frame, s_mframe, cur_mframe;
264 int bw_required, max_bw;
265 int ss_cs_count;
266 int cs_mframe;
267 int max_frame;
268 int i,j;
269 struct sch_ep *cur_sch_ep;
270 int ep_offset;
271 int ep_interval;
272 int ep_cs_count;
273 int tt_isoc_interval; //for isoc tt check
274 int cur_tt_isoc_interval; //for isoc tt check
275 int tmp_offset;
276 int tmp_interval;
277
278 is_cs = 0;
279
280 tt_isoc_interval = interval<<3; //frame to mframe
281 if(is_in){
282 is_cs = 1;
283 }
284 s_frame = offset/8;
285 s_mframe = offset%8;
286 ss_cs_count = (maxp + (188 - 1))/188;
287 if(is_cs){
288 cs_mframe = offset%8 + 2 + ss_cs_count;
289 if (cs_mframe <= 6)
290 ss_cs_count += 2;
291 else if (cs_mframe == 7)
292 ss_cs_count++;
293 else if (cs_mframe > 8)
294 return -1;
295 }
296 max_bw = 0;
297 if(is_in){
298 i=2;
299 }
300 for(cur_mframe = offset+i; i<ss_cs_count; cur_mframe++, i++){
301 bw_required = 0;
302 for(j=0; j<MAX_EP_NUM; j++){
303 cur_sch_ep = (struct sch_ep *)hs_eps[j];
304 if(cur_sch_ep == NULL){
305 continue;
306 }
307 ep_offset = cur_sch_ep->offset;
308 ep_interval = cur_sch_ep->interval;
309 if(cur_sch_ep->isTT && cur_sch_ep->ep_type == USB_EP_ISOC){
310 //isoc tt
311 //check if mframe offset overlap
312 //if overlap, add 188 to the bw
313 cur_tt_isoc_interval = ep_interval<<3;
314 if(cur_tt_isoc_interval >= tt_isoc_interval){
315 tmp_offset = (ep_offset+cur_tt_isoc_interval) - cur_mframe;
316 tmp_interval = tt_isoc_interval;
317 }
318 else{
319 tmp_offset = (cur_mframe+tt_isoc_interval) - ep_offset;
320 tmp_interval = cur_tt_isoc_interval;
321 }
322 if(cur_sch_ep->is_in){
323 if((tmp_offset%tmp_interval >=2) && (tmp_offset%tmp_interval <= cur_sch_ep->cs_count)){
324 bw_required += 188;
325 }
326 }
327 else{
328 if(tmp_offset%tmp_interval <= cur_sch_ep->cs_count){
329 bw_required += 188;
330 }
331 }
332
333 }
334 else if(cur_sch_ep->ep_type == USB_EP_INT || cur_sch_ep->ep_type == USB_EP_ISOC){
335 //check if mframe
336 if(ep_interval >= tt_isoc_interval){
337 tmp_offset = (ep_offset+ep_interval) - cur_mframe;
338 tmp_interval = tt_isoc_interval;
339 }
340 else{
341 tmp_offset = (cur_mframe+tt_isoc_interval) - ep_offset;
342 tmp_interval = ep_interval;
343 }
344 if(tmp_offset%tmp_interval == 0){
345 bw_required += cur_sch_ep->bw_cost;
346 }
347 }
348 }
349 bw_required += 188;
350 if(bw_required > max_bw){
351 max_bw = bw_required;
352 }
353 }
354 return max_bw;
355 }
356
357 int count_tt_intr_bw(int interval, int frame_offset){
358 //check all eps in tt_intr_eps
359 int ret;
360 int i,j;
361 int ep_offset;
362 int ep_interval;
363 int tmp_offset;
364 int tmp_interval;
365 ret = SCH_SUCCESS;
366 struct sch_ep *cur_sch_ep;
367
368 for(i=0; i<MAX_EP_NUM; i++){
369 cur_sch_ep = (struct sch_ep *)tt_intr_eps[i];
370 if(cur_sch_ep == NULL){
371 continue;
372 }
373 ep_offset = cur_sch_ep->offset;
374 ep_interval = cur_sch_ep->interval;
375 if(ep_interval >= interval){
376 tmp_offset = ep_offset + ep_interval - frame_offset;
377 tmp_interval = interval;
378 }
379 else{
380 tmp_offset = frame_offset + interval - ep_offset;
381 tmp_interval = ep_interval;
382 }
383
384 if(tmp_offset%tmp_interval==0){
385 return SCH_FAIL;
386 }
387 }
388 return SCH_SUCCESS;
389 }
390
391 struct sch_ep * mtk_xhci_scheduler_remove_ep(int dev_speed, int is_in, int isTT, int ep_type, mtk_u32 *ep){
392 int i;
393 struct sch_ep **ep_array;
394 struct sch_ep *cur_ep;
395
396 if (is_in && dev_speed == USB_SPEED_SUPER) {
397 ep_array = (struct sch_ep **)ss_in_eps;
398 }
399 else if (dev_speed == USB_SPEED_SUPER) {
400 ep_array = (struct sch_ep **)ss_out_eps;
401 }
402 else if (dev_speed == USB_SPEED_HIGH || (isTT && ep_type == USB_EP_ISOC)) {
403 ep_array = (struct sch_ep **)hs_eps;
404 }
405 else {
406 ep_array = (struct sch_ep **)tt_intr_eps;
407 }
408 for (i = 0; i < MAX_EP_NUM; i++) {
409 cur_ep = (struct sch_ep *)ep_array[i];
410 if(cur_ep != NULL && cur_ep->ep == ep){
411 ep_array[i] = NULL;
412 return cur_ep;
413 }
414 }
415 return NULL;
416 }
417
418 int mtk_xhci_scheduler_add_ep(int dev_speed, int is_in, int isTT, int ep_type, int maxp, int interval, int burst
419 , int mult, mtk_u32 *ep, mtk_u32 *ep_ctx, struct sch_ep *sch_ep){
420 mtk_u32 bPkts = 0;
421 mtk_u32 bCsCount = 0;
422 mtk_u32 bBm = 1;
423 mtk_u32 bOffset = 0;
424 mtk_u32 bRepeat = 0;
425 int ret;
426 struct mtk_xhci_ep_ctx *temp_ep_ctx;
427 int td_size;
428 int mframe_idx, frame_idx;
429 int bw_cost;
430 int cur_bw, best_bw, best_bw_idx,repeat, max_repeat, best_bw_repeat;
431 int cur_offset, cs_mframe;
432 int break_out;
433 int frame_interval;
434
435 printk(KERN_ERR "add_ep parameters, dev_speed %d, is_in %d, isTT %d, ep_type %d, maxp %d, interval %d, burst %d, mult %d, ep 0x%x, ep_ctx 0x%x, sch_ep 0x%x\n", dev_speed, is_in, isTT, ep_type, maxp
436 , interval, burst, mult, ep, ep_ctx, sch_ep);
437 if(isTT && ep_type == USB_EP_INT && ((dev_speed == USB_SPEED_LOW) || (dev_speed == USB_SPEED_FULL))){
438 frame_interval = interval >> 3;
439 for(frame_idx=0; frame_idx<frame_interval; frame_idx++){
440 printk(KERN_ERR "check tt_intr_bw interval %d, frame_idx %d\n", frame_interval, frame_idx);
441 if(count_tt_intr_bw(frame_interval, frame_idx) == SCH_SUCCESS){
442 printk(KERN_ERR "check OK............\n");
443 bOffset = frame_idx<<3;
444 bPkts = 1;
445 bCsCount = 3;
446 bw_cost = maxp;
447 bRepeat = 0;
448 if(add_sch_ep(dev_speed, is_in, isTT, ep_type, maxp, frame_interval, burst, mult
449 , bOffset, bRepeat, bPkts, bCsCount, bBm, maxp, ep, sch_ep) == SCH_FAIL){
450 return SCH_FAIL;
451 }
452 ret = SCH_SUCCESS;
453 break;
454 }
455 }
456 }
457 else if(isTT && ep_type == USB_EP_ISOC){
458 best_bw = HS_BW_BOUND;
459 best_bw_idx = -1;
460 cur_bw = 0;
461 td_size = maxp;
462 break_out = 0;
463 frame_interval = interval>>3;
464 for(frame_idx=0; frame_idx<frame_interval && !break_out; frame_idx++){
465 for(mframe_idx=0; mframe_idx<8; mframe_idx++){
466 cur_offset = (frame_idx*8) + mframe_idx;
467 cur_bw = count_tt_isoc_bw(is_in, maxp, frame_interval, cur_offset, td_size);
468 if(cur_bw > 0 && cur_bw < best_bw){
469 best_bw_idx = cur_offset;
470 best_bw = cur_bw;
471 if(cur_bw == td_size || cur_bw < (HS_BW_BOUND>>1)){
472 break_out = 1;
473 break;
474 }
475 }
476 }
477 }
478 if(best_bw_idx == -1){
479 return SCH_FAIL;
480 }
481 else{
482 bOffset = best_bw_idx;
483 bPkts = 1;
484 bCsCount = (maxp + (188 - 1)) / 188;
485 if(is_in){
486 cs_mframe = bOffset%8 + 2 + bCsCount;
487 if (cs_mframe <= 6)
488 bCsCount += 2;
489 else if (cs_mframe == 7)
490 bCsCount++;
491 }
492 bw_cost = 188;
493 bRepeat = 0;
494 if(add_sch_ep( dev_speed, is_in, isTT, ep_type, maxp, interval, burst, mult
495 , bOffset, bRepeat, bPkts, bCsCount, bBm, bw_cost, ep, sch_ep) == SCH_FAIL){
496 return SCH_FAIL;
497 }
498 ret = SCH_SUCCESS;
499 }
500 }
501 else if((dev_speed == USB_SPEED_FULL || dev_speed == USB_SPEED_LOW) && ep_type == USB_EP_INT){
502 bPkts = 1;
503 ret = SCH_SUCCESS;
504 }
505 else if(dev_speed == USB_SPEED_FULL && ep_type == USB_EP_ISOC){
506 bPkts = 1;
507 ret = SCH_SUCCESS;
508 }
509 else if(dev_speed == USB_SPEED_HIGH && (ep_type == USB_EP_INT || ep_type == USB_EP_ISOC)){
510 best_bw = HS_BW_BOUND;
511 best_bw_idx = -1;
512 cur_bw = 0;
513 td_size = maxp*(burst+1);
514 for(cur_offset = 0; cur_offset<interval; cur_offset++){
515 cur_bw = count_hs_bw(ep_type, maxp, interval, cur_offset, td_size);
516 if(cur_bw > 0 && cur_bw < best_bw){
517 best_bw_idx = cur_offset;
518 best_bw = cur_bw;
519 if(cur_bw == td_size || cur_bw < (HS_BW_BOUND>>1)){
520 break;
521 }
522 }
523 }
524 if(best_bw_idx == -1){
525 return SCH_FAIL;
526 }
527 else{
528 bOffset = best_bw_idx;
529 bPkts = burst + 1;
530 bCsCount = 0;
531 bw_cost = td_size;
532 bRepeat = 0;
533 if(add_sch_ep(dev_speed, is_in, isTT, ep_type, maxp, interval, burst, mult
534 , bOffset, bRepeat, bPkts, bCsCount, bBm, bw_cost, ep, sch_ep) == SCH_FAIL){
535 return SCH_FAIL;
536 }
537 ret = SCH_SUCCESS;
538 }
539 }
540 else if(dev_speed == USB_SPEED_SUPER && (ep_type == USB_EP_INT || ep_type == USB_EP_ISOC)){
541 best_bw = SS_BW_BOUND;
542 best_bw_idx = -1;
543 cur_bw = 0;
544 td_size = maxp * (mult+1) * (burst+1);
545 if(mult == 0){
546 max_repeat = 0;
547 }
548 else{
549 max_repeat = (interval-1)/(mult+1);
550 }
551 break_out = 0;
552 for(frame_idx = 0; (frame_idx < interval) && !break_out; frame_idx++){
553 for(repeat = max_repeat; repeat >= 0; repeat--){
554 cur_bw = count_ss_bw(is_in, ep_type, maxp, interval, burst, mult, frame_idx
555 , repeat, td_size);
556 printk(KERN_ERR "count_ss_bw, frame_idx %d, repeat %d, td_size %d, result bw %d\n"
557 , frame_idx, repeat, td_size, cur_bw);
558 if(cur_bw > 0 && cur_bw < best_bw){
559 best_bw_idx = frame_idx;
560 best_bw_repeat = repeat;
561 best_bw = cur_bw;
562 if(cur_bw <= td_size || cur_bw < (HS_BW_BOUND>>1)){
563 break_out = 1;
564 break;
565 }
566 }
567 }
568 }
569 printk(KERN_ERR "final best idx %d, best repeat %d\n", best_bw_idx, best_bw_repeat);
570 if(best_bw_idx == -1){
571 return SCH_FAIL;
572 }
573 else{
574 bOffset = best_bw_idx;
575 bCsCount = 0;
576 bRepeat = best_bw_repeat;
577 if(bRepeat == 0){
578 bw_cost = (burst+1)*(mult+1)*maxp;
579 bPkts = (burst+1)*(mult+1);
580 }
581 else{
582 bw_cost = (burst+1)*maxp;
583 bPkts = (burst+1);
584 }
585 if(add_sch_ep(dev_speed, is_in, isTT, ep_type, maxp, interval, burst, mult
586 , bOffset, bRepeat, bPkts, bCsCount, bBm, bw_cost, ep, sch_ep) == SCH_FAIL){
587 return SCH_FAIL;
588 }
589 ret = SCH_SUCCESS;
590 }
591 }
592 else{
593 bPkts = 1;
594 ret = SCH_SUCCESS;
595 }
596 if(ret == SCH_SUCCESS){
597 temp_ep_ctx = (struct mtk_xhci_ep_ctx *)ep_ctx;
598 temp_ep_ctx->reserved[0] |= (BPKTS(bPkts) | BCSCOUNT(bCsCount) | BBM(bBm));
599 temp_ep_ctx->reserved[1] |= (BOFFSET(bOffset) | BREPEAT(bRepeat));
600
601 printk(KERN_DEBUG "[DBG] BPKTS: %x, BCSCOUNT: %x, BBM: %x\n", bPkts, bCsCount, bBm);
602 printk(KERN_DEBUG "[DBG] BOFFSET: %x, BREPEAT: %x\n", bOffset, bRepeat);
603 return SCH_SUCCESS;
604 }
605 else{
606 return SCH_FAIL;
607 }
608 }