diff options
| -rw-r--r-- | drivers/spi/spi-sirf.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index dc962a17f373..a72b8f87a156 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c | |||
| @@ -131,6 +131,8 @@ | |||
| 131 | #define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \ | 131 | #define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \ |
| 132 | ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE)) | 132 | ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE)) |
| 133 | 133 | ||
| 134 | #define SIRFSOC_MAX_CMD_BYTES 4 | ||
| 135 | |||
| 134 | struct sirfsoc_spi { | 136 | struct sirfsoc_spi { |
| 135 | struct spi_bitbang bitbang; | 137 | struct spi_bitbang bitbang; |
| 136 | struct completion rx_done; | 138 | struct completion rx_done; |
| @@ -161,6 +163,12 @@ struct sirfsoc_spi { | |||
| 161 | void *dummypage; | 163 | void *dummypage; |
| 162 | int word_width; /* in bytes */ | 164 | int word_width; /* in bytes */ |
| 163 | 165 | ||
| 166 | /* | ||
| 167 | * if tx size is not more than 4 and rx size is NULL, use | ||
| 168 | * command model | ||
| 169 | */ | ||
| 170 | bool tx_by_cmd; | ||
| 171 | |||
| 164 | int chipselect[0]; | 172 | int chipselect[0]; |
| 165 | }; | 173 | }; |
| 166 | 174 | ||
| @@ -259,6 +267,12 @@ static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id) | |||
| 259 | 267 | ||
| 260 | writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS); | 268 | writel(spi_stat, sspi->base + SIRFSOC_SPI_INT_STATUS); |
| 261 | 269 | ||
| 270 | if (sspi->tx_by_cmd && (spi_stat & SIRFSOC_SPI_FRM_END)) { | ||
| 271 | complete(&sspi->tx_done); | ||
| 272 | writel(0x0, sspi->base + SIRFSOC_SPI_INT_EN); | ||
| 273 | return IRQ_HANDLED; | ||
| 274 | } | ||
| 275 | |||
| 262 | /* Error Conditions */ | 276 | /* Error Conditions */ |
| 263 | if (spi_stat & SIRFSOC_SPI_RX_OFLOW || | 277 | if (spi_stat & SIRFSOC_SPI_RX_OFLOW || |
| 264 | spi_stat & SIRFSOC_SPI_TX_UFLOW) { | 278 | spi_stat & SIRFSOC_SPI_TX_UFLOW) { |
| @@ -309,6 +323,34 @@ static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
| 309 | 323 | ||
| 310 | writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS); | 324 | writel(SIRFSOC_SPI_INT_MASK_ALL, sspi->base + SIRFSOC_SPI_INT_STATUS); |
| 311 | 325 | ||
| 326 | /* | ||
| 327 | * fill tx_buf into command register and wait for its completion | ||
| 328 | */ | ||
| 329 | if (sspi->tx_by_cmd) { | ||
| 330 | u32 cmd; | ||
| 331 | memcpy(&cmd, sspi->tx, t->len); | ||
| 332 | |||
| 333 | if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST)) | ||
| 334 | cmd = cpu_to_be32(cmd) >> | ||
| 335 | ((SIRFSOC_MAX_CMD_BYTES - t->len) * 8); | ||
| 336 | if (sspi->word_width == 2 && t->len == 4 && | ||
| 337 | (!(spi->mode & SPI_LSB_FIRST))) | ||
| 338 | cmd = ((cmd & 0xffff) << 16) | (cmd >> 16); | ||
| 339 | |||
| 340 | writel(cmd, sspi->base + SIRFSOC_SPI_CMD); | ||
| 341 | writel(SIRFSOC_SPI_FRM_END_INT_EN, | ||
| 342 | sspi->base + SIRFSOC_SPI_INT_EN); | ||
| 343 | writel(SIRFSOC_SPI_CMD_TX_EN, | ||
| 344 | sspi->base + SIRFSOC_SPI_TX_RX_EN); | ||
| 345 | |||
| 346 | if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) { | ||
| 347 | dev_err(&spi->dev, "transfer timeout\n"); | ||
| 348 | return 0; | ||
| 349 | } | ||
| 350 | |||
| 351 | return t->len; | ||
| 352 | } | ||
| 353 | |||
| 312 | if (sspi->left_tx_word == 1) { | 354 | if (sspi->left_tx_word == 1) { |
| 313 | writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | | 355 | writel(readl(sspi->base + SIRFSOC_SPI_CTRL) | |
| 314 | SIRFSOC_SPI_ENA_AUTO_CLR, | 356 | SIRFSOC_SPI_ENA_AUTO_CLR, |
| @@ -509,6 +551,14 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
| 509 | writel(txfifo_ctrl, sspi->base + SIRFSOC_SPI_TXFIFO_CTRL); | 551 | writel(txfifo_ctrl, sspi->base + SIRFSOC_SPI_TXFIFO_CTRL); |
| 510 | writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL); | 552 | writel(rxfifo_ctrl, sspi->base + SIRFSOC_SPI_RXFIFO_CTRL); |
| 511 | 553 | ||
| 554 | if (t && t->tx_buf && !t->rx_buf && (t->len <= SIRFSOC_MAX_CMD_BYTES)) { | ||
| 555 | regval |= (SIRFSOC_SPI_CMD_BYTE_NUM((t->len - 1)) | | ||
| 556 | SIRFSOC_SPI_CMD_MODE); | ||
| 557 | sspi->tx_by_cmd = true; | ||
| 558 | } else { | ||
| 559 | regval &= ~SIRFSOC_SPI_CMD_MODE; | ||
| 560 | sspi->tx_by_cmd = false; | ||
| 561 | } | ||
| 512 | writel(regval, sspi->base + SIRFSOC_SPI_CTRL); | 562 | writel(regval, sspi->base + SIRFSOC_SPI_CTRL); |
| 513 | 563 | ||
| 514 | if (IS_DMA_VALID(t)) { | 564 | if (IS_DMA_VALID(t)) { |
