diff options
Diffstat (limited to 'meta/recipes-kernel/linux/linux-rp-2.6.24/pxa2xx_udc-clock.patch')
-rw-r--r-- | meta/recipes-kernel/linux/linux-rp-2.6.24/pxa2xx_udc-clock.patch | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-rp-2.6.24/pxa2xx_udc-clock.patch b/meta/recipes-kernel/linux/linux-rp-2.6.24/pxa2xx_udc-clock.patch new file mode 100644 index 0000000000..14c496a31a --- /dev/null +++ b/meta/recipes-kernel/linux/linux-rp-2.6.24/pxa2xx_udc-clock.patch | |||
@@ -0,0 +1,221 @@ | |||
1 | --- | ||
2 | drivers/usb/gadget/pxa2xx_udc.c | 88 ++++++++++++++++++++++------------------ | ||
3 | drivers/usb/gadget/pxa2xx_udc.h | 4 + | ||
4 | 2 files changed, 53 insertions(+), 39 deletions(-) | ||
5 | |||
6 | --- g26.orig/drivers/usb/gadget/pxa2xx_udc.c 2008-02-19 12:47:06.000000000 -0800 | ||
7 | +++ g26/drivers/usb/gadget/pxa2xx_udc.c 2008-02-19 14:07:17.000000000 -0800 | ||
8 | @@ -103,6 +103,12 @@ static const char ep0name [] = "ep0"; | ||
9 | #error "Can't configure both IXP and PXA" | ||
10 | #endif | ||
11 | |||
12 | +/* IXP doesn't yet support <linux/clk.h> */ | ||
13 | +#define clk_get(dev,name) NULL | ||
14 | +#define clk_enable(clk) do { } while (0) | ||
15 | +#define clk_disable(clk) do { } while (0) | ||
16 | +#define clk_put(clk) do { } while (0) | ||
17 | + | ||
18 | #endif | ||
19 | |||
20 | #include "pxa2xx_udc.h" | ||
21 | @@ -934,20 +940,31 @@ static void udc_disable(struct pxa2xx_ud | ||
22 | /* We disable the UDC -- and its 48 MHz clock -- whenever it's not | ||
23 | * in active use. | ||
24 | */ | ||
25 | -static int pullup(struct pxa2xx_udc *udc, int is_active) | ||
26 | +static int pullup(struct pxa2xx_udc *udc) | ||
27 | { | ||
28 | - is_active = is_active && udc->vbus && udc->pullup; | ||
29 | + int is_active = udc->vbus && udc->pullup && !udc->suspended; | ||
30 | DMSG("%s\n", is_active ? "active" : "inactive"); | ||
31 | - if (is_active) | ||
32 | - udc_enable(udc); | ||
33 | - else { | ||
34 | - if (udc->gadget.speed != USB_SPEED_UNKNOWN) { | ||
35 | - DMSG("disconnect %s\n", udc->driver | ||
36 | - ? udc->driver->driver.name | ||
37 | - : "(no driver)"); | ||
38 | - stop_activity(udc, udc->driver); | ||
39 | + if (is_active) { | ||
40 | + if (!udc->active) { | ||
41 | + udc->active = 1; | ||
42 | + /* Enable clock for USB device */ | ||
43 | + clk_enable(udc->clk); | ||
44 | + udc_enable(udc); | ||
45 | } | ||
46 | - udc_disable(udc); | ||
47 | + } else { | ||
48 | + if (udc->active) { | ||
49 | + if (udc->gadget.speed != USB_SPEED_UNKNOWN) { | ||
50 | + DMSG("disconnect %s\n", udc->driver | ||
51 | + ? udc->driver->driver.name | ||
52 | + : "(no driver)"); | ||
53 | + stop_activity(udc, udc->driver); | ||
54 | + } | ||
55 | + udc_disable(udc); | ||
56 | + /* Disable clock for USB device */ | ||
57 | + clk_disable(udc->clk); | ||
58 | + udc->active = 0; | ||
59 | + } | ||
60 | + | ||
61 | } | ||
62 | return 0; | ||
63 | } | ||
64 | @@ -958,9 +975,9 @@ static int pxa2xx_udc_vbus_session(struc | ||
65 | struct pxa2xx_udc *udc; | ||
66 | |||
67 | udc = container_of(_gadget, struct pxa2xx_udc, gadget); | ||
68 | - udc->vbus = is_active = (is_active != 0); | ||
69 | + udc->vbus = (is_active != 0); | ||
70 | DMSG("vbus %s\n", is_active ? "supplied" : "inactive"); | ||
71 | - pullup(udc, is_active); | ||
72 | + pullup(udc); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | @@ -975,9 +992,8 @@ static int pxa2xx_udc_pullup(struct usb_ | ||
77 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) | ||
78 | return -EOPNOTSUPP; | ||
79 | |||
80 | - is_active = (is_active != 0); | ||
81 | - udc->pullup = is_active; | ||
82 | - pullup(udc, is_active); | ||
83 | + udc->pullup = (is_active != 0); | ||
84 | + pullup(udc); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | @@ -1146,11 +1162,6 @@ static void udc_disable(struct pxa2xx_ud | ||
89 | |||
90 | udc_clear_mask_UDCCR(UDCCR_UDE); | ||
91 | |||
92 | -#ifdef CONFIG_ARCH_PXA | ||
93 | - /* Disable clock for USB device */ | ||
94 | - clk_disable(dev->clk); | ||
95 | -#endif | ||
96 | - | ||
97 | ep0_idle (dev); | ||
98 | dev->gadget.speed = USB_SPEED_UNKNOWN; | ||
99 | } | ||
100 | @@ -1191,11 +1202,6 @@ static void udc_enable (struct pxa2xx_ud | ||
101 | { | ||
102 | udc_clear_mask_UDCCR(UDCCR_UDE); | ||
103 | |||
104 | -#ifdef CONFIG_ARCH_PXA | ||
105 | - /* Enable clock for USB device */ | ||
106 | - clk_enable(dev->clk); | ||
107 | -#endif | ||
108 | - | ||
109 | /* try to clear these bits before we enable the udc */ | ||
110 | udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR); | ||
111 | |||
112 | @@ -1286,7 +1292,7 @@ fail: | ||
113 | * for set_configuration as well as eventual disconnect. | ||
114 | */ | ||
115 | DMSG("registered gadget driver '%s'\n", driver->driver.name); | ||
116 | - pullup(dev, 1); | ||
117 | + pullup(dev); | ||
118 | dump_state(dev); | ||
119 | return 0; | ||
120 | } | ||
121 | @@ -1329,7 +1335,8 @@ int usb_gadget_unregister_driver(struct | ||
122 | return -EINVAL; | ||
123 | |||
124 | local_irq_disable(); | ||
125 | - pullup(dev, 0); | ||
126 | + dev->pullup = 0; | ||
127 | + pullup(dev); | ||
128 | stop_activity(dev, driver); | ||
129 | local_irq_enable(); | ||
130 | |||
131 | @@ -2131,13 +2138,11 @@ static int __init pxa2xx_udc_probe(struc | ||
132 | if (irq < 0) | ||
133 | return -ENODEV; | ||
134 | |||
135 | -#ifdef CONFIG_ARCH_PXA | ||
136 | dev->clk = clk_get(&pdev->dev, "UDCCLK"); | ||
137 | if (IS_ERR(dev->clk)) { | ||
138 | retval = PTR_ERR(dev->clk); | ||
139 | goto err_clk; | ||
140 | } | ||
141 | -#endif | ||
142 | |||
143 | pr_debug("%s: IRQ %d%s%s\n", driver_name, irq, | ||
144 | dev->has_cfr ? "" : " (!cfr)", | ||
145 | @@ -2250,10 +2255,8 @@ lubbock_fail0: | ||
146 | if (dev->mach->gpio_vbus) | ||
147 | gpio_free(dev->mach->gpio_vbus); | ||
148 | err_gpio_vbus: | ||
149 | -#ifdef CONFIG_ARCH_PXA | ||
150 | clk_put(dev->clk); | ||
151 | err_clk: | ||
152 | -#endif | ||
153 | return retval; | ||
154 | } | ||
155 | |||
156 | @@ -2269,7 +2272,9 @@ static int __exit pxa2xx_udc_remove(stru | ||
157 | if (dev->driver) | ||
158 | return -EBUSY; | ||
159 | |||
160 | - udc_disable(dev); | ||
161 | + dev->pullup = 0; | ||
162 | + pullup(dev); | ||
163 | + | ||
164 | remove_proc_files(); | ||
165 | |||
166 | if (dev->got_irq) { | ||
167 | @@ -2289,9 +2294,7 @@ static int __exit pxa2xx_udc_remove(stru | ||
168 | if (dev->mach->gpio_pullup) | ||
169 | gpio_free(dev->mach->gpio_pullup); | ||
170 | |||
171 | -#ifdef CONFIG_ARCH_PXA | ||
172 | clk_put(dev->clk); | ||
173 | -#endif | ||
174 | |||
175 | platform_set_drvdata(pdev, NULL); | ||
176 | the_controller = NULL; | ||
177 | @@ -2317,10 +2320,15 @@ static int __exit pxa2xx_udc_remove(stru | ||
178 | static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state) | ||
179 | { | ||
180 | struct pxa2xx_udc *udc = platform_get_drvdata(dev); | ||
181 | + unsigned long flags; | ||
182 | |||
183 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) | ||
184 | WARN("USB host won't detect disconnect!\n"); | ||
185 | - pullup(udc, 0); | ||
186 | + udc->suspended = 1; | ||
187 | + | ||
188 | + local_irq_save(flags); | ||
189 | + pullup(udc); | ||
190 | + local_irq_restore(flags); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | @@ -2328,8 +2336,12 @@ static int pxa2xx_udc_suspend(struct pla | ||
195 | static int pxa2xx_udc_resume(struct platform_device *dev) | ||
196 | { | ||
197 | struct pxa2xx_udc *udc = platform_get_drvdata(dev); | ||
198 | + unsigned long flags; | ||
199 | |||
200 | - pullup(udc, 1); | ||
201 | + udc->suspended = 0; | ||
202 | + local_irq_save(flags); | ||
203 | + pullup(udc); | ||
204 | + local_irq_restore(flags); | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | --- g26.orig/drivers/usb/gadget/pxa2xx_udc.h 2008-02-19 12:47:06.000000000 -0800 | ||
209 | +++ g26/drivers/usb/gadget/pxa2xx_udc.h 2008-02-19 12:57:42.000000000 -0800 | ||
210 | @@ -119,7 +119,9 @@ struct pxa2xx_udc { | ||
211 | has_cfr : 1, | ||
212 | req_pending : 1, | ||
213 | req_std : 1, | ||
214 | - req_config : 1; | ||
215 | + req_config : 1, | ||
216 | + suspended : 1, | ||
217 | + active : 1; | ||
218 | |||
219 | #define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200)) | ||
220 | struct timer_list timer; | ||
221 | - | ||