--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -74,6 +74,7 @@ static void __iomem		*base_addr;
 static u64			rsrc_start;
 static u64			rsrc_len;
 static struct dentry		*s3c2410_udc_debugfs_root;
+static struct timer_list	vbus_poll_timer;
 
 static inline u32 udc_read(u32 reg)
 {
@@ -134,6 +135,8 @@ static int dprintk(int level, const char
 	return 0;
 }
 #endif
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
 static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
 {
 	u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;
@@ -197,6 +200,7 @@ static const struct file_operations s3c2
 	.release	= single_release,
 	.owner		= THIS_MODULE,
 };
+#endif
 
 /* io macros */
 
@@ -843,6 +847,7 @@ static void s3c2410_udc_handle_ep(struct
 	u32			ep_csr1;
 	u32			idx;
 
+handle_ep_again:
 	if (likely (!list_empty(&ep->queue)))
 		req = list_entry(ep->queue.next,
 				struct s3c2410_request, queue);
@@ -882,6 +887,8 @@ static void s3c2410_udc_handle_ep(struct
 
 		if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
 			s3c2410_udc_read_fifo(ep,req);
+			if (s3c2410_udc_fifo_count_out())
+				goto handle_ep_again;
 		}
 	}
 }
@@ -1520,6 +1527,20 @@ static irqreturn_t s3c2410_udc_vbus_irq(
 	return IRQ_HANDLED;
 }
 
+static void s3c2410_udc_vbus_poll(unsigned long _data)
+{
+	struct s3c2410_udc	*data = (struct s3c2410_udc *)_data;
+	int			v;
+
+	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+	if (udc_info && udc_info->get_vbus_status) {
+		v = udc_info->get_vbus_status();
+		if ((v > -1) && (v != data->vbus))
+			s3c2410_udc_vbus_session(&data->gadget, v);
+		mod_timer(&vbus_poll_timer, jiffies + msecs_to_jiffies(900));
+	}
+}
+
 static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
 {
 	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
@@ -1677,6 +1698,11 @@ int usb_gadget_register_driver(struct us
 		goto register_error;
 	}
 
+	if (udc_info && udc_info->get_vbus_status && !udc_info->vbus_pin) {
+		mod_timer(&vbus_poll_timer, jiffies + msecs_to_jiffies(50));
+		return 0; /* just return, vbus change will enable udc */
+	}
+
 	/* Enable udc */
 	s3c2410_udc_enable(udc);
 
@@ -1707,6 +1733,7 @@ int usb_gadget_unregister_driver(struct 
 	if (driver->disconnect)
 		driver->disconnect(&udc->gadget);
 
+	driver->unbind(&udc->gadget);
 	device_del(&udc->gadget.dev);
 	udc->driver = NULL;
 
@@ -1893,10 +1920,16 @@ static int s3c2410_udc_probe(struct plat
 		}
 
 		dev_dbg(dev, "got irq %i\n", irq);
+	} else if (udc_info && udc_info->get_vbus_status) {
+		udc->vbus = 0;
+		init_timer(&vbus_poll_timer);
+		vbus_poll_timer.function = s3c2410_udc_vbus_poll;
+		vbus_poll_timer.data = (unsigned long) udc;
 	} else {
 		udc->vbus = 1;
 	}
 
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
 	if (s3c2410_udc_debugfs_root) {
 		udc->regs_info = debugfs_create_file("registers", S_IRUGO,
 				s3c2410_udc_debugfs_root,
@@ -1904,6 +1937,7 @@ static int s3c2410_udc_probe(struct plat
 		if (!udc->regs_info)
 			dev_warn(dev, "debugfs file creation failed\n");
 	}
+#endif
 
 	dev_dbg(dev, "probe ok\n");
 
@@ -1939,6 +1973,8 @@ static int s3c2410_udc_remove(struct pla
 	if (udc_info && udc_info->vbus_pin > 0) {
 		irq = gpio_to_irq(udc_info->vbus_pin);
 		free_irq(irq, udc);
+	} else if (udc_info && udc_info->get_vbus_status) {
+		del_timer_sync(&vbus_poll_timer);
 	}
 
 	free_irq(IRQ_USBD, udc);
@@ -2013,12 +2049,14 @@ static int __init udc_init(void)
 
 	dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
 
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
 	s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
 	if (IS_ERR(s3c2410_udc_debugfs_root)) {
 		printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",
 			gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
 		s3c2410_udc_debugfs_root = NULL;
 	}
+#endif
 
 	retval = platform_driver_register(&udc_driver_2410);
 	if (retval)
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -21,6 +21,8 @@
 
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <mach/hardware.h>
+#include <mach/regs-gpio.h>
 #include <plat/usb-control.h>
 
 #define valid_port(idx) ((idx) == 1 || (idx) == 2)
@@ -306,6 +308,42 @@ static void s3c2410_hcd_oc(struct s3c241
 	local_irq_restore(flags);
 }
 
+/* switching of USB pads */
+static ssize_t show_usb_mode(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	if (__raw_readl(S3C24XX_MISCCR) & S3C2410_MISCCR_USBHOST)
+		return sprintf(buf, "host\n");
+
+	return sprintf(buf, "device\n");
+}
+
+static ssize_t set_usb_mode(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	if (!strncmp(buf, "host", 4)) {
+		printk(KERN_WARNING "s3c2410: changing usb to host\n");
+		s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
+				      S3C2410_MISCCR_USBHOST);
+		/* FIXME:
+		 * - call machine-specific disable-pullup function i
+		 * - enable +Vbus (if hardware supports it)
+		 */
+		s3c2410_gpio_setpin(S3C2410_GPB9, 0);
+	} else if (!strncmp(buf, "device", 6)) {
+		printk(KERN_WARNING "s3c2410: changing usb to device\n");
+		s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, 0);
+		s3c2410_gpio_setpin(S3C2410_GPB9, 1);
+	} else {
+		printk(KERN_WARNING "s3c2410: unknown mode\n");
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(usb_mode, S_IRUGO | S_IWUSR, show_usb_mode, set_usb_mode);
+
 /* may be called without controller electrically present */
 /* may be called with controller, bus, and devices active */
 
@@ -486,15 +524,23 @@ static int ohci_hcd_s3c2410_drv_remove(s
 	return 0;
 }
 
+static int ohci_hcd_s3c2410_drv_resume(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	ohci_finish_controller_resume(hcd);
+	return 0;
+}
+
 static struct platform_driver ohci_hcd_s3c2410_driver = {
 	.probe		= ohci_hcd_s3c2410_drv_probe,
 	.remove		= ohci_hcd_s3c2410_drv_remove,
 	.shutdown	= usb_hcd_platform_shutdown,
 	/*.suspend	= ohci_hcd_s3c2410_drv_suspend, */
-	/*.resume	= ohci_hcd_s3c2410_drv_resume, */
+	.resume		= ohci_hcd_s3c2410_drv_resume,
 	.driver		= {
 		.owner	= THIS_MODULE,
-		.name	= "s3c2410-ohci",
+		.name	= "s3c-ohci",
 	},
 };
 
--- a/arch/arm/plat-s3c24xx/include/plat/udc.h
+++ b/arch/arm/plat-s3c24xx/include/plat/udc.h
@@ -27,6 +27,7 @@ enum s3c2410_udc_cmd_e {
 struct s3c2410_udc_mach_info {
 	void	(*udc_command)(enum s3c2410_udc_cmd_e);
  	void	(*vbus_draw)(unsigned int ma);
+	int	(*get_vbus_status)(void);
 	unsigned int vbus_pin;
 	unsigned char vbus_pin_inverted;
 };