diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2011-06-23 08:26:15 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-07-01 17:31:13 -0400 |
commit | 352c2dc8b07491bbab77ddf86c20c16a97326ee7 (patch) | |
tree | a1aaa9ab0b95701e4f8aba194bfbbb42df81b572 | |
parent | b5738413c96126e8191bc506b403cd55950b8f9a (diff) |
usb: gadget: udc-core: add "new-style" registration interface
udc_start() should only trigger the internal state machine and make
minimal house keeping. Before that call udc-core calls the bind()
callback and after the callback the pullup().
udc_stop() is simillar, udc-core calls pullup(), unbind() and finally
udc_stop().
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/gadget/udc-core.c | 75 | ||||
-rw-r--r-- | include/linux/usb/gadget.h | 6 |
2 files changed, 77 insertions, 4 deletions
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 83e9e5f99b4a..2ddb7c8b5b3d 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c | |||
@@ -73,6 +73,26 @@ static inline int usb_gadget_start(struct usb_gadget *gadget, | |||
73 | } | 73 | } |
74 | 74 | ||
75 | /** | 75 | /** |
76 | * usb_gadget_udc_start - tells usb device controller to start up | ||
77 | * @gadget: The gadget we want to get started | ||
78 | * @driver: The driver we want to bind to @gadget | ||
79 | * | ||
80 | * This call is issued by the UDC Class driver when it's about | ||
81 | * to register a gadget driver to the device controller, before | ||
82 | * calling gadget driver's bind() method. | ||
83 | * | ||
84 | * It allows the controller to be powered off until strictly | ||
85 | * necessary to have it powered on. | ||
86 | * | ||
87 | * Returns zero on success, else negative errno. | ||
88 | */ | ||
89 | static inline int usb_gadget_udc_start(struct usb_gadget *gadget, | ||
90 | struct usb_gadget_driver *driver) | ||
91 | { | ||
92 | return gadget->ops->udc_start(gadget, driver); | ||
93 | } | ||
94 | |||
95 | /** | ||
76 | * usb_gadget_stop - tells usb device controller we don't need it anymore | 96 | * usb_gadget_stop - tells usb device controller we don't need it anymore |
77 | * @gadget: The device we want to stop activity | 97 | * @gadget: The device we want to stop activity |
78 | * @driver: The driver to unbind from @gadget | 98 | * @driver: The driver to unbind from @gadget |
@@ -91,6 +111,24 @@ static inline void usb_gadget_stop(struct usb_gadget *gadget, | |||
91 | } | 111 | } |
92 | 112 | ||
93 | /** | 113 | /** |
114 | * usb_gadget_udc_stop - tells usb device controller we don't need it anymore | ||
115 | * @gadget: The device we want to stop activity | ||
116 | * @driver: The driver to unbind from @gadget | ||
117 | * | ||
118 | * This call is issued by the UDC Class driver after calling | ||
119 | * gadget driver's unbind() method. | ||
120 | * | ||
121 | * The details are implementation specific, but it can go as | ||
122 | * far as powering off UDC completely and disable its data | ||
123 | * line pullups. | ||
124 | */ | ||
125 | static inline void usb_gadget_udc_stop(struct usb_gadget *gadget, | ||
126 | struct usb_gadget_driver *driver) | ||
127 | { | ||
128 | gadget->ops->udc_stop(gadget, driver); | ||
129 | } | ||
130 | |||
131 | /** | ||
94 | * usb_udc_release - release the usb_udc struct | 132 | * usb_udc_release - release the usb_udc struct |
95 | * @dev: the dev member within usb_udc | 133 | * @dev: the dev member within usb_udc |
96 | * | 134 | * |
@@ -155,6 +193,14 @@ err1: | |||
155 | } | 193 | } |
156 | EXPORT_SYMBOL_GPL(usb_add_gadget_udc); | 194 | EXPORT_SYMBOL_GPL(usb_add_gadget_udc); |
157 | 195 | ||
196 | static int udc_is_newstyle(struct usb_udc *udc) | ||
197 | { | ||
198 | if (udc->gadget->ops->udc_start && udc->gadget->ops->udc_stop) | ||
199 | return 1; | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | |||
158 | static void usb_gadget_remove_driver(struct usb_udc *udc) | 204 | static void usb_gadget_remove_driver(struct usb_udc *udc) |
159 | { | 205 | { |
160 | dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n", | 206 | dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n", |
@@ -162,7 +208,14 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) | |||
162 | 208 | ||
163 | kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); | 209 | kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); |
164 | 210 | ||
165 | usb_gadget_stop(udc->gadget, udc->driver); | 211 | if (udc_is_newstyle(udc)) { |
212 | usb_gadget_disconnect(udc->gadget); | ||
213 | udc->driver->unbind(udc->gadget); | ||
214 | usb_gadget_udc_stop(udc->gadget, udc->driver); | ||
215 | |||
216 | } else { | ||
217 | usb_gadget_stop(udc->gadget, udc->driver); | ||
218 | } | ||
166 | 219 | ||
167 | udc->driver = NULL; | 220 | udc->driver = NULL; |
168 | udc->dev.driver = NULL; | 221 | udc->dev.driver = NULL; |
@@ -232,9 +285,23 @@ found: | |||
232 | udc->driver = driver; | 285 | udc->driver = driver; |
233 | udc->dev.driver = &driver->driver; | 286 | udc->dev.driver = &driver->driver; |
234 | 287 | ||
235 | ret = usb_gadget_start(udc->gadget, driver, bind); | 288 | if (udc_is_newstyle(udc)) { |
236 | if (ret) | 289 | ret = bind(udc->gadget); |
237 | goto err1; | 290 | if (ret) |
291 | goto err1; | ||
292 | ret = usb_gadget_udc_start(udc->gadget, driver); | ||
293 | if (ret) { | ||
294 | driver->unbind(udc->gadget); | ||
295 | goto err1; | ||
296 | } | ||
297 | usb_gadget_connect(udc->gadget); | ||
298 | } else { | ||
299 | |||
300 | ret = usb_gadget_start(udc->gadget, driver, bind); | ||
301 | if (ret) | ||
302 | goto err1; | ||
303 | |||
304 | } | ||
238 | 305 | ||
239 | kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); | 306 | kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); |
240 | mutex_unlock(&udc_lock); | 307 | mutex_unlock(&udc_lock); |
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index afb67d997f0c..087f4b931833 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h | |||
@@ -459,6 +459,12 @@ struct usb_gadget_ops { | |||
459 | int (*ioctl)(struct usb_gadget *, | 459 | int (*ioctl)(struct usb_gadget *, |
460 | unsigned code, unsigned long param); | 460 | unsigned code, unsigned long param); |
461 | void (*get_config_params)(struct usb_dcd_config_params *); | 461 | void (*get_config_params)(struct usb_dcd_config_params *); |
462 | int (*udc_start)(struct usb_gadget *, | ||
463 | struct usb_gadget_driver *); | ||
464 | int (*udc_stop)(struct usb_gadget *, | ||
465 | struct usb_gadget_driver *); | ||
466 | |||
467 | /* Those two are deprecated */ | ||
462 | int (*start)(struct usb_gadget_driver *, | 468 | int (*start)(struct usb_gadget_driver *, |
463 | int (*bind)(struct usb_gadget *)); | 469 | int (*bind)(struct usb_gadget *)); |
464 | int (*stop)(struct usb_gadget_driver *); | 470 | int (*stop)(struct usb_gadget_driver *); |