From: Kuo-Jung Su <dant...@faraday-tech.com>

This patch add supports to both Faraday FUSBH200 and FOTG210,
these controllers slightly differ from standard EHCI specification.

Signed-off-by: Kuo-Jung Su <dant...@faraday-tech.com>
CC: Marek Vasut <ma...@denx.de>
---
 common/usb_hub.c                |    5 ++
 drivers/usb/host/Makefile       |    1 +
 drivers/usb/host/ehci-faraday.c |  122 +++++++++++++++++++++++++++++++++++++++
 drivers/usb/host/ehci-hcd.c     |   11 ++++
 drivers/usb/host/ehci.h         |    5 ++
 include/usb/fotg210.h           |   71 +++++++++++++++++++++++
 include/usb/fusbh200.h          |   28 +++++++++
 7 files changed, 243 insertions(+)
 create mode 100644 drivers/usb/host/ehci-faraday.c
 create mode 100644 include/usb/fotg210.h
 create mode 100644 include/usb/fusbh200.h

diff --git a/common/usb_hub.c b/common/usb_hub.c
index b5eeb62..26d66b8 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -375,6 +375,11 @@ static int usb_hub_configure(struct usb_device *dev)
                return -1;
        }
 
+#ifdef CONFIG_USB_EHCI_FARADAY
+       /* Faraday USB 2.0 EHCI chips need a long long delay here */
+       mdelay(250);
+#endif
+
        if (usb_get_hub_status(dev, buffer) < 0) {
                USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",
                                dev->status);
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 87a5970..98f2a10 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -43,6 +43,7 @@ COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-mpc512x.o
 else
 COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o
 endif
+COBJS-$(CONFIG_USB_EHCI_FARADAY) += ehci-faraday.o
 COBJS-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o
 COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
 COBJS-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o
diff --git a/drivers/usb/host/ehci-faraday.c b/drivers/usb/host/ehci-faraday.c
new file mode 100644
index 0000000..adf57d1
--- /dev/null
+++ b/drivers/usb/host/ehci-faraday.c
@@ -0,0 +1,122 @@
+/*
+ * Faraday USB 2.0 EHCI Controller
+ *
+ * (C) Copyright 2010 Faraday Technology
+ * Dante Su <dant...@faraday-tech.com>
+ *
+ * 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 <common.h>
+#include <asm/io.h>
+#include <usb.h>
+#include <usb/fusbh200.h>
+#include <usb/fotg210.h>
+
+#include "ehci.h"
+
+union ehci_faraday_regs {
+       struct fusbh200_regs usb;
+       struct fotg210_regs  otg;
+};
+
+static inline int ehci_hci_fotg2xx(struct ehci_hccr *hccr)
+{
+       union ehci_faraday_regs __iomem *regs = (void *)hccr;
+       return !readl(&regs->usb.easstr);
+}
+
+/*
+ * Create the appropriate control structures to manage
+ * a new EHCI host controller.
+ */
+int ehci_hcd_init(int index, struct ehci_hccr **ret_hccr,
+               struct ehci_hcor **ret_hcor)
+{
+       struct ehci_hccr *hccr;
+       struct ehci_hcor *hcor;
+       union ehci_faraday_regs __iomem *regs;
+#ifdef CONFIG_USB_EHCI_BASE_LIST
+       uint32_t base_list[] = CONFIG_USB_EHCI_BASE_LIST;
+#else
+       uint32_t base_list[] = { CONFIG_USB_EHCI_BASE };
+#endif
+
+       if (index < 0 || index >= ARRAY_SIZE(base_list))
+               return -1;
+       regs = (void __iomem *)base_list[index];
+       hccr = (struct ehci_hccr *)&regs->usb.hccr;
+       hcor = (struct ehci_hcor *)&regs->usb.hcor;
+
+       if (ehci_hci_fotg2xx(hccr)) {
+               /* A-device bus reset */
+               /* ... Power off A-device */
+               setbits_le32(&regs->otg.otgcsr, BIT_MASK(5));
+               /* ... Drop vbus and bus traffic */
+               clrbits_le32(&regs->otg.otgcsr, BIT_MASK(4));
+               mdelay(1);
+               /* ... Power on A-device */
+               clrbits_le32(&regs->otg.otgcsr, BIT_MASK(5));
+               /* ... Drive vbus and bus traffic */
+               setbits_le32(&regs->otg.otgcsr, BIT_MASK(4));
+               mdelay(1);
+               /* Disable OTG & device interrupts, interrupt=level-high */
+               writel(0x0b, &regs->otg.imr);
+               /* Clear all interrupt status */
+               writel(0x07, &regs->otg.isr);
+       } else {
+               /* Interrupt=level-high */
+               setbits_le32(&regs->usb.bmcsr, BIT_MASK(3));
+               /* VBUS on */
+               clrbits_le32(&regs->usb.bmcsr, BIT_MASK(4));
+               /* Disable all interrupts */
+               writel(0x00, &regs->usb.bmier);
+               writel(0x1f, &regs->usb.bmisr);
+       }
+
+       *ret_hccr = hccr;
+       *ret_hcor = hcor;
+
+       return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(int index)
+{
+       return 0;
+}
+
+int ehci_hcd_port_speed(struct ehci_hccr *hccr)
+{
+       int ret = 0;
+       int speed;
+       union ehci_faraday_regs __iomem *regs = (void *)hccr;
+
+       if (ehci_hci_fotg2xx(hccr))
+               speed = (readl(&regs->otg.otgcsr) >> 22) & 0x03;
+       else
+               speed = (readl(&regs->usb.bmcsr) >>  9) & 0x03;
+
+       switch (speed) {
+       case 0:    /* full speed */
+               break;
+
+       case 1:    /* low  speed */
+               ret = USB_PORT_STAT_LOW_SPEED;
+               break;
+
+       case 2:    /* high speed */
+               ret = USB_PORT_STAT_HIGH_SPEED;
+               break;
+
+       default:
+               printf("ehci-faraday: invalid device speed\n");
+               break;
+       }
+
+       return ret;
+}
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c816878..450d217 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -149,8 +149,10 @@ static int handshake(uint32_t *ptr, uint32_t mask, 
uint32_t done, int usec)
 static int ehci_reset(int index)
 {
        uint32_t cmd;
+#ifndef CONFIG_USB_EHCI_FARADAY
        uint32_t tmp;
        uint32_t *reg_ptr;
+#endif
        int ret = 0;
 
        cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
@@ -163,6 +165,7 @@ static int ehci_reset(int index)
                goto out;
        }
 
+#ifndef CONFIG_USB_EHCI_FARADAY
        if (ehci_is_TDI()) {
                reg_ptr = (uint32_t *)((u8 *)ehcic[index].hcor + USBMODE);
                tmp = ehci_readl(reg_ptr);
@@ -172,6 +175,7 @@ static int ehci_reset(int index)
 #endif
                ehci_writel(reg_ptr, tmp);
        }
+#endif /* !CONFIG_USB_EHCI_FARADAY */
 
 #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH
        cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning);
@@ -711,6 +715,9 @@ ehci_submit_root(struct usb_device *dev, unsigned long 
pipe, void *buffer,
                        tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
 
                if (ehci_is_TDI()) {
+#ifdef CONFIG_USB_EHCI_FARADAY
+                       tmpbuf[1] |= ehci_hcd_port_speed(ctrl->hccr) >> 8;
+#else
                        switch (PORTSC_PSPD(reg)) {
                        case PORTSC_PSPD_FS:
                                break;
@@ -722,6 +729,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long 
pipe, void *buffer,
                                tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
                                break;
                        }
+#endif
                } else {
                        tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
                }
@@ -950,10 +958,13 @@ int usb_lowlevel_init(int index, void **controller)
        cmd |= CMD_RUN;
        ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd);
 
+#ifndef CONFIG_USB_EHCI_FARADAY
        /* take control over the ports */
        cmd = ehci_readl(&ehcic[index].hcor->or_configflag);
        cmd |= FLAG_CF;
        ehci_writel(&ehcic[index].hcor->or_configflag, cmd);
+#endif
+
        /* unblock posted write */
        cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
        mdelay(5);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index d090f0a..9309ede 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -82,6 +82,7 @@ struct ehci_hcor {
        uint32_t or_periodiclistbase;
        uint32_t or_asynclistaddr;
        uint32_t _reserved_0_;
+#ifndef CONFIG_USB_EHCI_FARADAY
        uint32_t or_burstsize;
        uint32_t or_txfilltuning;
 #define TXFIFO_THRESH_MASK             (0x3f << 16)
@@ -89,6 +90,7 @@ struct ehci_hcor {
        uint32_t _reserved_1_[6];
        uint32_t or_configflag;
 #define FLAG_CF                (1 << 0)        /* true:  we'll support "high 
speed" */
+#endif  /* #ifndef CONFIG_USB_EHCI_FARADAY */
        uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS];
 #define PORTSC_PSPD(x)         (((x) >> 26) & 0x3)
 #define PORTSC_PSPD_FS                 0x0
@@ -255,5 +257,8 @@ struct QH {
 /* Low level init functions */
 int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor);
 int ehci_hcd_stop(int index);
+#ifdef CONFIG_USB_EHCI_FARADAY
+int ehci_hcd_port_speed(struct ehci_hccr *hccr);
+#endif
 
 #endif /* USB_EHCI_H */
diff --git a/include/usb/fotg210.h b/include/usb/fotg210.h
new file mode 100644
index 0000000..0249afd
--- /dev/null
+++ b/include/usb/fotg210.h
@@ -0,0 +1,71 @@
+/*
+ * Faraday USB 2.0 OTG Controller
+ *
+ * (C) Copyright 2010 Faraday Technology
+ * Dante Su <dant...@faraday-tech.com>
+ *
+ * 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.
+ */
+
+#ifndef _FOTG210_H
+#define _FOTG210_H
+
+struct fotg210_regs {
+       /* USB Host Controller */
+       struct {
+               uint32_t data[4];
+       } hccr;                 /* 0x00 - 0x0f: hccr */
+       struct {
+               uint32_t data[9];
+       } hcor;                 /* 0x10 - 0x33: hcor */
+       uint32_t rsvd1[3];
+       uint32_t msicr; /* 0x40: Miscellaneous Register */
+       uint32_t rsvd2[15];
+       /* USB OTG Controller */
+       uint32_t otgcsr;/* 0x80: OTG Control Status Register */
+       uint32_t otgisr;/* 0x84: OTG Interrupt Status Register */
+       uint32_t otgier;/* 0x88: OTG Interrupt Enable Register */
+       uint32_t rsvd3[13];
+       uint32_t isr;   /* 0xC0: Global Interrupt Status Register */
+       uint32_t imr;   /* 0xC4: Global Interrupt Mask Register */
+       uint32_t rsvd4[14];
+       /* USB Device Controller */
+       uint32_t dev_ctrl;/* 0x100: Device Control Register */
+       uint32_t dev_addr;/* 0x104: Device Address Register */
+       uint32_t dev_test;/* 0x108: Device Test Register */
+       uint32_t sof_fnr; /* 0x10c: SOF Frame Number Register */
+       uint32_t sof_mtr; /* 0x110: SOF Mask Timer Register */
+       uint32_t phy_tmsr;/* 0x114: PHY Test Mode Selector Register */
+       uint32_t rsvd5[1];
+       uint32_t cxsr;  /* 0x11c: CX Status Register */
+       uint32_t cxfifo;/* 0x120: CX FIFO Register */
+       uint32_t idle;  /* 0x124: IDLE Counter Register */
+       uint32_t rsvd6[2];
+       uint32_t gimr;  /* 0x130: Group Interrupt Mask Register */
+       uint32_t gimr0; /* 0x134: Group Interrupt Mask Register 0 */
+       uint32_t gimr1; /* 0x138: Group Interrupt Mask Register 1 */
+       uint32_t gimr2; /* 0x13c: Group Interrupt Mask Register 2 */
+       uint32_t gisr;  /* 0x140: Group Interrupt Status Register */
+       uint32_t gisr0; /* 0x144: Group Interrupt Status Register 0 */
+       uint32_t gisr1; /* 0x148: Group Interrupt Status Register 1 */
+       uint32_t gisr2; /* 0x14c: Group Interrupt Status Register 2 */
+       uint32_t rxzlp; /* 0x150: Receive Zero-Length-Packet Register */
+       uint32_t txzlp; /* 0x154: Transfer Zero-Length-Packet Register */
+       uint32_t ioseasr;/* 0x158: ISOC Error/Abort Status Register */
+       uint32_t rsvd7[1];
+       uint32_t iep[8]; /* 0x160 - 0x17f: IN Endpoint Register */
+       uint32_t oep[8]; /* 0x180 - 0x19f: OUT Endpoint Register */
+       uint32_t epmap14;/* 0x1a0: Endpoint Map Register (EP1 ~ 4) */
+       uint32_t epmap58;/* 0x1a4: Endpoint Map Register (EP5 ~ 8) */
+       uint32_t fifomap;/* 0x1a8: FIFO Map Register */
+       uint32_t fifocfg; /* 0x1ac: FIFO Configuration Register */
+       uint32_t fifocsr[4];/* 0x1b0 - 0x1bf: FIFO Control Status Register */
+       uint32_t dma_fifo; /* 0x1c0: DMA Target FIFO Register */
+       uint32_t rsvd8[1];
+       uint32_t dma_ctrl; /* 0x1c8: DMA Control Register */
+       uint32_t dma_addr; /* 0x1cc: DMA Address Register */
+       uint32_t dma_data; /* 0x1d0: DMA CX Data Register */
+};
+
+#endif
diff --git a/include/usb/fusbh200.h b/include/usb/fusbh200.h
new file mode 100644
index 0000000..2d514b8
--- /dev/null
+++ b/include/usb/fusbh200.h
@@ -0,0 +1,28 @@
+/*
+ * Faraday USB 2.0 EHCI Controller
+ *
+ * (C) Copyright 2010 Faraday Technology
+ * Dante Su <dant...@faraday-tech.com>
+ *
+ * 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.
+ */
+
+#ifndef _FUSBH200_H
+#define _FUSBH200_H
+
+struct fusbh200_regs {
+       struct {
+               uint32_t data[4];
+       } hccr;                 /* 0x00 - 0x0f: hccr */
+       struct {
+               uint32_t data[9];
+       } hcor;                 /* 0x10 - 0x33: hcor */
+       uint32_t easstr;/* 0x34: EOF&Async. Schedule Sleep Timer Register */
+       uint32_t rsvd[2];
+       uint32_t bmcsr; /* 0x40: Bus Monitor Control Status Register */
+       uint32_t bmisr; /* 0x44: Bus Monitor Interrupt Status Register */
+       uint32_t bmier; /* 0x48: Bus Monitor Interrupt Enable Register */
+};
+
+#endif
-- 
1.7.9.5

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to