Add support for the USB Host controller of the MPC5121e, based on the original 
patch by Francesco Rendine [1].

The patch configures the USB Host controller and the on-board UTMI phy, 
including the Freescale-specific registers as per the Linux kernel driver.

Tested on the MPC5121ADS platform with various USB mass storage devices.

[1] http://lists.denx.de/pipermail/u-boot/2009-June/055022.html

Signed-off-by: Damien Dusha <d.du...@gmail.com>
---
 arch/powerpc/include/asm/immap_512x.h   |    4 +
 board/freescale/mpc5121ads/mpc5121ads.c |    4 +-
 drivers/usb/host/ehci-fsl.c             |  137 ++++++++++++++++++++++++++++-
 drivers/usb/host/ehci.h                 |    5 +
 include/configs/mpc5121ads.h            |   22 +++++-
 include/usb/ehci-fsl.h                  |  149 +++++++++++++++++++++++++------
 6 files changed, 292 insertions(+), 29 deletions(-)

diff --git a/arch/powerpc/include/asm/immap_512x.h 
b/arch/powerpc/include/asm/immap_512x.h
index 7f9db8b..4923a17 100644
--- a/arch/powerpc/include/asm/immap_512x.h
+++ b/arch/powerpc/include/asm/immap_512x.h
@@ -1246,4 +1246,8 @@ static inline u32 get_pata_base (void)
 }
 #endif /* __ASSEMBLY__ */
 
+#define CONFIG_SYS_MPC512x_USB_OFFSET   0x4000
+#define CONFIG_SYS_MPC512x_USB_ADDR \
+       (CONFIG_SYS_IMMR + CONFIG_SYS_MPC512x_USB_OFFSET)
+
 #endif /* __IMMAP_512x__ */
diff --git a/board/freescale/mpc5121ads/mpc5121ads.c 
b/board/freescale/mpc5121ads/mpc5121ads.c
index 2e13ea8..4c0caa7 100644
--- a/board/freescale/mpc5121ads/mpc5121ads.c
+++ b/board/freescale/mpc5121ads/mpc5121ads.c
@@ -53,7 +53,9 @@ DECLARE_GLOBAL_DATA_PTR;
 #define SCCR2_CLOCKS_EN        (CLOCK_SCCR2_DIU_EN |           \
                         CLOCK_SCCR2_I2C_EN |           \
                         CLOCK_SCCR2_MEM_EN |           \
-                        CLOCK_SCCR2_SPDIF_EN)
+                        CLOCK_SCCR2_SPDIF_EN |         \
+                        CLOCK_SCCR2_USB1_EN |          \
+                        CLOCK_SCCR2_USB2_EN)
 
 void __mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip);
 
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index c674929..d7b07ca 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -1,4 +1,9 @@
 /*
+ * (C) Copyright 2010, Damien Dusha, <d.du...@gmail.com>
+ *
+ * (C) Copyright 2009, Value Team S.p.A.
+ * Francesco Rendine, <francesco.rend...@...>
+ *
  * (C) Copyright 2009 Freescale Semiconductor, Inc.
  *
  * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB
@@ -30,6 +35,7 @@
 #include "ehci.h"
 #include "ehci-core.h"
 
+#ifndef  CONFIG_MPC512X
 /*
  * Create the appropriate control structures to manage
  * a new EHCI host controller.
@@ -40,7 +46,7 @@ int ehci_hcd_init(void)
 {
        struct usb_ehci *ehci;
 
-       ehci = (struct usb_ehci *)CONFIG_SYS_MPC8xxx_USB_ADDR;
+       ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR;
        hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
        hcor = (struct ehci_hcor *)((uint32_t) hccr +
                        HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
@@ -77,3 +83,132 @@ int ehci_hcd_stop(void)
 {
        return 0;
 }
+
+#else
+
+static void fsl_setup_phy(volatile struct ehci_hcor *);
+static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci);
+static int reset_usb_controller(volatile struct usb_ehci *ehci);
+static void usb_platform_dr_init(volatile struct usb_ehci *ehci);
+
+/*
+ * Initialise SOC FSL EHCI Controller
+ *
+ * This code is derived from EHCI FSL USB Linux driver for MPC5121
+ *
+ */
+int ehci_hcd_init(void)
+{
+       volatile struct usb_ehci *ehci;
+
+       /* Hook the memory mapped registers for EHCI-Controller */
+       ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR;
+       hccr = (struct ehci_hccr *)((uint32_t)&(ehci->caplength));
+       hcor = (struct ehci_hcor *)((uint32_t) hccr +
+                       HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+
+       /* configure interface for UTMI_WIDE */
+       usb_platform_dr_init(ehci);
+
+       /* Init Phy USB0 to UTMI+ */
+       fsl_setup_phy(hcor);
+
+       /* Set to host mode */
+       fsl_platform_set_host_mode(ehci);
+
+       /*
+        * Setting the burst size seems to be required to prevent the
+        * USB from hanging when communicating with certain USB Mass
+        * storage devices. This was determined by analysing the
+        * EHCI registers under Linux vs U-Boot and burstsize was the
+        * major non-interrupt related difference between the two
+        * implementations.
+        *
+        * Some USB sticks behave better than others. In particular,
+        * the following USB stick is especially problematic:
+        * 0930:6545 Toshiba Corp
+        *
+        * The burstsize is set here to match the Linux implementation.
+        */
+       out_be32(&ehci->burstsize, FSL_EHCI_TXPBURST(8) | FSL_EHCI_RXPBURST(8));
+
+       return 0;
+}
+
+/*
+ * Destroy the appropriate control structures corresponding
+ * the the EHCI host controller.
+ */
+int ehci_hcd_stop(void)
+{
+       volatile struct usb_ehci *ehci;
+       int exit_status = 0;
+
+       if (hcor) {
+               /* Unhook struct */
+               hccr = NULL;
+               hcor = NULL;
+
+               /* Reset the USB controller */
+               ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR;
+               exit_status = reset_usb_controller(ehci);
+       }
+
+       return exit_status;
+}
+
+static int reset_usb_controller(volatile struct usb_ehci *ehci)
+{
+       unsigned int i;
+
+       /* Command a reset of the USB Controller */
+       out_be32(&(ehci->usbcmd), EHCI_FSL_USBCMD_RST);
+
+       /* Wait for the reset process to finish */
+       for (i = 65535 ; i > 0 ; i--) {
+               /*
+                * The host will set this bit to zero once the
+                * reset process is complete
+                */
+               if ((in_be32(&(ehci->usbcmd)) & EHCI_FSL_USBCMD_RST) == 0)
+                       return 0;
+       }
+
+       /* Hub did not reset in time */
+       return -1;
+}
+
+static void fsl_setup_phy(volatile struct ehci_hcor *hcor)
+{
+       uint32_t portsc;
+
+       portsc  = ehci_readl(&hcor->or_portsc[0]);
+       portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
+
+       /* Enable the phy mode to UTMI Wide */
+       portsc |= PORT_PTS_PTW;
+       portsc |= PORT_PTS_UTMI;
+
+       ehci_writel(&hcor->or_portsc[0], portsc);
+}
+
+static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci)
+{
+       uint32_t temp;
+
+       temp  = in_le32(&ehci->usbmode);
+       temp |= CM_HOST | ES_BE;
+       out_le32(&ehci->usbmode, temp);
+}
+
+static void usb_platform_dr_init(volatile struct usb_ehci *ehci)
+{
+       /* Confgure interface for UTMI_WIDE */
+       out_be32(&ehci->isiphyctrl, PHYCTRL_PHYE | PHYCTRL_PXE);
+       out_be32(&ehci->usbgenctrl, GC_PPP | GC_PFP );
+}
+
+#endif
+
+
+
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index b3c1d5d..5ba612d 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -71,6 +71,11 @@ struct ehci_hcor {
 #define        STD_ASS         (1 << 15)
 #define STS_HALT       (1 << 12)
        uint32_t or_usbintr;
+#define INTR_UE                (1 << 0)                /* USB interrupt enable 
*/
+#define INTR_UEE       (1 << 1)                /* USB error interrupt enable */
+#define INTR_PCE       (1 << 2)                /* Port change detect enable */
+#define INTR_SEE       (1 << 4)                /* system error enable */
+#define INTR_AAE       (1 << 5)                /* Int on async adavance */
        uint32_t or_frindex;
        uint32_t or_ctrldssegment;
        uint32_t or_periodiclistbase;
diff --git a/include/configs/mpc5121ads.h b/include/configs/mpc5121ads.h
index 5281042..ce0df57 100644
--- a/include/configs/mpc5121ads.h
+++ b/include/configs/mpc5121ads.h
@@ -374,6 +374,20 @@
 #define CONFIG_SYS_I2C_RTC_ADDR                0x68    /* at address 0x68      
        */
 
 /*
+ * USB  Support
+ */
+#define CONFIG_CMD_USB
+
+#if defined(CONFIG_CMD_USB)
+#define CONFIG_USB_EHCI                                /* Enable EHCI Support  
*/
+#define CONFIG_USB_EHCI_FSL                    /* On a FSL platform    */
+#define CONFIG_EHCI_MMIO_BIG_ENDIAN            /* With big-endian regs */
+#define CONFIG_EHCI_DESC_BIG_ENDIAN
+#define CONFIG_EHCI_IS_TDI
+#define CONFIG_USB_STORAGE
+#endif
+
+/*
  * Environment
  */
 #define CONFIG_ENV_IS_IN_FLASH 1
@@ -441,10 +455,16 @@
                                        "mpc5121.nand:-(data)"
 
 
-#if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_EXT2)
+#if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_EXT2) || \
+       defined(CONFIG_CMD_USB)
+
 #define CONFIG_DOS_PARTITION
 #define CONFIG_MAC_PARTITION
 #define CONFIG_ISO_PARTITION
+
+#define CONFIG_CMD_FAT
+#define CONFIG_SUPPORT_VFAT
+
 #endif /* defined(CONFIG_CMD_IDE) */
 
 /*
diff --git a/include/usb/ehci-fsl.h b/include/usb/ehci-fsl.h
index f48945a..559a96a 100644
--- a/include/usb/ehci-fsl.h
+++ b/include/usb/ehci-fsl.h
@@ -35,12 +35,17 @@
 #define PORT_PTS_ULPI          (2 << 30)
 #define PORT_PTS_SERIAL                (3 << 30)
 #define PORT_PTS_PTW           (1 << 28)
+#define PORT_PFSC              (1 << 24)       /* See p39 of MPC5121e ERM */
+#define PORT_PTS_PHCD          (1 << 23)
+#define PORT_PP                        (1 << 12)
+#define PORT_PR                        (1 << 8)
 
 /* USBMODE Register bits */
 #define CM_IDLE                        (0 << 0)
 #define CM_RESERVED            (1 << 0)
 #define CM_DEVICE              (2 << 0)
 #define CM_HOST                        (3 << 0)
+#define ES_BE                  (1 << 2)        /* Big Endian Select MPC5121e */
 #define USBMODE_RESERVED_2     (0 << 2)
 #define SLOM                   (1 << 3)
 #define SDIS                   (1 << 4)
@@ -70,7 +75,78 @@
 #define PHY_CLK_VALID          (1 << 17)
 
 #define FSL_SOC_USB_PORTSC2    0x188
+
+/* OTG Status Control Register bits */
+#define FSL_SOC_USB_OTGSC      0x1a4
+#define CTRL_VBUS_DISCHARGE    (1 << 0)
+#define CTRL_VBUS_CHARGE       (1 << 1)
+#define CTRL_OTG_TERMINATION   (1 << 3)
+#define CTRL_DATA_PULSING      (1 << 4)
+#define CTRL_ID_PULL_EN                (1 << 5)
+#define HA_DATA_PULSE          (1 << 6)
+#define HA_BA                  (1 << 7)
+#define STS_USB_ID             (1 << 8)
+#define STS_A_VBUS_VALID       (1 << 9)
+#define STS_A_SESSION_VALID    (1 << 10)
+#define STS_B_SESSION_VALID    (1 << 11)
+#define STS_B_SESSION_END      (1 << 12)
+#define STS_1MS_TOGGLE         (1 << 13)
+#define STS_DATA_PULSING       (1 << 14)
+#define INTSTS_USB_ID          (1 << 16)
+#define INTSTS_A_VBUS_VALID    (1 << 17)
+#define INTSTS_A_SESSION_VALID (1 << 18)
+#define INTSTS_B_SESSION_VALID (1 << 19)
+#define INTSTS_B_SESSION_END   (1 << 20)
+#define INTSTS_1MS             (1 << 21)
+#define INTSTS_DATA_PULSING    (1 << 22)
+#define INTR_USB_ID_EN         (1 << 24)
+#define INTR_A_VBUS_VALID_EN   (1 << 25)
+#define INTR_A_SESSION_VALID_EN        (1 << 26)
+#define INTR_B_SESSION_VALID_EN        (1 << 27)
+#define INTR_B_SESSION_END_EN  (1 << 28)
+#define INTR_1MS_TIMER_EN      (1 << 29)
+#define INTR_DATA_PULSING_EN   (1 << 30)
+#define INTSTS_MASK            0x00ff0000
+
+/* USBCMD Bits of interest */
+#define EHCI_FSL_USBCMD_RST    (1 << 1)
+#define EHCI_FSL_USBCMD_RS     (1 << 0)
+
+#define  INTERRUPT_ENABLE_BITS_MASK    \
+               (INTR_USB_ID_EN         | \
+               INTR_1MS_TIMER_EN       | \
+               INTR_A_VBUS_VALID_EN    | \
+               INTR_A_SESSION_VALID_EN | \
+               INTR_B_SESSION_VALID_EN | \
+               INTR_B_SESSION_END_EN   | \
+               INTR_DATA_PULSING_EN)
+
+#define  INTERRUPT_STATUS_BITS_MASK    \
+               (INTSTS_USB_ID          | \
+               INTR_1MS_TIMER_EN       | \
+               INTSTS_A_VBUS_VALID     | \
+               INTSTS_A_SESSION_VALID  | \
+               INTSTS_B_SESSION_VALID  | \
+               INTSTS_B_SESSION_END    | \
+               INTSTS_DATA_PULSING)
+
 #define FSL_SOC_USB_USBMODE    0x1a8
+
+#define USBGENCTRL             0x200           /* NOTE: big endian */
+#define GC_WU_INT_CLR          (1 << 5)        /* Wakeup int clear */
+#define GC_ULPI_SEL            (1 << 4)        /* ULPI i/f select (usb0 only)*/
+#define GC_PPP                 (1 << 3)        /* Port Power Polarity */
+#define GC_PFP                 (1 << 2)        /* Power Fault Polarity */
+#define GC_WU_ULPI_EN          (1 << 1)        /* Wakeup on ULPI event */
+#define GC_WU_IE               (1 << 1)        /* Wakeup interrupt enable */
+
+#define ISIPHYCTRL             0x204           /* NOTE: big endian */
+#define PHYCTRL_PHYE           (1 << 4)        /* On-chip UTMI PHY enable */
+#define PHYCTRL_BSENH          (1 << 3)        /* Bit Stuff Enable High */
+#define PHYCTRL_BSEN           (1 << 2)        /* Bit Stuff Enable */
+#define PHYCTRL_LSFE           (1 << 1)        /* Line State Filter Enable */
+#define PHYCTRL_PXE            (1 << 0)        /* PHY oscillator enable */
+
 #define FSL_SOC_USB_SNOOP1     0x400   /* NOTE: big-endian */
 #define FSL_SOC_USB_SNOOP2     0x404   /* NOTE: big-endian */
 #define FSL_SOC_USB_AGECNTTHRSH        0x408   /* NOTE: big-endian */
@@ -85,65 +161,86 @@
 #define MPC83XX_SCCR_USB_DRCM_01       0x00100000
 #define MPC83XX_SCCR_USB_DRCM_10       0x00200000
 
-#if defined(CONFIG_MPC83xx)
-#define CONFIG_SYS_MPC8xxx_USB_ADDR CONFIG_SYS_MPC83xx_USB_ADDR
+#if defined(CONFIG_MPC83XX)
+#define CONFIG_SYS_FSL_USB_ADDR CONFIG_SYS_MPC83xx_USB_ADDR
 #elif defined(CONFIG_MPC85xx)
-#define CONFIG_SYS_MPC8xxx_USB_ADDR CONFIG_SYS_MPC85xx_USB_ADDR
+#define CONFIG_SYS_FSL_USB_ADDR CONFIG_SYS_MPC85xx_USB_ADDR
+#elif defined(CONFIG_MPC512X)
+#define CONFIG_SYS_FSL_USB_ADDR CONFIG_SYS_MPC512x_USB_ADDR
 #endif
 
 /*
  * USB Registers
  */
 struct usb_ehci {
-       u8      res1[0x100];
+       u32     id;             /* 0x000 - Identification register */
+       u32     hwgeneral;      /* 0x004 - General hardware parameters */
+       u32     hwhost;         /* 0x008 - Host hardware parameters */
+       u32     hwdevice;       /* 0x00C - Device hardware parameters  */
+       u32     hwtxbuf;        /* 0x010 - TX buffer hardware parameters */
+       u32     hwrxbuf;        /* 0x014 - RX buffer hardware parameters */
+       u8      res1[0x68];
+       u32     gptimer0_ld;    /* 0x080 - General Purpose Timer 0 load value */
+       u32     gptimer0_ctrl;  /* 0x084 - General Purpose Timer 0 control */
+       u32     gptimer1_ld;    /* 0x088 - General Purpose Timer 1 load value */
+       u32     gptimer1_ctrl;  /* 0x08C - General Purpose Timer 1 control */
+       u32     sbuscfg;        /* 0x090 - System Bus Interface Control */
+       u8      res2[0x6C];
        u16     caplength;      /* 0x100 - Capability Register Length */
        u16     hciversion;     /* 0x102 - Host Interface Version */
        u32     hcsparams;      /* 0x104 - Host Structural Parameters */
        u32     hccparams;      /* 0x108 - Host Capability Parameters */
-       u8      res2[0x14];
+       u8      res3[0x14];
        u32     dciversion;     /* 0x120 - Device Interface Version */
        u32     dciparams;      /* 0x124 - Device Controller Params */
-       u8      res3[0x18];
+       u8      res4[0x18];
        u32     usbcmd;         /* 0x140 - USB Command */
        u32     usbsts;         /* 0x144 - USB Status */
        u32     usbintr;        /* 0x148 - USB Interrupt Enable */
        u32     frindex;        /* 0x14C - USB Frame Index */
-       u8      res4[0x4];
+       u8      res5[0x4];
        u32     perlistbase;    /* 0x154 - Periodic List Base
                                         - USB Device Address */
        u32     ep_list_addr;   /* 0x158 - Next Asynchronous List
-                                        - Endpoint Address */
-       u8      res5[0x4];
+                                        - End Point Address */
+       u8 res6[0x4];
        u32     burstsize;      /* 0x160 - Programmable Burst Size */
+#define FSL_EHCI_TXPBURST(X)   ((X) << 8)
+#define FSL_EHCI_RXPBURST(X)   (X)
        u32     txfilltuning;   /* 0x164 - Host TT Transmit
                                           pre-buffer packet tuning */
-       u8      res6[0x8];
+       u8      res7[0x8];
        u32     ulpi_viewpoint; /* 0x170 - ULPI Reister Access */
-       u8      res7[0xc];
+       u8      res8[0xc];
        u32     config_flag;    /* 0x180 - Configured Flag Register */
        u32     portsc;         /* 0x184 - Port status/control */
-       u8      res8[0x20];
+       u8      res9[0x1C];
+       u32     otgsc;          /* 0x1a4 - Oo-The-Go status and control */
        u32     usbmode;        /* 0x1a8 - USB Device Mode */
-       u32     epsetupstat;    /* 0x1ac - Endpoint Setup Status */
-       u32     epprime;        /* 0x1b0 - Endpoint Init Status */
-       u32     epflush;        /* 0x1b4 - Endpoint De-initlialize */
-       u32     epstatus;       /* 0x1b8 - Endpoint Status */
-       u32     epcomplete;     /* 0x1bc - Endpoint Complete */
-       u32     epctrl0;        /* 0x1c0 - Endpoint Control 0 */
-       u32     epctrl1;        /* 0x1c4 - Endpoint Control 1 */
-       u32     epctrl2;        /* 0x1c8 - Endpoint Control 2 */
-       u32     epctrl3;        /* 0x1cc - Endpoint Control 3 */
-       u32     epctrl4;        /* 0x1d0 - Endpoint Control 4 */
-       u32     epctrl5;        /* 0x1d4 - Endpoint Control 5 */
-       u8      res9[0x228];
+       u32     epsetupstat;    /* 0x1ac - End Point Setup Status */
+       u32     epprime;        /* 0x1b0 - End Point Init Status */
+       u32     epflush;        /* 0x1b4 - End Point De-initlialize */
+       u32     epstatus;       /* 0x1b8 - End Point Status */
+       u32     epcomplete;     /* 0x1bc - End Point Complete */
+       u32     epctrl0;        /* 0x1c0 - End Point Control 0 */
+       u32     epctrl1;        /* 0x1c4 - End Point Control 1 */
+       u32     epctrl2;        /* 0x1c8 - End Point Control 2 */
+       u32     epctrl3;        /* 0x1cc - End Point Control 3 */
+       u32     epctrl4;        /* 0x1d0 - End Point Control 4 */
+       u32     epctrl5;        /* 0x1d4 - End Point Control 5 */
+       u8      res10[0x28];
+       u32     usbgenctrl;     /* 0x200 - USB General Control */
+       u32     isiphyctrl;     /* 0x204 - On-Chip PHY Control */
+       u8      res11[0x1F8];
        u32     snoop1;         /* 0x400 - Snoop 1 */
        u32     snoop2;         /* 0x404 - Snoop 2 */
        u32     age_cnt_limit;  /* 0x408 - Age Count Threshold */
        u32     prictrl;        /* 0x40c - Priority Control */
        u32     sictrl;         /* 0x410 - System Interface Control */
-       u8      res10[0xEC];
+       u8      res12[0xEC];
        u32     control;        /* 0x500 - Control */
-       u8      res11[0xafc];
+       u8      res13[0xafc];
 };
 
 #endif /* _EHCI_FSL_H */
+
-- 
1.7.0.4

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

Reply via email to