|
35 | 35 |
|
36 | 36 | #include "host/hcd.h" |
37 | 37 | #include "host/usbh.h" |
| 38 | +#include "host/usbh_pvt.h" |
38 | 39 | #include "ehci_api.h" |
39 | 40 | #include "ehci.h" |
40 | 41 |
|
| 42 | +// NXP specific fixes |
| 43 | +#if TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX, OPT_MCU_LPC55, OPT_MCU_MCXN9) |
| 44 | +#include "fsl_device_registers.h" |
| 45 | +#endif |
| 46 | + |
41 | 47 | //--------------------------------------------------------------------+ |
42 | 48 | // MACRO CONSTANT TYPEDEF |
43 | 49 | //--------------------------------------------------------------------+ |
@@ -179,12 +185,43 @@ static void ehci_enable_schedule(ehci_registers_t* regs, bool is_period) { |
179 | 185 | } |
180 | 186 | } |
181 | 187 |
|
| 188 | +#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) |
| 189 | +static void nxp_usbphy_disconn_detector_set(uint8_t port, bool enable) { |
| 190 | + // unify naming convention |
| 191 | +#if !defined(USBPHY1) && defined(USBPHY) |
| 192 | + #define USBPHY1 USBPHY |
| 193 | +#endif |
| 194 | + |
| 195 | + if (port == 0) { |
| 196 | + if (enable) { |
| 197 | + USBPHY1->CTRL_SET = USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; |
| 198 | + } else { |
| 199 | + USBPHY1->CTRL_CLR = USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; |
| 200 | + } |
| 201 | + } |
| 202 | +#if FSL_FEATURE_SOC_USBPHY_COUNT > 1U |
| 203 | + else if (port == 1) { |
| 204 | + if (enable) { |
| 205 | + USBPHY2->CTRL_SET = USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; |
| 206 | + } else { |
| 207 | + USBPHY2->CTRL_CLR = USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; |
| 208 | + } |
| 209 | + } |
| 210 | +#endif |
| 211 | + |
| 212 | +#if !defined(USBPHY1) && defined(USBPHY) |
| 213 | + #undef USBPHY1 |
| 214 | +#endif |
| 215 | +} |
| 216 | +#endif |
| 217 | + |
182 | 218 | //--------------------------------------------------------------------+ |
183 | 219 | // HCD API |
184 | 220 | //--------------------------------------------------------------------+ |
185 | 221 | uint32_t hcd_frame_number(uint8_t rhport) { |
186 | 222 | (void) rhport; |
187 | | - return (ehci_data.uframe_number + ehci_data.regs->frame_index) >> 3; |
| 223 | + uint32_t uframe = ehci_data.regs->frame_index; |
| 224 | + return (ehci_data.uframe_number + uframe) >> 3; |
188 | 225 | } |
189 | 226 |
|
190 | 227 | void hcd_port_reset(uint8_t rhport) { |
@@ -212,16 +249,21 @@ void hcd_port_reset_end(uint8_t rhport) { |
212 | 249 | (void) rhport; |
213 | 250 | ehci_registers_t* regs = ehci_data.regs; |
214 | 251 |
|
215 | | - // skip if reset is already complete |
216 | | - if (!regs->portsc_bm.port_reset) { |
217 | | - return; |
218 | | - } |
| 252 | + // stop reset only if is not complete yet |
| 253 | + if (regs->portsc_bm.port_reset) { |
| 254 | + // mask out all change bits since they are Write 1 to clear |
| 255 | + uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C; |
| 256 | + portsc &= ~EHCI_PORTSC_MASK_PORT_RESET; |
219 | 257 |
|
220 | | - // mask out all change bits since they are Write 1 to clear |
221 | | - uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C; |
222 | | - portsc &= ~EHCI_PORTSC_MASK_PORT_RESET; |
| 258 | + regs->portsc = portsc; |
| 259 | + } |
223 | 260 |
|
224 | | - regs->portsc = portsc; |
| 261 | +#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) |
| 262 | + // Enable disconnect detector for highspeed device only |
| 263 | + if (hcd_port_speed_get(rhport) == TUSB_SPEED_HIGH) { |
| 264 | + nxp_usbphy_disconn_detector_set(rhport, true); |
| 265 | + } |
| 266 | +#endif |
225 | 267 | } |
226 | 268 |
|
227 | 269 | bool hcd_port_connect_status(uint8_t rhport) { |
@@ -578,6 +620,10 @@ void port_connect_status_change_isr(uint8_t rhport) { |
578 | 620 | hcd_event_device_attach(rhport, true); |
579 | 621 | } else // device unplugged |
580 | 622 | { |
| 623 | +#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) |
| 624 | + // Disable disconnect detector |
| 625 | + nxp_usbphy_disconn_detector_set(rhport, false); |
| 626 | +#endif |
581 | 627 | hcd_event_device_remove(rhport, true); |
582 | 628 | } |
583 | 629 | } |
@@ -821,14 +867,21 @@ static ehci_qhd_t *qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) { |
821 | 867 | } |
822 | 868 |
|
823 | 869 | ehci_qhd_t *qhd_pool = ehci_data.qhd_pool; |
| 870 | + |
| 871 | + // protect qhd_pool since 'used' and 'removing' can be changed in isr |
| 872 | + ehci_qhd_t *result = NULL; |
| 873 | + usbh_spin_lock(false); |
824 | 874 | for (uint32_t i = 0; i < QHD_MAX; i++) { |
825 | 875 | if ((qhd_pool[i].dev_addr == dev_addr) && |
826 | | - ep_addr == qhd_ep_addr(&qhd_pool[i])) { |
827 | | - return &qhd_pool[i]; |
| 876 | + ep_addr == qhd_ep_addr(&qhd_pool[i]) && |
| 877 | + qhd_pool[i].used && !qhd_pool[i].removing) { |
| 878 | + result = &qhd_pool[i]; |
| 879 | + break; |
828 | 880 | } |
829 | 881 | } |
| 882 | + usbh_spin_unlock(false); |
830 | 883 |
|
831 | | - return NULL; |
| 884 | + return result; |
832 | 885 | } |
833 | 886 |
|
834 | 887 | // Init queue head with endpoint descriptor |
@@ -896,7 +949,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c |
896 | 949 | p_qhd->used = 1; |
897 | 950 | p_qhd->removing = 0; |
898 | 951 | p_qhd->attached_qtd = NULL; |
899 | | - p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint |
| 952 | + p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint |
900 | 953 |
|
901 | 954 | //------------- active, but no TD list -------------// |
902 | 955 | p_qhd->qtd_overlay.halted = 0; |
|
0 commit comments