Skip to content

Commit cc346dc

Browse files
Victor Brzeskivbrzeski
authored andcommitted
dwc2: support ISO transfer scheduling
1 parent f270e28 commit cc346dc

File tree

1 file changed

+74
-12
lines changed

1 file changed

+74
-12
lines changed

drivers/usb/udc/udc_dwc2.c

Lines changed: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ enum dwc2_drv_event_type {
6262
*/
6363
#define UDC_DWC2_FIFO0_DEPTH (2 * 16U)
6464

65+
#define UDC_DWC2_TARGET_FRAME_INITIAL UINT16_MAX
66+
6567
/* Get Data FIFO access register */
6668
#define UDC_DWC2_EP_FIFO(base, idx) ((mem_addr_t)base + 0x1000 * (idx + 1))
6769

@@ -138,6 +140,8 @@ struct udc_dwc2_data {
138140
/* Number of OUT endpoints including control endpoint */
139141
uint8_t outeps;
140142
uint8_t setup[8];
143+
/* Target frame numbers for isochronous endpoints */
144+
uint16_t target_frames[32];
141145
};
142146

143147
#if defined(CONFIG_PINCTRL)
@@ -381,6 +385,21 @@ static bool dwc2_ep_is_periodic(struct udc_ep_config *const cfg)
381385
}
382386
}
383387

388+
static void dwc2_ep_next_target_frame(const struct device *dev, struct udc_ep_config *const cfg) {
389+
struct udc_dwc2_data *const priv = udc_get_private(dev);
390+
uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr);
391+
uint16_t limit = USB_DWC2_DSTS_SOFFN_LIMIT;
392+
393+
if ((priv->enumspd != USB_DWC2_DSTS_ENUMSPD_HS3060) {
394+
limit >>= 3;
395+
}
396+
397+
priv->target_frames[ep_idx] += cfg->interval;
398+
if (priv->target_frames[ep_idx] > limit) {
399+
priv->target_frames[ep_idx] &= limit;
400+
}
401+
}
402+
384403
static bool dwc2_ep_is_iso(struct udc_ep_config *const cfg)
385404
{
386405
return (cfg->attributes & USB_EP_TRANSFER_TYPE_MASK) == USB_EP_TYPE_ISO;
@@ -566,13 +585,12 @@ static int dwc2_tx_fifo_write(const struct device *dev,
566585
}
567586

568587
if (is_iso) {
569-
/* Queue transfer on next SOF. TODO: allow stack to explicitly
570-
* specify on which (micro-)frame the data should be sent.
571-
*/
572-
if (priv->sof_num & 1) {
573-
diepctl |= USB_DWC2_DEPCTL_SETEVENFR;
574-
} else {
575-
diepctl |= USB_DWC2_DEPCTL_SETODDFR;
588+
if (cfg->interval == 1) {
589+
if (priv->target_frames[ep_idx] & 1) {
590+
diepctl |= USB_DWC2_DEPCTL_SETODDFR;
591+
} else {
592+
diepctl |= USB_DWC2_DEPCTL_SETEVENFR;
593+
}
576594
}
577595
}
578596

@@ -706,10 +724,12 @@ static void dwc2_prep_rx(const struct device *dev, struct net_buf *buf,
706724
}
707725

708726
/* Set the Even/Odd (micro-)frame appropriately */
709-
if (priv->sof_num & 1) {
710-
doepctl |= USB_DWC2_DEPCTL_SETEVENFR;
711-
} else {
712-
doepctl |= USB_DWC2_DEPCTL_SETODDFR;
727+
if (cfg->interval == 1) {
728+
if (priv->target_frames[ep_idx] & 1) {
729+
diepctl |= USB_DWC2_DEPCTL_SETODDFR;
730+
} else {
731+
diepctl |= USB_DWC2_DEPCTL_SETEVENFR;
732+
}
713733
}
714734
} else {
715735
xfersize = net_buf_tailroom(buf);
@@ -1363,6 +1383,7 @@ static int dwc2_set_dedicated_fifo(const struct device *dev,
13631383
static int dwc2_ep_control_enable(const struct device *dev,
13641384
struct udc_ep_config *const cfg)
13651385
{
1386+
struct udc_dwc2_data *const priv = udc_get_private(dev);
13661387
mem_addr_t dxepctl0_reg;
13671388
uint32_t dxepctl0;
13681389

@@ -1395,6 +1416,11 @@ static int dwc2_ep_control_enable(const struct device *dev,
13951416
dwc2_flush_tx_fifo(dev, 0);
13961417
}
13971418

1419+
if (dwc2_ep_is_iso(cfg)) {
1420+
const uint8_t ep_idx = USB_EP_GET_IDX(ep) + (USB_EP_DIR_IS_IN(ep) ? 0U : 16U);
1421+
priv->target_frames[ep_idx] = UDC_DWC2_TARGET_FRAME_INITIAL;
1422+
}
1423+
13981424
sys_write32(dxepctl0, dxepctl0_reg);
13991425
dwc2_set_epint(dev, cfg, true);
14001426

@@ -2417,6 +2443,7 @@ static void dwc2_on_bus_reset(const struct device *dev)
24172443
uint32_t doepmsk;
24182444

24192445
/* Set the NAK bit for all OUT endpoints */
2446+
sys_clear_bits((mem_addr_t)&base->diepmsk, USB_DWC2_DIEPINT_NAKINTRPT);
24202447
for (uint8_t i = 0U; i < priv->numdeveps; i++) {
24212448
uint32_t epdir = usb_dwc2_get_ghwcfg1_epdir(priv->ghwcfg1, i);
24222449
mem_addr_t doepctl_reg;
@@ -2435,7 +2462,7 @@ static void dwc2_on_bus_reset(const struct device *dev)
24352462
}
24362463

24372464
sys_write32(doepmsk, (mem_addr_t)&base->doepmsk);
2438-
sys_set_bits((mem_addr_t)&base->diepmsk, USB_DWC2_DIEPINT_XFERCOMPL);
2465+
sys_set_bits((mem_addr_t)&base->diepmsk, USB_DWC2_DIEPINT_XFERCOMPL | USB_DWC2_DIEPINT_NAKINTRPT);
24392466

24402467
/* Software has to handle RxFLvl interrupt only in Completer mode */
24412468
if (dwc2_in_completer_mode(dev)) {
@@ -2562,6 +2589,38 @@ static inline void dwc2_handle_in_xfercompl(const struct device *dev,
25622589
k_event_post(&priv->drv_evt, BIT(DWC2_DRV_EVT_EP_FINISHED));
25632590
}
25642591

2592+
static inline void dwc2_handle_in_nakintrpt(const struct device *dev,
2593+
const uint8_t ep_idx)
2594+
{
2595+
struct udc_dwc2_data *const priv = udc_get_private(dev);
2596+
/* TODO: use dwc2_get_dxepctl_reg() */
2597+
mem_addr_t diepctl_reg = (mem_addr_t)&base->in_ep[ep_idx].diepctl;
2598+
struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep_idx | USB_EP_DIR_IN);
2599+
uint32_t diepctl;
2600+
2601+
if (!dwc2_ep_is_iso(ep_cfg)) {
2602+
return;
2603+
}
2604+
2605+
if (priv->target_frames[ep_idx] == UDC_DWC2_TARGET_FRAME_INITIAL) {
2606+
priv->target_frames[ep_idx] = priv->sof_num;
2607+
if (cfg->interval > 1) {
2608+
diepctl = sys_read32(diepctl_reg);
2609+
if (priv->target_frames[ep_idx] & 1) {
2610+
diepctl |= USB_DWC2_DEPCTL_SETODDFR;
2611+
} else {
2612+
diepctl |= USB_DWC2_DEPCTL_SETEVENFR;
2613+
}
2614+
2615+
sys_write32(diepctl, diepctl_reg);
2616+
}
2617+
}
2618+
2619+
// TODO this holy fuck
2620+
diepctl = sys_read32(diepctl_reg);
2621+
if (diepctl )
2622+
}
2623+
25652624
static inline void dwc2_handle_iepint(const struct device *dev)
25662625
{
25672626
struct usb_dwc2_reg *const base = dwc2_get_base(dev);
@@ -2590,6 +2649,9 @@ static inline void dwc2_handle_iepint(const struct device *dev)
25902649
dwc2_handle_in_xfercompl(dev, n);
25912650
}
25922651

2652+
if (status & USB_DWC2_DIEPINT_NAKINTRPT) {
2653+
dwc2_handle_in_nakintrpt(dev, n);
2654+
}
25932655
}
25942656
}
25952657

0 commit comments

Comments
 (0)