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 271 cl->rx_cfg.channels = kzalloc(cells * sizeof(channel), GFP_KERNEL); 272 if (!cl->rx_cfg.channels) { 273 err = -ENOMEM; 274 goto err; 275 } 276 277 cl->tx_cfg.channels = kzalloc(cells * sizeof(channel), GFP_KERNEL); 278 if (!cl->tx_cfg.channels) { 279 err = -ENOMEM; 280 goto err2; 281 } 282 283 max_chan = 0; 284 for (i = 0; i < cells; i++) { 285 err = of_property_read_u32_index(client, "hsi-channel-ids", i, 286 &channel.id); 287 if (err) 288 goto err3; 289 290 err = of_property_read_string_index(client, "hsi-channel-names", 291 i, &channel.name); 292 if (err) 293 channel.name = NULL; 294 295 if (channel.id > max_chan) 296 max_chan = channel.id; 297 298 cl->rx_cfg.channels[i] = channel; 299 cl->tx_cfg.channels[i] = channel; 300 } 301 302 cl->rx_cfg.num_hw_channels = max_chan + 1; 303 cl->tx_cfg.num_hw_channels = max_chan + 1; 304 305 cl->device.bus = &hsi_bus_type; 306 cl->device.parent = &port->device; 307 cl->device.release = hsi_client_release; 308 cl->device.of_node = client; 309 310 if (device_register(&cl->device) < 0) { 311 pr_err("hsi: failed to register client: %s\n", name); 312 put_device(&cl->device); 313 } 314 315 return; 316 317 err3: 318 kfree(cl->tx_cfg.channels); 319 err2: 320 kfree(cl->rx_cfg.channels); 321 err: 322 kfree(cl); 323 pr_err("hsi client: missing or incorrect of property: err=%d\n", err); 324 } 325 326 void hsi_add_clients_from_dt(struct hsi_port *port, struct device_node *clients) 327 { 328 struct device_node *child; 329 330 /* register hsi-char device */ 331 hsi_new_client(port, &hsi_char_dev_info); 332 333 for_each_available_child_of_node(clients, child) 334 hsi_add_client_from_dt(port, child); 335 } 336 EXPORT_SYMBOL_GPL(hsi_add_clients_from_dt); 337 #endif 338 339 int hsi_remove_client(struct device *dev, void *data __maybe_unused) 340 { 341 device_unregister(dev); 342 343 return 0; 344 } 345 EXPORT_SYMBOL_GPL(hsi_remove_client); 346 347 static int hsi_remove_port(struct device *dev, void *data __maybe_unused) 348 { 349 device_for_each_child(dev, NULL, hsi_remove_client); 350 device_unregister(dev); 351 352 return 0; 353 } 354 355 static void hsi_controller_release(struct device *dev) 356 { 357 struct hsi_controller *hsi = to_hsi_controller(dev); 358 359 kfree(hsi->port); 360 kfree(hsi); 361 } 362 363 static void hsi_port_release(struct device *dev) 364 { 365 kfree(to_hsi_port(dev)); 366 } 367 368 /** 369 * hsi_unregister_port - Unregister an HSI port 370 * @port: The HSI port to unregister 371 */ 372 void hsi_port_unregister_clients(struct hsi_port *port) 373 { 374 device_for_each_child(&port->device, NULL, hsi_remove_client); 375 } 376 EXPORT_SYMBOL_GPL(hsi_port_unregister_clients); 377 378 /** 379 * hsi_unregister_controller - Unregister an HSI controller 380 * @hsi: The HSI controller to register 381 */ 382 void hsi_unregister_controller(struct hsi_controller *hsi) 383 { 384 device_for_each_child(&hsi->device, NULL, hsi_remove_port); 385 device_unregister(&hsi->device); 386 } 387 EXPORT_SYMBOL_GPL(hsi_unregister_controller); 388 389 /** 390 * hsi_register_controller - Register an HSI controller and its ports 391 * @hsi: The HSI controller to register 392 * 393 * Returns -errno on failure, 0 on success. 394 */ 395 int hsi_register_controller(struct hsi_controller *hsi) 396 { 397 unsigned int i; 398 int err; 399 400 err = device_add(&hsi->device); 401 if (err < 0) 402 return err; 403 for (i = 0; i < hsi->num_ports; i++) { 404 hsi->port[i]->device.parent = &hsi->device; 405 err = device_add(&hsi->port[i]->device); 406 if (err < 0) 407 goto out; 408 } 409 /* Populate HSI bus with HSI clients */ 410 hsi_scan_board_info(hsi); 411 412 return 0; 413 out: 414 while (i-- > 0) 415 device_del(&hsi->port[i]->device); 416 device_del(&hsi->device); 417 418 return err; 419 } 420 EXPORT_SYMBOL_GPL(hsi_register_controller); 421 422 /** 423 * hsi_register_client_driver - Register an HSI client to the HSI bus 424 * @drv: HSI client driver to register 425 * 426 * Returns -errno on failure, 0 on success. 427 */ 428 int hsi_register_client_driver(struct hsi_client_driver *drv) 429 { 430 drv->driver.bus = &hsi_bus_type; 431 432 return driver_register(&drv->driver); 433 } 434 EXPORT_SYMBOL_GPL(hsi_register_client_driver); 435 436 static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused) 437 { 438 return 0; 439 } 440 441 static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused) 442 { 443 return 0; 444 } 445 446 /** 447 * hsi_put_controller - Free an HSI controller 448 * 449 * @hsi: Pointer to the HSI controller to freed 450 * 451 * HSI controller drivers should only use this function if they need 452 * to free their allocated hsi_controller structures before a successful 453 * call to hsi_register_controller. Other use is not allowed. 454 */ 455 void hsi_put_controller(struct hsi_controller *hsi) 456 { 457 unsigned int i; 458 459 if (!hsi) 460 return; 461 462 for (i = 0; i < hsi->num_ports; i++) 463 if (hsi->port && hsi->port[i]) 464 put_device(&hsi->port[i]->device); 465 put_device(&hsi->device); 466 } 467 EXPORT_SYMBOL_GPL(hsi_put_controller); 468 469 /** 470 * hsi_alloc_controller - Allocate an HSI controller and its ports 471 * @n_ports: Number of ports on the HSI controller 472 * @flags: Kernel allocation flags 473 * 474 * Return NULL on failure or a pointer to an hsi_controller on success. 475 */ 476 struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags) 477 { 478 struct hsi_controller *hsi; 479 struct hsi_port **port; 480 unsigned int i; 481 482 if (!n_ports) 483 return NULL; 484 485 hsi = kzalloc(sizeof(*hsi), flags); 486 if (!hsi) 487 return NULL; 488 port = kzalloc(sizeof(*port)*n_ports, flags); 489 if (!port) { 490 kfree(hsi); 491 return NULL; 492 } 493 hsi->num_ports = n_ports; 494 hsi->port = port; 495 hsi->device.release = hsi_controller_release; 496 device_initialize(&hsi->device); 497 498 for (i = 0; i < n_ports; i++) { 499 port[i] = kzalloc(sizeof(**port), flags); 500 if (port[i] == NULL) 501 goto out; 502 port[i]->num = i; 503 port[i]->async = hsi_dummy_msg; 504 port[i]->setup = hsi_dummy_cl; 505 port[i]->flush = hsi_dummy_cl; 506 port[i]->start_tx = hsi_dummy_cl; 507 port[i]->stop_tx = hsi_dummy_cl; 508 port[i]->release = hsi_dummy_cl; 509 mutex_init(&port[i]->lock); 510 BLOCKING_INIT_NOTIFIER_HEAD(&port[i]->n_head); 511 dev_set_name(&port[i]->device, "port%d", i); 512 hsi->port[i]->device.release = hsi_port_release; 513 device_initialize(&hsi->port[i]->device); 514 } 515 516 return hsi; 517 out: 518 hsi_put_controller(hsi); 519 520 return NULL; 521 } 522 EXPORT_SYMBOL_GPL(hsi_alloc_controller); 523 524 /** 525 * hsi_free_msg - Free an HSI message 526 * @msg: Pointer to the HSI message 527 * 528 * Client is responsible to free the buffers pointed by the scatterlists. 529 */ 530 void hsi_free_msg(struct hsi_msg *msg) 531 { 532 if (!msg) 533 return; 534 sg_free_table(&msg->sgt); 535 kfree(msg); 536 } 537 EXPORT_SYMBOL_GPL(hsi_free_msg); 538 539 /** 540 * hsi_alloc_msg - Allocate an HSI message 541 * @nents: Number of memory entries 542 * @flags: Kernel allocation flags 543 * 544 * nents can be 0. This mainly makes sense for read transfer. 545 * In that case, HSI drivers will call the complete callback when 546 * there is data to be read without consuming it. 547 * 548 * Return NULL on failure or a pointer to an hsi_msg on success. 549 */ 550 struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags) 551 { 552 struct hsi_msg *msg; 553 int err; 554 555 msg = kzalloc(sizeof(*msg), flags); 556 if (!msg) 557 return NULL; 558 559 if (!nents) 560 return msg; 561 562 err = sg_alloc_table(&msg->sgt, nents, flags); 563 if (unlikely(err)) { 564 kfree(msg); 565 msg = NULL; 566 } 567 568 return msg; 569 } 570 EXPORT_SYMBOL_GPL(hsi_alloc_msg); 571 572 /** 573 * hsi_async - Submit an HSI transfer to the controller 574 * @cl: HSI client sending the transfer 575 * @msg: The HSI transfer passed to controller 576 * 577 * The HSI message must have the channel, ttype, complete and destructor 578 * fields set beforehand. If nents > 0 then the client has to initialize 579 * also the scatterlists to point to the buffers to write to or read from. 580 * 581 * HSI controllers relay on pre-allocated buffers from their clients and they 582 * do not allocate buffers on their own. 583 * 584 * Once the HSI message transfer finishes, the HSI controller calls the 585 * complete callback with the status and actual_len fields of the HSI message 586 * updated. The complete callback can be called before returning from 587 * hsi_async. 588 * 589 * Returns -errno on failure or 0 on success 590 */ 591 int hsi_async(struct hsi_client *cl, struct hsi_msg *msg) 592 { 593 struct hsi_port *port = hsi_get_port(cl); 594 595 if (!hsi_port_claimed(cl)) 596 return -EACCES; 597 598 WARN_ON_ONCE(!msg->destructor || !msg->complete); 599 msg->cl = cl; 600 601 return port->async(msg); 602 } 603 EXPORT_SYMBOL_GPL(hsi_async); 604 605 /** 606 * hsi_claim_port - Claim the HSI client's port 607 * @cl: HSI client that wants to claim its port 608 * @share: Flag to indicate if the client wants to share the port or not. 609 * 610 * Returns -errno on failure, 0 on success. 611 */ 612 int hsi_claim_port(struct hsi_client *cl, unsigned int share) 613 { 614 struct hsi_port *port = hsi_get_port(cl); 615 int err = 0; 616 617 mutex_lock(&port->lock); 618 if ((port->claimed) && (!port->shared || !share)) { 619 err = -EBUSY; 620 goto out; 621 } 622 if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) { 623 err = -ENODEV; 624 goto out; 625 } 626 port->claimed++; 627 port->shared = !!share; 628 cl->pclaimed = 1; 629 out: 630 mutex_unlock(&port->lock); 631 632 return err; 633 } 634 EXPORT_SYMBOL_GPL(hsi_claim_port); 635 636 /** 637 * hsi_release_port - Release the HSI client's port 638 * @cl: HSI client which previously claimed its port 639 */ 640 void hsi_release_port(struct hsi_client *cl) 641 { 642 struct hsi_port *port = hsi_get_port(cl); 643 644 mutex_lock(&port->lock); 645 /* Allow HW driver to do some cleanup */ 646 port->release(cl); 647 if (cl->pclaimed) 648 port->claimed--; 649 BUG_ON(port->claimed < 0); 650 cl->pclaimed = 0; 651 if (!port->claimed) 652 port->shared = 0; 653 module_put(to_hsi_controller(port->device.parent)->owner); 654 mutex_unlock(&port->lock); 655 } 656 EXPORT_SYMBOL_GPL(hsi_release_port); 657 658 static int hsi_event_notifier_call(struct notifier_block *nb, 659 unsigned long event, void *data __maybe_unused) 660 { 661 struct hsi_client *cl = container_of(nb, struct hsi_client, nb); 662 663 (*cl->ehandler)(cl, event); 664 665 return 0; 666 } 667 668 /** 669 * hsi_register_port_event - Register a client to receive port events 670 * @cl: HSI client that wants to receive port events 671 * @handler: Event handler callback 672 * 673 * Clients should register a callback to be able to receive 674 * events from the ports. Registration should happen after 675 * claiming the port. 676 * The handler can be called in interrupt context. 677 * 678 * Returns -errno on error, or 0 on success. 679 */ 680 int hsi_register_port_event(struct hsi_client *cl, 681 void (*handler)(struct hsi_client *, unsigned long)) 682 { 683 struct hsi_port *port = hsi_get_port(cl); 684 685 if (!handler || cl->ehandler) 686 return -EINVAL; 687 if (!hsi_port_claimed(cl)) 688 return -EACCES; 689 cl->ehandler = handler; 690 cl->nb.notifier_call = hsi_event_notifier_call; 691 692 return blocking_notifier_chain_register(&port->n_head, &cl->nb); 693 } 694 EXPORT_SYMBOL_GPL(hsi_register_port_event); 695 696 /** 697 * hsi_unregister_port_event - Stop receiving port events for a client 698 * @cl: HSI client that wants to stop receiving port events 699 * 700 * Clients should call this function before releasing their associated 701 * port. 702 * 703 * Returns -errno on error, or 0 on success. 704 */ 705 int hsi_unregister_port_event(struct hsi_client *cl) 706 { 707 struct hsi_port *port = hsi_get_port(cl); 708 int err; 709 710 WARN_ON(!hsi_port_claimed(cl)); 711 712 err = blocking_notifier_chain_unregister(&port->n_head, &cl->nb); 713 if (!err) 714 cl->ehandler = NULL; 715 716 return err; 717 } 718 EXPORT_SYMBOL_GPL(hsi_unregister_port_event); 719 720 /** 721 * hsi_event - Notifies clients about port events 722 * @port: Port where the event occurred 723 * @event: The event type 724 * 725 * Clients should not be concerned about wake line behavior. However, due 726 * to a race condition in HSI HW protocol, clients need to be notified 727 * about wake line changes, so they can implement a workaround for it. 728 * 729 * Events: 730 * HSI_EVENT_START_RX - Incoming wake line high 731 * HSI_EVENT_STOP_RX - Incoming wake line down 732 * 733 * Returns -errno on error, or 0 on success. 734 */ 735 int hsi_event(struct hsi_port *port, unsigned long event) 736 { 737 return blocking_notifier_call_chain(&port->n_head, event, NULL); 738 } 739 EXPORT_SYMBOL_GPL(hsi_event); 740 741 /** 742 * hsi_get_channel_id_by_name - acquire channel id by channel name 743 * @cl: HSI client, which uses the channel 744 * @name: name the channel is known under 745 * 746 * Clients can call this function to get the hsi channel ids similar to 747 * requesting IRQs or GPIOs by name. This function assumes the same 748 * channel configuration is used for RX and TX. 749 * 750 * Returns -errno on error or channel id on success. 751 */ 752 int hsi_get_channel_id_by_name(struct hsi_client *cl, char *name) 753 { 754 int i; 755 756 if (!cl->rx_cfg.channels) 757 return -ENOENT; 758 759 for (i = 0; i < cl->rx_cfg.num_channels; i++) 760 if (!strcmp(cl->rx_cfg.channels[i].name, name)) 761 return cl->rx_cfg.channels[i].id; 762 763 return -ENXIO; 764 } 765 EXPORT_SYMBOL_GPL(hsi_get_channel_id_by_name); 766 767 static int __init hsi_init(void) 768 { 769 return bus_register(&hsi_bus_type); 770 } 771 postcore_initcall(hsi_init); 772 773 static void __exit hsi_exit(void) 774 { 775 bus_unregister(&hsi_bus_type); 776 } 777 module_exit(hsi_exit); 778 779 MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>"); 780 MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework"); 781 MODULE_LICENSE("GPL v2"); 782