00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "compat.h"
00013 #include <asm/arch/hwregs/intr_vect.h>
00014 #include <asm/arch/hwregs/dma_defs.h>
00015 #include <asm/arch/hwregs/iop/iop_reg_space.h>
00016 #include <asm/arch/hwregs/iop/iop_mpu_macros.h>
00017 #include <asm/arch/hwregs/iop/iop_mpu_defs.h>
00018 #include <asm/arch/hwregs/iop/iop_spu_defs.h>
00019 #include <asm/arch/hwregs/iop/iop_sw_cfg_defs.h>
00020 #include <asm/arch/hwregs/iop/iop_sw_cpu_defs.h>
00021 #include <asm/arch/hwregs/iop/iop_dmc_in_defs.h>
00022 #include <asm/arch/hwregs/iop/iop_fifo_in_defs.h>
00023 #include <asm/arch/hwregs/iop/iop_fifo_out_defs.h>
00024 #include <asm/arch/hwregs/iop/iop_scrc_out_defs.h>
00025 #include <asm/arch/hwregs/iop/iop_crc_par_defs.h>
00026 #include <asm/arch/hwregs/iop/iop_sap_in_defs.h>
00027 #include <asm/arch/hwregs/iop/iop_sap_out_defs.h>
00028 #include <asm/arch/hwregs/iop/iop_timer_grp_defs.h>
00029 #include "iop-usb.h"
00030 #include "iop-usb-int.h"
00031
00032 #ifdef SIMDEF_TARGET_BANANA
00033 #define D(x) (x)
00034 #else
00035 #define D(x)
00036 #endif
00037
00038
00039 #define IOP_TIMEOUT 1000
00040
00041
00042 static unsigned int port_power;
00043
00044
00045
00046 static __inline__ struct iop_usb_ed *ctxt_to_ed(dma_descr_context *ctxt)
00047 {
00048 return (struct iop_usb_ed *) ctxt;
00049 }
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #define MAX_INTERVAL_ISOC 1024
00060
00061
00062 #define MAX_INTERVAL_INTR 256
00063
00064
00065 #define NUM_TRANSFER_TYPE 4
00066
00067
00068 #define NUM_PER_TRANSFER_TYPE 2
00069
00070
00071 #define IOP_USB_GROUP_EOL (IOP_USB_BULK + 1)
00072
00073
00074 static dma_descr_group *group_top;
00075 static dma_descr_group *group_head;
00076 static struct {
00077 int num;
00078 dma_descr_group *groups;
00079 } group_periodic[NUM_PER_TRANSFER_TYPE];
00080 static unsigned long group_top_phys;
00081
00082
00083 static dma_descr_context *ctxt_head;
00084 static dma_descr_context *ctxt_eol;
00085 static dma_descr_context *ctxt_in_eol;
00086
00087
00088 #define TOTAL_DESCR_SIZE ( \
00089 (sizeof(dma_descr_context) * \
00090 (NUM_TRANSFER_TYPE + NUM_PER_TRANSFER_TYPE + 2)) + \
00091 (sizeof(dma_descr_group) * \
00092 (1 + NUM_TRANSFER_TYPE + 1 + MAX_INTERVAL_ISOC + MAX_INTERVAL_INTR)) \
00093 )
00094
00095
00096 #define DUMMY_BUF_SIZE 1500
00097 static char *dummy_buf;
00098
00099
00100 static int alloc_dummy_buf(void)
00101 {
00102 DUMMY_BUF(buf, DUMMY_BUF_SIZE);
00103
00104 if (!buf)
00105 return -1;
00106 dummy_buf = buf;
00107 return 0;
00108 }
00109
00110
00111
00112 static char *cur_static_descr;
00113
00114 static __inline__ int init_alloc_static_descr(void)
00115 {
00116 STATIC_DMA_DESCR(buf, TOTAL_DESCR_SIZE, L1_CACHE_BYTES);
00117 if (!buf)
00118 return -1;
00119 cur_static_descr = buf;
00120 return 0;
00121 }
00122
00123 static __inline__ void* alloc_static_descr(size_t size)
00124 {
00125 void *descr = cur_static_descr;
00126 cur_static_descr += size;
00127 return descr;
00128 }
00129
00130 #define ALLOC_DESCR(num, type) \
00131 ((type *) alloc_static_descr((num) * sizeof(type)))
00132
00133 static int alloc_static_descrs(void)
00134 {
00135 if (init_alloc_static_descr() != 0)
00136 return -1;
00137
00138 ctxt_head = ALLOC_DESCR(NUM_TRANSFER_TYPE, dma_descr_context);
00139 ctxt_eol = ALLOC_DESCR(NUM_PER_TRANSFER_TYPE, dma_descr_context);
00140 ctxt_in_eol = ALLOC_DESCR(2, dma_descr_context);
00141 group_top = ALLOC_DESCR(1, dma_descr_group);
00142 group_head = ALLOC_DESCR(NUM_TRANSFER_TYPE + 1, dma_descr_group);
00143
00144 group_periodic[IOP_USB_ISOC].num = MAX_INTERVAL_ISOC;
00145 group_periodic[IOP_USB_ISOC].groups =
00146 ALLOC_DESCR(MAX_INTERVAL_ISOC, dma_descr_group);
00147
00148 group_periodic[IOP_USB_INTR].num = MAX_INTERVAL_INTR;
00149 group_periodic[IOP_USB_INTR].groups =
00150 ALLOC_DESCR(MAX_INTERVAL_INTR, dma_descr_group);
00151
00152 return 0;
00153 }
00154
00155
00156 static void init_dma_periodic(enum iop_usb_transaction_type type)
00157 {
00158 unsigned int i, num_groups = group_periodic[type].num;
00159 dma_descr_group *groups = group_periodic[type].groups;
00160
00161 for (i = 0; i < num_groups; i++) {
00162 struct iop_usb_ttd *ttd = iop_usb_ttd(&groups[i]);
00163 memset(&groups[i], 0, sizeof(dma_descr_group));
00164 groups[i].bol = 1;
00165 groups[i].up = VIRT_TO_PHYS(&group_head[type]);
00166 groups[i].next =
00167 VIRT_TO_PHYS(&groups[i > 0 ? i - 1 : num_groups - 1]);
00168 groups[i].down.context = VIRT_TO_PHYS(&ctxt_head[type]);
00169 ttd->is_periodic = 1;
00170 ttd->is_isoc = type == IOP_USB_ISOC;
00171 }
00172 memset(&ctxt_eol[type], 0, sizeof(dma_descr_context));
00173 ctxt_eol[type].eol = 1;
00174 ctxt_eol[type].store_mode = 1;
00175 ctxt_eol[type].next = VIRT_TO_PHYS(&ctxt_head[type]);
00176 }
00177
00178
00179
00180 static void init_dma_in(void)
00181 {
00182 int i;
00183
00184 for (i = 0; i < 2; i++) {
00185 memset(&ctxt_in_eol[i], 0, sizeof(dma_descr_context));
00186 ctxt_in_eol->eol = 1;
00187 ctxt_in_eol->next = VIRT_TO_PHYS(&ctxt_in_eol[(i + 1) % 2]);
00188 }
00189 }
00190
00191
00192 static void init_dma(void)
00193 {
00194 unsigned int type;
00195
00196 group_top_phys = (unsigned long) VIRT_TO_PHYS(group_top);
00197 memset(group_top, 0, sizeof(dma_descr_group));
00198 group_top->tol = 1;
00199 group_top->bol = 1;
00200 group_top->eol = 1;
00201 group_top->next = VIRT_TO_PHYS(&group_head[IOP_USB_ISOC]);
00202
00203 for (type = 0; type <= NUM_TRANSFER_TYPE; type++) {
00204 struct iop_usb_ttd *ttd_head = iop_usb_ttd(&group_head[type]);
00205
00206 memset(&group_head[type], 0, sizeof(dma_descr_group));
00207 group_head[type].up = VIRT_TO_PHYS(group_top);
00208
00209 if (type != IOP_USB_GROUP_EOL)
00210 memset(&ctxt_head[type], 0, sizeof(dma_descr_context));
00211
00212 switch (type) {
00213 case IOP_USB_ISOC:
00214 ttd_head->is_isoc = 1;
00215
00216 case IOP_USB_INTR:
00217 ttd_head->is_periodic = 1;
00218 group_head[type].down.group =
00219 VIRT_TO_PHYS(group_periodic[type].groups);
00220 ctxt_head[type].next =
00221 VIRT_TO_PHYS(&ctxt_eol[type]);
00222 break;
00223 case IOP_USB_CTRL:
00224 ttd_head->is_ctrl = 1;
00225
00226 case IOP_USB_BULK:
00227 group_head[type].bol = 1;
00228 group_head[type].down.context =
00229 VIRT_TO_PHYS(&ctxt_head[type]);
00230 ctxt_head[type].next =
00231 VIRT_TO_PHYS(&ctxt_head[type]);
00232 break;
00233 case IOP_USB_GROUP_EOL:
00234 group_head[type].next = VIRT_TO_PHYS(group_top);
00235 group_head[type].bol = 1;
00236 group_head[type].eol = 1;
00237 continue;
00238 default:
00239 BUG();
00240 }
00241
00242 group_head[type].next = VIRT_TO_PHYS(&group_head[type + 1]);
00243 ctxt_head[type].eol = 1;
00244 ctxt_head[type].store_mode = 1;
00245 }
00246
00247 init_dma_periodic(IOP_USB_ISOC);
00248 init_dma_periodic(IOP_USB_INTR);
00249 init_dma_in();
00250
00251 wmb();
00252
00253 DMA_RESET(INST(dma_out));
00254 DMA_ENABLE(INST(dma_out));
00255 REG_WR(dma, INST(dma_out), rw_group, group_top_phys);
00256 REG_WR(dma, INST(dma_out), rw_ctxt, 0);
00257 REG_WR(dma, INST(dma_out), rw_ctxt_next, 0);
00258 DMA_WR_CMD(INST(dma_out), regk_dma_load_g);
00259
00260 DMA_RESET(INST(dma_in));
00261 DMA_ENABLE(INST(dma_in));
00262 DMA_WR_CMD(INST(dma_in), regk_dma_set_w_size1);
00263 }
00264
00265
00266 static __inline__ void enable_group(enum iop_usb_transfer_type type)
00267 {
00268 wmb();
00269 group_head[type].en = 1;
00270 group_head[type].dis = 0;
00271 }
00272
00273
00274 static __inline__ void reset_ed_status(struct iop_usb_ed *ed)
00275 {
00276 struct iop_usb_ctxt_md *ctxt_md = iop_usb_ctxt_md(&ed->ctxt);
00277 ctxt_md->stat = IOP_USB_STAT_OK;
00278 ctxt_md->toggle = 0;
00279 }
00280
00281
00282 static void reset_out_context(struct iop_usb_ed *ed, struct iop_usb_td *td)
00283 {
00284 dma_descr_context *ctxt = &ed->ctxt;
00285
00286 BUG_ON(ctxt->en && !ctxt->dis);
00287
00288 if (!td) {
00289 ctxt->saved_data = NULL;
00290 ctxt->saved_data_buf = NULL;
00291 return;
00292 }
00293 ctxt->saved_data = VIRT_TO_PHYS(&td->u.priv.d_out);
00294 ctxt->saved_data_buf = td->u.priv.d_out.buf;
00295 wmb();
00296 ctxt->dis = 0;
00297 }
00298
00299
00300 static void wait_on_ctxt(struct iop_usb_ed *ed)
00301 {
00302 unsigned int type = ed->type;
00303 unsigned long phys = (unsigned long) VIRT_TO_PHYS(&ed->ctxt);
00304 unsigned long group_first, group_last;
00305 reg_dma_rw_stat stat;
00306
00307 BUG_ON(ed->ctxt.en);
00308
00309 if (type == IOP_USB_ISOC || type == IOP_USB_INTR) {
00310 group_first = (unsigned int)
00311 VIRT_TO_PHYS(group_periodic[type].groups);
00312 group_last = group_first + (group_periodic[type].num - 1 ) *
00313 sizeof(dma_descr_group *);
00314 } else
00315 group_first = group_last = (unsigned int)
00316 VIRT_TO_PHYS(&group_head[type]);
00317 wmb();
00318 while (((REG_RD(dma, INST(dma_out), rw_group) >= group_first) &&
00319 (REG_RD(dma, INST(dma_out), rw_group) <= group_last)) &&
00320 ((phys == REG_RD(dma, INST(dma_out), rw_ctxt) ||
00321 phys == REG_RD(dma, INST(dma_out), rw_ctxt_next) ||
00322 phys == REG_RD(dma, INST(dma_out), rw_group_down)))) {
00323 stat = REG_RD(dma, INST(dma_out), rw_stat);
00324 if (stat.mode != regk_dma_running)
00325 break;
00326 BUSY_WAIT();
00327 }
00328 }
00329
00330
00331 static void schedule_periodic(unsigned int type, dma_descr_context *ctxt)
00332 {
00333 unsigned int i, num = group_periodic[type].num;
00334 unsigned int interval, next_interval;
00335 dma_descr_group *groups = group_periodic[type].groups;
00336 dma_descr_context *next, *last;
00337 struct iop_usb_ttd *ttd;
00338
00339 wmb();
00340 while (1) {
00341 next = PHYS_TO_VIRT(ctxt->next);
00342 if (next->eol)
00343 break;
00344 ctxt = next;
00345 }
00346 last = ctxt;
00347
00348 ctxt = &ctxt_head[type];
00349 interval = (unsigned int) -1;
00350 while (1) {
00351 next = PHYS_TO_VIRT(ctxt->next);
00352 next_interval = ctxt_to_ed(next)->interval;
00353 if (next->eol)
00354 break;
00355 if (next_interval != interval)
00356 for (i = next_interval - 1;
00357 i < num;
00358 i += next_interval) {
00359 ttd = iop_usb_ttd(&groups[i]);
00360 if (ttd->mark)
00361 continue;
00362 groups[i].down.context = VIRT_TO_PHYS(ctxt);
00363 ttd->mark = 1;
00364 }
00365 ctxt = next;
00366 interval = next_interval;
00367 }
00368 for (i = 0; i < num; i++) {
00369 ttd = iop_usb_ttd(&groups[i]);
00370 if (!ttd->mark)
00371 groups[i].down.context = VIRT_TO_PHYS(last);
00372 ttd->mark = 0;
00373 }
00374 }
00375
00376
00377 void iop_usb_endpoint_init(
00378 struct iop_usb_ed *ed,
00379 enum iop_usb_transfer_type type,
00380 unsigned int daddr,
00381 unsigned int epnum,
00382 int is_in,
00383 enum iop_usb_speed speed,
00384 unsigned int maxsize,
00385 unsigned int interval,
00386 unsigned long maxtime)
00387 {
00388 struct iop_usb_ctxt_md *ctxt_md = iop_usb_ctxt_md(&ed->ctxt);
00389
00390 BUG_ON((unsigned long) ed % ALIGN_IOP_USB_ED != 0);
00391
00392 switch (type) {
00393 case IOP_USB_ISOC:
00394 if (interval > MAX_INTERVAL_ISOC)
00395 interval = MAX_INTERVAL_ISOC;
00396 break;
00397 case IOP_USB_INTR:
00398 if (interval > MAX_INTERVAL_INTR)
00399 interval = MAX_INTERVAL_INTR;
00400 break;
00401 case IOP_USB_CTRL:
00402 case IOP_USB_BULK:
00403 interval = 1;
00404 break;
00405 default:
00406 BUG();
00407 }
00408
00409 memset(&ed->ctxt, 0, sizeof(dma_descr_context));
00410 ctxt_md->daddr = daddr;
00411 ctxt_md->epnum = epnum;
00412 ctxt_md->low_speed = speed == IOP_USB_SPEED_LOW;
00413 ctxt_md->maxsize = maxsize;
00414
00415
00416
00417 ctxt_md->maxtime = maxtime / (1000/12) + 1 + EOF1_EARLY;
00418 ctxt_md->stat = IOP_USB_STAT_OK;
00419 ctxt_md->toggle = 0;
00420 ed->ctxt.en = 1;
00421 ed->ctxt.dis = 1;
00422 ed->ctxt.store_mode = 1;
00423 ed->type = type;
00424 ed->is_in = is_in;
00425 ed->interval = interval;
00426 ed->head_out = NULL;
00427
00428 if (type == IOP_USB_CTRL || is_in) {
00429 memset(&ed->in_group, 0, sizeof(dma_descr_group));
00430 ed->in_group.eol = 1;
00431 ed->in_group.tol = 1;
00432 ed->in_group.bol = 1;
00433 ed->in_group.down.context = VIRT_TO_PHYS(ctxt_in_eol);
00434 ctxt_md->in_group = (unsigned) VIRT_TO_PHYS(&ed->in_group);
00435 ed->head_in = NULL;
00436 }
00437 }
00438
00439
00440 void iop_usb_endpoint_add(struct iop_usb_ed *ed)
00441 {
00442 unsigned int type = ed->type;
00443 unsigned int interval = ed->interval;
00444 unsigned int next_interval;
00445 dma_descr_context *prev, *next;
00446
00447 D(printf("add endpoint %p\n", ed));
00448
00449
00450 prev = &ctxt_head[type];
00451 while (1) {
00452 next = PHYS_TO_VIRT(prev->next);
00453 next_interval = ctxt_to_ed(next)->interval;
00454 if (next->eol || interval > next_interval)
00455 break;
00456 prev = next;
00457 }
00458
00459 ed->ctxt.next = prev->next;
00460 prev->next = VIRT_TO_PHYS(&ed->ctxt);
00461
00462
00463 if (iop_usb_ttd(&group_head[type])->is_periodic)
00464 schedule_periodic(type, prev);
00465 }
00466
00467
00468 void iop_usb_endpoint_release(struct iop_usb_ed *ed)
00469 {
00470 unsigned int type = ed->type;
00471 dma_descr_context *head, *prev, *next;
00472
00473 D(printf("release endpoint %p\n", ed));
00474
00475
00476 prev = head = &ctxt_head[type];
00477 while (1) {
00478 next = PHYS_TO_VIRT(prev->next);
00479 if (next == &ed->ctxt)
00480 break;
00481 if (next->eol)
00482 return;
00483 prev = next;
00484 }
00485 prev->next = ed->ctxt.next;
00486 ed->ctxt.en = 0;
00487
00488
00489 if (iop_usb_ttd(&group_head[type])->is_periodic)
00490 schedule_periodic(type, prev);
00491 }
00492
00493
00494
00495 void iop_usb_endpoint_release_wait(struct iop_usb_ed *ed)
00496 {
00497
00498
00499
00500
00501 wait_on_ctxt(ed);
00502 }
00503
00504
00505 void iop_usb_trans_init(
00506 struct iop_usb_td *td,
00507 enum iop_usb_transaction_type type,
00508 unsigned int maxsize,
00509 void *buffer,
00510 unsigned int buffer_length,
00511 int zeropacket)
00512 {
00513 char *buf, *after;
00514
00515 D(printf("trans init %p (buffer=%p)\n", td, buffer));
00516
00517 BUG_ON(!buffer && buffer_length > 0);
00518 BUG_ON((unsigned long) td % ALIGN_IOP_USB_TD != 0);
00519
00520 memset(td, 0, type == IOP_USB_IN ?
00521 sizeof(struct iop_usb_td) : sizeof(dma_descr_data));
00522
00523 td->u.priv.d_out.wait = 1;
00524 td->u.priv.d_out.out_eop = 1;
00525 iop_usb_data_md(&td->u.priv.d_out)->type = type;
00526
00527 buf = buffer ? VIRT_TO_PHYS(buffer) : dummy_buf;
00528 after = buf + buffer_length;
00529
00530 switch (type) {
00531 case IOP_USB_IN:
00532 D(printf("IN d_in=%p c_in=%p dummy=%p dummy_buf=%p\n",
00533 &td->u.priv.d_in, &td->u.priv.c_in, &td->u.priv.dummy,
00534 dummy_buf));
00535 td->u.priv.d_out.after =
00536 td->u.priv.d_out.buf = dummy_buf;
00537
00538 td->u.priv.d_in.buf = buf;
00539 td->u.priv.d_in.after = after;
00540 td->u.priv.c_in.en = 1;
00541 td->u.priv.c_in.store_mode = 1;
00542 td->u.priv.c_in.saved_data = &td->u.priv.d_in;
00543 td->u.priv.c_in.saved_data_buf = buf;
00544
00545
00546 td->u.priv.c_in.md1 = buffer_length == 0 ?
00547 1 : (buffer_length - 1) / maxsize + 1;
00548
00549
00550
00551 td->u.priv.d_in.next = VIRT_TO_PHYS(&td->u.priv.dummy);
00552 td->u.priv.dummy.eol = 1;
00553 td->u.priv.dummy.buf = dummy_buf;
00554 td->u.priv.dummy.after =
00555 td->u.priv.dummy.buf + DUMMY_BUF_SIZE;
00556 flush_dma_list(&td->u.priv.d_in);
00557 break;
00558 case IOP_USB_OUT:
00559 D(printf("OUT/SETUP\n"));
00560 if (zeropacket && (buffer_length % maxsize == 0))
00561 iop_usb_data_md(&td->u.priv.d_out)->zend = 1;
00562
00563 case IOP_USB_SETUP:
00564 td->u.priv.d_out.buf = buf;
00565 td->u.priv.d_out.after = after;
00566 break;
00567 }
00568 }
00569
00570
00571 static int insert_descr_out(struct iop_usb_ed *ed, struct iop_usb_td *td)
00572 {
00573 struct iop_usb_td *last = td;
00574
00575
00576
00577 while (last->u.next) {
00578 struct iop_usb_td *next = last->u.next;
00579 last->u.next = VIRT_TO_PHYS(next);
00580 last = next;
00581 }
00582 last->u.priv.d_out.eol = 1;
00583 wmb();
00584 if (ed->head_out) {
00585
00586 struct iop_usb_td *prev;
00587 for (prev = ed->head_out;
00588 !prev->u.priv.d_out.eol;
00589 prev = PHYS_TO_VIRT(prev->u.next))
00590 ;
00591 prev->u.next = VIRT_TO_PHYS(td);
00592 prev->u.priv.d_out.eol = 0;
00593 } else {
00594
00595 ed->head_out = td;
00596 reset_out_context(ed, td);
00597 }
00598 if (ed->ctxt.dis) {
00599
00600 if (iop_usb_ctxt_md(&ed->ctxt)->stat != IOP_USB_STAT_OK)
00601 return -1;
00602 if (ed->ctxt.saved_data == VIRT_TO_PHYS(&last->u.priv.d_out))
00603 return 0;
00604
00605 reset_out_context(ed, td);
00606 }
00607 return 0;
00608 }
00609
00610
00611 static void insert_descr_in(struct iop_usb_ed *ed, struct iop_usb_td *td)
00612 {
00613 dma_descr_context *first = NULL, *prev = NULL, *cur = NULL;
00614
00615 if (ed->type != IOP_USB_CTRL && !ed->is_in)
00616 return;
00617
00618
00619 for (; td; td = td->u.next)
00620 if (iop_usb_data_md(&td->u.priv.d_out)->type == IOP_USB_IN) {
00621 cur = &td->u.priv.c_in;
00622 if (!first)
00623 first = cur;
00624 if (prev)
00625 prev->next = VIRT_TO_PHYS(cur);
00626 prev = cur;
00627 }
00628 if (!first)
00629 return;
00630
00631 cur->next = VIRT_TO_PHYS(ctxt_in_eol);
00632 if (ed->head_in) {
00633
00634 prev = NULL;
00635 cur = ed->head_in;
00636 do {
00637 prev = cur;
00638 cur = PHYS_TO_VIRT(cur->next);
00639 } while (!cur->eol);
00640 prev->next = VIRT_TO_PHYS(first);
00641 } else {
00642
00643 ed->head_in = first;
00644 }
00645
00646 if (ed->in_group.down.context == VIRT_TO_PHYS(ctxt_in_eol))
00647 ed->in_group.down.context = VIRT_TO_PHYS(first);
00648 }
00649
00650
00651 static void remove_descr_out(
00652 struct iop_usb_ed *ed,
00653 struct iop_usb_td *first,
00654 struct iop_usb_td *last)
00655 {
00656 struct iop_usb_td *after, *cur;
00657 dma_descr_data *saved_data = PHYS_TO_VIRT(ed->ctxt.saved_data);
00658
00659 BUG_ON(ed->ctxt.en);
00660
00661 after = last->u.priv.d_out.eol ? NULL : PHYS_TO_VIRT(last->u.next);
00662
00663 if (ed->head_out == first) {
00664
00665 ed->head_out = after;
00666 } else {
00667
00668 struct iop_usb_td *prev;
00669 for (prev = ed->head_out;
00670 !prev->u.priv.d_out.eol;
00671 prev = PHYS_TO_VIRT(prev->u.next))
00672 if (PHYS_TO_VIRT(prev->u.next) == first)
00673 break;
00674 BUG_ON(prev->u.priv.d_out.eol);
00675 if (!after)
00676 prev->u.priv.d_out.eol = 1;
00677 prev->u.next = after;
00678 }
00679
00680
00681 for (cur = first; ; cur = cur->u.next) {
00682 if (&cur->u.priv.d_out == saved_data)
00683 reset_out_context(ed, after);
00684 cur->u.next = PHYS_TO_VIRT(cur->u.next);
00685 if (cur == last || cur->u.priv.d_out.eol)
00686 break;
00687 }
00688 BUG_ON(cur != last);
00689 last->u.next = NULL;
00690 }
00691
00692
00693 static void remove_descr_in(
00694 struct iop_usb_ed *ed,
00695 struct iop_usb_td *first,
00696 struct iop_usb_td *last)
00697 {
00698 struct iop_usb_td *td;
00699 dma_descr_context *first_in, *last_in, *after, *cur;
00700 dma_descr_context *down = PHYS_TO_VIRT(ed->in_group.down.context);
00701
00702 BUG_ON(ed->ctxt.en && !ed->ctxt.dis);
00703
00704 if (ed->type != IOP_USB_CTRL && !ed->is_in)
00705 return;
00706
00707
00708 first_in = last_in = NULL;
00709 for (td = first; ; td = PHYS_TO_VIRT(td->u.next)) {
00710 if (iop_usb_data_md(&td->u.priv.d_out)->type == IOP_USB_IN) {
00711 last_in = &td->u.priv.c_in;
00712 if (!first_in)
00713 first_in = last_in;
00714 }
00715 if (td == last)
00716 break;
00717 BUG_ON(td->u.priv.d_out.eol);
00718 }
00719 if (!first_in)
00720 return;
00721
00722
00723
00724 after = PHYS_TO_VIRT(last_in->next);
00725
00726
00727 if (ed->head_in == first_in) {
00728
00729 ed->head_in = after->eol ? NULL : after;
00730 } else {
00731
00732 dma_descr_context *prev;
00733 for (prev = ed->head_in;
00734 !prev->eol;
00735 prev = PHYS_TO_VIRT(prev->next))
00736 if (PHYS_TO_VIRT(prev->next) == first_in)
00737 break;
00738 BUG_ON(prev->eol);
00739 prev->next = after;
00740 }
00741
00742 for (cur = first_in; !cur->eol; cur = PHYS_TO_VIRT(cur->next)) {
00743 if (cur == down)
00744 ed->in_group.down.context = VIRT_TO_PHYS(after);
00745 if (cur == last_in)
00746 break;
00747 }
00748 BUG_ON(cur != last_in);
00749 last_in->next = NULL;
00750 }
00751
00752
00753 int iop_usb_trans_enqueue(struct iop_usb_ed *ed, struct iop_usb_td *td)
00754 {
00755 int retval = 0;
00756
00757 D(printf("trans enqueue %p -> %p\n", td, ed));
00758
00759 insert_descr_in(ed, td);
00760 wmb();
00761 retval = insert_descr_out(ed, td);
00762 if (retval != 0) {
00763
00764
00765
00766 remove_descr_in(ed, td, td);
00767 return IOP_USB_ERR_CTXT_DIS;
00768 }
00769 enable_group(ed->type);
00770 return IOP_USB_OK;
00771 }
00772
00773
00774
00775 void iop_usb_trans_dequeue_lock(struct iop_usb_ed *ed)
00776 {
00777
00778
00779 ed->ctxt.en = 0;
00780
00781 wait_on_ctxt(ed);
00782 }
00783
00784
00785 int iop_usb_trans_dequeue(struct iop_usb_ed *ed,
00786 struct iop_usb_td *td_first,
00787 struct iop_usb_td *td_last)
00788 {
00789 D(printf("trans dequeue %p:%p -> %p\n", td_first, td_last, ed));
00790
00791 BUG_ON(ed->ctxt.en);
00792
00793 if (iop_usb_data_md(&td_last->u.priv.d_out)->done)
00794 return IOP_USB_ERR_ALL_DONE;
00795
00796 remove_descr_in(ed, td_first, td_last);
00797 wmb();
00798 remove_descr_out(ed, td_first, td_last);
00799 wmb();
00800 return IOP_USB_OK;
00801 }
00802
00803
00804
00805 void iop_usb_trans_dequeue_unlock(struct iop_usb_ed *ed)
00806 {
00807 BUG_ON(ed->ctxt.en);
00808
00809 if (ed->ctxt.saved_data) {
00810 if (ed->type == IOP_USB_CTRL || ed->type == IOP_USB_BULK) {
00811 static int fe_irq_request(void);
00812
00813
00814 enable_group(ed->type);
00815
00816
00817
00818
00819
00820 fe_irq_request();
00821 }
00822 } else
00823 ed->ctxt.dis = 1;
00824 wmb();
00825 ed->ctxt.en = 1;
00826 }
00827
00828
00829
00830 void iop_usb_stop_periodic(enum iop_usb_transfer_type type)
00831 {
00832 BUG_ON(type != IOP_USB_ISOC && type != IOP_USB_INTR);
00833 group_head[type].en = 0;
00834 }
00835
00836
00837 static void finish_data(
00838 struct iop_usb_ed *ed,
00839 void (*cb)(struct iop_usb_td *, int, int))
00840 {
00841 struct iop_usb_td *next, *td = ed->head_out;
00842 struct iop_usb_data_md *data_md;
00843 dma_descr_data *data = &td->u.priv.d_out;
00844 dma_descr_context *ctxt_in;
00845 unsigned int ep_stat;
00846
00847 if (!td)
00848 return;
00849 ctxt_in = (ed->type == IOP_USB_CTRL || ed->is_in) ? ed->head_in : NULL;
00850
00851
00852
00853 ep_stat = iop_usb_ctxt_md(&ed->ctxt)->stat;
00854 rmb();
00855 while ((data_md = iop_usb_data_md(data))->done ||
00856 ep_stat != IOP_USB_STAT_OK) {
00857 int length = 0;
00858 int status =
00859 data_md->done ? data_md->stat : IOP_USB_STAT_FLUSHED;
00860
00861 switch (data_md->type) {
00862 case IOP_USB_IN:
00863
00864
00865 BUG_ON(!ctxt_in || ctxt_in->eol);
00866 BUG_ON(ctxt_in != &td->u.priv.c_in);
00867 if (status != IOP_USB_STAT_FLUSHED) {
00868 dma_descr_data *data_in = &td->u.priv.d_in;
00869 length = data_in->after - data_in->buf;
00870
00871
00872
00873
00874 if (status == IOP_USB_STAT_OK && !data_in->in_eop)
00875 status = IOP_USB_STAT_ORUN;
00876 }
00877 ctxt_in = PHYS_TO_VIRT(ctxt_in->next);
00878 break;
00879 case IOP_USB_OUT:
00880 if (status != IOP_USB_STAT_FLUSHED)
00881 length = data->after - data->buf;
00882 break;
00883 default:
00884 break;
00885 }
00886
00887 next = td->u.next ? PHYS_TO_VIRT(td->u.next) : NULL;
00888 td->u.next = next;
00889 wmb();
00890 data->buf = PHYS_TO_VIRT(data->buf);
00891 data->after = PHYS_TO_VIRT(data->after);
00892 cb((struct iop_usb_td *) td, status, length);
00893 if (data->eol) {
00894 td = NULL;
00895 break;
00896 }
00897 td = next;
00898 data = &td->u.priv.d_out;
00899 }
00900
00901 if (ep_stat != IOP_USB_STAT_OK) {
00902 BUG_ON(!ed->ctxt.dis);
00903 reset_ed_status(ed);
00904 }
00905 ed->head_out = (struct iop_usb_td *) td;
00906 if (ed->type == IOP_USB_CTRL || ed->is_in)
00907 ed->head_in = (dma_descr_context *) ctxt_in;
00908 if (!ed->head_out) {
00909
00910 ed->ctxt.dis = 1;
00911 if (ed->type == IOP_USB_CTRL || ed->is_in) {
00912 BUG_ON(ed->head_in && !ed->head_in->eol);
00913 ed->head_in = NULL;
00914 ed->in_group.down.context = VIRT_TO_PHYS(ctxt_in_eol);
00915 }
00916 return;
00917 }
00918
00919
00920 if (ed->ctxt.dis)
00921 reset_out_context(ed, ed->head_out);
00922
00923 if (ed->type == IOP_USB_CTRL || ed->type == IOP_USB_BULK)
00924 enable_group(ed->type);
00925 }
00926
00927
00928 void iop_usb_trans_done_irq(void (*cb)(struct iop_usb_td *, int, int))
00929 {
00930 unsigned int type;
00931
00932
00933 for (type = 0; type < NUM_TRANSFER_TYPE; type++) {
00934 dma_descr_context *ctxt = &ctxt_head[type];
00935 while (1) {
00936 ctxt = PHYS_TO_VIRT(ctxt->next);
00937 if (ctxt->eol)
00938 break;
00939 finish_data(ctxt_to_ed(ctxt), cb);
00940 }
00941 }
00942 }
00943
00944
00945 static __inline__ int wait_mpu_idle(void)
00946 {
00947 reg_iop_mpu_r_stat mpu_stat;
00948 unsigned int timeout = IOP_TIMEOUT;
00949
00950 do {
00951 mpu_stat = REG_RD(iop_mpu, regi_iop_mpu, r_stat);
00952 } while (mpu_stat.instr_reg_busy == regk_iop_mpu_yes && --timeout > 0);
00953 return timeout > 0 ? 0 : -1;
00954 }
00955
00956
00957 static __inline__ int wait_mpu_reg_data(void)
00958 {
00959 int data;
00960 unsigned int timeout = IOP_TIMEOUT;
00961
00962 do {
00963 data = REG_RD_VECT(iop_mpu, regi_iop_mpu, rw_r, MPU_REG_DATA);
00964 } while (data && --timeout > 0);
00965 return timeout > 0 ? 0 : -1;
00966 }
00967
00968
00969 static int read_mpu_mem(u32 addr, u32 *data)
00970 {
00971 reg_iop_mpu_rw_ctrl ctrl = REG_RD(iop_mpu, regi_iop_mpu, rw_ctrl);
00972
00973 if (wait_mpu_idle() != 0)
00974 return -1;
00975 if (ctrl.en) {
00976 REG_WR_VECT(iop_mpu, regi_iop_mpu, rw_r, MPU_REG_DATA, addr);
00977 REG_WR(iop_mpu, regi_iop_mpu, rw_instr,
00978 MPU_JIR_I(MK_DWORD_ADDR(MPU_ADDR_READ_MEM)));
00979 } else
00980 REG_WR(iop_mpu, regi_iop_mpu, rw_instr,
00981 MPU_LW_IR(MK_DWORD_ADDR(addr), MPU_REG_DATA));
00982 if (wait_mpu_idle() != 0)
00983 return -1;
00984 *data = REG_RD_VECT(iop_mpu, regi_iop_mpu, rw_r, MPU_REG_DATA);
00985 return 0;
00986 }
00987
00988
00989 static int write_mpu_mem(u32 addr, u32 data)
00990 {
00991 if (wait_mpu_idle() != 0)
00992 return -1;
00993 REG_WR_VECT(iop_mpu, regi_iop_mpu, rw_r, MPU_REG_DATA, data);
00994 REG_WR(iop_mpu, regi_iop_mpu, rw_instr,
00995 MPU_SW_RI(MPU_REG_DATA, MK_DWORD_ADDR(addr)));
00996 if (wait_mpu_idle() != 0)
00997 return -1;
00998 return 0;
00999 }
01000
01001
01002 static int mpu_halt(void)
01003 {
01004 if (wait_mpu_idle() != 0)
01005 return -1;
01006 REG_WR(iop_mpu, regi_iop_mpu, rw_instr, MPU_HALT());
01007 if (wait_mpu_idle() != 0)
01008 return -1;
01009 return 0;
01010 }
01011
01012
01013 static int mpu_start(void)
01014 {
01015 reg_iop_mpu_rw_ctrl mpu_ctrl = { .en = regk_iop_mpu_yes };
01016
01017
01018 if (wait_mpu_idle() != 0)
01019 return IOP_USB_ERR_TIMEOUT;
01020 REG_WR(iop_mpu, regi_iop_mpu, rw_instr, MPU_BA_I(MPU_ADDR_START));
01021 if (wait_mpu_idle() != 0)
01022 return IOP_USB_ERR_TIMEOUT;
01023
01024
01025 REG_WR(iop_mpu, regi_iop_mpu, rw_instr, MPU_DI());
01026 if (wait_mpu_idle() != 0)
01027 return -1;
01028
01029
01030 REG_WR(iop_mpu, regi_iop_mpu, rw_ctrl, mpu_ctrl);
01031
01032 return 0;
01033 }
01034
01035
01036
01037 static int mpu_rh_port_request(
01038 unsigned int req,
01039 unsigned int port,
01040 unsigned int feat)
01041 {
01042 static u32 addr = 0;
01043 u32 data = CPU_DATA_VAL(req, port, feat);
01044
01045 if (!addr && read_mpu_mem(MPU_ADDR_RH_PORT_REQ, &addr) != 0)
01046 return -1;
01047 if (wait_mpu_idle() != 0)
01048 return -1;
01049 REG_WR_VECT(iop_mpu, regi_iop_mpu, rw_r, MPU_REG_DATA, data);
01050 REG_WR(iop_mpu, regi_iop_mpu, rw_instr,
01051 MPU_JIR_I(MK_DWORD_ADDR(addr)));
01052 if (wait_mpu_reg_data() != 0)
01053 return -1;
01054 return 0;
01055 }
01056
01057
01058
01059 static int fe_irq_request(void)
01060 {
01061 static u32 addr = 0;
01062
01063 if (!addr && read_mpu_mem(MPU_ADDR_FE_IRQ_REQ, &addr) != 0)
01064 return -1;
01065 if (wait_mpu_idle() != 0)
01066 return -1;
01067 REG_WR(iop_mpu, regi_iop_mpu, rw_instr,
01068 MPU_JIR_I(MK_DWORD_ADDR(addr)));
01069 return 0;
01070 }
01071
01072
01073 static void port_gio_config(unsigned int port, int low_speed)
01074 {
01075 reg_iop_sw_cfg_rw_gio_out_grp0_cfg cfg0;
01076 reg_iop_sw_cfg_rw_gio_out_grp1_cfg cfg1;
01077 reg_iop_sw_cfg_rw_gio_out_grp2_cfg cfg2;
01078 reg_iop_sw_cfg_rw_gio_out_grp3_cfg cfg3;
01079 reg_iop_sw_cfg_rw_gio_out_grp4_cfg cfg4;
01080 reg_iop_sw_cfg_rw_gio_out_grp5_cfg cfg5;
01081 reg_iop_sw_cfg_rw_gio_out_grp6_cfg cfg6;
01082 reg_iop_sw_cfg_rw_gio_out_grp7_cfg cfg7;
01083 reg_iop_sap_in_rw_gio sap_in;
01084 reg_iop_sw_cpu_rw_gio_set_mask set_mask;
01085 reg_iop_sw_cpu_rw_gio_clr_mask clr_mask;
01086 unsigned int spu_v_mo, spu_v_po, spu_oe;
01087 unsigned int gio_speed, gio_rcv = GIO_RCV;
01088
01089
01090 switch (INST(spu)) {
01091 case regi_iop_spu0:
01092 spu_v_mo = regk_iop_sw_cfg_spu0_gioout0;
01093 spu_v_po = regk_iop_sw_cfg_spu0_gioout2;
01094 spu_oe = regk_iop_sw_cfg_spu0_gioout16;
01095 break;
01096 case regi_iop_spu1:
01097 spu_v_mo = regk_iop_sw_cfg_spu1_gioout0;
01098 spu_v_po = regk_iop_sw_cfg_spu1_gioout2;
01099 spu_oe = regk_iop_sw_cfg_spu1_gioout16;
01100 break;
01101 default:
01102 BUG();
01103 }
01104 if (low_speed) {
01105
01106 unsigned int tmp = spu_v_mo;
01107 spu_v_mo = spu_v_po;
01108 spu_v_po = tmp;
01109 }
01110 switch (port) {
01111 case 0:
01112 cfg2 = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp2_cfg);
01113 cfg6 = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp6_cfg);
01114 cfg2.gio8 = spu_v_mo;
01115 cfg2.gio9 = spu_v_po;
01116 cfg6.gio24 = spu_oe;
01117 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp2_cfg, cfg2);
01118 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp6_cfg, cfg6);
01119 gio_speed = PORT_GIO_SPEED(0);
01120 gio_rcv += GIO_PORT_BASE(0);
01121 break;
01122 case 1:
01123 cfg3 = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp3_cfg);
01124 cfg7 = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp7_cfg);
01125 cfg3.gio12 = spu_v_mo;
01126 cfg3.gio13 = spu_v_po;
01127 cfg7.gio28 = spu_oe;
01128 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp3_cfg, cfg3);
01129 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp7_cfg, cfg7);
01130 gio_speed = PORT_GIO_SPEED(1);
01131 gio_rcv += GIO_PORT_BASE(1);
01132 break;
01133 case 2:
01134 cfg1 = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp1_cfg);
01135 cfg5 = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp5_cfg);
01136 cfg1.gio4 = spu_v_mo;
01137 cfg1.gio5 = spu_v_po;
01138 cfg5.gio20 = spu_oe;
01139 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp1_cfg, cfg1);
01140 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp5_cfg, cfg5);
01141 gio_speed = PORT_GIO_SPEED(2);
01142 gio_rcv += GIO_PORT_BASE(2);
01143 break;
01144 case 3:
01145 cfg0 = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp0_cfg);
01146 cfg4 = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp4_cfg);
01147 cfg0.gio0 = spu_v_mo;
01148 cfg0.gio1 = spu_v_po;
01149 cfg4.gio16 = spu_oe;
01150 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp0_cfg, cfg0);
01151 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_out_grp4_cfg, cfg4);
01152 gio_speed = PORT_GIO_SPEED(3);
01153 gio_rcv += GIO_PORT_BASE(3);
01154 break;
01155 default:
01156 BUG();
01157 }
01158
01159 sap_in = REG_RD_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, gio_rcv);
01160 sap_in.logic = low_speed ? regk_iop_sap_in_inv : regk_iop_sap_in_none;
01161 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, gio_rcv, sap_in);
01162
01163 set_mask = REG_RD(iop_sw_cpu, regi_iop_sw_cpu, rw_gio_set_mask);
01164 clr_mask = REG_RD(iop_sw_cpu, regi_iop_sw_cpu, rw_gio_clr_mask);
01165 if (!low_speed) {
01166 set_mask.val |= gio_speed;
01167 clr_mask.val &= ~gio_speed;
01168 } else {
01169 set_mask.val &= ~gio_speed;
01170 clr_mask.val |= gio_speed;
01171 }
01172 REG_WR(iop_sw_cpu, regi_iop_sw_cpu, rw_gio_set_mask, set_mask);
01173 REG_WR(iop_sw_cpu, regi_iop_sw_cpu, rw_gio_clr_mask, clr_mask);
01174 }
01175
01176
01177 int __init_or_module iop_usb_init(
01178 unsigned int dma_map,
01179 unsigned int ports,
01180 int int_phy)
01181 {
01182
01183 iop_usb_cfg.dma_map = dma_map;
01184 iop_usb_cfg.ports = ports;
01185 iop_usb_cfg.int_phy = int_phy;
01186
01187 if (ports == 0 || (ports & 0xf) == 0)
01188 return IOP_USB_ERR_INVAL;
01189 if (dma_map > 1)
01190 return IOP_USB_ERR_INVAL;
01191 if (alloc_dummy_buf() != 0 || alloc_static_descrs() != 0)
01192 return IOP_USB_ERR_BUSY;
01193
01194
01195 if (iop_request_dma(dma_map, INST(dma_in), "crisv32_hcd") != 0)
01196 goto out_0;
01197 if (iop_request_dma(dma_map, INST(dma_out), "crisv32_hcd") != 0)
01198 goto out_1;
01199
01200
01201 if (port_in_use(0) && int_phy != 0)
01202 if (iop_pinmux_alloc(PORT_C, 8, 14) != 0)
01203 goto out_2;
01204 if (port_in_use(1) && int_phy != 1)
01205 if (iop_pinmux_alloc(PORT_E, 8, 14) != 0)
01206 goto out_3;
01207 if (port_in_use(2))
01208 if (iop_pinmux_alloc(PORT_D, 8, 14) != 0)
01209 goto out_4;
01210 if (port_in_use(3))
01211 if (iop_pinmux_alloc(PORT_B, 8, 14) != 0)
01212 goto out_5;
01213 iop_usb_phy(int_phy);
01214
01215 iop_start_clock();
01216
01217 return IOP_USB_OK;
01218
01219 out_5:
01220 if (port_in_use(2))
01221 iop_pinmux_dealloc(PORT_D, 8, 14);
01222 out_4:
01223 if (port_in_use(1) && int_phy != 1)
01224 iop_pinmux_dealloc(PORT_E, 8, 14);
01225 out_3:
01226 if (port_in_use(0) && int_phy != 0)
01227 iop_pinmux_dealloc(PORT_C, 8, 14);
01228 out_2:
01229 iop_free_dma(INST(dma_out));
01230 out_1:
01231 iop_free_dma(INST(dma_in));
01232 out_0:
01233 return IOP_USB_ERR_BUSY;
01234 }
01235
01236
01237 void iop_usb_exit(void)
01238 {
01239 int intr0_mask;
01240
01241 intr0_mask = REG_RD_INT(iop_sw_cpu, regi_iop_sw_cpu, rw_intr0_mask);
01242 intr0_mask &= ~CPU_IRQ_MASK;
01243 REG_WR_INT(iop_sw_cpu, regi_iop_sw_cpu, rw_intr0_mask, intr0_mask);
01244
01245 iop_free_dma(INST(dma_in));
01246 iop_free_dma(INST(dma_out));
01247 iop_pinmux_dealloc(PORT_C, 8, 14);
01248 iop_pinmux_dealloc(PORT_E, 8, 14);
01249 iop_pinmux_dealloc(PORT_D, 8, 14);
01250 iop_pinmux_dealloc(PORT_B, 8, 14);
01251 }
01252
01253
01254 void __init_or_module iop_usb_config(void)
01255 {
01256 reg_iop_sw_cfg_rw_pdp0_cfg pdp0_cfg;
01257 reg_iop_sw_cfg_rw_pdp1_cfg pdp1_cfg;
01258 reg_iop_dmc_in_rw_cfg dmc_in_cfg = {
01259 .last_dis_dif = regk_iop_dmc_in_no,
01260 .sth_intr = regk_iop_dmc_in_lim64,
01261 };
01262 reg_iop_dmc_in_rw_ctrl dmc_in_ctrl = {
01263 .stream_clr = regk_iop_dmc_in_no,
01264 .dif_dis = regk_iop_dmc_in_no,
01265 .dif_en = regk_iop_dmc_in_yes,
01266 };
01267 reg_iop_dmc_in_rw_stream_ctrl dmc_in_stream_ctrl = {
01268 .size = 0,
01269 .keep_md = regk_iop_dmc_in_yes,
01270 .wait = regk_iop_dmc_in_yes,
01271 .eop = regk_iop_dmc_in_no,
01272 };
01273 reg_iop_fifo_in_rw_cfg fifo_in_cfg = {
01274 .mode = regk_iop_fifo_in_size8,
01275 .last_dis_dif_in = regk_iop_fifo_in_no,
01276 .trig = regk_iop_fifo_in_pos,
01277 .byte_order = regk_iop_fifo_in_order8,
01278 .avail_lim = 3,
01279 };
01280 reg_iop_fifo_in_rw_ctrl fifo_in_ctrl = {
01281 .dif_out_en = regk_iop_fifo_in_yes,
01282 .dif_in_en = regk_iop_fifo_in_yes,
01283 };
01284 reg_iop_fifo_out_rw_ctrl fifo_out_ctrl = {
01285 .dif_out_en = regk_iop_fifo_out_no,
01286 .dif_in_en = regk_iop_fifo_out_yes,
01287 };
01288 reg_iop_fifo_out_rw_cfg fifo_out_cfg = {
01289 .mode = regk_iop_fifo_out_size8,
01290 .last_dis_dif_out = regk_iop_fifo_out_no,
01291 .last_dis_dif_in = regk_iop_fifo_out_no,
01292 .byte_order = regk_iop_fifo_out_order8,
01293 .free_lim = 4,
01294 };
01295 reg_iop_scrc_out_rw_cfg scrc_out_cfg = {
01296 .inv_crc = regk_iop_scrc_out_yes,
01297 };
01298 reg_iop_crc_par_rw_cfg crc_par_cfg = {
01299 .poly = regk_iop_crc_par_crc16,
01300 .crc_out = regk_iop_crc_par_no,
01301 .mode = regk_iop_crc_par_check,
01302 };
01303 unsigned int mask;
01304 reg_iop_sw_cfg_rw_gio_mask gio_mask;
01305 reg_iop_sw_cfg_rw_gio_oe_mask gio_oe_mask;
01306 reg_iop_sw_cpu_rw_gio_oe_set_mask gio_oe_set_mask;
01307 reg_iop_sap_in_rw_gio sap_in0 = {
01308 .logic = regk_iop_sap_in_none,
01309 .sync_sel = regk_iop_sap_in_two_clk200,
01310 };
01311 reg_iop_sap_in_rw_gio sap_in1 = {
01312 .logic = regk_iop_sap_in_or,
01313 .sync_sel = regk_iop_sap_in_two_clk200,
01314 };
01315 reg_iop_sap_out_rw_gio sap_out = {
01316 .oe_logic = regk_iop_sap_out_none,
01317 .oe_clk_sel = regk_iop_sap_out_none,
01318 .out_logic = regk_iop_sap_out_none,
01319 .out_clk_inv = regk_iop_sap_out_no,
01320 .out_clk_sel = regk_iop_sap_out_clk12,
01321 };
01322 reg_iop_timer_grp_rw_cfg tmr_grp_cfg = {
01323 .clk_src = regk_iop_timer_grp_ext,
01324 .trig = regk_iop_timer_grp_pos_neg,
01325 };
01326 reg_iop_timer_grp_rw_half_period half_period = {
01327 .quota_hi_sel = regk_iop_timer_grp_short_period,
01328 .quota_hi = 1,
01329 .quota_lo = 0,
01330 };
01331 reg_iop_timer_grp_rw_tmr_cfg sof_tmr_cfg = {
01332 .rst_at_en_strb = regk_iop_timer_grp_no,
01333 .dis_only_by_reg = regk_iop_timer_grp_yes,
01334 .en_only_by_reg = regk_iop_timer_grp_yes,
01335 .inv = regk_iop_timer_grp_no,
01336 .active_on_tmr = SOF_TMR,
01337 .out_mode = regk_iop_timer_grp_pulse,
01338 .run_mode = regk_iop_timer_grp_stop,
01339 .strb = regk_iop_timer_grp_pos,
01340 .clk_src = regk_iop_timer_grp_clk_gen,
01341 };
01342 reg_iop_timer_grp_rw_tmr_cfg eof2_tmr_cfg = {
01343 .rst_at_en_strb = regk_iop_timer_grp_yes,
01344 .dis_only_by_reg = regk_iop_timer_grp_yes,
01345 .en_only_by_reg = regk_iop_timer_grp_no,
01346 .inv = regk_iop_timer_grp_no,
01347 .active_on_tmr = EOF2_TMR,
01348 .out_mode = regk_iop_timer_grp_toggle,
01349 .run_mode = regk_iop_timer_grp_once,
01350 .strb = regk_iop_timer_grp_pos,
01351 .clk_src = regk_iop_timer_grp_clk_gen,
01352 .en_by_tmr = SOF_TMR,
01353 };
01354 reg_iop_timer_grp_rw_tmr_cfg rx_cnt_tmr_cfg = {
01355 .rst_at_en_strb = regk_iop_timer_grp_no,
01356 .dis_only_by_reg = regk_iop_timer_grp_yes,
01357 .en_only_by_reg = regk_iop_timer_grp_yes,
01358 .inv = regk_iop_timer_grp_no,
01359 .active_on_tmr = RX_CNT_TMR,
01360 .out_mode = regk_iop_timer_grp_pulse,
01361 .run_mode = regk_iop_timer_grp_once,
01362 .strb = regk_iop_timer_grp_pos,
01363 .clk_src = regk_iop_timer_grp_clk_gen,
01364 };
01365 reg_iop_timer_grp_rw_tmr_len sof_tmr_len = {
01366 .val = FRAME_TIME - 1
01367 };
01368 reg_iop_timer_grp_rw_tmr_len eof2_tmr_len = {
01369 .val = FRAME_TIME - EOF2_NOM - 1
01370 };
01371 reg_iop_timer_grp_rw_cmd tmr_grp_cmd_rst = {
01372 .rst = 1<<SOF_TMR | 1<<EOF2_TMR
01373 };
01374 reg_iop_timer_grp_rw_cmd tmr_grp_cmd_en = {
01375 .en = 1<<SOF_TMR | 1<<EOF2_TMR
01376 };
01377 reg_iop_sw_cfg_rw_timer_grp0_cfg tmr_grp0_cfg;
01378 reg_iop_sw_cfg_rw_timer_grp1_cfg tmr_grp1_cfg;
01379 reg_iop_sw_cfg_rw_timer_grp2_cfg tmr_grp2_cfg;
01380 reg_iop_sw_cfg_rw_timer_grp3_cfg tmr_grp3_cfg;
01381 reg_iop_sw_cfg_rw_spu0_owner spu0_owner = {
01382 .cfg = regk_iop_sw_cfg_mpu
01383 };
01384 reg_iop_sw_cfg_rw_spu1_owner spu1_owner = {
01385 .cfg = regk_iop_sw_cfg_mpu
01386 };
01387 reg_iop_sw_cfg_rw_dmc_in0_owner dmc_in0_owner = {
01388 .cfg = regk_iop_sw_cfg_mpu
01389 };
01390 reg_iop_sw_cfg_rw_dmc_in1_owner dmc_in1_owner = {
01391 .cfg = regk_iop_sw_cfg_mpu
01392 };
01393 reg_iop_sw_cfg_rw_dmc_out0_owner dmc_out0_owner = {
01394 .cfg = regk_iop_sw_cfg_mpu
01395 };
01396 reg_iop_sw_cfg_rw_dmc_out1_owner dmc_out1_owner = {
01397 .cfg = regk_iop_sw_cfg_mpu
01398 };
01399 reg_iop_sw_cfg_rw_fifo_in0_owner fifo_in0_owner = {
01400 .cfg = regk_iop_sw_cfg_mpu
01401 };
01402 reg_iop_sw_cfg_rw_fifo_in1_owner fifo_in1_owner = {
01403 .cfg = regk_iop_sw_cfg_mpu
01404 };
01405 unsigned int spu = -1;
01406 reg_iop_sw_cfg_rw_fifo_out0_owner fifo_out0_owner;
01407 reg_iop_sw_cfg_rw_fifo_out1_owner fifo_out1_owner;
01408 reg_iop_sw_cfg_rw_fifo_out0_extra_owner fifo_out0_extra_owner = {
01409 .cfg = regk_iop_sw_cfg_mpu
01410
01411 };
01412 reg_iop_sw_cfg_rw_fifo_out1_extra_owner fifo_out1_extra_owner = {
01413 .cfg = regk_iop_sw_cfg_mpu
01414 };
01415 reg_iop_sw_cfg_rw_scrc_out0_owner scrc_out0_owner;
01416 reg_iop_sw_cfg_rw_scrc_out1_owner scrc_out1_owner;
01417 reg_iop_sw_cfg_rw_crc_par0_owner crc_par0_owner;
01418 reg_iop_sw_cfg_rw_crc_par1_owner crc_par1_owner;
01419 reg_iop_sw_cfg_rw_timer_grp0_owner timer_grp0_owner = {
01420 .cfg = regk_iop_sw_cfg_mpu
01421 };
01422 reg_iop_sw_cfg_rw_timer_grp1_owner timer_grp1_owner = {
01423 .cfg = regk_iop_sw_cfg_mpu
01424 };
01425 reg_iop_sw_cfg_rw_timer_grp2_owner timer_grp2_owner = {
01426 .cfg = regk_iop_sw_cfg_mpu
01427 };
01428 reg_iop_sw_cfg_rw_timer_grp3_owner timer_grp3_owner = {
01429 .cfg = regk_iop_sw_cfg_mpu
01430 };
01431
01432
01433 switch (iop_usb_cfg.dma_map) {
01434 case 0:
01435 pdp0_cfg = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_pdp0_cfg);
01436 pdp0_cfg.out_src = regk_iop_sw_cfg_dmc0;
01437 pdp0_cfg.dmc0_usr = regk_iop_sw_cfg_par0;
01438 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_pdp0_cfg, pdp0_cfg);
01439 break;
01440 case 1:
01441 pdp1_cfg = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_pdp1_cfg);
01442 pdp1_cfg.out_src = regk_iop_sw_cfg_dmc1;
01443 pdp1_cfg.dmc1_usr = regk_iop_sw_cfg_par1;
01444 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_pdp1_cfg, pdp1_cfg);
01445 break;
01446 default:
01447 BUG();
01448 }
01449
01450
01451 REG_WR(iop_dmc_in, INST(dmc_in), rw_cfg, dmc_in_cfg);
01452 REG_WR(iop_dmc_in, INST(dmc_in), rw_ctrl, dmc_in_ctrl);
01453 REG_WR(iop_dmc_in, INST(dmc_in), rw_stream_ctrl, dmc_in_stream_ctrl);
01454
01455
01456 REG_WR(iop_fifo_in, INST(fifo_in), rw_cfg, fifo_in_cfg);
01457 REG_WR(iop_fifo_in, INST(fifo_in), rw_ctrl, fifo_in_ctrl);
01458
01459
01460 REG_WR(iop_fifo_out, INST(fifo_out), rw_ctrl, fifo_out_ctrl);
01461 REG_WR(iop_fifo_out, INST(fifo_out), rw_cfg, fifo_out_cfg);
01462
01463
01464 REG_WR(iop_scrc_out, INST(scrc_out), rw_cfg, scrc_out_cfg);
01465
01466
01467 REG_WR(iop_crc_par, INST(crc_par), rw_cfg, crc_par_cfg);
01468 REG_WR(iop_crc_par, INST(crc_par), rw_correct_crc, 0x800D);
01469
01470
01471 if (port_in_use(0)) {
01472 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 10, sap_in1);
01473 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 11, sap_in0);
01474 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 26, sap_in0);
01475 }
01476 if (port_in_use(1)) {
01477 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 14, sap_in1);
01478 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 15, sap_in0);
01479 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 30, sap_in0);
01480 }
01481 if (port_in_use(2)) {
01482 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 6, sap_in1);
01483 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 7, sap_in0);
01484 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 22, sap_in0);
01485 }
01486 if (port_in_use(3)) {
01487 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 2, sap_in1);
01488 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 3, sap_in0);
01489 REG_WR_VECT(iop_sap_in, regi_iop_sap_in, rw_gio, 18, sap_in0);
01490 }
01491
01492
01493 if (port_in_use(0)) {
01494 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 8, sap_out);
01495 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 9, sap_out);
01496 }
01497 if (port_in_use(1)) {
01498 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 12, sap_out);
01499 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 13, sap_out);
01500 }
01501 if (port_in_use(2)) {
01502 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 4, sap_out);
01503 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 5, sap_out);
01504 }
01505 if (port_in_use(3)) {
01506 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 0, sap_out);
01507 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 1, sap_out);
01508 }
01509
01510 sap_out.out_logic = regk_iop_sap_out_inv;
01511 if (port_in_use(0))
01512 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 24, sap_out);
01513 if (port_in_use(1))
01514 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 28, sap_out);
01515 if (port_in_use(2))
01516 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 20, sap_out);
01517 if (port_in_use(3))
01518 REG_WR_VECT(iop_sap_out, regi_iop_sap_out, rw_gio, 16, sap_out);
01519
01520
01521 if (port_in_use(0))
01522 port_gio_config(0, 0);
01523 if (port_in_use(1))
01524 port_gio_config(1, 0);
01525 if (port_in_use(2))
01526 port_gio_config(2, 0);
01527 if (port_in_use(3))
01528 port_gio_config(3, 0);
01529
01530
01531 mask = 0;
01532 gio_mask = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_mask);
01533 gio_oe_mask = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_oe_mask);
01534 gio_oe_set_mask = REG_RD(
01535 iop_sw_cpu, regi_iop_sw_cpu, rw_gio_oe_set_mask);
01536 if (port_in_use(0))
01537 mask |= PORT_GIO_OUT_ALL(0);
01538 if (port_in_use(1))
01539 mask |= PORT_GIO_OUT_ALL(1);
01540 if (port_in_use(2))
01541 mask |= PORT_GIO_OUT_ALL(2);
01542 if (port_in_use(3))
01543 mask |= PORT_GIO_OUT_ALL(3);
01544 gio_mask.val |= mask;
01545 gio_oe_mask.val |= mask;
01546 gio_oe_set_mask.val |= mask;
01547 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_mask, gio_mask);
01548 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_gio_oe_mask, gio_oe_mask);
01549 REG_WR(iop_sw_cpu, regi_iop_sw_cpu, rw_gio_oe_set_mask,
01550 gio_oe_set_mask);
01551
01552
01553 switch (INST(frame_timer_grp)) {
01554 case regi_iop_timer_grp0:
01555 tmr_grp0_cfg =
01556 REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp0_cfg);
01557 tmr_grp0_cfg.ext_clk = regk_iop_sw_cfg_clk12;
01558 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp0_cfg,
01559 tmr_grp0_cfg);
01560 REG_WR_INT(iop_timer_grp, regi_iop_timer_grp0, rw_intr_mask,
01561 1 << EOF2_TMR);
01562 break;
01563 case regi_iop_timer_grp1:
01564 tmr_grp1_cfg =
01565 REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp1_cfg);
01566 tmr_grp1_cfg.ext_clk = regk_iop_sw_cfg_clk12;
01567 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp1_cfg,
01568 tmr_grp1_cfg);
01569 REG_WR_INT(iop_timer_grp, regi_iop_timer_grp1, rw_intr_mask,
01570 1 << EOF2_TMR);
01571 break;
01572 default:
01573 BUG();
01574 }
01575 REG_WR(iop_timer_grp, INST(frame_timer_grp), rw_cfg, tmr_grp_cfg);
01576 REG_WR(iop_timer_grp, INST(frame_timer_grp), rw_half_period,
01577 half_period);
01578 REG_WR_INT(iop_timer_grp, INST(frame_timer_grp), rw_half_period_len,
01579 1);
01580 REG_WR_VECT(iop_timer_grp, INST(frame_timer_grp), rw_tmr_cfg,
01581 SOF_TMR, sof_tmr_cfg);
01582 REG_WR_VECT(iop_timer_grp, INST(frame_timer_grp), rw_tmr_len,
01583 SOF_TMR, sof_tmr_len);
01584 REG_WR_VECT(iop_timer_grp, INST(frame_timer_grp), rw_tmr_cfg,
01585 EOF2_TMR, eof2_tmr_cfg);
01586 REG_WR_VECT(iop_timer_grp, INST(frame_timer_grp), rw_tmr_len,
01587 EOF2_TMR, eof2_tmr_len);
01588 REG_WR(iop_timer_grp, INST(frame_timer_grp), rw_cmd, tmr_grp_cmd_rst);
01589 REG_WR(iop_timer_grp, INST(frame_timer_grp), rw_cmd, tmr_grp_cmd_en);
01590
01591
01592 switch (INST(rx_cnt_timer_grp)) {
01593 case regi_iop_timer_grp2:
01594 tmr_grp2_cfg =
01595 REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp2_cfg);
01596 tmr_grp2_cfg.ext_clk = regk_iop_sw_cfg_spu0_gio7;
01597 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp2_cfg,
01598 tmr_grp2_cfg);
01599 break;
01600 case regi_iop_timer_grp3:
01601 tmr_grp3_cfg =
01602 REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp3_cfg);
01603 tmr_grp3_cfg.ext_clk = regk_iop_sw_cfg_spu1_gio7;
01604 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp3_cfg,
01605 tmr_grp3_cfg);
01606 break;
01607 default:
01608 BUG();
01609 }
01610 REG_WR(iop_timer_grp, INST(rx_cnt_timer_grp), rw_cfg, tmr_grp_cfg);
01611 REG_WR(iop_timer_grp, INST(rx_cnt_timer_grp), rw_half_period,
01612 half_period);
01613 REG_WR_INT(iop_timer_grp, INST(rx_cnt_timer_grp), rw_half_period_len,
01614 1);
01615 REG_WR_VECT(iop_timer_grp, INST(rx_cnt_timer_grp), rw_tmr_cfg,
01616 RX_CNT_TMR, rx_cnt_tmr_cfg);
01617
01618
01619
01620
01621
01622 switch (INST(spu)) {
01623 case regi_iop_spu0:
01624 spu = regk_iop_sw_cfg_spu0;
01625 break;
01626 case regi_iop_spu1:
01627 spu = regk_iop_sw_cfg_spu1;
01628 break;
01629 default:
01630 BUG();
01631 }
01632
01633
01634 switch (INST(spu)) {
01635 case regi_iop_spu0:
01636 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_spu0_owner,
01637 spu0_owner);
01638 break;
01639 case regi_iop_spu1:
01640 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_spu1_owner,
01641 spu1_owner);
01642 break;
01643 default:
01644 BUG();
01645 }
01646
01647
01648 switch (INST(dmc_in)) {
01649 case regi_iop_dmc_in0:
01650 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_dmc_in0_owner,
01651 dmc_in0_owner);
01652 break;
01653 case regi_iop_dmc_in1:
01654 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_dmc_in1_owner,
01655 dmc_in1_owner);
01656 break;
01657 default:
01658 BUG();
01659 }
01660
01661
01662 switch (INST(dmc_out)) {
01663 case regi_iop_dmc_out0:
01664 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_dmc_out0_owner,
01665 dmc_out0_owner);
01666 break;
01667 case regi_iop_dmc_out1:
01668 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_dmc_out1_owner,
01669 dmc_out1_owner);
01670 break;
01671 default:
01672 BUG();
01673 }
01674
01675
01676 switch (INST(fifo_in)) {
01677 case regi_iop_fifo_in0:
01678 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_fifo_in0_owner,
01679 fifo_in0_owner);
01680 break;
01681 case regi_iop_fifo_in1:
01682 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_fifo_in1_owner,
01683 fifo_in1_owner);
01684 break;
01685 default:
01686 BUG();
01687 }
01688
01689
01690 switch (INST(fifo_out)) {
01691 case regi_iop_fifo_out0:
01692 fifo_out0_owner.cfg = spu;
01693 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_fifo_out0_owner,
01694 fifo_out0_owner);
01695 break;
01696 case regi_iop_fifo_out1:
01697 fifo_out1_owner.cfg = spu;
01698 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_fifo_out1_owner,
01699 fifo_out1_owner);
01700 break;
01701 default:
01702 BUG();
01703 }
01704
01705
01706 switch (INST(fifo_out_extra)) {
01707 case regi_iop_fifo_out0_extra:
01708 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_fifo_out0_extra_owner,
01709 fifo_out0_extra_owner);
01710 break;
01711 case regi_iop_fifo_out1_extra:
01712 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_fifo_out1_extra_owner,
01713 fifo_out1_extra_owner);
01714 break;
01715 default:
01716 BUG();
01717 }
01718
01719
01720 switch (INST(scrc_out)) {
01721 case regi_iop_scrc_out0:
01722 scrc_out0_owner.cfg = spu;
01723 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_scrc_out0_owner,
01724 scrc_out0_owner);
01725 break;
01726 case regi_iop_scrc_out1:
01727 scrc_out1_owner.cfg = spu;
01728 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_scrc_out1_owner,
01729 scrc_out1_owner);
01730 break;
01731 default:
01732 BUG();
01733 }
01734
01735
01736 switch (INST(crc_par)) {
01737 case regi_iop_crc_par0:
01738 crc_par0_owner.cfg = spu;
01739 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_crc_par0_owner,
01740 crc_par0_owner);
01741 break;
01742 case regi_iop_crc_par1:
01743 crc_par1_owner.cfg = spu;
01744 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_crc_par1_owner,
01745 crc_par1_owner);
01746 break;
01747 default:
01748 BUG();
01749 }
01750
01751
01752 switch (INST(frame_timer_grp)) {
01753 case regi_iop_timer_grp0:
01754 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp0_owner,
01755 timer_grp0_owner);
01756 break;
01757 case regi_iop_timer_grp1:
01758 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp1_owner,
01759 timer_grp1_owner);
01760 break;
01761 default:
01762 BUG();
01763 }
01764
01765
01766 switch (INST(rx_cnt_timer_grp)) {
01767 case regi_iop_timer_grp2:
01768 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp2_owner,
01769 timer_grp2_owner);
01770 break;
01771 case regi_iop_timer_grp3:
01772 REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_timer_grp3_owner,
01773 timer_grp3_owner);
01774 break;
01775 default:
01776 BUG();
01777 }
01778 }
01779
01780
01781 int iop_usb_reset(void)
01782 {
01783 reg_iop_spu_rw_ctrl spu_ctrl = {
01784 .en = regk_iop_spu_no,
01785 .fsm = regk_iop_spu_no,
01786 };
01787
01788
01789 REG_WR(iop_spu, INST(spu), rw_ctrl, spu_ctrl);
01790 if (mpu_halt() != 0)
01791 return IOP_USB_ERR_TIMEOUT;
01792
01793 return IOP_USB_OK;
01794 }
01795
01796
01797 int iop_usb_start(int intr_mask)
01798 {
01799 int intr0_mask;
01800 u32 fw_id;
01801
01802 BUG_ON(iop_usb_cfg.ports < 0);
01803
01804
01805 port_power = 0;
01806
01807
01808 init_dma();
01809
01810
01811 if (read_mpu_mem(MPU_ADDR_FW_ID, &fw_id) != 0)
01812 return IOP_USB_ERR_TIMEOUT;
01813 if (!CHECK_FW_ID(fw_id, MPU, iop_usb_cfg.dma_map))
01814 return IOP_USB_ERR_BAD_FW;
01815
01816
01817 if (write_mpu_mem(MPU_ADDR_PORTS, iop_usb_cfg.ports))
01818 return IOP_USB_ERR_TIMEOUT;
01819
01820
01821 if (mpu_start() != 0)
01822 return IOP_USB_ERR_TIMEOUT;
01823
01824
01825 intr0_mask = REG_RD_INT(iop_sw_cpu, regi_iop_sw_cpu, rw_intr0_mask);
01826 intr0_mask |= intr_mask & CPU_IRQ_MASK;
01827 REG_WR_INT(iop_sw_cpu, regi_iop_sw_cpu, rw_intr0_mask, intr0_mask);
01828
01829 return IOP_USB_OK;
01830 }
01831
01832
01833 int iop_usb_get_frame(void)
01834 {
01835 u32 data;
01836 if (read_mpu_mem(MPU_ADDR_FRAME_NUMBER, &data) != 0)
01837 return -1;
01838 return data & 0x7ff;
01839 }
01840
01841
01842 int iop_usb_port_stat(unsigned int port, u16 *wPortStatus, u16 *wPortChange)
01843 {
01844 u32 data;
01845
01846 BUG_ON(port < 0 || port >= IOP_USB_ROOT_HUB_PORTS);
01847 if (!port_in_use(port))
01848 return IOP_USB_ERR_INVAL;
01849 if (read_mpu_mem(mpu_addr_port_stat(port), &data) != 0)
01850 return IOP_USB_ERR_TIMEOUT;
01851 if (wPortStatus) {
01852 *wPortStatus = data & 0xffff;
01853 if (port_power & (1 << port))
01854 *wPortStatus |= (1 << IOP_USB_PORT_POWER);
01855 }
01856 if (wPortChange)
01857 *wPortChange = (data >> 16) & 0xff;
01858 return IOP_USB_OK;
01859 }
01860
01861
01862 int iop_usb_set_port_feat(unsigned int port, unsigned int feat)
01863 {
01864 u16 wPortStatus;
01865 int low_speed;
01866
01867 BUG_ON(port < 0 || port >= IOP_USB_ROOT_HUB_PORTS);
01868
01869 if (!port_in_use(port))
01870 return IOP_USB_ERR_INVAL;
01871
01872 switch (feat) {
01873 case IOP_USB_PORT_POWER:
01874
01875
01876 port_power |= (1 << port);
01877 return IOP_USB_OK;
01878 case IOP_USB_PORT_RESET:
01879 if (iop_usb_port_stat(port, &wPortStatus, NULL) != IOP_USB_OK)
01880 return IOP_USB_ERR_TIMEOUT;
01881 low_speed = wPortStatus & (1 << IOP_USB_PORT_LOW_SPEED);
01882 port_gio_config(port, low_speed);
01883 break;
01884 case IOP_USB_PORT_SUSPEND:
01885 break;
01886 default:
01887 return IOP_USB_ERR_INVAL;
01888 }
01889 if (mpu_rh_port_request(IOP_USB_SET_FEATURE, port, feat) != 0)
01890 return IOP_USB_ERR_TIMEOUT;
01891 return IOP_USB_OK;
01892 }
01893
01894
01895 int iop_usb_clr_port_feat(unsigned int port, unsigned int feat)
01896 {
01897 BUG_ON(port < 0 || port >= IOP_USB_ROOT_HUB_PORTS);
01898 if (!port_in_use(port))
01899 return IOP_USB_ERR_INVAL;
01900
01901 switch (feat) {
01902 case IOP_USB_PORT_POWER:
01903
01904
01905 port_power &= ~(1 << port);
01906 return IOP_USB_OK;
01907 case IOP_USB_PORT_ENABLE:
01908 case IOP_USB_PORT_SUSPEND:
01909 break;
01910 case IOP_USB_C_PORT_CONNECTION:
01911 case IOP_USB_C_PORT_ENABLE:
01912 case IOP_USB_C_PORT_SUSPEND:
01913 case IOP_USB_C_PORT_OVERCURRENT:
01914 case IOP_USB_C_PORT_RESET:
01915
01916 break;
01917 default:
01918 return IOP_USB_ERR_INVAL;
01919 }
01920 if (mpu_rh_port_request(IOP_USB_CLEAR_FEATURE, port, feat) != 0)
01921 return IOP_USB_ERR_TIMEOUT;
01922 return IOP_USB_OK;
01923 }
01924
01925
01926 int iop_usb_active_irqs(void)
01927 {
01928 int irqs = REG_RD_INT(iop_sw_cpu, regi_iop_sw_cpu, r_masked_intr0);
01929 irqs &= CPU_IRQ_MASK;
01930 REG_WR_INT(iop_sw_cpu, regi_iop_sw_cpu, rw_ack_intr0, irqs);
01931 return irqs;
01932 }
01933
01934
01935 int iop_usb_spu_nr(void)
01936 {
01937 if (iop_usb_cfg.dma_map < 0)
01938 return -1;
01939 switch (INST(spu)) {
01940 case regi_iop_spu0:
01941 return 0;
01942 case regi_iop_spu1:
01943 return 1;
01944 default:
01945 return -1;
01946 }
01947 }
01948
01949
01950 int iop_usb_dma_map(void)
01951 {
01952 u32 fw_id;
01953
01954 if (read_mpu_mem(MPU_ADDR_FW_ID, &fw_id) != 0)
01955 return -1;
01956 return (fw_id & FW_ID_DMAMAP_MASK) >> FW_ID_DMAMAP_BIT;
01957 }