From: Kuo-Jung Su
This patch would try to use Faraday FOTG210 to implement
a USB RNDIS Ethernet.
Signed-off-by: Kuo-Jung Su
---
drivers/usb/gadget/Makefile |1 +
drivers/usb/gadget/fotg210.c | 926 +
drivers/usb/gadget/fotg210.h | 99
drivers/usb/gadget/gadget_chips.h |8 +
4 files changed, 1034 insertions(+)
create mode 100644 drivers/usb/gadget/fotg210.c
create mode 100644 drivers/usb/gadget/fotg210.h
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index e545b6b..432cf17 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -35,6 +35,7 @@ endif
# new USB gadget layer dependencies
ifdef CONFIG_USB_GADGET
COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
+COBJS-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o
COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
COBJS-$(CONFIG_DFU_FUNCTION) += f_dfu.o
endif
diff --git a/drivers/usb/gadget/fotg210.c b/drivers/usb/gadget/fotg210.c
new file mode 100644
index 000..640ae55
--- /dev/null
+++ b/drivers/usb/gadget/fotg210.c
@@ -0,0 +1,926 @@
+/*
+ * Faraday USB 2.0 OTG Controller
+ *
+ * (C) Copyright 2010 Faraday Technology
+ * Dante Su
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "fotg210.h"
+
+#define CFG_HALF_SPEED 0
+#define CFG_LOW_TIMING 0
+#define CFG_NUM_ENDPOINTS 4
+#define CFG_EP0_MAX_PACKET_SIZE64
+#define CFG_EPX_MAX_PACKET_SIZE512
+
+struct fotg210_chip;
+
+struct fotg210_ep {
+ struct usb_ep ep;
+
+ uint32_t maxpacket:16;
+ uint32_t id:4;
+ uint32_t stopped:1;
+ uint32_t rsvd:11;
+
+ struct list_head queue;
+ const struct usb_endpoint_descriptor *desc;
+ struct fotg210_chip *chip;
+};
+
+struct fotg210_request {
+ struct usb_request req;
+ struct list_head queue;
+ struct fotg210_ep *ep;
+};
+
+struct fotg210_chip {
+ struct usb_gadget gadget;
+ struct usb_gadget_driver *driver;
+ uint32_t iobase;
+ uint8_t irq;
+ uint16_t addr;
+ int pullup;
+ enum usb_device_state state;
+ struct fotg210_ep ep[1 + CFG_NUM_ENDPOINTS];
+};
+
+static struct usb_endpoint_descriptor ep0_desc = {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes =USB_ENDPOINT_XFER_CONTROL,
+};
+
+#define USB_REG32(chip, off)*(volatile uint32_t *)((chip)->iobase + (off))
+
+static inline int
+fifo_to_ep(struct fotg210_chip *chip, int id, int in)
+{
+ return (id < 0) ? 0 : ((id % 4) + 1);
+}
+
+static inline int
+ep_to_fifo(struct fotg210_chip *chip, int id)
+{
+ return (id <= 0) ? -1 : ((id - 1) % 4);
+}
+
+static inline int
+ep_reset(struct fotg210_chip *chip, uint8_t ep_addr)
+{
+ int ep = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+
+ if (ep_addr & USB_DIR_IN) {
+ /* input */
+ USB_REG32(chip, REG_IEP1 + (ep - 1) * 4) |= BIT(12);
+ USB_REG32(chip, REG_IEP1 + (ep - 1) * 4) &= ~BIT(12);
+ USB_REG32(chip, REG_IEP1 + (ep - 1) * 4) &= ~BIT(11);
+ } else {
+ /* output */
+ USB_REG32(chip, REG_OEP1 + (ep - 1) * 4) |= BIT(12);
+ USB_REG32(chip, REG_OEP1 + (ep - 1) * 4) &= BIT(12);
+ USB_REG32(chip, REG_OEP1 + (ep - 1) * 4) &= BIT(11);
+ }
+
+ return 0;
+}
+
+static int
+fotg210_reset(struct fotg210_chip *chip)
+{
+ chip->state = USB_STATE_POWERED;
+
+ /* device address reset */
+ chip->addr = 0;
+ USB_REG32(chip, REG_DCAR) = 0;
+
+ /* enable the chip and perform a soft reset later */
+ USB_REG32(chip, REG_DCCR) = BIT(5);
+
+ /* set idle counter */
+ USB_REG32(chip, REG_DCIDLE) = 7;
+
+ /* disable interrupts */
+ USB_REG32(chip, REG_HCIER) = 0;
+ USB_REG32(chip, REG_DCIMR) = 0x3;
+ USB_REG32(chip, REG_DCIMR0) = 0x3F;
+ USB_REG32(chip, REG_DCIMR1) = 0xF00FF;
+ USB_REG32(chip, REG_DCIMR2) = 0x7FF;
+
+ /* clear interrupts */
+ USB_REG32(chip, REG_HCISR) = 0x3F;
+ USB_REG32(chip, REG_OTGISR) = 0x1FFF;
+ USB_REG32(chip, REG_DCISR) = 0;
+ USB_REG32(chip, REG_DCISR0) = 0;
+ USB_REG32(chip, REG_DCISR1) = 0;
+ USB_REG32(chip, REG_DCISR2) = 0;
+
+ /* soft reset */
+ USB_REG32(chip, REG_DCCR) |= BIT(4);
+ while (USB_REG32(chip, REG_DCCR) & BIT(4))
+ ;
+
+ /* CX FIFO reset */
+ USB_REG32(chip, REG_DCC