summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2025-07-16 21:49:54 +0800
committersakumisu <[email protected]>2025-07-16 21:49:54 +0800
commit7a357a10da5664c8df556a16a6676d9630470798 (patch)
tree1ff9cf5a5afc4330c968f2dd58f8ee63d37ae985
parentd58037e3d491cc527bcf24d2c3ff70cf4bf8a68b (diff)
feat(port/dwc2): support ep mult
Signed-off-by: sakumisu <[email protected]>
-rw-r--r--port/dwc2/usb_dc_dwc2.c6
-rw-r--r--port/dwc2/usb_dwc2_reg.h7
-rw-r--r--port/dwc2/usb_hc_dwc2.c77
3 files changed, 76 insertions, 14 deletions
diff --git a/port/dwc2/usb_dc_dwc2.c b/port/dwc2/usb_dc_dwc2.c
index 36fb9cb2..e9de2602 100644
--- a/port/dwc2/usb_dc_dwc2.c
+++ b/port/dwc2/usb_dc_dwc2.c
@@ -877,8 +877,12 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
USB_OTG_INEP(ep_idx)->DIEPCTL &= ~USB_OTG_DIEPCTL_SODDFRM;
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
}
+ }
+
+ if (g_dwc2_udc[busid].in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS ||
+ g_dwc2_udc[busid].in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) {
USB_OTG_INEP(ep_idx)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT);
- USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1U << 29));
+ USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & ((usbd_get_ep_mult(busid, ep) + 1) << 29));
}
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
diff --git a/port/dwc2/usb_dwc2_reg.h b/port/dwc2/usb_dwc2_reg.h
index cdf4f51a..599d4ea5 100644
--- a/port/dwc2/usb_dwc2_reg.h
+++ b/port/dwc2/usb_dwc2_reg.h
@@ -215,9 +215,7 @@ typedef struct
#define USB_OTG_HCFG_FSLSS_Pos (2U)
#define USB_OTG_HCFG_FSLSS_Msk (0x1UL << USB_OTG_HCFG_FSLSS_Pos) /*!< 0x00000004 */
#define USB_OTG_HCFG_FSLSS USB_OTG_HCFG_FSLSS_Msk /*!< FS- and LS-only support */
-#define USB_OTG_HFIR_RELOAD_CTRL_Pos (16U)
-#define USB_OTG_HFIR_RELOAD_CTRL_Msk (0x1UL << USB_OTG_HFIR_RELOAD_CTRL_Pos)
-#define USB_OTG_HFIR_RELOAD_CTRL USB_OTG_HFIR_RELOAD_CTRL_Msk
+
/******************** Bit definition for USB_OTG_DCFG register ********************/
#define USB_OTG_DCFG_DSPD_Pos (0U)
@@ -335,6 +333,9 @@ typedef struct
#define USB_OTG_HFIR_FRIVL_Pos (0U)
#define USB_OTG_HFIR_FRIVL_Msk (0xFFFFUL << USB_OTG_HFIR_FRIVL_Pos) /*!< 0x0000FFFF */
#define USB_OTG_HFIR_FRIVL USB_OTG_HFIR_FRIVL_Msk /*!< Frame interval */
+#define USB_OTG_HFIR_RELOAD_CTRL_Pos (16U)
+#define USB_OTG_HFIR_RELOAD_CTRL_Msk (0x1UL << USB_OTG_HFIR_RELOAD_CTRL_Pos)
+#define USB_OTG_HFIR_RELOAD_CTRL USB_OTG_HFIR_RELOAD_CTRL_Msk
/******************** Bit definition for USB_OTG_HFNUM register ********************/
#define USB_OTG_HFNUM_FRNUM_Pos (0U)
diff --git a/port/dwc2/usb_hc_dwc2.c b/port/dwc2/usb_hc_dwc2.c
index 9b7b2ab1..3ceead00 100644
--- a/port/dwc2/usb_hc_dwc2.c
+++ b/port/dwc2/usb_hc_dwc2.c
@@ -222,7 +222,14 @@ static inline uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t po
}
}
-static inline void dwc2_chan_char_init(struct usbh_bus *bus, uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps, uint8_t speed)
+static inline void dwc2_chan_char_init(struct usbh_bus *bus,
+ uint8_t ch_num,
+ uint8_t dev_addr,
+ uint8_t ep_addr,
+ uint8_t ep_type,
+ uint16_t ep_mps,
+ uint8_t ep_mult,
+ uint8_t speed)
{
uint32_t regval;
@@ -230,7 +237,8 @@ static inline void dwc2_chan_char_init(struct usbh_bus *bus, uint8_t ch_num, uin
regval = (((uint32_t)ep_mps << USB_OTG_HCCHAR_MPSIZ_Pos) & USB_OTG_HCCHAR_MPSIZ) |
((((uint32_t)ep_addr & 0x7FU) << USB_OTG_HCCHAR_EPNUM_Pos) & USB_OTG_HCCHAR_EPNUM) |
(((uint32_t)ep_type << USB_OTG_HCCHAR_EPTYP_Pos) & USB_OTG_HCCHAR_EPTYP) |
- (((uint32_t)devaddr << USB_OTG_HCCHAR_DAD_Pos) & USB_OTG_HCCHAR_DAD);
+ (((uint32_t)ep_mult << USB_OTG_HCCHAR_MC_Pos) & USB_OTG_HCCHAR_MC) |
+ (((uint32_t)dev_addr << USB_OTG_HCCHAR_DAD_Pos) & USB_OTG_HCCHAR_DAD);
if ((ep_addr & 0x80U) == 0x80U) {
regval |= USB_OTG_HCCHAR_EPDIR;
@@ -272,7 +280,14 @@ static inline void dwc2_chan_splt_init(struct usbh_bus *bus, uint8_t ch_num)
}
}
-static void dwc2_chan_init(struct usbh_bus *bus, uint8_t ch_num, uint8_t devaddr, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps, uint8_t speed)
+static void dwc2_chan_init(struct usbh_bus *bus,
+ uint8_t ch_num,
+ uint8_t dev_addr,
+ uint8_t ep_addr,
+ uint8_t ep_type,
+ uint16_t ep_mps,
+ uint8_t ep_mult,
+ uint8_t speed)
{
/* Clear old interrupt conditions for this host channel. */
USB_OTG_HC((uint32_t)ch_num)->HCINT = 0xFFFFFFFFU;
@@ -283,7 +298,7 @@ static void dwc2_chan_init(struct usbh_bus *bus, uint8_t ch_num, uint8_t devaddr
/* Enable the top level host channel interrupt. */
USB_OTG_HOST->HAINTMSK |= 1UL << (ch_num & 0xFU);
- dwc2_chan_char_init(bus, ch_num, devaddr, ep_addr, ep_type, ep_mps, speed);
+ dwc2_chan_char_init(bus, ch_num, dev_addr, ep_addr, ep_type, ep_mps, ep_mult, speed);
dwc2_chan_splt_init(bus, ch_num);
}
@@ -519,27 +534,62 @@ static void dwc2_control_urb_init(struct usbh_bus *bus, uint8_t chidx, struct us
if (chan->ep0_state == DWC2_EP0_STATE_SETUP) /* fill setup */
{
chan->num_packets = dwc2_calculate_packet_num(8, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
- dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
+ dwc2_chan_init(bus,
+ chidx,
+ urb->hport->dev_addr,
+ 0x00,
+ USB_ENDPOINT_TYPE_CONTROL,
+ USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize),
+ 1,
+ urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x00, (uint8_t *)setup, chan->xferlen, chan->num_packets, HC_PID_SETUP);
} else if (chan->ep0_state == DWC2_EP0_STATE_INDATA) /* fill in data */
{
chan->num_packets = dwc2_calculate_packet_num(datalen, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
- dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
+ dwc2_chan_init(bus,
+ chidx,
+ urb->hport->dev_addr,
+ 0x80,
+ USB_ENDPOINT_TYPE_CONTROL,
+ USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize),
+ 1,
+ urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x80, buffer, chan->xferlen, chan->num_packets, data_pid);
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTDATA) /* fill out data */
{
chan->num_packets = dwc2_calculate_packet_num(datalen, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
- dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
+ dwc2_chan_init(bus,
+ chidx,
+ urb->hport->dev_addr,
+ 0x00,
+ USB_ENDPOINT_TYPE_CONTROL,
+ USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize),
+ 1,
+ urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x00, buffer, chan->xferlen, chan->num_packets, data_pid);
} else if (chan->ep0_state == DWC2_EP0_STATE_INSTATUS) /* fill in status */
{
chan->num_packets = dwc2_calculate_packet_num(0, 0x80, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
- dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x80, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
+ dwc2_chan_init(bus,
+ chidx,
+ urb->hport->dev_addr,
+ 0x80,
+ USB_ENDPOINT_TYPE_CONTROL,
+ USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize),
+ 1,
+ urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x80, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1);
} else if (chan->ep0_state == DWC2_EP0_STATE_OUTSTATUS) /* fill out status */
{
chan->num_packets = dwc2_calculate_packet_num(0, 0x00, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
- dwc2_chan_init(bus, chidx, urb->hport->dev_addr, 0x00, USB_ENDPOINT_TYPE_CONTROL, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
+ dwc2_chan_init(bus,
+ chidx,
+ urb->hport->dev_addr,
+ 0x00,
+ USB_ENDPOINT_TYPE_CONTROL,
+ USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize),
+ 1,
+ urb->hport->speed);
dwc2_chan_transfer(bus, chidx, 0x00, NULL, chan->xferlen, chan->num_packets, HC_PID_DATA1);
}
}
@@ -562,7 +612,14 @@ static void dwc2_bulk_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct
}
chan->num_packets = dwc2_calculate_packet_num(datalen, urb->ep->bEndpointAddress, USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), &chan->xferlen);
- dwc2_chan_init(bus, chidx, urb->hport->dev_addr, urb->ep->bEndpointAddress, USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes), USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize), urb->hport->speed);
+ dwc2_chan_init(bus,
+ chidx,
+ urb->hport->dev_addr,
+ urb->ep->bEndpointAddress,
+ USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes),
+ USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize),
+ USB_GET_MULT(urb->ep->wMaxPacketSize) + 1,
+ urb->hport->speed);
dwc2_chan_transfer(bus, chidx, urb->ep->bEndpointAddress, buffer, chan->xferlen, chan->num_packets, urb->data_toggle == 0 ? HC_PID_DATA0 : HC_PID_DATA1);
}