diff options
Diffstat (limited to 'drivers/spi/spidev.c')
| -rw-r--r-- | drivers/spi/spidev.c | 117 |
1 files changed, 71 insertions, 46 deletions
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 1935ca613447..9a0160f6dc3d 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -64,7 +64,8 @@ static_assert(N_SPI_MINORS > 0 && N_SPI_MINORS <= 256); | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \ | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL \ | SPI_RX_QUAD | SPI_RX_OCTAL \ - | SPI_RX_CPHA_FLIP) + | SPI_RX_CPHA_FLIP | SPI_3WIRE_HIZ \ + | SPI_MOSI_IDLE_LOW) struct spidev_data { dev_t devt; @@ -90,9 +91,21 @@ MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message"); /*-------------------------------------------------------------------------*/ static ssize_t +spidev_sync_unlocked(struct spi_device *spi, struct spi_message *message) +{ + ssize_t status; + + status = spi_sync(spi, message); + if (status == 0) + status = message->actual_length; + + return status; +} + +static ssize_t spidev_sync(struct spidev_data *spidev, struct spi_message *message) { - int status; + ssize_t status; struct spi_device *spi; mutex_lock(&spidev->spi_lock); @@ -101,10 +114,7 @@ spidev_sync(struct spidev_data *spidev, struct spi_message *message) if (spi == NULL) status = -ESHUTDOWN; else - status = spi_sync(spi, message); - - if (status == 0) - status = message->actual_length; + status = spidev_sync_unlocked(spi, message); mutex_unlock(&spidev->spi_lock); return status; @@ -228,7 +238,7 @@ static int spidev_message(struct spidev_data *spidev, /* Ensure that also following allocations from rx_buf/tx_buf will meet * DMA alignment requirements. */ - unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_KMALLOC_MINALIGN); + unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_DMA_MINALIGN); k_tmp->len = u_tmp->len; @@ -294,7 +304,7 @@ static int spidev_message(struct spidev_data *spidev, spi_message_add_tail(k_tmp, &msg); } - status = spidev_sync(spidev, &msg); + status = spidev_sync_unlocked(spidev->spi, &msg); if (status < 0) goto done; @@ -347,6 +357,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) int retval = 0; struct spidev_data *spidev; struct spi_device *spi; + struct spi_controller *ctlr; u32 tmp; unsigned n_ioc; struct spi_ioc_transfer *ioc; @@ -366,6 +377,8 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -ESHUTDOWN; } + ctlr = spi->controller; + /* use the buffer lock here for triple duty: * - prevent I/O (from us) so calling spi_setup() is safe; * - prevent concurrent SPI_IOC_WR_* from morphing @@ -378,22 +391,15 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* read requests */ case SPI_IOC_RD_MODE: case SPI_IOC_RD_MODE32: - tmp = spi->mode; + tmp = spi->mode & SPI_MODE_MASK; - { - struct spi_controller *ctlr = spi->controller; - - if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && - ctlr->cs_gpiods[spi->chip_select]) - tmp &= ~SPI_CS_HIGH; - } + if (ctlr->use_gpio_descriptors && spi_get_csgpiod(spi, 0)) + tmp &= ~SPI_CS_HIGH; if (cmd == SPI_IOC_RD_MODE) - retval = put_user(tmp & SPI_MODE_MASK, - (__u8 __user *)arg); + retval = put_user(tmp, (__u8 __user *)arg); else - retval = put_user(tmp & SPI_MODE_MASK, - (__u32 __user *)arg); + retval = put_user(tmp, (__u32 __user *)arg); break; case SPI_IOC_RD_LSB_FIRST: retval = put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, @@ -414,7 +420,6 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) else retval = get_user(tmp, (u32 __user *)arg); if (retval == 0) { - struct spi_controller *ctlr = spi->controller; u32 save = spi->mode; if (tmp & ~SPI_MODE_MASK) { @@ -422,8 +427,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } - if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && - ctlr->cs_gpiods[spi->chip_select]) + if (ctlr->use_gpio_descriptors && spi_get_csgpiod(spi, 0)) tmp |= SPI_CS_HIGH; tmp |= spi->mode & ~SPI_MODE_MASK; @@ -662,7 +666,7 @@ static int spidev_release(struct inode *inode, struct file *filp) } #ifdef CONFIG_SPI_SLAVE if (!dofree) - spi_slave_abort(spidev->spi); + spi_target_abort(spidev->spi); #endif mutex_unlock(&device_list_lock); @@ -681,7 +685,6 @@ static const struct file_operations spidev_fops = { .compat_ioctl = spidev_compat_ioctl, .open = spidev_open, .release = spidev_release, - .llseek = no_llseek, }; /*-------------------------------------------------------------------------*/ @@ -691,17 +694,31 @@ static const struct file_operations spidev_fops = { * It also simplifies memory management. */ -static struct class *spidev_class; +static const struct class spidev_class = { + .name = "spidev", +}; +/* + * The spi device ids are expected to match the device names of the + * spidev_dt_ids array below. Both arrays are kept in the same ordering. + */ static const struct spi_device_id spidev_spi_ids[] = { - { .name = "dh2228fv" }, - { .name = "ltc2488" }, - { .name = "sx1301" }, - { .name = "bk4" }, - { .name = "dhcom-board" }, - { .name = "m53cpld" }, - { .name = "spi-petra" }, - { .name = "spi-authenta" }, + { .name = /* abb */ "spi-sensor" }, + { .name = /* arduino */ "unoq-mcu" }, + { .name = /* cisco */ "spi-petra" }, + { .name = /* dh */ "dhcom-board" }, + { .name = /* elgin */ "jg10309-01" }, + { .name = /* gocontroll */ "moduline-module-slot"}, + { .name = /* lineartechnology */ "ltc2488" }, + { .name = /* lwn */ "bk4" }, + { .name = /* lwn */ "bk4-spi" }, + { .name = /* menlo */ "m53cpld" }, + { .name = /* micron */ "spi-authenta" }, + { .name = /* rohm */ "bh2228fv" }, + { .name = /* rohm */ "dh2228fv" }, + { .name = /* semtech */ "sx1301" }, + { .name = /* silabs */ "em3581" }, + { .name = /* silabs */ "si3210" }, {}, }; MODULE_DEVICE_TABLE(spi, spidev_spi_ids); @@ -720,14 +737,22 @@ static int spidev_of_check(struct device *dev) } static const struct of_device_id spidev_dt_ids[] = { - { .compatible = "rohm,dh2228fv", .data = &spidev_of_check }, + { .compatible = "abb,spi-sensor", .data = &spidev_of_check }, + { .compatible = "arduino,unoq-mcu", .data = &spidev_of_check }, + { .compatible = "cisco,spi-petra", .data = &spidev_of_check }, + { .compatible = "dh,dhcom-board", .data = &spidev_of_check }, + { .compatible = "elgin,jg10309-01", .data = &spidev_of_check }, + { .compatible = "gocontroll,moduline-module-slot", .data = &spidev_of_check}, { .compatible = "lineartechnology,ltc2488", .data = &spidev_of_check }, - { .compatible = "semtech,sx1301", .data = &spidev_of_check }, { .compatible = "lwn,bk4", .data = &spidev_of_check }, - { .compatible = "dh,dhcom-board", .data = &spidev_of_check }, + { .compatible = "lwn,bk4-spi", .data = &spidev_of_check }, { .compatible = "menlo,m53cpld", .data = &spidev_of_check }, - { .compatible = "cisco,spi-petra", .data = &spidev_of_check }, { .compatible = "micron,spi-authenta", .data = &spidev_of_check }, + { .compatible = "rohm,bh2228fv", .data = &spidev_of_check }, + { .compatible = "rohm,dh2228fv", .data = &spidev_of_check }, + { .compatible = "semtech,sx1301", .data = &spidev_of_check }, + { .compatible = "silabs,em3581", .data = &spidev_of_check }, + { .compatible = "silabs,si3210", .data = &spidev_of_check }, {}, }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); @@ -790,9 +815,9 @@ static int spidev_probe(struct spi_device *spi) struct device *dev; spidev->devt = MKDEV(SPIDEV_MAJOR, minor); - dev = device_create(spidev_class, &spi->dev, spidev->devt, + dev = device_create(&spidev_class, &spi->dev, spidev->devt, spidev, "spidev%d.%d", - spi->master->bus_num, spi->chip_select); + spi->controller->bus_num, spi_get_chipselect(spi, 0)); status = PTR_ERR_OR_ZERO(dev); } else { dev_dbg(&spi->dev, "no minor number available!\n"); @@ -826,7 +851,7 @@ static void spidev_remove(struct spi_device *spi) mutex_unlock(&spidev->spi_lock); list_del(&spidev->device_entry); - device_destroy(spidev_class, spidev->devt); + device_destroy(&spidev_class, spidev->devt); clear_bit(MINOR(spidev->devt), minors); if (spidev->users == 0) kfree(spidev); @@ -864,15 +889,15 @@ static int __init spidev_init(void) if (status < 0) return status; - spidev_class = class_create(THIS_MODULE, "spidev"); - if (IS_ERR(spidev_class)) { + status = class_register(&spidev_class); + if (status) { unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); - return PTR_ERR(spidev_class); + return status; } status = spi_register_driver(&spidev_spi_driver); if (status < 0) { - class_destroy(spidev_class); + class_unregister(&spidev_class); unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); } return status; @@ -882,7 +907,7 @@ module_init(spidev_init); static void __exit spidev_exit(void) { spi_unregister_driver(&spidev_spi_driver); - class_destroy(spidev_class); + class_unregister(&spidev_class); unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); } module_exit(spidev_exit); |
