/* 
 * 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;
}
Esempio n. 2
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;
}
Esempio n. 3
0
/*
  Register entry point for the peripheral controller driver.
*/
int usb_gadget_register_driver(struct usb_gadget_driver* driver)
{
	struct elfin_udc *dev = the_controller;
	int retval;

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

	if (!driver
	    || driver->speed != USB_SPEED_FULL
	    || !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;

	device_add(&dev->gadget.dev);
	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;
	}

	reconfig_usbd();
	enable_irq(IRQ_USBD);

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

	GPIO_ENABLE;

/* TODO: callback for checking usb connection */
#ifdef CONFIG_MACH_TOMTOMGO
/* Here we should wait until the usb gadget device is completely enumerated if we want debugging support.... */
	if (IO_GetInput(USB_HOST_DETECT)) {
		usb_enum_completion = kmalloc(sizeof(struct completion), GFP_KERNEL);
		init_completion(usb_enum_completion);
		wait_for_completion(usb_enum_completion);		
	}
#endif

	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;
	}
Esempio n. 5
0
static void
udc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs)
{
  	__u8 saveIdx = UD_INDEX;
    	__u8 usb_status = UD_USBINT;
  	__u8 usbd_status = UD_INT;
	static int sb_debug_cnt = 1;	

	LOG("usb_status = 0x%02x, usbd_status = 0x%02x\n",
			usb_status, usbd_status);

	if ( usb_status & UD_USBINT_RESET ) {

	    LOG("\n[%d]RESET interrupt\n",sb_debug_cnt++);
	    if( usbctl_next_state_on_event(kEvReset) != kError ) {
		LOG("%s Resetting\n",pszMe);

		ep0_reset();
		ep1_reset();/* output */
		ep2_reset();/* input */

	    }

	   // reset_usbd();
	    reconfig_usbd();
	    UD_USBINT = UD_USBINT_RESET; //RESET_INT should be cleared after reconfig_usbd().- by samsung src
	    ep0_state = EP0_STATE_IDLE;

	}


	/* RESume Interrupt Request */
	if ( usb_status & UD_USBINT_RESUM ) {
 		LOG("[%d]RESUME interrupt\n", sb_debug_cnt++);
		UD_USBINT = UD_USBINT_RESUM;/* clear */
		usbctl_next_state_on_event( kEvResume );

	}


	/* SUSpend Interrupt Request */
	if ( usb_status & UD_USBINT_SUSPND ) { 
		LOG("[%d]SUSPEND interrupt\n", sb_debug_cnt++);
		UD_USBINT = UD_USBINT_SUSPND; /* clear */
		usbctl_next_state_on_event( kEvSuspend );

	}

	if ( usbd_status & UD_INT_EP0 ) {
		LOG("\n[%d]EP0 interrupt\n",sb_debug_cnt++);
		UD_INT = UD_INT_EP0; /* clear */
		ep0_int_hndlr();

	}

         /* output */
	if ( usbd_status & UD_INT_EP1 ) { 
		LOG("[%d]EP1 interrupt\n", sb_debug_cnt++);
		UD_INT = UD_INT_EP1;/* clear */
		ep1_int_hndlr(usbd_status);

	}
        /* input */
	if ( usbd_status & UD_INT_EP2 ) {
		LOG("[%d]EP2 interrupt\n", sb_debug_cnt++); 
		UD_INT = UD_INT_EP2; /* clear */
		ep2_int_hndlr(usbd_status);
		
	}

	if(usbd_status & UD_INT_EP3) UD_INT = UD_INT_EP3;
	if(usbd_status & UD_INT_EP4) UD_INT = UD_INT_EP4;
	
  	Clear_pending(INT_USBD);
	UD_INDEX= saveIdx;
	
}