diff --git a/osal/usb_osal_rtems.c b/osal/usb_osal_rtems.c new file mode 100644 index 00000000..701e4b7e --- /dev/null +++ b/osal/usb_osal_rtems.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2022, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifdef __rtems__ + +#include "usb_osal.h" +#include "usb_errno.h" +#include + +#define SYS_USB_MBOX_SIZE (sizeof(void *)) + +usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args) +{ + rtems_id id = 0; + rtems_status_code res; + + res = rtems_task_create( + rtems_build_name(name[0], name[1], name[2], name[3]), + prio, + stack_size, + RTEMS_PREEMPT, + 0, + &id); + + if (res != RTEMS_SUCCESSFUL) { + return NULL; + } + + res = rtems_task_start(id, (rtems_task_entry)entry, (rtems_task_argument)args); + + if (res != RTEMS_SUCCESSFUL) { + rtems_task_delete(id); + return NULL; + } + + return (usb_osal_thread_t)id; +} + +void usb_osal_thread_delete(usb_osal_thread_t thread) +{ + rtems_task_delete(thread); +} + +usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count) +{ + rtems_id semaphore = 0; + rtems_status_code ret = rtems_semaphore_create( + rtems_build_name('U', 'S', 'B', 's'), + initial_count, + RTEMS_COUNTING_SEMAPHORE, + 0, + &semaphore); + + return semaphore; +} + +void usb_osal_sem_delete(usb_osal_sem_t sem) +{ + rtems_semaphore_delete(sem); +} + +int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout) +{ + rtems_status_code status; + status = rtems_semaphore_obtain(sem, RTEMS_WAIT, timeout); + return status == RTEMS_SUCCESSFUL ? 0 : -USB_ERR_TIMEOUT; +} + +int usb_osal_sem_give(usb_osal_sem_t sem) +{ + rtems_status_code status = rtems_semaphore_release(sem); + + return (status == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT; +} + +usb_osal_mutex_t usb_osal_mutex_create(void) +{ + rtems_id mutex; + rtems_status_code ret = rtems_semaphore_create( + rtems_build_name('U', 'S', 'B', 'm'), + 1, + RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_LOCAL, + 0, + &mutex); + + return mutex; +} + +void usb_osal_mutex_delete(usb_osal_mutex_t mutex) +{ + rtems_semaphore_delete(mutex); +} + +int usb_osal_mutex_take(usb_osal_mutex_t mutex) +{ + return (rtems_semaphore_obtain(mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT) == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT; +} + +int usb_osal_mutex_give(usb_osal_mutex_t mutex) +{ + return (rtems_semaphore_release(mutex) == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT; +} + +usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs) +{ + rtems_status_code ret; + rtems_id mailbox = 0; + ret = rtems_message_queue_create( + rtems_build_name('U', 'S', 'B', 'q'), + max_msgs, + SYS_USB_MBOX_SIZE, + RTEMS_DEFAULT_ATTRIBUTES, + &mailbox); + return mailbox; +} + +int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr) +{ + rtems_status_code ret; + ret = rtems_message_queue_send(mq, &addr, SYS_USB_MBOX_SIZE); + return (ret == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT; +} + +int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout) +{ + size_t size; + rtems_status_code sc; + sc = rtems_message_queue_receive( + mq, + addr, + &size, + RTEMS_WAIT, + timeout); + return (sc == RTEMS_SUCCESSFUL) ? 0 : -USB_ERR_TIMEOUT; +} + +uint32_t usb_osal_enter_critical_section(void) +{ + rtems_interrupt_level pval; + +#if RTEMS_SMP + rtems_recursive_mutex_lock(&sys_arch_lock); +#else + rtems_interrupt_disable(pval); +#endif + return pval; +} + +void usb_osal_leave_critical_section(size_t flag) +{ +#if RTEMS_SMP + rtems_recursive_mutex_unlock(&sys_arch_lock); +#else + rtems_interrupt_enable(flag); +#endif +} + +void usb_osal_msleep(uint32_t delay) +{ + rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(delay)); +} + +#endif \ No newline at end of file diff --git a/port/ehci/README.md b/port/ehci/README.md index b5a87d2a..bccb2bc0 100644 --- a/port/ehci/README.md +++ b/port/ehci/README.md @@ -18,6 +18,14 @@ - Nuvoton all series +### Artinchip + +- d13x, d21x + +### Intel + +Intel 6 Series Chipset and Intel C200 Series Chipset + ## Before Use Your should implement `usb_hc_low_level_init`. diff --git a/port/ehci/usb_glue_aic.c b/port/ehci/usb_glue_aic.c new file mode 100644 index 00000000..dde38929 --- /dev/null +++ b/port/ehci/usb_glue_aic.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022, Artinchip Technology Co., Ltd + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "usbh_core.h" +#include "usb_ehci_priv.h" + +extern void USBH_IRQHandler(void); + +void usb_hc_low_level_init(void) +{ + uint32_t val; + + /* set usb0 phy switch: Host/Device */ +#ifdef AIC_USING_USB0_HOST + syscfg_usb_phy0_sw_host(1); +#endif + + /* set phy type: UTMI/ULPI */ + val = readl((volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x800)); +#ifdef FPGA_BOARD_ARTINCHIP + /* fpga phy type = ULPI */ + writel((val & ~0x1U), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x800)); +#else + /* board phy type = UTMI */ + writel((val | 0x1), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x800)); +#endif + +#if 0 + /* Set AHB2STBUS_INSREG01 + Set EHCI packet buffer IN/OUT threshold (in DWORDs) + Must increase the OUT threshold to avoid underrun. (FIFO size - 4) + */ +#ifdef FPGA_BOARD_ARTINCHIP + writel((32 | (127 << 16)), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x94)); +#else + writel((32 | (32 << 16)), (volatile void *)(unsigned long)(CONFIG_USB_EHCI_HCCR_BASE+0x94)); +#endif +#endif + + /* enable clock */ + hal_clk_enable(CONFIG_USB_EHCI_PHY_CLK); + hal_clk_enable(CONFIG_USB_EHCI_CLK); + aicos_udelay(300); + hal_reset_assert(CONFIG_USB_EHCI_PHY_RESET); + hal_reset_assert(CONFIG_USB_EHCI_RESET); + aicos_udelay(300); + hal_reset_deassert(CONFIG_USB_EHCI_PHY_RESET); + hal_reset_deassert(CONFIG_USB_EHCI_RESET); + aicos_udelay(300); + + /* register interrupt callback */ + aicos_request_irq(CONFIG_USB_EHCI_IRQ_NUM, (irq_handler_t)USBH_IRQHandler, + 0, "usb_host_ehci", NULL); + aicos_irq_enable(CONFIG_USB_EHCI_IRQ_NUM); +} + +uint8_t usbh_get_port_speed(const uint8_t port) +{ + /* Defined by individual manufacturers */ + uint32_t regval; + + regval = EHCI_HCOR->portsc[port-1]; + if ((regval & EHCI_PORTSC_LSTATUS_MASK) == EHCI_PORTSC_LSTATUS_KSTATE) + return USB_SPEED_LOW; + + if (regval & EHCI_PORTSC_PE) + return USB_SPEED_HIGH; + else + return USB_SPEED_FULL; +} + +void usb_ehci_dcache_clean(uintptr_t addr, uint32_t len) +{ + aicos_dcache_clean_range((size_t *)addr, len); +} + +void usb_ehci_dcache_invalidate(uintptr_t addr, uint32_t len) +{ + aicos_dcache_invalid_range((size_t *)addr, len); +} + +void usb_ehci_dcache_clean_invalidate(uintptr_t addr, uint32_t len) +{ + aicos_dcache_clean_invalid_range((size_t *)addr, len); +} diff --git a/port/ehci/usb_glue_intel.c b/port/ehci/usb_glue_intel.c new file mode 100644 index 00000000..b2264b15 --- /dev/null +++ b/port/ehci/usb_glue_intel.c @@ -0,0 +1,55 @@ +#ifdef __rtems__ + +#include +#include +#include +#include "usbh_core.h" + +uint32_t echi_base; +static int ehci_bus; +static int ehci_slot; +static int ehci_function; +static int ehci_vector; + +extern void USBH_IRQHandler(void *para); + +void ehci_pci_scan(int bus, int slot, int fun, int vector) +{ + ehci_bus = bus; + ehci_slot = slot; + ehci_function = fun; + ehci_vector = vector; + pci_read_config_dword(bus, slot, fun, PCI_BASE_ADDRESS_0, &echi_base); +} +void usb_hc_low_level_init(void) +{ + //set software own ehci + uint32_t legacy_val; + pci_write_config_dword(ehci_bus, ehci_slot, ehci_function, 0x68, 1 << 24); + pci_read_config_dword(ehci_bus, ehci_slot, ehci_function, 0x68, &legacy_val); + if ((legacy_val & 0x01010000) == 0x01000000) + printf("OS owned echi\n"); + else + printf("BIOS owned echi\n"); + + rtems_status_code sc; + sc = rtems_interrupt_handler_install( + ehci_vector, + "USBirq", + RTEMS_INTERRUPT_SHARED, + USBH_IRQHandler, + (void *)0); + + if (sc != RTEMS_SUCCESSFUL) { + printf("USB install isr falied,%s\n", rtems_status_text(sc)); + return; + } +} + +uint8_t usbh_get_port_speed(const uint8_t port) +{ + printf("USB_SPEED_HIGH present\n"); + return USB_SPEED_HIGH; +} + +#endif \ No newline at end of file