Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.16-rc3 585 lines 15 kB view raw
1/** 2 * udc.c - Core UDC Framework 3 * 4 * Copyright (C) 2010 Texas Instruments 5 * Author: Felipe Balbi <balbi@ti.com> 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 of 9 * the License as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20#include <linux/kernel.h> 21#include <linux/module.h> 22#include <linux/device.h> 23#include <linux/list.h> 24#include <linux/err.h> 25#include <linux/dma-mapping.h> 26#include <linux/workqueue.h> 27 28#include <linux/usb/ch9.h> 29#include <linux/usb/gadget.h> 30 31/** 32 * struct usb_udc - describes one usb device controller 33 * @driver - the gadget driver pointer. For use by the class code 34 * @dev - the child device to the actual controller 35 * @gadget - the gadget. For use by the class code 36 * @list - for use by the udc class driver 37 * 38 * This represents the internal data structure which is used by the UDC-class 39 * to hold information about udc driver and gadget together. 40 */ 41struct usb_udc { 42 struct usb_gadget_driver *driver; 43 struct usb_gadget *gadget; 44 struct device dev; 45 struct list_head list; 46}; 47 48static struct class *udc_class; 49static LIST_HEAD(udc_list); 50static DEFINE_MUTEX(udc_lock); 51 52/* ------------------------------------------------------------------------- */ 53 54#ifdef CONFIG_HAS_DMA 55 56int usb_gadget_map_request(struct usb_gadget *gadget, 57 struct usb_request *req, int is_in) 58{ 59 if (req->length == 0) 60 return 0; 61 62 if (req->num_sgs) { 63 int mapped; 64 65 mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs, 66 is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); 67 if (mapped == 0) { 68 dev_err(&gadget->dev, "failed to map SGs\n"); 69 return -EFAULT; 70 } 71 72 req->num_mapped_sgs = mapped; 73 } else { 74 req->dma = dma_map_single(&gadget->dev, req->buf, req->length, 75 is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); 76 77 if (dma_mapping_error(&gadget->dev, req->dma)) { 78 dev_err(&gadget->dev, "failed to map buffer\n"); 79 return -EFAULT; 80 } 81 } 82 83 return 0; 84} 85EXPORT_SYMBOL_GPL(usb_gadget_map_request); 86 87void usb_gadget_unmap_request(struct usb_gadget *gadget, 88 struct usb_request *req, int is_in) 89{ 90 if (req->length == 0) 91 return; 92 93 if (req->num_mapped_sgs) { 94 dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs, 95 is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); 96 97 req->num_mapped_sgs = 0; 98 } else { 99 dma_unmap_single(&gadget->dev, req->dma, req->length, 100 is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); 101 } 102} 103EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); 104 105#endif /* CONFIG_HAS_DMA */ 106 107/* ------------------------------------------------------------------------- */ 108 109static void usb_gadget_state_work(struct work_struct *work) 110{ 111 struct usb_gadget *gadget = work_to_gadget(work); 112 113 sysfs_notify(&gadget->dev.kobj, NULL, "state"); 114} 115 116void usb_gadget_set_state(struct usb_gadget *gadget, 117 enum usb_device_state state) 118{ 119 gadget->state = state; 120 schedule_work(&gadget->work); 121} 122EXPORT_SYMBOL_GPL(usb_gadget_set_state); 123 124/* ------------------------------------------------------------------------- */ 125 126/** 127 * usb_gadget_udc_start - tells usb device controller to start up 128 * @gadget: The gadget we want to get started 129 * @driver: The driver we want to bind to @gadget 130 * 131 * This call is issued by the UDC Class driver when it's about 132 * to register a gadget driver to the device controller, before 133 * calling gadget driver's bind() method. 134 * 135 * It allows the controller to be powered off until strictly 136 * necessary to have it powered on. 137 * 138 * Returns zero on success, else negative errno. 139 */ 140static inline int usb_gadget_udc_start(struct usb_gadget *gadget, 141 struct usb_gadget_driver *driver) 142{ 143 return gadget->ops->udc_start(gadget, driver); 144} 145 146/** 147 * usb_gadget_udc_stop - tells usb device controller we don't need it anymore 148 * @gadget: The device we want to stop activity 149 * @driver: The driver to unbind from @gadget 150 * 151 * This call is issued by the UDC Class driver after calling 152 * gadget driver's unbind() method. 153 * 154 * The details are implementation specific, but it can go as 155 * far as powering off UDC completely and disable its data 156 * line pullups. 157 */ 158static inline void usb_gadget_udc_stop(struct usb_gadget *gadget, 159 struct usb_gadget_driver *driver) 160{ 161 gadget->ops->udc_stop(gadget, driver); 162} 163 164/** 165 * usb_udc_release - release the usb_udc struct 166 * @dev: the dev member within usb_udc 167 * 168 * This is called by driver's core in order to free memory once the last 169 * reference is released. 170 */ 171static void usb_udc_release(struct device *dev) 172{ 173 struct usb_udc *udc; 174 175 udc = container_of(dev, struct usb_udc, dev); 176 dev_dbg(dev, "releasing '%s'\n", dev_name(dev)); 177 kfree(udc); 178} 179 180static const struct attribute_group *usb_udc_attr_groups[]; 181 182static void usb_udc_nop_release(struct device *dev) 183{ 184 dev_vdbg(dev, "%s\n", __func__); 185} 186 187/** 188 * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list 189 * @parent: the parent device to this udc. Usually the controller driver's 190 * device. 191 * @gadget: the gadget to be added to the list. 192 * @release: a gadget release function. 193 * 194 * Returns zero on success, negative errno otherwise. 195 */ 196int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, 197 void (*release)(struct device *dev)) 198{ 199 struct usb_udc *udc; 200 int ret = -ENOMEM; 201 202 udc = kzalloc(sizeof(*udc), GFP_KERNEL); 203 if (!udc) 204 goto err1; 205 206 dev_set_name(&gadget->dev, "gadget"); 207 INIT_WORK(&gadget->work, usb_gadget_state_work); 208 gadget->dev.parent = parent; 209 210#ifdef CONFIG_HAS_DMA 211 dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask); 212 gadget->dev.dma_parms = parent->dma_parms; 213 gadget->dev.dma_mask = parent->dma_mask; 214#endif 215 216 if (release) 217 gadget->dev.release = release; 218 else 219 gadget->dev.release = usb_udc_nop_release; 220 221 ret = device_register(&gadget->dev); 222 if (ret) 223 goto err2; 224 225 device_initialize(&udc->dev); 226 udc->dev.release = usb_udc_release; 227 udc->dev.class = udc_class; 228 udc->dev.groups = usb_udc_attr_groups; 229 udc->dev.parent = parent; 230 ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj)); 231 if (ret) 232 goto err3; 233 234 udc->gadget = gadget; 235 236 mutex_lock(&udc_lock); 237 list_add_tail(&udc->list, &udc_list); 238 239 ret = device_add(&udc->dev); 240 if (ret) 241 goto err4; 242 243 usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED); 244 245 mutex_unlock(&udc_lock); 246 247 return 0; 248 249err4: 250 list_del(&udc->list); 251 mutex_unlock(&udc_lock); 252 253err3: 254 put_device(&udc->dev); 255 256err2: 257 put_device(&gadget->dev); 258 kfree(udc); 259 260err1: 261 return ret; 262} 263EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release); 264 265/** 266 * usb_add_gadget_udc - adds a new gadget to the udc class driver list 267 * @parent: the parent device to this udc. Usually the controller 268 * driver's device. 269 * @gadget: the gadget to be added to the list 270 * 271 * Returns zero on success, negative errno otherwise. 272 */ 273int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) 274{ 275 return usb_add_gadget_udc_release(parent, gadget, NULL); 276} 277EXPORT_SYMBOL_GPL(usb_add_gadget_udc); 278 279static void usb_gadget_remove_driver(struct usb_udc *udc) 280{ 281 dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n", 282 udc->gadget->name); 283 284 kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); 285 286 usb_gadget_disconnect(udc->gadget); 287 udc->driver->disconnect(udc->gadget); 288 udc->driver->unbind(udc->gadget); 289 usb_gadget_udc_stop(udc->gadget, NULL); 290 291 udc->driver = NULL; 292 udc->dev.driver = NULL; 293 udc->gadget->dev.driver = NULL; 294} 295 296/** 297 * usb_del_gadget_udc - deletes @udc from udc_list 298 * @gadget: the gadget to be removed. 299 * 300 * This, will call usb_gadget_unregister_driver() if 301 * the @udc is still busy. 302 */ 303void usb_del_gadget_udc(struct usb_gadget *gadget) 304{ 305 struct usb_udc *udc = NULL; 306 307 mutex_lock(&udc_lock); 308 list_for_each_entry(udc, &udc_list, list) 309 if (udc->gadget == gadget) 310 goto found; 311 312 dev_err(gadget->dev.parent, "gadget not registered.\n"); 313 mutex_unlock(&udc_lock); 314 315 return; 316 317found: 318 dev_vdbg(gadget->dev.parent, "unregistering gadget\n"); 319 320 list_del(&udc->list); 321 mutex_unlock(&udc_lock); 322 323 if (udc->driver) 324 usb_gadget_remove_driver(udc); 325 326 kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); 327 flush_work(&gadget->work); 328 device_unregister(&udc->dev); 329 device_unregister(&gadget->dev); 330} 331EXPORT_SYMBOL_GPL(usb_del_gadget_udc); 332 333/* ------------------------------------------------------------------------- */ 334 335static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver) 336{ 337 int ret; 338 339 dev_dbg(&udc->dev, "registering UDC driver [%s]\n", 340 driver->function); 341 342 udc->driver = driver; 343 udc->dev.driver = &driver->driver; 344 udc->gadget->dev.driver = &driver->driver; 345 346 ret = driver->bind(udc->gadget, driver); 347 if (ret) 348 goto err1; 349 ret = usb_gadget_udc_start(udc->gadget, driver); 350 if (ret) { 351 driver->unbind(udc->gadget); 352 goto err1; 353 } 354 usb_gadget_connect(udc->gadget); 355 356 kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); 357 return 0; 358err1: 359 if (ret != -EISNAM) 360 dev_err(&udc->dev, "failed to start %s: %d\n", 361 udc->driver->function, ret); 362 udc->driver = NULL; 363 udc->dev.driver = NULL; 364 udc->gadget->dev.driver = NULL; 365 return ret; 366} 367 368int udc_attach_driver(const char *name, struct usb_gadget_driver *driver) 369{ 370 struct usb_udc *udc = NULL; 371 int ret = -ENODEV; 372 373 mutex_lock(&udc_lock); 374 list_for_each_entry(udc, &udc_list, list) { 375 ret = strcmp(name, dev_name(&udc->dev)); 376 if (!ret) 377 break; 378 } 379 if (ret) { 380 ret = -ENODEV; 381 goto out; 382 } 383 if (udc->driver) { 384 ret = -EBUSY; 385 goto out; 386 } 387 ret = udc_bind_to_driver(udc, driver); 388out: 389 mutex_unlock(&udc_lock); 390 return ret; 391} 392EXPORT_SYMBOL_GPL(udc_attach_driver); 393 394int usb_gadget_probe_driver(struct usb_gadget_driver *driver) 395{ 396 struct usb_udc *udc = NULL; 397 int ret; 398 399 if (!driver || !driver->bind || !driver->setup) 400 return -EINVAL; 401 402 mutex_lock(&udc_lock); 403 list_for_each_entry(udc, &udc_list, list) { 404 /* For now we take the first one */ 405 if (!udc->driver) 406 goto found; 407 } 408 409 pr_debug("couldn't find an available UDC\n"); 410 mutex_unlock(&udc_lock); 411 return -ENODEV; 412found: 413 ret = udc_bind_to_driver(udc, driver); 414 mutex_unlock(&udc_lock); 415 return ret; 416} 417EXPORT_SYMBOL_GPL(usb_gadget_probe_driver); 418 419int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) 420{ 421 struct usb_udc *udc = NULL; 422 int ret = -ENODEV; 423 424 if (!driver || !driver->unbind) 425 return -EINVAL; 426 427 mutex_lock(&udc_lock); 428 list_for_each_entry(udc, &udc_list, list) 429 if (udc->driver == driver) { 430 usb_gadget_remove_driver(udc); 431 usb_gadget_set_state(udc->gadget, 432 USB_STATE_NOTATTACHED); 433 ret = 0; 434 break; 435 } 436 437 mutex_unlock(&udc_lock); 438 return ret; 439} 440EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver); 441 442/* ------------------------------------------------------------------------- */ 443 444static ssize_t usb_udc_srp_store(struct device *dev, 445 struct device_attribute *attr, const char *buf, size_t n) 446{ 447 struct usb_udc *udc = container_of(dev, struct usb_udc, dev); 448 449 if (sysfs_streq(buf, "1")) 450 usb_gadget_wakeup(udc->gadget); 451 452 return n; 453} 454static DEVICE_ATTR(srp, S_IWUSR, NULL, usb_udc_srp_store); 455 456static ssize_t usb_udc_softconn_store(struct device *dev, 457 struct device_attribute *attr, const char *buf, size_t n) 458{ 459 struct usb_udc *udc = container_of(dev, struct usb_udc, dev); 460 461 if (sysfs_streq(buf, "connect")) { 462 usb_gadget_udc_start(udc->gadget, udc->driver); 463 usb_gadget_connect(udc->gadget); 464 } else if (sysfs_streq(buf, "disconnect")) { 465 usb_gadget_disconnect(udc->gadget); 466 usb_gadget_udc_stop(udc->gadget, udc->driver); 467 } else { 468 dev_err(dev, "unsupported command '%s'\n", buf); 469 return -EINVAL; 470 } 471 472 return n; 473} 474static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store); 475 476static ssize_t state_show(struct device *dev, struct device_attribute *attr, 477 char *buf) 478{ 479 struct usb_udc *udc = container_of(dev, struct usb_udc, dev); 480 struct usb_gadget *gadget = udc->gadget; 481 482 return sprintf(buf, "%s\n", usb_state_string(gadget->state)); 483} 484static DEVICE_ATTR_RO(state); 485 486#define USB_UDC_SPEED_ATTR(name, param) \ 487ssize_t name##_show(struct device *dev, \ 488 struct device_attribute *attr, char *buf) \ 489{ \ 490 struct usb_udc *udc = container_of(dev, struct usb_udc, dev); \ 491 return snprintf(buf, PAGE_SIZE, "%s\n", \ 492 usb_speed_string(udc->gadget->param)); \ 493} \ 494static DEVICE_ATTR_RO(name) 495 496static USB_UDC_SPEED_ATTR(current_speed, speed); 497static USB_UDC_SPEED_ATTR(maximum_speed, max_speed); 498 499#define USB_UDC_ATTR(name) \ 500ssize_t name##_show(struct device *dev, \ 501 struct device_attribute *attr, char *buf) \ 502{ \ 503 struct usb_udc *udc = container_of(dev, struct usb_udc, dev); \ 504 struct usb_gadget *gadget = udc->gadget; \ 505 \ 506 return snprintf(buf, PAGE_SIZE, "%d\n", gadget->name); \ 507} \ 508static DEVICE_ATTR_RO(name) 509 510static USB_UDC_ATTR(is_otg); 511static USB_UDC_ATTR(is_a_peripheral); 512static USB_UDC_ATTR(b_hnp_enable); 513static USB_UDC_ATTR(a_hnp_support); 514static USB_UDC_ATTR(a_alt_hnp_support); 515 516static struct attribute *usb_udc_attrs[] = { 517 &dev_attr_srp.attr, 518 &dev_attr_soft_connect.attr, 519 &dev_attr_state.attr, 520 &dev_attr_current_speed.attr, 521 &dev_attr_maximum_speed.attr, 522 523 &dev_attr_is_otg.attr, 524 &dev_attr_is_a_peripheral.attr, 525 &dev_attr_b_hnp_enable.attr, 526 &dev_attr_a_hnp_support.attr, 527 &dev_attr_a_alt_hnp_support.attr, 528 NULL, 529}; 530 531static const struct attribute_group usb_udc_attr_group = { 532 .attrs = usb_udc_attrs, 533}; 534 535static const struct attribute_group *usb_udc_attr_groups[] = { 536 &usb_udc_attr_group, 537 NULL, 538}; 539 540static int usb_udc_uevent(struct device *dev, struct kobj_uevent_env *env) 541{ 542 struct usb_udc *udc = container_of(dev, struct usb_udc, dev); 543 int ret; 544 545 ret = add_uevent_var(env, "USB_UDC_NAME=%s", udc->gadget->name); 546 if (ret) { 547 dev_err(dev, "failed to add uevent USB_UDC_NAME\n"); 548 return ret; 549 } 550 551 if (udc->driver) { 552 ret = add_uevent_var(env, "USB_UDC_DRIVER=%s", 553 udc->driver->function); 554 if (ret) { 555 dev_err(dev, "failed to add uevent USB_UDC_DRIVER\n"); 556 return ret; 557 } 558 } 559 560 return 0; 561} 562 563static int __init usb_udc_init(void) 564{ 565 udc_class = class_create(THIS_MODULE, "udc"); 566 if (IS_ERR(udc_class)) { 567 pr_err("failed to create udc class --> %ld\n", 568 PTR_ERR(udc_class)); 569 return PTR_ERR(udc_class); 570 } 571 572 udc_class->dev_uevent = usb_udc_uevent; 573 return 0; 574} 575subsys_initcall(usb_udc_init); 576 577static void __exit usb_udc_exit(void) 578{ 579 class_destroy(udc_class); 580} 581module_exit(usb_udc_exit); 582 583MODULE_DESCRIPTION("UDC Framework"); 584MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 585MODULE_LICENSE("GPL v2");