1 /* 2 * HSI core. 3 * 4 * Copyright (C) 2010 Nokia Corporation. All rights reserved. 5 * 6 * Contact: Carlos Chinea <carlos.chinea@nokia.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA 21 */ 22 #include <linux/hsi/hsi.h> 23 #include <linux/compiler.h> 24 #include <linux/list.h> 25 #include <linux/kobject.h> 26 #include <linux/slab.h> 27 #include <linux/string.h> 28 #include <linux/notifier.h> 29 #include <linux/of.h> 30 #include <linux/of_device.h> 31 #include "hsi_core.h" 32 33 static ssize_t modalias_show(struct device *dev, 34 struct device_attribute *a __maybe_unused, char *buf) 35 { 36 return sprintf(buf, "hsi:%s\n", dev_name(dev)); 37 } 38 static DEVICE_ATTR_RO(modalias); 39 40 static struct attribute *hsi_bus_dev_attrs[] = { 41 &dev_attr_modalias.attr, 42 NULL, 43 }; 44 ATTRIBUTE_GROUPS(hsi_bus_dev); 45 46 static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) 47 { 48 add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev)); 49 50 return 0; 51 } 52 53 static int hsi_bus_match(struct device *dev, struct device_driver *driver) 54 { 55 if (of_driver_match_device(dev, driver)) 56 return true; 57 58 if (strcmp(dev_name(dev), driver->name) == 0) 59 return true; 60 61 return false; 62 } 63 64 static struct bus_type hsi_bus_type = { 65 .name = "hsi", 66 .dev_groups = hsi_bus_dev_groups, 67 .match = hsi_bus_match, 68 .uevent = hsi_bus_uevent, 69 }; 70 71 static void hsi_client_release(struct device *dev) 72 { 73 struct hsi_client *cl = to_hsi_client(dev); 74 75 kfree(cl->tx_cfg.channels); 76 kfree(cl->rx_cfg.channels); 77 kfree(cl); 78 } 79 80 struct hsi_client *hsi_new_client(struct hsi_port *port, 81 struct hsi_board_info *info) 82 { 83 struct hsi_client *cl; 84 size_t size; 85 86 cl = kzalloc(sizeof(*cl), GFP_KERNEL); 87 if (!cl) 88 goto err; 89 90 cl->tx_cfg = info->tx_cfg; 91 if (cl->tx_cfg.channels) { 92 size = cl->tx_cfg.num_channels * sizeof(*cl->tx_cfg.channels); 93 cl->tx_cfg.channels = kmemdup(info->tx_cfg.channels, size, 94 GFP_KERNEL); 95 if (!cl->tx_cfg.channels) 96 goto err_tx; 97 } 98 99 cl->rx_cfg = info->rx_cfg; 100 if (cl->rx_cfg.channels) { 101 size = cl->rx_cfg.num_channels * sizeof(*cl->rx_cfg.channels); 102 cl->rx_cfg.channels = kmemdup(info->rx_cfg.channels, size, 103 GFP_KERNEL); 104 if (!cl->rx_cfg.channels) 105 goto err_rx; 106 } 107 108 cl->device.bus = &hsi_bus_type; 109 cl->device.parent = &port->device; 110 cl->device.release = hsi_client_release; 111 dev_set_name(&cl->device, "%s", info->name); 112 cl->device.platform_data = info->platform_data; 113 if (info->archdata) 114 cl->device.archdata = *info->archdata; 115 if (device_register(&cl->device) < 0) { 116 pr_err("hsi: failed to register client: %s\n", info->name); 117 put_device(&cl->device); 118 } 119 120 return cl; 121 err_rx: 122 kfree(cl->tx_cfg.channels); 123 err_tx: 124 kfree(cl); 125 err: 126 return NULL; 127 } 128 EXPORT_SYMBOL_GPL(hsi_new_client); 129 130 static void hsi_scan_board_info(struct hsi_controller *hsi) 131 { 132 struct hsi_cl_info *cl_info; 133 struct hsi_port *p; 134 135 list_for_each_entry(cl_info, &hsi_board_list, list) 136 if (cl_info->info.hsi_id == hsi->id) { 137 p = hsi_find_port_num(hsi, cl_info->info.port); 138 if (!p) 139 continue; 140 hsi_new_client(p, &cl_info->info); 141 } 142 } 143 144 #ifdef CONFIG_OF 145 static struct hsi_board_info hsi_char_dev_info = { 146 .name = "hsi_char", 147 }; 148 149 static int hsi_of_property_parse_mode(struct device_node *client, char *name, 150 unsigned int *result) 151 { 152 const char *mode; 153 int err; 154 155 err = of_property_read_string(client, name, &mode); 156 if (err < 0) 157 return err; 158 159 if (strcmp(mode, "stream") == 0) 160 *result = HSI_MODE_STREAM; 161 else if (strcmp(mode, "frame") == 0) 162 *result = HSI_MODE_FRAME; 163 else 164 return -EINVAL; 165 166 return 0; 167 } 168 169 static int hsi_of_property_parse_flow(struct device_node *client, char *name, 170 unsigned int *result) 171 { 172 const char *flow; 173 int err; 174 175 err = of_property_read_string(client, name, &flow); 176 if (err < 0) 177 return err; 178 179 if (strcmp(flow, "synchronized") == 0) 180 *result = HSI_FLOW_SYNC; 181 else if (strcmp(flow, "pipeline") == 0) 182 *result = HSI_FLOW_PIPE; 183 else 184 return -EINVAL; 185 186 return 0; 187 } 188 189 static int hsi_of_property_parse_arb_mode(struct device_node *client, 190 char *name, unsigned int *result) 191 { 192 const char *arb_mode; 193 int err; 194 195 err = of_property_read_string(client, name, &arb_mode); 196 if (err < 0) 197 return err; 198 199 if (strcmp(arb_mode, "round-robin") == 0) 200 *result = HSI_ARB_RR; 201 else if (strcmp(arb_mode, "priority") == 0) 202 *result = HSI_ARB_PRIO; 203 else 204 return -EINVAL; 205 206 return 0; 207 } 208 209 static void hsi_add_client_from_dt(struct hsi_port *port, 210 struct device_node *client) 211 { 212 struct hsi_client *cl; 213 struct hsi_channel channel; 214 struct property *prop; 215 char name[32]; 216 int length, cells, err, i, max_chan, mode; 217 218 cl = kzalloc(sizeof(*cl), GFP_KERNEL); 219 if (!cl) 220 return; 221 222 err = of_modalias_node(client, name, sizeof(name)); 223 if (err) 224 goto err; 225 226 dev_set_name(&cl->device, "%s", name); 227 228 err = hsi_of_property_parse_mode(client, "hsi-mode", &mode); 229 if (err) { 230 err = hsi_of_property_parse_mode(client, "hsi-rx-mode", 231 &cl->rx_cfg.mode); 232 if (err) 233 goto err; 234 235 err = hsi_of_property_parse_mode(client, "hsi-tx-mode", 236 &cl->tx_cfg.mode); 237 if (err) 238 goto err; 239 } else { 240 cl->rx_cfg.mode = mode; 241 cl->tx_cfg.mode = mode; 242 } 243 244 err = of_property_read_u32(client, "hsi-speed-kbps", 245 &cl->tx_cfg.speed); 246 if (err) 247 goto err; 248 cl->rx_cfg.speed = cl->tx_cfg.speed; 249 250 err = hsi_of_property_parse_flow(client, "hsi-flow", 251 &cl->rx_cfg.flow); 252 if (err) 253 goto err; 254 255 err = hsi_of_property_parse_arb_mode(client, "hsi-arb-mode", 256 &cl->rx_cfg.arb_mode); 257 if (err) 258 goto err; 259 260 prop = of_find_property(client, "hsi-channel-ids", &length); 261 if (!prop) { 262 err = -EINVAL; 263 goto err; 264 } 265 266 cells = length / sizeof(u32); 267 268 cl->rx_cfg.num_channels = cells; 269 cl->tx_cfg.num_channels = cells; 270 cl->rx_cfg.channels = kcalloc(cells, sizeof(channel), GFP_KERNEL); 271 if (!cl->rx_cfg.channels) { 272 err = -ENOMEM; 273 goto err; 274 } 275 276 cl->tx_cfg.channels = kcalloc(cells, sizeof(channel), GFP_KERNEL); 277 if (!cl->tx_cfg.channels) { 278 err = -ENOMEM; 279 goto err2; 280 } 281 282 max_chan = 0; 283 for (i = 0; i < cells; i++) { 284 err = of_property_read_u32_index(client, "hsi-channel-ids", i, 285 &channel.id); 286 if (err) 287 goto err3; 288 289 err = of_property_read_string_index(client, "hsi-channel-names", 290 i, &channel.name); 291 if (err) 292 channel.name = NULL; 293 294 if (channel.id > max_chan) 295 max_chan = channel.id; 296 297 cl->rx_cfg.channels[i] = channel; 298 cl->tx_cfg.channels[i] = channel; 299 } 300 301 cl->rx_cfg.num_hw_channels = max_chan + 1; 302 cl->tx_cfg.num_hw_channels = max_chan + 1; 303 304 cl->device.bus = &hsi_bus_type; 305 cl->device.parent = &port->device; 306 cl->device.release = hsi_client_release; 307 cl->device.of_node = client; 308 309 if (device_register(&cl->device) < 0) { 310 pr_err("hsi: failed to register client: %s\n", name); 311 put_device(&cl->device); 312 } 313 314 return; 315 316 err3: 317 kfree(cl->tx_cfg.channels); 318 err2: 319 kfree(cl->rx_cfg.channels); 320 err: 321 kfree(cl); 322 pr_err("hsi client: missing or incorrect of property: err=%d\n", err); 323 } 324 325 void hsi_add_clients_from_dt(struct hsi_port *port, struct device_node *clients) 326 { 327 struct device_node *child; 328 329 /* register hsi-char device */ 330 hsi_new_client(port, &hsi_char_dev_info); 331 332 for_each_available_child_of_node(clients, child) 333 hsi_add_client_from_dt(port, child); 334 } 335 EXPORT_SYMBOL_GPL(hsi_add_clients_from_dt); 336 #endif 337 338 int hsi_remove_client(struct device *dev, void *data __maybe_unused) 339 { 340 device_unregister(dev); 341 342 return 0; 343 } 344 EXPORT_SYMBOL_GPL(hsi_remove_client); 345 346 static int hsi_remove_port(struct device *dev, void *data __maybe_unused) 347 { 348 device_for_each_child(dev, NULL, hsi_remove_client); 349 device_unregister(dev); 350 351 return 0; 352 } 353 354 static void hsi_controller_release(struct device *dev) 355 { 356 struct hsi_controller *hsi = to_hsi_controller(dev); 357 358 kfree(hsi->port); 359 kfree(hsi); 360 } 361 362 static void hsi_port_release(struct device *dev) 363 { 364 kfree(to_hsi_port(dev)); 365 } 366 367 /** 368 * hsi_unregister_port - Unregister an HSI port 369 * @port: The HSI port to unregister 370 */ 371 void hsi_port_unregister_clients(struct hsi_port *port) 372 { 373 device_for_each_child(&port->device, NULL, hsi_remove_client); 374 } 375 EXPORT_SYMBOL_GPL(hsi_port_unregister_clients); 376 377 /** 378 * hsi_unregister_controller - Unregister an HSI controller 379 * @hsi: The HSI controller to register 380 */ 381 void hsi_unregister_controller(struct hsi_controller *hsi) 382 { 383 device_for_each_child(&hsi->device, NULL, hsi_remove_port); 384 device_unregister(&hsi->device); 385 } 386 EXPORT_SYMBOL_GPL(hsi_unregister_controller); 387 388 /** 389 * hsi_register_controller - Register an HSI controller and its ports 390 * @hsi: The HSI controller to register 391 * 392 * Returns -errno on failure, 0 on success. 393 */ 394 int hsi_register_controller(struct hsi_controller *hsi) 395 { 396 unsigned int i; 397 int err; 398 399 err = device_add(&hsi->device); 400 if (err < 0) 401 return err; 402 for (i = 0; i < hsi->num_ports; i++) { 403 hsi->port[i]->device.parent = &hsi->device; 404 err = device_add(&hsi->port[i]->device); 405 if (err < 0) 406 goto out; 407 } 408 /* Populate HSI bus with HSI clients */ 409 hsi_scan_board_info(hsi); 410 411 return 0; 412 out: 413 while (i-- > 0) 414 device_del(&hsi->port[i]->device); 415 device_del(&hsi->device); 416 417 return err; 418 } 419 EXPORT_SYMBOL_GPL(hsi_register_controller); 420 421 /** 422 * hsi_register_client_driver - Register an HSI client to the HSI bus 423 * @drv: HSI client driver to register 424 * 425 * Returns -errno on failure, 0 on success. 426 */ 427 int hsi_register_client_driver(struct hsi_client_driver *drv) 428 { 429 drv->driver.bus = &hsi_bus_type; 430 431 return driver_register(&drv->driver); 432 } 433 EXPORT_SYMBOL_GPL(hsi_register_client_driver); 434 435 static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused) 436 { 437 return 0; 438 } 439 440 static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused) 441 { 442 return 0; 443 } 444 445 /** 446 * hsi_put_controller - Free an HSI controller 447 * 448 * @hsi: Pointer to the HSI controller to freed 449 * 450 * HSI controller drivers should only use this function if they need 451 * to free their allocated hsi_controller structures before a successful 452 * call to hsi_register_controller. Other use is not allowed. 453 */ 454 void hsi_put_controller(struct hsi_controller *hsi) 455 { 456 unsigned int i; 457 458 if (!hsi) 459 return; 460 461 for (i = 0; i < hsi->num_ports; i++) 462 if (hsi->port && hsi->port[i]) 463 put_device(&hsi->port[i]->device); 464 put_device(&hsi->device); 465 } 466 EXPORT_SYMBOL_GPL(hsi_put_controller); 467 468 /** 469 * hsi_alloc_controller - Allocate an HSI controller and its ports 470 * @n_ports: Number of ports on the HSI controller 471 * @flags: Kernel allocation flags 472 * 473 * Return NULL on failure or a pointer to an hsi_controller on success. 474 */ 475 struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags) 476 { 477 struct hsi_controller *hsi; 478 struct hsi_port **port; 479 unsigned int i; 480 481 if (!n_ports) 482 return NULL; 483 484 hsi = kzalloc(sizeof(*hsi), flags); 485 if (!hsi) 486 return NULL; 487 port = kcalloc(n_ports, sizeof(*port), flags); 488 if (!port) { 489 kfree(hsi); 490 return NULL; 491 } 492 hsi->num_ports = n_ports; 493 hsi->port = port; 494 hsi->device.release = hsi_controller_release; 495 device_initialize(&hsi->device); 496 497 for (i = 0; i < n_ports; i++) { 498 port[i] = kzalloc(sizeof(**port), flags); 499 if (port[i] == NULL) 500 goto out; 501 port[i]->num = i; 502 port[i]->async = hsi_dummy_msg; 503 port[i]->setup = hsi_dummy_cl; 504 port[i]->flush = hsi_dummy_cl; 505 port[i]->start_tx = hsi_dummy_cl; 506 port[i]->stop_tx = hsi_dummy_cl; 507 port[i]->release = hsi_dummy_cl; 508 mutex_init(&port[i]->lock); 509 BLOCKING_INIT_NOTIFIER_HEAD(&port[i]->n_head); 510 dev_set_name(&port[i]->device, "port%d", i); 511 hsi->port[i]->device.release = hsi_port_release; 512 device_initialize(&hsi->port[i]->device); 513 } 514 515 return hsi; 516 out: 517 hsi_put_controller(hsi); 518 519 return NULL; 520 } 521 EXPORT_SYMBOL_GPL(hsi_alloc_controller); 522 523 /** 524 * hsi_free_msg - Free an HSI message 525 * @msg: Pointer to the HSI message 526 * 527 * Client is responsible to free the buffers pointed by the scatterlists. 528 */ 529 void hsi_free_msg(struct hsi_msg *msg) 530 { 531 if (!msg) 532 return; 533 sg_free_table(&msg->sgt); 534 kfree(msg); 535 } 536 EXPORT_SYMBOL_GPL(hsi_free_msg); 537 538 /** 539 * hsi_alloc_msg - Allocate an HSI message 540 * @nents: Number of memory entries 541 * @flags: Kernel allocation flags 542 * 543 * nents can be 0. This mainly makes sense for read transfer. 544 * In that case, HSI drivers will call the complete callback when 545 * there is data to be read without consuming it. 546 * 547 * Return NULL on failure or a pointer to an hsi_msg on success. 548 */ 549 struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags) 550 { 551 struct hsi_msg *msg; 552 int err; 553 554 msg = kzalloc(sizeof(*msg), flags); 555 if (!msg) 556 return NULL; 557 558 if (!nents) 559 return msg; 560 561 err = sg_alloc_table(&msg->sgt, nents, flags); 562 if (unlikely(err)) { 563 kfree(msg); 564 msg = NULL; 565 } 566 567 return msg; 568 } 569 EXPORT_SYMBOL_GPL(hsi_alloc_msg); 570 571 /** 572 * hsi_async - Submit an HSI transfer to the controller 573 * @cl: HSI client sending the transfer 574 * @msg: The HSI transfer passed to controller 575 * 576 * The HSI message must have the channel, ttype, complete and destructor 577 * fields set beforehand. If nents > 0 then the client has to initialize 578 * also the scatterlists to point to the buffers to write to or read from. 579 * 580 * HSI controllers relay on pre-allocated buffers from their clients and they 581 * do not allocate buffers on their own. 582 * 583 * Once the HSI message transfer finishes, the HSI controller calls the 584 * complete callback with the status and actual_len fields of the HSI message 585 * updated. The complete callback can be called before returning from 586 * hsi_async. 587 * 588 * Returns -errno on failure or 0 on success 589 */ 590 int hsi_async(struct hsi_client *cl, struct hsi_msg *msg) 591 { 592 struct hsi_port *port = hsi_get_port(cl); 593 594 if (!hsi_port_claimed(cl)) 595 return -EACCES; 596 597 WARN_ON_ONCE(!msg->destructor || !msg->complete); 598 msg->cl = cl; 599 600 return port->async(msg); 601 } 602 EXPORT_SYMBOL_GPL(hsi_async); 603 604 /** 605 * hsi_claim_port - Claim the HSI client's port 606 * @cl: HSI client that wants to claim its port 607 * @share: Flag to indicate if the client wants to share the port or not. 608 * 609 * Returns -errno on failure, 0 on success. 610 */ 611 int hsi_claim_port(struct hsi_client *cl, unsigned int share) 612 { 613 struct hsi_port *port = hsi_get_port(cl); 614 int err = 0; 615 616 mutex_lock(&port->lock); 617 if ((port->claimed) && (!port->shared || !share)) { 618 err = -EBUSY; 619 goto out; 620 } 621 if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) { 622 err = -ENODEV; 623 goto out; 624 } 625 port->claimed++; 626 port->shared = !!share; 627 cl->pclaimed = 1; 628 out: 629 mutex_unlock(&port->lock); 630 631 return err; 632 } 633 EXPORT_SYMBOL_GPL(hsi_claim_port); 634 635 /** 636 * hsi_release_port - Release the HSI client's port 637 * @cl: HSI client which previously claimed its port 638 */ 639 void hsi_release_port(struct hsi_client *cl) 640 { 641 struct hsi_port *port = hsi_get_port(cl); 642 643 mutex_lock(&port->lock); 644 /* Allow HW driver to do some cleanup */ 645 port->release(cl); 646 if (cl->pclaimed) 647 port->claimed--; 648 BUG_ON(port->claimed < 0); 649 cl->pclaimed = 0; 650 if (!port->claimed) 651 port->shared = 0; 652 module_put(to_hsi_controller(port->device.parent)->owner); 653 mutex_unlock(&port->lock); 654 } 655 EXPORT_SYMBOL_GPL(hsi_release_port); 656 657 static int hsi_event_notifier_call(struct notifier_block *nb, 658 unsigned long event, void *data __maybe_unused) 659 { 660 struct hsi_client *cl = container_of(nb, struct hsi_client, nb); 661 662 (*cl->ehandler)(cl, event); 663 664 return 0; 665 } 666 667 /** 668 * hsi_register_port_event - Register a client to receive port events 669 * @cl: HSI client that wants to receive port events 670 * @handler: Event handler callback 671 * 672 * Clients should register a callback to be able to receive 673 * events from the ports. Registration should happen after 674 * claiming the port. 675 * The handler can be called in interrupt context. 676 * 677 * Returns -errno on error, or 0 on success. 678 */ 679 int hsi_register_port_event(struct hsi_client *cl, 680 void (*handler)(struct hsi_client *, unsigned long)) 681 { 682 struct hsi_port *port = hsi_get_port(cl); 683 684 if (!handler || cl->ehandler) 685 return -EINVAL; 686 if (!hsi_port_claimed(cl)) 687 return -EACCES; 688 cl->ehandler = handler; 689 cl->nb.notifier_call = hsi_event_notifier_call; 690 691 return blocking_notifier_chain_register(&port->n_head, &cl->nb); 692 } 693 EXPORT_SYMBOL_GPL(hsi_register_port_event); 694 695 /** 696 * hsi_unregister_port_event - Stop receiving port events for a client 697 * @cl: HSI client that wants to stop receiving port events 698 * 699 * Clients should call this function before releasing their associated 700 * port. 701 * 702 * Returns -errno on error, or 0 on success. 703 */ 704 int hsi_unregister_port_event(struct hsi_client *cl) 705 { 706 struct hsi_port *port = hsi_get_port(cl); 707 int err; 708 709 WARN_ON(!hsi_port_claimed(cl)); 710 711 err = blocking_notifier_chain_unregister(&port->n_head, &cl->nb); 712 if (!err) 713 cl->ehandler = NULL; 714 715 return err; 716 } 717 EXPORT_SYMBOL_GPL(hsi_unregister_port_event); 718 719 /** 720 * hsi_event - Notifies clients about port events 721 * @port: Port where the event occurred 722 * @event: The event type 723 * 724 * Clients should not be concerned about wake line behavior. However, due 725 * to a race condition in HSI HW protocol, clients need to be notified 726 * about wake line changes, so they can implement a workaround for it. 727 * 728 * Events: 729 * HSI_EVENT_START_RX - Incoming wake line high 730 * HSI_EVENT_STOP_RX - Incoming wake line down 731 * 732 * Returns -errno on error, or 0 on success. 733 */ 734 int hsi_event(struct hsi_port *port, unsigned long event) 735 { 736 return blocking_notifier_call_chain(&port->n_head, event, NULL); 737 } 738 EXPORT_SYMBOL_GPL(hsi_event); 739 740 /** 741 * hsi_get_channel_id_by_name - acquire channel id by channel name 742 * @cl: HSI client, which uses the channel 743 * @name: name the channel is known under 744 * 745 * Clients can call this function to get the hsi channel ids similar to 746 * requesting IRQs or GPIOs by name. This function assumes the same 747 * channel configuration is used for RX and TX. 748 * 749 * Returns -errno on error or channel id on success. 750 */ 751 int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name) 752 { 753 int i; 754 755 if (!cl->rx_cfg.channels) 756 return -ENOENT; 757 758 for (i = 0; i < cl->rx_cfg.num_channels; i++) 759 if (!strcmp(cl->rx_cfg.channels[i].name, name)) 760 return cl->rx_cfg.channels[i].id; 761 762 return -ENXIO; 763 } 764 EXPORT_SYMBOL_GPL(hsi_get_channel_id_by_name); 765 766 static int __init hsi_init(void) 767 { 768 return bus_register(&hsi_bus_type); 769 } 770 postcore_initcall(hsi_init); 771 772 static void __exit hsi_exit(void) 773 { 774 bus_unregister(&hsi_bus_type); 775 } 776 module_exit(hsi_exit); 777 778 MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>"); 779 MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework"); 780 MODULE_LICENSE("GPL v2"); 781