
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.yanok@cogentembedded.com --- arch/arm/cpu/armv7/am33xx/board.c | 81 ++++++++++++++++++++++++++- 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, 100 insertions(+), 4 deletions(-)
diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c index 2ca4ca7..dafc264 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;
@@ -273,9 +278,65 @@ static struct cpsw_platform_data cpsw_data = { .host_port_num = 0, .version = CPSW_CTRL_VERSION_2, }; +#endif + +#ifdef CONFIG_MUSB_GADGET +#ifdef CONFIG_MUSB_GADGET_PORT0 +#define USB_CTRL_REG &cdev->usb_ctrl0 +#define OTG_REGS_BASE ((void *)AM335X_USB0_OTG_BASE) +#elif defined(CONFIG_MUSB_GADGET_PORT1) +#define USB_CTRL_REG &cdev->usb_ctrl1 +#define OTG_REGS_BASE ((void *)AM335X_USB1_OTG_BASE) +#else +#error "Please define CONFIG_MUSB_GADGET_PORT0 or CONFIG_MUSB_GADGET_PORT1" +#endif + +/* 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 usb_ctrl_reg; + + usb_ctrl_reg = readl(USB_CTRL_REG); + 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, USB_CTRL_REG); +} + +static struct musb_hdrc_config musb_config = { + .multipoint = 1, + .dyn_fifo = 1, + .num_eps = 16, + .ram_bits = 12, +};
+struct omap_musb_board_data musb_board_data = { + .set_phy_power = am33xx_usb_set_phy_power, +}; + +static struct musb_hdrc_platform_data musb_plat = { + .mode = MUSB_PERIPHERAL, + .config = &musb_config, + .power = 50, + .platform_ops = &musb_dsps_ops, + .board_data = &musb_board_data, +}; +#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;
@@ -307,6 +368,24 @@ 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 = musb_register(&musb_plat, &musb_board_data, OTG_REGS_BASE); + if (rv < 0) { + printf("Error %d registering MUSB device\n", rv); + } else { + 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 1071f92..5ad84ce 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; @@ -148,6 +149,11 @@ static void enable_per_clocks(void) writel(PRCM_MOD_EN, &cmper->cpgmac0clkctrl); while ((readl(&cmper->cpgmac0clkctrl) & CPGMAC0_IDLE) != PRCM_FUNCTL) ; + + /* MUSB */ + writel(PRCM_MOD_EN, &cmper->usb0clkctrl); + while (readl(&cmper->usb0clkctrl) != PRCM_MOD_EN) + ; }
static void mpu_pll_config(void) @@ -244,6 +250,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 de9ee91..a98ffa2 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 */ @@ -258,12 +259,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 c617331..f98f497 100644 --- a/arch/arm/include/asm/arch-am33xx/hardware.h +++ b/arch/arm/include/asm/arch-am33xx/hardware.h @@ -82,4 +82,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 */