Hi,
I want to write an test application in u-boot level to test the USB interface of the 8148EVM.
Can anybody suggest me how can i proceed? any code snippet will be helpful.
Regards,
Vimal
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I want to write an test application in u-boot level to test the USB interface of the 8148EVM.
Can anybody suggest me how can i proceed? any code snippet will be helpful.
Regards,
Vimal
Try "> usb reset" and ">usb start" commands in uboot console.
Regards,
Rajesh
Hi Rajesh,
The usb command is not available in the u-boot level.
Regards,
Vimal
Vimal,
"usb reset" and "usb start" u-boot commands are available for newer version of the u-boot (newer than the DM814x EZSDK u-boot-2010.06), like in example u-boot (2013) for AM335x, OMAP5, etc.
The DM814x EZSDK u-boot-2010.06 does not support USB and there are no plans for USB u-boot support in the future.
Thus I can recommend you to check the DM814x EZSDK linux kernel USB support and re-use it in the u-boot.
http://processors.wiki.ti.com/index.php/DM814x_AM387x_PSP_User_Guide#USB_Driver
http://processors.wiki.ti.com/index.php/DM81xx_AM38XX_USB_User_Guide
http://processors.wiki.ti.com/index.php/TI81XX_PSP_USB_Driver_User_Guide
http://processors.wiki.ti.com/index.php/Usbgeneralpage
Also you can try to re-use the USB CCS test code from the Mistral SW package.
Regards,
Pavel
Hi Pavel,
I tried the reuse of USB CCS test code from the mistral SW Package in the u-boot but it is not working.
It is getting struct in usbotg_ss_init() function while writng the EOI.
Kindly suggest me something to overcome it.
here i am attaching the code.
/***************************************************************************** **+------------------------------------------------------------------------+** **| |** **| Copyright 2010 Mistral Solutions Pvt Ltd. |** **| |** **| |** **| |** **| This program is free software; you can redistribute it and/or |** **| modify it under the terms of the GNU General Public License as |** **| published by the Free Software Foundation; either version 2 of |** **| the License, or (at your option) any later version. |** **| |** **| This program is distributed in the hope that it will be useful, |** **| but WITHOUT ANY WARRANTY; without even the implied warranty of |** **| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |** **| GNU General Public License for more details. |** **| |** **| You should have received a copy of the GNU General Public License |** **| along with this program; if not, write to the Free Software |** **| Foundation, Inc., 59 Temple Place, Suite 330, Boston, |** **| MA 02111-1307 USA |** **+------------------------------------------------------------------------+** *****************************************************************************/ #include <common.h> #include <command.h> #include "ti814x_usbss.h" #include "musb_regs.h" typedef unsigned char UINT8; typedef unsigned short UINT16; typedef unsigned int UINT32; typedef char INT8; typedef short INT16; typedef int INT32; #define USBSS_CORE 0x0 #define L3_TI816X_BASE 0x44000000 #define L4_FAST_TI816X_BASE 0x4a000000 #define L4_SLOW_TI816X_BASE 0x48000000 #define TI816X_SCM_BASE 0x48140000 #define TI816X_CTRL_BASE TI816X_SCM_BASE #define TI816X_PRCM_BASE 0x48180000 #define TI816X_ARM_INTC_BASE 0x48200000 #define TI816X_GPMC_BASE 0x50000000 #define TI816X_PCIE_REG_BASE 0x51000000 #define TI816X_PCIE_MEM_BASE 0x20000000 #define TI816X_PCIE_IO_BASE 0x40000000 /* Using 3MB reserved space */ #define TI816X_USBSS_BASE 0x47400000 #define TI816X_USBSS_LEN 0xFFF #define TI816X_USB0_BASE 0x47401000 #define TI816X_USB1_BASE 0x47401800 #define TI816X_USB_CPPIDMA_BASE 0x47402000 #define TI816X_USB_CPPIDMA_LEN 0x5FFF /* TI814X specific definitions */ #define TI814X_USBCTRL0 0x0620 #define TI814X_USBSTS0 0x0624 #define TI814X_USBCTRL1 0x0628 #define TI814X_USBSTS1 0x062c /* PHY controls bits */ #define TI814X_USBPHY_CM_PWRDN (1 << 0) #define TI814X_USBPHY_OTG_PWRDN (1 << 1) #define TI814X_USBPHY_CHGDET_DIS (1 << 2) #define TI814X_USBPHY_CHGDET_RSTRT (1 << 3) #define TI814X_USBPHY_SRCONDM (1 << 4) #define TI814X_USBPHY_SINKONDP (1 << 5) #define TI814X_USBPHY_CHGISINK_EN (1 << 6) #define TI814X_USBPHY_CHGVSRC_EN (1 << 7) #define TI814X_USBPHY_DMPULLUP (1 << 8) #define TI814X_USBPHY_DPPULLUP (1 << 9) #define TI814X_USBPHY_CDET_EXTCTL (1 << 10) #define TI814X_USBPHY_GPIO_MODE (1 << 12) #define TI814X_USBPHY_DPOPBUFCTL (1 << 13) #define TI814X_USBPHY_DMOPBUFCTL (1 << 14) #define TI814X_USBPHY_DPINPUT (1 << 15) #define TI814X_USBPHY_DMINPUT (1 << 16) #define TI814X_USBPHY_DPGPIO_PD (1 << 17) #define TI814X_USBPHY_DMGPIO_PD (1 << 18) #define TI814X_USBPHY_OTGVDET_EN (1 << 19) #define TI814X_USBPHY_OTGSESSEND_EN (1 << 20) #define TI814X_USBPHY_DATA_POLARITY (1 << 23) #define USB_TX_EP_MASK 0xffff /* EP0 + 15 Tx EPs */ #define USB_RX_EP_MASK 0xfffe /* 15 Rx EPs */ #define USB_TX_INTR_MASK (USB_TX_EP_MASK << USB_INTR_TX_SHIFT) #define USB_RX_INTR_MASK (USB_RX_EP_MASK << USB_INTR_RX_SHIFT) #define A_WAIT_BCON_TIMEOUT 1100 /* in ms */ #define USBSS_INTR_RX_STARV 0x00000001 #define USBSS_INTR_PD_CMPL 0x00000004 #define USBSS_INTR_TX_CMPL 0x00000500 #define USBSS_INTR_RX_CMPL 0x00000A00 #define USBSS_INTR_FLAGS (USBSS_INTR_PD_CMPL | USBSS_INTR_TX_CMPL \ | USBSS_INTR_RX_CMPL) /* USB 2.0 PHY Control */ #define CONF2_PHY_GPIOMODE (1 << 23) #define CONF2_OTGMODE (3 << 14) #define CONF2_SESENDEN (1 << 13) /* Vsess_end comparator */ #define CONF2_VBDTCTEN (1 << 12) /* Vbus comparator */ #define CONF2_REFFREQ_24MHZ (2 << 8) #define CONF2_REFFREQ_26MHZ (7 << 8) #define CONF2_REFFREQ_13MHZ (6 << 8) #define CONF2_REFFREQ (0xf << 8) #define CONF2_PHYCLKGD (1 << 7) #define CONF2_VBUSSENSE (1 << 6) #define CONF2_PHY_PLLON (1 << 5) /* override PLL suspend */ #define CONF2_RESET (1 << 4) #define CONF2_PHYPWRDN (1 << 3) #define CONF2_OTGPWRDN (1 << 2) #define CONF2_DATPOL (1 << 1) #define USB_TX_EP_MASK 0xffff /* EP0 + 15 Tx EPs */ #define USB_RX_EP_MASK 0xfffe /* 15 Rx EPs */ #define USB_TX_INTR_MASK (USB_TX_EP_MASK << USB_INTR_TX_SHIFT) #define USB_RX_INTR_MASK (USB_RX_EP_MASK << USB_INTR_RX_SHIFT) #define A_WAIT_BCON_TIMEOUT 1100 /* in ms */ #define USBSS_INTR_RX_STARV 0x00000001 #define USBSS_INTR_PD_CMPL 0x00000004 #define USBSS_INTR_TX_CMPL 0x00000500 #define USBSS_INTR_RX_CMPL 0x00000A00 #define USBSS_INTR_FLAGS (USBSS_INTR_PD_CMPL | USBSS_INTR_TX_CMPL \ | USBSS_INTR_RX_CMPL) #define is_peripheral_enabled(musb_board_mode) (musb_board_mode != MUSB_HOST) #define is_host_enabled(musb_board_mode) (musb_board_mode != MUSB_PERIPHERAL) #define is_otg_enabled(musb_board_mode) (musb_board_mode == MUSB_OTG) #define OMAP_CTRL_REGADDR(reg) (TI816X_CTRL_BASE + (reg)) /* mentor is at offset of 0x400 in am3517/ti816x */ void *musb_mregs = (void *)(TI816X_USB0_BASE + USB_MENTOR_CORE_OFFSET); void *musb_ctrl_base = (void *)TI816X_USB0_BASE; UINT32 musb_is_active = 0; struct usbotg_ss { void *base; void *intc_base; int init_done; }; enum musb_mode { MUSB_UNDEFINED = 0, MUSB_HOST, /* A or Mini-A connector */ MUSB_PERIPHERAL, /* B or Mini-B connector */ MUSB_OTG /* Mini-AB connector */ }; struct usbotg_ss usbss; UINT32 usbss_read(UINT32 offs) { UINT32 val = 0; val = *(volatile UINT32 *)((UINT32)usbss.base + offs); return val; } void usbss_write(UINT32 offs, UINT32 val) { if (!usbss.init_done) return; *(volatile UINT32 *)((UINT32)usbss.base + offs) = val; } UINT32 omap_ctrl_readl(UINT16 offset) { UINT32 val = 0; val = *(volatile UINT32 *)(OMAP_CTRL_REGADDR(offset)); return val; } void omap_ctrl_writel(UINT32 val, UINT16 offset) { *(volatile UINT32 *)(OMAP_CTRL_REGADDR(offset)) = val; } UINT32 musb_readl(const void *addr, unsigned offset) { UINT32 val = 0; val = *(volatile UINT32 *)((UINT32)addr + offset); return val; } void musb_writel(void *addr, unsigned offset, UINT32 data){ *(volatile UINT32 *)((UINT32)addr + offset) = data; } UINT16 musb_readw(const void *addr, unsigned offset) { UINT32 tmp; UINT16 val; tmp = musb_readl(addr, (offset & ~3)); switch (offset & 0x3) { case 0: val = (tmp & 0xffff); break; case 1: val = (tmp >> 8) & 0xffff; break; case 2: case 3: default: val = (tmp >> 16) & 0xffff; break; } return val; } void musb_writew (void *addr, unsigned offset, UINT16 data) { *(volatile UINT16 *)((UINT32)addr + offset) = data; } UINT8 musb_readb(const void *addr, unsigned offset) { UINT32 tmp; UINT8 val; tmp = musb_readl(addr, (offset & ~3)); switch (offset & 0x3) { case 0: val = tmp & 0xff; break; case 1: val = (tmp >> 8); break; case 2: val = (tmp >> 16); break; case 3: default: val = (tmp >> 24); break; } return val; } void musb_writeb(void *addr, unsigned offset, UINT8 data) { *(volatile UINT8 *)((UINT32)addr + offset) = data; } int usbotg_ss_init(void) { int status = 0; printf("inside usbotg_ss_init usbss.init_done = %d \n",usbss.init_done); if (!usbss.init_done) { usbss.base = (void *)TI816X_USBSS_BASE; usbss.intc_base = (void *)0x50000000; usbss.init_done = 1; /* eoi to usbss */ printf("inside usbotg_ss_init before EOI Write \n"); usbss_write(USBSS_IRQ_EOI, 0); printf("inside usbotg_ss_init before interrupt write \n"); /* clear any USBSS interrupts */ usbss_write(USBSS_IRQ_STATUS, usbss_read(USBSS_IRQ_STATUS)); } printf("inside usbotg_ss_init return status = %d \n",status); return status; } void phy_on(UINT8 id) { UINT32 usbphycfg; printf("phy_on..\n"); /* * Start the on-chip PHY and its PLL. */ if (id == 0) usbphycfg = omap_ctrl_readl(TI814X_USBCTRL0); else if (id == 1) usbphycfg = omap_ctrl_readl(TI814X_USBCTRL1); usbphycfg &= ~(TI814X_USBPHY_CM_PWRDN | TI814X_USBPHY_OTG_PWRDN | TI814X_USBPHY_DMPULLUP | TI814X_USBPHY_DPPULLUP | TI814X_USBPHY_DPINPUT | TI814X_USBPHY_DMINPUT | TI814X_USBPHY_DATA_POLARITY); usbphycfg |= (TI814X_USBPHY_SRCONDM | TI814X_USBPHY_SINKONDP | TI814X_USBPHY_CHGISINK_EN | TI814X_USBPHY_CHGVSRC_EN | TI814X_USBPHY_CDET_EXTCTL | TI814X_USBPHY_DPOPBUFCTL | TI814X_USBPHY_DMOPBUFCTL | TI814X_USBPHY_DPGPIO_PD | TI814X_USBPHY_DMGPIO_PD | TI814X_USBPHY_OTGVDET_EN | TI814X_USBPHY_OTGSESSEND_EN); if (id == 0) omap_ctrl_writel(usbphycfg, TI814X_USBCTRL0); else if (id == 1) omap_ctrl_writel(usbphycfg, TI814X_USBCTRL1); } void phy_off(UINT8 id) { UINT32 usbphycfg; printf("phy_off..\n"); if (id == 0) usbphycfg = omap_ctrl_readl(TI814X_USBCTRL0); else if (id == 1) usbphycfg = omap_ctrl_readl(TI814X_USBCTRL1); usbphycfg |= TI814X_USBPHY_CM_PWRDN | TI814X_USBPHY_OTG_PWRDN; if (id == 0) omap_ctrl_writel(usbphycfg, TI814X_USBCTRL0); else if (id == 1) omap_ctrl_writel(usbphycfg, TI814X_USBCTRL1); } static int vbus_state = -1; static void ti816x_source_power(int is_on, int immediate) { if (is_on) is_on = 1; if (vbus_state == is_on) return; vbus_state = is_on; /* 0/1 vs "-1 == unknown/init" */ } void ti816x_set_vbus(int is_on) { ti816x_source_power(is_on, 0); } void musb_platform_enable(void) { void *reg_base = musb_ctrl_base; UINT32 epmask, coremask; /* Workaround: setup IRQs through both register sets. */ epmask = ((0xFFFF & USB_TX_EP_MASK) << USB_INTR_TX_SHIFT) | ((0xFFFF & USB_RX_EP_MASK) << USB_INTR_RX_SHIFT); coremask = (0x03ff << USB_INTR_USB_SHIFT); coremask &= ~0x8; /* disable the SOF */ coremask |= 0x8; musb_writel(reg_base, USB_EP_INTR_SET_REG, epmask); musb_writel(reg_base, USB_CORE_INTR_SET_REG, coremask); /* Force the DRVVBUS IRQ so we can start polling for ID change. */ if (is_otg_enabled(MUSB_HOST)) musb_writel(reg_base, USB_CORE_INTR_SET_REG, USB_INTR_DRVVBUS << USB_INTR_USB_SHIFT); } /** * musb_platform_disable - disable HDRC and flush interrupts */ void musb_platform_disable(void) { void *reg_base = musb_ctrl_base; musb_writel(reg_base, USB_CORE_INTR_CLEAR_REG, USB_INTR_USB_MASK); musb_writel(reg_base, USB_EP_INTR_CLEAR_REG, USB_TX_INTR_MASK | USB_RX_INTR_MASK); musb_writeb(musb_mregs, MUSB_DEVCTL, 0); musb_writel(reg_base, USB_IRQ_EOI, 0); } int musb_platform_set_mode(UINT8 musb_mode) { void *reg_base = musb_ctrl_base; /* TODO: implement this using CONF0 */ if (musb_mode == MUSB_HOST) { musb_writel(reg_base, USB_MODE_REG, 0); musb_writel(musb_ctrl_base, USB_PHY_UTMI_REG, 0x02); } else if (musb_mode == MUSB_PERIPHERAL) { /* TODO commmented writing 8 to USB_MODE_REG device mode is not working */ musb_writel(reg_base, USB_MODE_REG, 0x100); } return -1; } void musb_start(void) { void *regs = musb_mregs; UINT8 devctl = musb_readb(regs, MUSB_DEVCTL); musb_writeb(regs, MUSB_TESTMODE, 0); /* put into basic highspeed mode and start session */ musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE | MUSB_POWER_SOFTCONN | MUSB_POWER_HSENAB /* ENSUSPEND wedges tusb */ | MUSB_POWER_ENSUSPEND ); devctl = musb_readb(regs, MUSB_DEVCTL); devctl &= ~MUSB_DEVCTL_SESSION; if (is_host_enabled(MUSB_HOST)) { /* assume ID pin is hard-wired to ground */ devctl |= MUSB_DEVCTL_SESSION; } else /* peripheral is enabled */ { if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) musb_is_active = 1; } /* flush pending interrupts */ musb_readb(regs, MUSB_INTRUSB); musb_readw(regs, MUSB_INTRTX); musb_readw(regs, MUSB_INTRRX); musb_writew(regs, MUSB_INTRTXE, 0xFFFF); musb_writew(regs, MUSB_INTRRXE, 0xFFFF); musb_writeb(regs, MUSB_INTRUSBE, 0xf7); musb_platform_enable(); musb_writeb(regs, MUSB_DEVCTL, devctl); } #define PRCM_BASE_ADDR 0x48180000 #define CM_ALWON2_USB_CLKCTRL (PRCM_BASE_ADDR + 0x0558) int musb_platform_init(void) { void *reg_base = (void *)TI816X_USB0_BASE; UINT32 rev; UINT8 mode; printf(" inside musb_platform_init \n"); /* usb subsystem init */ usbotg_ss_init(); rev = musb_readl(reg_base, USB_REVISION_REG); printf("MUSB revision: 0x%X\n", rev); if (!rev) return -1; printf("MUSB revision: 0x%X\n", rev); ti816x_source_power(0, 1); /* set musb controller to host mode */ if (is_host_enabled(MUSB_HOST)) musb_platform_set_mode(MUSB_HOST); else musb_platform_set_mode(MUSB_PERIPHERAL); /* follow recommended reset procedure */ /* Reset the controller */ musb_writel(reg_base, USB_CTRL_REG, USB_SOFT_RESET_MASK); /* wait till reset bit clears */ while ((musb_readl(reg_base, USB_CTRL_REG) & 0x1)); /* clock disable */ *(volatile UINT32 *)CM_ALWON2_USB_CLKCTRL = 0; /* Disable USB Clock*/ while((*(volatile UINT32 *)CM_ALWON2_USB_CLKCTRL & 0x30000) != 0x30000); /* Poll for Module is disabled */ /* Start the on-chip PHY and its PLL. */ phy_on(0); /* clock enable */ *(volatile UINT32 *)CM_ALWON2_USB_CLKCTRL = 0x2; /* Enable USB Clock*/ while((*(volatile UINT32 *)CM_ALWON2_USB_CLKCTRL & 0x0F) != 0x2); /* Poll for Module is functional */ /* set musb controller to host mode */ if (is_host_enabled(MUSB_HOST)) mode = MUSB_HOST; else mode = MUSB_PERIPHERAL; musb_platform_set_mode(mode); musb_writel(reg_base, USB_IRQ_EOI, 0); //usbss_write(USBSS_IRQ_EOI, 0); return 0; } static int usb_test( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] ) { void *reg_base = (void *)TI816X_USB0_BASE; UINT8 reg_val = 0; printf(" inside usb_test\n"); musb_platform_init(); musb_start(); /* The above two steps puts the controller in session, After this its required to poll for session req interrupt and determine the type of cable/speed of the device */ /* TODO: 1. PRCM/MUX needs to get done in Gel. 2. Need datasheet to determine the base addresses for DM814X 3. Need datasheet to determine the registers for connect/disconnect and speed of device. 4. RIP */ printf("Waiting for connect\n"); while ((musb_readl(reg_base , USB_CORE_INTR_STATUS_REG) & MUSB_INTR_CONNECT) != MUSB_INTR_CONNECT); musb_writel(reg_base, USB_CORE_INTR_STATUS_REG, MUSB_INTR_CONNECT); printf("Connected\n Checking Speed and cable\n"); reg_val = musb_readb(musb_mregs, MUSB_DEVCTL); if ((reg_val & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) printf("USBSS VBUS Stable\n"); if (reg_val & MUSB_DEVCTL_HM) printf("USBSS is a Host\n"); else printf("USBSS is a Device\n"); if (reg_val & MUSB_DEVCTL_BDEVICE) printf("Cable is Type B\n"); else printf("Cable is Type A\n"); if (reg_val & MUSB_DEVCTL_FSDEV) printf("USBSS is a High/Full Speed Device\n"); else if (reg_val & MUSB_DEVCTL_LSDEV) printf("USBSS is a Low Speed Device\n"); else printf("USBSS Unknown device speed\n"); printf("Waiting for disconnect\n"); while ((musb_readl(reg_base, USB_CORE_INTR_STATUS_REG) & MUSB_INTR_DISCONNECT) != MUSB_INTR_DISCONNECT); musb_writel(reg_base, USB_CORE_INTR_STATUS_REG, MUSB_INTR_DISCONNECT); printf("Disconnected\n"); musb_writeb(musb_mregs, MUSB_DEVCTL, (reg_val & ~MUSB_DEVCTL_SESSION)); } U_BOOT_CMD(UU_USB, 3, 0,usb_test,"USB TEST",0);
Regards,
Vimal
Vimal,
Vimal Gupta said:It is getting struct in usbotg_ss_init() function while writng the EOI.
I am not sure I understand this correctly. Could you provide more details?
Vimal Gupta said:here i am attaching the code.1882.cmd_uu_usb.c/***************************************************************************** **+------------------------------------------------------------------------+** **| |** **| Copyright 2010 Mistral Solutions Pvt Ltd. |** **| |** **| |** **| |** **| This program is free software; you can redistribute it and/or |** **| modify it under the terms of the GNU General Public License as |** **| published by the Free Software Foundation; either version 2 of |** **| the License, or (at your option) any later version. |** **| |** **| This program is distributed in the hope that it will be useful, |** **| but WITHOUT ANY WARRANTY; without even the implied warranty of |** **| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |** **| GNU General Public License for more details. |** **| |** **| You should have received a copy of the GNU General Public License |** **| along with this program; if not, write to the Free Software |** **| Foundation, Inc., 59 Temple Place, Suite 330, Boston, |** **| MA 02111-1307 USA |** **+------------------------------------------------------------------------+** *****************************************************************************/ #include <common.h> #include <command.h> #include "ti814x_usbss.h" #include "musb_regs.h" typedef unsigned char UINT8; typedef unsigned short UINT16; typedef unsigned int UINT32; typedef char INT8; typedef short INT16; typedef int INT32; #define USBSS_CORE 0x0 #define L3_TI816X_BASE 0x44000000 #define L4_FAST_TI816X_BASE 0x4a000000 #define L4_SLOW_TI816X_BASE 0x48000000 #define TI816X_SCM_BASE 0x48140000 #define TI816X_CTRL_BASE TI816X_SCM_BASE #define TI816X_PRCM_BASE 0x48180000 #define TI816X_ARM_INTC_BASE 0x48200000 #define TI816X_GPMC_BASE 0x50000000 #define TI816X_PCIE_REG_BASE 0x51000000 #define TI816X_PCIE_MEM_BASE 0x20000000 #define TI816X_PCIE_IO_BASE 0x40000000 /* Using 3MB reserved space */ #define TI816X_USBSS_BASE 0x47400000 #define TI816X_USBSS_LEN 0xFFF #define TI816X_USB0_BASE 0x47401000 #define TI816X_USB1_BASE 0x47401800 #define TI816X_USB_CPPIDMA_BASE 0x47402000 #define TI816X_USB_CPPIDMA_LEN 0x5FFF /* TI814X specific definitions */ #define TI814X_USBCTRL0 0x0620 #define TI814X_USBSTS0 0x0624 #define TI814X_USBCTRL1 0x0628 #define TI814X_USBSTS1 0x062c /* PHY controls bits */ #define TI814X_USBPHY_CM_PWRDN (1 << 0) #define TI814X_USBPHY_OTG_PWRDN (1 << 1) #define TI814X_USBPHY_CHGDET_DIS (1 << 2) #define TI814X_USBPHY_CHGDET_RSTRT (1 << 3) #define TI814X_USBPHY_SRCONDM (1 << 4) #define TI814X_USBPHY_SINKONDP (1 << 5) #define TI814X_USBPHY_CHGISINK_EN (1 << 6) #define TI814X_USBPHY_CHGVSRC_EN (1 << 7) #define TI814X_USBPHY_DMPULLUP (1 << 8) #define TI814X_USBPHY_DPPULLUP (1 << 9) #define TI814X_USBPHY_CDET_EXTCTL (1 << 10) #define TI814X_USBPHY_GPIO_MODE (1 << 12) #define TI814X_USBPHY_DPOPBUFCTL (1 << 13) #define TI814X_USBPHY_DMOPBUFCTL (1 << 14) #define TI814X_USBPHY_DPINPUT (1 << 15) #define TI814X_USBPHY_DMINPUT (1 << 16) #define TI814X_USBPHY_DPGPIO_PD (1 << 17) #define TI814X_USBPHY_DMGPIO_PD (1 << 18) #define TI814X_USBPHY_OTGVDET_EN (1 << 19) #define TI814X_USBPHY_OTGSESSEND_EN (1 << 20) #define TI814X_USBPHY_DATA_POLARITY (1 << 23) #define USB_TX_EP_MASK 0xffff /* EP0 + 15 Tx EPs */ #define USB_RX_EP_MASK 0xfffe /* 15 Rx EPs */ #define USB_TX_INTR_MASK (USB_TX_EP_MASK << USB_INTR_TX_SHIFT) #define USB_RX_INTR_MASK (USB_RX_EP_MASK << USB_INTR_RX_SHIFT) #define A_WAIT_BCON_TIMEOUT 1100 /* in ms */ #define USBSS_INTR_RX_STARV 0x00000001 #define USBSS_INTR_PD_CMPL 0x00000004 #define USBSS_INTR_TX_CMPL 0x00000500 #define USBSS_INTR_RX_CMPL 0x00000A00 #define USBSS_INTR_FLAGS (USBSS_INTR_PD_CMPL | USBSS_INTR_TX_CMPL \ | USBSS_INTR_RX_CMPL) /* USB 2.0 PHY Control */ #define CONF2_PHY_GPIOMODE (1 << 23) #define CONF2_OTGMODE (3 << 14) #define CONF2_SESENDEN (1 << 13) /* Vsess_end comparator */ #define CONF2_VBDTCTEN (1 << 12) /* Vbus comparator */ #define CONF2_REFFREQ_24MHZ (2 << 8) #define CONF2_REFFREQ_26MHZ (7 << 8) #define CONF2_REFFREQ_13MHZ (6 << 8) #define CONF2_REFFREQ (0xf << 8) #define CONF2_PHYCLKGD (1 << 7) #define CONF2_VBUSSENSE (1 << 6) #define CONF2_PHY_PLLON (1 << 5) /* override PLL suspend */ #define CONF2_RESET (1 << 4) #define CONF2_PHYPWRDN (1 << 3) #define CONF2_OTGPWRDN (1 << 2) #define CONF2_DATPOL (1 << 1) #define USB_TX_EP_MASK 0xffff /* EP0 + 15 Tx EPs */ #define USB_RX_EP_MASK 0xfffe /* 15 Rx EPs */ #define USB_TX_INTR_MASK (USB_TX_EP_MASK << USB_INTR_TX_SHIFT) #define USB_RX_INTR_MASK (USB_RX_EP_MASK << USB_INTR_RX_SHIFT) #define A_WAIT_BCON_TIMEOUT 1100 /* in ms */ #define USBSS_INTR_RX_STARV 0x00000001 #define USBSS_INTR_PD_CMPL 0x00000004 #define USBSS_INTR_TX_CMPL 0x00000500 #define USBSS_INTR_RX_CMPL 0x00000A00 #define USBSS_INTR_FLAGS (USBSS_INTR_PD_CMPL | USBSS_INTR_TX_CMPL \ | USBSS_INTR_RX_CMPL) #define is_peripheral_enabled(musb_board_mode) (musb_board_mode != MUSB_HOST) #define is_host_enabled(musb_board_mode) (musb_board_mode != MUSB_PERIPHERAL) #define is_otg_enabled(musb_board_mode) (musb_board_mode == MUSB_OTG) #define OMAP_CTRL_REGADDR(reg) (TI816X_CTRL_BASE + (reg)) /* mentor is at offset of 0x400 in am3517/ti816x */ void *musb_mregs = (void *)(TI816X_USB0_BASE + USB_MENTOR_CORE_OFFSET); void *musb_ctrl_base = (void *)TI816X_USB0_BASE; UINT32 musb_is_active = 0; struct usbotg_ss { void *base; void *intc_base; int init_done; }; enum musb_mode { MUSB_UNDEFINED = 0, MUSB_HOST, /* A or Mini-A connector */ MUSB_PERIPHERAL, /* B or Mini-B connector */ MUSB_OTG /* Mini-AB connector */ }; struct usbotg_ss usbss; UINT32 usbss_read(UINT32 offs) { UINT32 val = 0; val = *(volatile UINT32 *)((UINT32)usbss.base + offs); return val; } void usbss_write(UINT32 offs, UINT32 val) { if (!usbss.init_done) return; *(volatile UINT32 *)((UINT32)usbss.base + offs) = val; } UINT32 omap_ctrl_readl(UINT16 offset) { UINT32 val = 0; val = *(volatile UINT32 *)(OMAP_CTRL_REGADDR(offset)); return val; } void omap_ctrl_writel(UINT32 val, UINT16 offset) { *(volatile UINT32 *)(OMAP_CTRL_REGADDR(offset)) = val; } UINT32 musb_readl(const void *addr, unsigned offset) { UINT32 val = 0; val = *(volatile UINT32 *)((UINT32)addr + offset); return val; } void musb_writel(void *addr, unsigned offset, UINT32 data){ *(volatile UINT32 *)((UINT32)addr + offset) = data; } UINT16 musb_readw(const void *addr, unsigned offset) { UINT32 tmp; UINT16 val; tmp = musb_readl(addr, (offset & ~3)); switch (offset & 0x3) { case 0: val = (tmp & 0xffff); break; case 1: val = (tmp >> 8) & 0xffff; break; case 2: case 3: default: val = (tmp >> 16) & 0xffff; break; } return val; } void musb_writew (void *addr, unsigned offset, UINT16 data) { *(volatile UINT16 *)((UINT32)addr + offset) = data; } UINT8 musb_readb(const void *addr, unsigned offset) { UINT32 tmp; UINT8 val; tmp = musb_readl(addr, (offset & ~3)); switch (offset & 0x3) { case 0: val = tmp & 0xff; break; case 1: val = (tmp >> 8); break; case 2: val = (tmp >> 16); break; case 3: default: val = (tmp >> 24); break; } return val; } void musb_writeb(void *addr, unsigned offset, UINT8 data) { *(volatile UINT8 *)((UINT32)addr + offset) = data; } int usbotg_ss_init(void) { int status = 0; printf("inside usbotg_ss_init usbss.init_done = %d \n",usbss.init_done); if (!usbss.init_done) { usbss.base = (void *)TI816X_USBSS_BASE; usbss.intc_base = (void *)0x50000000; usbss.init_done = 1; /* eoi to usbss */ printf("inside usbotg_ss_init before EOI Write \n"); usbss_write(USBSS_IRQ_EOI, 0); printf("inside usbotg_ss_init before interrupt write \n"); /* clear any USBSS interrupts */ usbss_write(USBSS_IRQ_STATUS, usbss_read(USBSS_IRQ_STATUS)); } printf("inside usbotg_ss_init return status = %d \n",status); return status; } void phy_on(UINT8 id) { UINT32 usbphycfg; printf("phy_on..\n"); /* * Start the on-chip PHY and its PLL. */ if (id == 0) usbphycfg = omap_ctrl_readl(TI814X_USBCTRL0); else if (id == 1) usbphycfg = omap_ctrl_readl(TI814X_USBCTRL1); usbphycfg &= ~(TI814X_USBPHY_CM_PWRDN | TI814X_USBPHY_OTG_PWRDN | TI814X_USBPHY_DMPULLUP | TI814X_USBPHY_DPPULLUP | TI814X_USBPHY_DPINPUT | TI814X_USBPHY_DMINPUT | TI814X_USBPHY_DATA_POLARITY); usbphycfg |= (TI814X_USBPHY_SRCONDM | TI814X_USBPHY_SINKONDP | TI814X_USBPHY_CHGISINK_EN | TI814X_USBPHY_CHGVSRC_EN | TI814X_USBPHY_CDET_EXTCTL | TI814X_USBPHY_DPOPBUFCTL | TI814X_USBPHY_DMOPBUFCTL | TI814X_USBPHY_DPGPIO_PD | TI814X_USBPHY_DMGPIO_PD | TI814X_USBPHY_OTGVDET_EN | TI814X_USBPHY_OTGSESSEND_EN); if (id == 0) omap_ctrl_writel(usbphycfg, TI814X_USBCTRL0); else if (id == 1) omap_ctrl_writel(usbphycfg, TI814X_USBCTRL1); } void phy_off(UINT8 id) { UINT32 usbphycfg; printf("phy_off..\n"); if (id == 0) usbphycfg = omap_ctrl_readl(TI814X_USBCTRL0); else if (id == 1) usbphycfg = omap_ctrl_readl(TI814X_USBCTRL1); usbphycfg |= TI814X_USBPHY_CM_PWRDN | TI814X_USBPHY_OTG_PWRDN; if (id == 0) omap_ctrl_writel(usbphycfg, TI814X_USBCTRL0); else if (id == 1) omap_ctrl_writel(usbphycfg, TI814X_USBCTRL1); } static int vbus_state = -1; static void ti816x_source_power(int is_on, int immediate) { if (is_on) is_on = 1; if (vbus_state == is_on) return; vbus_state = is_on; /* 0/1 vs "-1 == unknown/init" */ } void ti816x_set_vbus(int is_on) { ti816x_source_power(is_on, 0); } void musb_platform_enable(void) { void *reg_base = musb_ctrl_base; UINT32 epmask, coremask; /* Workaround: setup IRQs through both register sets. */ epmask = ((0xFFFF & USB_TX_EP_MASK) << USB_INTR_TX_SHIFT) | ((0xFFFF & USB_RX_EP_MASK) << USB_INTR_RX_SHIFT); coremask = (0x03ff << USB_INTR_USB_SHIFT); coremask &= ~0x8; /* disable the SOF */ coremask |= 0x8; musb_writel(reg_base, USB_EP_INTR_SET_REG, epmask); musb_writel(reg_base, USB_CORE_INTR_SET_REG, coremask); /* Force the DRVVBUS IRQ so we can start polling for ID change. */ if (is_otg_enabled(MUSB_HOST)) musb_writel(reg_base, USB_CORE_INTR_SET_REG, USB_INTR_DRVVBUS << USB_INTR_USB_SHIFT); } /** * musb_platform_disable - disable HDRC and flush interrupts */ void musb_platform_disable(void) { void *reg_base = musb_ctrl_base; musb_writel(reg_base, USB_CORE_INTR_CLEAR_REG, USB_INTR_USB_MASK); musb_writel(reg_base, USB_EP_INTR_CLEAR_REG, USB_TX_INTR_MASK | USB_RX_INTR_MASK); musb_writeb(musb_mregs, MUSB_DEVCTL, 0); musb_writel(reg_base, USB_IRQ_EOI, 0); } int musb_platform_set_mode(UINT8 musb_mode) { void *reg_base = musb_ctrl_base; /* TODO: implement this using CONF0 */ if (musb_mode == MUSB_HOST) { musb_writel(reg_base, USB_MODE_REG, 0); musb_writel(musb_ctrl_base, USB_PHY_UTMI_REG, 0x02); } else if (musb_mode == MUSB_PERIPHERAL) { /* TODO commmented writing 8 to USB_MODE_REG device mode is not working */ musb_writel(reg_base, USB_MODE_REG, 0x100); } return -1; } void musb_start(void) { void *regs = musb_mregs; UINT8 devctl = musb_readb(regs, MUSB_DEVCTL); musb_writeb(regs, MUSB_TESTMODE, 0); /* put into basic highspeed mode and start session */ musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE | MUSB_POWER_SOFTCONN | MUSB_POWER_HSENAB /* ENSUSPEND wedges tusb */ | MUSB_POWER_ENSUSPEND ); devctl = musb_readb(regs, MUSB_DEVCTL); devctl &= ~MUSB_DEVCTL_SESSION; if (is_host_enabled(MUSB_HOST)) { /* assume ID pin is hard-wired to ground */ devctl |= MUSB_DEVCTL_SESSION; } else /* peripheral is enabled */ { if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) musb_is_active = 1; } /* flush pending interrupts */ musb_readb(regs, MUSB_INTRUSB); musb_readw(regs, MUSB_INTRTX); musb_readw(regs, MUSB_INTRRX); musb_writew(regs, MUSB_INTRTXE, 0xFFFF); musb_writew(regs, MUSB_INTRRXE, 0xFFFF); musb_writeb(regs, MUSB_INTRUSBE, 0xf7); musb_platform_enable(); musb_writeb(regs, MUSB_DEVCTL, devctl); } #define PRCM_BASE_ADDR 0x48180000 #define CM_ALWON2_USB_CLKCTRL (PRCM_BASE_ADDR + 0x0558) int musb_platform_init(void) { void *reg_base = (void *)TI816X_USB0_BASE; UINT32 rev; UINT8 mode; printf(" inside musb_platform_init \n"); /* usb subsystem init */ usbotg_ss_init(); rev = musb_readl(reg_base, USB_REVISION_REG); printf("MUSB revision: 0x%X\n", rev); if (!rev) return -1; printf("MUSB revision: 0x%X\n", rev); ti816x_source_power(0, 1); /* set musb controller to host mode */ if (is_host_enabled(MUSB_HOST)) musb_platform_set_mode(MUSB_HOST); else musb_platform_set_mode(MUSB_PERIPHERAL); /* follow recommended reset procedure */ /* Reset the controller */ musb_writel(reg_base, USB_CTRL_REG, USB_SOFT_RESET_MASK); /* wait till reset bit clears */ while ((musb_readl(reg_base, USB_CTRL_REG) & 0x1)); /* clock disable */ *(volatile UINT32 *)CM_ALWON2_USB_CLKCTRL = 0; /* Disable USB Clock*/ while((*(volatile UINT32 *)CM_ALWON2_USB_CLKCTRL & 0x30000) != 0x30000); /* Poll for Module is disabled */ /* Start the on-chip PHY and its PLL. */ phy_on(0); /* clock enable */ *(volatile UINT32 *)CM_ALWON2_USB_CLKCTRL = 0x2; /* Enable USB Clock*/ while((*(volatile UINT32 *)CM_ALWON2_USB_CLKCTRL & 0x0F) != 0x2); /* Poll for Module is functional */ /* set musb controller to host mode */ if (is_host_enabled(MUSB_HOST)) mode = MUSB_HOST; else mode = MUSB_PERIPHERAL; musb_platform_set_mode(mode); musb_writel(reg_base, USB_IRQ_EOI, 0); //usbss_write(USBSS_IRQ_EOI, 0); return 0; } static int usb_test( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] ) { void *reg_base = (void *)TI816X_USB0_BASE; UINT8 reg_val = 0; printf(" inside usb_test\n"); musb_platform_init(); musb_start(); /* The above two steps puts the controller in session, After this its required to poll for session req interrupt and determine the type of cable/speed of the device */ /* TODO: 1. PRCM/MUX needs to get done in Gel. 2. Need datasheet to determine the base addresses for DM814X 3. Need datasheet to determine the registers for connect/disconnect and speed of device. 4. RIP */ printf("Waiting for connect\n"); while ((musb_readl(reg_base , USB_CORE_INTR_STATUS_REG) & MUSB_INTR_CONNECT) != MUSB_INTR_CONNECT); musb_writel(reg_base, USB_CORE_INTR_STATUS_REG, MUSB_INTR_CONNECT); printf("Connected\n Checking Speed and cable\n"); reg_val = musb_readb(musb_mregs, MUSB_DEVCTL); if ((reg_val & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) printf("USBSS VBUS Stable\n"); if (reg_val & MUSB_DEVCTL_HM) printf("USBSS is a Host\n"); else printf("USBSS is a Device\n"); if (reg_val & MUSB_DEVCTL_BDEVICE) printf("Cable is Type B\n"); else printf("Cable is Type A\n"); if (reg_val & MUSB_DEVCTL_FSDEV) printf("USBSS is a High/Full Speed Device\n"); else if (reg_val & MUSB_DEVCTL_LSDEV) printf("USBSS is a Low Speed Device\n"); else printf("USBSS Unknown device speed\n"); printf("Waiting for disconnect\n"); while ((musb_readl(reg_base, USB_CORE_INTR_STATUS_REG) & MUSB_INTR_DISCONNECT) != MUSB_INTR_DISCONNECT); musb_writel(reg_base, USB_CORE_INTR_STATUS_REG, MUSB_INTR_DISCONNECT); printf("Disconnected\n"); musb_writeb(musb_mregs, MUSB_DEVCTL, (reg_val & ~MUSB_DEVCTL_SESSION)); } U_BOOT_CMD(UU_USB, 3, 0,usb_test,"USB TEST",0);
Note that we have the GEL file loaded before running the test application under CCS. This GEL file is configuring the USB DPLL, the USB pins, clocks, phys, etc. So you will need to implement the GEL file also into the u-boot (at least the USB part).
Procudure
----------
This test application assumes the MUSB controller initialization as well as all
the PLL initialization already carried out by the GEL scripts. At the minimum
the following GEL scripts are to be executed.
1. PG 2.x DM814X --> ALL_ADPLL_CLOCKS_ENABLE_API
2. PG 2.x DM814X --> USB_CLOCK_ENABLE
load "BB_017_USB0_HOST_Test.out" file and run.
Regards,
Pavel
Vimal,
I implemented the functions from the USB_CLOCK_ENABLE GEL file in the u-boot as below:
TI8148_EVM#mw 0x48180558 0x2 1
TI8148_EVM#mw.l 0x48140C34 0x00060001 1
TI8148_EVM#mw.l 0x48140834 0x00060080 1
TI8148_EVM#mw.l 0x48180B10 0x0000009F 1
TI8148_EVM#mw.l 0x48140620 0x3C1E64F4 1
TI8148_EVM#mw.l 0x48140628 0x3C1E64F4 1
Then I run the USB test:
TI8148_EVM#UU_USB
inside usb_test
inside musb_platform_init
inside usbotg_ss_init usbss.init_done = 0
inside usbotg_ss_init before EOI Write
inside usbotg_ss_init before interrupt write
inside usbotg_ss_init return status = 0
MUSB revision: 0x4EA20800
MUSB revision: 0x4EA20800
phy_on..
Waiting for connect
Connected
Checking Speed and cable
USBSS VBUS Stable
USBSS is a Host
Cable is Type A
USBSS is a Low Speed Device
Waiting for disconnect
Disconnected
TI8148_EVM#
As you can see from the log above, everything is running fine on my side.
Regards,
Pavel