Subversion Repositories freemyipod

Rev

Rev 890 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 890 Rev 945
Line 14... Line 14...
14
#define SYNOPSYSOTG_TURNAROUND 3
14
#define SYNOPSYSOTG_TURNAROUND 3
15
#endif
15
#endif
16
 
16
 
17
static void synopsysotg_flush_out_endpoint(const struct usb_instance* instance, int ep)
17
static void synopsysotg_flush_out_endpoint(const struct usb_instance* instance, int ep)
18
{
18
{
-
 
19
    if (!ep) return;
19
    const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
20
    const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
20
    if (data->core->outep_regs[ep].doepctl.b.epena)
21
    if (data->core->outep_regs[ep].doepctl.b.epena)
21
    {
22
    {
22
        // We are waiting for an OUT packet on this endpoint, which might arrive any moment.
23
        // We are waiting for an OUT packet on this endpoint, which might arrive any moment.
23
        // Assert a global output NAK to avoid race conditions while shutting down the endpoint.
24
        // Assert a global output NAK to avoid race conditions while shutting down the endpoint.
24
        synopsysotg_target_disable_irq(instance);
25
        synopsysotg_target_disable_irq(instance);
25
        data->core->dregs.dctl.b.sgoutnak = 1;
26
        data->core->dregs.dctl.b.sgoutnak = 1;
26
        while (!(data->core->gregs.gintsts.b.goutnakeff));
27
        while (!(data->core->gregs.gintsts.b.goutnakeff));
27
        union synopsysotg_depctl doepctl = { .b = { .snak = 1, .epdis = 1 } };
28
        data->core->outep_regs[ep].doepctl.b.snak = 1;
28
        data->core->outep_regs[ep].doepctl = doepctl;
29
        data->core->outep_regs[ep].doepctl.b.epdis = 1;
29
        while (!(data->core->outep_regs[ep].doepint.b.epdisabled));
30
        while (!(data->core->outep_regs[ep].doepint.b.epdisabled));
30
        data->core->dregs.dctl.b.cgoutnak = 1;
31
        data->core->dregs.dctl.b.cgoutnak = 1;
31
        synopsysotg_target_enable_irq(instance);
32
        synopsysotg_target_enable_irq(instance);
32
    }
33
    }
33
    data->core->outep_regs[ep].doepctl.b.usbactep = 0;
34
    data->core->outep_regs[ep].doepctl.b.usbactep = 0;
Line 35... Line 36...
35
    data->core->outep_regs[ep].doeptsiz.d32 = 0;
36
    data->core->outep_regs[ep].doeptsiz.d32 = 0;
36
}
37
}
37
 
38
 
38
static void synopsysotg_flush_in_endpoint(const struct usb_instance* instance, int ep)
39
static void synopsysotg_flush_in_endpoint(const struct usb_instance* instance, int ep)
39
{
40
{
-
 
41
    if (!ep) return;
40
    const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
42
    const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
41
    if (data->core->inep_regs[ep].diepctl.b.epena)
43
    if (data->core->inep_regs[ep].diepctl.b.epena)
42
    {
44
    {
43
        // We are shutting down an endpoint that might still have IN packets in the FIFO.
45
        // We are shutting down an endpoint that might still have IN packets in the FIFO.
44
        // Disable the endpoint, wait for things to settle, and flush the relevant FIFO.
46
        // Disable the endpoint, wait for things to settle, and flush the relevant FIFO.
45
        synopsysotg_target_disable_irq(instance);
47
        synopsysotg_target_disable_irq(instance);
46
        data->core->inep_regs[ep].diepctl.b.snak = 1;
48
        data->core->inep_regs[ep].diepctl.b.snak = 1;
47
        while (!(data->core->inep_regs[ep].diepint.b.inepnakeff));
49
        while (!(data->core->inep_regs[ep].diepint.b.inepnakeff));
48
        data->core->inep_regs[ep].diepctl.b.epdis = 1;
50
        data->core->inep_regs[ep].diepctl.b.epdis = 1;
49
        while (!(data->core->inep_regs[ep].diepint.b.epdisabled));
51
        while (!(data->core->inep_regs[ep].diepint.b.epdisabled));
50
        if (ep) data->core->inep_regs[ep].diepctl.b.usbactep = 0;
52
        data->core->inep_regs[ep].diepctl.b.usbactep = 0;
51
        synopsysotg_target_enable_irq(instance);
53
        synopsysotg_target_enable_irq(instance);
52
        // Wait for any DMA activity to stop, to make sure nobody will touch the FIFO.
54
        // Wait for any DMA activity to stop, to make sure nobody will touch the FIFO.
53
        while (!data->core->gregs.grstctl.b.ahbidle);
55
        while (!data->core->gregs.grstctl.b.ahbidle);
54
        // Flush it all the way down!
56
        // Flush it all the way down!
55
        union synopsysotg_grstctl grstctl = { .b = { .txfnum = data->core->inep_regs[ep].diepctl.b.txfnum, .txfflsh = 1 } };
57
        union synopsysotg_grstctl grstctl = { .b = { .txfnum = data->core->inep_regs[ep].diepctl.b.txfnum, .txfflsh = 1 } };
Line 159... Line 161...
159
    if (ep.direction == USB_ENDPOINT_DIRECTION_IN)
161
    if (ep.direction == USB_ENDPOINT_DIRECTION_IN)
160
        return !!data->core->inep_regs[ep.number].diepctl.b.stall;
162
        return !!data->core->inep_regs[ep.number].diepctl.b.stall;
161
    return !!data->core->outep_regs[ep.number].doepctl.b.stall;
163
    return !!data->core->outep_regs[ep.number].doepctl.b.stall;
162
}
164
}
163
 
165
 
164
void synopsysotg_set_stall(const struct usb_instance* instance, union usb_endpoint_number ep, int stall)
166
void synopsysotg_set_stall(const struct usb_instance* instance, union usb_endpoint_number ep, bool stall)
165
{
167
{
166
    const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
168
    const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
167
    if (ep.direction == USB_ENDPOINT_DIRECTION_IN)
169
    if (ep.direction == USB_ENDPOINT_DIRECTION_IN)
168
    {
170
    {
169
        data->core->inep_regs[ep.number].diepctl.b.stall = !!stall;
171
        data->core->inep_regs[ep.number].diepctl.b.stall = !!stall;
Line 222... Line 224...
222
        data->core->outep_regs[ep.number].doepctl = depctl;
224
        data->core->outep_regs[ep.number].doepctl = depctl;
223
        data->core->dregs.daintmsk.ep.out |= (1 << ep.number);
225
        data->core->dregs.daintmsk.ep.out |= (1 << ep.number);
224
    }
226
    }
225
}
227
}
226
 
228
 
227
void synopsysotg_ep0_start_rx(const struct usb_instance* instance, int non_setup)
229
void synopsysotg_ep0_start_rx(const struct usb_instance* instance, bool non_setup, int len)
228
{
230
{
229
    const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
231
    const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
230
    struct synopsysotg_state* state = (struct synopsysotg_state*)instance->driver_state;
232
    struct synopsysotg_state* state = (struct synopsysotg_state*)instance->driver_state;
231
 
233
 
232
    // Set up data destination
234
    // Set up data destination
233
    if (data->use_dma) data->core->outep_regs[0].doepdma = instance->buffer;
235
    if (data->use_dma) data->core->outep_regs[0].doepdma = instance->buffer;
234
    else state->endpoints[0].rxaddr = (uint32_t*)instance->buffer;
236
    else state->endpoints[0].rxaddr = (uint32_t*)instance->buffer;
235
    union synopsysotg_dep0xfrsiz deptsiz = { .b = { .supcnt = 3, .pktcnt = !!non_setup, .xfersize = 64 } };
237
    union synopsysotg_dep0xfrsiz deptsiz = { .b = { .supcnt = 3, .pktcnt = !!non_setup, .xfersize = len } };
236
    data->core->outep_regs[0].doeptsiz.d32 = deptsiz.d32;
238
    data->core->outep_regs[0].doeptsiz.d32 = deptsiz.d32;
237
 
239
 
238
    // Flush CPU cache if necessary
240
    // Flush CPU cache if necessary
239
    if (data->use_dma) invalidate_dcache(instance->buffer, sizeof(instance->buffer));
241
    if (data->use_dma) invalidate_dcache(instance->buffer, len);
240
 
242
 
241
    // Enable the endpoint
243
    // Enable the endpoint
242
    union synopsysotg_depctl depctl = data->core->outep_regs[0].doepctl;
244
    union synopsysotg_depctl depctl = data->core->outep_regs[0].doepctl;
243
    depctl.b.epena = 1;
245
    depctl.b.epena = 1;
244
    depctl.b.cnak = non_setup;
246
    depctl.b.cnak = !!non_setup;
245
    data->core->outep_regs[0].doepctl = depctl;
247
    data->core->outep_regs[0].doepctl = depctl;
246
}
248
}
247
 
249
 
248
void synopsysotg_ep0_start_tx(const struct usb_instance* instance, const void* buf, int len)
250
void synopsysotg_ep0_start_tx(const struct usb_instance* instance, const void* buf, int len)
249
{
251
{
Line 362... Line 364...
362
                        }
364
                        }
363
                    }
365
                    }
364
                }
366
                }
365
                union usb_endpoint_number epnum = { .direction = USB_ENDPOINT_DIRECTION_IN, .number = ep };
367
                union usb_endpoint_number epnum = { .direction = USB_ENDPOINT_DIRECTION_IN, .number = ep };
366
                int bytesleft = data->core->inep_regs[ep].dieptsiz.b.xfersize;
368
                int bytesleft = data->core->inep_regs[ep].dieptsiz.b.xfersize;
-
 
369
                data->core->inep_regs[ep].diepint = epints;
367
                if (epints.b.timeout) usb_handle_timeout(instance, epnum, bytesleft);
370
                if (epints.b.timeout) usb_handle_timeout(instance, epnum, bytesleft);
368
                if (epints.b.xfercompl) usb_handle_xfer_complete(instance, epnum, bytesleft);
371
                if (epints.b.xfercompl) usb_handle_xfer_complete(instance, epnum, bytesleft);
369
                data->core->inep_regs[ep].diepint = epints;
-
 
370
            }
372
            }
371
    }
373
    }
372
 
374
 
373
    if (gintsts.b.outepintr)
375
    if (gintsts.b.outepintr)
374
    {
376
    {
Line 376... Line 378...
376
        int ep;
378
        int ep;
377
        for (ep = 0; ep < 16; ep++)
379
        for (ep = 0; ep < 16; ep++)
378
            if (daint.ep.out & (1 << ep))
380
            if (daint.ep.out & (1 << ep))
379
            {
381
            {
380
                union synopsysotg_doepintn epints = data->core->outep_regs[ep].doepint;
382
                union synopsysotg_doepintn epints = data->core->outep_regs[ep].doepint;
-
 
383
                data->core->outep_regs[ep].doepint = epints;
381
                union usb_endpoint_number epnum = { .direction = USB_ENDPOINT_DIRECTION_OUT, .number = ep };
384
                union usb_endpoint_number epnum = { .direction = USB_ENDPOINT_DIRECTION_OUT, .number = ep };
382
                if (epints.b.setup)
385
                if (epints.b.setup)
383
                {
386
                {
384
                    if (data->use_dma) invalidate_dcache(instance->buffer, sizeof(instance->buffer));
387
                    if (data->use_dma) invalidate_dcache((const void*)data->core->inep_regs[ep].diepdma, 8);
385
                    synopsysotg_flush_in_endpoint(instance, ep);
388
                    synopsysotg_flush_in_endpoint(instance, ep);
386
                    usb_handle_setup_received(instance, epnum);
389
                    usb_handle_setup_received(instance, epnum);
387
                }
390
                }
388
                else if (epints.b.xfercompl)
391
                else if (epints.b.xfercompl)
389
                {
392
                {
390
                    int bytesleft = data->core->inep_regs[ep].dieptsiz.b.xfersize;
393
                    int bytesleft = data->core->inep_regs[ep].dieptsiz.b.xfersize;
391
                    usb_handle_xfer_complete(instance, epnum, bytesleft);
394
                    usb_handle_xfer_complete(instance, epnum, bytesleft);
392
                }
395
                }
393
                data->core->outep_regs[ep].doepint = epints;
-
 
394
            }
396
            }
395
    }
397
    }
396
 
398
 
397
    data->core->gregs.gintsts = gintsts;
399
    data->core->gregs.gintsts = gintsts;
398
}
400
}
Line 456... Line 458...
456
        data->core->dregs.dthrctl = dthrctl;
458
        data->core->dregs.dthrctl = dthrctl;
457
    }
459
    }
458
    int addr = data->fifosize;
460
    int addr = data->fifosize;
459
    for (i = 0; i < 16; i++)
461
    for (i = 0; i < 16; i++)
460
    {
462
    {
-
 
463
        data->core->inep_regs[i].diepctl.b.nextep = (i + 1) & 0xf;
461
        int size = data->txfifosize[i];
464
        int size = data->txfifosize[i];
462
        addr -= size;
465
        addr -= size;
463
        if (size)
466
        if (size)
464
        {
467
        {
465
            data->core->inep_regs[i].diepctl.b.nextep = (i + 1) & 0xf;
-
 
466
            union synopsysotg_txfsiz fsiz = { .b = { .startaddr = addr, .depth = size } };
468
            union synopsysotg_txfsiz fsiz = { .b = { .startaddr = addr, .depth = size } };
467
            if (!i) data->core->gregs.dieptxf0_hnptxfsiz = fsiz;
469
            if (!i) data->core->gregs.dieptxf0_hnptxfsiz = fsiz;
468
            else data->core->gregs.dieptxf[i - 1] = fsiz;
470
            else data->core->gregs.dieptxf[i - 1] = fsiz;
469
        }
471
        }
470
    }
472
    }
Line 524... Line 526...
524
    .set_address = synopsysotg_set_address,
526
    .set_address = synopsysotg_set_address,
525
    .configure_ep = synopsysotg_configure_ep,
527
    .configure_ep = synopsysotg_configure_ep,
526
    .unconfigure_ep = synopsysotg_unconfigure_ep,
528
    .unconfigure_ep = synopsysotg_unconfigure_ep,
527
    .get_max_transfer_size = synopsysotg_get_max_transfer_size,
529
    .get_max_transfer_size = synopsysotg_get_max_transfer_size,
528
};
530
};
-
 
531