Subversion Repositories freemyipod

Rev

Rev 923 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 923 Rev 944
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 380... Line 382...
380
                union synopsysotg_doepintn epints = data->core->outep_regs[ep].doepint;
382
                union synopsysotg_doepintn epints = data->core->outep_regs[ep].doepint;
381
                data->core->outep_regs[ep].doepint = epints;
383
                data->core->outep_regs[ep].doepint = epints;
382
                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 };
383
                if (epints.b.setup)
385
                if (epints.b.setup)
384
                {
386
                {
385
                    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);
386
                    synopsysotg_flush_in_endpoint(instance, ep);
388
                    synopsysotg_flush_in_endpoint(instance, ep);
387
                    usb_handle_setup_received(instance, epnum);
389
                    usb_handle_setup_received(instance, epnum);
388
                }
390
                }
389
                else if (epints.b.xfercompl)
391
                else if (epints.b.xfercompl)
390
                {
392
                {
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
    }