• Home
  • Raw
  • Download

Lines Matching +full:spi +full:- +full:device

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Simple synchronous userspace interface to SPI devices
6 * Andrea Paterniani <a.paterniani@swapp-eng.it>
14 #include <linux/device.h>
25 #include <linux/spi/spi.h>
26 #include <linux/spi/spidev.h>
32 * This supports access to SPI devices using normal userspace I/O calls.
34 * and often mask message boundaries, full SPI support requires full duplex
38 * SPI has a character major number assigned. We allocate minor numbers
40 * (or mdev with busybox) to create and destroy the /dev/spidevB.C device
42 * particular SPI bus or device.
54 * - CS_HIGH ... this device will be active when it shouldn't be
55 * - 3WIRE ... when active, it won't behave as it should
56 * - NO_CS ... there will be no explicit message boundaries; this
58 * - READY ... transfers may proceed when they shouldn't.
71 struct spi_device *spi; member
74 /* TX/RX buffers are NULL unless this device is open (users > 0) */
87 MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message");
89 /*-------------------------------------------------------------------------*/
95 struct spi_device *spi; in spidev_sync() local
97 spin_lock_irq(&spidev->spi_lock); in spidev_sync()
98 spi = spidev->spi; in spidev_sync()
99 spin_unlock_irq(&spidev->spi_lock); in spidev_sync()
101 if (spi == NULL) in spidev_sync()
102 status = -ESHUTDOWN; in spidev_sync()
104 status = spi_sync(spi, message); in spidev_sync()
107 status = message->actual_length; in spidev_sync()
116 .tx_buf = spidev->tx_buffer, in spidev_sync_write()
118 .speed_hz = spidev->speed_hz, in spidev_sync_write()
131 .rx_buf = spidev->rx_buffer, in spidev_sync_read()
133 .speed_hz = spidev->speed_hz, in spidev_sync_read()
142 /*-------------------------------------------------------------------------*/
144 /* Read-only message with current device setup */
153 return -EMSGSIZE; in spidev_read()
155 spidev = filp->private_data; in spidev_read()
157 mutex_lock(&spidev->buf_lock); in spidev_read()
162 missing = copy_to_user(buf, spidev->rx_buffer, status); in spidev_read()
164 status = -EFAULT; in spidev_read()
166 status = status - missing; in spidev_read()
168 mutex_unlock(&spidev->buf_lock); in spidev_read()
173 /* Write-only message with current device setup */
184 return -EMSGSIZE; in spidev_write()
186 spidev = filp->private_data; in spidev_write()
188 mutex_lock(&spidev->buf_lock); in spidev_write()
189 missing = copy_from_user(spidev->tx_buffer, buf, count); in spidev_write()
193 status = -EFAULT; in spidev_write()
194 mutex_unlock(&spidev->buf_lock); in spidev_write()
208 int status = -EFAULT; in spidev_message()
213 return -ENOMEM; in spidev_message()
216 * We walk the array of user-provided transfers, using each one in spidev_message()
219 tx_buf = spidev->tx_buffer; in spidev_message()
220 rx_buf = spidev->rx_buffer; in spidev_message()
226 n--, k_tmp++, u_tmp++) { in spidev_message()
230 unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_KMALLOC_MINALIGN); in spidev_message()
232 k_tmp->len = u_tmp->len; in spidev_message()
234 total += k_tmp->len; in spidev_message()
240 if (total > INT_MAX || k_tmp->len > INT_MAX) { in spidev_message()
241 status = -EMSGSIZE; in spidev_message()
245 if (u_tmp->rx_buf) { in spidev_message()
249 status = -EMSGSIZE; in spidev_message()
252 k_tmp->rx_buf = rx_buf; in spidev_message()
255 if (u_tmp->tx_buf) { in spidev_message()
259 status = -EMSGSIZE; in spidev_message()
262 k_tmp->tx_buf = tx_buf; in spidev_message()
264 (uintptr_t) u_tmp->tx_buf, in spidev_message()
265 u_tmp->len)) in spidev_message()
270 k_tmp->cs_change = !!u_tmp->cs_change; in spidev_message()
271 k_tmp->tx_nbits = u_tmp->tx_nbits; in spidev_message()
272 k_tmp->rx_nbits = u_tmp->rx_nbits; in spidev_message()
273 k_tmp->bits_per_word = u_tmp->bits_per_word; in spidev_message()
274 k_tmp->delay.value = u_tmp->delay_usecs; in spidev_message()
275 k_tmp->delay.unit = SPI_DELAY_UNIT_USECS; in spidev_message()
276 k_tmp->speed_hz = u_tmp->speed_hz; in spidev_message()
277 k_tmp->word_delay.value = u_tmp->word_delay_usecs; in spidev_message()
278 k_tmp->word_delay.unit = SPI_DELAY_UNIT_USECS; in spidev_message()
279 if (!k_tmp->speed_hz) in spidev_message()
280 k_tmp->speed_hz = spidev->speed_hz; in spidev_message()
282 dev_dbg(&spidev->spi->dev, in spidev_message()
284 k_tmp->len, in spidev_message()
285 k_tmp->rx_buf ? "rx " : "", in spidev_message()
286 k_tmp->tx_buf ? "tx " : "", in spidev_message()
287 k_tmp->cs_change ? "cs " : "", in spidev_message()
288 k_tmp->bits_per_word ? : spidev->spi->bits_per_word, in spidev_message()
289 k_tmp->delay.value, in spidev_message()
290 k_tmp->word_delay.value, in spidev_message()
291 k_tmp->speed_hz ? : spidev->spi->max_speed_hz); in spidev_message()
303 n--, k_tmp++, u_tmp++) { in spidev_message()
304 if (u_tmp->rx_buf) { in spidev_message()
306 (uintptr_t) u_tmp->rx_buf, k_tmp->rx_buf, in spidev_message()
307 u_tmp->len)) { in spidev_message()
308 status = -EFAULT; in spidev_message()
330 return ERR_PTR(-ENOTTY); in spidev_get_ioc_message()
334 return ERR_PTR(-EINVAL); in spidev_get_ioc_message()
348 struct spi_device *spi; in spidev_ioctl() local
355 return -ENOTTY; in spidev_ioctl()
357 /* guard against device removal before, or while, in spidev_ioctl()
360 spidev = filp->private_data; in spidev_ioctl()
361 spin_lock_irq(&spidev->spi_lock); in spidev_ioctl()
362 spi = spi_dev_get(spidev->spi); in spidev_ioctl()
363 spin_unlock_irq(&spidev->spi_lock); in spidev_ioctl()
365 if (spi == NULL) in spidev_ioctl()
366 return -ESHUTDOWN; in spidev_ioctl()
369 * - prevent I/O (from us) so calling spi_setup() is safe; in spidev_ioctl()
370 * - prevent concurrent SPI_IOC_WR_* from morphing in spidev_ioctl()
372 * - SPI_IOC_MESSAGE needs the buffer locked "normally". in spidev_ioctl()
374 mutex_lock(&spidev->buf_lock); in spidev_ioctl()
380 tmp = spi->mode; in spidev_ioctl()
383 struct spi_controller *ctlr = spi->controller; in spidev_ioctl()
385 if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && in spidev_ioctl()
386 ctlr->cs_gpiods[spi->chip_select]) in spidev_ioctl()
398 retval = put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, in spidev_ioctl()
402 retval = put_user(spi->bits_per_word, (__u8 __user *)arg); in spidev_ioctl()
405 retval = put_user(spidev->speed_hz, (__u32 __user *)arg); in spidev_ioctl()
416 struct spi_controller *ctlr = spi->controller; in spidev_ioctl()
417 u32 save = spi->mode; in spidev_ioctl()
420 retval = -EINVAL; in spidev_ioctl()
424 if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && in spidev_ioctl()
425 ctlr->cs_gpiods[spi->chip_select]) in spidev_ioctl()
428 tmp |= spi->mode & ~SPI_MODE_MASK; in spidev_ioctl()
429 spi->mode = (u16)tmp; in spidev_ioctl()
430 retval = spi_setup(spi); in spidev_ioctl()
432 spi->mode = save; in spidev_ioctl()
434 dev_dbg(&spi->dev, "spi mode %x\n", tmp); in spidev_ioctl()
440 u32 save = spi->mode; in spidev_ioctl()
443 spi->mode |= SPI_LSB_FIRST; in spidev_ioctl()
445 spi->mode &= ~SPI_LSB_FIRST; in spidev_ioctl()
446 retval = spi_setup(spi); in spidev_ioctl()
448 spi->mode = save; in spidev_ioctl()
450 dev_dbg(&spi->dev, "%csb first\n", in spidev_ioctl()
457 u8 save = spi->bits_per_word; in spidev_ioctl()
459 spi->bits_per_word = tmp; in spidev_ioctl()
460 retval = spi_setup(spi); in spidev_ioctl()
462 spi->bits_per_word = save; in spidev_ioctl()
464 dev_dbg(&spi->dev, "%d bits per word\n", tmp); in spidev_ioctl()
470 u32 save = spi->max_speed_hz; in spidev_ioctl()
472 spi->max_speed_hz = tmp; in spidev_ioctl()
473 retval = spi_setup(spi); in spidev_ioctl()
475 spidev->speed_hz = tmp; in spidev_ioctl()
476 dev_dbg(&spi->dev, "%d Hz (max)\n", in spidev_ioctl()
477 spidev->speed_hz); in spidev_ioctl()
479 spi->max_speed_hz = save; in spidev_ioctl()
484 /* segmented and/or full-duplex I/O request */ in spidev_ioctl()
501 mutex_unlock(&spidev->buf_lock); in spidev_ioctl()
502 spi_dev_put(spi); in spidev_ioctl()
514 struct spi_device *spi; in spidev_compat_ioc_message() local
520 /* guard against device removal before, or while, in spidev_compat_ioc_message()
523 spidev = filp->private_data; in spidev_compat_ioc_message()
524 spin_lock_irq(&spidev->spi_lock); in spidev_compat_ioc_message()
525 spi = spi_dev_get(spidev->spi); in spidev_compat_ioc_message()
526 spin_unlock_irq(&spidev->spi_lock); in spidev_compat_ioc_message()
528 if (spi == NULL) in spidev_compat_ioc_message()
529 return -ESHUTDOWN; in spidev_compat_ioc_message()
532 mutex_lock(&spidev->buf_lock); in spidev_compat_ioc_message()
554 mutex_unlock(&spidev->buf_lock); in spidev_compat_ioc_message()
555 spi_dev_put(spi); in spidev_compat_ioc_message()
576 int status = -ENXIO; in spidev_open()
581 if (spidev->devt == inode->i_rdev) { in spidev_open()
592 if (!spidev->tx_buffer) { in spidev_open()
593 spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL); in spidev_open()
594 if (!spidev->tx_buffer) { in spidev_open()
595 status = -ENOMEM; in spidev_open()
600 if (!spidev->rx_buffer) { in spidev_open()
601 spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL); in spidev_open()
602 if (!spidev->rx_buffer) { in spidev_open()
603 status = -ENOMEM; in spidev_open()
608 spidev->users++; in spidev_open()
609 filp->private_data = spidev; in spidev_open()
616 kfree(spidev->tx_buffer); in spidev_open()
617 spidev->tx_buffer = NULL; in spidev_open()
629 spidev = filp->private_data; in spidev_release()
630 filp->private_data = NULL; in spidev_release()
632 spin_lock_irq(&spidev->spi_lock); in spidev_release()
633 /* ... after we unbound from the underlying device? */ in spidev_release()
634 dofree = (spidev->spi == NULL); in spidev_release()
635 spin_unlock_irq(&spidev->spi_lock); in spidev_release()
638 spidev->users--; in spidev_release()
639 if (!spidev->users) { in spidev_release()
641 kfree(spidev->tx_buffer); in spidev_release()
642 spidev->tx_buffer = NULL; in spidev_release()
644 kfree(spidev->rx_buffer); in spidev_release()
645 spidev->rx_buffer = NULL; in spidev_release()
650 spidev->speed_hz = spidev->spi->max_speed_hz; in spidev_release()
654 spi_slave_abort(spidev->spi); in spidev_release()
676 /*-------------------------------------------------------------------------*/
679 * /dev/spidevB.C character device nodes exposing our userspace API.
692 { .compatible = "dh,dhcom-board" },
701 /* Dummy SPI devices not to be used in production systems */
709 * a proper driver instead of poking directly to the SPI bus.
718 static void spidev_probe_acpi(struct spi_device *spi) in spidev_probe_acpi() argument
722 if (!has_acpi_companion(&spi->dev)) in spidev_probe_acpi()
725 id = acpi_match_device(spidev_acpi_ids, &spi->dev); in spidev_probe_acpi()
729 if (id->driver_data == SPIDEV_ACPI_DUMMY) in spidev_probe_acpi()
730 dev_warn(&spi->dev, "do not use this driver in production systems!\n"); in spidev_probe_acpi()
733 static inline void spidev_probe_acpi(struct spi_device *spi) {} in spidev_probe_acpi() argument
736 /*-------------------------------------------------------------------------*/
738 static int spidev_probe(struct spi_device *spi) in spidev_probe() argument
749 WARN(spi->dev.of_node && in spidev_probe()
750 of_device_is_compatible(spi->dev.of_node, "spidev"), in spidev_probe()
751 "%pOF: buggy DT: spidev listed directly in DT\n", spi->dev.of_node); in spidev_probe()
753 spidev_probe_acpi(spi); in spidev_probe()
758 return -ENOMEM; in spidev_probe()
761 spidev->spi = spi; in spidev_probe()
762 spin_lock_init(&spidev->spi_lock); in spidev_probe()
763 mutex_init(&spidev->buf_lock); in spidev_probe()
765 INIT_LIST_HEAD(&spidev->device_entry); in spidev_probe()
767 /* If we can allocate a minor number, hook up this device. in spidev_probe()
773 struct device *dev; in spidev_probe()
775 spidev->devt = MKDEV(SPIDEV_MAJOR, minor); in spidev_probe()
776 dev = device_create(spidev_class, &spi->dev, spidev->devt, in spidev_probe()
778 spi->master->bus_num, spi->chip_select); in spidev_probe()
781 dev_dbg(&spi->dev, "no minor number available!\n"); in spidev_probe()
782 status = -ENODEV; in spidev_probe()
786 list_add(&spidev->device_entry, &device_list); in spidev_probe()
790 spidev->speed_hz = spi->max_speed_hz; in spidev_probe()
793 spi_set_drvdata(spi, spidev); in spidev_probe()
800 static int spidev_remove(struct spi_device *spi) in spidev_remove() argument
802 struct spidev_data *spidev = spi_get_drvdata(spi); in spidev_remove()
807 spin_lock_irq(&spidev->spi_lock); in spidev_remove()
808 spidev->spi = NULL; in spidev_remove()
809 spin_unlock_irq(&spidev->spi_lock); in spidev_remove()
811 list_del(&spidev->device_entry); in spidev_remove()
812 device_destroy(spidev_class, spidev->devt); in spidev_remove()
813 clear_bit(MINOR(spidev->devt), minors); in spidev_remove()
814 if (spidev->users == 0) in spidev_remove()
837 /*-------------------------------------------------------------------------*/
843 /* Claim our 256 reserved device numbers. Then register a class in spidev_init()
845 * the driver which manages those device numbers. in spidev_init()
848 status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops); in spidev_init()
875 MODULE_AUTHOR("Andrea Paterniani, <a.paterniani@swapp-eng.it>");
876 MODULE_DESCRIPTION("User mode SPI device interface");
878 MODULE_ALIAS("spi:spidev");