summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-08-11 19:21:24 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-08-11 19:21:24 +0200
commit737dafe7dfbc6c1e3dc54d8685bc5dffbcf13342 (patch)
tree39f60d0aa4a9fe315ce96ea93066c91b1b794991
parent1b1692ff06a563db90e812a4edf8c1434bc4976d (diff)
downloadrockbox-737dafe.tar.gz
rockbox-737dafe.zip
Revert "rk27xx: implement usb driver"
This reverts commit 310f9e068d58d3113358e86d6dd239500cdd11c4.
-rw-r--r--firmware/export/config.h4
-rw-r--r--firmware/export/rk27xx.h5
-rw-r--r--firmware/target/arm/rk27xx/usb-drv-rk27xx.c714
-rw-r--r--firmware/target/arm/rk27xx/usb-rk27xx.c14
4 files changed, 288 insertions, 449 deletions
diff --git a/firmware/export/config.h b/firmware/export/config.h
index c252b44f4e..7252d62c5e 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -834,6 +834,7 @@ Lyre prototype 1 */
#define USB_STATUS_BY_EVENT
#define USB_DETECT_BY_REQUEST
#elif CONFIG_USBOTG == USBOTG_RK27XX
+#define USB_STATUS_BY_EVENT
#define USB_DETECT_BY_REQUEST
#endif /* CONFIG_USB == */
#endif /* HAVE_USBSTACK */
@@ -1068,8 +1069,7 @@ Lyre prototype 1 */
#elif (CONFIG_USBOTG == USBOTG_ARC) || \
(CONFIG_USBOTG == USBOTG_JZ4740) || \
(CONFIG_USBOTG == USBOTG_M66591) || \
- (CONFIG_USBOTG == USBOTG_AS3525) || \
- (CONFIG_USBOTG == USBOTG_RK27XX)
+ (CONFIG_USBOTG == USBOTG_AS3525)
#define USB_HAS_BULK
#define USB_HAS_INTERRUPT
#elif defined(CPU_TCC780X) || defined(CPU_TCC77X)
diff --git a/firmware/export/rk27xx.h b/firmware/export/rk27xx.h
index dc6bca7cbd..58b3fe8166 100644
--- a/firmware/export/rk27xx.h
+++ b/firmware/export/rk27xx.h
@@ -8,8 +8,7 @@
#define FLASH_BANK1 0x11000000
#define USB_NUM_ENDPOINTS 16
-/* cache aligned */
-#define USB_DEVBSS_ATTR __attribute__((aligned(CACHEALIGN_SIZE)))
+#define USB_DEVBSS_ATTR
/* Timers */
#define APB0_TIMER (ARM_BUS0_BASE + 0x00000000)
@@ -812,7 +811,6 @@
#define RXVOIDINTEN (1<<5)
#define RXERRINTEN (1<<6)
#define RXACKINTEN (1<<7)
-#define RXCFINTE (1<<12)
/* bits 31:8 reserved for EP0 */
/* bits 31:14 reserved for others */
@@ -835,7 +833,6 @@
#define TXERRINTEN (1<<5)
#define TXACKINTEN (1<<6)
#define TXDMADNEN (1<<7) /* reserved for EP0 */
-#define TXCFINTE (1<<12)
/* bits 31:8 reserved */
/* TXnBUF bits */
diff --git a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c
index af613e7024..9380f54193 100644
--- a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c
+++ b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c
@@ -5,9 +5,9 @@
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
+ * $Id$
*
* Copyright (C) 2011 by Marcin Bukat
- * Copyright (C) 2012 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -28,12 +28,13 @@
#include "kernel.h"
#include "panic.h"
+//#include "usb-s3c6400x.h"
+
#include "usb_ch9.h"
#include "usb_core.h"
#include <inttypes.h>
#include "power.h"
-/*#define LOGF_ENABLE*/
#include "logf.h"
typedef volatile uint32_t reg32;
@@ -58,16 +59,6 @@ typedef volatile uint32_t reg32;
#define IIN_DMAINCTL(ep_num) (*(reg32*)(AHB0_UDC+0x84+0x38*((ep_num/3)-1)))
#define IIN_DMAINLMADDR(ep_num) (*(reg32*)(AHB0_UDC+0x88+0x38*((ep_num/3)-1)))
-#define USB_FULL_SPEED 0
-#define USB_HIGH_SPEED 1
-
-/* max allowed packet size definitions */
-#define CTL_MAX_SIZE 64
-#define BLK_HS_MAX_SIZE 512
-#define BLK_FS_MAX_SIZE 64
-#define INT_HS_MAX_SIZE 1024
-#define INT_FS_MAX_SIZE 64
-
#ifdef LOGF_ENABLE
#define XFER_DIR_STR(dir) ((dir) ? "IN" : "OUT")
#define XFER_TYPE_STR(type) \
@@ -80,7 +71,6 @@ typedef volatile uint32_t reg32;
struct endpoint_t {
const int type; /* EP type */
const int dir; /* DIR_IN/DIR_OUT */
- const unsigned int intr_mask;
bool allocated; /* flag to mark EPs taken */
volatile void *buf; /* tx/rx buffer address */
volatile int len; /* size of the transfer (bytes) */
@@ -90,33 +80,30 @@ struct endpoint_t {
};
static struct endpoint_t ctrlep[2] = {
- {USB_ENDPOINT_XFER_CONTROL, DIR_OUT, 0, true, NULL, 0, 0, true, {0, 0, 0}},
- {USB_ENDPOINT_XFER_CONTROL, DIR_IN, 0, true, NULL, 0, 0, true, {0, 0, 0}}
+ {USB_ENDPOINT_XFER_CONTROL, DIR_OUT, true, NULL, 0, 0, true, {0, 0, 0}},
+ {USB_ENDPOINT_XFER_CONTROL, DIR_IN, true, NULL, 0, 0, true, {0, 0, 0}}
};
static struct endpoint_t endpoints[16] = {
- {USB_ENDPOINT_XFER_CONTROL, 3, 0, true, NULL, 0, 0, true, {0, 0, 0}}, /* stub */
- {USB_ENDPOINT_XFER_BULK, DIR_OUT, BOUT1_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT1 */
- {USB_ENDPOINT_XFER_BULK, DIR_IN, BIN2_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN2 */
- {USB_ENDPOINT_XFER_INT, DIR_IN, IIN3_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN3 */
- {USB_ENDPOINT_XFER_BULK, DIR_OUT, BOUT4_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT4 */
- {USB_ENDPOINT_XFER_BULK, DIR_IN, BIN5_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN5 */
- {USB_ENDPOINT_XFER_INT, DIR_IN, IIN6_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN6 */
- {USB_ENDPOINT_XFER_BULK, DIR_OUT, BOUT7_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT7 */
- {USB_ENDPOINT_XFER_BULK, DIR_IN, BIN8_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN8 */
- {USB_ENDPOINT_XFER_INT, DIR_IN, IIN9_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN9 */
- {USB_ENDPOINT_XFER_BULK, DIR_OUT, BOUT10_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT10 */
- {USB_ENDPOINT_XFER_BULK, DIR_IN, BIN11_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN11 */
- {USB_ENDPOINT_XFER_INT, DIR_IN, IIN12_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN12 */
- {USB_ENDPOINT_XFER_BULK, DIR_OUT, BOUT13_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT13 */
- {USB_ENDPOINT_XFER_BULK, DIR_IN, BIN14_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN14 */
- {USB_ENDPOINT_XFER_INT, DIR_IN, IIN15_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN15 */
+ {USB_ENDPOINT_XFER_CONTROL, 3, true, NULL, 0, 0, true, {0, 0, 0}}, /* stub */
+ {USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT1 */
+ {USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN2 */
+ {USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN3 */
+ {USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT4 */
+ {USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN5 */
+ {USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN6 */
+ {USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT7 */
+ {USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN8 */
+ {USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN9 */
+ {USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT10 */
+ {USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN11 */
+ {USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN12 */
+ {USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT13 */
+ {USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN14 */
+ {USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN15 */
};
-static volatile bool set_address = false;
-static volatile bool set_configuration = false;
-
-static void setup_irq_handler(void)
+static void setup_received(void)
{
static uint32_t setup_data[2];
@@ -124,6 +111,10 @@ static void setup_irq_handler(void)
setup_data[0] = SETUP1;
setup_data[1] = SETUP2;
+ /* clear all pending control transfers
+ * do we need this here?
+ */
+
/* pass setup data to the upper layer */
usb_core_control_request((struct usb_ctrlrequest*)setup_data);
}
@@ -131,12 +122,12 @@ static void setup_irq_handler(void)
/* service ep0 IN transaction */
static void ctr_write(void)
{
- int xfer_size = MIN(ctrlep[DIR_IN].cnt, CTL_MAX_SIZE);
+ int xfer_size = (ctrlep[DIR_IN].cnt > 64) ? 64 : ctrlep[DIR_IN].cnt;
unsigned int timeout = current_tick + HZ/10;
while (TX0BUF & TXFULL) /* TX0FULL flag */
{
- if (TIME_AFTER(current_tick, timeout))
+ if(TIME_AFTER(current_tick, timeout))
break;
}
@@ -152,7 +143,7 @@ static void ctr_write(void)
* get zero len after transfer which indicates we need to send
* zero length packet to signal host end of the transfer.
*/
- ctrlep[DIR_IN].cnt -= CTL_MAX_SIZE;
+ ctrlep[DIR_IN].cnt -= 64;
ctrlep[DIR_IN].buf += xfer_size;
}
@@ -170,147 +161,60 @@ static void ctr_read(void)
RX0DMACTLO = DMA_START; /* start DMA */
}
-static void blk_write(int ep_num)
+static void blk_write(int ep)
{
+ int ep_num = EP_NUM(ep);
+ int max = usb_drv_port_speed() ? 512 : 64;
+ int xfer_size = (endpoints[ep_num].cnt > max) ? max : endpoints[ep_num].cnt;
unsigned int timeout = current_tick + HZ/10;
- int max = usb_drv_port_speed() ? BLK_HS_MAX_SIZE : BLK_FS_MAX_SIZE;
- int xfer_size = MIN(endpoints[ep_num].cnt, max);
-
+
while (BIN_TXBUF(ep_num) & TXFULL) /* TXFULL flag */
{
- if (TIME_AFTER(current_tick, timeout))
+ if(TIME_AFTER(current_tick, timeout))
break;
}
-
+
BIN_TXSTAT(ep_num) = xfer_size; /* size */
BIN_DMAINLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf; /* buf address */
BIN_DMAINCTL(ep_num) = DMA_START; /* start DMA */
BIN_TXCON(ep_num) &= ~TXNAK; /* clear NAK */
-
+
/* Decrement by max packet size is intentional.
- * This way if we have final packet short one we will get negative len
- * after transfer, which in turn indicates we *don't* need to send
- * zero length packet. If the final packet is max sized packet we will
- * get zero len after transfer which indicates we need to send
- * zero length packet to signal host end of the transfer.
- */
+ * This way if we have final packet short one we will get negative len
+ * after transfer, which in turn indicates we *don't* need to send
+ * zero length packet. If the final packet is max sized packet we will
+ * get zero len after transfer which indicates we need to send
+ * zero length packet to signal host end of the transfer.
+ */
endpoints[ep_num].cnt -= max;
endpoints[ep_num].buf += xfer_size;
}
-static void blk_in_irq_handler(int ep_num)
-{
- uint32_t txstat = BIN_TXSTAT(ep_num);
- struct endpoint_t *endp = &endpoints[ep_num];
-
- if (txstat & TXERR)
- {
- panicf("error condition ep%d, %ld", ep_num, current_tick);
- }
-
- if (txstat & TXCFINT)
- {
- logf("blk_write: cf(0x%x), %ld", ep_num, current_tick);
- /* bit cleared by read */
- usb_drv_stall(ep_num, false, true);
- }
-
- if (txstat & TXACK) /* check TxACK flag */
- {
- if (endp->cnt > 0)
- {
- logf("blk_write: ack(0x%x), %ld", ep_num, current_tick);
- /* we still have data to send (or ZLP) */
- blk_write(ep_num);
- }
- else
- {
- logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_IN, 0, 0x%x), %ld",
- ep_num, endp->len, current_tick);
-
- /* final ack received */
- usb_core_transfer_complete(ep_num, /* ep */
- USB_DIR_IN, /* dir */
- 0, /* status */
- endp->len); /* length */
-
- /* release semaphore for blocking transfer */
- if (endp->block)
- {
- logf("udc_intr: ep=0x%x, semaphore_release(), %ld",
- ep_num, current_tick);
-
- semaphore_release(&endp->complete);
- }
- }
- }
-}
-
-static void blk_out_irq_handler(int ep_num)
+static void blk_read(int ep)
{
- uint32_t rxstat = BOUT_RXSTAT(ep_num);
- int xfer_size = rxstat & 0xffff;
- int max = usb_drv_port_speed() ? BLK_HS_MAX_SIZE : BLK_FS_MAX_SIZE;
- struct endpoint_t *endp = &endpoints[ep_num];
-
- if (rxstat & RXERR)
- {
- panicf("error condition ep%d, %ld", ep_num, current_tick);
- }
-
- if (rxstat & RXOVF)
- {
- panicf("rxovf ep%d, %ld", ep_num, current_tick);
- }
-
- if (rxstat & RXCFINT)
- {
- logf("blk_read:cf(0x%x), %ld", ep_num, current_tick);
- usb_drv_stall(ep_num, false, false);
- }
-
- if ((rxstat & RXACK) && endp->cnt > 0)
- {
- logf("blk_read:ack(0x%x,0x%x), %ld", ep_num, xfer_size, current_tick);
-
- /* clear NAK bit */
- BOUT_RXCON(ep_num) &= ~RXNAK;
-
- endp->cnt -= xfer_size;
- endp->buf += xfer_size;
-
- /* if the transfer was short or if the total count is zero,
- * transfer is complete
- */
- if (endp->cnt == 0 || xfer_size < max)
- {
- logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_OUT, 0, 0x%x), %ld",
- ep_num, endp->len, current_tick);
-
- usb_core_transfer_complete(ep_num, /* ep */
- USB_DIR_OUT, /* dir */
- 0, /* status */
- endp->len - endp->cnt); /* length */
- endp->cnt = 0;
- }
- else
- {
- BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)endp->buf;
- BOUT_DMAOUTCTL(ep_num) = DMA_START;
- }
- }
+ int ep_num = EP_NUM(ep);
+ int xfer_size = BOUT_RXSTAT(ep_num) & 0xffff;
+
+ /* clear NAK bit */
+ BOUT_RXCON(ep_num) &= ~RXNAK;
+
+ endpoints[ep_num].cnt -= xfer_size;
+ endpoints[ep_num].buf += xfer_size;
+
+ BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf;
+ BOUT_DMAOUTCTL(ep_num) = DMA_START;
}
static void int_write(int ep)
{
int ep_num = EP_NUM(ep);
- int max = usb_drv_port_speed() ? INT_HS_MAX_SIZE : INT_FS_MAX_SIZE;
- int xfer_size = MIN(endpoints[ep_num].cnt, max);
+ int max = usb_drv_port_speed() ? 1024 : 64;
+ int xfer_size = (endpoints[ep_num].cnt > max) ? max : endpoints[ep_num].cnt;
unsigned int timeout = current_tick + HZ/10;
- while (IIN_TXBUF(ep_num) & TXFULL)
+ while (IIN_TXBUF(ep_num) & TXFULL) /* TXFULL flag */
{
- if (TIME_AFTER(current_tick, timeout))
+ if(TIME_AFTER(current_tick, timeout))
break;
}
@@ -330,99 +234,167 @@ static void int_write(int ep)
endpoints[ep_num].buf += xfer_size;
}
-static void int_in_irq_handler(int ep_num)
+/* UDC ISR function */
+void INT_UDC(void)
{
- uint32_t txstat = IIN_TXSTAT(ep_num);
- struct endpoint_t *endp = &endpoints[ep_num];
-
- if (txstat & TXCFINT)
+ uint32_t txstat, rxstat;
+ int tmp, ep_num;
+
+ /* read what caused UDC irq */
+ uint32_t intsrc = INT2FLAG & 0x7fffff;
+
+ if (intsrc & SETUP_INTR) /* setup interrupt */
{
- logf("int_write: cf(0x%x), %ld", ep_num, current_tick);
- /* bit cleared by read */
- usb_drv_stall(ep_num, false, true);
+ setup_received();
}
-
- if (txstat & TXERR)
+ else if (intsrc & IN0_INTR) /* ep0 in interrupt */
{
- panicf("error condition ep%d, %ld", ep_num, current_tick);
+ txstat = TX0STAT; /* read clears flags */
+
+ /* TODO handle errors */
+ if (txstat & TXACK) /* check TxACK flag */
+ {
+ if (ctrlep[DIR_IN].cnt >= 0)
+ {
+ /* we still have data to send (or ZLP) */
+ ctr_write();
+ }
+ else
+ {
+ /* final ack received */
+ usb_core_transfer_complete(0, /* ep */
+ USB_DIR_IN, /* dir */
+ 0, /* status */
+ ctrlep[DIR_IN].len); /* length */
+
+ /* release semaphore for blocking transfer */
+ if (ctrlep[DIR_IN].block)
+ semaphore_release(&ctrlep[DIR_IN].complete);
+ }
+ }
}
+ else if (intsrc & OUT0_INTR) /* ep0 out interrupt */
+ {
+ rxstat = RX0STAT;
- if (txstat & TXACK) /* check TxACK flag */
+ /* TODO handle errors */
+ if (rxstat & RXACK) /* RxACK */
+ {
+ if (ctrlep[DIR_OUT].cnt > 0)
+ ctr_read();
+ else
+ usb_core_transfer_complete(0, /* ep */
+ USB_DIR_OUT, /* dir */
+ 0, /* status */
+ ctrlep[DIR_OUT].len); /* length */
+ }
+ }
+ else if (intsrc & USBRST_INTR) /* usb reset */
{
- if (endp->cnt > 0)
+ usb_drv_init();
+ }
+ else if (intsrc & RESUME_INTR) /* usb resume */
+ {
+ TX0CON |= TXCLR; /* TxClr */
+ TX0CON &= ~TXCLR;
+ RX0CON |= RXCLR; /* RxClr */
+ RX0CON &= ~RXCLR;
+ }
+ else if (intsrc & SUSP_INTR) /* usb suspend */
+ {
+ }
+ else if (intsrc & CONN_INTR) /* usb connect */
+ {
+ }
+ else
+ {
+ /* lets figure out which ep generated irq */
+ tmp = intsrc >> 7;
+ for (ep_num=1; ep_num < 15; ep_num++)
{
- logf("int_write: ack(0x%x), %ld", ep_num, current_tick);
- /* we still have data to send (or ZLP) */
- int_write(ep_num);
+ tmp >>= ep_num;
+ if (tmp & 0x01)
+ break;
}
- else
+
+ if (intsrc & ((1<<8)|(1<<11)|(1<<14)|(1<<17)|(1<<20)))
{
- logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_IN, 0, 0x%x), %ld",
- ep_num, endp->len, current_tick);
-
- /* final ack received */
- usb_core_transfer_complete(ep_num, /* ep */
- USB_DIR_IN, /* dir */
- 0, /* status */
- endp->len); /* length */
-
- /* release semaphore for blocking transfer */
- if (endp->block)
+ /* bulk out */
+ rxstat = BOUT_RXSTAT(ep_num);
+
+ /* TODO handle errors */
+ if (rxstat & (1<<18)) /* RxACK */
{
- logf("udc_intr: ep=0x%x, semaphore_release(), %ld",
- ep_num, current_tick);
-
- semaphore_release(&endp->complete);
+ if (endpoints[ep_num].cnt > 0)
+ blk_read(ep_num);
+ else
+ usb_core_transfer_complete(ep_num, /* ep */
+ USB_DIR_OUT, /* dir */
+ 0, /* status */
+ endpoints[ep_num].len); /* length */
}
}
- }
-}
-
-static void udc_phy_reset(void)
-{
- DEV_CTL |= SOFT_POR;
- udelay(10000); /* min 10ms */
- DEV_CTL &= ~SOFT_POR;
-}
-
-static void udc_soft_connect(void)
-{
- DEV_CTL |= CSR_DONE |
- DEV_SOFT_CN |
- DEV_SELF_PWR;
-}
-
-static void udc_helper(void)
-{
- uint32_t dev_info = DEV_INFO;
-
- /* This polls for DEV_EN bit set in DEV_INFO register
- * as well as tracks current requested configuration
- * (DEV_INFO [11:8]). On state change it notifies usb stack
- * about it.
- */
-
- /* SET ADDRESS request */
- if (set_address == false)
- if ((dev_info & 0x7f))
+ else if (intsrc & ((1<<9)|(1<<12)|(1<<15)|(1<<18)|(1<<21)))
{
- set_address = true;
- usb_core_notify_set_address(dev_info & 0x7f);
+ /* bulk in */
+ txstat = BIN_TXSTAT(ep_num);
+
+ /* TODO handle errors */
+ if (txstat & (1<<18)) /* check TxACK flag */
+ {
+ if (endpoints[ep_num].cnt >= 0)
+ {
+ /* we still have data to send (or ZLP) */
+ blk_write(ep_num);
+ }
+ else
+ {
+ /* final ack received */
+ usb_core_transfer_complete(ep_num, /* ep */
+ USB_DIR_IN, /* dir */
+ 0, /* status */
+ endpoints[ep_num].len); /* length */
+
+ /* release semaphore for blocking transfer */
+ if (endpoints[ep_num].block)
+ semaphore_release(&endpoints[ep_num].complete);
+ }
+ }
}
-
- /* SET CONFIGURATION request */
- if (set_configuration == false)
- if (dev_info & DEV_EN)
+ else if (intsrc & ((1<<10)|(1<13)|(1<<16)|(1<<19)|(1<<22)))
{
- set_configuration = true;
- usb_core_notify_set_config(((dev_info >> 7) & 0xf) + 1);
+ /* int in */
+ txstat = IIN_TXSTAT(ep_num);
+
+ /* TODO handle errors */
+ if (txstat & TXACK) /* check TxACK flag */
+ {
+ if (endpoints[ep_num].cnt >= 0)
+ {
+ /* we still have data to send (or ZLP) */
+ int_write(ep_num);
+ }
+ else
+ {
+ /* final ack received */
+ usb_core_transfer_complete(ep_num, /* ep */
+ USB_DIR_IN, /* dir */
+ 0, /* status */
+ endpoints[ep_num].len); /* length */
+
+ /* release semaphore for blocking transfer */
+ if (endpoints[ep_num].block)
+ semaphore_release(&endpoints[ep_num].complete);
+ }
+ }
}
+ }
}
-/* return port speed */
+/* return port speed FS=0, HS=1 */
int usb_drv_port_speed(void)
{
- return ((DEV_INFO & DEV_SPEED) ? USB_FULL_SPEED : USB_HIGH_SPEED);
+ return ((DEV_INFO & DEV_SPEED) == 0) ? 0 : 1;
}
/* Reserve endpoint */
@@ -438,7 +410,7 @@ int usb_drv_request_endpoint(int type, int dir)
logf("req: %s %s", XFER_DIR_STR(ep_dir), XFER_TYPE_STR(ep_type));
/* Find an available ep/dir pair */
- for (ep_num = 1; ep_num < USB_NUM_ENDPOINTS; ep_num++)
+ for (ep_num=1;ep_num<USB_NUM_ENDPOINTS;ep_num++)
{
struct endpoint_t* endpoint = &endpoints[ep_num];
@@ -448,35 +420,7 @@ int usb_drv_request_endpoint(int type, int dir)
{
/* mark endpoint as taken */
endpoint->allocated = true;
-
- if (ep_num%3 == 0) /* IIN 3, 6, 9, 12, 15 */
- {
- IIN_TXCON(ep_num) = (ep_num<<8) | /* set ep number */
- TXERRINTEN |
- TXEPEN | /* endpoint enable */
- TXNAK | /* respond with NAK */
- TXACKINTEN | /* irq on ACK */
- TXCFINTE; /* irq on Clear feature */
- }
- else if (ep_num%3 == 1) /* BOUT 1, 4, 7, 10, 13 */
- {
- BOUT_RXCON(ep_num) = (ep_num<<8) | /* set ep number */
- RXERRINTEN |
- RXEPEN | /* endpoint enable */
- RXNAK | /* respond with NAK */
- RXACKINTEN | /* irq on ACK */
- RXCFINTE; /* irq on Clear feature */
- }
- else if (ep_num%3 == 2) /* BIN 2, 5, 8, 11, 14 */
- {
- BIN_TXCON(ep_num) = (ep_num<<8) | /* set ep number */
- TXERRINTEN |
- TXEPEN | /* endpoint enable */
- TXNAK | /* respond with NAK */
- TXACKINTEN | /* irq on ACK */
- TXCFINTE; /* irq on Clear feature */
- }
-
+
/* enable interrupt from this endpoint */
EN_INT |= (1<<(ep_num+7));
@@ -491,7 +435,10 @@ int usb_drv_request_endpoint(int type, int dir)
void usb_drv_release_endpoint(int ep)
{
int ep_num = EP_NUM(ep);
- logf("rel: ep%d %s", ep_num, XFER_DIR_STR(EP_DIR(ep)));
+ int ep_dir = EP_DIR(ep);
+ (void) ep_dir;
+
+ logf("rel: ep%d %s", ep_num, XFER_DIR_STR(ep_dir));
endpoints[ep_num].allocated = false;
/* disable interrupt from this endpoint */
@@ -507,20 +454,14 @@ void usb_drv_release_endpoint(int ep)
void usb_drv_set_address(int address)
{
(void)address;
- /* UDC sets this automaticaly */
+ /* UDC seems to set this automaticaly */
}
static int _usb_drv_send(int endpoint, void *ptr, int length, bool block)
{
struct endpoint_t *ep;
int ep_num = EP_NUM(endpoint);
-
- /* for send transfers, make sure the data is committed */
- commit_discard_dcache_range(ptr, length);
-
- logf("_usb_drv_send: endpt=0x%x, len=0x%x, block=%d",
- endpoint, length, block);
-
+
if (ep_num == 0)
ep = &ctrlep[DIR_IN];
else
@@ -536,7 +477,7 @@ static int _usb_drv_send(int endpoint, void *ptr, int length, bool block)
switch (ep->type)
{
- case USB_ENDPOINT_XFER_CONTROL:
+ case USB_ENDPOINT_XFER_CONTROL:
ctr_write();
break;
@@ -574,40 +515,30 @@ int usb_drv_recv(int endpoint, void* ptr, int length)
struct endpoint_t *ep;
int ep_num = EP_NUM(endpoint);
- logf("usb_drv_recv: endpt=0x%x, len=0x%x, %ld",
- endpoint, length, current_tick);
-
- /* for recv, discard the cache lines related to the buffer */
- commit_discard_dcache_range(ptr, length);
-
if (ep_num == 0)
{
ep = &ctrlep[DIR_OUT];
- ep->buf = ptr;
- ep->len = ep->cnt = length;
-
- /* clear NAK bit */
- RX0CON &= ~RXNAK;
- RX0DMAOUTLMADDR = (uint32_t)ptr; /* buffer address */
- RX0DMACTLO = DMA_START; /* start DMA */
+
+ ctr_read();
}
else
{
ep = &endpoints[ep_num];
- ep->buf = ptr;
- ep->len = ep->cnt = length;
-
+
/* clear NAK bit */
BOUT_RXCON(ep_num) &= ~RXNAK;
BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)ptr;
BOUT_DMAOUTCTL(ep_num) = DMA_START;
}
+
+ ep->buf = ptr;
+ ep->len = ep->cnt = length;
return 0;
}
/* Kill all transfers. Usually you need to set a bit for each endpoint
- * and flush fifos. You should also call the completion handler with
+ * and flush fifos. You should also call the completion handler with
* error status for everything
*/
void usb_drv_cancel_all_transfers(void)
@@ -661,8 +592,6 @@ bool usb_drv_stalled(int endpoint, bool in)
void usb_drv_stall(int endpoint, bool stall, bool in)
{
int ep_num = EP_NUM(endpoint);
- logf("usb_drv: %sstall EP%d %s",
- stall ? "": "un", ep_num, in ? "IN" : "OUT");
switch (endpoints[ep_num].type)
{
@@ -716,23 +645,87 @@ void usb_drv_stall(int endpoint, bool stall, bool in)
void usb_drv_init(void)
{
int ep_num;
+
+ /* enable USB clock */
+ SCU_CLKCFG &= ~CLKCFG_UDC;
+
+ /* 1. do soft disconnect */
+ DEV_CTL = DEV_SELF_PWR;
+
+ /* 2. do power on reset to PHY */
+ DEV_CTL = DEV_SELF_PWR |
+ SOFT_POR;
+
+ /* 3. wait more than 10ms */
+ udelay(20000);
+
+ /* 4. clear SOFT_POR bit */
+ DEV_CTL &= ~SOFT_POR;
+
+ /* 5. configure minimal EN_INT */
+ EN_INT = EN_SUSP_INTR | /* Enable Suspend Interrupt */
+ EN_RESUME_INTR | /* Enable Resume Interrupt */
+ EN_USBRST_INTR | /* Enable USB Reset Interrupt */
+ EN_OUT0_INTR | /* Enable OUT Token receive Interrupt EP0 */
+ EN_IN0_INTR | /* Enable IN Token transmits Interrupt EP0 */
+ EN_SETUP_INTR; /* Enable SETUP Packet Receive Interrupt */
+
+ /* 6. configure INTCON */
+ INTCON = UDC_INTHIGH_ACT | /* interrupt high active */
+ UDC_INTEN; /* enable EP0 interrupts */
+
+ /* 7. configure EP0 control registers */
+ TX0CON = TXACKINTEN | /* Set as one to enable the EP0 tx irq */
+ TXNAK; /* Set as one to response NAK handshake */
+
+ RX0CON = RXACKINTEN |
+ RXEPEN | /* Endpoint 0 Enable. When cleared the endpoint does
+ * not respond to an SETUP or OUT token
+ */
+
+ RXNAK; /* Set as one to response NAK handshake */
+
+ /* 8. write final bits to DEV_CTL */
+ DEV_CTL = CSR_DONE | /* Configure CSR done */
+ DEV_PHY16BIT | /* 16-bit data path enabled. udc_clk = 30MHz */
+ DEV_SOFT_CN | /* Device soft connect */
+ DEV_SELF_PWR; /* Device self power */
/* init semaphore of ep0 */
semaphore_init(&ctrlep[DIR_OUT].complete, 1, 0);
semaphore_init(&ctrlep[DIR_IN].complete, 1, 0);
-
- /* init semaphores for other endpoints */
+
for (ep_num = 1; ep_num < USB_NUM_ENDPOINTS; ep_num++)
+ {
semaphore_init(&endpoints[ep_num].complete, 1, 0);
+
+ if (ep_num%3 == 0) /* IIN 3, 6, 9, 12, 15 */
+ {
+ IIN_TXCON(ep_num) |= (ep_num<<8)|TXEPEN|TXNAK; /* ep_num, enable, NAK */
+ }
+ else if (ep_num%3 == 1) /* BOUT 1, 4, 7, 10, 13 */
+ {
+ BOUT_RXCON(ep_num) |= (ep_num<<8)|RXEPEN|RXNAK; /* ep_num, NAK, enable */
+ }
+ else if (ep_num%3 == 2) /* BIN 2, 5, 8, 11, 14 */
+ {
+ BIN_TXCON(ep_num) |= (ep_num<<8)|TXEPEN|TXNAK; /* ep_num, enable, NAK */
+ }
+ }
}
/* turn off usb core */
void usb_drv_exit(void)
{
- /* udc module reset */
- SCU_RSTCFG |= (1<<1);
- udelay(10);
- SCU_RSTCFG &= ~(1<<1);
+ DEV_CTL = DEV_SELF_PWR;
+
+ /* disable USB interrupts in interrupt controller */
+ INTC_IMR &= ~IRQ_ARM_UDC;
+ INTC_IECR &= ~IRQ_ARM_UDC;
+
+ /* we cannot disable UDC clock since this causes data abort
+ * when reading DEV_INFO in order to check usb connect event
+ */
}
int usb_detect(void)
@@ -743,140 +736,3 @@ int usb_detect(void)
return USB_EXTRACTED;
}
-/* UDC ISR function */
-void INT_UDC(void)
-{
- uint32_t txstat, rxstat;
- int ep_num;
-
- /* read what caused UDC irq */
- uint32_t intsrc = INT2FLAG & 0x7fffff;
-
- if (intsrc & USBRST_INTR) /* usb reset */
- {
- logf("udc_int: reset, %ld", current_tick);
-
- EN_INT = EN_SUSP_INTR | /* Enable Suspend Irq */
- EN_RESUME_INTR | /* Enable Resume Irq */
- EN_USBRST_INTR | /* Enable USB Reset Irq */
- EN_OUT0_INTR | /* Enable OUT Token receive Irq EP0 */
- EN_IN0_INTR | /* Enable IN Token transmit Irq EP0 */
- EN_SETUP_INTR; /* Enable SETUP Packet Receive Irq */
-
- INTCON = UDC_INTHIGH_ACT | /* interrupt high active */
- UDC_INTEN; /* enable EP0 irqs */
-
- TX0CON = TXACKINTEN | /* Set as one to enable the EP0 tx irq */
- TXNAK; /* Set as one to response NAK handshake */
-
- RX0CON = RXACKINTEN |
- RXEPEN | /* Endpoint 0 Enable. When cleared the
- * endpoint does not respond to an SETUP
- * or OUT token */
- RXNAK; /* Set as one to response NAK handshake */
-
- set_address = false;
- set_configuration = false;
- }
-
- /* This needs to be processed AFTER usb reset */
- udc_helper();
-
- if (intsrc & SETUP_INTR) /* setup interrupt */
- {
- setup_irq_handler();
- }
-
- if (intsrc & IN0_INTR) /* ep0 in interrupt */
- {
- txstat = TX0STAT; /* read clears flags */
-
- /* TODO handle errors */
- if (txstat & TXACK) /* check TxACK flag */
- {
- if (ctrlep[DIR_IN].cnt >= 0)
- {
- /* we still have data to send (or ZLP) */
- ctr_write();
- }
- else
- {
- /* final ack received */
- usb_core_transfer_complete(0, /* ep */
- USB_DIR_IN, /* dir */
- 0, /* status */
- ctrlep[DIR_IN].len); /* length */
-
- /* release semaphore for blocking transfer */
- if (ctrlep[DIR_IN].block)
- semaphore_release(&ctrlep[DIR_IN].complete);
- }
- }
- }
-
- if (intsrc & OUT0_INTR) /* ep0 out interrupt */
- {
- rxstat = RX0STAT;
-
- /* TODO handle errors */
- if (rxstat & RXACK) /* RxACK */
- {
- if (ctrlep[DIR_OUT].cnt > 0)
- ctr_read();
- else
- usb_core_transfer_complete(0, /* ep */
- USB_DIR_OUT, /* dir */
- 0, /* status */
- ctrlep[DIR_OUT].len); /* length */
- }
- }
-
- if (intsrc & RESUME_INTR) /* usb resume */
- {
- TX0CON |= TXCLR; /* TxClr */
- TX0CON &= ~TXCLR;
-
- RX0CON |= RXCLR; /* RxClr */
- RX0CON &= ~RXCLR;
- }
-
- if (intsrc & SUSP_INTR) /* usb suspend */
- {
- }
-
- if (intsrc & CONN_INTR) /* usb connect */
- {
- udc_phy_reset();
- udelay(10000); /* wait at least 10ms */
- udc_soft_connect();
- }
-
- /* endpoints other then EP0 */
- if (intsrc & 0x7fff00)
- {
- /* lets figure out which ep generated irq */
- for (ep_num = 1; ep_num < USB_NUM_ENDPOINTS; ep_num++)
- {
- struct endpoint_t *ep = &endpoints[ep_num];
-
- if ((intsrc & ep->intr_mask) && ep->allocated)
- {
- switch (ep->type)
- {
- case USB_ENDPOINT_XFER_BULK:
- if (ep->dir == DIR_OUT)
- blk_out_irq_handler(ep_num);
- else
- blk_in_irq_handler(ep_num);
-
- break;
-
- case USB_ENDPOINT_XFER_INT:
- int_in_irq_handler(ep_num);
-
- break;
- }
- }
- }
- }
-}
diff --git a/firmware/target/arm/rk27xx/usb-rk27xx.c b/firmware/target/arm/rk27xx/usb-rk27xx.c
index 09c9090a3b..20bf867c8d 100644
--- a/firmware/target/arm/rk27xx/usb-rk27xx.c
+++ b/firmware/target/arm/rk27xx/usb-rk27xx.c
@@ -32,20 +32,6 @@ int usb_status = USB_EXTRACTED;
void usb_init_device(void)
{
- /* enable UDC interrupt */
- INTC_IMR |= (1<<16);
- INTC_IECR |= (1<<16);
-
- EN_INT = EN_SUSP_INTR | /* Enable Suspend Interrupt */
- EN_RESUME_INTR | /* Enable Resume Interrupt */
- EN_USBRST_INTR | /* Enable USB Reset Interrupt */
- EN_OUT0_INTR | /* Enable OUT Token receive Interrupt EP0 */
- EN_IN0_INTR | /* Enable IN Token transmits Interrupt EP0 */
- EN_SETUP_INTR; /* Enable SETUP Packet Receive Interrupt */
-
- /* configure INTCON */
- INTCON = UDC_INTHIGH_ACT | /* interrupt high active */
- UDC_INTEN; /* enable EP0 interrupts */
}
void usb_attach(void)