modules/usb/iop/common-R1_01/iop-usb.c

Go to the documentation of this file.
00001 /* $Id: iop-usb.c,v 1.1.1.1 2008/11/27 20:04:03 elphel Exp $
00002  *
00003  * ETRAX FS IOP USB 1.1 Host Controller
00004  *
00005  * Initialization of hardware and interaction with IOP
00006  *
00007  * Copyright (C) 2004, 2005  Axis Communications AB
00008  *
00009  * Author: Lars Viklund <larsv@axis.com>
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 /* SIMDEF_TARGET_BANANA */
00035 #define D(x)
00036 #endif /* SIMDEF_TARGET_BANANA */
00037 
00038 /* number of iteration in before timeout while waiting for IOP */
00039 #define IOP_TIMEOUT             1000
00040 
00041 /* port status power state */
00042 static unsigned int port_power; 
00043 
00044 /* convert output context descriptor to endpoint descriptor (depends
00045  * on this descriptor being the first field in struct iop_usb_ed) */
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  * The constants for maxium interval for periodic traffic below may
00053  * be adjusted as needed. However, note that the Linux USB core
00054  * currently does not allow value larger than 255 for interrupt
00055  * traffic and 1024 for isochronous traffic.
00056  */
00057 
00058 /* maximum interval for isochronous traffic */
00059 #define MAX_INTERVAL_ISOC       1024
00060 
00061 /* maximum interval for interrupt traffic */
00062 #define MAX_INTERVAL_INTR       256
00063 
00064 /* total number of transfer types */
00065 #define NUM_TRANSFER_TYPE       4
00066 
00067 /* number of periodic transfer types */
00068 #define NUM_PER_TRANSFER_TYPE   2
00069 
00070 /* extra group descriptor with EOL */
00071 #define IOP_USB_GROUP_EOL       (IOP_USB_BULK + 1)
00072 
00073 /* DMA group descriptors */
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 /* DMA context descriptors */
00083 static dma_descr_context *ctxt_head;
00084 static dma_descr_context *ctxt_eol;
00085 static dma_descr_context *ctxt_in_eol;
00086 
00087 /* total allocation size for static DMA descriptors */
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 /* dummy buffer, for overflow input data */
00096 #define DUMMY_BUF_SIZE          1500 /* largest possible packet in one frame */
00097 static char *dummy_buf;              /* physical address of dummy buffer */
00098 
00099 /* allocate dummy buffer */
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 /* allocate static DMA descriptors */
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 /* initialize DMA data structure for periodic traffic */
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 /* initialize DMA descriptors used to terminate input context
00179  * descriptor lists */
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 /* initialize DMA data structure and enable DMA */
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                         /*FALLTHROUGH*/
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                         /*FALLTHROUGH*/
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 /* enable group, called when data has been inserted */
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 /* reset the status of an endpoint, called when clearing an error condition */
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 /* reset output context pointers to data */
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 /* busy-wait until the DMA is clear of this (disabled) context */
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(); /* for write which disables context */
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 /* adjust group descriptor down pointers for periodic traffic */
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(); /* ensure context is updated before changing the group list */
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 /* initialize a descriptor for an endpoint */
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         /* Convert time from us to bit times and add marginal for
00415          * EOF1.  Note that the host controller delay should already
00416          * be included in the time passed to this function. */
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 /* initialize and add a descriptor for an endpoint */
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         /* the list of context descriptors is kept sorted on interval */
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         /* insert in list */
00459         ed->ctxt.next = prev->next;
00460         prev->next = VIRT_TO_PHYS(&ed->ctxt);
00461 
00462         /* adjust group descriptor down pointers for periodic traffic */
00463         if (iop_usb_ttd(&group_head[type])->is_periodic)
00464                 schedule_periodic(type, prev);
00465 }
00466 
00467 /* release a descriptor for an endpoint */
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         /* unlink context descriptor from list */
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         /* adjust group descriptor down pointers for periodic traffic */
00489         if (iop_usb_ttd(&group_head[type])->is_periodic)
00490                 schedule_periodic(type, prev);
00491 }
00492 
00493 /* wait until a released descriptor for an endpoint is no longer used
00494  * by the DMA */
00495 void iop_usb_endpoint_release_wait(struct iop_usb_ed *ed)
00496 {
00497 
00498         /* busy-wait until the DMA is clear of this context to ensure
00499          * that the descriptor is not freed while it is still in
00500          * use */
00501         wait_on_ctxt(ed);
00502 }
00503 
00504 /* initialize descriptors for an USB transaction */
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                 /* input descriptors refers to buffer */
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                 /* the number of expected packets is stored in the in
00545                  * context meta data */
00546                 td->u.priv.c_in.md1 = buffer_length == 0 ? 
00547                         1 : (buffer_length - 1) / maxsize + 1;
00548                 /* add dummy descriptor to catch additional data,
00549                  * otherwise the DMA channel will hang if the device
00550                  * returns more data than the driver expected */
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                 /*FALLTHROUGH*/
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 /* insert descriptors in output list */
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         /* find end of the new descriptors and set EOL, convert next
00576          * pointers to physical addresses at the same time */
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; /* terminate list */
00583         wmb();
00584         if (ed->head_out) {
00585                 /* insert at end of existing list */
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                 /* list is empty */
00595                 ed->head_out = td;
00596                 reset_out_context(ed, td);
00597         }
00598         if (ed->ctxt.dis) {
00599                 /* check if endpoint has halted */
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                 /* DMA stopped before processing the new data descriptor */
00605                 reset_out_context(ed, td);
00606         }
00607         return 0;
00608 }
00609 
00610 /* insert descriptors in input list */
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         /* assemble list of input context descriptors */
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; /* no input descriptors */
00630 
00631         cur->next = VIRT_TO_PHYS(ctxt_in_eol); /* terminate list */
00632         if (ed->head_in) {
00633                 /* insert at end of existing list */
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                 /* list is empty */
00643                 ed->head_in = first;
00644         }
00645         /* reset context pointer in in_group if it has reached end of list */
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 /* remove descriptors from output list */
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                 /* descriptors to remove is at the head of the list */
00665                 ed->head_out = after;
00666         } else {
00667                 /* search the list for the first descriptor to remove */
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); /* first not found */
00675                 if (!after)
00676                         prev->u.priv.d_out.eol = 1;
00677                 prev->u.next = after;
00678         }
00679         /* reset context if current descriptor is removed, convert
00680          * next pointers back to virtual addresses at the same time */ 
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); /* last not found */
00689         last->u.next = NULL;
00690 }
00691         
00692 /* remove descriptors from input list */
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         /* find input context descriptors to remove */
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; /* no IN transactions to remove */
00721 
00722         /* note that the list is terminated with ctxt_in_eol
00723          * descriptors, but an empty list is represented by NULL */
00724         after = PHYS_TO_VIRT(last_in->next);
00725         /* handle case were the descriptors to remove is at the head
00726          * of the list */
00727         if (ed->head_in == first_in) {
00728                 /* descriptors to remove is at the head of the list */
00729                 ed->head_in = after->eol ? NULL :  after;
00730         } else {
00731                 /* search the list for the first descriptor to remove */
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); /* first not found */
00739                 prev->next = after;
00740         }
00741         /* reset group if current descriptor is removed */
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); /* last not found */
00749         last_in->next = NULL;
00750 }
00751 
00752 /* enqueue DMA descriptors for an USB transaction */
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                 /* note that in this case the context will have been
00764                  * disabled by the MPU so it is safe to remove the in
00765                  * descriptor */
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 /* lock an endpoint to allow dequeuing data descriptors for an USB
00774  * transaction */
00775 void iop_usb_trans_dequeue_lock(struct iop_usb_ed *ed)
00776 {
00777         /* disable the context to ensure that the dequeuing is atomic
00778          * from the DMA point of view */
00779         ed->ctxt.en = 0;
00780         /* busy-wait while the DMA is working on the context */
00781         wait_on_ctxt(ed);
00782 }
00783 
00784 /* dequeue data descriptors for an USB transaction */
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 /* unlock an endpoint after dequeueing data descriptors for an USB
00804    transaction */
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                         /* DMA may disable the the group if no other
00813                          * contexts are enabled */
00814                         enable_group(ed->type);
00815                         /* It is still possible that the DMA disables
00816                          * the group after the enabling above. Request
00817                          * an interrupt at the end of the current
00818                          * frame and let finish_data() take care of
00819                          * this case. */
00820                         fe_irq_request();
00821                 }
00822         } else
00823                 ed->ctxt.dis = 1;
00824         wmb();
00825         ed->ctxt.en = 1;
00826 }
00827 
00828 /* stop processing peridic traffic of the specified type until more
00829  * traffic is submitted */
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 /* return completed data descriptors to upper layer */
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; /* nothing to do */
00849         ctxt_in = (ed->type == IOP_USB_CTRL || ed->is_in) ? ed->head_in : NULL;
00850         /* if the EP has stopped on an error all pending data should
00851          * be flushed, return it with status set to no error and
00852          * length set to zero */
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                 /* get length from descriptor */
00861                 switch (data_md->type) {
00862                 case IOP_USB_IN:
00863                         /* first verify that the output and input
00864                          * lists are in sync */
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                                 /* EOP should be set in the data
00871                                  * descriptor, otherwise we have got
00872                                  * an overrun into the dummy data
00873                                  * descriptor */
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                 /* restore pointers before calling the callback */
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         /* clear error condition, if any */
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                 /* have processed all data */
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         /* handle race condition where the DMA disabled the context
00919          * while we were inserting data into the list */
00920         if (ed->ctxt.dis)
00921                 reset_out_context(ed, ed->head_out);
00922         /* also handle case where the DMA disabled the group */
00923         if (ed->type == IOP_USB_CTRL || ed->type == IOP_USB_BULK)
00924                 enable_group(ed->type);
00925 }
00926 
00927 /* interrupt handler for IOP_USB_IRQ_TRANS_DONE */
00928 void iop_usb_trans_done_irq(void (*cb)(struct iop_usb_td *, int, int))
00929 {
00930         unsigned int type;
00931 
00932         /* check all endpoints for completed data descriptors */
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 /* wait for the MPU instruction register to become idle, with timeout */
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 /* wait for the MPU_REG_DATA register to become zero, with timeout */
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 /* read MPU memory */
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 /* write MPU memory */
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 /* halt the MPU */
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 /* start the MPU */
01013 static int mpu_start(void)
01014 {
01015         reg_iop_mpu_rw_ctrl mpu_ctrl = { .en = regk_iop_mpu_yes };
01016 
01017         /* reset MPU PC and wait for it to bite */
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         /* make sure the MPU starts executing with interrupts disabled */
01025         REG_WR(iop_mpu, regi_iop_mpu, rw_instr, MPU_DI());
01026         if (wait_mpu_idle() != 0)
01027                 return -1;
01028 
01029         /* ok, lets go! */
01030         REG_WR(iop_mpu, regi_iop_mpu, rw_ctrl, mpu_ctrl);
01031 
01032         return 0;
01033 }
01034 
01035 /* call interrupt routine in MPU to set flags to initiate a set or
01036  * clear feature request to the root hub */
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 /* call interrupt routine in MPU to set flag to request an interrupt
01058  * at the end of the current frame */
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 /* configure GIO for a port */
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         /* map V_PO/V_MO and OE from SPU to GIO_OUT */
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                 /* swap v_po and v_mo for low speed signaling */
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         /* set logic for GIO_IN depending on speed */
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         /* set SPEED using set/clr masks */
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 /* initialize multiplexing of DMA channels and pins, start clock */
01177 int __init_or_module iop_usb_init(
01178         unsigned int dma_map, 
01179         unsigned int ports, 
01180         int int_phy)
01181 {
01182         /* store configuration */
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         /* DMA channels */
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         /* pinmux */
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 /* free resources allocated by iop_usb_init() */
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 /* configure IOP */
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         /* Parallel Data Path */
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         /* DMC In */
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         /* FIFO In */
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         /* FIFO Out */
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         /* Serial CRC Out */
01464         REG_WR(iop_scrc_out, INST(scrc_out), rw_cfg, scrc_out_cfg);
01465 
01466         /* Parallel CRC */
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         /* SAP In */
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         /* SAP Out */
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         /* invert OE to PHY (active low) */
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         /* initial configuration of GIOs */
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         /* enable output for GIOs */
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         /* SOF and EOF2 Timers */
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         /* Timer used to count received bytes during IN transaction */
01591         /* Use SPU GIO_OUT7 as clock */
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          * Set owners 
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         /* MPU owns SPU */
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         /* MPU owns DMC_IN */
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         /* MPU owns DMC_OUT */
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         /* MPU owns FIFO_IN */
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         /* SPU owns FIFO_OUT */
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         /* MPU owns FIFO_OUT_EXTRA */
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         /* SPU owns SCRC_OUT */
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         /* SPU owns CRC_PAR */
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         /* MPU owns frame timers */
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         /* MPU owns timer used to count received bytes during IN transaction */
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 /* reset processors firmware and driver */
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         /* halt SPU and MPU */
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 /* start execution */
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         /* start with all ports powered off */
01805         port_power = 0;
01806 
01807         /* initialize DMA data structure */
01808         init_dma();
01809         
01810         /* validate the loaded firmware */
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         /* store information about included ports in MPU memory */
01817         if (write_mpu_mem(MPU_ADDR_PORTS, iop_usb_cfg.ports))
01818                 return IOP_USB_ERR_TIMEOUT;
01819 
01820         /* start the MPU */
01821         if (mpu_start() != 0)
01822                 return IOP_USB_ERR_TIMEOUT;
01823                 
01824         /* interrupts to CPU */
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 /* get current frame number */
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 /* get port status and port change fields */
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 /* set port status feature */
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                 /* enable power to port, not supported on FS testcard
01875                  * with D38 removed */
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 /* clear port status or port status change feature */
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                 /* disable power to port, not supported on FS testcard
01904                  * with D38 removed */
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                 /* clear port status change bit */
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 /* get active interrupts */
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 /* get SPU number used */
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 /* get DMA mapping used by the loaded firmware */
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 }

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1