Example #1
0
/*
 * This function is called when the SRP timer expires.	The SRP should
 * complete within 6 seconds. 
 */
static void s3c_udc_srp_timeout(unsigned long _ptr )
{
	struct s3c_udc *dev = the_controller;
	struct timer_list *srp_timer = &dev->srp_timer;
	u32 usb_otgctl;	
	
	DEBUG_SETUP("[%s] SRP Timeout \n", __func__);		

	/*
		Currently (2009.6.22) OTG not supported
		Originally GOTGINT.SesReqSucStsChng interrupt handler should read 
		GOTGCTL.SesReqScs
		ref. Synopsis Spec. 5.3.2.2 OTG Interrupt Register(GOTGINT)
	*/
	usb_otgctl = readl(S3C_UDC_OTG_GOTGCTL);
	if (usb_otgctl & B_SESSION_VALID &&
		usb_otgctl & SESSION_REQ_SUCCESS)
	{
		DEBUG_SETUP("[%s] SRP Success \n", __func__);		
		spin_unlock(&dev->lock);
		dev->driver->resume(&dev->gadget);
		spin_lock(&dev->lock);
	
		del_timer(srp_timer);		
	}
	else
	{
		DEBUG_SETUP("[%s] Device not connected/responding \n", __func__);		
	}
	
	usb_otgctl &= ~SESSION_REQ;
	writel(usb_otgctl, S3C_UDC_OTG_GOTGCTL);
}
/* 
 * until it becomes enabled, this UDC should be completely invisible
 * to any USB host.
 */
static int udc_enable(struct s3c_udc *dev)
{
	u32 uTemp;
	DEBUG_SETUP("%s: %p\n", __FUNCTION__, dev);

	uTemp = readl(S3C_OTHERS);
	uTemp |= (1<<16);   // USB_SIG_MASK
	writel(uTemp, S3C_OTHERS);
	
	// 1. Initializes OTG Phy.
	writel(0x0, S3C_USBOTG_PHYPWR);
//	writel(0x20, S3C_USBOTG_PHYCLK);
	writel(0x02, S3C_USBOTG_PHYCLK); /* 2010-0208, modified by CVKK(JC) */
	writel(0x1, S3C_USBOTG_RSTCON);
	udelay(50);
	writel(0x0, S3C_USBOTG_RSTCON);
	udelay(50);
	
	dev->udc_state = USB_STATE_POWERED;
	dev->gadget.speed = USB_SPEED_UNKNOWN;

	reconfig_usbd(dev);

	DEBUG_SETUP("S3C USB 2.0 OTG Controller Core Initialized : 0x%x\n",
			readl(S3C_UDC_OTG_GINTMSK));
	
	return 0;
}
Example #3
0
/* until it's enabled, this UDC should be completely invisible
 * to any USB host.
 */
static int udc_enable(struct s3c_udc *dev)
{
	DEBUG_SETUP("%s: %p\n", __FUNCTION__, dev);

	/* if reset by sleep wakeup, control the retention I/O cell */
	if (__raw_readl(S3C_RSTSTAT) & 0x8)
		__raw_writel(__raw_readl(S3C_RSTCON)|(1<<16), S3C_RSTCON);


	/* USB Port is Normal mode */
	__raw_writel(__raw_readl(S3C2410_MISCCR)&~(1<<12), S3C2410_MISCCR);

	/* PHY power enable */
	__raw_writel(__raw_readl(S3C_PWRCFG)|(1<<4), S3C_PWRCFG);

	/* USB device 2.0 must reset like bellow,
	 * 1st phy reset and after at least 10us, func_reset & host reset
	 * phy reset can reset bellow registers.
	 */
	/* PHY 2.0 S/W reset */
	__raw_writel((0<<2)|(0<<1)|(1<<0), S3C_URSTCON);
	udelay(20); /* phy reset must be asserted for at 10us */
	
	/*Function 2.0, Host 1.1 S/W reset*/
	__raw_writel((1<<2)|(1<<1)|(0<<0), S3C_URSTCON);
	__raw_writel((0<<2)|(0<<1)|(0<<0), S3C_URSTCON);
	
	/* 48Mhz,Crystal,External X-tal,device */
	__raw_writel((0<<3)|(0<<2)|(1<<1)|(0<<0), S3C_PHYCTRL);
	
	/* 48Mhz clock on ,PHY2.0 analog block power on
	 * XO block power on,XO block power in suspend mode,
	 * PHY 2.0 Pll power on ,suspend signal for save mode disable
	 */
	__raw_writel((1<<31)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0), S3C_PHYPWR);

	/* D+ pull up disable(VBUS detect), USB2.0 Function clock Enable,
	 * USB1.1 HOST disable, USB2.0 PHY test enable
	 */
	__raw_writel((0<<31)|(1<<2)|(0<<1)|(1<<0), S3C_UCLKCON);

	__raw_writel(IRQ_USBD, S3C2410_INTPND);
	__raw_writel(IRQ_USBD, S3C2410_SRCPND);

	reconfig_usbd();
	
	__raw_writel(__raw_readl(S3C2410_INTMSK)&~(IRQ_USBD), S3C2410_INTMSK);

	/* D+ pull up , USB2.0 Function clock Enable,
	 * USB1.1 HOST disable,USB2.0 PHY test enable
	 */
	__raw_writel((1<<31)|(1<<2)|(0<<1)|(1<<0), S3C_UCLKCON);
	
	DEBUG_SETUP("S3C2443 USB Controller Core Initialized\n");
	
	dev->gadget.speed = USB_SPEED_UNKNOWN;

	return 0;
}
Example #4
0
/*
 * Unregister entry point for the peripheral controller driver.
 */ 
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{
	struct s3c_udc *dev = the_controller;
	unsigned long flags;

	if (!dev)
		return -ENODEV;
	if (!driver || driver != dev->driver)
		return -EINVAL;
	
	disable_irq(IRQ_OTG);

	spin_lock_irqsave(&dev->lock, flags);
	s3c_udc_stop_activity(dev, driver);
	spin_unlock_irqrestore(&dev->lock, flags);

	driver->unbind(&dev->gadget);
	device_del(&dev->gadget.dev);

	DEBUG_SETUP("Unregistered gadget driver '%s'\n", driver->driver.name);

#ifndef CONFIG_PM
	s3c_udc_disable(dev);
#endif	
	dev->gadget.dev.driver = NULL;
	dev->driver = NULL;
	dev->config_gadget_driver = NO_GADGET_DRIVER;

	return 0;
}
Example #5
0
/*
 * 	s3c_ep_list_reinit - initialize software state
 */
static void s3c_ep_list_reinit(struct s3c_udc *dev)
{
	u8 i;

	DEBUG_SETUP("%s: %p\n", __func__, dev);

	/* device/ep0 records init */
	INIT_LIST_HEAD(&dev->gadget.ep_list);
	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
	dev->ep0state = WAIT_FOR_SETUP;

	/* basic endpoint records init */
	for (i = 0; i < S3C_MAX_ENDPOINTS; i++) {
		struct s3c_ep *ep = &dev->ep[i];

		if (i != 0)
			list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);

		ep->desc = 0;
		ep->stopped = 0;
		ep->pio_irqs = 0;
		INIT_LIST_HEAD(&ep->queue);
	}

	/* the rest was statically initialized, and is read-only */
}
Example #6
0
/*
 * 	udc_disable - disable USB device controller
 */
static void udc_disable(struct s3c_udc *dev)
{
	DEBUG_SETUP("%s: %p\n", __FUNCTION__, dev);

	udc_set_address(dev, 0);

	dev->ep0state = WAIT_FOR_SETUP;
	dev->gadget.speed = USB_SPEED_UNKNOWN;
	dev->usb_address = 0;

	/* usb power disable */
#if defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
	s3c2410_gpio_pullup(S3C2443_GPH14, 1); /* pull-down enable */
	s3c2410_gpio_pullup(S3C2410_GPF2, 1);  /* pull-down enable */
#else
	s3c2410_gpio_pullup(S3C2443_GPH14, 2); /* pull-down enable */
#endif
	s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
	s3c2410_gpio_setpin(S3C2443_GPH14, 0);

	/* usb clock disable */
	__raw_writel(0, S3C_UCLKCON);

	/* USB Port is Suspend mode */
	__raw_writel(__raw_readl(S3C2410_MISCCR)|(1<<12), S3C2410_MISCCR);

	/* PHY power disable */
	__raw_writel(__raw_readl(S3C_PWRCFG)&~(1<<4), S3C_PWRCFG);

}
Example #7
0
/*
 * 	udc_disable - disable USB device controller
 */
static void udc_disable(struct s3c_udc *dev)
{
	DEBUG_SETUP("%s: %p\n", __FUNCTION__, dev);

	udc_set_address(dev, 0);

	dev->ep0state = WAIT_FOR_SETUP;
	dev->gadget.speed = USB_SPEED_UNKNOWN;
	dev->usb_address = 0;
	__raw_writel(__raw_readl(S3C_PWRCFG)&~(1<<4), S3C_PWRCFG);
}
/*
 * 	udc_disable - disable USB device controller
 */
static void udc_disable(struct s3c_udc *dev)
{
	DEBUG_SETUP("%s: %p\n", __FUNCTION__, dev);

	udc_set_address(dev, 0);

	dev->ep0state = WAIT_FOR_SETUP;
	dev->gadget.speed = USB_SPEED_UNKNOWN;
	dev->usb_address = 0;
	//writel(readl(S3C_USBOTG_PHYPWR)|(0x7<<1), S3C_USBOTG_PHYPWR);
        otg_phy_init(0x42); /* 2010-0208, added by CVKK(JC) */
	dev->udc_state = USB_STATE_NOTATTACHED;
}
Example #9
0
/* 
 * until it becomes enabled, this UDC should be completely invisible
 * to any USB host.
 */
static int s3c_udc_enable(struct s3c_udc *dev)
{
	u32 reg_val;
	DEBUG_SETUP("%s: %p\n", __func__, dev);

#if USING_MACH_OTG_PHY
	otg_phy_init();
#else

	writel(1, S5P_USB_PHY_CONTROL);
	writel(0xa0, S3C_USBOTG_PHYPWR);				/* Power up */
	writel(OTGH_PHY_CLK_VALUE, S3C_USBOTG_PHYCLK);
	writel(0x1, S3C_USBOTG_RSTCON);
	udelay(50);
	writel(0x0, S3C_USBOTG_RSTCON);
	udelay(50);

#endif
	
	dev->udc_state = USB_STATE_POWERED;
	dev->gadget.speed = USB_SPEED_UNKNOWN;
	
	/* 14. Initialize OTG Link Core. */
	writel(GAHBCFG_INIT, S3C_UDC_OTG_GAHBCFG);
	
	writel( 0<<15		// PHY Low Power Clock sel
		|1<<14		// Non-Periodic TxFIFO Rewind Enable
		|0x5<<10	// Turnaround time
		|0<<9|0<<8	// [0:HNP disable, 1:HNP enable][ 0:SRP disable, 1:SRP enable] H1= 1,1
		|0<<7		// Ulpi DDR sel
		|0<<6		// 0: high speed utmi+, 1: full speed serial
		|0<<4		// 0: utmi+, 1:ulpi
		|1<<3		// phy i/f	0:8bit, 1:16bit
		|0x7<<0,	// HS/FS Timeout*
		S3C_UDC_OTG_GUSBCFG);

	s3c_udc_initialize(dev);

	//change proper register instead of S3C_UDC_OTG_GINTMSK
	reg_val = readl(S3C_UDC_OTG_GINTMSK);
	if(!reg_val)
	{
		DEBUG_ERROR("[%s] Fail to set GINTMSK 0x%x\n", __func__, reg_val);
		return -1;
	}
	return 0;
}
Example #10
0
/* 
 * until it becomes enabled, this UDC should be completely invisible
 * to any USB host.
 */
static int s3c_udc_enable(struct s3c_udc *dev)
{
	u32 reg_val;
	DEBUG_SETUP("%s: %p\n", __func__, dev);

	reg_val = readl(S3C_OTHERS);
	reg_val |= (1<<16);   // USB_SIG_MASK
	writel(reg_val, S3C_OTHERS);
	
	// 1. Initializes OTG Phy.
	writel(0x0, S3C_USBOTG_PHYPWR);
	writel(0x20, S3C_USBOTG_PHYCLK);
	writel(0x1, S3C_USBOTG_RSTCON);
	// confirm delay time with thinking pm logic
	udelay(50);
	writel(0x0, S3C_USBOTG_RSTCON);
	udelay(50);
	
	dev->udc_state = USB_STATE_POWERED;
	dev->gadget.speed = USB_SPEED_UNKNOWN;
	
	/* 14. Initialize OTG Link Core. */
	writel(GAHBCFG_INIT, S3C_UDC_OTG_GAHBCFG);
	
	writel( 0<<15		// PHY Low Power Clock sel
		|1<<14		// Non-Periodic TxFIFO Rewind Enable
		|0x5<<10	// Turnaround time
		|0<<9|0<<8	// [0:HNP disable, 1:HNP enable][ 0:SRP disable, 1:SRP enable] H1= 1,1
		|0<<7		// Ulpi DDR sel
		|0<<6		// 0: high speed utmi+, 1: full speed serial
		|0<<4		// 0: utmi+, 1:ulpi
		|1<<3		// phy i/f	0:8bit, 1:16bit
		|0x7<<0,	// HS/FS Timeout*
		S3C_UDC_OTG_GUSBCFG);

	s3c_udc_initialize(dev);

	//change proper register instead of S3C_UDC_OTG_GINTMSK
	reg_val = readl(S3C_UDC_OTG_GINTMSK);
	if(!reg_val)
	{
		DEBUG_ERROR("[%s] Fail to set GINTMSK 0x%x\n", __func__, reg_val);
		return -1;
	}
	return 0;
}
Example #11
0
/*
  Register entry point for the peripheral controller driver.
*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
{
	struct s3c_udc *dev = the_controller;
	int retval;

	DEBUG_SETUP("%s: %s\n", __FUNCTION__, driver->driver.name);

	if (!driver
	    || (driver->speed != USB_SPEED_FULL && driver->speed != USB_SPEED_HIGH)
	    || !driver->bind
	    || !driver->unbind || !driver->disconnect || !driver->setup)
		return -EINVAL;
	if (!dev)
		return -ENODEV;
	if (dev->driver)
		return -EBUSY;

	/* first hook up the driver ... */
	dev->driver = driver;
	dev->gadget.dev.driver = &driver->driver;
	retval = device_add(&dev->gadget.dev);

	if(retval) { /* TODO */
		printk("target device_add failed, error %d\n", retval);
		return retval;
	}

	retval = driver->bind(&dev->gadget);
	if (retval) {
		printk("%s: bind to driver %s --> error %d\n", dev->gadget.name,
		       driver->driver.name, retval);
		device_del(&dev->gadget.dev);

		dev->driver = 0;
		dev->gadget.dev.driver = 0;
		return retval;
	}

	enable_irq(IRQ_USBD);

	printk("Registered gadget driver '%s'\n", driver->driver.name);
	udc_enable(dev);

	return 0;
}
/*
 *	elfin usb client interrupt handler.
 */
static irqreturn_t s3c_udc_irq(int irq, void *_dev)
{
	struct s3c_udc *dev = _dev;
	u32 intr_status;
	u32 usb_status, ep_ctrl, gintmsk;

	spin_lock(&dev->lock);

	intr_status = readl(S3C_UDC_OTG_GINTSTS);
	gintmsk = readl(S3C_UDC_OTG_GINTMSK);

	DEBUG_ISR("\n**** %s : GINTSTS=0x%x(on state %s), GINTMSK : 0x%x\n",
			__FUNCTION__, intr_status, state_names[dev->ep0state], gintmsk);

	if (!intr_status) {
		spin_unlock(&dev->lock);
		return IRQ_HANDLED;
	}

	if (intr_status & INT_ENUMDONE) {
		DEBUG_SETUP("####################################\n");
		DEBUG_SETUP("    %s: Speed Detection interrupt\n",
				__FUNCTION__);
		writel(INT_ENUMDONE, S3C_UDC_OTG_GINTSTS);

		usb_status = (readl(S3C_UDC_OTG_DSTS) & 0x6);

		if (usb_status & (USB_FULL_30_60MHZ | USB_FULL_48MHZ)) {
			DEBUG_SETUP("    %s: Full Speed Detection\n",__FUNCTION__);
			set_max_pktsize(dev, USB_SPEED_FULL);

		} else {
			DEBUG_SETUP("    %s: High Speed Detection : 0x%x\n", __FUNCTION__, usb_status);
			set_max_pktsize(dev, USB_SPEED_HIGH);
		}
	}

	if (intr_status & INT_EARLY_SUSPEND) {
		DEBUG_SETUP("####################################\n");
		DEBUG_SETUP("    %s:Early suspend interrupt\n", __FUNCTION__);
		writel(INT_EARLY_SUSPEND, S3C_UDC_OTG_GINTSTS);
	}

	if (intr_status & INT_SUSPEND) {
		usb_status = readl(S3C_UDC_OTG_DSTS);
		DEBUG_SETUP("####################################\n");
		DEBUG_SETUP("    %s:Suspend interrupt :(DSTS):0x%x\n", __FUNCTION__, usb_status);
		writel(INT_SUSPEND, S3C_UDC_OTG_GINTSTS);

		if (dev->gadget.speed != USB_SPEED_UNKNOWN
		    && dev->driver
		    && dev->driver->suspend) {

			dev->driver->suspend(&dev->gadget);
		}
	}

	if (intr_status & INT_RESUME) {
		DEBUG_SETUP("####################################\n");
		DEBUG_SETUP("    %s: Resume interrupt\n", __FUNCTION__);
		writel(INT_RESUME, S3C_UDC_OTG_GINTSTS);

		if (dev->gadget.speed != USB_SPEED_UNKNOWN
		    && dev->driver
		    && dev->driver->resume) {

			dev->driver->resume(&dev->gadget);
		}
	}

	if (intr_status & INT_RESET) {
		usb_status = readl(S3C_UDC_OTG_GOTGCTL);
		DEBUG_SETUP("####################################\n");
		DEBUG_SETUP("    %s: Reset interrupt - (GOTGCTL):0x%x\n", __FUNCTION__, usb_status);
		writel(INT_RESET, S3C_UDC_OTG_GINTSTS);

		if((usb_status & 0xc0000) == (0x3 << 18)) {
			if(reset_available) {
				DEBUG_SETUP("     ===> OTG core got reset (%d)!! \n", reset_available);
				reconfig_usbd();
				dev->ep0state = WAIT_FOR_SETUP;
				reset_available = 0;
			}
		} else {
			reset_available = 1;
			DEBUG_SETUP("      RESET handling skipped : reset_available : %d\n", reset_available);
		}
	}

	if (intr_status & INT_RX_FIFO_NOT_EMPTY) {
		u32 grx_status, packet_status, ep_num, fifoCntByte = 0;

		/* Mask USB OTG 2.0 interrupt source : INT_RX_FIFO_NOT_EMPTY */
		gintmsk &= ~INT_RX_FIFO_NOT_EMPTY;
		writel(gintmsk, S3C_UDC_OTG_GINTMSK);

		grx_status = readl(S3C_UDC_OTG_GRXSTSR);
		DEBUG_ISR("    INT_RX_FIFO_NOT_EMPTY(GRXSTSR):0x%x, GINTMSK:0x%x\n", grx_status, gintmsk);

		packet_status = grx_status & 0x1E0000;
		fifoCntByte = (grx_status & 0x7ff0)>>4;
		ep_num = grx_status & EP_MASK;

		if (fifoCntByte) {

			if (packet_status == SETUP_PKT_RECEIVED)  {
				DEBUG_EP0("      => A SETUP data packet received : %d bytes\n", fifoCntByte);
				s3c_handle_ep0(dev);

				/* Unmask USB OTG 2.0 interrupt source : INT_RX_FIFO_NOT_EMPTY */
				gintmsk |= INT_RX_FIFO_NOT_EMPTY;

			} else if (packet_status == OUT_PKT_RECEIVED) {
				if(ep_num == EP1_OUT) {
					ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL1);
					DEBUG_ISR("      => A Bulk OUT data packet received : %d bytes, (DOEPCTL1):0x%x\n",
						fifoCntByte, ep_ctrl);
					s3c_out_epn(dev, 1);
					gintmsk = readl(S3C_UDC_OTG_GINTMSK);
					writel(ep_ctrl | DEPCTL_CNAK, S3C_UDC_OTG_DOEPCTL1);
				} else if (ep_num == EP0_CON) {
					ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL0);
					DEBUG_EP0("      => A CONTROL OUT data packet received : %d bytes, (DOEPCTL0):0x%x\n",
						fifoCntByte, ep_ctrl);
					dev->ep0state = DATA_STATE_RECV;
					s3c_ep0_read(dev);
					gintmsk |= INT_RX_FIFO_NOT_EMPTY;
				} else {
					DEBUG_ISR("      => Unused EP: %d bytes, (GRXSTSR):0x%x\n", fifoCntByte, grx_status);
				}
			} else {
				grx_status = readl(S3C_UDC_OTG_GRXSTSP);

				/* Unmask USB OTG 2.0 interrupt source : INT_RX_FIFO_NOT_EMPTY */
				gintmsk |= INT_RX_FIFO_NOT_EMPTY;

				DEBUG_ISR("      => A reserved packet received : %d bytes\n", fifoCntByte);
			}
		} else {
			if (dev->ep0state == DATA_STATE_XMIT) {
				ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL0);
				DEBUG_EP0("      => Write ep0 continue... (DOEPCTL0):0x%x\n", ep_ctrl);
				s3c_ep0_write(dev);
			}

			if (packet_status == SETUP_TRANSACTION_COMPLETED) {
				ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL0);
				DEBUG_EP0("      => A SETUP transaction completed (DOEPCTL0):0x%x\n", ep_ctrl);
				writel(ep_ctrl | DEPCTL_CNAK, S3C_UDC_OTG_DOEPCTL0);

			} else if (packet_status == OUT_TRANSFER_COMPLELTED) {
				if (ep_num == EP1_OUT) {
					ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL1);
					DEBUG_ISR("      => An OUT transaction completed (DOEPCTL1):0x%x\n", ep_ctrl);
					writel(ep_ctrl | DEPCTL_CNAK, S3C_UDC_OTG_DOEPCTL1);
				} else if (ep_num == EP0_CON) {
					ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL0);
					DEBUG_ISR("      => An OUT transaction completed (DOEPCTL0):0x%x\n", ep_ctrl);
					writel(ep_ctrl | DEPCTL_CNAK, S3C_UDC_OTG_DOEPCTL0);
				} else {
					DEBUG_ISR("      => Unused EP: %d bytes, (GRXSTSR):0x%x\n", fifoCntByte, grx_status);
				}
			} else if (packet_status == OUT_PKT_RECEIVED) {
				DEBUG_ISR("      => A  OUT PACKET RECEIVED (NO FIFO CNT BYTE)...(GRXSTSR):0x%x\n", grx_status);
			} else {
				DEBUG_ISR("      => A RESERVED PACKET RECEIVED (NO FIFO CNT BYTE)...(GRXSTSR):0x%x\n", grx_status);
			}

			grx_status = readl(S3C_UDC_OTG_GRXSTSP);

			/* Unmask USB OTG 2.0 interrupt source : INT_RX_FIFO_NOT_EMPTY */
			gintmsk |= INT_RX_FIFO_NOT_EMPTY;

		}

		/* Un/Mask USB OTG 2.0 interrupt sources */
		writel(gintmsk, S3C_UDC_OTG_GINTMSK);

		spin_unlock(&dev->lock);
		return IRQ_HANDLED;
	}
Example #13
0
/*
 * usb_gadget_ops wake-up 
 * This function starts the Protocol if no session is in progress. If
 * a session is already in progress, but the device is suspended,
 * remote wakeup signaling is started.
 */ 
static int s3c_udc_wakeup(struct usb_gadget *_gadget)
{
	struct s3c_udc *dev = the_controller;
	struct timer_list *srp_timer = &dev->srp_timer;
	
	u32 usb_otgctl, usb_dctl, usb_status;	
	unsigned long flags;
	int ret = -EINVAL;
	if (!_gadget)
	{
		return -ENODEV;
	} 
	DEBUG("[%s]: %s\n", __func__, _gadget->name);
 
	spin_lock_irqsave(&dev->lock, flags);
	if (!(dev->devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))) 
	{
		DEBUG_ERROR("[%s]Not set USB_DEVICE_REMOTE_WAKEUP \n", __func__);		
		goto s3c_udc_wakeup_exit;
	}
	
	/* Check if valid session */
	usb_otgctl = readl(S3C_UDC_OTG_GOTGCTL);
	if (usb_otgctl & B_SESSION_VALID)
	{
		/* Check if suspend state */
		usb_status = readl(S3C_UDC_OTG_DSTS);
		if (usb_status & (1<<SUSPEND_STS)) 
		{
			//sending remote wake up signaling			
			DEBUG("[%s]Set Remote Wakeup \n", __func__);		
			usb_dctl = readl(S3C_UDC_OTG_DCTL);
			usb_dctl |= REMOTE_WAKEUP_SIG;
			writel(usb_dctl, S3C_UDC_OTG_DCTL);
			mdelay(1);
			
			DEBUG_SETUP("[%s]Clear Remote Wakeup \n", __func__);		
			usb_dctl = readl(S3C_UDC_OTG_DCTL);
			usb_dctl = usb_dctl & ~REMOTE_WAKEUP_SIG;
			writel(usb_dctl, S3C_UDC_OTG_DCTL);
		}
		else
			DEBUG_SETUP("[%s] Already woked up \n", __func__); 				
	}
	else if (usb_otgctl & SESSION_REQ)
	{
		DEBUG_SETUP("[%s] Session Request Already active! \n", __func__);		
		goto s3c_udc_wakeup_exit;	
	}
	else
	{
		DEBUG_SETUP("[%s] Initiate Session Request  \n", __func__);		
	//The core clears this bit when the HstNegSucStsChng bit is cleared.
		usb_otgctl |= SESSION_REQ;
		writel(usb_otgctl, S3C_UDC_OTG_GOTGCTL);
		
		/* Start the SRP timer */
		init_timer(srp_timer);
		srp_timer->function = (void*)s3c_udc_srp_timeout;
		srp_timer->expires = jiffies + (HZ*6);
		add_timer(srp_timer);
	}
	ret = 0;

s3c_udc_wakeup_exit:	
	spin_unlock_irqrestore(&dev->lock, flags);
	return ret;
}
Example #14
0
/*
 * usb_gadget_register_driver
 * Register entry point for the peripheral controller driver.
 */
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
{
	struct s3c_udc *dev = the_controller;
	int retval;

	DEBUG_SETUP("%s: %s\n", __func__, driver->driver.name);
#if 1
/*
	adb composite fail to !driver->unbind in composite.c as below
	static struct usb_gadget_driver composite_driver = {
		.speed		= USB_SPEED_HIGH,

		.bind		= composite_bind,
		.unbind		= __exit_p(composite_unbind),
*/
	if (!driver
	    || (driver->speed < USB_SPEED_FULL)
	    || !driver->bind
	    || !driver->disconnect || !driver->setup)
		return -EINVAL;		
#else	
if (!driver
	|| (driver->speed != USB_SPEED_FULL && driver->speed != USB_SPEED_HIGH)
	|| !driver->bind
	|| !driver->unbind || !driver->disconnect || !driver->setup)
	return -EINVAL;
#endif
	
	if (!dev)
		return -ENODEV;

	if (dev->driver)
		return -EBUSY;

	/* first hook up the driver ... */
	dev->devstatus = 1 << USB_DEVICE_SELF_POWERED;
	dev->driver = driver;
	dev->gadget.dev.driver = &driver->driver;
	retval = device_add(&dev->gadget.dev);

	if(retval) { /* TODO */
		DEBUG_ERROR("target device_add failed, error %d\n", retval);
		return retval;
	}
	
	retval = driver->bind(&dev->gadget);
	if (retval) {
		DEBUG_ERROR("%s: bind to driver %s --> error %d\n", dev->gadget.name,
		       driver->driver.name, retval);
		device_del(&dev->gadget.dev);

		dev->driver = 0;
		dev->gadget.dev.driver = 0;
		return retval;
	}
	enable_irq(IRQ_OTG);
	
	DEBUG_SETUP("Registered gadget driver '%s'\n", driver->driver.name);

#ifndef CONFIG_PM
	s3c_udc_enable(dev);
#endif

/* 	in case of rndis, will be chaned at the time of SET_CONFIGURATION */
	if (strcmp(driver->driver.name, "g_ether") == 0)
		dev->config_gadget_driver = ETHER_CDC;	
	
	else if (strcmp(driver->driver.name, "android_adb") == 0)
		dev->config_gadget_driver = ANDROID_ADB;
	
	else if (strcmp(driver->driver.name, "android_usb") == 0)
		dev->config_gadget_driver = ANDROID_ADB_UMS;
	
	else if (strcmp(driver->driver.name, "android_adb_ums_acm") == 0)
		dev->config_gadget_driver = ANDROID_ADB_UMS_ACM;
	
	else if (strcmp(driver->driver.name, "g_serial") == 0)
		dev->config_gadget_driver = SERIAL;
	
	else if (strcmp(driver->driver.name, "g_cdc") == 0)
		dev->config_gadget_driver = CDC2;
	
	else if (strcmp(driver->driver.name, "g_file_storage") == 0)
		dev->config_gadget_driver = FILE_STORAGE;

	else
		DEBUG_ERROR("Not recognized driver's name '%s'\n", driver->driver.name);
		
	return 0;
}