update to 2.6.30-rc7
[openwrt.git] / target / linux / s3c24xx / patches-2.6.30 / 100-udc-poll-vbus.patch
1 --- a/drivers/usb/gadget/s3c2410_udc.c
2 +++ b/drivers/usb/gadget/s3c2410_udc.c
3 @@ -74,6 +74,7 @@ static void __iomem           *base_addr;
4  static u64                     rsrc_start;
5  static u64                     rsrc_len;
6  static struct dentry           *s3c2410_udc_debugfs_root;
7 +static struct timer_list       vbus_poll_timer;
8  
9  static inline u32 udc_read(u32 reg)
10  {
11 @@ -134,6 +135,8 @@ static int dprintk(int level, const char
12         return 0;
13  }
14  #endif
15 +
16 +#ifdef CONFIG_USB_GADGET_DEBUG_FS
17  static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
18  {
19         u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;
20 @@ -197,6 +200,7 @@ static const struct file_operations s3c2
21         .release        = single_release,
22         .owner          = THIS_MODULE,
23  };
24 +#endif
25  
26  /* io macros */
27  
28 @@ -843,6 +847,7 @@ static void s3c2410_udc_handle_ep(struct
29         u32                     ep_csr1;
30         u32                     idx;
31  
32 +handle_ep_again:
33         if (likely (!list_empty(&ep->queue)))
34                 req = list_entry(ep->queue.next,
35                                 struct s3c2410_request, queue);
36 @@ -882,6 +887,8 @@ static void s3c2410_udc_handle_ep(struct
37  
38                 if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
39                         s3c2410_udc_read_fifo(ep,req);
40 +                       if (s3c2410_udc_fifo_count_out())
41 +                               goto handle_ep_again;
42                 }
43         }
44  }
45 @@ -1520,6 +1527,20 @@ static irqreturn_t s3c2410_udc_vbus_irq(
46         return IRQ_HANDLED;
47  }
48  
49 +static void s3c2410_udc_vbus_poll(unsigned long _data)
50 +{
51 +       struct s3c2410_udc      *data = (struct s3c2410_udc *)_data;
52 +       int                     v;
53 +
54 +       dprintk(DEBUG_NORMAL, "%s()\n", __func__);
55 +       if (udc_info && udc_info->get_vbus_status) {
56 +               v = udc_info->get_vbus_status();
57 +               if ((v > -1) && (v != data->vbus))
58 +                       s3c2410_udc_vbus_session(&data->gadget, v);
59 +               mod_timer(&vbus_poll_timer, jiffies + msecs_to_jiffies(900));
60 +       }
61 +}
62 +
63  static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
64  {
65         dprintk(DEBUG_NORMAL, "%s()\n", __func__);
66 @@ -1677,6 +1698,11 @@ int usb_gadget_register_driver(struct us
67                 goto register_error;
68         }
69  
70 +       if (udc_info && udc_info->get_vbus_status && !udc_info->vbus_pin) {
71 +               mod_timer(&vbus_poll_timer, jiffies + msecs_to_jiffies(50));
72 +               return 0; /* just return, vbus change will enable udc */
73 +       }
74 +
75         /* Enable udc */
76         s3c2410_udc_enable(udc);
77  
78 @@ -1707,6 +1733,7 @@ int usb_gadget_unregister_driver(struct 
79         if (driver->disconnect)
80                 driver->disconnect(&udc->gadget);
81  
82 +       driver->unbind(&udc->gadget);
83         device_del(&udc->gadget.dev);
84         udc->driver = NULL;
85  
86 @@ -1893,10 +1920,16 @@ static int s3c2410_udc_probe(struct plat
87                 }
88  
89                 dev_dbg(dev, "got irq %i\n", irq);
90 +       } else if (udc_info && udc_info->get_vbus_status) {
91 +               udc->vbus = 0;
92 +               init_timer(&vbus_poll_timer);
93 +               vbus_poll_timer.function = s3c2410_udc_vbus_poll;
94 +               vbus_poll_timer.data = (unsigned long) udc;
95         } else {
96                 udc->vbus = 1;
97         }
98  
99 +#ifdef CONFIG_USB_GADGET_DEBUG_FS
100         if (s3c2410_udc_debugfs_root) {
101                 udc->regs_info = debugfs_create_file("registers", S_IRUGO,
102                                 s3c2410_udc_debugfs_root,
103 @@ -1904,6 +1937,7 @@ static int s3c2410_udc_probe(struct plat
104                 if (!udc->regs_info)
105                         dev_warn(dev, "debugfs file creation failed\n");
106         }
107 +#endif
108  
109         dev_dbg(dev, "probe ok\n");
110  
111 @@ -1939,6 +1973,8 @@ static int s3c2410_udc_remove(struct pla
112         if (udc_info && udc_info->vbus_pin > 0) {
113                 irq = gpio_to_irq(udc_info->vbus_pin);
114                 free_irq(irq, udc);
115 +       } else if (udc_info && udc_info->get_vbus_status) {
116 +               del_timer_sync(&vbus_poll_timer);
117         }
118  
119         free_irq(IRQ_USBD, udc);
120 @@ -2013,12 +2049,14 @@ static int __init udc_init(void)
121  
122         dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
123  
124 +#ifdef CONFIG_USB_GADGET_DEBUG_FS
125         s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
126         if (IS_ERR(s3c2410_udc_debugfs_root)) {
127                 printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",
128                         gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
129                 s3c2410_udc_debugfs_root = NULL;
130         }
131 +#endif
132  
133         retval = platform_driver_register(&udc_driver_2410);
134         if (retval)
135 --- a/drivers/usb/host/ohci-s3c2410.c
136 +++ b/drivers/usb/host/ohci-s3c2410.c
137 @@ -21,6 +21,8 @@
138  
139  #include <linux/platform_device.h>
140  #include <linux/clk.h>
141 +#include <mach/hardware.h>
142 +#include <mach/regs-gpio.h>
143  #include <plat/usb-control.h>
144  
145  #define valid_port(idx) ((idx) == 1 || (idx) == 2)
146 @@ -306,6 +308,42 @@ static void s3c2410_hcd_oc(struct s3c241
147         local_irq_restore(flags);
148  }
149  
150 +/* switching of USB pads */
151 +static ssize_t show_usb_mode(struct device *dev, struct device_attribute *attr,
152 +                            char *buf)
153 +{
154 +       if (__raw_readl(S3C24XX_MISCCR) & S3C2410_MISCCR_USBHOST)
155 +               return sprintf(buf, "host\n");
156 +
157 +       return sprintf(buf, "device\n");
158 +}
159 +
160 +static ssize_t set_usb_mode(struct device *dev, struct device_attribute *attr,
161 +                           const char *buf, size_t count)
162 +{
163 +       if (!strncmp(buf, "host", 4)) {
164 +               printk(KERN_WARNING "s3c2410: changing usb to host\n");
165 +               s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
166 +                                     S3C2410_MISCCR_USBHOST);
167 +               /* FIXME:
168 +                * - call machine-specific disable-pullup function i
169 +                * - enable +Vbus (if hardware supports it)
170 +                */
171 +               s3c2410_gpio_setpin(S3C2410_GPB9, 0);
172 +       } else if (!strncmp(buf, "device", 6)) {
173 +               printk(KERN_WARNING "s3c2410: changing usb to device\n");
174 +               s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, 0);
175 +               s3c2410_gpio_setpin(S3C2410_GPB9, 1);
176 +       } else {
177 +               printk(KERN_WARNING "s3c2410: unknown mode\n");
178 +               return -EINVAL;
179 +       }
180 +
181 +       return count;
182 +}
183 +
184 +static DEVICE_ATTR(usb_mode, S_IRUGO | S_IWUSR, show_usb_mode, set_usb_mode);
185 +
186  /* may be called without controller electrically present */
187  /* may be called with controller, bus, and devices active */
188  
189 @@ -486,15 +524,23 @@ static int ohci_hcd_s3c2410_drv_remove(s
190         return 0;
191  }
192  
193 +static int ohci_hcd_s3c2410_drv_resume(struct platform_device *pdev)
194 +{
195 +       struct usb_hcd *hcd = platform_get_drvdata(pdev);
196 +
197 +       ohci_finish_controller_resume(hcd);
198 +       return 0;
199 +}
200 +
201  static struct platform_driver ohci_hcd_s3c2410_driver = {
202         .probe          = ohci_hcd_s3c2410_drv_probe,
203         .remove         = ohci_hcd_s3c2410_drv_remove,
204         .shutdown       = usb_hcd_platform_shutdown,
205         /*.suspend      = ohci_hcd_s3c2410_drv_suspend, */
206 -       /*.resume       = ohci_hcd_s3c2410_drv_resume, */
207 +       .resume         = ohci_hcd_s3c2410_drv_resume,
208         .driver         = {
209                 .owner  = THIS_MODULE,
210 -               .name   = "s3c2410-ohci",
211 +               .name   = "s3c-ohci",
212         },
213  };
214  
215 --- a/arch/arm/plat-s3c24xx/include/plat/udc.h
216 +++ b/arch/arm/plat-s3c24xx/include/plat/udc.h
217 @@ -27,6 +27,7 @@ enum s3c2410_udc_cmd_e {
218  struct s3c2410_udc_mach_info {
219         void    (*udc_command)(enum s3c2410_udc_cmd_e);
220         void    (*vbus_draw)(unsigned int ma);
221 +       int     (*get_vbus_status)(void);
222         unsigned int vbus_pin;
223         unsigned char vbus_pin_inverted;
224  };