| .. | .. |
|---|
| 13 | 13 | #include <linux/slab.h> |
|---|
| 14 | 14 | #include <linux/spi/spi.h> |
|---|
| 15 | 15 | |
|---|
| 16 | +#include <soc/rockchip/rockchip-system-status.h> |
|---|
| 17 | + |
|---|
| 16 | 18 | #define SPI_OBJ_MAX_XFER_SIZE 0x1040 |
|---|
| 17 | 19 | #define SPI_OBJ_APP_RAM_SIZE 0x10000 |
|---|
| 18 | 20 | |
|---|
| .. | .. |
|---|
| 21 | 23 | #define SPI_OBJ_CTRL_CMD_READ 0x3A |
|---|
| 22 | 24 | #define SPI_OBJ_CTRL_CMD_WRITE 0x4B |
|---|
| 23 | 25 | #define SPI_OBJ_CTRL_CMD_DUPLEX 0x5C |
|---|
| 26 | + |
|---|
| 27 | +#define SPI_OBJ_CTRL_DYQ_PERF_THRESHOLD 0x20 |
|---|
| 24 | 28 | |
|---|
| 25 | 29 | struct spi_obj_ctrl { |
|---|
| 26 | 30 | u16 cmd; |
|---|
| .. | .. |
|---|
| 38 | 42 | struct task_struct *tsk; |
|---|
| 39 | 43 | bool tsk_run; |
|---|
| 40 | 44 | struct miscdevice misc_dev; |
|---|
| 45 | + |
|---|
| 46 | + /* |
|---|
| 47 | + * If the DRAM frequency conversion jitters during the transmission process, |
|---|
| 48 | + * it will cause the DMA to be unable to transport SPI FIFO data in a timely |
|---|
| 49 | + * manner, resulting in FIFO overflow/underflow. |
|---|
| 50 | + * |
|---|
| 51 | + * However, since the command packet length is smaller than FIFO, this |
|---|
| 52 | + * problem does not exist. So set performance status dynamically for data packet. |
|---|
| 53 | + */ |
|---|
| 54 | + bool dyq_perf; |
|---|
| 41 | 55 | }; |
|---|
| 42 | 56 | |
|---|
| 43 | 57 | static u32 bit_per_word = 8; |
|---|
| 44 | 58 | |
|---|
| 45 | | -static int spidev_slv_write(struct spidev_rkslv_data *spidev, const void *txbuf, size_t n) |
|---|
| 59 | +static int spidev_slv_write(struct spidev_rkslv_data *spidev, const void *txbuf, size_t len) |
|---|
| 46 | 60 | { |
|---|
| 47 | | - int ret = -1; |
|---|
| 48 | 61 | struct spi_device *spi = spidev->spi; |
|---|
| 49 | 62 | struct spi_transfer t = { |
|---|
| 50 | 63 | .tx_buf = txbuf, |
|---|
| 51 | | - .len = n, |
|---|
| 64 | + .len = len, |
|---|
| 52 | 65 | .bits_per_word = bit_per_word, |
|---|
| 53 | 66 | }; |
|---|
| 54 | 67 | struct spi_message m; |
|---|
| 68 | + int ret; |
|---|
| 55 | 69 | |
|---|
| 56 | 70 | spi_message_init(&m); |
|---|
| 57 | 71 | spi_message_add_tail(&t, &m); |
|---|
| 72 | + if (spidev->dyq_perf && len > SPI_OBJ_CTRL_DYQ_PERF_THRESHOLD) |
|---|
| 73 | + rockchip_set_system_status(SYS_STATUS_PERFORMANCE); |
|---|
| 58 | 74 | ret = spi_sync(spi, &m); |
|---|
| 75 | + if (spidev->dyq_perf && len > SPI_OBJ_CTRL_DYQ_PERF_THRESHOLD) |
|---|
| 76 | + rockchip_clear_system_status(SYS_STATUS_PERFORMANCE); |
|---|
| 59 | 77 | |
|---|
| 60 | 78 | return ret; |
|---|
| 61 | 79 | } |
|---|
| 62 | 80 | |
|---|
| 63 | | -static int spidev_slv_read(struct spidev_rkslv_data *spidev, void *rxbuf, size_t n) |
|---|
| 81 | +static int spidev_slv_read(struct spidev_rkslv_data *spidev, void *rxbuf, size_t len) |
|---|
| 64 | 82 | { |
|---|
| 65 | | - int ret = -1; |
|---|
| 66 | 83 | struct spi_device *spi = spidev->spi; |
|---|
| 67 | 84 | struct spi_transfer t = { |
|---|
| 68 | 85 | .rx_buf = rxbuf, |
|---|
| 69 | | - .len = n, |
|---|
| 86 | + .len = len, |
|---|
| 70 | 87 | .bits_per_word = bit_per_word, |
|---|
| 71 | 88 | }; |
|---|
| 72 | 89 | struct spi_message m; |
|---|
| 90 | + int ret; |
|---|
| 73 | 91 | |
|---|
| 74 | 92 | spi_message_init(&m); |
|---|
| 75 | 93 | spi_message_add_tail(&t, &m); |
|---|
| 94 | + if (spidev->dyq_perf && len > SPI_OBJ_CTRL_DYQ_PERF_THRESHOLD) |
|---|
| 95 | + rockchip_set_system_status(SYS_STATUS_PERFORMANCE); |
|---|
| 76 | 96 | ret = spi_sync(spi, &m); |
|---|
| 97 | + if (spidev->dyq_perf && len > SPI_OBJ_CTRL_DYQ_PERF_THRESHOLD) |
|---|
| 98 | + rockchip_clear_system_status(SYS_STATUS_PERFORMANCE); |
|---|
| 77 | 99 | |
|---|
| 78 | 100 | return ret; |
|---|
| 79 | 101 | } |
|---|
| .. | .. |
|---|
| 88 | 110 | .len = len, |
|---|
| 89 | 111 | }; |
|---|
| 90 | 112 | struct spi_message m; |
|---|
| 113 | + int ret; |
|---|
| 91 | 114 | |
|---|
| 92 | 115 | spi_message_init(&m); |
|---|
| 93 | 116 | spi_message_add_tail(&t, &m); |
|---|
| 94 | | - return spi_sync(spi, &m); |
|---|
| 117 | + |
|---|
| 118 | + if (spidev->dyq_perf && len > SPI_OBJ_CTRL_DYQ_PERF_THRESHOLD) |
|---|
| 119 | + rockchip_set_system_status(SYS_STATUS_PERFORMANCE); |
|---|
| 120 | + ret = spi_sync(spi, &m); |
|---|
| 121 | + if (spidev->dyq_perf && len > SPI_OBJ_CTRL_DYQ_PERF_THRESHOLD) |
|---|
| 122 | + rockchip_clear_system_status(SYS_STATUS_PERFORMANCE); |
|---|
| 123 | + |
|---|
| 124 | + return ret; |
|---|
| 95 | 125 | } |
|---|
| 96 | 126 | |
|---|
| 97 | 127 | static ssize_t spidev_rkslv_misc_write(struct file *filp, const char __user *buf, |
|---|
| .. | .. |
|---|
| 318 | 348 | if (!spidev->tempbuf) |
|---|
| 319 | 349 | return -ENOMEM; |
|---|
| 320 | 350 | |
|---|
| 351 | + spidev->dyq_perf = true; |
|---|
| 321 | 352 | spidev->spi = spi; |
|---|
| 322 | 353 | spidev->dev = &spi->dev; |
|---|
| 323 | 354 | dev_set_drvdata(&spi->dev, spidev); |
|---|