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