Loading drivers/spi/spi_qsd.c +72 −123 Original line number Diff line number Diff line /* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -45,8 +45,6 @@ #include <linux/msm-bus-board.h> #include "spi_qsd.h" #define SPI_MAX_BYTES_PER_WORD (4) static int msm_spi_pm_resume_runtime(struct device *device); static int msm_spi_pm_suspend_runtime(struct device *device); static inline void msm_spi_dma_unmap_buffers(struct msm_spi *dd); Loading Loading @@ -440,12 +438,10 @@ static void msm_spi_read_word_from_fifo(struct msm_spi *dd) u32 data_in; int i; int shift; int read_bytes = (dd->pack_words ? SPI_MAX_BYTES_PER_WORD : dd->bytes_per_word); data_in = readl_relaxed(dd->base + SPI_INPUT_FIFO); if (dd->read_buf) { for (i = 0; (i < read_bytes) && for (i = 0; (i < dd->bytes_per_word) && dd->rx_bytes_remaining; i++) { /* The data format depends on bytes_per_word: 4 bytes: 0x12345678 Loading @@ -458,8 +454,8 @@ static void msm_spi_read_word_from_fifo(struct msm_spi *dd) dd->rx_bytes_remaining--; } } else { if (dd->rx_bytes_remaining >= read_bytes) dd->rx_bytes_remaining -= read_bytes; if (dd->rx_bytes_remaining >= dd->bytes_per_word) dd->rx_bytes_remaining -= dd->bytes_per_word; else dd->rx_bytes_remaining = 0; } Loading Loading @@ -556,7 +552,7 @@ msm_spi_set_bpw_and_no_io_flags(struct msm_spi *dd, u32 *config, int n) if (n != (*config & SPI_CFG_N)) *config = (*config & ~SPI_CFG_N) | n; if (dd->tx_mode == SPI_BAM_MODE) { if (dd->mode == SPI_BAM_MODE) { if (dd->read_buf == NULL) *config |= SPI_NO_INPUT; if (dd->write_buf == NULL) Loading Loading @@ -621,34 +617,25 @@ static void msm_spi_set_spi_config(struct msm_spi *dd, int bpw) static void msm_spi_set_mx_counts(struct msm_spi *dd, u32 n_words) { /* * For FIFO mode: * - Set the MX_OUTPUT_COUNT/MX_INPUT_COUNT registers to 0 * - Set the READ/WRITE_COUNT registers to 0 (infinite mode) * or num bytes (finite mode) if less than fifo worth of data. * For Block mode: * - Set the MX_OUTPUT/MX_INPUT_COUNT registers to num xfer bytes. * - Set the READ/WRITE_COUNT registers to 0. * n_words cannot exceed fifo_size, and only one READ COUNT * interrupt is generated per transaction, so for transactions * larger than fifo size READ COUNT must be disabled. * For those transactions we usually move to Data Mover mode. */ if (dd->tx_mode != SPI_BAM_MODE) { if (dd->tx_mode == SPI_FIFO_MODE) { if (n_words <= dd->input_fifo_size) msm_spi_set_write_count(dd, n_words); else msm_spi_set_write_count(dd, 0); writel_relaxed(0, dd->base + SPI_MX_OUTPUT_COUNT); } else writel_relaxed(n_words, dd->base + SPI_MX_OUTPUT_COUNT); if (dd->rx_mode == SPI_FIFO_MODE) { if (n_words <= dd->input_fifo_size) if (dd->mode == SPI_FIFO_MODE) { if (n_words <= dd->input_fifo_size) { writel_relaxed(n_words, dd->base + SPI_MX_READ_COUNT); else writel_relaxed(0, dd->base + SPI_MX_READ_COUNT); msm_spi_set_write_count(dd, n_words); } else { writel_relaxed(0, dd->base + SPI_MX_READ_COUNT); msm_spi_set_write_count(dd, 0); } if (dd->qup_ver == SPI_QUP_VERSION_BFAM) { /* must be zero for FIFO */ writel_relaxed(0, dd->base + SPI_MX_INPUT_COUNT); } else writel_relaxed(n_words, dd->base + SPI_MX_INPUT_COUNT); writel_relaxed(0, dd->base + SPI_MX_OUTPUT_COUNT); } } else { /* must be zero for BAM and DMOV */ writel_relaxed(0, dd->base + SPI_MX_READ_COUNT); Loading Loading @@ -895,7 +882,7 @@ xfr_err: static int msm_spi_bam_next_transfer(struct msm_spi *dd) { if (dd->tx_mode != SPI_BAM_MODE) if (dd->mode != SPI_BAM_MODE) return 0; if (dd->tx_bytes_remaining > 0) { Loading @@ -914,7 +901,7 @@ msm_spi_bam_next_transfer(struct msm_spi *dd) static int msm_spi_dma_send_next(struct msm_spi *dd) { int ret = 0; if (dd->tx_mode == SPI_BAM_MODE) if (dd->mode == SPI_BAM_MODE) ret = msm_spi_bam_next_transfer(dd); return ret; } Loading Loading @@ -945,38 +932,32 @@ static inline irqreturn_t msm_spi_qup_irq(int irq, void *dev_id) } op = readl_relaxed(dd->base + SPI_OPERATIONAL); writel_relaxed(op, dd->base + SPI_OPERATIONAL); if (op & SPI_OP_INPUT_SERVICE_FLAG) { writel_relaxed(SPI_OP_INPUT_SERVICE_FLAG, dd->base + SPI_OPERATIONAL); /* * Ensure service flag was cleared before further * processing of interrupt. */ mb(); if (op & SPI_OP_INPUT_SERVICE_FLAG) { ret |= msm_spi_input_irq(irq, dev_id); } if (op & SPI_OP_OUTPUT_SERVICE_FLAG) { writel_relaxed(SPI_OP_OUTPUT_SERVICE_FLAG, dd->base + SPI_OPERATIONAL); /* * Ensure service flag was cleared before further * processing of interrupt. */ mb(); ret |= msm_spi_output_irq(irq, dev_id); } if (dd->tx_mode != SPI_BAM_MODE) { if (!dd->rx_done) { if (dd->rx_bytes_remaining == 0) dd->rx_done = true; } if (!dd->tx_done) { if (!dd->tx_bytes_remaining && (op & SPI_OP_IP_FIFO_NOT_EMPTY)) { dd->tx_done = true; } } } if (dd->tx_done && dd->rx_done) { msm_spi_set_state(dd, SPI_OP_STATE_RESET); dd->tx_done = false; dd->rx_done = false; if (dd->done) { complete(&dd->rx_transfer_complete); complete(&dd->tx_transfer_complete); dd->done = 0; } return ret; } Loading @@ -987,23 +968,17 @@ static irqreturn_t msm_spi_input_irq(int irq, void *dev_id) dd->stat_rx++; if (dd->rx_mode == SPI_MODE_NONE) if (dd->mode == SPI_MODE_NONE) return IRQ_HANDLED; if (dd->rx_mode == SPI_FIFO_MODE) { if (dd->mode == SPI_FIFO_MODE) { while ((readl_relaxed(dd->base + SPI_OPERATIONAL) & SPI_OP_IP_FIFO_NOT_EMPTY) && (dd->rx_bytes_remaining > 0)) { msm_spi_read_word_from_fifo(dd); } } else if (dd->rx_mode == SPI_BLOCK_MODE) { int count = 0; while (dd->rx_bytes_remaining && (count < dd->input_block_size)) { msm_spi_read_word_from_fifo(dd); count += SPI_MAX_BYTES_PER_WORD; } if (dd->rx_bytes_remaining == 0) msm_spi_complete(dd); } return IRQ_HANDLED; Loading @@ -1014,20 +989,18 @@ static void msm_spi_write_word_to_fifo(struct msm_spi *dd) u32 word; u8 byte; int i; int write_bytes = (dd->pack_words ? SPI_MAX_BYTES_PER_WORD : dd->bytes_per_word); word = 0; if (dd->write_buf) { for (i = 0; (i < write_bytes) && for (i = 0; (i < dd->bytes_per_word) && dd->tx_bytes_remaining; i++) { dd->tx_bytes_remaining--; byte = *dd->write_buf++; word |= (byte << (BITS_PER_BYTE * i)); } } else if (dd->tx_bytes_remaining > write_bytes) dd->tx_bytes_remaining -= write_bytes; if (dd->tx_bytes_remaining > dd->bytes_per_word) dd->tx_bytes_remaining -= dd->bytes_per_word; else dd->tx_bytes_remaining = 0; dd->write_xfr_cnt++; Loading @@ -1039,36 +1012,25 @@ static inline void msm_spi_write_rmn_to_fifo(struct msm_spi *dd) { int count = 0; if (dd->tx_mode == SPI_FIFO_MODE) { while ((dd->tx_bytes_remaining > 0) && (count < dd->input_fifo_size) && !(readl_relaxed(dd->base + SPI_OPERATIONAL) & SPI_OP_OUTPUT_FIFO_FULL)) { while ((dd->tx_bytes_remaining > 0) && (count < dd->input_fifo_size) && !(readl_relaxed(dd->base + SPI_OPERATIONAL) & SPI_OP_OUTPUT_FIFO_FULL)) { msm_spi_write_word_to_fifo(dd); count++; } } if (dd->tx_mode == SPI_BLOCK_MODE) { while (dd->tx_bytes_remaining && (count < dd->output_block_size)) { msm_spi_write_word_to_fifo(dd); count += SPI_MAX_BYTES_PER_WORD; } } } static irqreturn_t msm_spi_output_irq(int irq, void *dev_id) { struct msm_spi *dd = dev_id; dd->stat_tx++; if (dd->tx_mode == SPI_MODE_NONE) if (dd->mode == SPI_MODE_NONE) return IRQ_HANDLED; /* Output FIFO is empty. Transmit any outstanding write data. */ if ((dd->tx_mode == SPI_FIFO_MODE) || (dd->tx_mode == SPI_BLOCK_MODE)) if (dd->mode == SPI_FIFO_MODE) msm_spi_write_rmn_to_fifo(dd); return IRQ_HANDLED; Loading Loading @@ -1144,7 +1106,7 @@ error: static int msm_spi_dma_map_buffers(struct msm_spi *dd) { int ret = 0; if (dd->tx_mode == SPI_BAM_MODE) if (dd->mode == SPI_BAM_MODE) ret = msm_spi_bam_map_buffers(dd); return ret; } Loading Loading @@ -1173,7 +1135,7 @@ static void msm_spi_bam_unmap_buffers(struct msm_spi *dd) static inline void msm_spi_dma_unmap_buffers(struct msm_spi *dd) { if (dd->tx_mode == SPI_BAM_MODE) if (dd->mode == SPI_BAM_MODE) msm_spi_bam_unmap_buffers(dd); } Loading Loading @@ -1235,11 +1197,9 @@ static void msm_spi_set_transfer_mode(struct msm_spi *dd, u8 bpw, u32 read_count) { if (msm_spi_use_dma(dd, dd->cur_transfer, bpw)) { dd->tx_mode = SPI_BAM_MODE; dd->rx_mode = SPI_BAM_MODE; dd->mode = SPI_BAM_MODE; } else { dd->rx_mode = SPI_FIFO_MODE; dd->tx_mode = SPI_FIFO_MODE; dd->mode = SPI_FIFO_MODE; dd->read_len = dd->cur_transfer->len; dd->write_len = dd->cur_transfer->len; } Loading @@ -1255,19 +1215,14 @@ static void msm_spi_set_qup_io_modes(struct msm_spi *dd) spi_iom = readl_relaxed(dd->base + SPI_IO_MODES); /* Set input and output transfer mode: FIFO, DMOV, or BAM */ spi_iom &= ~(SPI_IO_M_INPUT_MODE | SPI_IO_M_OUTPUT_MODE); spi_iom = (spi_iom | (dd->tx_mode << OUTPUT_MODE_SHIFT)); spi_iom = (spi_iom | (dd->rx_mode << INPUT_MODE_SHIFT)); /* Always enable packing for all % 8 bits_per_word */ if (dd->cur_transfer->bits_per_word && ((dd->cur_transfer->bits_per_word == 8) || (dd->cur_transfer->bits_per_word == 16) || (dd->cur_transfer->bits_per_word == 32))) { spi_iom = (spi_iom | (dd->mode << OUTPUT_MODE_SHIFT)); spi_iom = (spi_iom | (dd->mode << INPUT_MODE_SHIFT)); /* Turn on packing for data mover */ if (dd->mode == SPI_BAM_MODE) spi_iom |= SPI_IO_M_PACK_EN | SPI_IO_M_UNPACK_EN; dd->pack_words = true; } else { else { spi_iom &= ~(SPI_IO_M_PACK_EN | SPI_IO_M_UNPACK_EN); spi_iom |= SPI_IO_M_OUTPUT_BIT_SHIFT_EN; dd->pack_words = false; } /*if (dd->mode == SPI_BAM_MODE) { Loading Loading @@ -1325,7 +1280,7 @@ static void msm_spi_set_qup_op_mask(struct msm_spi *dd) { /* mask INPUT and OUTPUT service flags in to prevent IRQs on FIFO status * change in BAM mode */ u32 mask = (dd->tx_mode == SPI_BAM_MODE) ? u32 mask = (dd->mode == SPI_BAM_MODE) ? QUP_OP_MASK_OUTPUT_SERVICE_FLAG | QUP_OP_MASK_INPUT_SERVICE_FLAG : 0; writel_relaxed(mask, dd->base + QUP_OPERATIONAL_MASK); Loading Loading @@ -1366,8 +1321,6 @@ static int msm_spi_process_transfer(struct msm_spi *dd) dd->rx_bytes_remaining = dd->cur_msg_len; dd->read_buf = dd->cur_transfer->rx_buf; dd->write_buf = dd->cur_transfer->tx_buf; dd->tx_done = false; dd->rx_done = false; init_completion(&dd->tx_transfer_complete); init_completion(&dd->rx_transfer_complete); if (dd->cur_transfer->bits_per_word) Loading Loading @@ -1398,12 +1351,10 @@ static int msm_spi_process_transfer(struct msm_spi *dd) msm_spi_set_transfer_mode(dd, bpw, read_count); msm_spi_set_mx_counts(dd, read_count); if (dd->tx_mode == SPI_BAM_MODE) { if (dd->mode == SPI_BAM_MODE) { ret = msm_spi_dma_map_buffers(dd); if (ret < 0) { pr_err("Mapping DMA buffers\n"); dd->tx_mode = SPI_MODE_NONE; dd->rx_mode = SPI_MODE_NONE; return ret; } } Loading @@ -1417,11 +1368,11 @@ static int msm_spi_process_transfer(struct msm_spi *dd) the first. Restricting this to one write avoids contention issues and race conditions between this thread and the int handler */ if (dd->tx_mode != SPI_BAM_MODE) { if (dd->mode == SPI_FIFO_MODE) { if (msm_spi_prepare_for_write(dd)) goto transfer_end; msm_spi_start_write(dd, read_count); } else { } else if (dd->mode == SPI_BAM_MODE) { if ((msm_spi_bam_begin_transfer(dd)) < 0) { dev_err(dd->dev, "%s: BAM transfer setup failed\n", __func__); Loading @@ -1437,11 +1388,11 @@ static int msm_spi_process_transfer(struct msm_spi *dd) * might fire before the first word is written resulting in a * possible race condition. */ if (dd->tx_mode != SPI_BAM_MODE) if (dd->mode != SPI_BAM_MODE) if (msm_spi_set_state(dd, SPI_OP_STATE_RUN)) { dev_warn(dd->dev, "%s: Failed to set QUP to run-state. Mode:%d", __func__, dd->tx_mode); __func__, dd->mode); goto transfer_end; } Loading Loading @@ -1471,11 +1422,10 @@ static int msm_spi_process_transfer(struct msm_spi *dd) msm_spi_udelay(dd->xfrs_delay_usec); transfer_end: if ((dd->tx_mode == SPI_BAM_MODE) && status) if ((dd->mode == SPI_BAM_MODE) && status) msm_spi_bam_flush(dd); msm_spi_dma_unmap_buffers(dd); dd->tx_mode = SPI_MODE_NONE; dd->rx_mode = SPI_MODE_NONE; dd->mode = SPI_MODE_NONE; msm_spi_set_state(dd, SPI_OP_STATE_RESET); if (!dd->cur_transfer->cs_change) Loading Loading @@ -2403,8 +2353,7 @@ static int init_resources(struct platform_device *pdev) pclk_enabled = 0; dd->transfer_pending = 0; dd->tx_mode = SPI_MODE_NONE; dd->rx_mode = SPI_MODE_NONE; dd->mode = SPI_MODE_NONE; rc = msm_spi_request_irq(dd, pdev, master); if (rc) Loading drivers/spi/spi_qsd.h +4 −10 Original line number Diff line number Diff line /* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -113,8 +113,6 @@ #define INPUT_MODE_SHIFT QSD_REG(10) QUP_REG(12) /* SPI_OPERATIONAL fields */ #define SPI_OP_IN_BLK_RD_REQ_FLAG 0x00002000 #define SPI_OP_OUT_BLK_WR_REQ_FLAG 0x00001000 #define SPI_OP_MAX_INPUT_DONE_FLAG 0x00000800 #define SPI_OP_MAX_OUTPUT_DONE_FLAG 0x00000400 #define SPI_OP_INPUT_SERVICE_FLAG 0x00000200 Loading Loading @@ -316,8 +314,7 @@ struct msm_spi { bool transfer_pending; wait_queue_head_t continue_suspend; /* DMA data */ enum msm_spi_mode tx_mode; enum msm_spi_mode rx_mode; enum msm_spi_mode mode; bool use_dma; int tx_dma_chan; int tx_dma_crci; Loading Loading @@ -349,8 +346,7 @@ struct msm_spi { #endif struct msm_spi_platform_data *pdata; /* Platform data */ /* When set indicates multiple transfers in a single message */ bool rx_done; bool tx_done; bool done; u32 cur_msg_len; /* Used in FIFO mode to keep track of the transfer being processed */ struct spi_transfer *cur_tx_transfer; Loading @@ -368,7 +364,6 @@ struct msm_spi { struct pinctrl_state *pins_active; struct pinctrl_state *pins_sleep; bool is_init_complete; bool pack_words; }; /* Forward declaration */ Loading Loading @@ -522,8 +517,7 @@ static inline void msm_spi_set_write_count(struct msm_spi *dd, int val) static inline void msm_spi_complete(struct msm_spi *dd) { dd->tx_done = true; dd->rx_done = true; dd->done = 1; } static inline void msm_spi_enable_error_flags(struct msm_spi *dd) Loading Loading
drivers/spi/spi_qsd.c +72 −123 Original line number Diff line number Diff line /* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -45,8 +45,6 @@ #include <linux/msm-bus-board.h> #include "spi_qsd.h" #define SPI_MAX_BYTES_PER_WORD (4) static int msm_spi_pm_resume_runtime(struct device *device); static int msm_spi_pm_suspend_runtime(struct device *device); static inline void msm_spi_dma_unmap_buffers(struct msm_spi *dd); Loading Loading @@ -440,12 +438,10 @@ static void msm_spi_read_word_from_fifo(struct msm_spi *dd) u32 data_in; int i; int shift; int read_bytes = (dd->pack_words ? SPI_MAX_BYTES_PER_WORD : dd->bytes_per_word); data_in = readl_relaxed(dd->base + SPI_INPUT_FIFO); if (dd->read_buf) { for (i = 0; (i < read_bytes) && for (i = 0; (i < dd->bytes_per_word) && dd->rx_bytes_remaining; i++) { /* The data format depends on bytes_per_word: 4 bytes: 0x12345678 Loading @@ -458,8 +454,8 @@ static void msm_spi_read_word_from_fifo(struct msm_spi *dd) dd->rx_bytes_remaining--; } } else { if (dd->rx_bytes_remaining >= read_bytes) dd->rx_bytes_remaining -= read_bytes; if (dd->rx_bytes_remaining >= dd->bytes_per_word) dd->rx_bytes_remaining -= dd->bytes_per_word; else dd->rx_bytes_remaining = 0; } Loading Loading @@ -556,7 +552,7 @@ msm_spi_set_bpw_and_no_io_flags(struct msm_spi *dd, u32 *config, int n) if (n != (*config & SPI_CFG_N)) *config = (*config & ~SPI_CFG_N) | n; if (dd->tx_mode == SPI_BAM_MODE) { if (dd->mode == SPI_BAM_MODE) { if (dd->read_buf == NULL) *config |= SPI_NO_INPUT; if (dd->write_buf == NULL) Loading Loading @@ -621,34 +617,25 @@ static void msm_spi_set_spi_config(struct msm_spi *dd, int bpw) static void msm_spi_set_mx_counts(struct msm_spi *dd, u32 n_words) { /* * For FIFO mode: * - Set the MX_OUTPUT_COUNT/MX_INPUT_COUNT registers to 0 * - Set the READ/WRITE_COUNT registers to 0 (infinite mode) * or num bytes (finite mode) if less than fifo worth of data. * For Block mode: * - Set the MX_OUTPUT/MX_INPUT_COUNT registers to num xfer bytes. * - Set the READ/WRITE_COUNT registers to 0. * n_words cannot exceed fifo_size, and only one READ COUNT * interrupt is generated per transaction, so for transactions * larger than fifo size READ COUNT must be disabled. * For those transactions we usually move to Data Mover mode. */ if (dd->tx_mode != SPI_BAM_MODE) { if (dd->tx_mode == SPI_FIFO_MODE) { if (n_words <= dd->input_fifo_size) msm_spi_set_write_count(dd, n_words); else msm_spi_set_write_count(dd, 0); writel_relaxed(0, dd->base + SPI_MX_OUTPUT_COUNT); } else writel_relaxed(n_words, dd->base + SPI_MX_OUTPUT_COUNT); if (dd->rx_mode == SPI_FIFO_MODE) { if (n_words <= dd->input_fifo_size) if (dd->mode == SPI_FIFO_MODE) { if (n_words <= dd->input_fifo_size) { writel_relaxed(n_words, dd->base + SPI_MX_READ_COUNT); else writel_relaxed(0, dd->base + SPI_MX_READ_COUNT); msm_spi_set_write_count(dd, n_words); } else { writel_relaxed(0, dd->base + SPI_MX_READ_COUNT); msm_spi_set_write_count(dd, 0); } if (dd->qup_ver == SPI_QUP_VERSION_BFAM) { /* must be zero for FIFO */ writel_relaxed(0, dd->base + SPI_MX_INPUT_COUNT); } else writel_relaxed(n_words, dd->base + SPI_MX_INPUT_COUNT); writel_relaxed(0, dd->base + SPI_MX_OUTPUT_COUNT); } } else { /* must be zero for BAM and DMOV */ writel_relaxed(0, dd->base + SPI_MX_READ_COUNT); Loading Loading @@ -895,7 +882,7 @@ xfr_err: static int msm_spi_bam_next_transfer(struct msm_spi *dd) { if (dd->tx_mode != SPI_BAM_MODE) if (dd->mode != SPI_BAM_MODE) return 0; if (dd->tx_bytes_remaining > 0) { Loading @@ -914,7 +901,7 @@ msm_spi_bam_next_transfer(struct msm_spi *dd) static int msm_spi_dma_send_next(struct msm_spi *dd) { int ret = 0; if (dd->tx_mode == SPI_BAM_MODE) if (dd->mode == SPI_BAM_MODE) ret = msm_spi_bam_next_transfer(dd); return ret; } Loading Loading @@ -945,38 +932,32 @@ static inline irqreturn_t msm_spi_qup_irq(int irq, void *dev_id) } op = readl_relaxed(dd->base + SPI_OPERATIONAL); writel_relaxed(op, dd->base + SPI_OPERATIONAL); if (op & SPI_OP_INPUT_SERVICE_FLAG) { writel_relaxed(SPI_OP_INPUT_SERVICE_FLAG, dd->base + SPI_OPERATIONAL); /* * Ensure service flag was cleared before further * processing of interrupt. */ mb(); if (op & SPI_OP_INPUT_SERVICE_FLAG) { ret |= msm_spi_input_irq(irq, dev_id); } if (op & SPI_OP_OUTPUT_SERVICE_FLAG) { writel_relaxed(SPI_OP_OUTPUT_SERVICE_FLAG, dd->base + SPI_OPERATIONAL); /* * Ensure service flag was cleared before further * processing of interrupt. */ mb(); ret |= msm_spi_output_irq(irq, dev_id); } if (dd->tx_mode != SPI_BAM_MODE) { if (!dd->rx_done) { if (dd->rx_bytes_remaining == 0) dd->rx_done = true; } if (!dd->tx_done) { if (!dd->tx_bytes_remaining && (op & SPI_OP_IP_FIFO_NOT_EMPTY)) { dd->tx_done = true; } } } if (dd->tx_done && dd->rx_done) { msm_spi_set_state(dd, SPI_OP_STATE_RESET); dd->tx_done = false; dd->rx_done = false; if (dd->done) { complete(&dd->rx_transfer_complete); complete(&dd->tx_transfer_complete); dd->done = 0; } return ret; } Loading @@ -987,23 +968,17 @@ static irqreturn_t msm_spi_input_irq(int irq, void *dev_id) dd->stat_rx++; if (dd->rx_mode == SPI_MODE_NONE) if (dd->mode == SPI_MODE_NONE) return IRQ_HANDLED; if (dd->rx_mode == SPI_FIFO_MODE) { if (dd->mode == SPI_FIFO_MODE) { while ((readl_relaxed(dd->base + SPI_OPERATIONAL) & SPI_OP_IP_FIFO_NOT_EMPTY) && (dd->rx_bytes_remaining > 0)) { msm_spi_read_word_from_fifo(dd); } } else if (dd->rx_mode == SPI_BLOCK_MODE) { int count = 0; while (dd->rx_bytes_remaining && (count < dd->input_block_size)) { msm_spi_read_word_from_fifo(dd); count += SPI_MAX_BYTES_PER_WORD; } if (dd->rx_bytes_remaining == 0) msm_spi_complete(dd); } return IRQ_HANDLED; Loading @@ -1014,20 +989,18 @@ static void msm_spi_write_word_to_fifo(struct msm_spi *dd) u32 word; u8 byte; int i; int write_bytes = (dd->pack_words ? SPI_MAX_BYTES_PER_WORD : dd->bytes_per_word); word = 0; if (dd->write_buf) { for (i = 0; (i < write_bytes) && for (i = 0; (i < dd->bytes_per_word) && dd->tx_bytes_remaining; i++) { dd->tx_bytes_remaining--; byte = *dd->write_buf++; word |= (byte << (BITS_PER_BYTE * i)); } } else if (dd->tx_bytes_remaining > write_bytes) dd->tx_bytes_remaining -= write_bytes; if (dd->tx_bytes_remaining > dd->bytes_per_word) dd->tx_bytes_remaining -= dd->bytes_per_word; else dd->tx_bytes_remaining = 0; dd->write_xfr_cnt++; Loading @@ -1039,36 +1012,25 @@ static inline void msm_spi_write_rmn_to_fifo(struct msm_spi *dd) { int count = 0; if (dd->tx_mode == SPI_FIFO_MODE) { while ((dd->tx_bytes_remaining > 0) && (count < dd->input_fifo_size) && !(readl_relaxed(dd->base + SPI_OPERATIONAL) & SPI_OP_OUTPUT_FIFO_FULL)) { while ((dd->tx_bytes_remaining > 0) && (count < dd->input_fifo_size) && !(readl_relaxed(dd->base + SPI_OPERATIONAL) & SPI_OP_OUTPUT_FIFO_FULL)) { msm_spi_write_word_to_fifo(dd); count++; } } if (dd->tx_mode == SPI_BLOCK_MODE) { while (dd->tx_bytes_remaining && (count < dd->output_block_size)) { msm_spi_write_word_to_fifo(dd); count += SPI_MAX_BYTES_PER_WORD; } } } static irqreturn_t msm_spi_output_irq(int irq, void *dev_id) { struct msm_spi *dd = dev_id; dd->stat_tx++; if (dd->tx_mode == SPI_MODE_NONE) if (dd->mode == SPI_MODE_NONE) return IRQ_HANDLED; /* Output FIFO is empty. Transmit any outstanding write data. */ if ((dd->tx_mode == SPI_FIFO_MODE) || (dd->tx_mode == SPI_BLOCK_MODE)) if (dd->mode == SPI_FIFO_MODE) msm_spi_write_rmn_to_fifo(dd); return IRQ_HANDLED; Loading Loading @@ -1144,7 +1106,7 @@ error: static int msm_spi_dma_map_buffers(struct msm_spi *dd) { int ret = 0; if (dd->tx_mode == SPI_BAM_MODE) if (dd->mode == SPI_BAM_MODE) ret = msm_spi_bam_map_buffers(dd); return ret; } Loading Loading @@ -1173,7 +1135,7 @@ static void msm_spi_bam_unmap_buffers(struct msm_spi *dd) static inline void msm_spi_dma_unmap_buffers(struct msm_spi *dd) { if (dd->tx_mode == SPI_BAM_MODE) if (dd->mode == SPI_BAM_MODE) msm_spi_bam_unmap_buffers(dd); } Loading Loading @@ -1235,11 +1197,9 @@ static void msm_spi_set_transfer_mode(struct msm_spi *dd, u8 bpw, u32 read_count) { if (msm_spi_use_dma(dd, dd->cur_transfer, bpw)) { dd->tx_mode = SPI_BAM_MODE; dd->rx_mode = SPI_BAM_MODE; dd->mode = SPI_BAM_MODE; } else { dd->rx_mode = SPI_FIFO_MODE; dd->tx_mode = SPI_FIFO_MODE; dd->mode = SPI_FIFO_MODE; dd->read_len = dd->cur_transfer->len; dd->write_len = dd->cur_transfer->len; } Loading @@ -1255,19 +1215,14 @@ static void msm_spi_set_qup_io_modes(struct msm_spi *dd) spi_iom = readl_relaxed(dd->base + SPI_IO_MODES); /* Set input and output transfer mode: FIFO, DMOV, or BAM */ spi_iom &= ~(SPI_IO_M_INPUT_MODE | SPI_IO_M_OUTPUT_MODE); spi_iom = (spi_iom | (dd->tx_mode << OUTPUT_MODE_SHIFT)); spi_iom = (spi_iom | (dd->rx_mode << INPUT_MODE_SHIFT)); /* Always enable packing for all % 8 bits_per_word */ if (dd->cur_transfer->bits_per_word && ((dd->cur_transfer->bits_per_word == 8) || (dd->cur_transfer->bits_per_word == 16) || (dd->cur_transfer->bits_per_word == 32))) { spi_iom = (spi_iom | (dd->mode << OUTPUT_MODE_SHIFT)); spi_iom = (spi_iom | (dd->mode << INPUT_MODE_SHIFT)); /* Turn on packing for data mover */ if (dd->mode == SPI_BAM_MODE) spi_iom |= SPI_IO_M_PACK_EN | SPI_IO_M_UNPACK_EN; dd->pack_words = true; } else { else { spi_iom &= ~(SPI_IO_M_PACK_EN | SPI_IO_M_UNPACK_EN); spi_iom |= SPI_IO_M_OUTPUT_BIT_SHIFT_EN; dd->pack_words = false; } /*if (dd->mode == SPI_BAM_MODE) { Loading Loading @@ -1325,7 +1280,7 @@ static void msm_spi_set_qup_op_mask(struct msm_spi *dd) { /* mask INPUT and OUTPUT service flags in to prevent IRQs on FIFO status * change in BAM mode */ u32 mask = (dd->tx_mode == SPI_BAM_MODE) ? u32 mask = (dd->mode == SPI_BAM_MODE) ? QUP_OP_MASK_OUTPUT_SERVICE_FLAG | QUP_OP_MASK_INPUT_SERVICE_FLAG : 0; writel_relaxed(mask, dd->base + QUP_OPERATIONAL_MASK); Loading Loading @@ -1366,8 +1321,6 @@ static int msm_spi_process_transfer(struct msm_spi *dd) dd->rx_bytes_remaining = dd->cur_msg_len; dd->read_buf = dd->cur_transfer->rx_buf; dd->write_buf = dd->cur_transfer->tx_buf; dd->tx_done = false; dd->rx_done = false; init_completion(&dd->tx_transfer_complete); init_completion(&dd->rx_transfer_complete); if (dd->cur_transfer->bits_per_word) Loading Loading @@ -1398,12 +1351,10 @@ static int msm_spi_process_transfer(struct msm_spi *dd) msm_spi_set_transfer_mode(dd, bpw, read_count); msm_spi_set_mx_counts(dd, read_count); if (dd->tx_mode == SPI_BAM_MODE) { if (dd->mode == SPI_BAM_MODE) { ret = msm_spi_dma_map_buffers(dd); if (ret < 0) { pr_err("Mapping DMA buffers\n"); dd->tx_mode = SPI_MODE_NONE; dd->rx_mode = SPI_MODE_NONE; return ret; } } Loading @@ -1417,11 +1368,11 @@ static int msm_spi_process_transfer(struct msm_spi *dd) the first. Restricting this to one write avoids contention issues and race conditions between this thread and the int handler */ if (dd->tx_mode != SPI_BAM_MODE) { if (dd->mode == SPI_FIFO_MODE) { if (msm_spi_prepare_for_write(dd)) goto transfer_end; msm_spi_start_write(dd, read_count); } else { } else if (dd->mode == SPI_BAM_MODE) { if ((msm_spi_bam_begin_transfer(dd)) < 0) { dev_err(dd->dev, "%s: BAM transfer setup failed\n", __func__); Loading @@ -1437,11 +1388,11 @@ static int msm_spi_process_transfer(struct msm_spi *dd) * might fire before the first word is written resulting in a * possible race condition. */ if (dd->tx_mode != SPI_BAM_MODE) if (dd->mode != SPI_BAM_MODE) if (msm_spi_set_state(dd, SPI_OP_STATE_RUN)) { dev_warn(dd->dev, "%s: Failed to set QUP to run-state. Mode:%d", __func__, dd->tx_mode); __func__, dd->mode); goto transfer_end; } Loading Loading @@ -1471,11 +1422,10 @@ static int msm_spi_process_transfer(struct msm_spi *dd) msm_spi_udelay(dd->xfrs_delay_usec); transfer_end: if ((dd->tx_mode == SPI_BAM_MODE) && status) if ((dd->mode == SPI_BAM_MODE) && status) msm_spi_bam_flush(dd); msm_spi_dma_unmap_buffers(dd); dd->tx_mode = SPI_MODE_NONE; dd->rx_mode = SPI_MODE_NONE; dd->mode = SPI_MODE_NONE; msm_spi_set_state(dd, SPI_OP_STATE_RESET); if (!dd->cur_transfer->cs_change) Loading Loading @@ -2403,8 +2353,7 @@ static int init_resources(struct platform_device *pdev) pclk_enabled = 0; dd->transfer_pending = 0; dd->tx_mode = SPI_MODE_NONE; dd->rx_mode = SPI_MODE_NONE; dd->mode = SPI_MODE_NONE; rc = msm_spi_request_irq(dd, pdev, master); if (rc) Loading
drivers/spi/spi_qsd.h +4 −10 Original line number Diff line number Diff line /* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -113,8 +113,6 @@ #define INPUT_MODE_SHIFT QSD_REG(10) QUP_REG(12) /* SPI_OPERATIONAL fields */ #define SPI_OP_IN_BLK_RD_REQ_FLAG 0x00002000 #define SPI_OP_OUT_BLK_WR_REQ_FLAG 0x00001000 #define SPI_OP_MAX_INPUT_DONE_FLAG 0x00000800 #define SPI_OP_MAX_OUTPUT_DONE_FLAG 0x00000400 #define SPI_OP_INPUT_SERVICE_FLAG 0x00000200 Loading Loading @@ -316,8 +314,7 @@ struct msm_spi { bool transfer_pending; wait_queue_head_t continue_suspend; /* DMA data */ enum msm_spi_mode tx_mode; enum msm_spi_mode rx_mode; enum msm_spi_mode mode; bool use_dma; int tx_dma_chan; int tx_dma_crci; Loading Loading @@ -349,8 +346,7 @@ struct msm_spi { #endif struct msm_spi_platform_data *pdata; /* Platform data */ /* When set indicates multiple transfers in a single message */ bool rx_done; bool tx_done; bool done; u32 cur_msg_len; /* Used in FIFO mode to keep track of the transfer being processed */ struct spi_transfer *cur_tx_transfer; Loading @@ -368,7 +364,6 @@ struct msm_spi { struct pinctrl_state *pins_active; struct pinctrl_state *pins_sleep; bool is_init_complete; bool pack_words; }; /* Forward declaration */ Loading Loading @@ -522,8 +517,7 @@ static inline void msm_spi_set_write_count(struct msm_spi *dd, int val) static inline void msm_spi_complete(struct msm_spi *dd) { dd->tx_done = true; dd->rx_done = true; dd->done = 1; } static inline void msm_spi_enable_error_flags(struct msm_spi *dd) Loading