first commit for chrg
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
# Note
|
||||
|
||||
## Support Chip List
|
||||
|
||||
### Eastsoft
|
||||
|
||||
- ES32F3xx
|
||||
|
||||
### TI
|
||||
|
||||
- MSP432E4x
|
||||
|
||||
### Bekencorp
|
||||
|
||||
- BK7256/BK7258
|
||||
|
||||
### AllwinnerTech
|
||||
|
||||
- F1Cxxx, F2Cxxx
|
||||
|
||||
### SIFLI
|
||||
|
||||
- SF325X
|
||||
@@ -0,0 +1,898 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usb_musb_reg.h"
|
||||
|
||||
#define HWREG(x) \
|
||||
(*((volatile uint32_t *)(x)))
|
||||
#define HWREGH(x) \
|
||||
(*((volatile uint16_t *)(x)))
|
||||
#define HWREGB(x) \
|
||||
(*((volatile uint8_t *)(x)))
|
||||
|
||||
#define USB_BASE (g_usbdev_bus[0].reg_base)
|
||||
|
||||
#if defined(CONFIG_USB_MUSB_SUNXI)
|
||||
#define MUSB_FADDR_OFFSET 0x98
|
||||
#define MUSB_POWER_OFFSET 0x40
|
||||
#define MUSB_TXIS_OFFSET 0x44
|
||||
#define MUSB_RXIS_OFFSET 0x46
|
||||
#define MUSB_TXIE_OFFSET 0x48
|
||||
#define MUSB_RXIE_OFFSET 0x4A
|
||||
#define MUSB_IS_OFFSET 0x4C
|
||||
#define MUSB_IE_OFFSET 0x50
|
||||
#define MUSB_EPIDX_OFFSET 0x42
|
||||
|
||||
#define MUSB_IND_TXMAP_OFFSET 0x80
|
||||
#define MUSB_IND_TXCSRL_OFFSET 0x82
|
||||
#define MUSB_IND_TXCSRH_OFFSET 0x83
|
||||
#define MUSB_IND_RXMAP_OFFSET 0x84
|
||||
#define MUSB_IND_RXCSRL_OFFSET 0x86
|
||||
#define MUSB_IND_RXCSRH_OFFSET 0x87
|
||||
#define MUSB_IND_RXCOUNT_OFFSET 0x88
|
||||
#define MUSB_IND_TXTYPE_OFFSET 0x8C
|
||||
#define MUSB_IND_TXINTERVAL_OFFSET 0x8D
|
||||
#define MUSB_IND_RXTYPE_OFFSET 0x8E
|
||||
#define MUSB_IND_RXINTERVAL_OFFSET 0x8F
|
||||
|
||||
#define MUSB_FIFO_OFFSET 0x00
|
||||
|
||||
#define MUSB_DEVCTL_OFFSET 0x41
|
||||
|
||||
#define MUSB_TXFIFOSZ_OFFSET 0x90
|
||||
#define MUSB_RXFIFOSZ_OFFSET 0x94
|
||||
#define MUSB_TXFIFOADD_OFFSET 0x92
|
||||
#define MUSB_RXFIFOADD_OFFSET 0x96
|
||||
|
||||
#define MUSB_TXFUNCADDR0_OFFSET 0x98
|
||||
#define MUSB_TXHUBADDR0_OFFSET 0x9A
|
||||
#define MUSB_TXHUBPORT0_OFFSET 0x9B
|
||||
#define MUSB_TXFUNCADDRx_OFFSET 0x98
|
||||
#define MUSB_TXHUBADDRx_OFFSET 0x9A
|
||||
#define MUSB_TXHUBPORTx_OFFSET 0x9B
|
||||
#define MUSB_RXFUNCADDRx_OFFSET 0x9C
|
||||
#define MUSB_RXHUBADDRx_OFFSET 0x9E
|
||||
#define MUSB_RXHUBPORTx_OFFSET 0x9F
|
||||
|
||||
#define USB_TXMAP_BASE(ep_idx) (USB_BASE + MUSB_IND_TXMAP_OFFSET)
|
||||
#define USB_TXCSRL_BASE(ep_idx) (USB_BASE + MUSB_IND_TXCSRL_OFFSET)
|
||||
#define USB_TXCSRH_BASE(ep_idx) (USB_BASE + MUSB_IND_TXCSRH_OFFSET)
|
||||
#define USB_RXMAP_BASE(ep_idx) (USB_BASE + MUSB_IND_RXMAP_OFFSET)
|
||||
#define USB_RXCSRL_BASE(ep_idx) (USB_BASE + MUSB_IND_RXCSRL_OFFSET)
|
||||
#define USB_RXCSRH_BASE(ep_idx) (USB_BASE + MUSB_IND_RXCSRH_OFFSET)
|
||||
#define USB_RXCOUNT_BASE(ep_idx) (USB_BASE + MUSB_IND_RXCOUNT_OFFSET)
|
||||
#define USB_TXTYPE_BASE(ep_idx) (USB_BASE + MUSB_IND_TXTYPE_OFFSET)
|
||||
#define USB_TXINTERVAL_BASE(ep_idx) (USB_BASE + MUSB_IND_TXINTERVAL_OFFSET)
|
||||
#define USB_RXTYPE_BASE(ep_idx) (USB_BASE + MUSB_IND_RXTYPE_OFFSET)
|
||||
#define USB_RXINTERVAL_BASE(ep_idx) (USB_BASE + MUSB_IND_RXINTERVAL_OFFSET)
|
||||
|
||||
#define USB_TXADDR_BASE(ep_idx) (USB_BASE + MUSB_TXFUNCADDRx_OFFSET)
|
||||
#define USB_TXHUBADDR_BASE(ep_idx) (USB_BASE + MUSB_TXHUBADDRx_OFFSET)
|
||||
#define USB_TXHUBPORT_BASE(ep_idx) (USB_BASE + MUSB_TXHUBPORTx_OFFSET)
|
||||
#define USB_RXADDR_BASE(ep_idx) (USB_BASE + MUSB_RXFUNCADDRx_OFFSET)
|
||||
#define USB_RXHUBADDR_BASE(ep_idx) (USB_BASE + MUSB_RXHUBADDRx_OFFSET)
|
||||
#define USB_RXHUBPORT_BASE(ep_idx) (USB_BASE + MUSB_RXHUBPORTx_OFFSET)
|
||||
|
||||
#elif defined(CONFIG_USB_MUSB_CUSTOM)
|
||||
#include "musb_custom.h"
|
||||
#else
|
||||
#define MUSB_FADDR_OFFSET 0x00
|
||||
#define MUSB_POWER_OFFSET 0x01
|
||||
#define MUSB_TXIS_OFFSET 0x02
|
||||
#define MUSB_RXIS_OFFSET 0x04
|
||||
#define MUSB_TXIE_OFFSET 0x06
|
||||
#define MUSB_RXIE_OFFSET 0x08
|
||||
#define MUSB_IS_OFFSET 0x0A
|
||||
#define MUSB_IE_OFFSET 0x0B
|
||||
|
||||
#define MUSB_EPIDX_OFFSET 0x0E
|
||||
|
||||
#define MUSB_IND_TXMAP_OFFSET 0x10
|
||||
#define MUSB_IND_TXCSRL_OFFSET 0x12
|
||||
#define MUSB_IND_TXCSRH_OFFSET 0x13
|
||||
#define MUSB_IND_RXMAP_OFFSET 0x14
|
||||
#define MUSB_IND_RXCSRL_OFFSET 0x16
|
||||
#define MUSB_IND_RXCSRH_OFFSET 0x17
|
||||
#define MUSB_IND_RXCOUNT_OFFSET 0x18
|
||||
#define MUSB_IND_TXTYPE_OFFSET 0x1A
|
||||
#define MUSB_IND_TXINTERVAL_OFFSET 0x1B
|
||||
#define MUSB_IND_RXTYPE_OFFSET 0x1C
|
||||
#define MUSB_IND_RXINTERVAL_OFFSET 0x1D
|
||||
|
||||
#define MUSB_FIFO_OFFSET 0x20
|
||||
|
||||
#define MUSB_DEVCTL_OFFSET 0x60
|
||||
|
||||
#define MUSB_TXFIFOSZ_OFFSET 0x62
|
||||
#define MUSB_RXFIFOSZ_OFFSET 0x63
|
||||
#define MUSB_TXFIFOADD_OFFSET 0x64
|
||||
#define MUSB_RXFIFOADD_OFFSET 0x66
|
||||
|
||||
#define MUSB_TXFUNCADDR0_OFFSET 0x80
|
||||
#define MUSB_TXHUBADDR0_OFFSET 0x82
|
||||
#define MUSB_TXHUBPORT0_OFFSET 0x83
|
||||
#define MUSB_TXFUNCADDRx_OFFSET 0x88
|
||||
#define MUSB_TXHUBADDRx_OFFSET 0x8A
|
||||
#define MUSB_TXHUBPORTx_OFFSET 0x8B
|
||||
#define MUSB_RXFUNCADDRx_OFFSET 0x8C
|
||||
#define MUSB_RXHUBADDRx_OFFSET 0x8E
|
||||
#define MUSB_RXHUBPORTx_OFFSET 0x8F
|
||||
|
||||
#define MUSB_TXMAP0_OFFSET 0x100
|
||||
|
||||
// do not use EPIDX
|
||||
#define USB_TXMAP_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx)
|
||||
#define USB_TXCSRL_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx + 2)
|
||||
#define USB_TXCSRH_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx + 3)
|
||||
#define USB_RXMAP_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx + 4)
|
||||
#define USB_RXCSRL_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx + 6)
|
||||
#define USB_RXCSRH_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx + 7)
|
||||
#define USB_RXCOUNT_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx + 8)
|
||||
#define USB_TXTYPE_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx + 0x0A)
|
||||
#define USB_TXINTERVAL_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx + 0x0B)
|
||||
#define USB_RXTYPE_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx + 0x0C)
|
||||
#define USB_RXINTERVAL_BASE(ep_idx) (USB_BASE + MUSB_TXMAP0_OFFSET + 0x10 * ep_idx + 0x0D)
|
||||
|
||||
#define USB_TXADDR_BASE(ep_idx) (USB_BASE + MUSB_TXFUNCADDR0_OFFSET + 0x8 * ep_idx)
|
||||
#define USB_TXHUBADDR_BASE(ep_idx) (USB_BASE + MUSB_TXFUNCADDR0_OFFSET + 0x8 * ep_idx + 2)
|
||||
#define USB_TXHUBPORT_BASE(ep_idx) (USB_BASE + MUSB_TXFUNCADDR0_OFFSET + 0x8 * ep_idx + 3)
|
||||
#define USB_RXADDR_BASE(ep_idx) (USB_BASE + MUSB_TXFUNCADDR0_OFFSET + 0x8 * ep_idx + 4)
|
||||
#define USB_RXHUBADDR_BASE(ep_idx) (USB_BASE + MUSB_TXFUNCADDR0_OFFSET + 0x8 * ep_idx + 6)
|
||||
#define USB_RXHUBPORT_BASE(ep_idx) (USB_BASE + MUSB_TXFUNCADDR0_OFFSET + 0x8 * ep_idx + 7)
|
||||
#endif
|
||||
|
||||
#define USB_FIFO_BASE(ep_idx) (USB_BASE + MUSB_FIFO_OFFSET + 0x4 * ep_idx)
|
||||
|
||||
typedef enum {
|
||||
USB_EP0_STATE_SETUP = 0x0, /**< SETUP DATA */
|
||||
USB_EP0_STATE_IN_DATA = 0x1, /**< IN DATA */
|
||||
USB_EP0_STATE_OUT_DATA = 0x3, /**< OUT DATA */
|
||||
USB_EP0_STATE_IN_STATUS = 0x4, /**< IN status */
|
||||
USB_EP0_STATE_OUT_STATUS = 0x5, /**< OUT status */
|
||||
USB_EP0_STATE_IN_ZLP = 0x6, /**< OUT status */
|
||||
USB_EP0_STATE_STALL = 0x7, /**< STALL status */
|
||||
} ep0_state_t;
|
||||
|
||||
/* Endpoint state */
|
||||
struct musb_ep_state {
|
||||
uint16_t ep_mps; /* Endpoint max packet size */
|
||||
uint8_t ep_type; /* Endpoint type */
|
||||
uint8_t ep_stalled; /* Endpoint stall flag */
|
||||
uint8_t ep_enable; /* Endpoint enable */
|
||||
uint8_t *xfer_buf;
|
||||
uint32_t xfer_len;
|
||||
uint32_t actual_xfer_len;
|
||||
};
|
||||
|
||||
/* Driver state */
|
||||
struct musb_udc {
|
||||
volatile uint8_t dev_addr;
|
||||
__attribute__((aligned(32))) struct usb_setup_packet setup;
|
||||
struct musb_ep_state in_ep[CONFIG_USB_MUSB_EP_NUM]; /*!< IN endpoint parameters*/
|
||||
struct musb_ep_state out_ep[CONFIG_USB_MUSB_EP_NUM]; /*!< OUT endpoint parameters */
|
||||
} g_musb_udc;
|
||||
|
||||
static volatile uint8_t usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
|
||||
/* get current active ep */
|
||||
static uint8_t musb_get_active_ep(void)
|
||||
{
|
||||
return HWREGB(USB_BASE + MUSB_EPIDX_OFFSET);
|
||||
}
|
||||
|
||||
/* set the active ep */
|
||||
static void musb_set_active_ep(uint8_t ep_index)
|
||||
{
|
||||
HWREGB(USB_BASE + MUSB_EPIDX_OFFSET) = ep_index;
|
||||
}
|
||||
|
||||
static void musb_write_packet(uint8_t ep_idx, uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
uint32_t *buf32;
|
||||
uint8_t *buf8;
|
||||
uint32_t count32;
|
||||
uint32_t count8;
|
||||
int i;
|
||||
|
||||
if ((uint32_t)buffer & 0x03) {
|
||||
buf8 = buffer;
|
||||
for (i = 0; i < len; i++) {
|
||||
HWREGB(USB_FIFO_BASE(ep_idx)) = *buf8++;
|
||||
}
|
||||
} else {
|
||||
count32 = len >> 2;
|
||||
count8 = len & 0x03;
|
||||
|
||||
buf32 = (uint32_t *)buffer;
|
||||
|
||||
while (count32--) {
|
||||
HWREG(USB_FIFO_BASE(ep_idx)) = *buf32++;
|
||||
}
|
||||
|
||||
buf8 = (uint8_t *)buf32;
|
||||
|
||||
while (count8--) {
|
||||
HWREGB(USB_FIFO_BASE(ep_idx)) = *buf8++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void musb_read_packet(uint8_t ep_idx, uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
uint32_t *buf32;
|
||||
uint8_t *buf8;
|
||||
uint32_t count32;
|
||||
uint32_t count8;
|
||||
int i;
|
||||
|
||||
if ((uint32_t)buffer & 0x03) {
|
||||
buf8 = buffer;
|
||||
for (i = 0; i < len; i++) {
|
||||
*buf8++ = HWREGB(USB_FIFO_BASE(ep_idx));
|
||||
}
|
||||
} else {
|
||||
count32 = len >> 2;
|
||||
count8 = len & 0x03;
|
||||
|
||||
buf32 = (uint32_t *)buffer;
|
||||
|
||||
while (count32--) {
|
||||
*buf32++ = HWREG(USB_FIFO_BASE(ep_idx));
|
||||
}
|
||||
|
||||
buf8 = (uint8_t *)buf32;
|
||||
|
||||
while (count8--) {
|
||||
*buf8++ = HWREGB(USB_FIFO_BASE(ep_idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t musb_get_fifo_size(uint16_t mps, uint16_t *used)
|
||||
{
|
||||
uint32_t size;
|
||||
|
||||
for (uint8_t i = USB_TXFIFOSZ_SIZE_8; i <= USB_TXFIFOSZ_SIZE_2048; i++) {
|
||||
size = (8 << i);
|
||||
if (mps <= size) {
|
||||
*used = size;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
*used = 0;
|
||||
return USB_TXFIFOSZ_SIZE_8;
|
||||
}
|
||||
|
||||
static uint32_t usbd_musb_fifo_config(struct musb_fifo_cfg *cfg, uint32_t offset)
|
||||
{
|
||||
uint16_t fifo_used;
|
||||
uint8_t c_size;
|
||||
uint16_t c_off;
|
||||
|
||||
c_off = offset >> 3;
|
||||
c_size = musb_get_fifo_size(cfg->maxpacket, &fifo_used);
|
||||
|
||||
musb_set_active_ep(cfg->ep_num);
|
||||
|
||||
switch (cfg->style) {
|
||||
case FIFO_TX:
|
||||
HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET) = c_size & 0x0f;
|
||||
HWREGH(USB_BASE + MUSB_TXFIFOADD_OFFSET) = c_off;
|
||||
break;
|
||||
case FIFO_RX:
|
||||
HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET) = c_size & 0x0f;
|
||||
HWREGH(USB_BASE + MUSB_RXFIFOADD_OFFSET) = c_off;
|
||||
break;
|
||||
case FIFO_TXRX:
|
||||
HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET) = c_size & 0x0f;
|
||||
HWREGH(USB_BASE + MUSB_TXFIFOADD_OFFSET) = c_off;
|
||||
HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET) = c_size & 0x0f;
|
||||
HWREGH(USB_BASE + MUSB_RXFIFOADD_OFFSET) = c_off;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (offset + fifo_used);
|
||||
}
|
||||
|
||||
__WEAK void usb_dc_low_level_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usb_dc_low_level_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int usb_dc_init(uint8_t busid)
|
||||
{
|
||||
uint16_t offset = 0;
|
||||
uint8_t cfg_num;
|
||||
struct musb_fifo_cfg *cfg;
|
||||
|
||||
usb_dc_low_level_init();
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
HWREGB(USB_BASE + MUSB_POWER_OFFSET) |= USB_POWER_HSENAB;
|
||||
#else
|
||||
HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~USB_POWER_HSENAB;
|
||||
#endif
|
||||
|
||||
musb_set_active_ep(0);
|
||||
HWREGB(USB_BASE + MUSB_FADDR_OFFSET) = 0;
|
||||
|
||||
HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) |= USB_DEVCTL_SESSION;
|
||||
|
||||
cfg_num = usbd_get_musb_fifo_cfg(&cfg);
|
||||
|
||||
for (uint8_t i = 0; i < cfg_num; i++) {
|
||||
offset = usbd_musb_fifo_config(&cfg[i], offset);
|
||||
}
|
||||
|
||||
USB_ASSERT_MSG(offset <= usb_get_musb_ram_size(), "Your fifo config is overflow, please check");
|
||||
|
||||
/* Enable USB interrupts */
|
||||
HWREGB(USB_BASE + MUSB_IE_OFFSET) = USB_IE_RESET | USB_IE_SUSPND | USB_IE_RESUME;
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) = USB_TXIE_EP0;
|
||||
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) = 0;
|
||||
|
||||
#ifdef CONFIG_USBDEV_SOF_ENABLE
|
||||
HWREGB(USB_BASE + MUSB_IE_OFFSET) |= USB_IE_SOF;
|
||||
#endif
|
||||
|
||||
HWREGB(USB_BASE + MUSB_POWER_OFFSET) |= USB_POWER_SOFTCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_dc_deinit(uint8_t busid)
|
||||
{
|
||||
HWREGB(USB_BASE + MUSB_IE_OFFSET) = 0;
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) = 0;
|
||||
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) = 0;
|
||||
|
||||
HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~USB_POWER_SOFTCONN;
|
||||
|
||||
usb_dc_low_level_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_set_address(uint8_t busid, const uint8_t addr)
|
||||
{
|
||||
if (addr == 0) {
|
||||
HWREGB(USB_BASE + MUSB_FADDR_OFFSET) = 0;
|
||||
}
|
||||
|
||||
g_musb_udc.dev_addr = addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_set_remote_wakeup(uint8_t busid)
|
||||
{
|
||||
HWREGB(USB_BASE + MUSB_POWER_OFFSET) |= USB_POWER_RESUME;
|
||||
usbd_musb_delay_ms(10);
|
||||
HWREGB(USB_BASE + MUSB_POWER_OFFSET) &= ~USB_POWER_RESUME;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbd_get_port_speed(uint8_t busid)
|
||||
{
|
||||
uint8_t speed = USB_SPEED_UNKNOWN;
|
||||
|
||||
if (HWREGB(USB_BASE + MUSB_POWER_OFFSET) & USB_POWER_HSMODE)
|
||||
speed = USB_SPEED_HIGH;
|
||||
else if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_FSDEV)
|
||||
speed = USB_SPEED_FULL;
|
||||
else if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_LSDEV)
|
||||
speed = USB_SPEED_LOW;
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
uint8_t old_ep_idx;
|
||||
uint32_t ui32Flags = 0;
|
||||
uint16_t ui32Register = 0;
|
||||
|
||||
if (ep_idx == 0) {
|
||||
g_musb_udc.out_ep[0].ep_mps = USB_CTRL_EP_MPS;
|
||||
g_musb_udc.out_ep[0].ep_type = 0x00;
|
||||
g_musb_udc.out_ep[0].ep_enable = true;
|
||||
g_musb_udc.in_ep[0].ep_mps = USB_CTRL_EP_MPS;
|
||||
g_musb_udc.in_ep[0].ep_type = 0x00;
|
||||
g_musb_udc.in_ep[0].ep_enable = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
USB_ASSERT_MSG(ep_idx < CONFIG_USB_MUSB_EP_NUM, "Ep addr %02x overflow", ep->bEndpointAddress);
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
g_musb_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_musb_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_musb_udc.out_ep[ep_idx].ep_enable = true;
|
||||
|
||||
#ifndef CONFIG_USB_MUSB_SIFLI
|
||||
USB_ASSERT_MSG((8 << HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET)) >= g_musb_udc.out_ep[ep_idx].ep_mps,
|
||||
"Ep %02x fifo is overflow", ep->bEndpointAddress);
|
||||
#endif
|
||||
|
||||
HWREGH(USB_RXMAP_BASE(ep_idx)) = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
|
||||
//
|
||||
// Allow auto clearing of RxPktRdy when packet of size max packet
|
||||
// has been unloaded from the FIFO.
|
||||
//
|
||||
if (ui32Flags & USB_EP_AUTO_CLEAR) {
|
||||
ui32Register = USB_RXCSRH1_AUTOCL;
|
||||
}
|
||||
//
|
||||
// Configure the DMA mode.
|
||||
//
|
||||
if (ui32Flags & USB_EP_DMA_MODE_1) {
|
||||
ui32Register |= USB_RXCSRH1_DMAEN | USB_RXCSRH1_DMAMOD;
|
||||
} else if (ui32Flags & USB_EP_DMA_MODE_0) {
|
||||
ui32Register |= USB_RXCSRH1_DMAEN;
|
||||
}
|
||||
//
|
||||
// If requested, disable NYET responses for high-speed bulk and
|
||||
// interrupt endpoints.
|
||||
//
|
||||
if (ui32Flags & USB_EP_DIS_NYET) {
|
||||
ui32Register |= USB_RXCSRH1_DISNYET;
|
||||
}
|
||||
|
||||
//
|
||||
// Enable isochronous mode if requested.
|
||||
//
|
||||
if (USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == 0x01) {
|
||||
ui32Register |= USB_RXCSRH1_ISO;
|
||||
}
|
||||
|
||||
HWREGB(USB_RXCSRH_BASE(ep_idx)) = ui32Register;
|
||||
|
||||
// Reset the Data toggle to zero.
|
||||
if (HWREGB(USB_RXCSRL_BASE(ep_idx)) & USB_RXCSRL1_RXRDY)
|
||||
HWREGB(USB_RXCSRL_BASE(ep_idx)) = (USB_RXCSRL1_CLRDT | USB_RXCSRL1_FLUSH);
|
||||
else
|
||||
HWREGB(USB_RXCSRL_BASE(ep_idx)) = USB_RXCSRL1_CLRDT;
|
||||
|
||||
HWREGB(USB_TXCSRH_BASE(ep_idx)) &= ~USB_TXCSRH1_MODE;
|
||||
} else {
|
||||
g_musb_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_musb_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_musb_udc.in_ep[ep_idx].ep_enable = true;
|
||||
|
||||
#ifndef CONFIG_USB_MUSB_SIFLI
|
||||
USB_ASSERT_MSG((8 << HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET)) >= g_musb_udc.in_ep[ep_idx].ep_mps,
|
||||
"Ep %02x fifo is overflow", ep->bEndpointAddress);
|
||||
#endif
|
||||
|
||||
HWREGH(USB_TXMAP_BASE(ep_idx)) = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
|
||||
//
|
||||
// Allow auto setting of TxPktRdy when max packet size has been loaded
|
||||
// into the FIFO.
|
||||
//
|
||||
if (ui32Flags & USB_EP_AUTO_SET) {
|
||||
ui32Register |= USB_TXCSRH1_AUTOSET;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the DMA mode.
|
||||
//
|
||||
if (ui32Flags & USB_EP_DMA_MODE_1) {
|
||||
ui32Register |= USB_TXCSRH1_DMAEN | USB_TXCSRH1_DMAMOD;
|
||||
} else if (ui32Flags & USB_EP_DMA_MODE_0) {
|
||||
ui32Register |= USB_TXCSRH1_DMAEN;
|
||||
}
|
||||
|
||||
//
|
||||
// Enable isochronous mode if requested.
|
||||
//
|
||||
if (USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == 0x01) {
|
||||
ui32Register |= USB_TXCSRH1_ISO;
|
||||
}
|
||||
|
||||
HWREGB(USB_TXCSRH_BASE(ep_idx)) = ui32Register | USB_TXCSRH1_MODE;
|
||||
|
||||
// Reset the Data toggle to zero.
|
||||
if (HWREGB(USB_TXCSRL_BASE(ep_idx)) & USB_TXCSRL1_TXRDY)
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = (USB_TXCSRL1_CLRDT | USB_TXCSRL1_FLUSH);
|
||||
else
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = USB_TXCSRL1_CLRDT;
|
||||
}
|
||||
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_close(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
uint8_t old_ep_idx;
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
if (ep_idx == 0x00) {
|
||||
usb_ep0_state = USB_EP0_STATE_STALL;
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) |= (USB_CSRL0_STALL | USB_CSRL0_RXRDYC);
|
||||
} else {
|
||||
HWREGB(USB_RXCSRL_BASE(ep_idx)) |= USB_RXCSRL1_STALL;
|
||||
}
|
||||
} else {
|
||||
if (ep_idx == 0x00) {
|
||||
usb_ep0_state = USB_EP0_STATE_STALL;
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) |= (USB_CSRL0_STALL | USB_CSRL0_RXRDYC);
|
||||
} else {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) |= USB_TXCSRL1_STALL;
|
||||
}
|
||||
}
|
||||
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
uint8_t old_ep_idx;
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
if (ep_idx == 0x00) {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_CSRL0_STALLED;
|
||||
} else {
|
||||
// Clear the stall on an OUT endpoint.
|
||||
HWREGB(USB_RXCSRL_BASE(ep_idx)) &= ~(USB_RXCSRL1_STALL | USB_RXCSRL1_STALLED);
|
||||
// Reset the data toggle.
|
||||
HWREGB(USB_RXCSRL_BASE(ep_idx)) |= USB_RXCSRL1_CLRDT;
|
||||
}
|
||||
} else {
|
||||
if (ep_idx == 0x00) {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_CSRL0_STALLED;
|
||||
} else {
|
||||
// Clear the stall on an IN endpoint.
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~(USB_TXCSRL1_STALL | USB_TXCSRL1_STALLED);
|
||||
// Reset the data toggle.
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) |= USB_TXCSRL1_CLRDT;
|
||||
}
|
||||
}
|
||||
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
uint8_t old_ep_idx;
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
if (HWREGB(USB_RXCSRL_BASE(ep_idx)) & USB_RXCSRL1_STALL) {
|
||||
*stalled = 1;
|
||||
} else {
|
||||
*stalled = 0;
|
||||
}
|
||||
} else {
|
||||
if (HWREGB(USB_TXCSRL_BASE(ep_idx)) & USB_TXCSRL1_STALL) {
|
||||
*stalled = 1;
|
||||
} else {
|
||||
*stalled = 0;
|
||||
}
|
||||
}
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
uint8_t old_ep_idx;
|
||||
|
||||
if (!data && data_len) {
|
||||
return -1;
|
||||
}
|
||||
if (!g_musb_udc.in_ep[ep_idx].ep_enable) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
if (HWREGB(USB_TXCSRL_BASE(ep_idx)) & USB_TXCSRL1_TXRDY) {
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return -3;
|
||||
}
|
||||
|
||||
g_musb_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_musb_udc.in_ep[ep_idx].xfer_len = data_len;
|
||||
g_musb_udc.in_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
if (data_len == 0) {
|
||||
if (ep_idx == 0x00) {
|
||||
if (g_musb_udc.setup.wLength == 0) {
|
||||
usb_ep0_state = USB_EP0_STATE_IN_STATUS;
|
||||
} else {
|
||||
usb_ep0_state = USB_EP0_STATE_IN_ZLP;
|
||||
}
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = (USB_CSRL0_TXRDY | USB_CSRL0_DATAEND);
|
||||
} else {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = USB_TXCSRL1_TXRDY;
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << ep_idx);
|
||||
}
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
data_len = MIN(data_len, g_musb_udc.in_ep[ep_idx].ep_mps);
|
||||
|
||||
musb_write_packet(ep_idx, (uint8_t *)data, data_len);
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << ep_idx);
|
||||
|
||||
if (ep_idx == 0x00) {
|
||||
usb_ep0_state = USB_EP0_STATE_IN_DATA;
|
||||
if (data_len < g_musb_udc.in_ep[ep_idx].ep_mps) {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = (USB_CSRL0_TXRDY | USB_CSRL0_DATAEND);
|
||||
} else {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = USB_CSRL0_TXRDY;
|
||||
}
|
||||
} else {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = USB_TXCSRL1_TXRDY;
|
||||
}
|
||||
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
uint8_t old_ep_idx;
|
||||
|
||||
if (!data && data_len) {
|
||||
return -1;
|
||||
}
|
||||
if (!g_musb_udc.out_ep[ep_idx].ep_enable) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
musb_set_active_ep(ep_idx);
|
||||
|
||||
g_musb_udc.out_ep[ep_idx].xfer_buf = data;
|
||||
g_musb_udc.out_ep[ep_idx].xfer_len = data_len;
|
||||
g_musb_udc.out_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
if (data_len == 0) {
|
||||
if (ep_idx == 0) {
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
}
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
if (ep_idx == 0) {
|
||||
usb_ep0_state = USB_EP0_STATE_OUT_DATA;
|
||||
} else {
|
||||
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) |= (1 << ep_idx);
|
||||
}
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_ep0(void)
|
||||
{
|
||||
uint8_t ep_idx = 0; // EP0 index is always 0
|
||||
uint8_t ep0_status = HWREGB(USB_TXCSRL_BASE(ep_idx));
|
||||
uint16_t read_count;
|
||||
|
||||
if (ep0_status & USB_CSRL0_STALLED) {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_CSRL0_STALLED;
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ep0_status & USB_CSRL0_SETEND) {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = USB_CSRL0_SETENDC;
|
||||
}
|
||||
|
||||
if (g_musb_udc.dev_addr > 0) {
|
||||
HWREGB(USB_BASE + MUSB_FADDR_OFFSET) = g_musb_udc.dev_addr;
|
||||
g_musb_udc.dev_addr = 0;
|
||||
}
|
||||
|
||||
switch (usb_ep0_state) {
|
||||
case USB_EP0_STATE_SETUP:
|
||||
if (ep0_status & USB_CSRL0_RXRDY) {
|
||||
read_count = HWREGH(USB_RXCOUNT_BASE(ep_idx));
|
||||
|
||||
if (read_count != 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
musb_read_packet(0, (uint8_t *)&g_musb_udc.setup, 8);
|
||||
if (g_musb_udc.setup.wLength) {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = USB_CSRL0_RXRDYC;
|
||||
} else {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = (USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND);
|
||||
}
|
||||
|
||||
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_musb_udc.setup);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_EP0_STATE_IN_DATA:
|
||||
if (g_musb_udc.in_ep[0].xfer_len > g_musb_udc.in_ep[0].ep_mps) {
|
||||
g_musb_udc.in_ep[0].actual_xfer_len += g_musb_udc.in_ep[0].ep_mps;
|
||||
g_musb_udc.in_ep[0].xfer_len -= g_musb_udc.in_ep[0].ep_mps;
|
||||
} else {
|
||||
g_musb_udc.in_ep[0].actual_xfer_len += g_musb_udc.in_ep[0].xfer_len;
|
||||
g_musb_udc.in_ep[0].xfer_len = 0;
|
||||
}
|
||||
|
||||
usbd_event_ep_in_complete_handler(0, 0x80, g_musb_udc.in_ep[0].actual_xfer_len);
|
||||
|
||||
break;
|
||||
case USB_EP0_STATE_OUT_DATA:
|
||||
if (ep0_status & USB_CSRL0_RXRDY) {
|
||||
read_count = HWREGH(USB_RXCOUNT_BASE(ep_idx));
|
||||
|
||||
musb_read_packet(0, g_musb_udc.out_ep[0].xfer_buf, read_count);
|
||||
g_musb_udc.out_ep[0].xfer_buf += read_count;
|
||||
g_musb_udc.out_ep[0].actual_xfer_len += read_count;
|
||||
|
||||
if (read_count < g_musb_udc.out_ep[0].ep_mps) {
|
||||
usbd_event_ep_out_complete_handler(0, 0x00, g_musb_udc.out_ep[0].actual_xfer_len);
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = (USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND);
|
||||
usb_ep0_state = USB_EP0_STATE_IN_STATUS;
|
||||
} else {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = USB_CSRL0_RXRDYC;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_EP0_STATE_IN_STATUS:
|
||||
case USB_EP0_STATE_IN_ZLP:
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
usbd_event_ep_in_complete_handler(0, 0x80, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void USBD_IRQHandler(uint8_t busid)
|
||||
{
|
||||
uint32_t is;
|
||||
uint32_t txis;
|
||||
uint32_t rxis;
|
||||
uint8_t old_ep_idx;
|
||||
uint8_t ep_idx;
|
||||
uint16_t write_count, read_count;
|
||||
|
||||
if (HWREGB(USB_BASE + MUSB_DEVCTL_OFFSET) & USB_DEVCTL_HOST) {
|
||||
return;
|
||||
}
|
||||
|
||||
is = HWREGB(USB_BASE + MUSB_IS_OFFSET);
|
||||
txis = HWREGH(USB_BASE + MUSB_TXIS_OFFSET);
|
||||
rxis = HWREGH(USB_BASE + MUSB_RXIS_OFFSET);
|
||||
|
||||
HWREGB(USB_BASE + MUSB_IS_OFFSET) = is;
|
||||
|
||||
old_ep_idx = musb_get_active_ep();
|
||||
|
||||
/* Receive a reset signal from the USB bus */
|
||||
if (is & USB_IS_RESET) {
|
||||
memset(&g_musb_udc, 0, sizeof(struct musb_udc));
|
||||
usbd_event_reset_handler(0);
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) = USB_TXIE_EP0;
|
||||
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) = 0;
|
||||
|
||||
usb_ep0_state = USB_EP0_STATE_SETUP;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_SOF_ENABLE
|
||||
if (is & USB_IS_SOF) {
|
||||
usbd_event_sof_handler(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is & USB_IS_RESUME) {
|
||||
usbd_event_resume_handler(0);
|
||||
}
|
||||
|
||||
if (is & USB_IS_SUSPEND) {
|
||||
usbd_event_suspend_handler(0);
|
||||
}
|
||||
|
||||
txis &= HWREGH(USB_BASE + MUSB_TXIE_OFFSET);
|
||||
/* Handle EP0 interrupt */
|
||||
if (txis & USB_TXIE_EP0) {
|
||||
HWREGH(USB_BASE + MUSB_TXIS_OFFSET) = USB_TXIE_EP0;
|
||||
musb_set_active_ep(0);
|
||||
handle_ep0();
|
||||
txis &= ~USB_TXIE_EP0;
|
||||
}
|
||||
|
||||
ep_idx = 1;
|
||||
while (txis) {
|
||||
if (txis & (1 << ep_idx)) {
|
||||
musb_set_active_ep(ep_idx);
|
||||
HWREGH(USB_BASE + MUSB_TXIS_OFFSET) = (1 << ep_idx);
|
||||
if (HWREGB(USB_TXCSRL_BASE(ep_idx)) & USB_TXCSRL1_UNDRN) {
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_TXCSRL1_UNDRN;
|
||||
}
|
||||
|
||||
if (g_musb_udc.in_ep[ep_idx].xfer_len > g_musb_udc.in_ep[ep_idx].ep_mps) {
|
||||
g_musb_udc.in_ep[ep_idx].xfer_buf += g_musb_udc.in_ep[ep_idx].ep_mps;
|
||||
g_musb_udc.in_ep[ep_idx].actual_xfer_len += g_musb_udc.in_ep[ep_idx].ep_mps;
|
||||
g_musb_udc.in_ep[ep_idx].xfer_len -= g_musb_udc.in_ep[ep_idx].ep_mps;
|
||||
} else {
|
||||
g_musb_udc.in_ep[ep_idx].xfer_buf += g_musb_udc.in_ep[ep_idx].xfer_len;
|
||||
g_musb_udc.in_ep[ep_idx].actual_xfer_len += g_musb_udc.in_ep[ep_idx].xfer_len;
|
||||
g_musb_udc.in_ep[ep_idx].xfer_len = 0;
|
||||
}
|
||||
|
||||
if (g_musb_udc.in_ep[ep_idx].xfer_len == 0) {
|
||||
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) &= ~(1 << ep_idx);
|
||||
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_musb_udc.in_ep[ep_idx].actual_xfer_len);
|
||||
} else {
|
||||
write_count = MIN(g_musb_udc.in_ep[ep_idx].xfer_len, g_musb_udc.in_ep[ep_idx].ep_mps);
|
||||
|
||||
musb_write_packet(ep_idx, g_musb_udc.in_ep[ep_idx].xfer_buf, write_count);
|
||||
HWREGB(USB_TXCSRL_BASE(ep_idx)) = USB_TXCSRL1_TXRDY;
|
||||
}
|
||||
|
||||
txis &= ~(1 << ep_idx);
|
||||
}
|
||||
ep_idx++;
|
||||
}
|
||||
|
||||
rxis &= HWREGH(USB_BASE + MUSB_RXIE_OFFSET);
|
||||
ep_idx = 1;
|
||||
while (rxis) {
|
||||
if (rxis & (1 << ep_idx)) {
|
||||
musb_set_active_ep(ep_idx);
|
||||
HWREGH(USB_BASE + MUSB_RXIS_OFFSET) = (1 << ep_idx);
|
||||
if (HWREGB(USB_RXCSRL_BASE(ep_idx)) & USB_RXCSRL1_RXRDY) {
|
||||
read_count = HWREGH(USB_RXCOUNT_BASE(ep_idx));
|
||||
|
||||
musb_read_packet(ep_idx, g_musb_udc.out_ep[ep_idx].xfer_buf, read_count);
|
||||
HWREGB(USB_RXCSRL_BASE(ep_idx)) &= ~(USB_RXCSRL1_RXRDY);
|
||||
|
||||
g_musb_udc.out_ep[ep_idx].xfer_buf += read_count;
|
||||
g_musb_udc.out_ep[ep_idx].actual_xfer_len += read_count;
|
||||
g_musb_udc.out_ep[ep_idx].xfer_len -= read_count;
|
||||
|
||||
if ((read_count < g_musb_udc.out_ep[ep_idx].ep_mps) || (g_musb_udc.out_ep[ep_idx].xfer_len == 0)) {
|
||||
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) &= ~(1 << ep_idx);
|
||||
usbd_event_ep_out_complete_handler(0, ep_idx, g_musb_udc.out_ep[ep_idx].actual_xfer_len);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
rxis &= ~(1 << ep_idx);
|
||||
}
|
||||
ep_idx++;
|
||||
}
|
||||
|
||||
musb_set_active_ep(old_ep_idx);
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "sys_driver.h"
|
||||
#include "gpio_driver.h"
|
||||
#include <driver/gpio.h>
|
||||
#include <driver/gpio_types.h>
|
||||
#include <driver/int.h>
|
||||
#include "bk_misc.h"
|
||||
#include "usbd_core.h"
|
||||
#include "usbh_core.h"
|
||||
#include "usb_musb_reg.h"
|
||||
|
||||
#define USB_BASE_ADDR SOC_USB_REG_BASE
|
||||
|
||||
#if (CONFIG_SOC_BK7271)
|
||||
#define REG_AHB2_USB_OTG_CFG (*((volatile unsigned char *)(USB_BASE_ADDR + 0x80)))
|
||||
#define REG_AHB2_USB_DMA_ENDP (*((volatile unsigned char *)(USB_BASE_ADDR + 0x84)))
|
||||
#define REG_AHB2_USB_VTH (*((volatile unsigned char *)(USB_BASE_ADDR + 0x88)))
|
||||
#define REG_AHB2_USB_GEN (*((volatile unsigned char *)(USB_BASE_ADDR + 0x8C)))
|
||||
#define REG_AHB2_USB_STAT (*((volatile unsigned char *)(USB_BASE_ADDR + 0x90)))
|
||||
#define REG_AHB2_USB_INT (*((volatile unsigned char *)(USB_BASE_ADDR + 0x94)))
|
||||
#define REG_AHB2_USB_RESET (*((volatile unsigned char *)(USB_BASE_ADDR + 0x98)))
|
||||
#define REG_AHB2_USB_DEV_CFG (*((volatile unsigned char *)(USB_BASE_ADDR + 0x9C)))
|
||||
#elif (CONFIG_SOC_BK7256XX)
|
||||
#define REG_AHB2_USB_OTG_CFG (*((volatile unsigned char *)(USB_BASE_ADDR + 0x280)))
|
||||
#define REG_AHB2_USB_DMA_ENDP (*((volatile unsigned char *)(USB_BASE_ADDR + 0x284)))
|
||||
#define REG_AHB2_USB_VTH (*((volatile unsigned char *)(USB_BASE_ADDR + 0x288)))
|
||||
#define REG_AHB2_USB_GEN (*((volatile unsigned char *)(USB_BASE_ADDR + 0x28C)))
|
||||
#define REG_AHB2_USB_STAT (*((volatile unsigned char *)(USB_BASE_ADDR + 0x290)))
|
||||
#define REG_AHB2_USB_INT (*((volatile unsigned char *)(USB_BASE_ADDR + 0x294)))
|
||||
#define REG_AHB2_USB_RESET (*((volatile unsigned char *)(USB_BASE_ADDR + 0x298)))
|
||||
#define REG_AHB2_USB_DEV_CFG (*((volatile unsigned char *)(USB_BASE_ADDR + 0x29C)))
|
||||
#elif (CONFIG_SOC_BK7236XX) || (CONFIG_SOC_BK7239XX) || (CONFIG_SOC_BK7286XX)
|
||||
#define REG_AHB2_USB_DEVICE_ID (*((volatile unsigned char *)(USB_BASE_ADDR + 0x280)))
|
||||
#define REG_AHB2_USB_VERSION_ID (*((volatile unsigned char *)(USB_BASE_ADDR + 0x284)))
|
||||
#define REG_AHB2_USB_GLOBAL_CTRL (*((volatile unsigned char *)(USB_BASE_ADDR + 0x288)))
|
||||
#define REG_AHB2_USB_DEVICE_STATUS (*((volatile unsigned char *)(USB_BASE_ADDR + 0x28c)))
|
||||
#define REG_AHB2_USB_OTG_CFG (*((volatile unsigned char *)(USB_BASE_ADDR + 0x290)))
|
||||
#define REG_AHB2_USB_DMA_ENDP (*((volatile unsigned char *)(USB_BASE_ADDR + 0x294)))
|
||||
#define REG_AHB2_USB_VTH (*((volatile unsigned char *)(USB_BASE_ADDR + 0x298)))
|
||||
#define REG_AHB2_USB_GEN (*((volatile unsigned char *)(USB_BASE_ADDR + 0x29C)))
|
||||
#define REG_AHB2_USB_STAT (*((volatile unsigned char *)(USB_BASE_ADDR + 0x2A0)))
|
||||
#define REG_AHB2_USB_INT (*((volatile unsigned char *)(USB_BASE_ADDR + 0x2A4)))
|
||||
#define REG_AHB2_USB_RESET (*((volatile unsigned char *)(USB_BASE_ADDR + 0x2A8)))
|
||||
#define REG_AHB2_USB_DEV_CFG (*((volatile unsigned char *)(USB_BASE_ADDR + 0x2AC)))
|
||||
|
||||
#define REG_USB_USR_700 (*((volatile unsigned long *)(USB_BASE_ADDR + 0x700)))
|
||||
#define REG_USB_USR_704 (*((volatile unsigned long *)(USB_BASE_ADDR + 0x704)))
|
||||
#define REG_USB_USR_708 (*((volatile unsigned long *)(USB_BASE_ADDR + 0x708)))
|
||||
#define REG_USB_USR_70C (*((volatile unsigned long *)(USB_BASE_ADDR + 0x70C)))
|
||||
#define REG_USB_USR_710 (*((volatile unsigned long *)(USB_BASE_ADDR + 0x710)))
|
||||
#define REG_USB_USR_714 (*((volatile unsigned long *)(USB_BASE_ADDR + 0x714)))
|
||||
#define REG_USB_PHY_00 (*((volatile unsigned long *)(USB_BASE_ADDR + 0x400)))
|
||||
#define REG_USB_PHY_01 (*((volatile unsigned long *)(USB_BASE_ADDR + 0x404)))
|
||||
#endif
|
||||
|
||||
#define USB_DP_CAPABILITY_VALUE (0xF)
|
||||
#define USB_DN_CAPABILITY_VALUE (0xF)
|
||||
|
||||
#define NANENG_PHY_FC_REG01 (0x01 * 4)
|
||||
#define NANENG_PHY_FC_REG02 (0x02 * 4)
|
||||
#define NANENG_PHY_FC_REG03 (0x03 * 4)
|
||||
#define NANENG_PHY_FC_REG04 (0x04 * 4)
|
||||
#define NANENG_PHY_FC_REG05 (0x05 * 4)
|
||||
#define NANENG_PHY_FC_REG06 (0x06 * 4)
|
||||
#define NANENG_PHY_FC_REG07 (0x07 * 4)
|
||||
#define NANENG_PHY_FC_REG08 (0x08 * 4)
|
||||
#define NANENG_PHY_FC_REG09 (0x09 * 4)
|
||||
#define NANENG_PHY_FC_REG0A (0x0A * 4)
|
||||
#define NANENG_PHY_FC_REG0B (0x0B * 4)
|
||||
#define NANENG_PHY_FC_REG0C (0x0C * 4)
|
||||
#define NANENG_PHY_FC_REG0D (0x0D * 4)
|
||||
#define NANENG_PHY_FC_REG0E (0x0E * 4)
|
||||
#define NANENG_PHY_FC_REG0F (0x0F * 4)
|
||||
#define NANENG_PHY_FC_REG0F_BYTE 0x0F
|
||||
|
||||
#define NANENG_PHY_FC_REG10 (0x10 * 4)
|
||||
#define NANENG_PHY_FC_REG11 (0x11 * 4)
|
||||
#define NANENG_PHY_FC_REG12 (0x12 * 4)
|
||||
#define NANENG_PHY_FC_REG13 (0x13 * 4)
|
||||
#define NANENG_PHY_FC_REG14 (0x14 * 4)
|
||||
#define NANENG_PHY_FC_REG15 (0x15 * 4)
|
||||
#define NANENG_PHY_FC_REG16 (0x16 * 4)
|
||||
#define NANENG_PHY_FC_REG17 (0x17 * 4)
|
||||
#define NANENG_PHY_FC_REG18 (0x18 * 4)
|
||||
#define NANENG_PHY_FC_REG19 (0x19 * 4)
|
||||
#define NANENG_PHY_FC_REG1A (0x1A * 4)
|
||||
#define NANENG_PHY_FC_REG1B (0x1B * 4)
|
||||
#define NANENG_PHY_FC_REG1C (0x1C * 4)
|
||||
#define NANENG_PHY_FC_REG1D (0x1D * 4)
|
||||
#define NANENG_PHY_FC_REG1E (0x1E * 4)
|
||||
#define NANENG_PHY_FC_REG1F (0x1F * 4)
|
||||
|
||||
#if CONFIG_USB_MUSB_EP_NUM != 8
|
||||
#error beken chips only support 8 endpoints
|
||||
#endif
|
||||
|
||||
#if CONFIG_USB_MUSB_PIPE_NUM != 8
|
||||
#error beken chips only support 8 pipes
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
static struct musb_fifo_cfg musb_device_table[] = {
|
||||
{ .ep_num = 0, .style = FIFO_TXRX, .maxpacket = 64, },
|
||||
{ .ep_num = 1, .style = FIFO_TX, .maxpacket = 1024, },
|
||||
{ .ep_num = 1, .style = FIFO_RX, .maxpacket = 1024, },
|
||||
{ .ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .ep_num = 4, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 4, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .ep_num = 5, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 5, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .ep_num = 6, .style = FIFO_TXRX, .maxpacket = 512, },
|
||||
{ .ep_num = 7, .style = FIFO_TXRX, .maxpacket = 512, }
|
||||
};
|
||||
|
||||
static struct musb_fifo_cfg musb_host_table[] = {
|
||||
{ .ep_num = 0, .style = FIFO_TXRX, .maxpacket = 64, },
|
||||
{ .ep_num = 1, .style = FIFO_TX, .maxpacket = 1024, },
|
||||
{ .ep_num = 1, .style = FIFO_RX, .maxpacket = 1024, },
|
||||
{ .ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .ep_num = 4, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 4, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .ep_num = 5, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 5, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .ep_num = 6, .style = FIFO_TXRX, .maxpacket = 512, },
|
||||
{ .ep_num = 7, .style = FIFO_TXRX, .maxpacket = 512, }
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
uint8_t usbd_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
|
||||
{
|
||||
*cfg = musb_device_table;
|
||||
return sizeof(musb_device_table) / sizeof(musb_device_table[0]);
|
||||
}
|
||||
|
||||
uint8_t usbh_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
|
||||
{
|
||||
*cfg = musb_host_table;
|
||||
return sizeof(musb_host_table) / sizeof(musb_host_table[0]);
|
||||
}
|
||||
|
||||
uint32_t usb_get_musb_ram_size(void)
|
||||
{
|
||||
return 8192;
|
||||
}
|
||||
|
||||
extern void USBD_IRQHandler(uint8_t busid);
|
||||
|
||||
void USBD_IRQ(void)
|
||||
{
|
||||
USBD_IRQHandler(0);
|
||||
}
|
||||
|
||||
static void bk_analog_layer_usb_sys_related_ops(uint32_t usb_mode, bool ops)
|
||||
{
|
||||
extern void delay(INT32 num);
|
||||
|
||||
#if 0
|
||||
sys_drv_usb_analog_phy_en(ops, NULL);
|
||||
sys_drv_usb_analog_speed_en(ops, NULL);
|
||||
sys_drv_usb_analog_ckmcu_en(ops, NULL);
|
||||
#endif
|
||||
if (ops) {
|
||||
sys_drv_usb_clock_ctrl(true, NULL);
|
||||
delay(100);
|
||||
#if 0
|
||||
sys_drv_usb_analog_deepsleep_en(false);
|
||||
#endif
|
||||
sys_drv_usb_analog_dp_capability(USB_DP_CAPABILITY_VALUE);
|
||||
sys_drv_usb_analog_dn_capability(USB_DN_CAPABILITY_VALUE);
|
||||
if (!sys_hal_psram_ldo_status()) {
|
||||
sys_drv_psram_ldo_enable(1);
|
||||
}
|
||||
sys_drv_usb_analog_phy_en(1, NULL);
|
||||
|
||||
if (usb_mode == 0) {
|
||||
REG_USB_USR_708 = 0x0;
|
||||
REG_USB_USR_710 &= ~(0x1 << 7);
|
||||
delay(100);
|
||||
|
||||
REG_USB_USR_710 |= (0x1 << 15);
|
||||
//REG_USB_USR_710 |= (0x1<<14);
|
||||
REG_USB_USR_710 |= (0x1 << 16);
|
||||
REG_USB_USR_710 |= (0x1 << 17);
|
||||
REG_USB_USR_710 |= (0x1 << 18);
|
||||
REG_USB_USR_710 |= (0x1 << 19);
|
||||
REG_USB_USR_710 &= ~(0x1 << 20);
|
||||
REG_USB_USR_710 |= (0x1 << 21);
|
||||
REG_USB_USR_710 |= (0x0 << 0);
|
||||
REG_USB_USR_710 |= (0x1 << 5);
|
||||
REG_USB_USR_710 |= (0x1 << 6);
|
||||
REG_USB_USR_710 |= (0x1 << 9);
|
||||
REG_USB_USR_710 |= (0x1 << 10);
|
||||
REG_USB_USR_710 |= (0x1 << 1);
|
||||
|
||||
REG_USB_USR_710 |= (0x1 << 7);
|
||||
REG_USB_USR_708 = 0x1;
|
||||
#if 0
|
||||
REG_USB_PHY_00 = 0x08;
|
||||
REG_USB_PHY_01 = 0x02;
|
||||
REG_USB_USR_710 |= (0x1<< 8);
|
||||
while(1){
|
||||
reg = REG_USB_USR_70C;
|
||||
if(reg & 0x100){
|
||||
USB_DRIVER_LOGI("SelfTest Fin!\r\n");
|
||||
USB_DRIVER_LOGI("test end!\r\n");
|
||||
break;
|
||||
} else {
|
||||
USB_DRIVER_LOGI("70c_reg:0x%x\r\n", reg);
|
||||
delay(10000);
|
||||
}
|
||||
}
|
||||
REG_USB_PHY_00 &= ~0x08;
|
||||
REG_USB_PHY_01 &= ~0x02;
|
||||
REG_USB_USR_710 &= ~(0x1<< 8);
|
||||
#endif
|
||||
} else {
|
||||
REG_USB_USR_710 |= (0x1 << 15);
|
||||
REG_USB_USR_710 |= (0x1 << 14);
|
||||
REG_USB_USR_710 |= (0x1 << 16);
|
||||
REG_USB_USR_710 |= (0x1 << 17);
|
||||
REG_USB_USR_710 |= (0x1 << 18);
|
||||
REG_USB_USR_710 |= (0x1 << 19);
|
||||
REG_USB_USR_710 &= ~(0x1 << 20);
|
||||
REG_USB_USR_710 |= (0x1 << 21);
|
||||
REG_USB_USR_710 |= (0x0 << 0);
|
||||
REG_USB_USR_710 |= (0x1 << 5);
|
||||
REG_USB_USR_710 |= (0x1 << 6);
|
||||
REG_USB_USR_710 |= (0x1 << 9);
|
||||
REG_USB_USR_710 |= (0x1 << 10);
|
||||
REG_USB_USR_710 |= (0x1 << 7);
|
||||
|
||||
REG_USB_USR_708 = 0x1;
|
||||
}
|
||||
} else {
|
||||
sys_drv_usb_analog_phy_en(0, NULL);
|
||||
sys_drv_usb_clock_ctrl(false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_dc_low_level_init(void)
|
||||
{
|
||||
#if CONFIG_SYS_CPU0
|
||||
bk_pm_module_vote_sleep_ctrl(PM_SLEEP_MODULE_NAME_USB_1, 0x0, 0x0);
|
||||
#endif
|
||||
bk_analog_layer_usb_sys_related_ops(1, true);
|
||||
bk_gpio_set_output_high(CONFIG_USB_VBAT_CONTROL_GPIO_ID);
|
||||
|
||||
bk_pm_module_vote_cpu_freq(PM_DEV_ID_USB_1, PM_CPU_FRQ_120M);
|
||||
|
||||
sys_hal_usb_analog_phy_en(true);
|
||||
|
||||
sys_drv_usb_clock_ctrl(true, NULL);
|
||||
sys_drv_int_enable(USB_INTERRUPT_CTRL_BIT);
|
||||
|
||||
bk_int_isr_register(INT_SRC_USB, USBD_IRQ, NULL);
|
||||
bk_int_set_priority(INT_SRC_USB, 2);
|
||||
}
|
||||
|
||||
void usb_dc_low_level_deinit(void)
|
||||
{
|
||||
bk_pm_module_vote_cpu_freq(PM_DEV_ID_USB_1, PM_CPU_FRQ_DEFAULT);
|
||||
sys_hal_usb_analog_phy_en(false);
|
||||
sys_drv_usb_clock_ctrl(false, NULL);
|
||||
sys_drv_int_disable(USB_INTERRUPT_CTRL_BIT);
|
||||
bk_int_isr_unregister(INT_SRC_USB);
|
||||
bk_analog_layer_usb_sys_related_ops(1, false);
|
||||
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_USB_1, CLK_PWR_CTRL_PWR_DOWN);
|
||||
}
|
||||
|
||||
void usbd_musb_delay_ms(uint8_t ms)
|
||||
{
|
||||
/* implement later */
|
||||
}
|
||||
|
||||
extern void USBH_IRQHandler(uint8_t busid);
|
||||
|
||||
void USBH_IRQ(void)
|
||||
{
|
||||
USBH_IRQHandler(0);
|
||||
}
|
||||
|
||||
#define NANENG_PHY_CFG 1
|
||||
#define USB_PHY_BASE (SOC_USB_REG_BASE + 0x400)
|
||||
|
||||
#define HWREG(x) \
|
||||
(*((volatile uint32_t *)(x)))
|
||||
#define HWREGH(x) \
|
||||
(*((volatile uint16_t *)(x)))
|
||||
#define HWREGB(x) \
|
||||
(*((volatile uint8_t *)(x)))
|
||||
|
||||
void usb_hc_low_level_init(struct usbh_bus *bus)
|
||||
{
|
||||
#if CONFIG_SYS_CPU0
|
||||
bk_pm_module_vote_sleep_ctrl(PM_SLEEP_MODULE_NAME_USB_1, 0x0, 0x0);
|
||||
#endif
|
||||
bk_analog_layer_usb_sys_related_ops(0, true);
|
||||
bk_gpio_set_output_high(CONFIG_USB_VBAT_CONTROL_GPIO_ID);
|
||||
|
||||
#if NANENG_PHY_CFG
|
||||
//NANENG_PHY_CFG_HSRX_TEST
|
||||
HWREGB(USB_PHY_BASE + NANENG_PHY_FC_REG0F) |= (0x1 << 4);
|
||||
//disconnect value 640mv
|
||||
HWREGB(USB_PHY_BASE + NANENG_PHY_FC_REG0B) = 0x7C;
|
||||
#endif
|
||||
bk_int_isr_register(INT_SRC_USB, USBH_IRQ, NULL);
|
||||
sys_drv_int_enable(USB_INTERRUPT_CTRL_BIT);
|
||||
}
|
||||
|
||||
void usb_hc_low_level_deinit(struct usbh_bus *bus)
|
||||
{
|
||||
sys_drv_int_disable(USB_INTERRUPT_CTRL_BIT);
|
||||
bk_int_isr_unregister(INT_SRC_USB);
|
||||
sys_drv_dev_clk_pwr_up(CLK_PWR_ID_USB_1, CLK_PWR_CTRL_PWR_DOWN);
|
||||
bk_analog_layer_usb_sys_related_ops(0, false);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usb_config.h"
|
||||
#include "stdint.h"
|
||||
#include "usb_musb_reg.h"
|
||||
|
||||
#if CONFIG_USB_MUSB_EP_NUM != 6
|
||||
#error es32 chips only support 6 endpoints
|
||||
#endif
|
||||
|
||||
#if CONFIG_USB_MUSB_PIPE_NUM != 6
|
||||
#error es32 chips only support 6 pipes
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
static struct musb_fifo_cfg musb_device_table[] = {
|
||||
{ .ep_num = 0, .style = FIFO_TXRX, .maxpacket = 64, },
|
||||
{ .ep_num = 1, .style = FIFO_TXRX, .maxpacket = 1024, },
|
||||
{ .ep_num = 2, .style = FIFO_TXRX, .maxpacket = 512, },
|
||||
{ .ep_num = 3, .style = FIFO_TXRX, .maxpacket = 512, },
|
||||
{ .ep_num = 4, .style = FIFO_TXRX, .maxpacket = 512, },
|
||||
{ .ep_num = 5, .style = FIFO_TXRX, .maxpacket = 512, },
|
||||
};
|
||||
|
||||
static struct musb_fifo_cfg musb_host_table[] = {
|
||||
{ .ep_num = 0, .style = FIFO_TXRX, .maxpacket = 64, },
|
||||
{ .ep_num = 1, .style = FIFO_TXRX, .maxpacket = 1024, },
|
||||
{ .ep_num = 2, .style = FIFO_TXRX, .maxpacket = 512, },
|
||||
{ .ep_num = 3, .style = FIFO_TXRX, .maxpacket = 512, },
|
||||
{ .ep_num = 4, .style = FIFO_TXRX, .maxpacket = 512, },
|
||||
{ .ep_num = 5, .style = FIFO_TXRX, .maxpacket = 512, },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
uint8_t usbd_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
|
||||
{
|
||||
*cfg = musb_device_table;
|
||||
return sizeof(musb_device_table) / sizeof(musb_device_table[0]);
|
||||
}
|
||||
|
||||
uint8_t usbh_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
|
||||
{
|
||||
*cfg = musb_host_table;
|
||||
return sizeof(musb_host_table) / sizeof(musb_host_table[0]);
|
||||
}
|
||||
|
||||
uint32_t usb_get_musb_ram_size(void)
|
||||
{
|
||||
return 4096;
|
||||
}
|
||||
|
||||
void usbd_musb_delay_ms(uint8_t ms)
|
||||
{
|
||||
/* implement later */
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2025, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbh_core.h"
|
||||
#include "usb_musb_reg.h"
|
||||
|
||||
#undef USB_POWER_SOFTCONN
|
||||
#undef USB_DEVCTL_FSDEV
|
||||
#undef USB_DEVCTL_LSDEV
|
||||
#undef USB_DEVCTL_SESSION
|
||||
#undef USB_POWER_HSENAB
|
||||
#undef USB_POWER_HSMODE
|
||||
#undef USB_POWER_RESET
|
||||
#undef USB_POWER_RESUME
|
||||
|
||||
#ifndef CONFIG_USB_MUSB_SIFLI
|
||||
#error must define CONFIG_USB_MUSB_SIFLI when use sunxi chips
|
||||
#endif
|
||||
|
||||
#include "bf0_hal.h"
|
||||
|
||||
uint8_t usbd_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
|
||||
{
|
||||
*cfg = NULL; // No FIFO configuration for this implementation, readonly
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbh_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
|
||||
{
|
||||
*cfg = NULL; // No FIFO configuration for this implementation, readonly
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t usb_get_musb_ram_size(void)
|
||||
{
|
||||
return 0xFFFF; // No specific RAM size for this implementation
|
||||
}
|
||||
|
||||
void usbd_musb_delay_ms(uint8_t ms)
|
||||
{
|
||||
/* implement later */
|
||||
}
|
||||
|
||||
#ifdef PKG_CHERRYUSB_DEVICE
|
||||
void usb_dc_low_level_init(uint8_t busid)
|
||||
{
|
||||
HAL_RCC_EnableModule(RCC_MOD_USBC);
|
||||
|
||||
#ifdef SOC_SF32LB58X
|
||||
//hwp_usbc->utmicfg12 = hwp_usbc->utmicfg12 | 0x3; //set xo_clk_sel
|
||||
hwp_usbc->ldo25 = hwp_usbc->ldo25 | 0xa; //set psw_en and ldo25_en
|
||||
HAL_Delay(1);
|
||||
hwp_usbc->swcntl3 = 0x1; //set utmi_en for USB2.0
|
||||
hwp_usbc->usbcfg = hwp_usbc->usbcfg | 0x40; //enable usb PLL.
|
||||
#elif defined(SOC_SF32LB56X) || defined(SOC_SF32LB52X)
|
||||
hwp_hpsys_cfg->USBCR |= HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_DP_EN | HPSYS_CFG_USBCR_USB_EN;
|
||||
#elif defined(SOC_SF32LB55X)
|
||||
hwp_hpsys_cfg->USBCR |= HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_USB_EN;
|
||||
#endif
|
||||
#ifndef SOC_SF32LB55X
|
||||
hwp_usbc->usbcfg |= (USB_USBCFG_AVALID | USB_USBCFG_AVALID_DR);
|
||||
hwp_usbc->dpbrxdisl = 0xFE;
|
||||
hwp_usbc->dpbtxdisl = 0xFE;
|
||||
#endif
|
||||
NVIC_EnableIRQ(USBC_IRQn);
|
||||
__HAL_SYSCFG_Enable_USB();
|
||||
}
|
||||
|
||||
void usb_dc_low_level_deinit(uint8_t busid)
|
||||
{
|
||||
NVIC_DisableIRQ(USBC_IRQn);
|
||||
#ifdef SOC_SF32LB58X
|
||||
hwp_usbc->usbcfg &= ~0x40; // Disable usb PLL.
|
||||
hwp_usbc->swcntl3 = 0x0;
|
||||
hwp_usbc->ldo25 &= ~0xa; // Disable psw_en and ldo25_en
|
||||
#elif defined(SOC_SF32LB56X) || defined(SOC_SF32LB52X)
|
||||
hwp_hpsys_cfg->USBCR &= ~(HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_DP_EN | HPSYS_CFG_USBCR_USB_EN);
|
||||
#elif defined(SOC_SF32LB55X)
|
||||
hwp_hpsys_cfg->USBCR &= ~(HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_USB_EN);
|
||||
#endif
|
||||
/* reset USB to make DP change to PULLDOWN state */
|
||||
hwp_hpsys_rcc->RSTR2 |= HPSYS_RCC_RSTR2_USBC;
|
||||
HAL_Delay_us(100);
|
||||
hwp_hpsys_rcc->RSTR2 &= ~HPSYS_RCC_RSTR2_USBC;
|
||||
HAL_RCC_DisableModule(RCC_MOD_USBC);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PKG_CHERRYUSB_HOST
|
||||
void usb_hc_low_level_init(struct usbh_bus *bus)
|
||||
{
|
||||
HAL_RCC_EnableModule(RCC_MOD_USBC);
|
||||
|
||||
#ifdef SOC_SF32LB58X
|
||||
//hwp_usbc->utmicfg12 = hwp_usbc->utmicfg12 | 0x3; //set xo_clk_sel
|
||||
hwp_usbc->ldo25 = hwp_usbc->ldo25 | 0xa; //set psw_en and ldo25_en
|
||||
HAL_Delay(1);
|
||||
hwp_usbc->swcntl3 = 0x1; //set utmi_en for USB2.0
|
||||
hwp_usbc->usbcfg = hwp_usbc->usbcfg | 0x40; //enable usb PLL.
|
||||
#elif defined(SOC_SF32LB56X) || defined(SOC_SF32LB52X)
|
||||
hwp_hpsys_cfg->USBCR |= HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_DP_EN | HPSYS_CFG_USBCR_USB_EN;
|
||||
#elif defined(SOC_SF32LB55X)
|
||||
hwp_hpsys_cfg->USBCR |= HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_USB_EN;
|
||||
#endif
|
||||
#ifndef SOC_SF32LB55X
|
||||
hwp_usbc->usbcfg |= (USB_USBCFG_AVALID | USB_USBCFG_AVALID_DR);
|
||||
hwp_usbc->dpbrxdisl = 0xFE;
|
||||
hwp_usbc->dpbtxdisl = 0xFE;
|
||||
#endif
|
||||
__HAL_SYSCFG_Enable_USB();
|
||||
hwp_usbc->usbcfg &= 0xEF;
|
||||
hwp_usbc->dbgl = 0x80;
|
||||
|
||||
NVIC_EnableIRQ(USBC_IRQn);
|
||||
}
|
||||
|
||||
void usb_hc_low_level_deinit(struct usbh_bus *bus)
|
||||
{
|
||||
NVIC_DisableIRQ(USBC_IRQn);
|
||||
#ifdef SOC_SF32LB58X
|
||||
hwp_usbc->usbcfg &= ~0x40; // Disable usb PLL.
|
||||
hwp_usbc->swcntl3 = 0x0;
|
||||
hwp_usbc->ldo25 &= ~0xa; // Disable psw_en and ldo25_en
|
||||
#elif defined(SOC_SF32LB56X) || defined(SOC_SF32LB52X)
|
||||
hwp_hpsys_cfg->USBCR &= ~(HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_DP_EN | HPSYS_CFG_USBCR_USB_EN);
|
||||
#elif defined(SOC_SF32LB55X)
|
||||
hwp_hpsys_cfg->USBCR &= ~(HPSYS_CFG_USBCR_DM_PD | HPSYS_CFG_USBCR_USB_EN);
|
||||
#endif
|
||||
/* reset USB to make DP change to PULLDOWN state */
|
||||
hwp_hpsys_rcc->RSTR2 |= HPSYS_RCC_RSTR2_USBC;
|
||||
HAL_Delay_us(100);
|
||||
hwp_hpsys_rcc->RSTR2 &= ~HPSYS_RCC_RSTR2_USBC;
|
||||
HAL_RCC_DisableModule(RCC_MOD_USBC);
|
||||
}
|
||||
|
||||
void musb_reset_prev(void)
|
||||
{
|
||||
#if defined(SF32LB58X)
|
||||
hwp_usbc->rsvd0 = 0xc; //58
|
||||
#endif
|
||||
}
|
||||
|
||||
void musb_reset_post(void)
|
||||
{
|
||||
#if defined(SF32LB58X)
|
||||
hwp_usbc->rsvd0 = 0x0; //58
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void USBC_IRQHandler(void)
|
||||
{
|
||||
#ifdef PKG_CHERRYUSB_DEVICE
|
||||
USBD_IRQHandler(0);
|
||||
#endif
|
||||
#ifdef PKG_CHERRYUSB_HOST
|
||||
USBH_IRQHandler(0);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usb_config.h"
|
||||
#include "stdint.h"
|
||||
#include "usb_musb_reg.h"
|
||||
|
||||
#ifndef CONFIG_USB_MUSB_SUNXI
|
||||
#error must define CONFIG_USB_MUSB_SUNXI when use sunxi chips
|
||||
#endif
|
||||
|
||||
#if CONFIG_USB_MUSB_EP_NUM != 4
|
||||
#error sunxi chips only support 4 endpoints
|
||||
#endif
|
||||
|
||||
#if CONFIG_USB_MUSB_PIPE_NUM != 4
|
||||
#error sunxi chips only support 4 pipes
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
static struct musb_fifo_cfg musb_device_table[] = {
|
||||
{ .ep_num = 0, .style = FIFO_TXRX, .maxpacket = 64, },
|
||||
{ .ep_num = 1, .style = FIFO_TX, .maxpacket = 1024, },
|
||||
{ .ep_num = 1, .style = FIFO_RX, .maxpacket = 1024, },
|
||||
{ .ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
|
||||
};
|
||||
|
||||
static struct musb_fifo_cfg musb_host_table[] = {
|
||||
{ .ep_num = 0, .style = FIFO_TXRX, .maxpacket = 64, },
|
||||
{ .ep_num = 1, .style = FIFO_TX, .maxpacket = 1024, },
|
||||
{ .ep_num = 1, .style = FIFO_RX, .maxpacket = 1024, },
|
||||
{ .ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
uint8_t usbd_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
|
||||
{
|
||||
*cfg = musb_device_table;
|
||||
return sizeof(musb_device_table) / sizeof(musb_device_table[0]);
|
||||
}
|
||||
|
||||
uint8_t usbh_get_musb_fifo_cfg(struct musb_fifo_cfg **cfg)
|
||||
{
|
||||
*cfg = musb_host_table;
|
||||
return sizeof(musb_host_table) / sizeof(musb_host_table[0]);
|
||||
}
|
||||
|
||||
uint32_t usb_get_musb_ram_size(void)
|
||||
{
|
||||
return 8192;
|
||||
}
|
||||
|
||||
void usbd_musb_delay_ms(uint8_t ms)
|
||||
{
|
||||
/* implement later */
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user