update(port/musb): config fifo from fifo table, add beken and es32 glue

This commit is contained in:
sakumisu
2024-06-14 22:38:31 +08:00
parent 3cf2d6da31
commit 0f8c145d93
9 changed files with 640 additions and 77 deletions

View File

@@ -16,10 +16,6 @@
#define USB_BASE (bus->hcd.reg_base)
#if CONFIG_USBHOST_PIPE_NUM != 4
#error musb host ip only supports 4 pipe num
#endif
#ifdef CONFIG_USB_MUSB_SUNXI
#define MUSB_FADDR_OFFSET 0x98
#define MUSB_POWER_OFFSET 0x40
@@ -124,10 +120,6 @@
#define USB_FIFO_BASE(ep_idx) (USB_BASE + MUSB_FIFO_OFFSET + 0x4 * ep_idx)
#ifndef CONIFG_USB_MUSB_PIPE_NUM
#define CONIFG_USB_MUSB_PIPE_NUM 5
#endif
typedef enum {
USB_EP0_STATE_SETUP = 0x0, /**< SETUP DATA */
USB_EP0_STATE_IN_DATA, /**< IN DATA */
@@ -243,6 +235,56 @@ static void musb_read_packet(struct usbh_bus *bus, uint8_t ep_idx, uint8_t *buff
}
}
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 usbh_musb_fifo_config(struct usbh_bus *bus, 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(bus, 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);
}
void musb_control_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, struct usb_setup_packet *setup, uint8_t *buffer, uint32_t buflen)
{
uint8_t old_ep_index;
@@ -269,7 +311,7 @@ void musb_control_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb
musb_set_active_ep(bus, old_ep_index);
}
void musb_bulk_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
int musb_bulk_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
{
uint8_t old_ep_index;
uint8_t speed = USB_TXTYPE1_SPEED_FULL;
@@ -286,6 +328,11 @@ void musb_bulk_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *ur
}
if (urb->ep->bEndpointAddress & 0x80) {
if ((8 << HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET)) < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
USB_LOG_ERR("Ep %02x fifo is overflow\r\n", urb->ep->bEndpointAddress);
return -USB_ERR_RANGE;
}
HWREGB(USB_RXADDR_BASE(chidx)) = urb->hport->dev_addr;
HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_BULK;
HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = 0;
@@ -296,6 +343,11 @@ void musb_bulk_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *ur
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) |= (1 << chidx);
} else {
if ((8 << HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET)) < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
USB_LOG_ERR("Ep %02x fifo is overflow\r\n", urb->ep->bEndpointAddress);
return -USB_ERR_RANGE;
}
HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr;
HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_BULK;
HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = 0;
@@ -313,9 +365,10 @@ void musb_bulk_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *ur
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << chidx);
}
musb_set_active_ep(bus, old_ep_index);
return 0;
}
void musb_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
int musb_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *urb, uint8_t *buffer, uint32_t buflen)
{
uint8_t old_ep_index;
uint8_t speed = USB_TXTYPE1_SPEED_FULL;
@@ -332,6 +385,11 @@ void musb_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *ur
}
if (urb->ep->bEndpointAddress & 0x80) {
if ((8 << HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET)) < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
USB_LOG_ERR("Ep %02x fifo is overflow\r\n", urb->ep->bEndpointAddress);
return -USB_ERR_RANGE;
}
HWREGB(USB_RXADDR_BASE(chidx)) = urb->hport->dev_addr;
HWREGB(USB_BASE + MUSB_IND_RXTYPE_OFFSET) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_INT;
HWREGB(USB_BASE + MUSB_IND_RXINTERVAL_OFFSET) = urb->ep->bInterval;
@@ -342,6 +400,11 @@ void musb_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *ur
HWREGH(USB_BASE + MUSB_RXIE_OFFSET) |= (1 << chidx);
} else {
if ((8 << HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET)) < USB_GET_MAXPACKETSIZE(urb->ep->wMaxPacketSize)) {
USB_LOG_ERR("Ep %02x fifo is overflow\r\n", urb->ep->bEndpointAddress);
return -USB_ERR_RANGE;
}
HWREGB(USB_TXADDR_BASE(chidx)) = urb->hport->dev_addr;
HWREGB(USB_BASE + MUSB_IND_TXTYPE_OFFSET) = (urb->ep->bEndpointAddress & 0x0f) | speed | USB_TXTYPE1_PROTO_INT;
HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = urb->ep->bInterval;
@@ -359,6 +422,7 @@ void musb_intr_urb_init(struct usbh_bus *bus, uint8_t chidx, struct usbh_urb *ur
HWREGH(USB_BASE + MUSB_TXIE_OFFSET) |= (1 << chidx);
}
musb_set_active_ep(bus, old_ep_index);
return 0;
}
static int usbh_reset_port(struct usbh_bus *bus, const uint8_t port)
@@ -420,7 +484,9 @@ __WEAK void usb_hc_low_level_deinit(struct usbh_bus *bus)
int usb_hc_init(struct usbh_bus *bus)
{
uint8_t regval;
uint32_t fifo_offset = 0;
uint16_t offset = 0;
uint8_t cfg_num;
struct musb_fifo_cfg *cfg;
memset(&g_musb_hcd[bus->hcd.hcd_id], 0, sizeof(struct musb_hcd));
@@ -430,21 +496,16 @@ int usb_hc_init(struct usbh_bus *bus)
usb_hc_low_level_init(bus);
musb_set_active_ep(bus, 0);
HWREGB(USB_BASE + MUSB_IND_TXINTERVAL_OFFSET) = 0;
HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_64;
HWREGH(USB_BASE + MUSB_TXFIFOADD_OFFSET) = 0;
HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_64;
HWREGH(USB_BASE + MUSB_RXFIFOADD_OFFSET) = 0;
fifo_offset += 64;
cfg_num = usbh_get_musb_fifo_cfg(&cfg);
for (uint8_t i = 1; i < CONIFG_USB_MUSB_PIPE_NUM; i++) {
musb_set_active_ep(bus, i);
HWREGB(USB_BASE + MUSB_TXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_512;
HWREGH(USB_BASE + MUSB_TXFIFOADD_OFFSET) = fifo_offset;
HWREGB(USB_BASE + MUSB_RXFIFOSZ_OFFSET) = USB_TXFIFOSZ_SIZE_512;
HWREGH(USB_BASE + MUSB_RXFIFOADD_OFFSET) = fifo_offset;
fifo_offset += 512;
for (uint8_t i = 0; i < cfg_num; i++) {
offset = usbh_musb_fifo_config(bus, &cfg[i], offset);
}
if (offset > usb_get_musb_ram_size()) {
USB_LOG_ERR("offset:%d is overflow, please check your table\r\n", offset);
while (1) {
}
}
/* Enable USB interrupts */
@@ -652,10 +713,16 @@ int usbh_submit_urb(struct usbh_urb *urb)
musb_control_urb_init(bus, 0, urb, urb->setup, urb->transfer_buffer, urb->transfer_buffer_length);
break;
case USB_ENDPOINT_TYPE_BULK:
musb_bulk_urb_init(bus, chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
ret = musb_bulk_urb_init(bus, chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
if (ret < 0) {
return ret;
}
break;
case USB_ENDPOINT_TYPE_INTERRUPT:
musb_intr_urb_init(bus, chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
ret = musb_intr_urb_init(bus, chidx, urb, urb->transfer_buffer, urb->transfer_buffer_length);
if (ret < 0) {
return ret;
}
break;
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
return -USB_ERR_NOTSUPP;
@@ -919,7 +986,7 @@ void USBH_IRQHandler(uint8_t busid)
handle_ep0(bus);
}
for (ep_idx = 1; ep_idx < CONIFG_USB_MUSB_PIPE_NUM; ep_idx++) {
for (ep_idx = 1; ep_idx < CONFIG_USBHOST_PIPE_NUM; ep_idx++) {
if (txis & (1 << ep_idx)) {
HWREGH(USB_BASE + MUSB_TXIS_OFFSET) = (1 << ep_idx);
@@ -965,7 +1032,7 @@ void USBH_IRQHandler(uint8_t busid)
}
rxis &= HWREGH(USB_BASE + MUSB_RXIE_OFFSET);
for (ep_idx = 1; ep_idx < CONIFG_USB_MUSB_PIPE_NUM; ep_idx++) {
for (ep_idx = 1; ep_idx < CONFIG_USBHOST_PIPE_NUM; ep_idx++) {
if (rxis & (1 << ep_idx)) {
HWREGH(USB_BASE + MUSB_RXIS_OFFSET) = (1 << ep_idx); // clear isr flag