10 #define QM_USB_GRSTCTL_AHB_IDLE BIT(31)
11 #define QM_USB_GRSTCTL_TX_FNUM_OFFSET (6)
12 #define QM_USB_GRSTCTL_TX_FFLSH BIT(5)
13 #define QM_USB_GRSTCTL_C_SFT_RST BIT(0)
14 #define QM_USB_GAHBCFG_DMA_EN BIT(5)
15 #define QM_USB_GAHBCFG_GLB_INTR_MASK BIT(0)
16 #define QM_USB_DCTL_SFT_DISCON BIT(1)
17 #define QM_USB_GINTSTS_WK_UP_INT BIT(31)
18 #define QM_USB_GINTSTS_OEP_INT BIT(19)
19 #define QM_USB_GINTSTS_IEP_INT BIT(18)
20 #define QM_USB_GINTSTS_ENUM_DONE BIT(13)
21 #define QM_USB_GINTSTS_USB_RST BIT(12)
22 #define QM_USB_GINTSTS_USB_SUSP BIT(11)
23 #define QM_USB_GINTSTS_RX_FLVL BIT(4)
24 #define QM_USB_GINTSTS_OTG_INT BIT(2)
25 #define QM_USB_DCFG_DEV_SPD_LS (0x2)
26 #define QM_USB_DCFG_DEV_SPD_FS (0x3)
27 #define QM_USB_DCFG_DEV_ADDR_MASK (0x7F << 4)
28 #define QM_USB_DCFG_DEV_ADDR_OFFSET (4)
29 #define QM_USB_DAINT_IN_EP_INT(ep) (1 << (ep))
30 #define QM_USB_DAINT_OUT_EP_INT(ep) (0x10000 << (ep))
31 #define QM_USB_DEPCTL_EP_ENA BIT(31)
32 #define QM_USB_DEPCTL_EP_DIS BIT(30)
33 #define QM_USB_DEPCTL_SETDOPID BIT(28)
34 #define QM_USB_DEPCTL_SNAK BIT(27)
35 #define QM_USB_DEPCTL_CNAK BIT(26)
36 #define QM_USB_DEPCTL_STALL BIT(21)
37 #define QM_USB_DEPCTL_EP_TYPE_MASK (0x3 << 18)
38 #define QM_USB_DEPCTL_EP_TYPE_OFFSET (18)
39 #define QM_USB_DEPCTL_EP_TYPE_CONTROL (0)
40 #define QM_USB_DEPCTL_EP_TYPE_ISO (0x1)
41 #define QM_USB_DEPCTL_EP_TYPE_BULK (0x2)
42 #define QM_USB_DEPCTL_EP_TYPE_INTERRUPT (0x3)
43 #define QM_USB_DEPCTL_USB_ACT_EP BIT(15)
44 #define QM_USB_DEPCTL0_MSP_MASK (0x3)
45 #define QM_USB_DEPCTL0_MSP_8 (0x3)
46 #define QM_USB_DEPCTL0_MSP_16 (0x2)
47 #define QM_USB_DEPCTL0_MSP_32 (0x1)
48 #define QM_USB_DEPCTL0_MSP_64 (0)
49 #define QM_USB_DEPCTLn_MSP_MASK (0x3FF)
50 #define QM_USB_DEPCTL_MSP_OFFSET (0)
51 #define QM_USB_DOEPTSIZ_SUP_CNT_MASK (0x3 << 29)
52 #define QM_USB_DOEPTSIZ_SUP_CNT_OFFSET (29)
53 #define QM_USB_DOEPTSIZ0_PKT_CNT_MASK (0x1 << 19)
54 #define QM_USB_DOEPTSIZn_PKT_CNT_MASK (0x3FF << 19)
55 #define QM_USB_DIEPTSIZ0_PKT_CNT_MASK (0x3 << 19)
56 #define QM_USB_DIEPTSIZn_PKT_CNT_MASK (0x3FF << 19)
57 #define QM_USB_DEPTSIZ_PKT_CNT_OFFSET (19)
58 #define QM_USB_DEPTSIZ0_XFER_SIZE_MASK (0x7F)
59 #define QM_USB_DEPTSIZn_XFER_SIZE_MASK (0x7FFFF)
60 #define QM_USB_DEPTSIZ_XFER_SIZE_OFFSET (0)
61 #define QM_USB_DIEPINT_XFER_COMPL BIT(0)
62 #define QM_USB_DIEPINT_TX_FEMP BIT(7)
63 #define QM_USB_DIEPINT_XFER_COMPL BIT(0)
64 #define QM_USB_DOEPINT_SET_UP BIT(3)
65 #define QM_USB_DOEPINT_XFER_COMPL BIT(0)
66 #define QM_USB_DSTS_ENUM_SPD_MASK (0x3)
67 #define QM_USB_DSTS_ENUM_SPD_OFFSET (1)
68 #define QM_USB_DSTS_ENUM_LS (2)
69 #define QM_USB_DSTS_ENUM_FS (3)
70 #define QM_USB_GRXSTSR_EP_NUM_MASK (0xF << 0)
71 #define QM_USB_GRXSTSR_PKT_STS_MASK (0xF << 17)
72 #define QM_USB_GRXSTSR_PKT_STS_OFFSET (17)
73 #define QM_USB_GRXSTSR_PKT_CNT_MASK (0x7FF << 4)
74 #define QM_USB_GRXSTSR_PKT_CNT_OFFSET (4)
75 #define QM_USB_GRXSTSR_PKT_STS_OUT_DATA (2)
76 #define QM_USB_GRXSTSR_PKT_STS_OUT_DATA_DONE (3)
77 #define QM_USB_GRXSTSR_PKT_STS_SETUP_DONE (4)
78 #define QM_USB_GRXSTSR_PKT_STS_SETUP (6)
79 #define QM_USB_DTXFSTS_TXF_SPC_AVAIL_MASK (0xFFFF)
81 #define QM_USB_CORE_RST_TIMEOUT_US (10000)
82 #define QM_USB_PLL_TIMEOUT_US (100)
85 #define IS_IN_EP(ep) (ep < QM_USB_IN_EP_NUM)
88 #define QM_USB_SUP_CNT (1)
91 #define QM_USB_EP_FIFO(ep) (ep)
93 #define QM_USB_EP_FIFO(ep) (*(uint32_t *)(QM_USB_0_BASE + 0x1000 * (ep + 1)))
110 usb_ep_priv_t ep_ctrl[QM_USB_IN_EP_NUM + QM_USB_OUT_EP_NUM];
115 static usb_priv_t usb_ctrl[QM_USB_NUM];
117 static bool usb_dc_ep_is_valid(
const qm_usb_ep_idx_t ep)
119 return (ep < QM_USB_IN_EP_NUM + QM_USB_OUT_EP_NUM);
122 static int usb_dc_reset(
const qm_usb_t usb)
127 while (!(QM_USB[usb].grstctl & QM_USB_GRSTCTL_AHB_IDLE)) {
129 if (++cnt > QM_USB_CORE_RST_TIMEOUT_US) {
136 QM_USB[usb].grstctl |= QM_USB_GRSTCTL_C_SFT_RST;
138 if (++cnt > QM_USB_CORE_RST_TIMEOUT_US) {
142 }
while (QM_USB[usb].grstctl & QM_USB_GRSTCTL_C_SFT_RST);
150 static void usb_dc_prep_rx(
const qm_usb_t usb,
const qm_usb_ep_idx_t ep,
154 const uint8_t ep_idx = ep - QM_USB_IN_EP_NUM;
155 const uint16_t ep_mps =
156 usb_ctrl[usb].ep_ctrl[ep].ep_config->max_packet_size;
162 QM_USB[usb].out_ep_reg[ep_idx].doeptsiz =
163 (QM_USB_SUP_CNT << QM_USB_DOEPTSIZ_SUP_CNT_OFFSET) |
164 (1 << QM_USB_DEPTSIZ_PKT_CNT_OFFSET) | ep_mps;
168 QM_USB[usb].out_ep_reg[ep_idx].doepctl |= QM_USB_DEPCTL_CNAK;
170 QM_USB[usb].out_ep_reg[ep_idx].doepctl |= QM_USB_DEPCTL_EP_ENA;
173 static int usb_dc_tx(
const qm_usb_t usb, uint8_t ep,
const uint8_t *
const data,
176 uint32_t max_xfer_size, max_pkt_cnt, pkt_cnt, avail_space;
177 const uint16_t ep_mps =
178 usb_ctrl[usb].ep_ctrl[ep].ep_config->max_packet_size;
182 avail_space = QM_USB[usb].in_ep_reg[ep].dtxfsts &
183 QM_USB_DTXFSTS_TXF_SPC_AVAIL_MASK;
189 if (data_len > avail_space)
190 data_len = avail_space;
194 if (ep == QM_USB_IN_EP_0) {
195 max_pkt_cnt = QM_USB_DIEPTSIZ0_PKT_CNT_MASK >>
196 QM_USB_DEPTSIZ_PKT_CNT_OFFSET;
197 max_xfer_size = QM_USB_DEPTSIZ0_XFER_SIZE_MASK >>
198 QM_USB_DEPTSIZ_XFER_SIZE_OFFSET;
200 max_pkt_cnt = QM_USB_DIEPTSIZn_PKT_CNT_MASK >>
201 QM_USB_DEPTSIZ_PKT_CNT_OFFSET;
202 max_xfer_size = QM_USB_DEPTSIZn_XFER_SIZE_MASK >>
203 QM_USB_DEPTSIZ_XFER_SIZE_OFFSET;
207 if (data_len > max_xfer_size) {
208 data_len = max_xfer_size;
217 pkt_cnt = (data_len + ep_mps - 1) / ep_mps;
219 if (pkt_cnt > max_pkt_cnt) {
220 pkt_cnt = max_pkt_cnt;
221 data_len = pkt_cnt * ep_mps;
229 QM_USB[usb].in_ep_reg[ep].dieptsiz =
230 (pkt_cnt << QM_USB_DEPTSIZ_PKT_CNT_OFFSET) | data_len;
233 QM_USB[usb].in_ep_reg[ep].diepctl |= QM_USB_DEPCTL_CNAK;
234 QM_USB[usb].in_ep_reg[ep].diepctl |= QM_USB_DEPCTL_EP_ENA;
237 for (i = 0; i < data_len; i += 4)
238 QM_USB_EP_FIFO(ep) = *(uint32_t *)(data + i);
243 static void usb_dc_handle_reset(
const qm_usb_t usb)
245 if (usb_ctrl[usb].status_callback) {
246 usb_ctrl[usb].status_callback(usb_ctrl[usb].user_data, 0,
251 QM_USB[usb].dcfg &= ~QM_USB_DCFG_DEV_ADDR_MASK;
254 QM_USB[usb].doepmsk = 0;
255 QM_USB[usb].gintmsk |= QM_USB_GINTSTS_RX_FLVL;
256 QM_USB[usb].diepmsk |= QM_USB_DIEPINT_XFER_COMPL;
259 static void usb_dc_handle_enum_done(
const qm_usb_t usb)
261 if (usb_ctrl[usb].status_callback) {
262 usb_ctrl[usb].status_callback(usb_ctrl[usb].user_data, 0,
267 static __inline__
void handle_rx_fifo(
const qm_usb_t usb)
269 const uint32_t grxstsp = QM_USB[usb].grxstsp;
271 const uint8_t ep_idx =
272 (grxstsp & QM_USB_GRXSTSR_EP_NUM_MASK) + QM_USB_IN_EP_NUM;
273 const uint32_t status = (grxstsp & QM_USB_GRXSTSR_PKT_STS_MASK) >>
274 QM_USB_GRXSTSR_PKT_STS_OFFSET;
275 const uint32_t xfer_size = (grxstsp & QM_USB_GRXSTSR_PKT_CNT_MASK) >>
276 QM_USB_GRXSTSR_PKT_CNT_OFFSET;
278 usb_ctrl[usb].ep_ctrl[ep_idx].ep_config;
280 void (*ep_cb)(
void *data,
int error, qm_usb_ep_idx_t ep,
283 usb_ctrl[usb].ep_ctrl[ep_idx].data_len = xfer_size;
287 (status == QM_USB_GRXSTSR_PKT_STS_SETUP)
295 static __inline__
void handle_in_ep_intr(
const qm_usb_t usb)
297 uint32_t ep_intr_sts;
299 void (*ep_cb)(
void *data,
int error, qm_usb_ep_idx_t ep,
302 for (ep_idx = 0; ep_idx < QM_USB_IN_EP_NUM; ep_idx++) {
303 if (QM_USB[usb].daint & QM_USB_DAINT_IN_EP_INT(ep_idx)) {
305 ep_intr_sts = QM_USB[usb].in_ep_reg[ep_idx].diepint &
309 QM_USB[usb].in_ep_reg[ep_idx].diepint = ep_intr_sts;
312 usb_ctrl[usb].ep_ctrl[ep_idx].ep_config->callback;
314 if (ep_intr_sts & QM_USB_DIEPINT_XFER_COMPL && ep_cb) {
317 .ep_config->callback_data,
324 QM_USB[usb].gintsts = QM_USB_GINTSTS_IEP_INT;
327 static __inline__
void handle_out_ep_intr(
const qm_usb_t usb)
329 uint32_t ep_intr_sts;
334 for (ep_idx = 0; ep_idx < QM_USB_OUT_EP_NUM; ep_idx++) {
335 if (QM_USB[usb].daint & QM_USB_DAINT_OUT_EP_INT(ep_idx)) {
337 ep_intr_sts = QM_USB[usb].out_ep_reg[ep_idx].doepint &
341 QM_USB[usb].out_ep_reg[ep_idx].doepint = ep_intr_sts;
346 QM_USB[usb].gintsts = QM_USB_GINTSTS_OEP_INT;
350 static void usb_dc_isr_handler(
const qm_usb_t usb)
355 while ((int_status = (QM_USB[usb].gintsts & QM_USB[usb].gintmsk))) {
357 if (int_status & QM_USB_GINTSTS_USB_RST) {
359 QM_USB[usb].gintsts = QM_USB_GINTSTS_USB_RST;
362 usb_dc_handle_reset(usb);
365 if (int_status & QM_USB_GINTSTS_ENUM_DONE) {
367 QM_USB[usb].gintsts = QM_USB_GINTSTS_ENUM_DONE;
370 usb_dc_handle_enum_done(usb);
373 if (int_status & QM_USB_GINTSTS_USB_SUSP) {
375 QM_USB[usb].gintsts = QM_USB_GINTSTS_USB_SUSP;
377 if (usb_ctrl[usb].status_callback) {
378 usb_ctrl[usb].status_callback(
383 if (int_status & QM_USB_GINTSTS_WK_UP_INT) {
385 QM_USB[usb].gintsts = QM_USB_GINTSTS_WK_UP_INT;
387 if (usb_ctrl[usb].status_callback) {
388 usb_ctrl[usb].status_callback(
393 if (int_status & QM_USB_GINTSTS_RX_FLVL) {
398 if (int_status & QM_USB_GINTSTS_IEP_INT) {
400 handle_in_ep_intr(usb);
403 if (int_status & QM_USB_GINTSTS_OEP_INT) {
405 handle_out_ep_intr(usb);
412 usb_dc_isr_handler(QM_USB_0);
413 QM_ISR_EOI(QM_IRQ_USB_0_INT_VECTOR);
418 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
422 if (usb_ctrl[usb].attached) {
428 const int ret = usb_dc_reset(usb);
433 QM_USB[usb].dcfg |= QM_USB_DCFG_DEV_SPD_FS;
437 for (ep = 0; ep < QM_USB_OUT_EP_NUM; ep++) {
438 QM_USB[usb].out_ep_reg[ep].doepctl = QM_USB_DEPCTL_SNAK;
442 QM_USB[usb].gintmsk =
443 QM_USB_GINTSTS_OEP_INT | QM_USB_GINTSTS_IEP_INT |
444 QM_USB_GINTSTS_ENUM_DONE | QM_USB_GINTSTS_USB_RST |
445 QM_USB_GINTSTS_WK_UP_INT | QM_USB_GINTSTS_USB_SUSP;
448 QM_USB[usb].gahbcfg |= QM_USB_GAHBCFG_GLB_INTR_MASK;
451 QM_USB[usb].dctl &= ~QM_USB_DCTL_SFT_DISCON;
453 usb_ctrl[usb].attached =
true;
460 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
462 if (!usb_ctrl[usb].attached) {
469 QM_USB[usb].dctl |= QM_USB_DCTL_SFT_DISCON;
471 usb_ctrl[usb].attached =
false;
478 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
479 return usb_dc_reset(usb);
484 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
486 (QM_USB_DCFG_DEV_ADDR_MASK >> QM_USB_DCFG_DEV_ADDR_OFFSET),
489 QM_USB[usb].dcfg &= ~QM_USB_DCFG_DEV_ADDR_MASK;
490 QM_USB[usb].dcfg |= addr << QM_USB_DCFG_DEV_ADDR_OFFSET;
498 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
499 QM_CHECK(usb_ctrl[usb].attached, -EINVAL);
500 QM_CHECK(ep_cfg, -EINVAL);
501 if (!usb_dc_ep_is_valid(ep_cfg->ep)) {
505 volatile uint32_t *p_depctl;
506 const uint8_t ep_idx = ep_cfg->ep < QM_USB_IN_EP_NUM
508 : ep_cfg->ep - QM_USB_IN_EP_NUM;
510 if (!IS_IN_EP(ep_cfg->ep)) {
511 p_depctl = &QM_USB[usb].out_ep_reg[ep_idx].doepctl;
513 p_depctl = &QM_USB[usb].in_ep_reg[ep_idx].diepctl;
516 usb_ctrl[usb].ep_ctrl[ep_cfg->ep].ep_config = ep_cfg;
520 *p_depctl &= ~QM_USB_DEPCTL0_MSP_MASK;
523 *p_depctl |= QM_USB_DEPCTL0_MSP_8
524 << QM_USB_DEPCTL_MSP_OFFSET;
527 *p_depctl |= QM_USB_DEPCTL0_MSP_16
528 << QM_USB_DEPCTL_MSP_OFFSET;
531 *p_depctl |= QM_USB_DEPCTL0_MSP_32
532 << QM_USB_DEPCTL_MSP_OFFSET;
535 *p_depctl |= QM_USB_DEPCTL0_MSP_64
536 << QM_USB_DEPCTL_MSP_OFFSET;
545 (QM_USB_DEPCTLn_MSP_MASK >> QM_USB_DEPCTL_MSP_OFFSET))
548 *p_depctl &= ~QM_USB_DEPCTLn_MSP_MASK;
550 << QM_USB_DEPCTL_MSP_OFFSET;
553 *p_depctl &= ~QM_USB_DEPCTL_EP_TYPE_MASK;
554 switch (ep_cfg->
type) {
556 *p_depctl |= QM_USB_DEPCTL_EP_TYPE_CONTROL
557 << QM_USB_DEPCTL_EP_TYPE_OFFSET;
560 *p_depctl |= QM_USB_DEPCTL_EP_TYPE_BULK
561 << QM_USB_DEPCTL_EP_TYPE_OFFSET;
564 *p_depctl |= QM_USB_DEPCTL_EP_TYPE_INTERRUPT
565 << QM_USB_DEPCTL_EP_TYPE_OFFSET;
572 *p_depctl |= QM_USB_DEPCTL_SETDOPID;
579 const bool is_stalled)
581 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
582 QM_CHECK(usb_ctrl[usb].attached, -EINVAL);
583 if (!usb_dc_ep_is_valid(ep)) {
587 const uint8_t ep_idx = IS_IN_EP(ep) ? ep : ep - QM_USB_IN_EP_NUM;
589 if (!is_stalled && !ep_idx) {
595 uint32_t reg = QM_USB[usb].in_ep_reg[ep_idx].diepctl;
596 reg ^= (-is_stalled ^ reg) & QM_USB_DEPCTL_STALL;
597 QM_USB[usb].in_ep_reg[ep_idx].diepctl = reg;
602 uint32_t reg = QM_USB[usb].out_ep_reg[ep_idx].doepctl;
603 reg ^= (-is_stalled ^ reg) & QM_USB_DEPCTL_STALL;
604 QM_USB[usb].out_ep_reg[ep_idx].doepctl = reg;
611 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
612 QM_CHECK(usb_ctrl[usb].attached, -EINVAL);
613 if (!usb_dc_ep_is_valid(ep)) {
617 const uint8_t ep_idx = IS_IN_EP(ep) ? ep : ep - QM_USB_IN_EP_NUM;
618 volatile uint32_t *p_depctl;
626 p_depctl = &QM_USB[usb].out_ep_reg[ep_idx].doepctl;
628 p_depctl = &QM_USB[usb].in_ep_reg[ep_idx].diepctl;
632 *p_depctl |= QM_USB_DEPCTL_STALL;
633 if (*p_depctl & QM_USB_DEPCTL_EP_ENA) {
634 *p_depctl |= QM_USB_DEPCTL_EP_DIS;
643 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
644 QM_CHECK(usb_ctrl[usb].attached, -EINVAL);
645 QM_CHECK(stalled, -EINVAL);
646 if (!usb_dc_ep_is_valid(ep)) {
650 volatile uint32_t *p_depctl;
653 p_depctl = &QM_USB[usb].in_ep_reg[ep].diepctl;
655 const uint8_t ep_idx = ep - QM_USB_IN_EP_NUM;
656 p_depctl = &QM_USB[usb].out_ep_reg[ep_idx].doepctl;
659 *stalled = !!(*p_depctl & QM_USB_DEPCTL_STALL);
666 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
667 QM_CHECK(usb_ctrl[usb].attached, -EINVAL);
668 if (!usb_dc_ep_is_valid(ep)) {
672 usb_ctrl[usb].ep_ctrl[ep].enabled =
true;
676 QM_USB[usb].daintmsk |= QM_USB_DAINT_IN_EP_INT(ep);
679 QM_USB[usb].in_ep_reg[ep].diepctl |= QM_USB_DEPCTL_USB_ACT_EP;
681 const uint8_t ep_idx = ep - QM_USB_IN_EP_NUM;
684 QM_USB[usb].daintmsk |= QM_USB_DAINT_OUT_EP_INT(ep_idx);
687 QM_USB[usb].out_ep_reg[ep_idx].doepctl |=
688 QM_USB_DEPCTL_USB_ACT_EP;
691 usb_dc_prep_rx(usb, ep, 0);
699 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
700 if (!usb_dc_ep_is_valid(ep)) {
706 const uint8_t ep_idx = ep - QM_USB_IN_EP_NUM;
708 QM_USB[usb].daintmsk &= ~QM_USB_DAINT_OUT_EP_INT(ep_idx);
709 QM_USB[usb].doepmsk &= ~QM_USB_DOEPINT_SET_UP;
710 QM_USB[usb].out_ep_reg[ep_idx].doepctl &=
711 ~(QM_USB_DEPCTL_USB_ACT_EP | QM_USB_DEPCTL_EP_ENA |
714 QM_USB[usb].daintmsk &= ~QM_USB_DAINT_IN_EP_INT(ep);
715 QM_USB[usb].diepmsk &= ~QM_USB_DIEPINT_XFER_COMPL;
716 QM_USB[usb].gintmsk &= ~QM_USB_GINTSTS_RX_FLVL;
717 QM_USB[usb].in_ep_reg[ep].diepctl &=
718 ~(QM_USB_DEPCTL_USB_ACT_EP | QM_USB_DEPCTL_EP_ENA |
722 usb_ctrl[usb].ep_ctrl[ep].enabled =
false;
729 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
730 QM_CHECK(usb_ctrl[usb].attached, -EINVAL);
731 if (!usb_dc_ep_is_valid(ep)) {
747 QM_USB[usb].grstctl |= ep << QM_USB_GRSTCTL_TX_FNUM_OFFSET;
748 QM_USB[usb].grstctl |= QM_USB_GRSTCTL_TX_FFLSH;
752 if (++cnt > QM_USB_CORE_RST_TIMEOUT_US) {
756 }
while (QM_USB[usb].grstctl & QM_USB_GRSTCTL_TX_FFLSH);
762 const uint8_t *
const data,
const uint32_t data_len,
763 uint32_t *
const ret_bytes)
765 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
766 QM_CHECK(usb_ctrl[usb].attached, -EINVAL);
767 if (!usb_dc_ep_is_valid(ep)) {
775 if (!usb_ctrl[usb].ep_ctrl[ep].enabled) {
779 const int ret = usb_dc_tx(usb, ep, data, data_len);
792 uint8_t *
const data,
const uint32_t max_data_len,
793 uint32_t *
const read_bytes)
795 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
796 QM_CHECK(usb_ctrl[usb].attached, -EINVAL);
797 QM_CHECK(data, -EINVAL);
798 if (!usb_dc_ep_is_valid(ep)) {
805 uint32_t i, j, data_len, bytes_to_copy;
808 if (!usb_ctrl[usb].ep_ctrl[ep].enabled) {
812 data_len = usb_ctrl[usb].ep_ctrl[ep].data_len;
814 if (data_len > max_data_len) {
815 bytes_to_copy = max_data_len;
817 bytes_to_copy = data_len;
820 const uint8_t ep_idx = ep - QM_USB_IN_EP_NUM;
822 for (i = 0; i < (bytes_to_copy & ~0x3); i += 4) {
823 *(uint32_t *)(data + i) = QM_USB_EP_FIFO(ep_idx);
825 if (bytes_to_copy & 0x3) {
827 uint32_t last_dw = QM_USB_EP_FIFO(ep_idx);
829 for (j = 0; j < (bytes_to_copy & 0x3); j++) {
830 *(data + i + j) = (last_dw >> (8 * j)) & 0xFF;
834 usb_ctrl[usb].ep_ctrl[ep].data_len -= bytes_to_copy;
837 *read_bytes = bytes_to_copy;
841 if (!usb_ctrl[usb].ep_ctrl[ep].data_len) {
842 usb_dc_prep_rx(usb, ep, 0);
851 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
853 usb_ctrl[usb].status_callback = cb;
858 uint32_t *
const read_bytes)
860 QM_CHECK(usb < QM_USB_NUM, -EINVAL);
861 QM_CHECK(usb_ctrl[usb].attached, -EINVAL);
862 QM_CHECK(read_bytes, -EINVAL);
863 if (!usb_dc_ep_is_valid(ep)) {
871 if (!usb_ctrl[usb].ep_ctrl[ep].enabled) {
875 *read_bytes = usb_ctrl[usb].ep_ctrl[ep].data_len;
int qm_usb_ep_enable(const qm_usb_t usb, const qm_usb_ep_idx_t ep)
Enable the selected endpoint.
int clk_sys_usb_disable(void)
Disable the USB Clock mode.
USB connection resumed by the HOST.
int qm_usb_ep_flush(const qm_usb_t usb, const qm_usb_ep_idx_t ep)
Flush the selected IN endpoint TX FIFO.
uint16_t max_packet_size
Endpoint max packet size.
void * callback_data
Callback user data.
Out transaction on this EP.
QM_ISR_DECLARE(qm_usb_0_isr)
ISR for USB 0 interrupt.
int qm_usb_ep_is_stalled(const qm_usb_t usb, const qm_usb_ep_idx_t ep, bool *stalled)
Check stall condition for the selected endpoint.
int qm_usb_ep_get_bytes_read(const qm_usb_t usb, const qm_usb_ep_idx_t ep, uint32_t *const read_bytes)
Check how many bytes are available on OUT endpoint.
void(* qm_usb_status_callback_t)(void *data, int error, qm_usb_status_t status)
Callback function signature for the device status.
int qm_usb_ep_halt(const qm_usb_t usb, const qm_usb_ep_idx_t ep)
Halt the selected endpoint.
int qm_usb_ep_set_config(const qm_usb_t usb, const qm_usb_ep_config_t *const ep_cfg)
Configure endpoint.
USB Endpoint Configuration.
int qm_usb_reset(const qm_usb_t usb)
Reset the USB device controller back to it's initial state.
void clk_sys_udelay(uint32_t microseconds)
Idle loop the processor for at least the value given in microseconds.
void(* callback)(void *data, int error, qm_usb_ep_idx_t ep, qm_usb_ep_status_t status)
Callback for the USB Endpoint status.
USB connection suspended by the HOST.
int qm_usb_ep_read(const qm_usb_t usb, const qm_usb_ep_idx_t ep, uint8_t *const data, const uint32_t max_data_len, uint32_t *const read_bytes)
Read data from OUT endpoint.
USB connection ready and enumeration done.
int qm_usb_set_status_callback(const qm_usb_t usb, const qm_usb_status_callback_t cb)
Set USB device controller status callback.
int qm_usb_attach(const qm_usb_t usb)
Attach the USB device.
qm_usb_ep_status_t
USB Endpoint Callback Status Codes.
int qm_usb_ep_set_stall_state(const qm_usb_t usb, const qm_usb_ep_idx_t ep, const bool is_stalled)
Set / Clear stall condition for the selected endpoint.
qm_usb_t
Number of USB controllers.
int qm_usb_ep_disable(const qm_usb_t usb, const qm_usb_ep_idx_t ep)
Disable the selected endpoint.
qm_usb_ep_type_t type
Endpoint type.
int qm_usb_set_address(const qm_usb_t usb, const uint8_t addr)
Set USB device address.
int clk_sys_usb_enable(void)
Enable the USB Clock mode.
int qm_usb_ep_write(const qm_usb_t usb, const qm_usb_ep_idx_t ep, const uint8_t *const data, const uint32_t data_len, uint32_t *const ret_bytes)
Write data to the specified IN endpoint.
int qm_usb_detach(const qm_usb_t usb)
Detach the USB device.
In transaction on this EP.
qm_usb_status_t
USB Driver Status Codes.