Open FFBoard
Open source force feedback firmware
dcd_sunxi_musb.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2021 Koji KITAYAMA
5 * Copyright (c) 2021 Tian Yunhao (t123yh)
6 * Copyright (c) 2021 Ha Thach (tinyusb.org)
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 *
26 * This file is part of the TinyUSB stack.
27 */
28
29#include <stdint.h>
30#include "tusb_option.h"
31
32#if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_F1C100S
33
34#include "osal/osal.h"
35#include <f1c100s-irq.h>
36#include <device/dcd.h>
37#include "musb_def.h"
38
39//#include "bsp/board_api.h"
40extern uint32_t board_millis(void); // TODO remove
41
42typedef uint32_t u32;
43typedef uint16_t u16;
44typedef uint8_t u8;
45
46
47#define REQUEST_TYPE_INVALID (0xFFu)
48
49typedef struct {
50 uint_fast16_t beg; /* offset of including first element */
51 uint_fast16_t end; /* offset of excluding the last element */
53
54typedef struct TU_ATTR_PACKED
55{
56 void *buf; /* the start address of a transfer data buffer */
57 uint16_t length; /* the number of bytes in the buffer */
58 uint16_t remaining; /* the number of bytes remaining in the buffer */
60
61typedef struct
62{
64 uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */
65 int8_t status_out;
66 pipe_state_t pipe0;
67 pipe_state_t pipe[2][7]; /* pipe[direction][endpoint number - 1] */
68 uint16_t pipe_buf_is_fifo[2]; /* Bitmap. Each bit means whether 1:TU_FIFO or 0:POD. */
70
71/*------------------------------------------------------------------
72 * SUNXI FUNCTION
73 *------------------------------------------------------------------*/
74
75static void usb_phy_write(int addr, int data, int len)
76{
77 int j = 0, usbc_bit = 0;
78 void *dest = (void *)USBC_REG_CSR(USBC0_BASE);
79
80 usbc_bit = 1 << (0 * 2);
81 for (j = 0; j < len; j++)
82 {
83 /* set the bit address to be written */
84 USBC_ClrBit_Mask_l(dest, 0xff << 8);
85 USBC_SetBit_Mask_l(dest, (addr + j) << 8);
86
87 USBC_ClrBit_Mask_l(dest, usbc_bit);
88 /* set data bit */
89 if (data & 0x1)
90 USBC_SetBit_Mask_l(dest, 1 << 7);
91 else
92 USBC_ClrBit_Mask_l(dest, 1 << 7);
93
94 USBC_SetBit_Mask_l(dest, usbc_bit);
95
96 USBC_ClrBit_Mask_l(dest, usbc_bit);
97
98 data >>= 1;
99 }
100}
101
102static void delay_ms(uint32_t ms)
103{
104#if CFG_TUSB_OS == OPT_OS_NONE
105 int now = board_millis();
106 while (board_millis() - now <= ms) asm("nop");
107#else
108 osal_task_delay(ms);
109#endif
110}
111
112static void USBC_HardwareReset(void)
113{
114 // Reset phy and controller
115 USBC_REG_set_bit_l(USBPHY_CLK_RST_BIT, USBPHY_CLK_REG);
116 USBC_REG_set_bit_l(BUS_RST_USB_BIT, BUS_CLK_RST_REG);
117 delay_ms(2);
118
119 USBC_REG_set_bit_l(USBPHY_CLK_GAT_BIT, USBPHY_CLK_REG);
120 USBC_REG_set_bit_l(USBPHY_CLK_RST_BIT, USBPHY_CLK_REG);
121
122 USBC_REG_set_bit_l(BUS_CLK_USB_BIT, BUS_CLK_GATE0_REG);
123 USBC_REG_set_bit_l(BUS_RST_USB_BIT, BUS_CLK_RST_REG);
124}
125
126static void USBC_PhyConfig(void)
127{
128 /* Regulation 45 ohms */
129 usb_phy_write(0x0c, 0x01, 1);
130
131 /* adjust PHY's magnitude and rate */
132 usb_phy_write(0x20, 0x14, 5);
133
134 /* threshold adjustment disconnect */
135 usb_phy_write(0x2a, 3, 2);
136
137 return;
138}
139
140static void USBC_ConfigFIFO_Base(void)
141{
142 u32 reg_value;
143
144 /* config usb fifo, 8kb mode */
145 reg_value = USBC_Readl(SUNXI_SRAMC_BASE + 0x04);
146 reg_value &= ~(0x03 << 0);
147 reg_value |= (1 << 0);
148 USBC_Writel(reg_value, SUNXI_SRAMC_BASE + 0x04);
149}
150
151static unsigned int USBC_WakeUp_ClearChangeDetect(unsigned int reg_val)
152{
153 unsigned int temp = reg_val;
154 /* vbus, id, dpdm, these bit is set 1 to clear, so we clear these bit when operate other bits */
155 temp &= ~(1 << USBC_BP_ISCR_VBUS_CHANGE_DETECT);
156 temp &= ~(1 << USBC_BP_ISCR_ID_CHANGE_DETECT);
157 temp &= ~(1 << USBC_BP_ISCR_DPDM_CHANGE_DETECT);
158
159 return temp;
160}
161
162static void USBC_EnableDpDmPullUp(void)
163{
164 u32 reg_val = USBC_Readl(USBC_REG_ISCR(USBC0_BASE));
165 reg_val |= (1 << USBC_BP_ISCR_DPDM_PULLUP_EN);
166 reg_val |= 3<<USBC_BP_ISCR_VBUS_VALID_SRC;
167 reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
168 USBC_Writel(reg_val, USBC_REG_ISCR(USBC0_BASE));
169}
170
171static void USBC_ForceIdToHigh(void)
172{
173 /* first write 00, then write 10 */
174 u32 reg_val = USBC_Readl(USBC_REG_ISCR(USBC0_BASE));
175 reg_val |= (0x03 << USBC_BP_ISCR_FORCE_ID);
176 reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
177 USBC_Writel(reg_val, USBC_REG_ISCR(USBC0_BASE));
178}
179
181{
182 /* first write 00, then write 11 */
183 u32 reg_val = USBC_Readl(USBC_REG_ISCR(USBC0_BASE));
184 reg_val |= (0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID);
185 reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
186 USBC_Writel(reg_val, USBC_REG_ISCR(USBC0_BASE));
187}
188
189void USBC_SelectBus(u32 io_type, u32 ep_type, u32 ep_index)
190{
191 u32 reg_val = 0;
192
193 reg_val = USBC_Readb(USBC_REG_VEND0(USBC0_BASE));
194 if (io_type == USBC_IO_TYPE_DMA) {
195 if (ep_type == USBC_EP_TYPE_TX) {
196 reg_val |= ((ep_index - 0x01) << 1) << USBC_BP_VEND0_DRQ_SEL; //drq_sel
197 reg_val |= 0x1<<USBC_BP_VEND0_BUS_SEL; //io_dma
198 } else {
199 reg_val |= ((ep_index << 1) - 0x01) << USBC_BP_VEND0_DRQ_SEL;
200 reg_val |= 0x1<<USBC_BP_VEND0_BUS_SEL;
201 }
202 } else {
203 //reg_val &= ~(0x1 << USBC_BP_VEND0_DRQ_SEL); //clear drq_sel, select pio
204 reg_val &= 0x00; // clear drq_sel, select pio
205 }
206
207 /* in 1667 1673 and later ic, FIFO_BUS_SEL bit(bit24 of reg0x40 for host/device)
208 * is fixed to 1, the hw guarantee that it's ok for cpu/inner_dma/outer_dma transfer */
209
210// reg_val |= 0x1<<USBC_BP_VEND0_BUS_SEL; //for 1663 set 1: enable dma, set 0: enable fifo
211
212 USBC_Writeb(reg_val, USBC_REG_VEND0(USBC0_BASE));
213}
214
215static void USBC_SelectActiveEp(u8 ep_index)
216{
217 USBC_Writeb(ep_index, USBC_REG_EPIND(USBC0_BASE));
218}
219
221{
222 return USBC_Readb(USBC_REG_EPIND(USBC0_BASE));
223}
224
226{
227 USBC_REG_set_bit_w(USBC_BP_CSR0_D_SEND_STALL, USBC_REG_CSR0(USBC0_BASE));
228}
229
231{
232 USBC_REG_clear_bit_w(USBC_BP_CSR0_D_SEND_STALL, USBC_REG_CSR0(USBC0_BASE));
233 USBC_REG_clear_bit_w(USBC_BP_CSR0_D_SENT_STALL, USBC_REG_CSR0(USBC0_BASE));
234}
235
237{
238 USBC_REG_set_bit_w(USBC_BP_CSR0_D_SERVICED_SETUP_END, USBC_REG_CSR0(USBC0_BASE));
239}
240
241static void USBC_Dev_SetAddress(u8 address)
242{
243 USBC_Writeb(address, USBC_REG_FADDR(USBC0_BASE));
244}
245
246static void __USBC_Dev_Tx_SendStall(void)
247{
248 //send stall, and fifo is flushed automatically
249 USBC_REG_set_bit_w(USBC_BP_TXCSR_D_SEND_STALL, USBC_REG_TXCSR(USBC0_BASE));
250}
252{
253 return USBC_REG_test_bit_w(USBC_BP_TXCSR_D_SENT_STALL, USBC_REG_TXCSR(USBC0_BASE));
254}
256{
257 u32 reg_val = USBC_Readw(USBC_REG_TXCSR(USBC0_BASE));
258 reg_val &= ~((1 << USBC_BP_TXCSR_D_SENT_STALL)|(1 << USBC_BP_TXCSR_D_SEND_STALL)|(1<<USBC_BP_TXCSR_D_UNDER_RUN));
259 reg_val |= (1 << USBC_BP_TXCSR_D_CLEAR_DATA_TOGGLE);
260 USBC_Writew(reg_val, USBC_REG_TXCSR(USBC0_BASE));
261}
262
263static void __USBC_Dev_Rx_SendStall(void)
264{
265 USBC_REG_set_bit_w(USBC_BP_RXCSR_D_SEND_STALL, USBC_REG_RXCSR(USBC0_BASE));
266}
267
269{
270 return USBC_REG_test_bit_w(USBC_BP_RXCSR_D_SENT_STALL, USBC_REG_RXCSR(USBC0_BASE));
271}
272
274{
275 u32 reg_val = USBC_Readw(USBC_REG_RXCSR(USBC0_BASE));
276 reg_val &= ~((1 << USBC_BP_RXCSR_D_SENT_STALL)|(1 << USBC_BP_RXCSR_D_SEND_STALL)|(1<<USBC_BP_RXCSR_D_OVERRUN));
277 reg_val |= (1 << USBC_BP_RXCSR_D_CLEAR_DATA_TOGGLE);
278 USBC_Writew(reg_val, USBC_REG_RXCSR(USBC0_BASE));
279}
280
282{
283 if (USBC_REG_test_bit_b(USBC_BP_POWER_D_HIGH_SPEED_FLAG, USBC_REG_PCTL(USBC0_BASE)))
284 return TUSB_SPEED_HIGH;
285 else
286 return TUSB_SPEED_FULL;
287}
288
290{
291 USBC_Writew(1<<USBC_BP_CSR0_D_SERVICED_RX_PKT_READY, USBC_REG_CSR0(USBC0_BASE));
292}
293
295{
296 USBC_Writew((1<<USBC_BP_CSR0_D_SERVICED_RX_PKT_READY) | (1<<USBC_BP_CSR0_D_DATA_END),
297 USBC_REG_CSR0(USBC0_BASE));
298}
299
300
302{
303 USBC_Writew(1<<USBC_BP_CSR0_D_TX_PKT_READY, USBC_REG_CSR0(USBC0_BASE));
304}
305
307{
308 USBC_Writew((1<<USBC_BP_CSR0_D_TX_PKT_READY) | (1<<USBC_BP_CSR0_D_DATA_END),
309 USBC_REG_CSR0(USBC0_BASE));
310}
311
313{
314 USBC_Writeb((1 << USBC_BP_TXCSR_D_TX_READY), USBC_REG_TXCSR(USBC0_BASE));
315}
316
318{
319 USBC_Writeb(0, USBC_REG_RXCSR(USBC0_BASE));
320}
321
323{
324 return USBC_REG_test_bit_w(USBC_BP_RXCSR_D_RX_PKT_READY, USBC_REG_RXCSR(USBC0_BASE));
325}
326
327/* open a tx ep's interrupt */
328static void USBC_INT_EnableTxEp(u8 ep_index)
329{
330 USBC_REG_set_bit_w(ep_index, USBC_REG_INTTxE(USBC0_BASE));
331}
332
333/* open a rx ep's interrupt */
334static void USBC_INT_EnableRxEp(u8 ep_index)
335{
336 USBC_REG_set_bit_w(ep_index, USBC_REG_INTRxE(USBC0_BASE));
337}
338
339/* close a tx ep's interrupt */
340static void USBC_INT_DisableTxEp(u8 ep_index)
341{
342 USBC_REG_clear_bit_w(ep_index, USBC_REG_INTTxE(USBC0_BASE));
343}
344
345/* close a rx ep's interrupt */
346static void USBC_INT_DisableRxEp(u8 ep_index)
347{
348 USBC_REG_clear_bit_w(ep_index, USBC_REG_INTRxE(USBC0_BASE));
349}
350
351/*------------------------------------------------------------------
352 * INTERNAL FUNCTION DECLARATION
353 *------------------------------------------------------------------*/
354
355CFG_TUD_MEM_ALIGN static dcd_data_t _dcd;
356
357static inline free_block_t *find_containing_block(free_block_t *beg, free_block_t *end, uint_fast16_t addr)
358{
359 free_block_t *cur = beg;
360 for (; cur < end && ((addr < cur->beg) || (cur->end <= addr)); ++cur) ;
361 return cur;
362}
363
364static inline int update_free_block_list(free_block_t *blks, unsigned num, uint_fast16_t addr, uint_fast16_t size)
365{
366 free_block_t *p = find_containing_block(blks, blks + num, addr);
367 TU_ASSERT(p != blks + num, -2);
368 if (p->beg == addr) {
369 /* Shrink block */
370 p->beg = addr + size;
371 if (p->beg != p->end) return 0;
372 /* remove block */
373 free_block_t *end = blks + num;
374 while (p + 1 < end) {
375 *p = *(p + 1);
376 ++p;
377 }
378 return -1;
379 } else {
380 /* Split into 2 blocks */
381 free_block_t tmp = {
382 .beg = addr + size,
383 .end = p->end
384 };
385 p->end = addr;
386 if (p->beg == p->end) {
387 if (tmp.beg != tmp.end) {
388 *p = tmp;
389 return 0;
390 }
391 /* remove block */
392 free_block_t *end = blks + num;
393 while (p + 1 < end) {
394 *p = *(p + 1);
395 ++p;
396 }
397 return -1;
398 }
399 if (tmp.beg == tmp.end) return 0;
400 blks[num] = tmp;
401 return 1;
402 }
403}
404
405static inline unsigned free_block_size(free_block_t const *blk)
406{
407 return blk->end - blk->beg;
408}
409
410#if 0
411static inline void print_block_list(free_block_t const *blk, unsigned num)
412{
413 TU_LOG1("*************\r\n");
414 for (unsigned i = 0; i < num; ++i) {
415 TU_LOG1(" Blk%u %u %u\r\n", i, blk->beg, blk->end);
416 ++blk;
417 }
418}
419#else
420#define print_block_list(a,b)
421#endif
422
423#if CFG_TUSB_MCU == OPT_MCU_F1C100S
424#define USB_FIFO_SIZE_KB 4
425#else
426#error "Unsupported MCU"
427#endif
428
429static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3)
430{
431 free_block_t free_blocks[2 * (TUP_DCD_ENDPOINT_MAX - 1)];
432 unsigned num_blocks = 1;
433 /* Backup current EP to restore later */
434 u8 backup_ep = USBC_GetActiveEp();
435
436 /* Initialize free memory block list */
437 free_blocks[0].beg = 64 / 8;
438 free_blocks[0].end = (USB_FIFO_SIZE_KB << 10) / 8; /* 2KiB / 8 bytes */
439 for (int i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) {
440 uint_fast16_t addr;
441 int num;
443 addr = USBC_Readw(USBC_REG_TXFIFOAD(USBC0_BASE));
444 if (addr) {
445 unsigned sz = USBC_Readb(USBC_REG_TXFIFOSZ(USBC0_BASE));
446 unsigned sft = (sz & USB_TXFIFOSZ_SIZE_M) + ((sz & USB_TXFIFOSZ_DPB) ? 1: 0);
447 num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft);
448 TU_ASSERT(-2 < num, 0);
449 num_blocks += num;
450 print_block_list(free_blocks, num_blocks);
451 }
452 addr = USBC_Readw(USBC_REG_RXFIFOAD(USBC0_BASE));
453 if (addr) {
454 unsigned sz = USBC_Readb(USBC_REG_RXFIFOSZ(USBC0_BASE));
455 unsigned sft = (sz & USB_RXFIFOSZ_SIZE_M) + ((sz & USB_RXFIFOSZ_DPB) ? 1: 0);
456 num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft);
457 TU_ASSERT(-2 < num, 0);
458 num_blocks += num;
459 print_block_list(free_blocks, num_blocks);
460 }
461 }
462 print_block_list(free_blocks, num_blocks);
463
464 USBC_SelectActiveEp(backup_ep);
465
466 /* Find the best fit memory block */
467 uint_fast16_t size_in_8byte_unit = 1 << size_in_log2_minus3;
468 free_block_t const *min = NULL;
469 uint_fast16_t min_sz = 0xFFFFu;
470 free_block_t const *end = &free_blocks[num_blocks];
471 for (free_block_t const *cur = &free_blocks[0]; cur < end; ++cur) {
472 uint_fast16_t sz = free_block_size(cur);
473 if (sz < size_in_8byte_unit) continue;
474 if (size_in_8byte_unit == sz) return cur->beg;
475 if (sz < min_sz) min = cur;
476 }
477 TU_ASSERT(min, 0);
478 return min->beg;
479}
480
481static void pipe_write_packet(void *buff, volatile void *fifo, unsigned cnt)
482{
483 u32 len = 0;
484 u32 i32 = 0;
485 u32 i8 = 0;
486 u8 *buf8 = 0;
487 u32 *buf32 = 0;
488
489 //--<1>-- adjust data
490 buf32 = buff;
491 len = cnt;
492
493 i32 = len >> 2;
494 i8 = len & 0x03;
495
496 //--<2>-- deal with 4byte part
497 while (i32--) {
498 USBC_Writel(*buf32++, fifo);
499 }
500
501 //--<3>-- deal with no 4byte part
502 buf8 = (u8 *)buf32;
503 while (i8--) {
504 USBC_Writeb(*buf8++, fifo);
505 }
506}
507
508static void pipe_read_packet(void *buff, volatile void *fifo, unsigned cnt)
509{
510 u32 len = 0;
511 u32 i32 = 0;
512 u32 i8 = 0;
513 u8 *buf8 = 0;
514 u32 *buf32 = 0;
515
516 //--<1>-- adjust data
517 buf32 = buff;
518 len = cnt;
519
520 i32 = len >> 2;
521 i8 = len & 0x03;
522
523 //--<2>-- deal with 4byte part
524 while (i32--) {
525 *buf32++ = USBC_Readl(fifo);
526 }
527
528 //--<3>-- deal with no 4byte part
529 buf8 = (u8 *)buf32;
530 while (i8--) {
531 *buf8++ = USBC_Readb(fifo);
532 }
533}
534
535static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir)
536{
537 static const struct {
538 void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
539 void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n);
540 void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len);
541 } ops[] = {
544 };
546 ops[dir].tu_fifo_get_info(f, &info);
547 unsigned total_len = len;
548 len = TU_MIN(total_len, info.len_lin);
549 ops[dir].pipe_read_write(info.ptr_lin, fifo, len);
550 unsigned rem = total_len - len;
551 if (rem) {
552 len = TU_MIN(rem, info.len_wrap);
553 ops[dir].pipe_read_write(info.ptr_wrap, fifo, len);
554 rem -= len;
555 }
556 ops[dir].tu_fifo_advance(f, total_len - rem);
557}
558
559/*------------------------------------------------------------------
560 * TRANSFER FUNCTION DECLARATION
561 *------------------------------------------------------------------*/
562
563static void process_setup_packet(uint8_t rhport)
564{
565 uint32_t *p = (uint32_t*)(uintptr_t) &_dcd.setup_packet;
566 p[0] = USBC_Readl(USBC_REG_EPFIFO0(USBC0_BASE));
567 p[1] = USBC_Readl(USBC_REG_EPFIFO0(USBC0_BASE));
568
569 _dcd.pipe0.buf = NULL;
570 _dcd.pipe0.length = 0;
571 _dcd.pipe0.remaining = 0;
572 dcd_event_setup_received(rhport, (const uint8_t*)(uintptr_t)&_dcd.setup_packet, true);
573
574 const unsigned len = _dcd.setup_packet.wLength;
575 _dcd.remaining_ctrl = len;
576 const unsigned dir_in = tu_edpt_dir(_dcd.setup_packet.bmRequestType);
577 /* Clear RX FIFO and reverse the transaction direction */
578 if (len && dir_in) __USBC_Dev_ep0_ReadDataHalf();
579}
580
581static bool handle_xfer_in(uint_fast8_t ep_addr)
582{
583 unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1;
584 pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1];
585 const unsigned rem = pipe->remaining;
586
587 if (!rem) {
588 pipe->buf = NULL;
589 return true;
590 }
591
592 const unsigned mps = USBC_Readw(USBC_REG_TXMAXP(USBC0_BASE));
593 const unsigned len = TU_MIN(mps, rem);
594 uint8_t *buf = pipe->buf;
595 // TU_LOG1(" %p mps %d len %d rem %d\r\n", buf, mps, len, rem);
596 if (len) {
597 volatile void* addr = (volatile void*)(USBC_REG_EPFIFO1(USBC0_BASE) + (epnum_minus1 << 2));
598 if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) {
599 pipe_read_write_packet_ff((tu_fifo_t *)(uintptr_t) buf, addr, len, TUSB_DIR_IN);
600 } else {
601 pipe_write_packet(buf, addr, len);
602 pipe->buf = buf + len;
603 }
604 pipe->remaining = rem - len;
605 }
607 // TU_LOG1(" TXCSRL%d = %x %d\r\n", epnum_minus1 + 1, regs->TXCSRL, rem - len);
608 return false;
609}
610
611static bool handle_xfer_out(uint_fast8_t ep_addr)
612{
613 unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1;
614 pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1];
615 // TU_LOG1(" RXCSRL%d = %x\r\n", epnum_minus1 + 1, regs->RXCSRL);
616
618
619 const unsigned mps = USBC_Readw(USBC_REG_RXMAXP(USBC0_BASE));
620 const unsigned rem = pipe->remaining;
621 const unsigned vld = USBC_Readw(USBC_REG_RXCOUNT(USBC0_BASE));
622 const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
623 uint8_t *buf = pipe->buf;
624 if (len) {
625 volatile void* addr = (volatile void*)(USBC_REG_EPFIFO1(USBC0_BASE) + (epnum_minus1 << 2));
626 if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) {
627 pipe_read_write_packet_ff((tu_fifo_t *)(uintptr_t )buf, addr, len, TUSB_DIR_OUT);
628 } else {
629 pipe_read_packet(buf, addr, len);
630 pipe->buf = buf + len;
631 }
632 pipe->remaining = rem - len;
633 }
634 if ((len < mps) || (rem == len)) {
635 pipe->buf = NULL;
636 return NULL != buf;
637 }
639 return false;
640}
641
642static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
643{
644 (void)rhport;
645
646 unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1;
647 unsigned dir_in = tu_edpt_dir(ep_addr);
648
649 pipe_state_t *pipe = &_dcd.pipe[dir_in][epnum_minus1];
650 pipe->buf = buffer;
651 pipe->length = total_bytes;
652 pipe->remaining = total_bytes;
653
655
656 if (dir_in) {
657 handle_xfer_in(ep_addr);
658 } else {
661 }
662 return true;
663}
664
665static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
666{
667 (void)rhport;
668 TU_ASSERT(total_bytes <= 64); /* Current implementation supports for only up to 64 bytes. */
669
670 const unsigned req = _dcd.setup_packet.bmRequestType;
671 TU_ASSERT(req != REQUEST_TYPE_INVALID || total_bytes == 0);
672
674
675 if (req == REQUEST_TYPE_INVALID || _dcd.status_out) {
676 /* STATUS OUT stage.
677 * MUSB controller automatically handles STATUS OUT packets without
678 * software helps. We do not have to do anything. And STATUS stage
679 * may have already finished and received the next setup packet
680 * without calling this function, so we have no choice but to
681 * invoke the callback function of status packet here. */
682 // TU_LOG1(" STATUS OUT CSRL0 = %x\r\n", CSRL0);
683 _dcd.status_out = 0;
684 if (req == REQUEST_TYPE_INVALID) {
686 } else {
687 /* The next setup packet has already been received, it aborts
688 * invoking callback function to avoid confusing TUSB stack. */
689 TU_LOG1("Drop CONTROL_STAGE_ACK\r\n");
690 }
691 return true;
692 }
693 const unsigned dir_in = tu_edpt_dir(ep_addr);
694 if (tu_edpt_dir(req) == dir_in) { /* DATA stage */
695 TU_ASSERT(total_bytes <= _dcd.remaining_ctrl);
696 const unsigned rem = _dcd.remaining_ctrl;
697 const unsigned len = TU_MIN(TU_MIN(rem, 64), total_bytes);
698 if (dir_in) {
699 pipe_write_packet(buffer, (volatile void*) USBC_REG_EPFIFO0(USBC0_BASE), len);
700
701 _dcd.pipe0.buf = buffer + len;
702 _dcd.pipe0.length = len;
703 _dcd.pipe0.remaining = 0;
704
705 _dcd.remaining_ctrl = rem - len;
706 if ((len < 64) || (rem == len)) {
707 _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; /* Change to STATUS/SETUP stage */
708 _dcd.status_out = 1;
709 /* Flush TX FIFO and reverse the transaction direction. */
711 } else {
713 }
714 // TU_LOG1(" IN CSRL0 = %x\r\n", CSRL0);
715 } else {
716 // TU_LOG1(" OUT CSRL0 = %x\r\n", CSRL0);
718 _dcd.pipe0.length = len;
719 _dcd.pipe0.remaining = len;
721 }
722 } else if (dir_in) {
723 // TU_LOG1(" STATUS IN CSRL0 = %x\r\n", CSRL0);
724 _dcd.pipe0.buf = NULL;
725 _dcd.pipe0.length = 0;
726 _dcd.pipe0.remaining = 0;
727 /* Clear RX FIFO and reverse the transaction direction */
729 }
730 return true;
731}
732
733static void process_ep0(uint8_t rhport)
734{
736 uint_fast8_t csrl = USBC_Readw(USBC_REG_CSR0(USBC0_BASE));
737
738 // TU_LOG1(" EP0 CSRL0 = %x\r\n", csrl);
739
740 if (csrl & USB_CSRL0_STALLED) {
741 /* Returned STALL packet to HOST. */
743 return;
744 }
745
746 unsigned req = _dcd.setup_packet.bmRequestType;
747 if (csrl & USB_CSRL0_SETEND) {
748 // TU_LOG1(" ABORT by the next packets\r\n");
750 if (req != REQUEST_TYPE_INVALID && _dcd.pipe0.buf) {
751 /* DATA stage was aborted by receiving STATUS or SETUP packet. */
752 _dcd.pipe0.buf = NULL;
753 _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
755 req & TUSB_DIR_IN_MASK,
757 XFER_RESULT_SUCCESS, true);
758 }
759 req = REQUEST_TYPE_INVALID;
760 if (!(csrl & USB_CSRL0_RXRDY)) return; /* Received SETUP packet */
761 }
762
763 if (csrl & USB_CSRL0_RXRDY) {
764 /* Received SETUP or DATA OUT packet */
765 if (req == REQUEST_TYPE_INVALID) {
766 /* SETUP */
767 TU_ASSERT(sizeof(tusb_control_request_t) == USBC_Readw(USBC_REG_COUNT0(USBC0_BASE)),);
768 process_setup_packet(rhport);
769 return;
770 }
771 if (_dcd.pipe0.buf) {
772 /* DATA OUT */
773 const unsigned vld = USBC_Readw(USBC_REG_COUNT0(USBC0_BASE));
774 const unsigned rem = _dcd.pipe0.remaining;
775 const unsigned len = TU_MIN(TU_MIN(rem, 64), vld);
776 pipe_read_packet(_dcd.pipe0.buf, (volatile void*)USBC_REG_EPFIFO0(USBC0_BASE), len);
777
778 _dcd.pipe0.remaining = rem - len;
779 _dcd.remaining_ctrl -= len;
780
781 _dcd.pipe0.buf = NULL;
785 XFER_RESULT_SUCCESS, true);
786 }
787 return;
788 }
789
790 /* When CSRL0 is zero, it means that completion of sending a any length packet
791 * or receiving a zero length packet. */
792 if (req != REQUEST_TYPE_INVALID && !tu_edpt_dir(req)) {
793 /* STATUS IN */
794 if (*(const uint16_t*)(uintptr_t)&_dcd.setup_packet == 0x0500) {
795 /* The address must be changed on completion of the control transfer. */
796 USBC_Dev_SetAddress((uint8_t)_dcd.setup_packet.wValue);
797 }
798 _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
802 XFER_RESULT_SUCCESS, true);
803 return;
804 }
805 if (_dcd.pipe0.buf) {
806 /* DATA IN */
807 _dcd.pipe0.buf = NULL;
811 XFER_RESULT_SUCCESS, true);
812 }
813}
814
815static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr)
816{
817 bool completed;
818 const unsigned dir_in = tu_edpt_dir(ep_addr);
819 const unsigned epn = tu_edpt_number(ep_addr);
820
822
823 if (dir_in) {
824 // TU_LOG1(" TXCSRL%d = %x\r\n", epn_minus1 + 1, regs->TXCSRL);
827 return;
828 }
829 completed = handle_xfer_in(ep_addr);
830 } else {
831 // TU_LOG1(" RXCSRL%d = %x\r\n", epn_minus1 + 1, regs->RXCSRL);
834 return;
835 }
836 completed = handle_xfer_out(ep_addr);
837 }
838
839 if (completed) {
840 pipe_state_t *pipe = &_dcd.pipe[dir_in][tu_edpt_number(ep_addr) - 1];
841 dcd_event_xfer_complete(rhport, ep_addr,
842 pipe->length - pipe->remaining,
843 XFER_RESULT_SUCCESS, true);
844 }
845}
846
847static void process_bus_reset(uint8_t rhport)
848{
849 /* When bmRequestType is REQUEST_TYPE_INVALID(0xFF),
850 * a control transfer state is SETUP or STATUS stage. */
851 _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
852 _dcd.status_out = 0;
853 /* When pipe0.buf has not NULL, DATA stage works in progress. */
854 _dcd.pipe0.buf = NULL;
855
856 USBC_Writew(1, USBC_REG_INTTxE(USBC0_BASE)); /* Enable only EP0 */
857 USBC_Writew(0, USBC_REG_INTRxE(USBC0_BASE));
858
860}
861
862/*------------------------------------------------------------------
863 * Device API
864 *------------------------------------------------------------------*/
865
866static void usb_isr_handler(void) {
868}
869
870bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
871 (void) rh_init;
872
873 dcd_disconnect(rhport);
878 USBC_ForceIdToHigh(); // Force device mode
880 USBC_SelectBus(USBC_IO_TYPE_PIO, 0, 0);
881 dcd_edpt_close_all(rhport);
882
883 #if TUD_OPT_HIGH_SPEED
884 USBC_REG_set_bit_b(USBC_BP_POWER_D_HIGH_SPEED_EN, USBC_REG_PCTL(USBC0_BASE));
885 #else
886 USBC_REG_clear_bit_b(USBC_BP_POWER_D_HIGH_SPEED_EN, USBC_REG_PCTL(USBC0_BASE));
887 #endif
888
889 USBC_Writeb((1 << USBC_BP_INTUSBE_EN_SUSPEND)
890 | (1 << USBC_BP_INTUSBE_EN_RESUME)
891 | (1 << USBC_BP_INTUSBE_EN_RESET)
892 | (1 << USBC_BP_INTUSBE_EN_SOF)
893 | (1 << USBC_BP_INTUSBE_EN_DISCONNECT)
894 , USBC_REG_INTUSBE(USBC0_BASE));
895 f1c100s_intc_clear_pend(F1C100S_IRQ_USBOTG);
896 f1c100s_intc_set_isr(F1C100S_IRQ_USBOTG, usb_isr_handler);
897
898 dcd_connect(rhport);
899
900 return true;
901}
902
903// Connect by enabling internal pull-up resistor on D+/D-
904void dcd_connect(uint8_t rhport)
905{
906 (void)rhport;
907 USBC_REG_set_bit_b(USBC_BP_POWER_D_SOFT_CONNECT, USBC_REG_PCTL(USBC0_BASE));
908}
909
910// Disconnect by disabling internal pull-up resistor on D+/D-
911void dcd_disconnect(uint8_t rhport)
912{
913 (void)rhport;
914 USBC_REG_clear_bit_b(USBC_BP_POWER_D_SOFT_CONNECT, USBC_REG_PCTL(USBC0_BASE));
915}
916
917void dcd_sof_enable(uint8_t rhport, bool en)
918{
919 (void) rhport;
920 (void) en;
921
922 // TODO implement later
923}
924
925void dcd_int_enable(uint8_t rhport)
926{
927 (void)rhport;
928 f1c100s_intc_enable_irq(F1C100S_IRQ_USBOTG);
929}
930
931static void musb_int_mask(void)
932{
933 f1c100s_intc_mask_irq(F1C100S_IRQ_USBOTG);
934}
935
936void dcd_int_disable(uint8_t rhport)
937{
938 (void)rhport;
939 f1c100s_intc_disable_irq(F1C100S_IRQ_USBOTG);
940}
941
942static void musb_int_unmask(void)
943{
944 f1c100s_intc_unmask_irq(F1C100S_IRQ_USBOTG);
945}
946
947// Receive Set Address request, mcu port must also include status IN response
948void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
949{
950 (void)rhport;
951 (void)dev_addr;
952 _dcd.pipe0.buf = NULL;
953 _dcd.pipe0.length = 0;
954 _dcd.pipe0.remaining = 0;
955 /* Clear RX FIFO to return ACK. */
958}
959
960// Wake up host
961void dcd_remote_wakeup(uint8_t rhport)
962{
963 (void)rhport;
964 USBC_REG_set_bit_b(USBC_BP_POWER_D_RESUME, USBC_REG_PCTL(USBC0_BASE));
965 delay_ms(10);
966 USBC_REG_clear_bit_b(USBC_BP_POWER_D_RESUME, USBC_REG_PCTL(USBC0_BASE));
967}
968
969//--------------------------------------------------------------------+
970// Endpoint API
971//--------------------------------------------------------------------+
972
973#ifndef __ARMCC_VERSION
974#define __clz __builtin_clz
975#endif
976
977// Configure endpoint's registers according to descriptor
978bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
979{
980 (void) rhport;
981
982 uint16_t reg_val;
983
984 const unsigned ep_addr = ep_desc->bEndpointAddress;
985 const unsigned epn = tu_edpt_number(ep_addr);
986 const unsigned dir_in = tu_edpt_dir(ep_addr);
987 const unsigned xfer = ep_desc->bmAttributes.xfer;
988 const unsigned mps = tu_edpt_packet_size(ep_desc);
989
990 TU_ASSERT(epn < TUP_DCD_ENDPOINT_MAX);
991
992 pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1];
993 pipe->buf = NULL;
994 pipe->length = 0;
995 pipe->remaining = 0;
996
998
999 // volatile hw_endpoint_t *regs = edpt_regs(epn - 1);
1001 if (dir_in) {
1002 USBC_Writew(mps, USBC_REG_TXMAXP(USBC0_BASE));
1003
1004 reg_val = (1 << USBC_BP_TXCSR_D_MODE)
1005 | (1 << USBC_BP_TXCSR_D_FLUSH_FIFO)
1006 | (1 << USBC_BP_TXCSR_D_CLEAR_DATA_TOGGLE);
1008 reg_val |= (1 << USBC_BP_TXCSR_D_ISO);
1009 USBC_Writew(reg_val, USBC_REG_TXCSR(USBC0_BASE));
1010
1012 } else {
1013 USBC_Writew(mps, USBC_REG_RXMAXP(USBC0_BASE));
1014
1015 reg_val = (1 << USBC_BP_RXCSR_D_FLUSH_FIFO)
1016 | (1 << USBC_BP_RXCSR_D_CLEAR_DATA_TOGGLE);
1018 reg_val |= (1 << USBC_BP_RXCSR_D_ISO);
1019 USBC_Writew(reg_val, USBC_REG_RXCSR(USBC0_BASE));
1020
1022 }
1023
1024 /* Setup FIFO */
1025 int size_in_log2_minus3 = 28 - TU_MIN(28, __clz((uint32_t)mps));
1026 if ((8u << size_in_log2_minus3) < mps) ++size_in_log2_minus3;
1027 unsigned addr = find_free_memory(size_in_log2_minus3);
1028 TU_ASSERT(addr);
1029
1030 if (dir_in) {
1031 USBC_Writew(addr, USBC_REG_TXFIFOAD(USBC0_BASE));
1032 USBC_Writeb(size_in_log2_minus3, USBC_REG_TXFIFOSZ(USBC0_BASE));
1033 } else {
1034 USBC_Writew(addr, USBC_REG_RXFIFOAD(USBC0_BASE));
1035 USBC_Writeb(size_in_log2_minus3, USBC_REG_RXFIFOSZ(USBC0_BASE));
1036 }
1037
1039
1040 return true;
1041}
1042
1043void dcd_edpt_close_all(uint8_t rhport)
1044{
1045 (void) rhport;
1046 musb_int_mask();
1047 USBC_Writew(1, USBC_REG_INTTxE(USBC0_BASE)); /* Enable only EP0 */
1048 USBC_Writew(0, USBC_REG_INTRxE(USBC0_BASE));
1049 for (unsigned i = 1; i < TUP_DCD_ENDPOINT_MAX; ++i) {
1051 USBC_Writew(0, USBC_REG_TXMAXP(USBC0_BASE));
1052 USBC_Writew((1 << USBC_BP_TXCSR_D_MODE) | (1 << USBC_BP_TXCSR_D_CLEAR_DATA_TOGGLE) | (1 << USBC_BP_TXCSR_D_FLUSH_FIFO),
1053 USBC_REG_TXCSR(USBC0_BASE));
1054
1055 USBC_Writew(0, USBC_REG_RXMAXP(USBC0_BASE));
1056 USBC_Writew((1 << USBC_BP_RXCSR_D_CLEAR_DATA_TOGGLE) | (1 << USBC_BP_RXCSR_D_FLUSH_FIFO),
1057 USBC_REG_RXCSR(USBC0_BASE));
1058
1059 USBC_Writew(0, USBC_REG_TXFIFOAD(USBC0_BASE));
1060 USBC_Writeb(0, USBC_REG_TXFIFOSZ(USBC0_BASE));
1061 USBC_Writew(0, USBC_REG_RXFIFOAD(USBC0_BASE));
1062 USBC_Writeb(0, USBC_REG_RXFIFOSZ(USBC0_BASE));
1063 }
1065}
1066
1067void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
1068{
1069 (void)rhport;
1070 unsigned const epn = tu_edpt_number(ep_addr);
1071 unsigned const dir_in = tu_edpt_dir(ep_addr);
1072
1073 musb_int_mask();
1075 if (dir_in) {
1077 USBC_Writew(0, USBC_REG_TXMAXP(USBC0_BASE));
1078 USBC_Writew((1 << USBC_BP_TXCSR_D_MODE) | (1 << USBC_BP_TXCSR_D_CLEAR_DATA_TOGGLE) | (1 << USBC_BP_TXCSR_D_FLUSH_FIFO),
1079 USBC_REG_TXCSR(USBC0_BASE));
1080
1081 USBC_Writew(0, USBC_REG_TXFIFOAD(USBC0_BASE));
1082 USBC_Writeb(0, USBC_REG_TXFIFOSZ(USBC0_BASE));
1083 } else {
1085 USBC_Writew(0, USBC_REG_RXMAXP(USBC0_BASE));
1086 USBC_Writew((1 << USBC_BP_RXCSR_D_CLEAR_DATA_TOGGLE) | (1 << USBC_BP_RXCSR_D_FLUSH_FIFO),
1087 USBC_REG_RXCSR(USBC0_BASE));
1088
1089 USBC_Writew(0, USBC_REG_RXFIFOAD(USBC0_BASE));
1090 USBC_Writeb(0, USBC_REG_RXFIFOSZ(USBC0_BASE));
1091 }
1093}
1094
1095// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
1096bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
1097{
1098 (void)rhport;
1099 bool ret;
1100 // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
1101 unsigned const epnum = tu_edpt_number(ep_addr);
1102 musb_int_mask();
1103
1104 if (epnum) {
1105 _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] &= ~TU_BIT(epnum - 1);
1106 ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes);
1107 } else {
1108 ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes);
1109 }
1111 return ret;
1112}
1113
1114// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c
1115bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
1116{
1117 (void)rhport;
1118 bool ret;
1119 // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
1120 unsigned const epnum = tu_edpt_number(ep_addr);
1121 TU_ASSERT(epnum);
1122
1123 musb_int_mask();
1124 _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] |= TU_BIT(epnum - 1);
1125 ret = edpt_n_xfer(rhport, ep_addr, (uint8_t*)ff, total_bytes);
1127
1128 return ret;
1129}
1130
1131// Stall endpoint
1132void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
1133{
1134 (void)rhport;
1135 unsigned const epn = tu_edpt_number(ep_addr);
1136 musb_int_mask();
1138 if (0 == epn) {
1139 if (!ep_addr) { /* Ignore EP80 */
1140 _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID;
1141 _dcd.pipe0.buf = NULL;
1143 }
1144 } else {
1145 if (tu_edpt_dir(ep_addr)) { /* IN */
1147 } else { /* OUT */
1148 TU_ASSERT(!__USBC_Dev_Rx_IsReadDataReady(),);
1150 }
1151 }
1153}
1154
1155// clear stall, data toggle is also reset to DATA0
1156void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
1157{
1158 (void)rhport;
1159 unsigned const epn = tu_edpt_number(ep_addr);
1160 musb_int_mask();
1162 if (0 != epn) {
1163 if (tu_edpt_dir(ep_addr)) { /* IN */
1165 } else { /* OUT */
1167 }
1168 }
1170}
1171
1172
1173void dcd_int_handler(uint8_t rhport)
1174{
1175 uint8_t is;
1176 uint16_t txis, rxis;
1177
1178 is = USBC_Readb(USBC_REG_INTUSB(USBC0_BASE)); /* read interrupt status */
1179 txis = USBC_Readw(USBC_REG_INTTx(USBC0_BASE)); /* read interrupt status */
1180 rxis = USBC_Readw(USBC_REG_INTRx(USBC0_BASE)); /* read interrupt status */
1181
1182 is &= USBC_Readb(USBC_REG_INTUSBE(USBC0_BASE)); /* ignore disabled interrupts */
1183 USBC_Writeb(is, USBC_REG_INTUSB(USBC0_BASE)); /* sunxi musb requires a write to interrupt register to clear */
1184 if (is & USBC_INTUSB_DISCONNECT) {
1185 dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
1186 }
1187 if (is & USBC_INTUSB_SOF) {
1188 dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
1189 }
1190 if (is & USBC_INTUSB_RESET) {
1191 /* ep0 FADDR must be 0 when (re)entering peripheral mode */
1194 process_bus_reset(rhport);
1195 }
1196 if (is & USBC_INTUSB_RESUME) {
1197 dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
1198 }
1199 if (is & USBC_INTUSB_SUSPEND) {
1200 dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
1201 }
1202
1203 txis &= USBC_Readw(USBC_REG_INTTxE(USBC0_BASE));
1204 USBC_Writew(txis, USBC_REG_INTTx(USBC0_BASE));
1205 if (txis & USBC_INTTx_FLAG_EP0) {
1206 process_ep0(rhport);
1207 txis &= ~TU_BIT(0);
1208 }
1209 while (txis) {
1210 unsigned const num = __builtin_ctz(txis);
1212 txis &= ~TU_BIT(num);
1213 }
1214
1215 rxis &= USBC_Readw(USBC_REG_INTRxE(USBC0_BASE));
1216 USBC_Writew(rxis, USBC_REG_INTRx(USBC0_BASE));
1217 while (rxis) {
1218 unsigned const num = __builtin_ctz(rxis);
1220 rxis &= ~TU_BIT(num);
1221 }
1222}
1223
1224#endif
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_signal(uint8_t rhport, dcd_eventid_t eid, bool in_isr)
Definition: dcd.h:196
static TU_ATTR_ALWAYS_INLINE void dcd_event_xfer_complete(uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
Definition: dcd.h:222
static TU_ATTR_ALWAYS_INLINE void dcd_event_setup_received(uint8_t rhport, uint8_t const *setup, bool in_isr)
Definition: dcd.h:213
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_reset(uint8_t rhport, tusb_speed_t speed, bool in_isr)
Definition: dcd.h:204
static struct @612 data
xfer_td_t xfer[EP_CBI_COUNT+1][2]
Definition: dcd_nrf5x.c:119
uint16_t total_bytes
Definition: dcd_nuc505.c:113
uint8_t dev_addr
Definition: dcd_pic32mz.c:81
static TU_ATTR_ALWAYS_INLINE unsigned __builtin_ctz(unsigned int value)
Definition: dcd_rusb2.c:923
void USBC_SelectBus(u32 io_type, u32 ep_type, u32 ep_index)
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes)
static void __USBC_Dev_Rx_SendStall(void)
static void __USBC_Dev_ep0_ReadDataHalf(void)
struct TU_ATTR_PACKED pipe_state_t
static void process_setup_packet(uint8_t rhport)
static void USBC_HardwareReset(void)
static void musb_int_mask(void)
static void __USBC_Dev_ep0_SendStall(void)
static CFG_TUD_MEM_ALIGN dcd_data_t _dcd
static void __USBC_Dev_ep0_ReadDataComplete(void)
static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr)
static void print_block_list(free_block_t const *blk, unsigned num)
static void pipe_write_packet(void *buff, volatile void *fifo, unsigned cnt)
static void process_bus_reset(uint8_t rhport)
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
static int update_free_block_list(free_block_t *blks, unsigned num, uint_fast16_t addr, uint_fast16_t size)
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
static u8 USBC_GetActiveEp(void)
static void __USBC_Dev_Tx_WriteDataComplete(void)
static void __USBC_Dev_ep0_WriteDataComplete(void)
static unsigned int USBC_WakeUp_ClearChangeDetect(unsigned int reg_val)
static void USBC_INT_EnableTxEp(u8 ep_index)
static free_block_t * find_containing_block(free_block_t *beg, free_block_t *end, uint_fast16_t addr)
static bool handle_xfer_in(uint_fast8_t ep_addr)
void dcd_int_handler(uint8_t rhport)
void dcd_disconnect(uint8_t rhport)
static void __USBC_Dev_Rx_ClearStall(void)
static void USBC_ConfigFIFO_Base(void)
static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
static void USBC_Dev_SetAddress(u8 address)
static bool handle_xfer_out(uint_fast8_t ep_addr)
static u32 __USBC_Dev_Tx_IsEpStall(void)
static u32 __USBC_Dev_Rx_IsEpStall(void)
void dcd_edpt_close_all(uint8_t rhport)
static void usb_isr_handler(void)
void dcd_int_disable(uint8_t rhport)
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc)
static void process_ep0(uint8_t rhport)
static void musb_int_unmask(void)
static void __USBC_Dev_ep0_ClearStall(void)
static void USBC_Dev_Ctrl_ClearSetupEnd(void)
static void USBC_INT_EnableRxEp(u8 ep_index)
uint8_t u8
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
static void __USBC_Dev_ep0_WriteDataHalf(void)
static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
static void USBC_EnableDpDmPullUp(void)
static void pipe_read_packet(void *buff, volatile void *fifo, unsigned cnt)
static void USBC_SelectActiveEp(u8 ep_index)
static u32 __USBC_Dev_Rx_IsReadDataReady(void)
static tusb_speed_t USBC_Dev_QueryTransferMode(void)
void dcd_connect(uint8_t rhport)
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3)
static void delay_ms(uint32_t ms)
static void USBC_PhyConfig(void)
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
uint16_t u16
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
static void USBC_INT_DisableRxEp(u8 ep_index)
static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir)
static void USBC_INT_DisableTxEp(u8 ep_index)
static void usb_phy_write(int addr, int data, int len)
static void USBC_ForceVbusValidToHigh(void)
static void USBC_ForceIdToHigh(void)
static void __USBC_Dev_Rx_ReadDataComplete(void)
static void __USBC_Dev_Tx_ClearStall(void)
void dcd_int_enable(uint8_t rhport)
void dcd_remote_wakeup(uint8_t rhport)
static unsigned free_block_size(free_block_t const *blk)
uint32_t board_millis(void)
static void __USBC_Dev_Tx_SendStall(void)
void dcd_sof_enable(uint8_t rhport, bool en)
uint32_t u32
uint8_t const * buffer
Definition: midi_device.h:100
TU_ATTR_WEAK void osal_task_delay(uint32_t msec)
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
Definition: audio.h:672
uint16_t length
Definition: dcd_ci_fs.c:94
volatile uint16_t
Definition: hcd_rusb2.c:58
void * buf
Definition: dcd_musb.c:69
uint16_t remaining
Definition: dcd_ci_fs.c:95
uint8_t bEndpointAddress
Definition: video.h:306
uint16_t remaining_ctrl
Definition: dcd_musb.c:77
uint16_t pipe_buf_is_fifo[2]
Definition: dcd_musb.c:81
pipe_state_t pipe0
Definition: dcd_musb.c:79
uint8_t setup_packet[8]
Definition: dcd_ci_fs.c:110
int8_t status_out
Definition: dcd_musb.c:78
CFG_TUD_MEM_ALIGN tusb_control_request_t setup_packet
pipe_state_t pipe[2][TUP_DCD_ENDPOINT_MAX-1]
Definition: dcd_musb.c:80
uint_fast16_t end
Definition: hcd_musb.c:59
uint_fast16_t beg
Definition: hcd_musb.c:58
uint16_t length
Definition: dcd_rusb2.c:62
void * buf
Definition: dcd_rusb2.c:61
uint16_t remaining
Definition: dcd_rusb2.c:63
void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info)
Get linear write info.
Definition: tusb_fifo.c:1057
void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n)
Advance write pointer - intended to be used in combination with DMA. It is possible to fill the FIFO ...
Definition: tusb_fifo.c:948
void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n)
Advance read pointer - intended to be used in combination with DMA. It is possible to read from the F...
Definition: tusb_fifo.c:969
void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info)
Get read info.
Definition: tusb_fifo.c:989
@ TUSB_DIR_IN
Definition: tusb_types.h:67
@ TUSB_DIR_OUT
Definition: tusb_types.h:66
@ TUSB_DIR_IN_MASK
Definition: tusb_types.h:69
tusb_speed_t
defined base on EHCI specs value for Endpoint Speed
Definition: tusb_types.h:49
@ TUSB_SPEED_FULL
Definition: tusb_types.h:50
@ TUSB_SPEED_HIGH
Definition: tusb_types.h:52
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_number(uint8_t addr)
Definition: tusb_types.h:507
@ XFER_RESULT_SUCCESS
Definition: tusb_types.h:237
static TU_ATTR_ALWAYS_INLINE uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const *desc_ep)
Definition: tusb_types.h:515
@ TUSB_XFER_ISOCHRONOUS
Definition: tusb_types.h:60
TU_ATTR_PACKED_END TU_ATTR_BIT_FIELD_ORDER_END static TU_ATTR_ALWAYS_INLINE tusb_dir_t tu_edpt_dir(uint8_t addr)
Definition: tusb_types.h:502
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_addr(uint8_t num, uint8_t dir)
Definition: tusb_types.h:511