diff options
| author | tswan22 <[email protected]> | 2025-11-01 12:51:40 -0400 |
|---|---|---|
| committer | tswan22 <[email protected]> | 2025-11-01 12:51:40 -0400 |
| commit | ca44c772f7ad87a8d12de0b3a57ad8816f2edc10 (patch) | |
| tree | 2ac98dc0c073ca161741751504fdbeb0b710dd11 /src/portable | |
| parent | 9d46cca57637cfd086499970a8f5d5669ba9bfa0 (diff) | |
| parent | a6c16d147593732028ed89292805e0e6a972e4b5 (diff) | |
Merge branch 'master' of https://github.com/hathach/tinyusb
Diffstat (limited to 'src/portable')
| -rw-r--r-- | src/portable/ehci/ehci.h | 6 | ||||
| -rw-r--r-- | src/portable/ehci/ehci_api.h | 4 | ||||
| -rw-r--r-- | src/portable/nuvoton/nuc121/dcd_nuc121.c | 10 | ||||
| -rw-r--r-- | src/portable/nuvoton/nuc505/dcd_nuc505.c | 10 | ||||
| -rw-r--r-- | src/portable/nxp/lpc17_40/dcd_lpc17_40.h | 4 | ||||
| -rw-r--r-- | src/portable/ohci/ohci.c | 458 | ||||
| -rw-r--r-- | src/portable/ohci/ohci.h | 190 | ||||
| -rw-r--r-- | src/portable/ohci/ohci_nxp.h (renamed from src/portable/nxp/lpc17_40/hcd_lpc17_40.c) | 48 | ||||
| -rw-r--r-- | src/portable/raspberrypi/pio_usb/hcd_pio_usb.c | 11 | ||||
| -rw-r--r-- | src/portable/renesas/rusb2/rusb2_type.h | 6 | ||||
| -rw-r--r-- | src/portable/sunxi/musb_def.h | 4 | ||||
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_bcm.h | 4 | ||||
| -rw-r--r-- | src/portable/valentyusb/eptri/dcd_eptri.h | 6 |
13 files changed, 407 insertions, 354 deletions
diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index 87659701b..719bdeafc 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_EHCI_H_ -#define _TUSB_EHCI_H_ +#ifndef TUSB_EHCI_H_ +#define TUSB_EHCI_H_ /* Abbreviation @@ -458,4 +458,4 @@ TU_VERIFY_STATIC(sizeof(ehci_cap_registers_t) == 16, "size is not correct"); } #endif -#endif /* _TUSB_EHCI_H_ */ +#endif /* TUSB_EHCI_H_ */ diff --git a/src/portable/ehci/ehci_api.h b/src/portable/ehci/ehci_api.h index 12e0a73d7..79fbe702a 100644 --- a/src/portable/ehci/ehci_api.h +++ b/src/portable/ehci/ehci_api.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_EHCI_API_H_ -#define _TUSB_EHCI_API_H_ +#ifndef TUSB_EHCI_API_H_ +#define TUSB_EHCI_API_H_ #ifdef __cplusplus extern "C" { diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index 37210ea34..804a35565 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -38,8 +38,18 @@ #if CFG_TUD_ENABLED && ( (CFG_TUSB_MCU == OPT_MCU_NUC121) || (CFG_TUSB_MCU == OPT_MCU_NUC126) ) #include "device/dcd.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "NuMicro.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on #ifndef USE_SOF diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index fa457d861..6195015ae 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -38,8 +38,18 @@ #if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) #include "device/dcd.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "NUC505Series.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + /* * The DMA functionality of the USBD peripheral does not appear to succeed with * transfer lengths that are longer (> 64 bytes) and are not a multiple of 4. diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.h b/src/portable/nxp/lpc17_40/dcd_lpc17_40.h index 654b80866..25c9f9985 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.h +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DCD_LPC17_40_H_ -#define _TUSB_DCD_LPC17_40_H_ +#ifndef TUSB_DCD_LPC17_40_H_ +#define TUSB_DCD_LPC17_40_H_ #include "common/tusb_common.h" diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index f1689b5b4..6d4594450 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -41,13 +41,16 @@ #include "host/usbh.h" #include "ohci.h" -// TODO remove -#include "chip.h" +#if defined(TUP_USBIP_OHCI_NXP) + #include "ohci_nxp.h" +#else + #error Unsupported OHCI IP +#endif //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#define OHCI_REG ((ohci_registers_t *) LPC_USB_BASE) + enum { OHCI_CONTROL_FUNCSTATE_RESET = 0, @@ -109,17 +112,17 @@ enum { enum { OHCI_CCODE_NO_ERROR = 0, OHCI_CCODE_CRC = 1, - OHCI_CCODE_BIT_STUFFING = 2, - OHCI_CCODE_DATA_TOGGLE_MISMATCH = 3, - OHCI_CCODE_STALL = 4, - OHCI_CCODE_DEVICE_NOT_RESPONDING = 5, - OHCI_CCODE_PID_CHECK_FAILURE = 6, - OHCI_CCODE_UNEXPECTED_PID = 7, - OHCI_CCODE_DATA_OVERRUN = 8, - OHCI_CCODE_DATA_UNDERRUN = 9, - OHCI_CCODE_BUFFER_OVERRUN = 12, - OHCI_CCODE_BUFFER_UNDERRUN = 13, - OHCI_CCODE_NOT_ACCESSED = 14, + OHCI_CCODE_BIT_STUFFING = 2, + OHCI_CCODE_DATA_TOGGLE_MISMATCH = 3, + OHCI_CCODE_STALL = 4, + OHCI_CCODE_DEVICE_NOT_RESPONDING = 5, + OHCI_CCODE_PID_CHECK_FAILURE = 6, + OHCI_CCODE_UNEXPECTED_PID = 7, + OHCI_CCODE_DATA_OVERRUN = 8, + OHCI_CCODE_DATA_UNDERRUN = 9, + OHCI_CCODE_BUFFER_OVERRUN = 12, + OHCI_CCODE_BUFFER_UNDERRUN = 13, + OHCI_CCODE_NOT_ACCESSED = 14, }; enum { @@ -144,21 +147,36 @@ enum { }; //--------------------------------------------------------------------+ +// Support for explicit D-cache operations +//--------------------------------------------------------------------+ +TU_ATTR_WEAK bool hcd_dcache_clean(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; } +TU_ATTR_WEAK bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; } + +// Optional macro to access ED in uncached way +#ifndef hcd_dcache_uncached +#define hcd_dcache_uncached(x) (x) +#endif + +//--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(256) static ohci_data_t ohci_data; -static ohci_ed_t * const p_ed_head[] = -{ - [TUSB_XFER_CONTROL] = &ohci_data.control[0].ed, - [TUSB_XFER_BULK ] = &ohci_data.bulk_head_ed, - [TUSB_XFER_INTERRUPT] = &ohci_data.period_head_ed, +static ohci_ed_t * const p_ed_head[] = { + [TUSB_XFER_CONTROL] = hcd_dcache_uncached(&ohci_data.control[0].ed), + [TUSB_XFER_BULK ] = hcd_dcache_uncached(&ohci_data.bulk_head_ed), + [TUSB_XFER_INTERRUPT] = hcd_dcache_uncached(&ohci_data.period_head_ed), [TUSB_XFER_ISOCHRONOUS] = NULL // TODO Isochronous }; static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed); static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr); static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd); +static ohci_ed_t* ed_from_addr(uint8_t dev_addr, uint8_t ep_addr); + +TU_ATTR_ALWAYS_INLINE static inline ohci_ed_t* ed_control(uint8_t daddr) { + return hcd_dcache_uncached(&ohci_data.control[daddr].ed); +} //--------------------------------------------------------------------+ // USBH-HCD API @@ -166,13 +184,11 @@ static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd); // If your system requires separation of virtual and physical memory, implement // tusb_app_virt_to_phys and tusb_app_virt_to_phys in your application. -TU_ATTR_ALWAYS_INLINE static inline void *_phys_addr(void *virtual_address) -{ +TU_ATTR_ALWAYS_INLINE static inline void *_phys_addr(void *virtual_address) { return tusb_app_virt_to_phys(virtual_address); } -TU_ATTR_ALWAYS_INLINE static inline void *_virt_addr(void *physical_address) -{ +TU_ATTR_ALWAYS_INLINE static inline void *_virt_addr(void *physical_address) { return tusb_app_phys_to_virt(physical_address); } @@ -181,34 +197,33 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rhport; (void) rh_init; + ohci_phy_init(rhport); + //------------- Data Structure init -------------// tu_memclr(&ohci_data, sizeof(ohci_data_t)); - for(uint8_t i=0; i<32; i++) - { // assign all interrupt pointers to period head ed + // assign all interrupt pointers to period head ed + for(uint8_t i=0; i<32; i++) { ohci_data.hcca.interrupt_table[i] = (uint32_t) _phys_addr(&ohci_data.period_head_ed); } - ohci_data.control[0].ed.skip = 1; - ohci_data.bulk_head_ed.skip = 1; - ohci_data.period_head_ed.skip = 1; + ohci_data.control[0].ed.w0.skip = 1; + ohci_data.bulk_head_ed.w0.skip = 1; + ohci_data.period_head_ed.w0.skip = 1; //If OHCI hardware is in SMM mode, gain ownership (Ref OHCI spec 5.1.1.3.3) - if (OHCI_REG->control_bit.interrupt_routing == 1) - { + if (OHCI_REG->control_bit.interrupt_routing == 1) { OHCI_REG->command_status_bit.ownership_change_request = 1; while (OHCI_REG->control_bit.interrupt_routing == 1) {} - } - - //If OHCI hardware has come from warm-boot, signal resume (Ref OHCI spec 5.1.1.3.4) - else if (OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_RESET && - OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_OPERATIONAL) - { + } else if (OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_RESET && + OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_OPERATIONAL) { + //If OHCI hardware has come from warm-boot, signal resume (Ref OHCI spec 5.1.1.3.4) //Wait 20 ms. (Ref Usb spec 7.1.7.7) OHCI_REG->control_bit.hc_functional_state = OHCI_CONTROL_FUNCSTATE_RESUME; - tusb_time_delay_ms_api(20); } + hcd_dcache_clean(&ohci_data, sizeof(ohci_data)); + // reset controller OHCI_REG->command_status_bit.controller_reset = 1; while( OHCI_REG->command_status_bit.controller_reset ) {} // should not take longer than 10 us @@ -245,7 +260,6 @@ uint32_t hcd_frame_number(uint8_t rhport) return (ohci_data.frame_number_hi << 16) | OHCI_REG->frame_number; } - //--------------------------------------------------------------------+ // PORT API //--------------------------------------------------------------------+ @@ -271,26 +285,18 @@ tusb_speed_t hcd_port_speed_get(uint8_t hostid) // endpoints are tied to an address, which only reclaim after a long delay when enumerating // thus there is no need to make sure ED is not in HC's cahed as it will not for sure -void hcd_device_close(uint8_t rhport, uint8_t dev_addr) -{ +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // TODO OHCI (void) rhport; // addr0 serves as static head --> only set skip bit - if ( dev_addr == 0 ) - { - ohci_data.control[0].ed.skip = 1; - }else - { - // remove control - ed_list_remove_by_addr( p_ed_head[TUSB_XFER_CONTROL], dev_addr); - - // remove bulk - ed_list_remove_by_addr(p_ed_head[TUSB_XFER_BULK], dev_addr); - - // remove interrupt - ed_list_remove_by_addr(p_ed_head[TUSB_XFER_INTERRUPT], dev_addr); - + if (dev_addr == 0) { + ohci_ed_t* ed = ed_control(0); + ed->w0.skip = 1; + } else { + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_CONTROL], dev_addr); // remove control + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_BULK], dev_addr); // remove bulk + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_INTERRUPT], dev_addr); // remove interrupt // TODO remove ISO } } @@ -302,35 +308,36 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) //--------------------------------------------------------------------+ // List Helper //--------------------------------------------------------------------+ -static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed) -{ - return (p_ed->ep_number == 0 ) ? TUSB_XFER_CONTROL : - (p_ed->is_iso ) ? TUSB_XFER_ISOCHRONOUS : - (p_ed->is_interrupt_xfer) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; +static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_word0_t w0) { + return (w0.ep_number == 0 ) ? TUSB_XFER_CONTROL : + (w0.is_iso ) ? TUSB_XFER_ISOCHRONOUS : + (w0.is_interrupt_xfer) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; } -static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t ep_addr, uint8_t xfer_type, uint8_t interval) -{ +static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t ep_addr, uint8_t xfer_type, uint8_t interval) { (void) interval; // address 0 is used as async head, which always on the list --> cannot be cleared - if (dev_addr != 0) - { - tu_memclr(p_ed, sizeof(ohci_ed_t)); + if (dev_addr != 0) { + p_ed->td_tail = 0; + p_ed->td_head.address = 0; + p_ed->next = 0; } tuh_bus_info_t bus_info; tuh_bus_info_get(dev_addr, &bus_info); - p_ed->dev_addr = dev_addr; - p_ed->ep_number = ep_addr & 0x0F; - p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT); - p_ed->speed = bus_info.speed; - p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; - p_ed->max_packet_size = ep_size; + ohci_ed_word0_t w0 = {.value = 0}; + w0.dev_addr = dev_addr; + w0.ep_number = ep_addr & 0x0F; + w0.pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT); + w0.speed = bus_info.speed; + w0.is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; + w0.max_packet_size = ep_size; - p_ed->used = 1; - p_ed->is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); + w0.used = 1; + w0.is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); + p_ed->w0 = w0; } static void gtd_init(ohci_gtd_t *p_td, uint8_t *data_ptr, uint16_t total_bytes) { @@ -353,126 +360,109 @@ static void gtd_init(ohci_gtd_t *p_td, uint8_t *data_ptr, uint16_t total_bytes) } } -static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) -{ - if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; +static ohci_ed_t* ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) { + if (tu_edpt_number(ep_addr) == 0) { + return ed_control(dev_addr); + } ohci_ed_t* ed_pool = ohci_data.ed_pool; - - for(uint32_t i=0; i<ED_MAX; i++) - { - if ( (ed_pool[i].dev_addr == dev_addr) && - ep_addr == tu_edpt_addr(ed_pool[i].ep_number, ed_pool[i].pid == PID_IN) ) - { - return &ed_pool[i]; + for (size_t i = 0; i < ED_MAX; i++) { + ohci_ed_t* qhd = hcd_dcache_uncached(&ed_pool[i]); + if ((qhd->w0.dev_addr == dev_addr) && + ep_addr == tu_edpt_addr(qhd->w0.ep_number, qhd->w0.pid == PID_IN)) { + return qhd; } } return NULL; } -static ohci_ed_t * ed_find_free(void) -{ +static ohci_ed_t* ed_find_free(void) { ohci_ed_t* ed_pool = ohci_data.ed_pool; - - for(uint8_t i = 0; i < ED_MAX; i++) - { - if ( !ed_pool[i].used ) return &ed_pool[i]; + for (size_t i = 0; i < ED_MAX; i++) { + ohci_ed_t* qhd = hcd_dcache_uncached(&ed_pool[i]); + if (!qhd->w0.used) { + return qhd; + } } - return NULL; } -static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed) -{ +static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed) { p_ed->next = p_pre->next; p_pre->next = (uint32_t) _phys_addr(p_ed); } -static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) -{ +static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) { ohci_ed_t* p_prev = p_head; - while( p_prev->next ) - { - ohci_ed_t* ed = (ohci_ed_t*) _virt_addr((void *)p_prev->next); + while (p_prev->next) { + ohci_ed_t* ed = (ohci_ed_t*)_virt_addr((void*)p_prev->next); - if (ed->dev_addr == dev_addr) - { + if (ed->w0.dev_addr == dev_addr) { // Prevent Host Controller from processing this ED while we remove it - ed->skip = 1; + ed->w0.skip = 1; // unlink ed, will also move up p_prev p_prev->next = ed->next; // point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED - ed->next = (uint32_t) _phys_addr(p_head); - ed->used = 0; - ed->skip = 0; - }else - { - p_prev = (ohci_ed_t*) _virt_addr((void *)p_prev->next); + ed->next = (uint32_t)_phys_addr(p_head); + ed->w0.used = 0; + ed->w0.skip = 0; + } else { + p_prev = (ohci_ed_t*)_virt_addr((void*)p_prev->next); } } } -static ohci_gtd_t * gtd_find_free(void) -{ - for(uint8_t i=0; i < GTD_MAX; i++) - { - if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; +static ohci_gtd_t* gtd_find_free(void) { + for (uint8_t i = 0; i < GTD_MAX; i++) { + if (!ohci_data.gtd_pool[i].used) { + return &ohci_data.gtd_pool[i]; + } } - return NULL; } -static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) -{ - // tail is always NULL - if ( tu_align16(p_ed->td_head.address) == 0 ) - { // TD queue is empty --> head = TD - p_ed->td_head.address |= (uint32_t) _phys_addr(p_gtd); - } - else - { // TODO currently only support queue up to 2 TD each endpoint at a time - ((ohci_gtd_t*) tu_align16((uint32_t)_virt_addr((void *)p_ed->td_head.address)))->next = (uint32_t) _phys_addr(p_gtd); - } -} - //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* ep_desc) { + (void)rhport; // TODO iso support TU_ASSERT(ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); //------------- Prepare Queue Head -------------// - ohci_ed_t * p_ed; - - if ( ep_desc->bEndpointAddress == 0 ) - { - p_ed = &ohci_data.control[dev_addr].ed; - }else - { + ohci_ed_t* p_ed; + if (ep_desc->bEndpointAddress == 0) { + p_ed = ed_control(dev_addr); + } else { p_ed = ed_find_free(); } TU_ASSERT(p_ed); - ed_init( p_ed, dev_addr, tu_edpt_packet_size(ep_desc), ep_desc->bEndpointAddress, - ep_desc->bmAttributes.xfer, ep_desc->bInterval ); + ed_init(p_ed, dev_addr, tu_edpt_packet_size(ep_desc), ep_desc->bEndpointAddress, + ep_desc->bmAttributes.xfer, ep_desc->bInterval); // control of dev0 is used as static async head - if ( dev_addr == 0 ) - { - p_ed->skip = 0; // only need to clear skip bit + if (dev_addr == 0) { + p_ed->w0.skip = 0; // only need to clear skip bit return true; } - ed_list_insert( p_ed_head[ep_desc->bmAttributes.xfer], p_ed ); + if (tu_edpt_number(ep_desc->bEndpointAddress) != 0) { + // Get an empty TD and use it as the end-of-list marker. + // This marker TD will be used when a transfer is made on this EP + // (and a new, empty TD will be allocated for the next-next transfer). + ohci_gtd_t* gtd = gtd_find_free(); + TU_ASSERT(gtd); + p_ed->td_head.address = (uint32_t)_phys_addr(gtd); + p_ed->td_tail = (uint32_t)_phys_addr(gtd); + } + ed_list_insert(p_ed_head[ep_desc->bmAttributes.xfer], p_ed); return true; } @@ -481,18 +471,20 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { return false; // TODO not implemented yet } -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { (void) rhport; - ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; + ohci_ed_t* ed = ed_control(dev_addr); ohci_gtd_t *qtd = &ohci_data.control[dev_addr].gtd; + hcd_dcache_clean(setup_packet, 8); + gtd_init(qtd, (uint8_t*)(uintptr_t) setup_packet, 8); qtd->index = dev_addr; qtd->pid = PID_SETUP; qtd->data_toggle = GTD_DT_DATA0; qtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + hcd_dcache_clean(qtd, sizeof(ohci_gtd_t)); //------------- Attach TDs list to Control Endpoint -------------// ed->td_head.address = (uint32_t) _phys_addr(qtd); @@ -509,36 +501,48 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - if ( epnum == 0 ) - { - ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; + // IN transfer: invalidate buffer, OUT transfer: clean buffer + if (dir) { + hcd_dcache_invalidate(buffer, buflen); + } else { + hcd_dcache_clean(buffer, buflen); + } + + ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); + if (epnum == 0) { ohci_gtd_t* gtd = &ohci_data.control[dev_addr].gtd; gtd_init(gtd, buffer, buflen); gtd->index = dev_addr; - gtd->pid = dir ? PID_IN : PID_OUT; - gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 + gtd->pid = dir ? PID_IN : PID_OUT; + gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + hcd_dcache_clean(gtd, sizeof(ohci_gtd_t)); - ed->td_head.address = (uint32_t) _phys_addr(gtd); + ed->td_head.address = (uint32_t)_phys_addr(gtd); OHCI_REG->command_status_bit.control_list_filled = 1; - }else - { - ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); - ohci_gtd_t* gtd = gtd_find_free(); - - TU_ASSERT(gtd); + } else { + tusb_xfer_type_t xfer_type = ed_get_xfer_type(ed->w0); + ohci_gtd_t* gtd = (ohci_gtd_t*)_virt_addr((void*)ed->td_tail); gtd_init(gtd, buffer, buflen); gtd->index = ed-ohci_data.ed_pool; gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - td_insert_to_ed(ed, gtd); + // Insert a new, empty TD at the tail, to be used by the next transfer + ohci_gtd_t* new_gtd = gtd_find_free(); + TU_ASSERT(new_gtd); - tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); - if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; + gtd->next = (uint32_t)_phys_addr(new_gtd); + hcd_dcache_clean(gtd, sizeof(ohci_gtd_t)); + + ed->td_tail = (uint32_t)_phys_addr(new_gtd); + + if (TUSB_XFER_BULK == xfer_type) { + OHCI_REG->command_status_bit.bulk_list_filled = 1; + } } return true; @@ -556,13 +560,14 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) rhport; ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); - p_ed->is_stalled = 0; - p_ed->td_tail &= 0x0Ful; // set tail pointer back to NULL + ohci_ed_word2_t td_head = p_ed->td_head; + td_head.toggle = 0; // reset data toggle + td_head.halted = 0; + p_ed->td_head = td_head; - p_ed->td_head.toggle = 0; // reset data toggle - p_ed->td_head.halted = 0; - - if ( TUSB_XFER_BULK == ed_get_xfer_type(p_ed) ) OHCI_REG->command_status_bit.bulk_list_filled = 1; + if (TUSB_XFER_BULK == ed_get_xfer_type(p_ed->w0)) { + OHCI_REG->command_status_bit.bulk_list_filled = 1; + } return true; } @@ -571,14 +576,18 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { //--------------------------------------------------------------------+ // OHCI Interrupt Handler //--------------------------------------------------------------------+ -static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) -{ - ohci_td_item_t* td_reverse_head = NULL; +TU_ATTR_ALWAYS_INLINE static inline bool is_itd(ohci_td_item_t* item) { + (void) item; + return false; // ISO not supported yet +} - while(td_head != NULL) - { +static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) { + ohci_td_item_t* td_reverse_head = NULL; + while(td_head != NULL) { td_head = _virt_addr(td_head); - uint32_t next = td_head->next; + const uint32_t item_size = is_itd(td_head) ? sizeof(ohci_itd_t) : sizeof(ohci_gtd_t); + hcd_dcache_invalidate(td_head, item_size); + const uint32_t next = td_head->next; // make current's item become reverse's first item td_head->next = (uint32_t) td_reverse_head; @@ -590,24 +599,22 @@ static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) return _virt_addr(td_reverse_head); } -static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) -{ +TU_ATTR_ALWAYS_INLINE static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) { return ((uint32_t) p_qtd) < ((uint32_t) ohci_data.gtd_pool); // check ohci_data_t for memory layout } -static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) -{ - if ( gtd_is_control(p_qtd) ) - { - return &ohci_data.control[p_qtd->index].ed; - }else - { - return &ohci_data.ed_pool[p_qtd->index]; +TU_ATTR_ALWAYS_INLINE static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const* const p_qtd) { + ohci_ed_t* ed; + if (gtd_is_control(p_qtd)) { + ed = &ohci_data.control[p_qtd->index].ed; + } else { + ed = &ohci_data.ed_pool[p_qtd->index]; } + return hcd_dcache_uncached(ed); } static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd) { - if ( gtd_is_control(gtd) ) { + if (gtd_is_control(gtd)) { uint8_t idx = ((uintptr_t)gtd - (uintptr_t)&ohci_data.control->gtd) / sizeof(ohci_data.control[0]); return &ohci_data.gtd_extra_control[idx]; }else { @@ -615,102 +622,77 @@ static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd) { } } -static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) { // 5.2.9 OHCI sample code - // CBP is 0 mean all data is transferred - if (current_buffer == 0) return 0; + if (current_buffer == 0) { + return 0; + } return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + - tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; + tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; } -static void done_queue_isr(uint8_t hostid) -{ - (void) hostid; +static void done_queue_isr(uint8_t hostid) { + (void)hostid; // done head is written in reversed order of completion --> need to reverse the done queue first - ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) tu_align16(ohci_data.hcca.done_head) ); + ohci_td_item_t* td_head = list_reverse((ohci_td_item_t*)tu_align16(ohci_data.hcca.done_head)); ohci_data.hcca.done_head = 0; - while( td_head != NULL ) - { + while (td_head != NULL) { // TODO check if td_head is iso td //------------- Non ISO transfer -------------// - ohci_gtd_t * const qtd = (ohci_gtd_t *) td_head; + ohci_gtd_t* const qtd = (ohci_gtd_t*) td_head; xfer_result_t const event = (qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : (qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; - qtd->used = 0; // free TD - if ( (qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) - { - ohci_ed_t * const ed = gtd_get_ed(qtd); - uint32_t const xferred_bytes = gtd_get_extra_data(qtd)->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer); - - // NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs. - // When there is a error resulting this ED is halted, and this EP still has other queued TD - // --> the Bulk list only has this halted EP queueing TDs (remaining) - // --> Bulk list will be considered as not empty by HC !!! while there is no attempt transaction on this list - // --> HC will not process Control list (due to service ratio when Bulk list not empty) - // To walk-around this, the halted ED will have TailP = HeadP (empty list condition), when clearing halt - // the TailP must be set back to NULL for processing remaining TDs - if (event != XFER_RESULT_SUCCESS) - { - ed->td_tail &= 0x0Ful; - ed->td_tail |= tu_align16(ed->td_head.address); // mark halted EP as empty queue - if ( event == XFER_RESULT_STALLED ) ed->is_stalled = 1; - } - - uint8_t dir = (ed->ep_number == 0) ? (qtd->pid == PID_IN) : (ed->pid == PID_IN); - - hcd_event_xfer_complete(ed->dev_addr, tu_edpt_addr(ed->ep_number, dir), xferred_bytes, event, true); + if ((qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS)) { + const ohci_ed_t* ed = gtd_get_ed(qtd); + const ohci_ed_word0_t ed_w0 = ed->w0; + const uint32_t xferred_bytes = gtd_get_extra_data(qtd)->expected_bytes - gtd_xfer_byte_left((uint32_t)qtd->buffer_end, (uint32_t)qtd->current_buffer_pointer); + uint8_t dir = (ed_w0.ep_number == 0) ? (qtd->pid == PID_IN) : (ed_w0.pid == PID_IN); + const uint8_t ep_addr = tu_edpt_addr(ed_w0.ep_number, dir); + hcd_event_xfer_complete(ed_w0.dev_addr, ep_addr, xferred_bytes, event, true); } - td_head = (ohci_td_item_t*) _virt_addr((void *)td_head->next); + td_head = (ohci_td_item_t*)_virt_addr((void*)td_head->next); } } void hcd_int_handler(uint8_t hostid, bool in_isr) { - (void) in_isr; - - uint32_t const int_en = OHCI_REG->interrupt_enable; + (void)in_isr; + uint32_t const int_en = OHCI_REG->interrupt_enable; uint32_t const int_status = OHCI_REG->interrupt_status & int_en; - if (int_status == 0) return; + if (int_status == 0) { + return; + } // Disable MIE as per OHCI spec 5.3 OHCI_REG->interrupt_disable = OHCI_INT_MASTER_ENABLE_MASK; // Frame number overflow - if ( int_status & OHCI_INT_FRAME_OVERFLOW_MASK ) - { + if (int_status & OHCI_INT_FRAME_OVERFLOW_MASK) { ohci_data.frame_number_hi++; } //------------- RootHub status -------------// - if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK ) - { - for (int i = 0; i < TUP_OHCI_RHPORTS; i++) - { + if (int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK) { + for (int i = 0; i < TUP_OHCI_RHPORTS; i++) { uint32_t const rhport_status = OHCI_REG->rhport_status[i] & RHPORT_ALL_CHANGE_MASK; - if ( rhport_status & RHPORT_CONNECT_STATUS_CHANGE_MASK ) - { + if (rhport_status & RHPORT_CONNECT_STATUS_CHANGE_MASK) { // TODO check if remote wake-up - if ( OHCI_REG->rhport_status_bit[i].current_connect_status ) - { + if (OHCI_REG->rhport_status_bit[i].current_connect_status) { // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) OHCI_REG->rhport_status[i] = RHPORT_PORT_RESET_STATUS_MASK; hcd_event_device_attach(i, true); - }else - { + } else { hcd_event_device_remove(i, true); } } - if ( rhport_status & RHPORT_PORT_SUSPEND_CHANGE_MASK) - { - + if (rhport_status & RHPORT_PORT_SUSPEND_CHANGE_MASK) { } OHCI_REG->rhport_status[i] = rhport_status; // acknowledge all interrupt @@ -718,13 +700,11 @@ void hcd_int_handler(uint8_t hostid, bool in_isr) { } //------------- Transfer Complete -------------// - if (int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) - { + if (int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) { done_queue_isr(hostid); } OHCI_REG->interrupt_status = int_status; // Acknowledge handled interrupt - OHCI_REG->interrupt_enable = OHCI_INT_MASTER_ENABLE_MASK; // Enable MIE } //--------------------------------------------------------------------+ diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 94bad5df7..d9ebe1d54 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_OHCI_H_ -#define _TUSB_OHCI_H_ +#ifndef TUSB_OHCI_H_ +#define TUSB_OHCI_H_ #ifdef __cplusplus extern "C" { @@ -48,6 +48,10 @@ enum { // tinyUSB's OHCI implementation caps number of EDs to 8 bits TU_VERIFY_STATIC (ED_MAX <= 256, "Reduce CFG_TUH_DEVICE_MAX or CFG_TUH_ENDPOINT_MAX"); +#define GTD_ALIGN_SIZE TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16) +#define ED_ALIGN_SIZE TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16) +#define ITD_ALIGN_SIZE TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 32) + //--------------------------------------------------------------------+ // OHCI Data Structure //--------------------------------------------------------------------+ @@ -61,18 +65,35 @@ typedef struct { TU_VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); +// An OHCI host controller is controlled using data structures placed in memory (RAM). +// It needs to both read and write these data structures (as defined by the OHCI specification), +// and this can be mentally conceptualized similar to two software threads running on +// two different CPUs. In order to prevent a _data race_ where data gets corrupted, +// the CPU and the OHCI host controller need to agree on how the memory should be accessed. +// In this driver, we do this by transferring logical ownership of transfer descriptors (TDs) +// between the CPU and the OHCI host controller. Only the device which holds the logical ownership +// is allowed to read or write the TD. This ownership is not visible anywhere in the code, +// but it instead must be inferred based on the logical state of the transfer. +// +// If dcache-supporting mode is enabled, we need to do additional manual cache operations +// in order to correctly transfer this logical ownership and prevent data corruption. +// In order to do this, we also choose to align each OHCI TD so that it doesn't +// share CPU cache lines with other TDs. This is because manual cache operations +// can only be performed on cache line granularity. In other words, one cache line is +// the _smallest_ amount that can be read/written at a time. If there were to be multiple TDs +// in the same cache line, they would be required to always have the same logical ownership. +// This ends up being impossible to guarantee, so we choose a design which avoids the situation entirely. + // common link item for gtd and itd for list travel -// use as pointer only typedef struct TU_ATTR_ALIGNED(16) { uint32_t reserved[2]; volatile uint32_t next; uint32_t reserved2; }ohci_td_item_t; -typedef struct TU_ATTR_ALIGNED(16) -{ - // Word 0 - uint32_t used : 1; +typedef struct TU_ATTR_ALIGNED(GTD_ALIGN_SIZE) { + // Word 0 + uint32_t used : 1; uint32_t index : 8; // endpoint index the gtd belongs to, or device address in case of control xfer uint32_t : 9; // can be used uint32_t buffer_rounding : 1; @@ -82,56 +103,55 @@ typedef struct TU_ATTR_ALIGNED(16) volatile uint32_t error_count : 2; volatile uint32_t condition_code : 4; - // Word 1 - uint8_t* volatile current_buffer_pointer; + // Word 1 + uint8_t* volatile current_buffer_pointer; - // Word 2 : next TD - volatile uint32_t next; + // Word 2 : next TD + volatile uint32_t next; - // Word 3 - uint8_t* buffer_end; + // Word 3 + uint8_t* buffer_end; } ohci_gtd_t; +TU_VERIFY_STATIC(sizeof(ohci_gtd_t) == GTD_ALIGN_SIZE, "size is not correct" ); -TU_VERIFY_STATIC( sizeof(ohci_gtd_t) == 16, "size is not correct" ); - -typedef struct TU_ATTR_ALIGNED(16) -{ - // Word 0 - uint32_t dev_addr : 7; - uint32_t ep_number : 4; - uint32_t pid : 2; - uint32_t speed : 1; - uint32_t skip : 1; - uint32_t is_iso : 1; - uint32_t max_packet_size : 11; - // HCD: make use of 5 reserved bits - uint32_t used : 1; - uint32_t is_interrupt_xfer : 1; - uint32_t is_stalled : 1; - uint32_t : 2; - - // Word 1 - uint32_t td_tail; +typedef union { + struct { + uint32_t dev_addr : 7; + uint32_t ep_number : 4; + uint32_t pid : 2; + uint32_t speed : 1; + uint32_t skip : 1; + uint32_t is_iso : 1; + uint32_t max_packet_size : 11; + // HCD: make use of 5 reserved bits + uint32_t used : 1; + uint32_t is_interrupt_xfer : 1; + uint32_t : 3; + }; + uint32_t value; +} ohci_ed_word0_t; +TU_VERIFY_STATIC(sizeof(ohci_ed_word0_t) == 4, "size is not correct" ); - // Word 2 - volatile union { - uint32_t address; - struct { - uint32_t halted : 1; - uint32_t toggle : 1; - uint32_t : 30; - }; - }td_head; +typedef union { + uint32_t address; + struct { + uint32_t halted : 1; + uint32_t toggle : 1; + uint32_t : 30; + }; +} ohci_ed_word2_t; +TU_VERIFY_STATIC(sizeof(ohci_ed_word2_t) == 4, "size is not correct" ); - // Word 3: next ED - uint32_t next; +typedef struct TU_ATTR_ALIGNED(ED_ALIGN_SIZE) { + ohci_ed_word0_t w0; // Word 0 + uint32_t td_tail; // Word 1 + volatile ohci_ed_word2_t td_head; // Word 2 + uint32_t next; // Word 3 } ohci_ed_t; +TU_VERIFY_STATIC(sizeof(ohci_ed_t) == ED_ALIGN_SIZE, "size is not correct" ); -TU_VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); - -typedef struct TU_ATTR_ALIGNED(32) -{ - /*---------- Word 1 ----------*/ +typedef struct TU_ATTR_ALIGNED(ITD_ALIGN_SIZE) { + /*---------- Word 1 ----------*/ uint32_t starting_frame : 16; uint32_t : 5; // can be used uint32_t delay_interrupt : 3; @@ -139,24 +159,25 @@ typedef struct TU_ATTR_ALIGNED(32) uint32_t : 1; // can be used volatile uint32_t condition_code : 4; - /*---------- Word 2 ----------*/ - uint32_t buffer_page0; // 12 lsb bits can be used - /*---------- Word 3 ----------*/ - volatile uint32_t next; + /*---------- Word 2 ----------*/ + uint32_t buffer_page0; // 12 lsb bits can be used - /*---------- Word 4 ----------*/ - uint32_t buffer_end; + /*---------- Word 3 ----------*/ + volatile uint32_t next; - /*---------- Word 5-8 ----------*/ - volatile uint16_t offset_packetstatus[8]; -} ochi_itd_t; + /*---------- Word 4 ----------*/ + uint32_t buffer_end; -TU_VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); + /*---------- Word 5-8 ----------*/ + volatile uint16_t offset_packetstatus[8]; +} ohci_itd_t; +TU_VERIFY_STATIC(sizeof(ohci_itd_t) == ITD_ALIGN_SIZE, "size is not correct" ); typedef struct { uint16_t expected_bytes; // up to 8192 bytes so max is 13 bits } gtd_extra_data_t; +TU_VERIFY_STATIC(sizeof(gtd_extra_data_t) == 2, "size is not correct" ); // structure with member alignment required from large to small typedef struct TU_ATTR_ALIGNED(256) { @@ -192,10 +213,10 @@ typedef struct TU_ATTR_ALIGNED(256) { //--------------------------------------------------------------------+ typedef volatile struct { - uint32_t revision; + uint32_t revision; // 0x00 union { - uint32_t control; + uint32_t control; // 0x04 struct { uint32_t control_bulk_service_ratio : 2; uint32_t periodic_list_enable : 1; @@ -211,7 +232,7 @@ typedef volatile struct }; union { - uint32_t command_status; + uint32_t command_status; // 0x08 struct { uint32_t controller_reset : 1; uint32_t control_list_filled : 1; @@ -222,26 +243,24 @@ typedef volatile struct }command_status_bit; }; - uint32_t interrupt_status; - uint32_t interrupt_enable; - uint32_t interrupt_disable; - - uint32_t hcca; - uint32_t period_current_ed; - uint32_t control_head_ed; - uint32_t control_current_ed; - uint32_t bulk_head_ed; - uint32_t bulk_current_ed; - uint32_t done_head; - - uint32_t frame_interval; - uint32_t frame_remaining; - uint32_t frame_number; - uint32_t periodic_start; - uint32_t lowspeed_threshold; + uint32_t interrupt_status; // 0x0C + uint32_t interrupt_enable; // 0x10 + uint32_t interrupt_disable; // 0x14 + uint32_t hcca; // 0x18 + uint32_t period_current_ed; // 0x1C + uint32_t control_head_ed; // 0x20 + uint32_t control_current_ed; // 0x24 + uint32_t bulk_head_ed; // 0x28 + uint32_t bulk_current_ed; // 0x2C + uint32_t done_head; // 0x30 + uint32_t frame_interval; // 0x34 + uint32_t frame_remaining; // 0x38 + uint32_t frame_number; // 0x3C + uint32_t periodic_start; // 0x40 + uint32_t lowspeed_threshold; // 0x44 union { - uint32_t rh_descriptorA; + uint32_t rh_descriptorA; // 0x48 struct { uint32_t number_downstream_ports : 8; uint32_t power_switching_mode : 1; @@ -255,7 +274,7 @@ typedef volatile struct }; union { - uint32_t rh_descriptorB; + uint32_t rh_descriptorB; // 0x4C struct { uint32_t device_removable : 16; uint32_t port_power_control_mask : 16; @@ -263,9 +282,9 @@ typedef volatile struct }; union { - uint32_t rh_status; + uint32_t rh_status; // 0x50 struct { - uint32_t local_power_status : 1; // read Local Power Status; write: Clear Global Power + uint32_t local_power_status : 1; // read Local Power Status; write: Clear Global Power uint32_t over_current_indicator : 1; uint32_t : 13; uint32_t device_remote_wakeup_enable : 1; @@ -277,7 +296,8 @@ typedef volatile struct }; union { - uint32_t rhport_status[TUP_OHCI_RHPORTS]; + uint32_t rhport_status[TUP_OHCI_RHPORTS]; // 0x54 + struct { uint32_t current_connect_status : 1; uint32_t port_enable_status : 1; @@ -304,4 +324,4 @@ TU_VERIFY_STATIC( sizeof(ohci_registers_t) == (0x54 + (4 * TUP_OHCI_RHPORTS)), " } #endif -#endif /* _TUSB_OHCI_H_ */ +#endif /* TUSB_OHCI_H_ */ diff --git a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c b/src/portable/ohci/ohci_nxp.h index fea3e2a66..9cba05e95 100644 --- a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c +++ b/src/portable/ohci/ohci_nxp.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019, Ha Thach (tinyusb.org) + * Copyright (c) 2025 Ha Thach (tinyusb.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,26 +23,48 @@ * * This file is part of the TinyUSB stack. */ +#ifndef TUSB_OHCI_NXP_H +#define TUSB_OHCI_NXP_H -#include "tusb_option.h" - -#if CFG_TUH_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) +#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) #include "chip.h" -#include "host/hcd.h" -#include "host/usbh.h" +#define OHCI_REG ((ohci_registers_t *) LPC_USB_BASE) -void hcd_int_enable(uint8_t rhport) -{ - (void) rhport; +void hcd_int_enable(uint8_t rhport) { + (void)rhport; NVIC_EnableIRQ(USB_IRQn); } -void hcd_int_disable(uint8_t rhport) -{ - (void) rhport; +void hcd_int_disable(uint8_t rhport) { + (void)rhport; NVIC_DisableIRQ(USB_IRQn); } +static void ohci_phy_init(uint8_t rhport) { + (void) rhport; +} + +#else + +#include "fsl_device_registers.h" + +// for LPC55 USB0 controller +#define OHCI_REG ((ohci_registers_t *) USBFSH_BASE) + +static void ohci_phy_init(uint8_t rhport) { + (void) rhport; +} + +void hcd_int_enable(uint8_t rhport) { + (void)rhport; + NVIC_EnableIRQ(USB0_IRQn); +} + +void hcd_int_disable(uint8_t rhport) { + (void)rhport; + NVIC_DisableIRQ(USB0_IRQn); +} +#endif + #endif diff --git a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c index d59a2b4ee..90eb920e0 100644 --- a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c +++ b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c @@ -29,9 +29,20 @@ #if CFG_TUH_ENABLED && (CFG_TUSB_MCU == OPT_MCU_RP2040) && CFG_TUH_RPI_PIO_USB #include "pico.h" + #include "pio_usb.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + #include "pio_usb_ll.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ diff --git a/src/portable/renesas/rusb2/rusb2_type.h b/src/portable/renesas/rusb2/rusb2_type.h index dd88f66a7..71837d03c 100644 --- a/src/portable/renesas/rusb2/rusb2_type.h +++ b/src/portable/renesas/rusb2/rusb2_type.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_RUSB2_TYPE_H_ -#define _TUSB_RUSB2_TYPE_H_ +#ifndef TUSB_RUSB2_TYPE_H_ +#define TUSB_RUSB2_TYPE_H_ #include <stdint.h> #include <stddef.h> @@ -1777,4 +1777,4 @@ TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DPUSR1R_FS ) == 0x0404, "incorrect offset } #endif -#endif /* _TUSB_RUSB2_TYPE_H_ */ +#endif /* TUSB_RUSB2_TYPE_H_ */ diff --git a/src/portable/sunxi/musb_def.h b/src/portable/sunxi/musb_def.h index 53da5ded2..ce9b89d55 100644 --- a/src/portable/sunxi/musb_def.h +++ b/src/portable/sunxi/musb_def.h @@ -26,8 +26,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MUSB_DEF -#define _TUSB_MUSB_DEF +#ifndef TUSB_MUSB_DEF +#define TUSB_MUSB_DEF #define USBC_Readb(reg) (*(volatile unsigned char *)(reg)) diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h index e5824606a..df6d4a852 100644 --- a/src/portable/synopsys/dwc2/dwc2_bcm.h +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DWC2_BCM_H_ -#define _TUSB_DWC2_BCM_H_ +#ifndef TUSB_DWC2_BCM_H_ +#define TUSB_DWC2_BCM_H_ #ifdef __cplusplus extern "C" { diff --git a/src/portable/valentyusb/eptri/dcd_eptri.h b/src/portable/valentyusb/eptri/dcd_eptri.h index d67635d7c..2fe74a712 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.h +++ b/src/portable/valentyusb/eptri/dcd_eptri.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DCD_VALENTYUSB_EPTRI_H_ -#define _TUSB_DCD_VALENTYUSB_EPTRI_H_ +#ifndef TUSB_DCD_VALENTYUSB_EPTRI_H_ +#define TUSB_DCD_VALENTYUSB_EPTRI_H_ #include "common/tusb_common.h" #ifdef __cplusplus @@ -36,4 +36,4 @@ } #endif -#endif /* _TUSB_DCD_VALENTYUSB_EPTRI_H_ */ +#endif /* TUSB_DCD_VALENTYUSB_EPTRI_H_ */ |
