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 0xfff8
#define CLK_DIV_SEL0xFFE0
#define CPGMAC0_IDLE 0x3
+#define DPLL_CLKDCOLDO_GATE_CTRL0x300
const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;
const struct cm_wkuppll