Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 303821
b: refs/heads/master
c: 308d734
h: refs/heads/master
i:
  303819: cfa55a8
v: v3
  • Loading branch information
Lukasz Majewski authored and Felipe Balbi committed May 4, 2012
1 parent 52a255f commit 81fe181
Show file tree
Hide file tree
Showing 2 changed files with 174 additions and 162 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d3ca0259c56ee2dbc537d88a7496aba6b4712981
refs/heads/master: 308d734e9ed86b6713da46b4b9ce9ff017e75c63
334 changes: 173 additions & 161 deletions trunk/drivers/usb/gadget/s3c-hsotg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2138,6 +2138,178 @@ static struct s3c_hsotg *our_hsotg;
S3C_GINTSTS_PTxFEmp | \
S3C_GINTSTS_RxFLvl)

/**
* s3c_hsotg_corereset - issue softreset to the core
* @hsotg: The device state
*
* Issue a soft reset to the core, and await the core finishing it.
*/
static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
{
int timeout;
u32 grstctl;

dev_dbg(hsotg->dev, "resetting core\n");

/* issue soft reset */
writel(S3C_GRSTCTL_CSftRst, hsotg->regs + S3C_GRSTCTL);

timeout = 1000;
do {
grstctl = readl(hsotg->regs + S3C_GRSTCTL);
} while ((grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0);

if (grstctl & S3C_GRSTCTL_CSftRst) {
dev_err(hsotg->dev, "Failed to get CSftRst asserted\n");
return -EINVAL;
}

timeout = 1000;

while (1) {
u32 grstctl = readl(hsotg->regs + S3C_GRSTCTL);

if (timeout-- < 0) {
dev_info(hsotg->dev,
"%s: reset failed, GRSTCTL=%08x\n",
__func__, grstctl);
return -ETIMEDOUT;
}

if (!(grstctl & S3C_GRSTCTL_AHBIdle))
continue;

break; /* reset done */
}

dev_dbg(hsotg->dev, "reset successful\n");
return 0;
}

static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
{
s3c_hsotg_corereset(hsotg);

/*
* we must now enable ep0 ready for host detection and then
* set configuration.
*/

/* set the PLL on, remove the HNP/SRP and set the PHY */
writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) |
(0x5 << 10), hsotg->regs + S3C_GUSBCFG);

s3c_hsotg_init_fifo(hsotg);

__orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);

writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG);

/* Clear any pending OTG interrupts */
writel(0xffffffff, hsotg->regs + S3C_GOTGINT);

/* Clear any pending interrupts */
writel(0xffffffff, hsotg->regs + S3C_GINTSTS);

writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt |
S3C_GINTSTS_GOUTNakEff | S3C_GINTSTS_GINNakEff |
S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst |
S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt |
S3C_GINTSTS_USBSusp | S3C_GINTSTS_WkUpInt |
S3C_GINTSTS_ErlySusp,
hsotg->regs + S3C_GINTMSK);

if (using_dma(hsotg))
writel(S3C_GAHBCFG_GlblIntrEn | S3C_GAHBCFG_DMAEn |
S3C_GAHBCFG_HBstLen_Incr4,
hsotg->regs + S3C_GAHBCFG);
else
writel(S3C_GAHBCFG_GlblIntrEn, hsotg->regs + S3C_GAHBCFG);

/*
* Enabling INTknTXFEmpMsk here seems to be a big mistake, we end
* up being flooded with interrupts if the host is polling the
* endpoint to try and read data.
*/

writel(((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0) |
S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk |
S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
S3C_DIEPMSK_INTknEPMisMsk,
hsotg->regs + S3C_DIEPMSK);

/*
* don't need XferCompl, we get that from RXFIFO in slave mode. In
* DMA mode we may need this.
*/
writel((using_dma(hsotg) ? (S3C_DIEPMSK_XferComplMsk |
S3C_DIEPMSK_TimeOUTMsk) : 0) |
S3C_DOEPMSK_EPDisbldMsk | S3C_DOEPMSK_AHBErrMsk |
S3C_DOEPMSK_SetupMsk,
hsotg->regs + S3C_DOEPMSK);

writel(0, hsotg->regs + S3C_DAINTMSK);

dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
readl(hsotg->regs + S3C_DIEPCTL0),
readl(hsotg->regs + S3C_DOEPCTL0));

/* enable in and out endpoint interrupts */
s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt);

/*
* Enable the RXFIFO when in slave mode, as this is how we collect
* the data. In DMA mode, we get events from the FIFO but also
* things we cannot process, so do not use it.
*/
if (!using_dma(hsotg))
s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_RxFLvl);

/* Enable interrupts for EP0 in and out */
s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1);
s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1);

__orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone);
udelay(10); /* see openiboot */
__bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone);

dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL));

/*
* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by
* writing to the EPCTL register..
*/

/* set to read 1 8byte packet */
writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) |
S3C_DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0);

writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
S3C_DxEPCTL_CNAK | S3C_DxEPCTL_EPEna |
S3C_DxEPCTL_USBActEp,
hsotg->regs + S3C_DOEPCTL0);

/* enable, but don't activate EP0in */
writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
S3C_DxEPCTL_USBActEp, hsotg->regs + S3C_DIEPCTL0);

s3c_hsotg_enqueue_setup(hsotg);

dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
readl(hsotg->regs + S3C_DIEPCTL0),
readl(hsotg->regs + S3C_DOEPCTL0));

/* clear global NAKs */
writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK,
hsotg->regs + S3C_DCTL);

/* must be at-least 3ms to allow bus to see disconnect */
mdelay(3);

/* remove the soft-disconnect and let's go */
__bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);
}

/**
* s3c_hsotg_irq - handle device interrupt
* @irq: The IRQ number triggered
Expand Down Expand Up @@ -2578,54 +2750,6 @@ static struct usb_ep_ops s3c_hsotg_ep_ops = {
/* note, don't believe we have any call for the fifo routines */
};

/**
* s3c_hsotg_corereset - issue softreset to the core
* @hsotg: The device state
*
* Issue a soft reset to the core, and await the core finishing it.
*/
static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
{
int timeout;
u32 grstctl;

dev_dbg(hsotg->dev, "resetting core\n");

/* issue soft reset */
writel(S3C_GRSTCTL_CSftRst, hsotg->regs + S3C_GRSTCTL);

timeout = 1000;
do {
grstctl = readl(hsotg->regs + S3C_GRSTCTL);
} while ((grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0);

if (grstctl & S3C_GRSTCTL_CSftRst) {
dev_err(hsotg->dev, "Failed to get CSftRst asserted\n");
return -EINVAL;
}

timeout = 1000;

while (1) {
u32 grstctl = readl(hsotg->regs + S3C_GRSTCTL);

if (timeout-- < 0) {
dev_info(hsotg->dev,
"%s: reset failed, GRSTCTL=%08x\n",
__func__, grstctl);
return -ETIMEDOUT;
}

if (!(grstctl & S3C_GRSTCTL_AHBIdle))
continue;

break; /* reset done */
}

dev_dbg(hsotg->dev, "reset successful\n");
return 0;
}

/**
* s3c_hsotg_phy_enable - enable platform phy dev
*
Expand Down Expand Up @@ -2706,119 +2830,7 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver,
goto err;
}

/* we must now enable ep0 ready for host detection and then
* set configuration. */

s3c_hsotg_corereset(hsotg);

/* set the PLL on, remove the HNP/SRP and set the PHY */
writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) |
(0x5 << 10), hsotg->regs + S3C_GUSBCFG);

/* looks like soft-reset changes state of FIFOs */
s3c_hsotg_init_fifo(hsotg);

__orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);

writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG);

/* Clear any pending OTG interrupts */
writel(0xffffffff, hsotg->regs + S3C_GOTGINT);

/* Clear any pending interrupts */
writel(0xffffffff, hsotg->regs + S3C_GINTSTS);

writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt |
S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst |
S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt |
S3C_GINTSTS_USBSusp | S3C_GINTSTS_WkUpInt |
S3C_GINTSTS_GOUTNakEff | S3C_GINTSTS_GINNakEff |
S3C_GINTSTS_ErlySusp,
hsotg->regs + S3C_GINTMSK);

if (using_dma(hsotg))
writel(S3C_GAHBCFG_GlblIntrEn | S3C_GAHBCFG_DMAEn |
S3C_GAHBCFG_HBstLen_Incr4,
hsotg->regs + S3C_GAHBCFG);
else
writel(S3C_GAHBCFG_GlblIntrEn, hsotg->regs + S3C_GAHBCFG);

/* Enabling INTknTXFEmpMsk here seems to be a big mistake, we end
* up being flooded with interrupts if the host is polling the
* endpoint to try and read data. */

writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk |
S3C_DIEPMSK_INTknEPMisMsk |
S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk |
((hsotg->dedicated_fifos) ? S3C_DIEPMSK_TxFIFOEmpty : 0),
hsotg->regs + S3C_DIEPMSK);

/* don't need XferCompl, we get that from RXFIFO in slave mode. In
* DMA mode we may need this. */
writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk |
S3C_DOEPMSK_EPDisbldMsk |
(using_dma(hsotg) ? (S3C_DIEPMSK_XferComplMsk |
S3C_DIEPMSK_TimeOUTMsk) : 0),
hsotg->regs + S3C_DOEPMSK);

writel(0, hsotg->regs + S3C_DAINTMSK);

dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
readl(hsotg->regs + S3C_DIEPCTL0),
readl(hsotg->regs + S3C_DOEPCTL0));

/* enable in and out endpoint interrupts */
s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt);

/* Enable the RXFIFO when in slave mode, as this is how we collect
* the data. In DMA mode, we get events from the FIFO but also
* things we cannot process, so do not use it. */
if (!using_dma(hsotg))
s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_RxFLvl);

/* Enable interrupts for EP0 in and out */
s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1);
s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1);

__orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone);
udelay(10); /* see openiboot */
__bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone);

dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL));

/* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by
writing to the EPCTL register.. */

/* set to read 1 8byte packet */
writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) |
S3C_DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0);

writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
S3C_DxEPCTL_CNAK | S3C_DxEPCTL_EPEna |
S3C_DxEPCTL_USBActEp,
hsotg->regs + S3C_DOEPCTL0);

/* enable, but don't activate EP0in */
writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
S3C_DxEPCTL_USBActEp, hsotg->regs + S3C_DIEPCTL0);

s3c_hsotg_enqueue_setup(hsotg);

dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
readl(hsotg->regs + S3C_DIEPCTL0),
readl(hsotg->regs + S3C_DOEPCTL0));

/* clear global NAKs */
writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK,
hsotg->regs + S3C_DCTL);

/* must be at-least 3ms to allow bus to see disconnect */
msleep(3);

/* remove the soft-disconnect and let's go */
__bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon);

/* report to the user, and return */
s3c_hsotg_core_init(hsotg);

dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
return 0;
Expand Down

0 comments on commit 81fe181

Please sign in to comment.