1/* 2 * Simple synchronous userspace interface to SPI devices 3 * 4 * Copyright (C) 2006 SWAPP 5 * Andrea Paterniani <a.paterniani@swapp-eng.it> 6 * Copyright (C) 2007 David Brownell (simplification, cleanup) 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23#include <linux/init.h> 24#include <linux/module.h> 25#include <linux/ioctl.h> 26#include <linux/fs.h> 27#include <linux/device.h> 28#include <linux/err.h> 29#include <linux/list.h> 30#include <linux/errno.h> 31#include <linux/mutex.h> 32#include <linux/slab.h> 33#include <linux/compat.h> 34#include <linux/of.h> 35#include <linux/of_device.h> 36 37#include <linux/spi/spi.h> 38#include <linux/spi/spidev.h> 39 40#include <linux/uaccess.h> 41 42 43/* 44 * This supports access to SPI devices using normal userspace I/O calls. 45 * Note that while traditional UNIX/POSIX I/O semantics are half duplex, 46 * and often mask message boundaries, full SPI support requires full duplex 47 * transfers. There are several kinds of internal message boundaries to 48 * handle chipselect management and other protocol options. 49 * 50 * SPI has a character major number assigned. We allocate minor numbers 51 * dynamically using a bitmask. You must use hotplug tools, such as udev 52 * (or mdev with busybox) to create and destroy the /dev/spidevB.C device 53 * nodes, since there is no fixed association of minor numbers with any 54 * particular SPI bus or device. 55 */ 56#define SPIDEV_MAJOR 153 /* assigned */ 57#define N_SPI_MINORS 32 /* ... up to 256 */ 58 59static DECLARE_BITMAP(minors, N_SPI_MINORS); 60 61 62/* Bit masks for spi_device.mode management. Note that incorrect 63 * settings for some settings can cause *lots* of trouble for other 64 * devices on a shared bus: 65 * 66 * - CS_HIGH ... this device will be active when it shouldn't be 67 * - 3WIRE ... when active, it won't behave as it should 68 * - NO_CS ... there will be no explicit message boundaries; this 69 * is completely incompatible with the shared bus model 70 * - READY ... transfers may proceed when they shouldn't. 71 * 72 * REVISIT should changing those flags be privileged? 73 */ 74#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ 75 | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ 76 | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \ 77 | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD) 78 79struct spidev_data { 80 dev_t devt; 81 spinlock_t spi_lock; 82 struct spi_device *spi; 83 struct list_head device_entry; 84 85 /* TX/RX buffers are NULL unless this device is open (users > 0) */ 86 struct mutex buf_lock; 87 unsigned users; 88 u8 *tx_buffer; 89 u8 *rx_buffer; 90}; 91 92static LIST_HEAD(device_list); 93static DEFINE_MUTEX(device_list_lock); 94 95static unsigned bufsiz = 4096; 96module_param(bufsiz, uint, S_IRUGO); 97MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message"); 98 99/*-------------------------------------------------------------------------*/ 100 101/* 102 * We can't use the standard synchronous wrappers for file I/O; we 103 * need to protect against async removal of the underlying spi_device. 104 */ 105static void spidev_complete(void *arg) 106{ 107 complete(arg); 108} 109 110static ssize_t 111spidev_sync(struct spidev_data *spidev, struct spi_message *message) 112{ 113 DECLARE_COMPLETION_ONSTACK(done); 114 int status; 115 116 message->complete = spidev_complete; 117 message->context = &done; 118 119 spin_lock_irq(&spidev->spi_lock); 120 if (spidev->spi == NULL) 121 status = -ESHUTDOWN; 122 else 123 status = spi_async(spidev->spi, message); 124 spin_unlock_irq(&spidev->spi_lock); 125 126 if (status == 0) { 127 wait_for_completion(&done); 128 status = message->status; 129 if (status == 0) 130 status = message->actual_length; 131 } 132 return status; 133} 134 135static inline ssize_t 136spidev_sync_write(struct spidev_data *spidev, size_t len) 137{ 138 struct spi_transfer t = { 139 .tx_buf = spidev->tx_buffer, 140 .len = len, 141 }; 142 struct spi_message m; 143 144 spi_message_init(&m); 145 spi_message_add_tail(&t, &m); 146 return spidev_sync(spidev, &m); 147} 148 149static inline ssize_t 150spidev_sync_read(struct spidev_data *spidev, size_t len) 151{ 152 struct spi_transfer t = { 153 .rx_buf = spidev->rx_buffer, 154 .len = len, 155 }; 156 struct spi_message m; 157 158 spi_message_init(&m); 159 spi_message_add_tail(&t, &m); 160 return spidev_sync(spidev, &m); 161} 162 163/*-------------------------------------------------------------------------*/ 164 165/* Read-only message with current device setup */ 166static ssize_t 167spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) 168{ 169 struct spidev_data *spidev; 170 ssize_t status = 0; 171 172 /* chipselect only toggles at start or end of operation */ 173 if (count > bufsiz) 174 return -EMSGSIZE; 175 176 spidev = filp->private_data; 177 178 mutex_lock(&spidev->buf_lock); 179 status = spidev_sync_read(spidev, count); 180 if (status > 0) { 181 unsigned long missing; 182 183 missing = copy_to_user(buf, spidev->rx_buffer, status); 184 if (missing == status) 185 status = -EFAULT; 186 else 187 status = status - missing; 188 } 189 mutex_unlock(&spidev->buf_lock); 190 191 return status; 192} 193 194/* Write-only message with current device setup */ 195static ssize_t 196spidev_write(struct file *filp, const char __user *buf, 197 size_t count, loff_t *f_pos) 198{ 199 struct spidev_data *spidev; 200 ssize_t status = 0; 201 unsigned long missing; 202 203 /* chipselect only toggles at start or end of operation */ 204 if (count > bufsiz) 205 return -EMSGSIZE; 206 207 spidev = filp->private_data; 208 209 mutex_lock(&spidev->buf_lock); 210 missing = copy_from_user(spidev->tx_buffer, buf, count); 211 if (missing == 0) 212 status = spidev_sync_write(spidev, count); 213 else 214 status = -EFAULT; 215 mutex_unlock(&spidev->buf_lock); 216 217 return status; 218} 219 220static int spidev_message(struct spidev_data *spidev, 221 struct spi_ioc_transfer *u_xfers, unsigned n_xfers) 222{ 223 struct spi_message msg; 224 struct spi_transfer *k_xfers; 225 struct spi_transfer *k_tmp; 226 struct spi_ioc_transfer *u_tmp; 227 unsigned n, total; 228 u8 *tx_buf, *rx_buf; 229 int status = -EFAULT; 230 231 spi_message_init(&msg); 232 k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL); 233 if (k_xfers == NULL) 234 return -ENOMEM; 235 236 /* Construct spi_message, copying any tx data to bounce buffer. 237 * We walk the array of user-provided transfers, using each one 238 * to initialize a kernel version of the same transfer. 239 */ 240 tx_buf = spidev->tx_buffer; 241 rx_buf = spidev->rx_buffer; 242 total = 0; 243 for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; 244 n; 245 n--, k_tmp++, u_tmp++) { 246 k_tmp->len = u_tmp->len; 247 248 total += k_tmp->len; 249 if (total > bufsiz) { 250 status = -EMSGSIZE; 251 goto done; 252 } 253 254 if (u_tmp->rx_buf) { 255 k_tmp->rx_buf = rx_buf; 256 if (!access_ok(VERIFY_WRITE, (u8 __user *) 257 (uintptr_t) u_tmp->rx_buf, 258 u_tmp->len)) 259 goto done; 260 } 261 if (u_tmp->tx_buf) { 262 k_tmp->tx_buf = tx_buf; 263 if (copy_from_user(tx_buf, (const u8 __user *) 264 (uintptr_t) u_tmp->tx_buf, 265 u_tmp->len)) 266 goto done; 267 } 268 tx_buf += k_tmp->len; 269 rx_buf += k_tmp->len; 270 271 k_tmp->cs_change = !!u_tmp->cs_change; 272 k_tmp->tx_nbits = u_tmp->tx_nbits; 273 k_tmp->rx_nbits = u_tmp->rx_nbits; 274 k_tmp->bits_per_word = u_tmp->bits_per_word; 275 k_tmp->delay_usecs = u_tmp->delay_usecs; 276 k_tmp->speed_hz = u_tmp->speed_hz; 277#ifdef VERBOSE 278 dev_dbg(&spidev->spi->dev, 279 " xfer len %zd %s%s%s%dbits %u usec %uHz\n", 280 u_tmp->len, 281 u_tmp->rx_buf ? "rx " : "", 282 u_tmp->tx_buf ? "tx " : "", 283 u_tmp->cs_change ? "cs " : "", 284 u_tmp->bits_per_word ? : spidev->spi->bits_per_word, 285 u_tmp->delay_usecs, 286 u_tmp->speed_hz ? : spidev->spi->max_speed_hz); 287#endif 288 spi_message_add_tail(k_tmp, &msg); 289 } 290 291 status = spidev_sync(spidev, &msg); 292 if (status < 0) 293 goto done; 294 295 /* copy any rx data out of bounce buffer */ 296 rx_buf = spidev->rx_buffer; 297 for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { 298 if (u_tmp->rx_buf) { 299 if (__copy_to_user((u8 __user *) 300 (uintptr_t) u_tmp->rx_buf, rx_buf, 301 u_tmp->len)) { 302 status = -EFAULT; 303 goto done; 304 } 305 } 306 rx_buf += u_tmp->len; 307 } 308 status = total; 309 310done: 311 kfree(k_xfers); 312 return status; 313} 314 315static long 316spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 317{ 318 int err = 0; 319 int retval = 0; 320 struct spidev_data *spidev; 321 struct spi_device *spi; 322 u32 tmp; 323 unsigned n_ioc; 324 struct spi_ioc_transfer *ioc; 325 326 /* Check type and command number */ 327 if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC) 328 return -ENOTTY; 329 330 /* Check access direction once here; don't repeat below. 331 * IOC_DIR is from the user perspective, while access_ok is 332 * from the kernel perspective; so they look reversed. 333 */ 334 if (_IOC_DIR(cmd) & _IOC_READ) 335 err = !access_ok(VERIFY_WRITE, 336 (void __user *)arg, _IOC_SIZE(cmd)); 337 if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) 338 err = !access_ok(VERIFY_READ, 339 (void __user *)arg, _IOC_SIZE(cmd)); 340 if (err) 341 return -EFAULT; 342 343 /* guard against device removal before, or while, 344 * we issue this ioctl. 345 */ 346 spidev = filp->private_data; 347 spin_lock_irq(&spidev->spi_lock); 348 spi = spi_dev_get(spidev->spi); 349 spin_unlock_irq(&spidev->spi_lock); 350 351 if (spi == NULL) 352 return -ESHUTDOWN; 353 354 /* use the buffer lock here for triple duty: 355 * - prevent I/O (from us) so calling spi_setup() is safe; 356 * - prevent concurrent SPI_IOC_WR_* from morphing 357 * data fields while SPI_IOC_RD_* reads them; 358 * - SPI_IOC_MESSAGE needs the buffer locked "normally". 359 */ 360 mutex_lock(&spidev->buf_lock); 361 362 switch (cmd) { 363 /* read requests */ 364 case SPI_IOC_RD_MODE: 365 retval = __put_user(spi->mode & SPI_MODE_MASK, 366 (__u8 __user *)arg); 367 break; 368 case SPI_IOC_RD_MODE32: 369 retval = __put_user(spi->mode & SPI_MODE_MASK, 370 (__u32 __user *)arg); 371 break; 372 case SPI_IOC_RD_LSB_FIRST: 373 retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, 374 (__u8 __user *)arg); 375 break; 376 case SPI_IOC_RD_BITS_PER_WORD: 377 retval = __put_user(spi->bits_per_word, (__u8 __user *)arg); 378 break; 379 case SPI_IOC_RD_MAX_SPEED_HZ: 380 retval = __put_user(spi->max_speed_hz, (__u32 __user *)arg); 381 break; 382 383 /* write requests */ 384 case SPI_IOC_WR_MODE: 385 case SPI_IOC_WR_MODE32: 386 if (cmd == SPI_IOC_WR_MODE) 387 retval = __get_user(tmp, (u8 __user *)arg); 388 else 389 retval = __get_user(tmp, (u32 __user *)arg); 390 if (retval == 0) { 391 u32 save = spi->mode; 392 393 if (tmp & ~SPI_MODE_MASK) { 394 retval = -EINVAL; 395 break; 396 } 397 398 tmp |= spi->mode & ~SPI_MODE_MASK; 399 spi->mode = (u16)tmp; 400 retval = spi_setup(spi); 401 if (retval < 0) 402 spi->mode = save; 403 else 404 dev_dbg(&spi->dev, "spi mode %x\n", tmp); 405 } 406 break; 407 case SPI_IOC_WR_LSB_FIRST: 408 retval = __get_user(tmp, (__u8 __user *)arg); 409 if (retval == 0) { 410 u32 save = spi->mode; 411 412 if (tmp) 413 spi->mode |= SPI_LSB_FIRST; 414 else 415 spi->mode &= ~SPI_LSB_FIRST; 416 retval = spi_setup(spi); 417 if (retval < 0) 418 spi->mode = save; 419 else 420 dev_dbg(&spi->dev, "%csb first\n", 421 tmp ? 'l' : 'm'); 422 } 423 break; 424 case SPI_IOC_WR_BITS_PER_WORD: 425 retval = __get_user(tmp, (__u8 __user *)arg); 426 if (retval == 0) { 427 u8 save = spi->bits_per_word; 428 429 spi->bits_per_word = tmp; 430 retval = spi_setup(spi); 431 if (retval < 0) 432 spi->bits_per_word = save; 433 else 434 dev_dbg(&spi->dev, "%d bits per word\n", tmp); 435 } 436 break; 437 case SPI_IOC_WR_MAX_SPEED_HZ: 438 retval = __get_user(tmp, (__u32 __user *)arg); 439 if (retval == 0) { 440 u32 save = spi->max_speed_hz; 441 442 spi->max_speed_hz = tmp; 443 retval = spi_setup(spi); 444 if (retval < 0) 445 spi->max_speed_hz = save; 446 else 447 dev_dbg(&spi->dev, "%d Hz (max)\n", tmp); 448 } 449 break; 450 451 default: 452 /* segmented and/or full-duplex I/O request */ 453 if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0)) 454 || _IOC_DIR(cmd) != _IOC_WRITE) { 455 retval = -ENOTTY; 456 break; 457 } 458 459 tmp = _IOC_SIZE(cmd); 460 if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) { 461 retval = -EINVAL; 462 break; 463 } 464 n_ioc = tmp / sizeof(struct spi_ioc_transfer); 465 if (n_ioc == 0) 466 break; 467 468 /* copy into scratch area */ 469 ioc = kmalloc(tmp, GFP_KERNEL); 470 if (!ioc) { 471 retval = -ENOMEM; 472 break; 473 } 474 if (__copy_from_user(ioc, (void __user *)arg, tmp)) { 475 kfree(ioc); 476 retval = -EFAULT; 477 break; 478 } 479 480 /* translate to spi_message, execute */ 481 retval = spidev_message(spidev, ioc, n_ioc); 482 kfree(ioc); 483 break; 484 } 485 486 mutex_unlock(&spidev->buf_lock); 487 spi_dev_put(spi); 488 return retval; 489} 490 491#ifdef CONFIG_COMPAT 492static long 493spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 494{ 495 return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); 496} 497#else 498#define spidev_compat_ioctl NULL 499#endif /* CONFIG_COMPAT */ 500 501static int spidev_open(struct inode *inode, struct file *filp) 502{ 503 struct spidev_data *spidev; 504 int status = -ENXIO; 505 506 mutex_lock(&device_list_lock); 507 508 list_for_each_entry(spidev, &device_list, device_entry) { 509 if (spidev->devt == inode->i_rdev) { 510 status = 0; 511 break; 512 } 513 } 514 515 if (status) { 516 pr_debug("spidev: nothing for minor %d\n", iminor(inode)); 517 goto err_find_dev; 518 } 519 520 if (!spidev->tx_buffer) { 521 spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL); 522 if (!spidev->tx_buffer) { 523 dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); 524 status = -ENOMEM; 525 goto err_find_dev; 526 } 527 } 528 529 if (!spidev->rx_buffer) { 530 spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL); 531 if (!spidev->rx_buffer) { 532 dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); 533 status = -ENOMEM; 534 goto err_alloc_rx_buf; 535 } 536 } 537 538 spidev->users++; 539 filp->private_data = spidev; 540 nonseekable_open(inode, filp); 541 542 mutex_unlock(&device_list_lock); 543 return 0; 544 545err_alloc_rx_buf: 546 kfree(spidev->tx_buffer); 547 spidev->tx_buffer = NULL; 548err_find_dev: 549 mutex_unlock(&device_list_lock); 550 return status; 551} 552 553static int spidev_release(struct inode *inode, struct file *filp) 554{ 555 struct spidev_data *spidev; 556 int status = 0; 557 558 mutex_lock(&device_list_lock); 559 spidev = filp->private_data; 560 filp->private_data = NULL; 561 562 /* last close? */ 563 spidev->users--; 564 if (!spidev->users) { 565 int dofree; 566 567 kfree(spidev->tx_buffer); 568 spidev->tx_buffer = NULL; 569 570 kfree(spidev->rx_buffer); 571 spidev->rx_buffer = NULL; 572 573 /* ... after we unbound from the underlying device? */ 574 spin_lock_irq(&spidev->spi_lock); 575 dofree = (spidev->spi == NULL); 576 spin_unlock_irq(&spidev->spi_lock); 577 578 if (dofree) 579 kfree(spidev); 580 } 581 mutex_unlock(&device_list_lock); 582 583 return status; 584} 585 586static const struct file_operations spidev_fops = { 587 .owner = THIS_MODULE, 588 /* REVISIT switch to aio primitives, so that userspace 589 * gets more complete API coverage. It'll simplify things 590 * too, except for the locking. 591 */ 592 .write = spidev_write, 593 .read = spidev_read, 594 .unlocked_ioctl = spidev_ioctl, 595 .compat_ioctl = spidev_compat_ioctl, 596 .open = spidev_open, 597 .release = spidev_release, 598 .llseek = no_llseek, 599}; 600 601/*-------------------------------------------------------------------------*/ 602 603/* The main reason to have this class is to make mdev/udev create the 604 * /dev/spidevB.C character device nodes exposing our userspace API. 605 * It also simplifies memory management. 606 */ 607 608static struct class *spidev_class; 609 610/*-------------------------------------------------------------------------*/ 611 612static int spidev_probe(struct spi_device *spi) 613{ 614 struct spidev_data *spidev; 615 int status; 616 unsigned long minor; 617 618 /* Allocate driver data */ 619 spidev = kzalloc(sizeof(*spidev), GFP_KERNEL); 620 if (!spidev) 621 return -ENOMEM; 622 623 /* Initialize the driver data */ 624 spidev->spi = spi; 625 spin_lock_init(&spidev->spi_lock); 626 mutex_init(&spidev->buf_lock); 627 628 INIT_LIST_HEAD(&spidev->device_entry); 629 630 /* If we can allocate a minor number, hook up this device. 631 * Reusing minors is fine so long as udev or mdev is working. 632 */ 633 mutex_lock(&device_list_lock); 634 minor = find_first_zero_bit(minors, N_SPI_MINORS); 635 if (minor < N_SPI_MINORS) { 636 struct device *dev; 637 638 spidev->devt = MKDEV(SPIDEV_MAJOR, minor); 639 dev = device_create(spidev_class, &spi->dev, spidev->devt, 640 spidev, "spidev%d.%d", 641 spi->master->bus_num, spi->chip_select); 642 status = PTR_ERR_OR_ZERO(dev); 643 } else { 644 dev_dbg(&spi->dev, "no minor number available!\n"); 645 status = -ENODEV; 646 } 647 if (status == 0) { 648 set_bit(minor, minors); 649 list_add(&spidev->device_entry, &device_list); 650 } 651 mutex_unlock(&device_list_lock); 652 653 if (status == 0) 654 spi_set_drvdata(spi, spidev); 655 else 656 kfree(spidev); 657 658 return status; 659} 660 661static int spidev_remove(struct spi_device *spi) 662{ 663 struct spidev_data *spidev = spi_get_drvdata(spi); 664 665 /* make sure ops on existing fds can abort cleanly */ 666 spin_lock_irq(&spidev->spi_lock); 667 spidev->spi = NULL; 668 spin_unlock_irq(&spidev->spi_lock); 669 670 /* prevent new opens */ 671 mutex_lock(&device_list_lock); 672 list_del(&spidev->device_entry); 673 device_destroy(spidev_class, spidev->devt); 674 clear_bit(MINOR(spidev->devt), minors); 675 if (spidev->users == 0) 676 kfree(spidev); 677 mutex_unlock(&device_list_lock); 678 679 return 0; 680} 681 682static const struct of_device_id spidev_dt_ids[] = { 683 { .compatible = "rohm,dh2228fv" }, 684 {}, 685}; 686 687MODULE_DEVICE_TABLE(of, spidev_dt_ids); 688 689static struct spi_driver spidev_spi_driver = { 690 .driver = { 691 .name = "spidev", 692 .owner = THIS_MODULE, 693 .of_match_table = of_match_ptr(spidev_dt_ids), 694 }, 695 .probe = spidev_probe, 696 .remove = spidev_remove, 697 698 /* NOTE: suspend/resume methods are not necessary here. 699 * We don't do anything except pass the requests to/from 700 * the underlying controller. The refrigerator handles 701 * most issues; the controller driver handles the rest. 702 */ 703}; 704 705/*-------------------------------------------------------------------------*/ 706 707static int __init spidev_init(void) 708{ 709 int status; 710 711 /* Claim our 256 reserved device numbers. Then register a class 712 * that will key udev/mdev to add/remove /dev nodes. Last, register 713 * the driver which manages those device numbers. 714 */ 715 BUILD_BUG_ON(N_SPI_MINORS > 256); 716 status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops); 717 if (status < 0) 718 return status; 719 720 spidev_class = class_create(THIS_MODULE, "spidev"); 721 if (IS_ERR(spidev_class)) { 722 unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); 723 return PTR_ERR(spidev_class); 724 } 725 726 status = spi_register_driver(&spidev_spi_driver); 727 if (status < 0) { 728 class_destroy(spidev_class); 729 unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); 730 } 731 return status; 732} 733module_init(spidev_init); 734 735static void __exit spidev_exit(void) 736{ 737 spi_unregister_driver(&spidev_spi_driver); 738 class_destroy(spidev_class); 739 unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); 740} 741module_exit(spidev_exit); 742 743MODULE_AUTHOR("Andrea Paterniani, <a.paterniani@swapp-eng.it>"); 744MODULE_DESCRIPTION("User mode SPI device interface"); 745MODULE_LICENSE("GPL"); 746MODULE_ALIAS("spi:spidev"); 747