KT24-1110_65E-HA-651B/apps/common/usb/usb_config.c
2024-11-10 18:44:17 +08:00

345 lines
8.6 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "usb_config.h"
#include "usb/scsi.h"
#include "irq.h"
#include "init.h"
#include "gpio.h"
#include "timer.h"
#include "app_config.h"
#include "lbuf.h"
#ifdef CONFIG_ADAPTER_ENABLE
#include "adapter_usb_hid.h"
#endif//CONFIG_ADAPTER_ENABLE
#define LOG_TAG_CONST USB
#define LOG_TAG "[USB]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#define SET_INTERRUPT ___interrupt
#define MAX_EP_TX 5
#define MAX_EP_RX 5
static usb_interrupt usb_interrupt_tx[USB_MAX_HW_NUM][MAX_EP_TX];// SEC(.usb_g_bss);
static usb_interrupt usb_interrupt_rx[USB_MAX_HW_NUM][MAX_EP_RX];// SEC(.usb_h_bss);
static u8 ep0_dma_buffer[EP0_SETUP_LEN] __attribute__((aligned(4))) SEC(.usb_ep0) ;
#if TCFG_USB_SLAVE_MSD_ENABLE
#define MSD_DMA_SIZE (64*2)
#else
#define MSD_DMA_SIZE 0
#endif
#if TCFG_USB_SLAVE_HID_ENABLE
#define HID_DMA_SIZE 64
#else
#define HID_DMA_SIZE 0
#endif
#if TCFG_USB_SLAVE_AUDIO_ENABLE
#define AUDIO_DMA_SIZE 256+192
#else
#define AUDIO_DMA_SIZE 0
#endif
#if TCFG_USB_SLAVE_CDC_ENABLE
#if CDC_INTR_EP_ENABLE
#define CDC_DMA_SIZE (64 + 64 + 64*2)
#else
#define CDC_DMA_SIZE (64 + 64*2)
#endif
#else
#define CDC_DMA_SIZE 0
#endif
struct usb_config_var_t {
u8 usb_setup_buffer[USB_SETUP_SIZE];
struct usb_ep_addr_t usb_ep_addr;
struct usb_setup_t usb_setup;
};
static struct usb_config_var_t *usb_config_var = {NULL};
#if USB_MALLOC_ENABLE
#else
static struct usb_config_var_t _usb_config_var SEC(.usb_config_var);
#endif
#define USB_DMA_BUF_ALIGN (8)
#ifndef USB_DMA_BUF_MAX_SIZE
#define USB_DMA_BUF_MAX_SIZE (HID_DMA_SIZE +USB_DMA_BUF_ALIGN+ AUDIO_DMA_SIZE +USB_DMA_BUF_ALIGN+ MSD_DMA_SIZE + USB_DMA_BUF_ALIGN + 100)
#endif//USB_DMA_BUF_MAX_SIZE
static u8 usb_dma_buf[USB_DMA_BUF_MAX_SIZE] SEC(.usb_msd_dma) __attribute__((aligned(8)));
static u8 cdc_dma_buffer[CDC_DMA_SIZE] __attribute__((aligned(8))) SEC(.usb_cdc_dma);
struct lbuff_head *usb_dma_lbuf = NULL;
void usb_memory_init()
{
usb_dma_lbuf = lbuf_init(usb_dma_buf, sizeof(usb_dma_buf), USB_DMA_BUF_ALIGN, 0);
log_info("%s() total dma size %x @%x", __func__, sizeof(usb_dma_buf), usb_dma_buf);
}
__attribute__((always_inline_when_const_args))
void *usb_alloc_ep_dmabuffer(const usb_dev usb_id, u32 ep, u32 dma_size)
{
u8 *ep_buffer = NULL;
u32 _ep = ep & 0xf;
if (ep & USB_DIR_IN) {
switch (_ep) {
case 0:
ep_buffer = ep0_dma_buffer;
break;
case CDC_DATA_EP_IN:
ep_buffer = cdc_dma_buffer + MAXP_SIZE_CDC_BULKIN * 2;
break;
default :
ep_buffer = lbuf_alloc(usb_dma_lbuf, dma_size);
break;
}
} else {
switch (_ep) {
case 0:
ep_buffer = ep0_dma_buffer;
break;
case CDC_DATA_EP_OUT:
ep_buffer = cdc_dma_buffer;
break;
default :
ep_buffer = lbuf_alloc(usb_dma_lbuf, dma_size);
break;
}
}
ASSERT(ep_buffer, "usb_alloc_ep_dmabuffer ep_buffer = NULL!!!, _ep = %x, dma_size = %d\n", ep, dma_size);
log_info("ep_buffer = %x, ep = %x, dma_size = %d\n", ep_buffer, ep, dma_size);
return ep_buffer;
}
static void usb_resume_sign(void *priv)
{
usb_dev usb_id = usb_device2id(priv);
u32 reg = usb_read_power(usb_id);
usb_write_power(usb_id, reg | BIT(2));//send resume
os_time_dly(2);//10ms~20ms
usb_write_power(usb_id, reg);//clean resume
}
void usb_remote_wakeup(const usb_dev usb_id)
{
struct usb_device_t *usb_device = usb_id2device(usb_id);
if (usb_device->bRemoteWakup) {
sys_timeout_add(usb_device, usb_resume_sign, 1);
}
}
void usb_phy_resume(const usb_dev usb_id)
{
usb_iomode(0);
struct usb_device_t *usb_device = usb_id2device(usb_id);
usb_write_faddr(usb_id, usb_device->baddr);
if (usb_device->baddr == 0) {
usb_device->bDeviceStates = USB_DEFAULT;
} else {
usb_device->bDeviceStates = USB_CONFIGURED;
}
usb_otg_resume(usb_id);
}
void usb_phy_suspend(const usb_dev usb_id)
{
gpio_set_pull_up(IO_PORT_DP, 1);
gpio_set_pull_down(IO_PORT_DP, 0);
gpio_set_direction(IO_PORT_DP, 1);
usb_iomode(1);
/* musb_read_usb(0, MUSB_INTRUSB); */
usb_otg_suspend(usb_id, OTG_KEEP_STATE);
}
void usb_isr(const usb_dev usb_id)
{
u32 intr_usb, intr_usbe;
u32 intr_tx, intr_txe;
u32 intr_rx, intr_rxe;
__asm__ volatile("ssync");
usb_read_intr(usb_id, &intr_usb, &intr_tx, &intr_rx);
usb_read_intre(usb_id, &intr_usbe, &intr_txe, &intr_rxe);
struct usb_device_t *usb_device = usb_id2device(usb_id);
intr_usb &= intr_usbe;
intr_tx &= intr_txe;
intr_rx &= intr_rxe;
if (intr_usb & INTRUSB_SUSPEND) {
log_error("usb suspend");
#if USB_SUSPEND_RESUME
usb_phy_suspend(usb_id);
#endif
}
if (intr_usb & INTRUSB_RESET_BABBLE) {
log_error("usb reset");
usb_reset_interface(usb_device);
#if USB_SUSPEND_RESUME
u32 reg = usb_read_power(usb_id);
usb_write_power(usb_id, (reg | INTRUSB_SUSPEND | INTRUSB_RESUME));//enable suspend resume
#endif
}
if (intr_usb & INTRUSB_RESUME) {
log_error("usb resume");
#if USB_SUSPEND_RESUME
usb_phy_resume(usb_id);
#endif
}
if (intr_tx & BIT(0)) {
if (usb_interrupt_rx[usb_id][0]) {
usb_interrupt_rx[usb_id][0](usb_device, 0);
} else {
usb_control_transfer(usb_device);
}
}
for (int i = 1; i < MAX_EP_TX; i++) {
if (intr_tx & BIT(i)) {
if (usb_interrupt_tx[usb_id][i]) {
usb_interrupt_tx[usb_id][i](usb_device, i);
}
}
}
for (int i = 1; i < MAX_EP_RX; i++) {
if (intr_rx & BIT(i)) {
if (usb_interrupt_rx[usb_id][i]) {
usb_interrupt_rx[usb_id][i](usb_device, i);
}
}
}
__asm__ volatile("csync");
}
void usb_sof_isr(const usb_dev usb_id)
{
usb_sof_clr_pnd(usb_id);
static u32 sof_count = 0;
if ((sof_count++ % 1000) == 0) {
log_d("sof 1s isr frame:%d", usb_read_sofframe(usb_id));
}
}
void usb_suspend_check(void *p)
{
usb_dev usb_id = (usb_dev)p;
static u16 sof_frame = 0;
u16 frame = usb_read_sofframe(usb_id);// sof frame 不更新则usb进入断开或者suspend状态
if (frame == sof_frame) {
usb_phy_suspend(usb_id);
}
sof_frame = frame;
}
SET_INTERRUPT
void usb0_g_isr()
{
usb_isr(0);
}
SET_INTERRUPT
void usb0_sof_isr()
{
usb_sof_isr(0);
}
#if USB_MAX_HW_NUM == 2
SET_INTERRUPT
void usb1_g_isr()
{
usb_isr(1);
}
SET_INTERRUPT
void usb1_sof_isr()
{
usb_sof_isr(1);
}
#endif
__attribute__((always_inline_when_const_args))
u32 usb_g_set_intr_hander(const usb_dev usb_id, u32 ep, usb_interrupt hander)
{
if (ep & USB_DIR_IN) {
usb_interrupt_tx[usb_id][ep & 0xf] = hander;
} else {
usb_interrupt_rx[usb_id][ep] = hander;
}
return 0;
}
void usb_g_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id)
{
if (usb_id == 0) {
request_irq(IRQ_USB_CTRL_IDX, priority, usb0_g_isr, cpu_id);
} else {
#if USB_MAX_HW_NUM == 2
request_irq(IRQ_USB1_CTRL_IDX, priority, usb1_g_isr, cpu_id);
#endif
}
}
void usb_sof_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id)
{
if (usb_id == 0) {
request_irq(IRQ_USB_SOF_IDX, priority, usb0_sof_isr, cpu_id);
} else {
#if USB_MAX_HW_NUM == 2
request_irq(IRQ_USB1_SOF_IDX, priority, usb1_sof_isr, cpu_id);
#endif
}
}
u32 usb_config(const usb_dev usb_id)
{
memset(usb_interrupt_rx[usb_id], 0, sizeof(usb_interrupt_rx[usb_id]));
memset(usb_interrupt_tx[usb_id], 0, sizeof(usb_interrupt_tx[usb_id]));
if (!usb_config_var) {
#if USB_MALLOC_ENABLE
usb_config_var = (struct usb_config_var_t *)zalloc(sizeof(struct usb_config_var_t));
if (!usb_config_var) {
return -1;
}
#else
memset(&_usb_config_var, 0, sizeof(_usb_config_var));
usb_config_var = &_usb_config_var;
#endif
}
log_debug("zalloc: usb_config_var = %x\n", usb_config_var);
usb_var_init(usb_id, &(usb_config_var->usb_ep_addr));
usb_setup_init(usb_id, &(usb_config_var->usb_setup), usb_config_var->usb_setup_buffer);
return 0;
}
u32 usb_release(const usb_dev usb_id)
{
log_debug("free zalloc: usb_config_var = %x\n", usb_id, usb_config_var);
usb_var_init(usb_id, NULL);
usb_setup_init(usb_id, NULL, NULL);
#if USB_MALLOC_ENABLE
if (usb_config_var) {
log_debug("free: usb_config_var = %x\n", usb_config_var);
free(usb_config_var);
}
#endif
usb_config_var = NULL;
return 0;
}