AM33xx has support for dual port MUSB OTG controller. This patch
adds initialization for the controller using new MUSB gadget
driver and ether gadget.

Signed-off-by: Ilya Yanok <ilya.ya...@cogentembedded.com>
---
Changes in v2:
 - init both musb IPs (conditionally) from arch_init not
   from eth_initialize

 arch/arm/cpu/armv7/am33xx/board.c           |  107 ++++++++++++++++++++++++++-
 arch/arm/cpu/armv7/am33xx/clock.c           |    8 ++
 arch/arm/include/asm/arch-am33xx/cpu.h      |   11 ++-
 arch/arm/include/asm/arch-am33xx/hardware.h |    4 +
 4 files changed, 126 insertions(+), 4 deletions(-)

diff --git a/arch/arm/cpu/armv7/am33xx/board.c 
b/arch/arm/cpu/armv7/am33xx/board.c
index b387ac2..9007356 100644
--- a/arch/arm/cpu/armv7/am33xx/board.c
+++ b/arch/arm/cpu/armv7/am33xx/board.c
@@ -33,6 +33,11 @@
 #include <i2c.h>
 #include <miiphy.h>
 #include <cpsw.h>
+#include <asm/errno.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/musb.h>
+#include <asm/omap_musb.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -227,6 +232,88 @@ void setup_clocks_for_console(void)
        return;
 }
 
+/* AM33XX has two MUSB controllers which can be host or gadget */
+#if (defined(CONFIG_MUSB_GADGET) || defined(CONFIG_MUSB_HOST)) && \
+       (defined(CONFIG_AM335X_USB0) || defined(CONFIG_AM335X_USB1))
+/* USB 2.0 PHY Control */
+#define CM_PHY_PWRDN                   (1 << 0)
+#define CM_PHY_OTG_PWRDN               (1 << 1)
+#define OTGVDET_EN                     (1 << 19)
+#define OTGSESSENDEN                   (1 << 20)
+
+static void am33xx_usb_set_phy_power(u8 on, u32 *reg_addr)
+{
+       u32 usb_ctrl_reg;
+
+       usb_ctrl_reg = readl(reg_addr);
+       if (on) {
+               usb_ctrl_reg &= ~(CM_PHY_PWRDN | CM_PHY_OTG_PWRDN);
+               usb_ctrl_reg |= (OTGVDET_EN | OTGSESSENDEN);
+       } else {
+               usb_ctrl_reg |= (CM_PHY_PWRDN | CM_PHY_OTG_PWRDN);
+       }
+       writel(usb_ctrl_reg, reg_addr);
+}
+
+static struct musb_hdrc_config musb_config = {
+       .multipoint     = 1,
+       .dyn_fifo       = 1,
+       .num_eps        = 16,
+       .ram_bits       = 12,
+};
+
+#ifdef CONFIG_AM335X_USB0
+static void am33xx_otg0_set_phy_power(u8 on)
+{
+       am33xx_usb_set_phy_power(on, &cdev->usb_ctrl0);
+}
+
+struct omap_musb_board_data otg0_board_data = {
+       .set_phy_power = am33xx_otg0_set_phy_power,
+};
+
+static struct musb_hdrc_platform_data otg0_plat = {
+       .mode           = CONFIG_AM335X_USB0_MODE,
+       .config         = &musb_config,
+       .power          = 50,
+       .platform_ops   = &musb_dsps_ops,
+       .board_data     = &otg0_board_data,
+};
+#endif
+
+#ifdef CONFIG_AM335X_USB1
+static void am33xx_otg1_set_phy_power(u8 on)
+{
+       am33xx_usb_set_phy_power(on, &cdev->usb_ctrl1);
+}
+
+struct omap_musb_board_data otg1_board_data = {
+       .set_phy_power = am33xx_otg1_set_phy_power,
+};
+
+static struct musb_hdrc_platform_data otg1_plat = {
+       .mode           = CONFIG_AM335X_USB1_MODE,
+       .config         = &musb_config,
+       .power          = 50,
+       .platform_ops   = &musb_dsps_ops,
+       .board_data     = &otg1_board_data,
+};
+#endif
+#endif
+
+int arch_misc_init(void)
+{
+#ifdef CONFIG_AM335X_USB0
+       musb_register(&otg0_plat, &otg0_board_data,
+               (void *)AM335X_USB0_OTG_BASE);
+#endif
+#ifdef CONFIG_AM335X_USB1
+       musb_register(&otg1_plat, &otg1_board_data,
+               (void *)AM335X_USB1_OTG_BASE);
+#endif
+       return 0;
+}
+
 /*
  * Basic board specific setup.  Pinmux has been handled already.
  */
@@ -279,9 +366,14 @@ static struct cpsw_platform_data cpsw_data = {
        .host_port_num          = 0,
        .version                = CPSW_CTRL_VERSION_2,
 };
+#endif
 
+#if defined(CONFIG_DRIVER_TI_CPSW) || \
+       (defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET))
 int board_eth_init(bd_t *bis)
 {
+       int rv, n = 0;
+#ifdef CONFIG_DRIVER_TI_CPSW
        uint8_t mac_addr[6];
        uint32_t mac_hi, mac_lo;
 
@@ -313,6 +405,19 @@ int board_eth_init(bd_t *bis)
                                PHY_INTERFACE_MODE_RGMII;
        }
 
-       return cpsw_register(&cpsw_data);
+       rv = cpsw_register(&cpsw_data);
+       if (rv < 0)
+               printf("Error %d registering CPSW switch\n", rv);
+       else
+               n += rv;
+#endif
+#ifdef CONFIG_USB_ETHER
+       rv = usb_eth_initialize(bis);
+       if (rv < 0)
+               printf("Error %d registering USB_ETHER\n", rv);
+       else
+               n += rv;
+#endif
+       return n;
 }
 #endif
diff --git a/arch/arm/cpu/armv7/am33xx/clock.c 
b/arch/arm/cpu/armv7/am33xx/clock.c
index 2b19506..04841e4 100644
--- a/arch/arm/cpu/armv7/am33xx/clock.c
+++ b/arch/arm/cpu/armv7/am33xx/clock.c
@@ -40,6 +40,7 @@
 #define CLK_MODE_MASK          0xfffffff8
 #define CLK_DIV_SEL            0xFFFFFFE0
 #define CPGMAC0_IDLE           0x30000
+#define DPLL_CLKDCOLDO_GATE_CTRL        0x300
 
 const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;
 const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP;
@@ -153,6 +154,11 @@ static void enable_per_clocks(void)
        writel(PRCM_MOD_EN, &cmper->spi0clkctrl);
        while (readl(&cmper->spi0clkctrl) != PRCM_MOD_EN)
                ;
+
+       /* MUSB */
+       writel(PRCM_MOD_EN, &cmper->usb0clkctrl);
+       while (readl(&cmper->usb0clkctrl) != PRCM_MOD_EN)
+               ;
 }
 
 static void mpu_pll_config(void)
@@ -249,6 +255,8 @@ static void per_pll_config(void)
 
        while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK)
                ;
+
+       writel(DPLL_CLKDCOLDO_GATE_CTRL, &cmwkup->clkdcoldodpllper);
 }
 
 void ddr_pll_config(unsigned int ddrpll_m)
diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h 
b/arch/arm/include/asm/arch-am33xx/cpu.h
index 6cfbef7..60e28f9 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -82,7 +82,8 @@ struct cm_wkuppll {
        unsigned int clkseldpllcore;    /* offset 0x68 */
        unsigned int resv9[1];
        unsigned int idlestdpllper;     /* offset 0x70 */
-       unsigned int resv10[3];
+       unsigned int resv10[2];
+       unsigned int clkdcoldodpllper;  /* offset 0x7c */
        unsigned int divm4dpllcore;     /* offset 0x80 */
        unsigned int divm5dpllcore;     /* offset 0x84 */
        unsigned int clkmoddpllmpu;     /* offset 0x88 */
@@ -260,12 +261,16 @@ struct ctrl_stat {
 /* Control Device Register */
 struct ctrl_dev {
        unsigned int deviceid;          /* offset 0x00 */
-       unsigned int resv1[11];
+       unsigned int resv1[7];
+       unsigned int usb_ctrl0;         /* offset 0x20 */
+       unsigned int resv2;
+       unsigned int usb_ctrl1;         /* offset 0x28 */
+       unsigned int resv3;
        unsigned int macid0l;           /* offset 0x30 */
        unsigned int macid0h;           /* offset 0x34 */
        unsigned int macid1l;           /* offset 0x38 */
        unsigned int macid1h;           /* offset 0x3c */
-       unsigned int resv2[4];
+       unsigned int resv4[4];
        unsigned int miisel;            /* offset 0x50 */
 };
 #endif /* __ASSEMBLY__ */
diff --git a/arch/arm/include/asm/arch-am33xx/hardware.h 
b/arch/arm/include/asm/arch-am33xx/hardware.h
index 62332f2..39d0717 100644
--- a/arch/arm/include/asm/arch-am33xx/hardware.h
+++ b/arch/arm/include/asm/arch-am33xx/hardware.h
@@ -83,4 +83,8 @@
 #define AM335X_CPSW_BASE               0x4A100000
 #define AM335X_CPSW_MDIO_BASE          0x4A101000
 
+/* OTG */
+#define AM335X_USB0_OTG_BASE           0x47401000
+#define AM335X_USB1_OTG_BASE           0x47401800
+
 #endif /* __AM33XX_HARDWARE_H */
-- 
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