907 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Simple synchronous userspace interface to SPI devices4 *5 * Copyright (C) 2006 SWAPP6 * Andrea Paterniani <a.paterniani@swapp-eng.it>7 * Copyright (C) 2007 David Brownell (simplification, cleanup)8 */9 10#include <linux/init.h>11#include <linux/ioctl.h>12#include <linux/fs.h>13#include <linux/device.h>14#include <linux/err.h>15#include <linux/list.h>16#include <linux/errno.h>17#include <linux/mod_devicetable.h>18#include <linux/module.h>19#include <linux/mutex.h>20#include <linux/property.h>21#include <linux/slab.h>22#include <linux/compat.h>23 24#include <linux/spi/spi.h>25#include <linux/spi/spidev.h>26 27#include <linux/uaccess.h>28 29 30/*31 * This supports access to SPI devices using normal userspace I/O calls.32 * Note that while traditional UNIX/POSIX I/O semantics are half duplex,33 * and often mask message boundaries, full SPI support requires full duplex34 * transfers. There are several kinds of internal message boundaries to35 * handle chipselect management and other protocol options.36 *37 * SPI has a character major number assigned. We allocate minor numbers38 * dynamically using a bitmask. You must use hotplug tools, such as udev39 * (or mdev with busybox) to create and destroy the /dev/spidevB.C device40 * nodes, since there is no fixed association of minor numbers with any41 * particular SPI bus or device.42 */43#define SPIDEV_MAJOR 153 /* assigned */44#define N_SPI_MINORS 32 /* ... up to 256 */45 46static DECLARE_BITMAP(minors, N_SPI_MINORS);47 48static_assert(N_SPI_MINORS > 0 && N_SPI_MINORS <= 256);49 50/* Bit masks for spi_device.mode management. Note that incorrect51 * settings for some settings can cause *lots* of trouble for other52 * devices on a shared bus:53 *54 * - CS_HIGH ... this device will be active when it shouldn't be55 * - 3WIRE ... when active, it won't behave as it should56 * - NO_CS ... there will be no explicit message boundaries; this57 * is completely incompatible with the shared bus model58 * - READY ... transfers may proceed when they shouldn't.59 *60 * REVISIT should changing those flags be privileged?61 */62#define SPI_MODE_MASK (SPI_MODE_X_MASK | SPI_CS_HIGH \63 | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \64 | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \65 | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL \66 | SPI_RX_QUAD | SPI_RX_OCTAL \67 | SPI_RX_CPHA_FLIP | SPI_3WIRE_HIZ \68 | SPI_MOSI_IDLE_LOW)69 70struct spidev_data {71 dev_t devt;72 struct mutex spi_lock;73 struct spi_device *spi;74 struct list_head device_entry;75 76 /* TX/RX buffers are NULL unless this device is open (users > 0) */77 struct mutex buf_lock;78 unsigned users;79 u8 *tx_buffer;80 u8 *rx_buffer;81 u32 speed_hz;82};83 84static LIST_HEAD(device_list);85static DEFINE_MUTEX(device_list_lock);86 87static unsigned bufsiz = 4096;88module_param(bufsiz, uint, S_IRUGO);89MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");90 91/*-------------------------------------------------------------------------*/92 93static ssize_t94spidev_sync_unlocked(struct spi_device *spi, struct spi_message *message)95{96 ssize_t status;97 98 status = spi_sync(spi, message);99 if (status == 0)100 status = message->actual_length;101 102 return status;103}104 105static ssize_t106spidev_sync(struct spidev_data *spidev, struct spi_message *message)107{108 ssize_t status;109 struct spi_device *spi;110 111 mutex_lock(&spidev->spi_lock);112 spi = spidev->spi;113 114 if (spi == NULL)115 status = -ESHUTDOWN;116 else117 status = spidev_sync_unlocked(spi, message);118 119 mutex_unlock(&spidev->spi_lock);120 return status;121}122 123static inline ssize_t124spidev_sync_write(struct spidev_data *spidev, size_t len)125{126 struct spi_transfer t = {127 .tx_buf = spidev->tx_buffer,128 .len = len,129 .speed_hz = spidev->speed_hz,130 };131 struct spi_message m;132 133 spi_message_init(&m);134 spi_message_add_tail(&t, &m);135 return spidev_sync(spidev, &m);136}137 138static inline ssize_t139spidev_sync_read(struct spidev_data *spidev, size_t len)140{141 struct spi_transfer t = {142 .rx_buf = spidev->rx_buffer,143 .len = len,144 .speed_hz = spidev->speed_hz,145 };146 struct spi_message m;147 148 spi_message_init(&m);149 spi_message_add_tail(&t, &m);150 return spidev_sync(spidev, &m);151}152 153/*-------------------------------------------------------------------------*/154 155/* Read-only message with current device setup */156static ssize_t157spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)158{159 struct spidev_data *spidev;160 ssize_t status;161 162 /* chipselect only toggles at start or end of operation */163 if (count > bufsiz)164 return -EMSGSIZE;165 166 spidev = filp->private_data;167 168 mutex_lock(&spidev->buf_lock);169 status = spidev_sync_read(spidev, count);170 if (status > 0) {171 unsigned long missing;172 173 missing = copy_to_user(buf, spidev->rx_buffer, status);174 if (missing == status)175 status = -EFAULT;176 else177 status = status - missing;178 }179 mutex_unlock(&spidev->buf_lock);180 181 return status;182}183 184/* Write-only message with current device setup */185static ssize_t186spidev_write(struct file *filp, const char __user *buf,187 size_t count, loff_t *f_pos)188{189 struct spidev_data *spidev;190 ssize_t status;191 unsigned long missing;192 193 /* chipselect only toggles at start or end of operation */194 if (count > bufsiz)195 return -EMSGSIZE;196 197 spidev = filp->private_data;198 199 mutex_lock(&spidev->buf_lock);200 missing = copy_from_user(spidev->tx_buffer, buf, count);201 if (missing == 0)202 status = spidev_sync_write(spidev, count);203 else204 status = -EFAULT;205 mutex_unlock(&spidev->buf_lock);206 207 return status;208}209 210static int spidev_message(struct spidev_data *spidev,211 struct spi_ioc_transfer *u_xfers, unsigned n_xfers)212{213 struct spi_message msg;214 struct spi_transfer *k_xfers;215 struct spi_transfer *k_tmp;216 struct spi_ioc_transfer *u_tmp;217 unsigned n, total, tx_total, rx_total;218 u8 *tx_buf, *rx_buf;219 int status = -EFAULT;220 221 spi_message_init(&msg);222 k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);223 if (k_xfers == NULL)224 return -ENOMEM;225 226 /* Construct spi_message, copying any tx data to bounce buffer.227 * We walk the array of user-provided transfers, using each one228 * to initialize a kernel version of the same transfer.229 */230 tx_buf = spidev->tx_buffer;231 rx_buf = spidev->rx_buffer;232 total = 0;233 tx_total = 0;234 rx_total = 0;235 for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;236 n;237 n--, k_tmp++, u_tmp++) {238 /* Ensure that also following allocations from rx_buf/tx_buf will meet239 * DMA alignment requirements.240 */241 unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_DMA_MINALIGN);242 243 k_tmp->len = u_tmp->len;244 245 total += k_tmp->len;246 /* Since the function returns the total length of transfers247 * on success, restrict the total to positive int values to248 * avoid the return value looking like an error. Also check249 * each transfer length to avoid arithmetic overflow.250 */251 if (total > INT_MAX || k_tmp->len > INT_MAX) {252 status = -EMSGSIZE;253 goto done;254 }255 256 if (u_tmp->rx_buf) {257 /* this transfer needs space in RX bounce buffer */258 rx_total += len_aligned;259 if (rx_total > bufsiz) {260 status = -EMSGSIZE;261 goto done;262 }263 k_tmp->rx_buf = rx_buf;264 rx_buf += len_aligned;265 }266 if (u_tmp->tx_buf) {267 /* this transfer needs space in TX bounce buffer */268 tx_total += len_aligned;269 if (tx_total > bufsiz) {270 status = -EMSGSIZE;271 goto done;272 }273 k_tmp->tx_buf = tx_buf;274 if (copy_from_user(tx_buf, (const u8 __user *)275 (uintptr_t) u_tmp->tx_buf,276 u_tmp->len))277 goto done;278 tx_buf += len_aligned;279 }280 281 k_tmp->cs_change = !!u_tmp->cs_change;282 k_tmp->tx_nbits = u_tmp->tx_nbits;283 k_tmp->rx_nbits = u_tmp->rx_nbits;284 k_tmp->bits_per_word = u_tmp->bits_per_word;285 k_tmp->delay.value = u_tmp->delay_usecs;286 k_tmp->delay.unit = SPI_DELAY_UNIT_USECS;287 k_tmp->speed_hz = u_tmp->speed_hz;288 k_tmp->word_delay.value = u_tmp->word_delay_usecs;289 k_tmp->word_delay.unit = SPI_DELAY_UNIT_USECS;290 if (!k_tmp->speed_hz)291 k_tmp->speed_hz = spidev->speed_hz;292#ifdef VERBOSE293 dev_dbg(&spidev->spi->dev,294 " xfer len %u %s%s%s%dbits %u usec %u usec %uHz\n",295 k_tmp->len,296 k_tmp->rx_buf ? "rx " : "",297 k_tmp->tx_buf ? "tx " : "",298 k_tmp->cs_change ? "cs " : "",299 k_tmp->bits_per_word ? : spidev->spi->bits_per_word,300 k_tmp->delay.value,301 k_tmp->word_delay.value,302 k_tmp->speed_hz ? : spidev->spi->max_speed_hz);303#endif304 spi_message_add_tail(k_tmp, &msg);305 }306 307 status = spidev_sync_unlocked(spidev->spi, &msg);308 if (status < 0)309 goto done;310 311 /* copy any rx data out of bounce buffer */312 for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;313 n;314 n--, k_tmp++, u_tmp++) {315 if (u_tmp->rx_buf) {316 if (copy_to_user((u8 __user *)317 (uintptr_t) u_tmp->rx_buf, k_tmp->rx_buf,318 u_tmp->len)) {319 status = -EFAULT;320 goto done;321 }322 }323 }324 status = total;325 326done:327 kfree(k_xfers);328 return status;329}330 331static struct spi_ioc_transfer *332spidev_get_ioc_message(unsigned int cmd, struct spi_ioc_transfer __user *u_ioc,333 unsigned *n_ioc)334{335 u32 tmp;336 337 /* Check type, command number and direction */338 if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC339 || _IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0))340 || _IOC_DIR(cmd) != _IOC_WRITE)341 return ERR_PTR(-ENOTTY);342 343 tmp = _IOC_SIZE(cmd);344 if ((tmp % sizeof(struct spi_ioc_transfer)) != 0)345 return ERR_PTR(-EINVAL);346 *n_ioc = tmp / sizeof(struct spi_ioc_transfer);347 if (*n_ioc == 0)348 return NULL;349 350 /* copy into scratch area */351 return memdup_user(u_ioc, tmp);352}353 354static long355spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)356{357 int retval = 0;358 struct spidev_data *spidev;359 struct spi_device *spi;360 struct spi_controller *ctlr;361 u32 tmp;362 unsigned n_ioc;363 struct spi_ioc_transfer *ioc;364 365 /* Check type and command number */366 if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)367 return -ENOTTY;368 369 /* guard against device removal before, or while,370 * we issue this ioctl.371 */372 spidev = filp->private_data;373 mutex_lock(&spidev->spi_lock);374 spi = spi_dev_get(spidev->spi);375 if (spi == NULL) {376 mutex_unlock(&spidev->spi_lock);377 return -ESHUTDOWN;378 }379 380 ctlr = spi->controller;381 382 /* use the buffer lock here for triple duty:383 * - prevent I/O (from us) so calling spi_setup() is safe;384 * - prevent concurrent SPI_IOC_WR_* from morphing385 * data fields while SPI_IOC_RD_* reads them;386 * - SPI_IOC_MESSAGE needs the buffer locked "normally".387 */388 mutex_lock(&spidev->buf_lock);389 390 switch (cmd) {391 /* read requests */392 case SPI_IOC_RD_MODE:393 case SPI_IOC_RD_MODE32:394 tmp = spi->mode & SPI_MODE_MASK;395 396 if (ctlr->use_gpio_descriptors && spi_get_csgpiod(spi, 0))397 tmp &= ~SPI_CS_HIGH;398 399 if (cmd == SPI_IOC_RD_MODE)400 retval = put_user(tmp, (__u8 __user *)arg);401 else402 retval = put_user(tmp, (__u32 __user *)arg);403 break;404 case SPI_IOC_RD_LSB_FIRST:405 retval = put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,406 (__u8 __user *)arg);407 break;408 case SPI_IOC_RD_BITS_PER_WORD:409 retval = put_user(spi->bits_per_word, (__u8 __user *)arg);410 break;411 case SPI_IOC_RD_MAX_SPEED_HZ:412 retval = put_user(spidev->speed_hz, (__u32 __user *)arg);413 break;414 415 /* write requests */416 case SPI_IOC_WR_MODE:417 case SPI_IOC_WR_MODE32:418 if (cmd == SPI_IOC_WR_MODE)419 retval = get_user(tmp, (u8 __user *)arg);420 else421 retval = get_user(tmp, (u32 __user *)arg);422 if (retval == 0) {423 u32 save = spi->mode;424 425 if (tmp & ~SPI_MODE_MASK) {426 retval = -EINVAL;427 break;428 }429 430 if (ctlr->use_gpio_descriptors && spi_get_csgpiod(spi, 0))431 tmp |= SPI_CS_HIGH;432 433 tmp |= spi->mode & ~SPI_MODE_MASK;434 spi->mode = tmp & SPI_MODE_USER_MASK;435 retval = spi_setup(spi);436 if (retval < 0)437 spi->mode = save;438 else439 dev_dbg(&spi->dev, "spi mode %x\n", tmp);440 }441 break;442 case SPI_IOC_WR_LSB_FIRST:443 retval = get_user(tmp, (__u8 __user *)arg);444 if (retval == 0) {445 u32 save = spi->mode;446 447 if (tmp)448 spi->mode |= SPI_LSB_FIRST;449 else450 spi->mode &= ~SPI_LSB_FIRST;451 retval = spi_setup(spi);452 if (retval < 0)453 spi->mode = save;454 else455 dev_dbg(&spi->dev, "%csb first\n",456 tmp ? 'l' : 'm');457 }458 break;459 case SPI_IOC_WR_BITS_PER_WORD:460 retval = get_user(tmp, (__u8 __user *)arg);461 if (retval == 0) {462 u8 save = spi->bits_per_word;463 464 spi->bits_per_word = tmp;465 retval = spi_setup(spi);466 if (retval < 0)467 spi->bits_per_word = save;468 else469 dev_dbg(&spi->dev, "%d bits per word\n", tmp);470 }471 break;472 case SPI_IOC_WR_MAX_SPEED_HZ: {473 u32 save;474 475 retval = get_user(tmp, (__u32 __user *)arg);476 if (retval)477 break;478 if (tmp == 0) {479 retval = -EINVAL;480 break;481 }482 483 save = spi->max_speed_hz;484 485 spi->max_speed_hz = tmp;486 retval = spi_setup(spi);487 if (retval == 0) {488 spidev->speed_hz = tmp;489 dev_dbg(&spi->dev, "%d Hz (max)\n", spidev->speed_hz);490 }491 492 spi->max_speed_hz = save;493 break;494 }495 default:496 /* segmented and/or full-duplex I/O request */497 /* Check message and copy into scratch area */498 ioc = spidev_get_ioc_message(cmd,499 (struct spi_ioc_transfer __user *)arg, &n_ioc);500 if (IS_ERR(ioc)) {501 retval = PTR_ERR(ioc);502 break;503 }504 if (!ioc)505 break; /* n_ioc is also 0 */506 507 /* translate to spi_message, execute */508 retval = spidev_message(spidev, ioc, n_ioc);509 kfree(ioc);510 break;511 }512 513 mutex_unlock(&spidev->buf_lock);514 spi_dev_put(spi);515 mutex_unlock(&spidev->spi_lock);516 return retval;517}518 519#ifdef CONFIG_COMPAT520static long521spidev_compat_ioc_message(struct file *filp, unsigned int cmd,522 unsigned long arg)523{524 struct spi_ioc_transfer __user *u_ioc;525 int retval = 0;526 struct spidev_data *spidev;527 struct spi_device *spi;528 unsigned n_ioc, n;529 struct spi_ioc_transfer *ioc;530 531 u_ioc = (struct spi_ioc_transfer __user *) compat_ptr(arg);532 533 /* guard against device removal before, or while,534 * we issue this ioctl.535 */536 spidev = filp->private_data;537 mutex_lock(&spidev->spi_lock);538 spi = spi_dev_get(spidev->spi);539 if (spi == NULL) {540 mutex_unlock(&spidev->spi_lock);541 return -ESHUTDOWN;542 }543 544 /* SPI_IOC_MESSAGE needs the buffer locked "normally" */545 mutex_lock(&spidev->buf_lock);546 547 /* Check message and copy into scratch area */548 ioc = spidev_get_ioc_message(cmd, u_ioc, &n_ioc);549 if (IS_ERR(ioc)) {550 retval = PTR_ERR(ioc);551 goto done;552 }553 if (!ioc)554 goto done; /* n_ioc is also 0 */555 556 /* Convert buffer pointers */557 for (n = 0; n < n_ioc; n++) {558 ioc[n].rx_buf = (uintptr_t) compat_ptr(ioc[n].rx_buf);559 ioc[n].tx_buf = (uintptr_t) compat_ptr(ioc[n].tx_buf);560 }561 562 /* translate to spi_message, execute */563 retval = spidev_message(spidev, ioc, n_ioc);564 kfree(ioc);565 566done:567 mutex_unlock(&spidev->buf_lock);568 spi_dev_put(spi);569 mutex_unlock(&spidev->spi_lock);570 return retval;571}572 573static long574spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)575{576 if (_IOC_TYPE(cmd) == SPI_IOC_MAGIC577 && _IOC_NR(cmd) == _IOC_NR(SPI_IOC_MESSAGE(0))578 && _IOC_DIR(cmd) == _IOC_WRITE)579 return spidev_compat_ioc_message(filp, cmd, arg);580 581 return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));582}583#else584#define spidev_compat_ioctl NULL585#endif /* CONFIG_COMPAT */586 587static int spidev_open(struct inode *inode, struct file *filp)588{589 struct spidev_data *spidev = NULL, *iter;590 int status = -ENXIO;591 592 mutex_lock(&device_list_lock);593 594 list_for_each_entry(iter, &device_list, device_entry) {595 if (iter->devt == inode->i_rdev) {596 status = 0;597 spidev = iter;598 break;599 }600 }601 602 if (!spidev) {603 pr_debug("spidev: nothing for minor %d\n", iminor(inode));604 goto err_find_dev;605 }606 607 if (!spidev->tx_buffer) {608 spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL);609 if (!spidev->tx_buffer) {610 status = -ENOMEM;611 goto err_find_dev;612 }613 }614 615 if (!spidev->rx_buffer) {616 spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL);617 if (!spidev->rx_buffer) {618 status = -ENOMEM;619 goto err_alloc_rx_buf;620 }621 }622 623 spidev->users++;624 filp->private_data = spidev;625 stream_open(inode, filp);626 627 mutex_unlock(&device_list_lock);628 return 0;629 630err_alloc_rx_buf:631 kfree(spidev->tx_buffer);632 spidev->tx_buffer = NULL;633err_find_dev:634 mutex_unlock(&device_list_lock);635 return status;636}637 638static int spidev_release(struct inode *inode, struct file *filp)639{640 struct spidev_data *spidev;641 int dofree;642 643 mutex_lock(&device_list_lock);644 spidev = filp->private_data;645 filp->private_data = NULL;646 647 mutex_lock(&spidev->spi_lock);648 /* ... after we unbound from the underlying device? */649 dofree = (spidev->spi == NULL);650 mutex_unlock(&spidev->spi_lock);651 652 /* last close? */653 spidev->users--;654 if (!spidev->users) {655 656 kfree(spidev->tx_buffer);657 spidev->tx_buffer = NULL;658 659 kfree(spidev->rx_buffer);660 spidev->rx_buffer = NULL;661 662 if (dofree)663 kfree(spidev);664 else665 spidev->speed_hz = spidev->spi->max_speed_hz;666 }667#ifdef CONFIG_SPI_SLAVE668 if (!dofree)669 spi_target_abort(spidev->spi);670#endif671 mutex_unlock(&device_list_lock);672 673 return 0;674}675 676static const struct file_operations spidev_fops = {677 .owner = THIS_MODULE,678 /* REVISIT switch to aio primitives, so that userspace679 * gets more complete API coverage. It'll simplify things680 * too, except for the locking.681 */682 .write = spidev_write,683 .read = spidev_read,684 .unlocked_ioctl = spidev_ioctl,685 .compat_ioctl = spidev_compat_ioctl,686 .open = spidev_open,687 .release = spidev_release,688};689 690/*-------------------------------------------------------------------------*/691 692/* The main reason to have this class is to make mdev/udev create the693 * /dev/spidevB.C character device nodes exposing our userspace API.694 * It also simplifies memory management.695 */696 697static const struct class spidev_class = {698 .name = "spidev",699};700 701static const struct spi_device_id spidev_spi_ids[] = {702 { .name = "bh2228fv" },703 { .name = "dh2228fv" },704 { .name = "jg10309-01" },705 { .name = "ltc2488" },706 { .name = "sx1301" },707 { .name = "bk4" },708 { .name = "dhcom-board" },709 { .name = "m53cpld" },710 { .name = "spi-petra" },711 { .name = "spi-authenta" },712 { .name = "em3581" },713 { .name = "si3210" },714 {},715};716MODULE_DEVICE_TABLE(spi, spidev_spi_ids);717 718/*719 * spidev should never be referenced in DT without a specific compatible string,720 * it is a Linux implementation thing rather than a description of the hardware.721 */722static int spidev_of_check(struct device *dev)723{724 if (device_property_match_string(dev, "compatible", "spidev") < 0)725 return 0;726 727 dev_err(dev, "spidev listed directly in DT is not supported\n");728 return -EINVAL;729}730 731static const struct of_device_id spidev_dt_ids[] = {732 { .compatible = "cisco,spi-petra", .data = &spidev_of_check },733 { .compatible = "dh,dhcom-board", .data = &spidev_of_check },734 { .compatible = "elgin,jg10309-01", .data = &spidev_of_check },735 { .compatible = "lineartechnology,ltc2488", .data = &spidev_of_check },736 { .compatible = "lwn,bk4", .data = &spidev_of_check },737 { .compatible = "menlo,m53cpld", .data = &spidev_of_check },738 { .compatible = "micron,spi-authenta", .data = &spidev_of_check },739 { .compatible = "rohm,bh2228fv", .data = &spidev_of_check },740 { .compatible = "rohm,dh2228fv", .data = &spidev_of_check },741 { .compatible = "semtech,sx1301", .data = &spidev_of_check },742 { .compatible = "silabs,em3581", .data = &spidev_of_check },743 { .compatible = "silabs,si3210", .data = &spidev_of_check },744 {},745};746MODULE_DEVICE_TABLE(of, spidev_dt_ids);747 748/* Dummy SPI devices not to be used in production systems */749static int spidev_acpi_check(struct device *dev)750{751 dev_warn(dev, "do not use this driver in production systems!\n");752 return 0;753}754 755static const struct acpi_device_id spidev_acpi_ids[] = {756 /*757 * The ACPI SPT000* devices are only meant for development and758 * testing. Systems used in production should have a proper ACPI759 * description of the connected peripheral and they should also use760 * a proper driver instead of poking directly to the SPI bus.761 */762 { "SPT0001", (kernel_ulong_t)&spidev_acpi_check },763 { "SPT0002", (kernel_ulong_t)&spidev_acpi_check },764 { "SPT0003", (kernel_ulong_t)&spidev_acpi_check },765 {},766};767MODULE_DEVICE_TABLE(acpi, spidev_acpi_ids);768 769/*-------------------------------------------------------------------------*/770 771static int spidev_probe(struct spi_device *spi)772{773 int (*match)(struct device *dev);774 struct spidev_data *spidev;775 int status;776 unsigned long minor;777 778 match = device_get_match_data(&spi->dev);779 if (match) {780 status = match(&spi->dev);781 if (status)782 return status;783 }784 785 /* Allocate driver data */786 spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);787 if (!spidev)788 return -ENOMEM;789 790 /* Initialize the driver data */791 spidev->spi = spi;792 mutex_init(&spidev->spi_lock);793 mutex_init(&spidev->buf_lock);794 795 INIT_LIST_HEAD(&spidev->device_entry);796 797 /* If we can allocate a minor number, hook up this device.798 * Reusing minors is fine so long as udev or mdev is working.799 */800 mutex_lock(&device_list_lock);801 minor = find_first_zero_bit(minors, N_SPI_MINORS);802 if (minor < N_SPI_MINORS) {803 struct device *dev;804 805 spidev->devt = MKDEV(SPIDEV_MAJOR, minor);806 dev = device_create(&spidev_class, &spi->dev, spidev->devt,807 spidev, "spidev%d.%d",808 spi->controller->bus_num, spi_get_chipselect(spi, 0));809 status = PTR_ERR_OR_ZERO(dev);810 } else {811 dev_dbg(&spi->dev, "no minor number available!\n");812 status = -ENODEV;813 }814 if (status == 0) {815 set_bit(minor, minors);816 list_add(&spidev->device_entry, &device_list);817 }818 mutex_unlock(&device_list_lock);819 820 spidev->speed_hz = spi->max_speed_hz;821 822 if (status == 0)823 spi_set_drvdata(spi, spidev);824 else825 kfree(spidev);826 827 return status;828}829 830static void spidev_remove(struct spi_device *spi)831{832 struct spidev_data *spidev = spi_get_drvdata(spi);833 834 /* prevent new opens */835 mutex_lock(&device_list_lock);836 /* make sure ops on existing fds can abort cleanly */837 mutex_lock(&spidev->spi_lock);838 spidev->spi = NULL;839 mutex_unlock(&spidev->spi_lock);840 841 list_del(&spidev->device_entry);842 device_destroy(&spidev_class, spidev->devt);843 clear_bit(MINOR(spidev->devt), minors);844 if (spidev->users == 0)845 kfree(spidev);846 mutex_unlock(&device_list_lock);847}848 849static struct spi_driver spidev_spi_driver = {850 .driver = {851 .name = "spidev",852 .of_match_table = spidev_dt_ids,853 .acpi_match_table = spidev_acpi_ids,854 },855 .probe = spidev_probe,856 .remove = spidev_remove,857 .id_table = spidev_spi_ids,858 859 /* NOTE: suspend/resume methods are not necessary here.860 * We don't do anything except pass the requests to/from861 * the underlying controller. The refrigerator handles862 * most issues; the controller driver handles the rest.863 */864};865 866/*-------------------------------------------------------------------------*/867 868static int __init spidev_init(void)869{870 int status;871 872 /* Claim our 256 reserved device numbers. Then register a class873 * that will key udev/mdev to add/remove /dev nodes. Last, register874 * the driver which manages those device numbers.875 */876 status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);877 if (status < 0)878 return status;879 880 status = class_register(&spidev_class);881 if (status) {882 unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);883 return status;884 }885 886 status = spi_register_driver(&spidev_spi_driver);887 if (status < 0) {888 class_unregister(&spidev_class);889 unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);890 }891 return status;892}893module_init(spidev_init);894 895static void __exit spidev_exit(void)896{897 spi_unregister_driver(&spidev_spi_driver);898 class_unregister(&spidev_class);899 unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);900}901module_exit(spidev_exit);902 903MODULE_AUTHOR("Andrea Paterniani, <a.paterniani@swapp-eng.it>");904MODULE_DESCRIPTION("User mode SPI device interface");905MODULE_LICENSE("GPL");906MODULE_ALIAS("spi:spidev");907