diff options
author | lars <lars@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-09-21 18:29:46 +0000 |
---|---|---|
committer | lars <lars@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-09-21 18:29:46 +0000 |
commit | e2813918b96b7e6d5f5a37811e507246e604747f (patch) | |
tree | c656b15f93b7b083730061833ec95619662ce47a /target/linux/s3c24xx/patches-2.6.31/100-udc-poll-vbus.patch | |
parent | dac1d868d3131c0a9b579ccc07833faa208d2d08 (diff) |
[s3c24xx] Add 2.6.31 patches
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@17665 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.31/100-udc-poll-vbus.patch')
-rw-r--r-- | target/linux/s3c24xx/patches-2.6.31/100-udc-poll-vbus.patch | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.31/100-udc-poll-vbus.patch b/target/linux/s3c24xx/patches-2.6.31/100-udc-poll-vbus.patch new file mode 100644 index 000000000..7b2b9b25a --- /dev/null +++ b/target/linux/s3c24xx/patches-2.6.31/100-udc-poll-vbus.patch @@ -0,0 +1,244 @@ +From 6d17298d12f873a9b03e5e79ab745fda75bd5b4e Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen <lars@metafoo.de> +Date: Tue, 21 Jul 2009 12:51:33 +0200 +Subject: [PATCH] 100-udc-poll-vbus.patch + +--- + arch/arm/plat-s3c24xx/include/plat/udc.h | 1 + + drivers/usb/gadget/s3c2410_udc.c | 38 ++++++++++++++++++++++ + drivers/usb/host/ohci-s3c2410.c | 50 ++++++++++++++++++++++++++++- + 3 files changed, 87 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/plat-s3c24xx/include/plat/udc.h b/arch/arm/plat-s3c24xx/include/plat/udc.h +index 546bb40..763aeba 100644 +--- 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; + }; +diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c +index a9b452f..1c7e5d7 100644 +--- a/drivers/usb/gadget/s3c2410_udc.c ++++ b/drivers/usb/gadget/s3c2410_udc.c +@@ -73,6 +73,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) + { +@@ -133,6 +134,8 @@ static int dprintk(int level, const char *fmt, ...) + 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; +@@ -196,6 +199,7 @@ static const struct file_operations s3c2410_udc_debugfs_fops = { + .release = single_release, + .owner = THIS_MODULE, + }; ++#endif + + /* io macros */ + +@@ -842,6 +846,7 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep) + u32 ep_csr1; + u32 idx; + ++handle_ep_again: + if (likely (!list_empty(&ep->queue))) + req = list_entry(ep->queue.next, + struct s3c2410_request, queue); +@@ -881,6 +886,8 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep) + + if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) { + s3c2410_udc_read_fifo(ep,req); ++ if (s3c2410_udc_fifo_count_out()) ++ goto handle_ep_again; + } + } + } +@@ -1519,6 +1526,20 @@ static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev) + 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__); +@@ -1676,6 +1697,11 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) + 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); + +@@ -1706,6 +1732,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) + if (driver->disconnect) + driver->disconnect(&udc->gadget); + ++ driver->unbind(&udc->gadget); + device_del(&udc->gadget.dev); + udc->driver = NULL; + +@@ -1892,10 +1919,16 @@ static int s3c2410_udc_probe(struct platform_device *pdev) + } + + 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, +@@ -1903,6 +1936,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) + if (!udc->regs_info) + dev_warn(dev, "debugfs file creation failed\n"); + } ++#endif + + dev_dbg(dev, "probe ok\n"); + +@@ -1938,6 +1972,8 @@ static int s3c2410_udc_remove(struct platform_device *pdev) + 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); +@@ -2012,12 +2048,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) +diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c +index a68af2d..3b85d41 100644 +--- 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/gpio-fns.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 s3c2410_hcd_info *info, int port_oc) + 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_GPB(9), 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_GPB(9), 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(struct platform_device *pdev) + 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", + }, + }; + +-- +1.5.6.5 + |