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

There is at least one non-EHCI compliant controller (i.e. Faraday EHCI)
known to implement a non-standard TDI stuff.
Futhermore, it not only leave reserved and CONFIGFLAG registers
un-implemented but also has their address spaces removed.

And thus, we need weak-aliased functions to both TDI stuff
and PORTSC registers for interface abstraction.

Signed-off-by: Kuo-Jung Su <dant...@faraday-tech.com>
CC: Marek Vasut <ma...@denx.de>
---
Changes for v5:
   - Split up from Faraday EHCI patch

Changes for v2 - v4:
   - See 'usb: ehci: add Faraday USB 2.0 EHCI support'

 drivers/usb/host/ehci-hcd.c |  100 +++++++++++++++++++++++++++----------------
 1 file changed, 64 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c816878..b334173 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -117,10 +117,50 @@ static struct descriptor {
 };

 #if defined(CONFIG_EHCI_IS_TDI)
-#define ehci_is_TDI()  (1)
-#else
-#define ehci_is_TDI()  (0)
+# define ehci_is_TDI() (1)
+
+/* put TDI/ARC silicon into EHCI mode */
+void __ehci_tdi_reset(struct ehci_hcor *hcor)
+{
+       uint32_t tmp, *reg_ptr;
+
+       reg_ptr = (uint32_t *)((uint8_t *) + USBMODE);
+       tmp = ehci_readl(reg_ptr);
+       tmp |= USBMODE_CM_HC;
+#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
+       tmp |= USBMODE_BE;
 #endif
+       ehci_writel(reg_ptr, tmp);
+}
+
+void ehci_tdi_reset(struct ehci_hcor *hcor)
+       __attribute__((weak, alias("__ehci_tdi_reset")));
+
+int __ehci_port_speed(struct ehci_hcor *hcor, unsigned int portsc)
+{
+       int ret = 0;
+
+       switch (PORTSC_PSPD(portsc)) {
+       case PORTSC_PSPD_FS:
+               break;
+       case PORTSC_PSPD_LS:
+               ret = USB_PORT_STAT_LOW_SPEED;
+               break;
+       case PORTSC_PSPD_HS:
+       default:
+               ret = USB_PORT_STAT_HIGH_SPEED;
+               break;
+       }
+
+       return ret;
+}
+
+int ehci_port_speed(struct ehci_hcor *hcor, unsigned int portsc)
+       __attribute__((weak, alias("__ehci_port_speed")));
+
+#else  /* CONFIG_EHCI_IS_TDI */
+# define ehci_is_TDI() (0)
+#endif /* CONFIG_EHCI_IS_TDI */

 void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
 {
@@ -149,8 +189,6 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t 
done, int usec)
 static int ehci_reset(int index)
 {
        uint32_t cmd;
-       uint32_t tmp;
-       uint32_t *reg_ptr;
        int ret = 0;

        cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
@@ -163,15 +201,8 @@ static int ehci_reset(int index)
                goto out;
        }

-       if (ehci_is_TDI()) {
-               reg_ptr = (uint32_t *)((u8 *)ehcic[index].hcor + USBMODE);
-               tmp = ehci_readl(reg_ptr);
-               tmp |= USBMODE_CM_HC;
-#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
-               tmp |= USBMODE_BE;
-#endif
-               ehci_writel(reg_ptr, tmp);
-       }
+       if (ehci_is_TDI())
+               ehci_tdi_reset(ehcic[index].hcor);

 #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH
        cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning);
@@ -597,6 +628,18 @@ static inline int min3(int a, int b, int c)
        return a;
 }

+uint32_t *__ehci_get_portsc_register(struct ehci_hcor *hcor, int port)
+{
+       if (port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
+               printf("The request port(%d) is not configured\n", port);
+               return NULL;
+       }
+
+       return (uint32_t *)&hcor->or_portsc[port];
+}
+uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port)
+       __attribute__((weak, alias("__ehci_get_portsc_register")));
+
 int
 ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer,
                 int length, struct devrequest *req)
@@ -609,13 +652,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long 
pipe, void *buffer,
        uint32_t *status_reg;
        struct ehci_ctrl *ctrl = dev->controller;

-       if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) {
-               printf("The request port(%d) is not configured\n",
-                       le16_to_cpu(req->index) - 1);
+       status_reg = ehci_get_portsc_register(ctrl->hcor,
+               le16_to_cpu(req->index) - 1);
+       if (!status_reg)
                return -1;
-       }
-       status_reg = (uint32_t *)&ctrl->hcor->or_portsc[
-                                               le16_to_cpu(req->index) - 1];
        srclen = 0;

        debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n",
@@ -709,23 +749,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long 
pipe, void *buffer,
                        tmpbuf[0] |= USB_PORT_STAT_RESET;
                if (reg & EHCI_PS_PP)
                        tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
-
-               if (ehci_is_TDI()) {
-                       switch (PORTSC_PSPD(reg)) {
-                       case PORTSC_PSPD_FS:
-                               break;
-                       case PORTSC_PSPD_LS:
-                               tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
-                               break;
-                       case PORTSC_PSPD_HS:
-                       default:
-                               tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
-                               break;
-                       }
-               } else {
+               if (ehci_is_TDI())
+                       tmpbuf[1] |= ehci_port_speed(ctrl->hcor, reg) >> 8;
+               else
                        tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
-               }
-
                if (reg & EHCI_PS_CSC)
                        tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
                if (reg & EHCI_PS_PEC)
@@ -954,6 +981,7 @@ int usb_lowlevel_init(int index, void **controller)
        cmd = ehci_readl(&ehcic[index].hcor->or_configflag);
        cmd |= FLAG_CF;
        ehci_writel(&ehcic[index].hcor->or_configflag, cmd);
+
        /* unblock posted write */
        cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
        mdelay(5);
--
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