diff options
Diffstat (limited to 'drivers/usb/gadget/s3c-hsotg.c')
| -rw-r--r-- | drivers/usb/gadget/s3c-hsotg.c | 57 | 
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 1f73b485732..26193eceb32 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -297,6 +297,12 @@ static void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg,   */  static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)  { +	unsigned int ep; +	unsigned int addr; +	unsigned int size; +	int timeout; +	u32 val; +  	/* the ryu 2.6.24 release ahs  	   writel(0x1C0, hsotg->regs + S3C_GRXFSIZ);  	   writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) | @@ -310,6 +316,51 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)  	writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) |  	       S3C_GNPTXFSIZ_NPTxFDep(0x1C0),  	       hsotg->regs + S3C_GNPTXFSIZ); + +	/* arange all the rest of the TX FIFOs, as some versions of this +	 * block have overlapping default addresses. This also ensures +	 * that if the settings have been changed, then they are set to +	 * known values. */ + +	/* start at the end of the GNPTXFSIZ, rounded up */ +	addr = 2048 + 1024; +	size = 768; + +	/* currently we allocate TX FIFOs for all possible endpoints, +	 * and assume that they are all the same size. */ + +	for (ep = 0; ep <= 15; ep++) { +		val = addr; +		val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT; +		addr += size; + +		writel(val, hsotg->regs + S3C_DPTXFSIZn(ep)); +	} + +	/* according to p428 of the design guide, we need to ensure that +	 * all fifos are flushed before continuing */ + +	writel(S3C_GRSTCTL_TxFNum(0x10) | S3C_GRSTCTL_TxFFlsh | +	       S3C_GRSTCTL_RxFFlsh, hsotg->regs + S3C_GRSTCTL); + +	/* wait until the fifos are both flushed */ +	timeout = 100; +	while (1) { +		val = readl(hsotg->regs + S3C_GRSTCTL); + +		if ((val & (S3C_GRSTCTL_TxFFlsh | S3C_GRSTCTL_RxFFlsh)) == 0) +			break; + +		if (--timeout == 0) { +			dev_err(hsotg->dev, +				"%s: timeout flushing fifos (GRSTCTL=%08x)\n", +				__func__, val); +		} + +		udelay(1); +	} + +	dev_dbg(hsotg->dev, "FIFOs reset, timeout at %d\n", timeout);  }  /** @@ -2574,6 +2625,9 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)  	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); @@ -2730,6 +2784,9 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)  	writel(0, hsotg->regs + S3C_DAINTMSK); +	/* Be in disconnected state until gadget is registered */ +	__orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); +  	if (0) {  		/* post global nak until we're ready */  		writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak,  |