diff options
| author | Dmitry Baryshkov <dbaryshkov@gmail.com> | 2008-02-22 20:17:19 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-03-04 17:57:44 -0500 |
| commit | 64cc2dd937298324c77c7d584495052547c64a6a (patch) | |
| tree | f6409ea83ad3a905fa7211256b9a9c0d4d975760 | |
| parent | 546d7eec389a3df3173b3131d92829c14e614601 (diff) | |
USB: pxa2xx_udc: fix misuse of clock enable/disable calls
Fix pxa2xx_udc to balance calls to clk_enable/clk_disable.
[db: remove inline #ifdefs for IXP non-support of <linux/clk.h> calls]
Signed-off-by: Dmitry Baryshkov dbaryshkov@gmail.com
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -rw-r--r-- | drivers/usb/gadget/pxa2xx_udc.c | 88 | ||||
| -rw-r--r-- | drivers/usb/gadget/pxa2xx_udc.h | 4 |
2 files changed, 53 insertions, 39 deletions
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 4402d6f042d9..096c41cc40d1 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c | |||
| @@ -103,6 +103,12 @@ static const char ep0name [] = "ep0"; | |||
| 103 | #error "Can't configure both IXP and PXA" | 103 | #error "Can't configure both IXP and PXA" |
| 104 | #endif | 104 | #endif |
| 105 | 105 | ||
| 106 | /* IXP doesn't yet support <linux/clk.h> */ | ||
| 107 | #define clk_get(dev,name) NULL | ||
| 108 | #define clk_enable(clk) do { } while (0) | ||
| 109 | #define clk_disable(clk) do { } while (0) | ||
| 110 | #define clk_put(clk) do { } while (0) | ||
| 111 | |||
| 106 | #endif | 112 | #endif |
| 107 | 113 | ||
| 108 | #include "pxa2xx_udc.h" | 114 | #include "pxa2xx_udc.h" |
| @@ -934,20 +940,31 @@ static void udc_disable(struct pxa2xx_udc *); | |||
| 934 | /* We disable the UDC -- and its 48 MHz clock -- whenever it's not | 940 | /* We disable the UDC -- and its 48 MHz clock -- whenever it's not |
| 935 | * in active use. | 941 | * in active use. |
| 936 | */ | 942 | */ |
| 937 | static int pullup(struct pxa2xx_udc *udc, int is_active) | 943 | static int pullup(struct pxa2xx_udc *udc) |
| 938 | { | 944 | { |
| 939 | is_active = is_active && udc->vbus && udc->pullup; | 945 | int is_active = udc->vbus && udc->pullup && !udc->suspended; |
| 940 | DMSG("%s\n", is_active ? "active" : "inactive"); | 946 | DMSG("%s\n", is_active ? "active" : "inactive"); |
| 941 | if (is_active) | 947 | if (is_active) { |
| 942 | udc_enable(udc); | 948 | if (!udc->active) { |
| 943 | else { | 949 | udc->active = 1; |
| 944 | if (udc->gadget.speed != USB_SPEED_UNKNOWN) { | 950 | /* Enable clock for USB device */ |
| 945 | DMSG("disconnect %s\n", udc->driver | 951 | clk_enable(udc->clk); |
| 946 | ? udc->driver->driver.name | 952 | udc_enable(udc); |
| 947 | : "(no driver)"); | ||
| 948 | stop_activity(udc, udc->driver); | ||
| 949 | } | 953 | } |
| 950 | udc_disable(udc); | 954 | } else { |
| 955 | if (udc->active) { | ||
| 956 | if (udc->gadget.speed != USB_SPEED_UNKNOWN) { | ||
| 957 | DMSG("disconnect %s\n", udc->driver | ||
| 958 | ? udc->driver->driver.name | ||
| 959 | : "(no driver)"); | ||
| 960 | stop_activity(udc, udc->driver); | ||
| 961 | } | ||
| 962 | udc_disable(udc); | ||
| 963 | /* Disable clock for USB device */ | ||
| 964 | clk_disable(udc->clk); | ||
| 965 | udc->active = 0; | ||
| 966 | } | ||
| 967 | |||
| 951 | } | 968 | } |
| 952 | return 0; | 969 | return 0; |
| 953 | } | 970 | } |
| @@ -958,9 +975,9 @@ static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active) | |||
| 958 | struct pxa2xx_udc *udc; | 975 | struct pxa2xx_udc *udc; |
| 959 | 976 | ||
| 960 | udc = container_of(_gadget, struct pxa2xx_udc, gadget); | 977 | udc = container_of(_gadget, struct pxa2xx_udc, gadget); |
| 961 | udc->vbus = is_active = (is_active != 0); | 978 | udc->vbus = (is_active != 0); |
| 962 | DMSG("vbus %s\n", is_active ? "supplied" : "inactive"); | 979 | DMSG("vbus %s\n", is_active ? "supplied" : "inactive"); |
| 963 | pullup(udc, is_active); | 980 | pullup(udc); |
| 964 | return 0; | 981 | return 0; |
| 965 | } | 982 | } |
| 966 | 983 | ||
| @@ -975,9 +992,8 @@ static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active) | |||
| 975 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) | 992 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) |
| 976 | return -EOPNOTSUPP; | 993 | return -EOPNOTSUPP; |
| 977 | 994 | ||
| 978 | is_active = (is_active != 0); | 995 | udc->pullup = (is_active != 0); |
| 979 | udc->pullup = is_active; | 996 | pullup(udc); |
| 980 | pullup(udc, is_active); | ||
| 981 | return 0; | 997 | return 0; |
| 982 | } | 998 | } |
| 983 | 999 | ||
| @@ -997,7 +1013,7 @@ static const struct usb_gadget_ops pxa2xx_udc_ops = { | |||
| 997 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | 1013 | #ifdef CONFIG_USB_GADGET_DEBUG_FS |
| 998 | 1014 | ||
| 999 | static int | 1015 | static int |
| 1000 | udc_seq_show(struct seq_file *m, void *d) | 1016 | udc_seq_show(struct seq_file *m, void *_d) |
| 1001 | { | 1017 | { |
| 1002 | struct pxa2xx_udc *dev = m->private; | 1018 | struct pxa2xx_udc *dev = m->private; |
| 1003 | unsigned long flags; | 1019 | unsigned long flags; |
| @@ -1146,11 +1162,6 @@ static void udc_disable(struct pxa2xx_udc *dev) | |||
| 1146 | 1162 | ||
| 1147 | udc_clear_mask_UDCCR(UDCCR_UDE); | 1163 | udc_clear_mask_UDCCR(UDCCR_UDE); |
| 1148 | 1164 | ||
| 1149 | #ifdef CONFIG_ARCH_PXA | ||
| 1150 | /* Disable clock for USB device */ | ||
| 1151 | clk_disable(dev->clk); | ||
| 1152 | #endif | ||
| 1153 | |||
| 1154 | ep0_idle (dev); | 1165 | ep0_idle (dev); |
| 1155 | dev->gadget.speed = USB_SPEED_UNKNOWN; | 1166 | dev->gadget.speed = USB_SPEED_UNKNOWN; |
| 1156 | } | 1167 | } |
| @@ -1191,11 +1202,6 @@ static void udc_enable (struct pxa2xx_udc *dev) | |||
| 1191 | { | 1202 | { |
| 1192 | udc_clear_mask_UDCCR(UDCCR_UDE); | 1203 | udc_clear_mask_UDCCR(UDCCR_UDE); |
| 1193 | 1204 | ||
| 1194 | #ifdef CONFIG_ARCH_PXA | ||
| 1195 | /* Enable clock for USB device */ | ||
| 1196 | clk_enable(dev->clk); | ||
| 1197 | #endif | ||
| 1198 | |||
| 1199 | /* try to clear these bits before we enable the udc */ | 1205 | /* try to clear these bits before we enable the udc */ |
| 1200 | udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR); | 1206 | udc_ack_int_UDCCR(UDCCR_SUSIR|/*UDCCR_RSTIR|*/UDCCR_RESIR); |
| 1201 | 1207 | ||
| @@ -1286,7 +1292,7 @@ fail: | |||
| 1286 | * for set_configuration as well as eventual disconnect. | 1292 | * for set_configuration as well as eventual disconnect. |
| 1287 | */ | 1293 | */ |
| 1288 | DMSG("registered gadget driver '%s'\n", driver->driver.name); | 1294 | DMSG("registered gadget driver '%s'\n", driver->driver.name); |
| 1289 | pullup(dev, 1); | 1295 | pullup(dev); |
| 1290 | dump_state(dev); | 1296 | dump_state(dev); |
| 1291 | return 0; | 1297 | return 0; |
| 1292 | } | 1298 | } |
| @@ -1329,7 +1335,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
| 1329 | return -EINVAL; | 1335 | return -EINVAL; |
| 1330 | 1336 | ||
| 1331 | local_irq_disable(); | 1337 | local_irq_disable(); |
| 1332 | pullup(dev, 0); | 1338 | dev->pullup = 0; |
| 1339 | pullup(dev); | ||
| 1333 | stop_activity(dev, driver); | 1340 | stop_activity(dev, driver); |
| 1334 | local_irq_enable(); | 1341 | local_irq_enable(); |
| 1335 | 1342 | ||
| @@ -2131,13 +2138,11 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) | |||
| 2131 | if (irq < 0) | 2138 | if (irq < 0) |
| 2132 | return -ENODEV; | 2139 | return -ENODEV; |
| 2133 | 2140 | ||
| 2134 | #ifdef CONFIG_ARCH_PXA | ||
| 2135 | dev->clk = clk_get(&pdev->dev, "UDCCLK"); | 2141 | dev->clk = clk_get(&pdev->dev, "UDCCLK"); |
| 2136 | if (IS_ERR(dev->clk)) { | 2142 | if (IS_ERR(dev->clk)) { |
| 2137 | retval = PTR_ERR(dev->clk); | 2143 | retval = PTR_ERR(dev->clk); |
| 2138 | goto err_clk; | 2144 | goto err_clk; |
| 2139 | } | 2145 | } |
| 2140 | #endif | ||
| 2141 | 2146 | ||
| 2142 | pr_debug("%s: IRQ %d%s%s\n", driver_name, irq, | 2147 | pr_debug("%s: IRQ %d%s%s\n", driver_name, irq, |
| 2143 | dev->has_cfr ? "" : " (!cfr)", | 2148 | dev->has_cfr ? "" : " (!cfr)", |
| @@ -2250,10 +2255,8 @@ lubbock_fail0: | |||
| 2250 | if (dev->mach->gpio_vbus) | 2255 | if (dev->mach->gpio_vbus) |
| 2251 | gpio_free(dev->mach->gpio_vbus); | 2256 | gpio_free(dev->mach->gpio_vbus); |
| 2252 | err_gpio_vbus: | 2257 | err_gpio_vbus: |
| 2253 | #ifdef CONFIG_ARCH_PXA | ||
| 2254 | clk_put(dev->clk); | 2258 | clk_put(dev->clk); |
| 2255 | err_clk: | 2259 | err_clk: |
| 2256 | #endif | ||
| 2257 | return retval; | 2260 | return retval; |
| 2258 | } | 2261 | } |
| 2259 | 2262 | ||
| @@ -2269,7 +2272,9 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) | |||
| 2269 | if (dev->driver) | 2272 | if (dev->driver) |
| 2270 | return -EBUSY; | 2273 | return -EBUSY; |
| 2271 | 2274 | ||
| 2272 | udc_disable(dev); | 2275 | dev->pullup = 0; |
| 2276 | pullup(dev); | ||
| 2277 | |||
| 2273 | remove_debug_files(dev); | 2278 | remove_debug_files(dev); |
| 2274 | 2279 | ||
| 2275 | if (dev->got_irq) { | 2280 | if (dev->got_irq) { |
| @@ -2289,9 +2294,7 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) | |||
| 2289 | if (dev->mach->gpio_pullup) | 2294 | if (dev->mach->gpio_pullup) |
| 2290 | gpio_free(dev->mach->gpio_pullup); | 2295 | gpio_free(dev->mach->gpio_pullup); |
| 2291 | 2296 | ||
| 2292 | #ifdef CONFIG_ARCH_PXA | ||
| 2293 | clk_put(dev->clk); | 2297 | clk_put(dev->clk); |
| 2294 | #endif | ||
| 2295 | 2298 | ||
| 2296 | platform_set_drvdata(pdev, NULL); | 2299 | platform_set_drvdata(pdev, NULL); |
| 2297 | the_controller = NULL; | 2300 | the_controller = NULL; |
| @@ -2317,10 +2320,15 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) | |||
| 2317 | static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state) | 2320 | static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state) |
| 2318 | { | 2321 | { |
| 2319 | struct pxa2xx_udc *udc = platform_get_drvdata(dev); | 2322 | struct pxa2xx_udc *udc = platform_get_drvdata(dev); |
| 2323 | unsigned long flags; | ||
| 2320 | 2324 | ||
| 2321 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) | 2325 | if (!udc->mach->gpio_pullup && !udc->mach->udc_command) |
| 2322 | WARN("USB host won't detect disconnect!\n"); | 2326 | WARN("USB host won't detect disconnect!\n"); |
| 2323 | pullup(udc, 0); | 2327 | udc->suspended = 1; |
| 2328 | |||
| 2329 | local_irq_save(flags); | ||
| 2330 | pullup(udc); | ||
| 2331 | local_irq_restore(flags); | ||
| 2324 | 2332 | ||
| 2325 | return 0; | 2333 | return 0; |
| 2326 | } | 2334 | } |
| @@ -2328,8 +2336,12 @@ static int pxa2xx_udc_suspend(struct platform_device *dev, pm_message_t state) | |||
| 2328 | static int pxa2xx_udc_resume(struct platform_device *dev) | 2336 | static int pxa2xx_udc_resume(struct platform_device *dev) |
| 2329 | { | 2337 | { |
| 2330 | struct pxa2xx_udc *udc = platform_get_drvdata(dev); | 2338 | struct pxa2xx_udc *udc = platform_get_drvdata(dev); |
| 2339 | unsigned long flags; | ||
| 2331 | 2340 | ||
| 2332 | pullup(udc, 1); | 2341 | udc->suspended = 0; |
| 2342 | local_irq_save(flags); | ||
| 2343 | pullup(udc); | ||
| 2344 | local_irq_restore(flags); | ||
| 2333 | 2345 | ||
| 2334 | return 0; | 2346 | return 0; |
| 2335 | } | 2347 | } |
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h index b67e3ff5e4eb..e2c19e88c875 100644 --- a/drivers/usb/gadget/pxa2xx_udc.h +++ b/drivers/usb/gadget/pxa2xx_udc.h | |||
| @@ -119,7 +119,9 @@ struct pxa2xx_udc { | |||
| 119 | has_cfr : 1, | 119 | has_cfr : 1, |
| 120 | req_pending : 1, | 120 | req_pending : 1, |
| 121 | req_std : 1, | 121 | req_std : 1, |
| 122 | req_config : 1; | 122 | req_config : 1, |
| 123 | suspended : 1, | ||
| 124 | active : 1; | ||
| 123 | 125 | ||
| 124 | #define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200)) | 126 | #define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200)) |
| 125 | struct timer_list timer; | 127 | struct timer_list timer; |
