| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Simple synchronous userspace interface to SPI devices |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2006 SWAPP |
|---|
| 5 | 6 | * Andrea Paterniani <a.paterniani@swapp-eng.it> |
|---|
| 6 | 7 | * 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 | 8 | */ |
|---|
| 18 | 9 | |
|---|
| 19 | 10 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 71 | 62 | #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ |
|---|
| 72 | 63 | | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ |
|---|
| 73 | 64 | | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \ |
|---|
| 74 | | - | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD) |
|---|
| 65 | + | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL \ |
|---|
| 66 | + | SPI_RX_QUAD | SPI_RX_OCTAL) |
|---|
| 75 | 67 | |
|---|
| 76 | 68 | struct spidev_data { |
|---|
| 77 | 69 | dev_t devt; |
|---|
| .. | .. |
|---|
| 154 | 146 | spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) |
|---|
| 155 | 147 | { |
|---|
| 156 | 148 | struct spidev_data *spidev; |
|---|
| 157 | | - ssize_t status = 0; |
|---|
| 149 | + ssize_t status; |
|---|
| 158 | 150 | |
|---|
| 159 | 151 | /* chipselect only toggles at start or end of operation */ |
|---|
| 160 | 152 | if (count > bufsiz) |
|---|
| .. | .. |
|---|
| 184 | 176 | size_t count, loff_t *f_pos) |
|---|
| 185 | 177 | { |
|---|
| 186 | 178 | struct spidev_data *spidev; |
|---|
| 187 | | - ssize_t status = 0; |
|---|
| 179 | + ssize_t status; |
|---|
| 188 | 180 | unsigned long missing; |
|---|
| 189 | 181 | |
|---|
| 190 | 182 | /* chipselect only toggles at start or end of operation */ |
|---|
| .. | .. |
|---|
| 279 | 271 | k_tmp->tx_nbits = u_tmp->tx_nbits; |
|---|
| 280 | 272 | k_tmp->rx_nbits = u_tmp->rx_nbits; |
|---|
| 281 | 273 | k_tmp->bits_per_word = u_tmp->bits_per_word; |
|---|
| 282 | | - k_tmp->delay_usecs = u_tmp->delay_usecs; |
|---|
| 274 | + k_tmp->delay.value = u_tmp->delay_usecs; |
|---|
| 275 | + k_tmp->delay.unit = SPI_DELAY_UNIT_USECS; |
|---|
| 283 | 276 | k_tmp->speed_hz = u_tmp->speed_hz; |
|---|
| 277 | + k_tmp->word_delay.value = u_tmp->word_delay_usecs; |
|---|
| 278 | + k_tmp->word_delay.unit = SPI_DELAY_UNIT_USECS; |
|---|
| 284 | 279 | if (!k_tmp->speed_hz) |
|---|
| 285 | 280 | k_tmp->speed_hz = spidev->speed_hz; |
|---|
| 286 | 281 | #ifdef VERBOSE |
|---|
| 287 | 282 | dev_dbg(&spidev->spi->dev, |
|---|
| 288 | | - " xfer len %u %s%s%s%dbits %u usec %uHz\n", |
|---|
| 289 | | - u_tmp->len, |
|---|
| 290 | | - u_tmp->rx_buf ? "rx " : "", |
|---|
| 291 | | - u_tmp->tx_buf ? "tx " : "", |
|---|
| 292 | | - u_tmp->cs_change ? "cs " : "", |
|---|
| 293 | | - u_tmp->bits_per_word ? : spidev->spi->bits_per_word, |
|---|
| 294 | | - u_tmp->delay_usecs, |
|---|
| 295 | | - u_tmp->speed_hz ? : spidev->spi->max_speed_hz); |
|---|
| 283 | + " xfer len %u %s%s%s%dbits %u usec %u usec %uHz\n", |
|---|
| 284 | + k_tmp->len, |
|---|
| 285 | + k_tmp->rx_buf ? "rx " : "", |
|---|
| 286 | + k_tmp->tx_buf ? "tx " : "", |
|---|
| 287 | + k_tmp->cs_change ? "cs " : "", |
|---|
| 288 | + k_tmp->bits_per_word ? : spidev->spi->bits_per_word, |
|---|
| 289 | + k_tmp->delay.value, |
|---|
| 290 | + k_tmp->word_delay.value, |
|---|
| 291 | + k_tmp->speed_hz ? : spidev->spi->max_speed_hz); |
|---|
| 296 | 292 | #endif |
|---|
| 297 | 293 | spi_message_add_tail(k_tmp, &msg); |
|---|
| 298 | 294 | } |
|---|
| .. | .. |
|---|
| 406 | 402 | else |
|---|
| 407 | 403 | retval = get_user(tmp, (u32 __user *)arg); |
|---|
| 408 | 404 | if (retval == 0) { |
|---|
| 405 | + struct spi_controller *ctlr = spi->controller; |
|---|
| 409 | 406 | u32 save = spi->mode; |
|---|
| 410 | 407 | |
|---|
| 411 | 408 | if (tmp & ~SPI_MODE_MASK) { |
|---|
| 412 | 409 | retval = -EINVAL; |
|---|
| 413 | 410 | break; |
|---|
| 414 | 411 | } |
|---|
| 412 | + |
|---|
| 413 | + if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && |
|---|
| 414 | + ctlr->cs_gpiods[spi->chip_select]) |
|---|
| 415 | + tmp |= SPI_CS_HIGH; |
|---|
| 415 | 416 | |
|---|
| 416 | 417 | tmp |= spi->mode & ~SPI_MODE_MASK; |
|---|
| 417 | 418 | spi->mode = (u16)tmp; |
|---|
| .. | .. |
|---|
| 459 | 460 | |
|---|
| 460 | 461 | spi->max_speed_hz = tmp; |
|---|
| 461 | 462 | retval = spi_setup(spi); |
|---|
| 462 | | - if (retval >= 0) |
|---|
| 463 | + if (retval == 0) { |
|---|
| 463 | 464 | spidev->speed_hz = tmp; |
|---|
| 464 | | - else |
|---|
| 465 | | - dev_dbg(&spi->dev, "%d Hz (max)\n", tmp); |
|---|
| 465 | + dev_dbg(&spi->dev, "%d Hz (max)\n", |
|---|
| 466 | + spidev->speed_hz); |
|---|
| 467 | + } |
|---|
| 466 | 468 | spi->max_speed_hz = save; |
|---|
| 467 | 469 | } |
|---|
| 468 | 470 | break; |
|---|
| .. | .. |
|---|
| 596 | 598 | |
|---|
| 597 | 599 | spidev->users++; |
|---|
| 598 | 600 | filp->private_data = spidev; |
|---|
| 599 | | - nonseekable_open(inode, filp); |
|---|
| 601 | + stream_open(inode, filp); |
|---|
| 600 | 602 | |
|---|
| 601 | 603 | mutex_unlock(&device_list_lock); |
|---|
| 602 | 604 | return 0; |
|---|
| .. | .. |
|---|
| 677 | 679 | { .compatible = "lineartechnology,ltc2488" }, |
|---|
| 678 | 680 | { .compatible = "ge,achc" }, |
|---|
| 679 | 681 | { .compatible = "semtech,sx1301" }, |
|---|
| 682 | + { .compatible = "lwn,bk4" }, |
|---|
| 683 | + { .compatible = "dh,dhcom-board" }, |
|---|
| 684 | + { .compatible = "menlo,m53cpld" }, |
|---|
| 680 | 685 | { .compatible = "rockchip,spidev" }, |
|---|
| 681 | 686 | {}, |
|---|
| 682 | 687 | }; |
|---|