/*
 * Copyright (c) 2016, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */


#include "DM8127_EVM.h"
#include "stdio.h"
#include "ti816x_usbss.h"
#include "musb_regs.h"

#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 DM8127_GPMC_REG    (0x50000000)
#define INIT_DONE          (1u)
#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);

#ifdef DEBUG
    printf("\r\n USBSS_read value = 0x%x\r\n",val);
#endif
    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);
#ifdef DEBUG
    printf("\r\n USBSS_read1 value = 0x%x\r\n",val);
#endif
    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;
}

/**
 *\brief: subsystem module initializer.
 *
 *        This routine will complete the interrupt by writting 0.
 *
 *        it will clear the USBSS interrupt if any pending.
 *
 *@param : VOID
 *@return: status   Always success by writing 0.
 *
 */
int usbotg_ss_init(void)
{
    int status = 0;

#ifdef DEBUG
    printf("\r\n inside USB_OTG_SS_INIT\r\n");
#endif
    if (!usbss.init_done)
    {
        usbss.base = (void *)TI816X_USBSS_BASE;    
        usbss.intc_base = (void *)DM8127_GPMC_REG;
        usbss.init_done = INIT_DONE;

        /* eoi to usbss, completion of interrupt by writing 0 */
        usbss_write(USBSS_IRQ_EOI, 0);

        /* clear if any USBSS interrupt is pending */
        usbss_write(USBSS_IRQ_STATUS, usbss_read(USBSS_IRQ_STATUS));
    }

    return status;
}
/**
 *\brief : Phy configuration routine.
 *
 *         This routine will enable the PHY of the particular
 *         USB controller.
 *
 *@param : ID [IN] Phy id to be initialized.
 *@return: VOID
 */
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);
#ifdef DEBUG
    printf("\r\n Phy configuration Value for CM_PWRDN 0x%x \r\n",usbphycfg);
#endif
    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);
#ifdef DEBUG
    printf("\r\n Phy configuration Value for SR_CONDM 0x%x \r\n",usbphycfg);
#endif

    if (id == 0)
    {
        omap_ctrl_writel(usbphycfg, TI814X_USBCTRL0);
    	usbphycfg = omap_ctrl_readl(TI814X_USBCTRL0);
    	printf("\r\n Phy configuration CM_PWRDN read value 0x%x \r\n",usbphycfg);
    }
    else if (id == 1){
        omap_ctrl_writel(usbphycfg, TI814X_USBCTRL1);
        usbphycfg = omap_ctrl_readl(TI814X_USBCTRL1);
        printf("\r\n Phy configuration SR_CONDM read value 0x%x \r\n",usbphycfg);
    }
}

/**
 *\brief : Phy Disable routine.
 *
 *         This routine will disable the PHY of the particular
 *         USB controller.
 *
 *@param : ID [IN] Phy id to be initialized.
 *@return: VOID
 */

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);
}

#if 0
/*
 * Because we don't set CTRL.UINT, it's "important" to:
 *  - not read/write INTRUSB/INTRUSBE (except during
 *    initial setup, as a workaround);
 *  - use INTSET/INTCLR instead.
 */

/**
 * musb_platform_enable - enable interrupts
 */
void musb_platform_enable(struct musb *musb)
{
    void __iomem *reg_base = musb->ctrl_base;
    UINT32 epmask, coremask;

    /* Workaround: setup IRQs through both register sets. */
    epmask = ((musb->epmask & USB_TX_EP_MASK) << USB_INTR_TX_SHIFT) |
           ((musb->epmask & USB_RX_EP_MASK) << USB_INTR_RX_SHIFT);
    coremask = (0x01ff << 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))
        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(struct musb *musb)
{
    void __iomem *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);
}

#endif

static int vbus_state = -1;

static void ti816x_source_power(int is_on, int immediate)
{
	/* Logic changed here */
    if (! is_on)
        is_on = 1;

    if (vbus_state == is_on)
        return;

    vbus_state = is_on;     /* 0/1 vs "-1 == unknown/init" */
    printf("vbus_state current value is   %d \r\n ", vbus_state);
}

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;

    /* TO DO: 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) {
        /* TO DO 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)

/**
 *\brief: USB initialize routine.
 *
 *        This routine initializes the sub-system(SubModule)like OTG.
 *
 *
 *
 *
 */
int musb_platform_init(void)
{
    void *reg_base = (void *)TI816X_USB0_BASE;
    UINT32 rev;
    UINT8 mode;

    rev = INIT_VALUE;

    /* usb subsystem init */
    usbotg_ss_init();
	
    rev = musb_readl(reg_base, USB_REVISION_REG);
    if (!rev)
        return -1;
	printf("MUSB revision: 0x%X\n", rev);

	/* Enabling the vbus_state */
    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));

    printf("\r\n Disabling the clocks at address 0x%x \r\n",CM_ALWON2_USB_CLKCTRL);
    /* 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 */
    /* clock disable */
    //clk_disable(musb->clock);
	/* TO DO:  The clock was disabled before phy_on, why? */
	
    /* Start the on-chip PHY and its PLL. */
    phy_on(PHY_ID);
        /* 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 */

    //msleep(5);

    /* clock enable */
    //clk_enable(musb->clock);

    /* 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;
}

void main (void)
{
	void *reg_base = (void *)TI816X_USB0_BASE;
	UINT8 reg_val = 0;
#ifdef DEBUG
	printf("\r\n USB0 register base address  0x%x\r\n",*(VUINT32*)reg_base);
#endif
	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
	*/
	/*	TO DO:
		1.	PRCM/MUX needs to get done in Gel.
		2. 	Need datasheet to determine the base addresses for DM8127
		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));
}
