@@ -54,12 +54,6 @@ K_MSGQ_DEFINE(drv_msgq, sizeof(struct dwc2_drv_event),
54
54
/* TX FIFO0 depth in 32-bit words (used by control IN endpoint) */
55
55
#define UDC_DWC2_FIFO0_DEPTH 16U
56
56
57
- /* Number of endpoints supported by the driver.
58
- * This must be equal to or greater than the number supported by the hardware.
59
- * (FIXME)
60
- */
61
- #define UDC_DWC2_DRV_EP_NUM 8
62
-
63
57
/* Get Data FIFO access register */
64
58
#define UDC_DWC2_EP_FIFO (base , idx ) ((mem_addr_t)base + 0x1000 * (idx + 1))
65
59
@@ -1613,56 +1607,102 @@ static int dwc2_driver_preinit(const struct device *dev)
1613
1607
const struct udc_dwc2_config * config = dev -> config ;
1614
1608
struct udc_data * data = dev -> data ;
1615
1609
uint16_t mps = 1023 ;
1610
+ uint32_t numdeveps ;
1611
+ uint32_t ineps ;
1616
1612
int err ;
1617
1613
1618
1614
k_mutex_init (& data -> mutex );
1619
1615
1620
1616
data -> caps .rwup = true;
1621
1617
data -> caps .addr_before_status = true;
1622
1618
data -> caps .mps0 = UDC_MPS0_64 ;
1623
- if (config -> speed_idx == 2 ) {
1624
- data -> caps .hs = true;
1619
+
1620
+ (void )dwc2_quirk_caps (dev );
1621
+ if (data -> caps .hs ) {
1625
1622
mps = 1024 ;
1626
1623
}
1627
1624
1628
- for (int i = 0 ; i < config -> num_of_eps ; i ++ ) {
1629
- config -> ep_cfg_out [i ].caps .out = 1 ;
1625
+ /*
1626
+ * At this point, we cannot or do not want to access the hardware
1627
+ * registers to get GHWCFGn values. For now, we will use devicetree to
1628
+ * get GHWCFGn values and use them to determine the number and type of
1629
+ * configured endpoints in the hardware. This can be considered a
1630
+ * workaround, and we may change the upper layer internals to avoid it
1631
+ * in the future.
1632
+ */
1633
+ ineps = usb_dwc2_get_ghwcfg4_ineps (config -> ghwcfg4 ) + 1U ;
1634
+ numdeveps = usb_dwc2_get_ghwcfg2_numdeveps (config -> ghwcfg2 ) + 1U ;
1635
+ LOG_DBG ("Number of endpoints (NUMDEVEPS + 1) %u" , numdeveps );
1636
+ LOG_DBG ("Number of IN endpoints (INEPS + 1) %u" , ineps );
1637
+
1638
+ for (uint32_t i = 0 , n = 0 ; i < numdeveps ; i ++ ) {
1639
+ uint32_t epdir = usb_dwc2_get_ghwcfg1_epdir (config -> ghwcfg1 , i );
1640
+
1641
+ if (epdir != USB_DWC2_GHWCFG1_EPDIR_OUT &&
1642
+ epdir != USB_DWC2_GHWCFG1_EPDIR_BDIR ) {
1643
+ continue ;
1644
+ }
1645
+
1630
1646
if (i == 0 ) {
1631
- config -> ep_cfg_out [i ].caps .control = 1 ;
1632
- config -> ep_cfg_out [i ].caps .mps = 64 ;
1647
+ config -> ep_cfg_out [n ].caps .control = 1 ;
1648
+ config -> ep_cfg_out [n ].caps .mps = 64 ;
1633
1649
} else {
1634
- config -> ep_cfg_out [i ].caps .bulk = 1 ;
1635
- config -> ep_cfg_out [i ].caps .interrupt = 1 ;
1636
- config -> ep_cfg_out [i ].caps .iso = 1 ;
1637
- config -> ep_cfg_out [i ].caps .mps = mps ;
1650
+ config -> ep_cfg_out [n ].caps .bulk = 1 ;
1651
+ config -> ep_cfg_out [n ].caps .interrupt = 1 ;
1652
+ config -> ep_cfg_out [n ].caps .iso = 1 ;
1653
+ config -> ep_cfg_out [n ].caps .mps = mps ;
1638
1654
}
1639
1655
1640
- config -> ep_cfg_out [i ].addr = USB_EP_DIR_OUT | i ;
1641
- err = udc_register_ep (dev , & config -> ep_cfg_out [i ]);
1656
+ config -> ep_cfg_out [n ].caps .out = 1 ;
1657
+ config -> ep_cfg_out [n ].addr = USB_EP_DIR_OUT | i ;
1658
+
1659
+ LOG_DBG ("Register ep 0x%02x (%u)" , i , n );
1660
+ err = udc_register_ep (dev , & config -> ep_cfg_out [n ]);
1642
1661
if (err != 0 ) {
1643
1662
LOG_ERR ("Failed to register endpoint" );
1644
1663
return err ;
1645
1664
}
1665
+
1666
+ n ++ ;
1667
+ /* Also check the number of desired OUT endpoints in devicetree. */
1668
+ if (n >= config -> num_out_eps ) {
1669
+ break ;
1670
+ }
1646
1671
}
1647
1672
1648
- for (int i = 0 ; i < config -> num_of_eps ; i ++ ) {
1649
- config -> ep_cfg_in [i ].caps .in = 1 ;
1673
+ for (uint32_t i = 0 , n = 0 ; i < numdeveps ; i ++ ) {
1674
+ uint32_t epdir = usb_dwc2_get_ghwcfg1_epdir (config -> ghwcfg1 , i );
1675
+
1676
+ if (epdir != USB_DWC2_GHWCFG1_EPDIR_IN &&
1677
+ epdir != USB_DWC2_GHWCFG1_EPDIR_BDIR ) {
1678
+ continue ;
1679
+ }
1680
+
1650
1681
if (i == 0 ) {
1651
- config -> ep_cfg_in [i ].caps .control = 1 ;
1652
- config -> ep_cfg_in [i ].caps .mps = 64 ;
1682
+ config -> ep_cfg_in [n ].caps .control = 1 ;
1683
+ config -> ep_cfg_in [n ].caps .mps = 64 ;
1653
1684
} else {
1654
- config -> ep_cfg_in [i ].caps .bulk = 1 ;
1655
- config -> ep_cfg_in [i ].caps .interrupt = 1 ;
1656
- config -> ep_cfg_in [i ].caps .iso = 1 ;
1657
- config -> ep_cfg_in [i ].caps .mps = mps ;
1685
+ config -> ep_cfg_in [n ].caps .bulk = 1 ;
1686
+ config -> ep_cfg_in [n ].caps .interrupt = 1 ;
1687
+ config -> ep_cfg_in [n ].caps .iso = 1 ;
1688
+ config -> ep_cfg_in [n ].caps .mps = mps ;
1658
1689
}
1659
1690
1660
- config -> ep_cfg_in [i ].addr = USB_EP_DIR_IN | i ;
1661
- err = udc_register_ep (dev , & config -> ep_cfg_in [i ]);
1691
+ config -> ep_cfg_in [n ].caps .in = 1 ;
1692
+ config -> ep_cfg_in [n ].addr = USB_EP_DIR_IN | i ;
1693
+
1694
+ LOG_DBG ("Register ep 0x%02x (%u)" , USB_EP_DIR_IN | i , n );
1695
+ err = udc_register_ep (dev , & config -> ep_cfg_in [n ]);
1662
1696
if (err != 0 ) {
1663
1697
LOG_ERR ("Failed to register endpoint" );
1664
1698
return err ;
1665
1699
}
1700
+
1701
+ n ++ ;
1702
+ /* Also check the number of desired IN endpoints in devicetree. */
1703
+ if (n >= MIN (ineps , config -> num_in_eps )) {
1704
+ break ;
1705
+ }
1666
1706
}
1667
1707
1668
1708
config -> make_thread (dev );
@@ -1770,19 +1810,23 @@ static const struct udc_api udc_dwc2_api = {
1770
1810
irq_disable(DT_INST_IRQN(n)); \
1771
1811
} \
1772
1812
\
1773
- static struct udc_ep_config ep_cfg_out[UDC_DWC2_DRV_EP_NUM]; \
1774
- static struct udc_ep_config ep_cfg_in[UDC_DWC2_DRV_EP_NUM]; \
1813
+ static struct udc_ep_config ep_cfg_out[DT_INST_PROP(n, num_out_eps)]; \
1814
+ static struct udc_ep_config ep_cfg_in[DT_INST_PROP(n, num_in_eps)]; \
1775
1815
\
1776
1816
static const struct udc_dwc2_config udc_dwc2_config_##n = { \
1777
- .num_of_eps = UDC_DWC2_DRV_EP_NUM, \
1778
- .ep_cfg_in = ep_cfg_out, \
1779
- .ep_cfg_out = ep_cfg_in, \
1817
+ .num_out_eps = DT_INST_PROP(n, num_out_eps), \
1818
+ .num_in_eps = DT_INST_PROP(n, num_in_eps), \
1819
+ .ep_cfg_in = ep_cfg_in, \
1820
+ .ep_cfg_out = ep_cfg_out, \
1780
1821
.make_thread = udc_dwc2_make_thread_##n, \
1781
1822
.base = (struct usb_dwc2_reg *)UDC_DWC2_DT_INST_REG_ADDR(n), \
1782
1823
.pcfg = UDC_DWC2_PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
1783
1824
.irq_enable_func = udc_dwc2_irq_enable_func_##n, \
1784
1825
.irq_disable_func = udc_dwc2_irq_disable_func_##n, \
1785
1826
.quirks = UDC_DWC2_VENDOR_QUIRK_GET(n), \
1827
+ .ghwcfg1 = DT_INST_PROP(n, ghwcfg1), \
1828
+ .ghwcfg2 = DT_INST_PROP(n, ghwcfg2), \
1829
+ .ghwcfg4 = DT_INST_PROP(n, ghwcfg4), \
1786
1830
}; \
1787
1831
\
1788
1832
static struct udc_dwc2_data udc_priv_##n = { \
0 commit comments