Loading drivers/spi/spi-fsl-lpspi.c +2 −2 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ #define CFGR1_PCSPOL BIT(8) #define CFGR1_NOSTALL BIT(3) #define CFGR1_MASTER BIT(0) #define FSR_RXCOUNT (BIT(16)|BIT(17)|BIT(18)) #define FSR_TXCOUNT (0xFF) #define RSR_RXEMPTY BIT(1) #define TCR_CPOL BIT(31) #define TCR_CPHA BIT(30) Loading Loading @@ -771,7 +771,7 @@ static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) } if (temp_SR & SR_MBF || readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_RXCOUNT) { readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_TXCOUNT) { writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR); fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); return IRQ_HANDLED; Loading drivers/spi/spi-gpio.c +0 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ * platform_device->driver_data ... points to spi_gpio * * spi->controller_state ... reserved for bitbang framework code * spi->controller_data ... holds chipselect GPIO * * spi->master->dev.driver_data ... points to spi_gpio->bitbang */ Loading drivers/spi/spi-pic32.c +1 −1 Original line number Diff line number Diff line Loading @@ -559,7 +559,7 @@ static int pic32_spi_one_transfer(struct spi_master *master, dev_err(&spi->dev, "wait error/timedout\n"); if (dma_issued) { dmaengine_terminate_all(master->dma_rx); dmaengine_terminate_all(master->dma_rx); dmaengine_terminate_all(master->dma_tx); } ret = -ETIMEDOUT; } else { Loading drivers/spi/spi-tegra114.c +146 −62 Original line number Diff line number Diff line Loading @@ -307,10 +307,16 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } tspi->cur_tx_pos += written_words * tspi->bytes_per_word; } else { unsigned int write_bytes; max_n_32bit = min(tspi->curr_dma_words, tx_empty_count); written_words = max_n_32bit; nbytes = written_words * tspi->bytes_per_word; if (nbytes > t->len - tspi->cur_pos) nbytes = t->len - tspi->cur_pos; write_bytes = nbytes; for (count = 0; count < max_n_32bit; count++) { u32 x = 0; Loading @@ -319,8 +325,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } tspi->cur_tx_pos += write_bytes; } tspi->cur_tx_pos += written_words * tspi->bytes_per_word; return written_words; } Loading @@ -344,20 +352,27 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf( for (i = 0; len && (i < 4); i++, len--) *rx_buf++ = (x >> i*8) & 0xFF; } tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; read_words += tspi->curr_dma_words; tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; u8 bytes_per_word = tspi->bytes_per_word; unsigned int read_bytes; len = rx_full_count * bytes_per_word; if (len > t->len - tspi->cur_pos) len = t->len - tspi->cur_pos; read_bytes = len; for (count = 0; count < rx_full_count; count++) { u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask; for (i = 0; (i < tspi->bytes_per_word); i++) for (i = 0; len && (i < bytes_per_word); i++, len--) *rx_buf++ = (x >> (i*8)) & 0xFF; } tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word; read_words += rx_full_count; tspi->cur_rx_pos += read_bytes; } return read_words; } Loading @@ -372,12 +387,17 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len); tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { unsigned int i; unsigned int count; u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos; unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; unsigned int write_bytes; if (consume > t->len - tspi->cur_pos) consume = t->len - tspi->cur_pos; write_bytes = consume; for (count = 0; count < tspi->curr_dma_words; count++) { u32 x = 0; Loading @@ -386,8 +406,9 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tspi->tx_dma_buf[count] = x; } tspi->cur_tx_pos += write_bytes; } tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word; /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys, Loading @@ -405,20 +426,28 @@ static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf( unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len); tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { unsigned int i; unsigned int count; unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos; u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; unsigned int read_bytes; if (consume > t->len - tspi->cur_pos) consume = t->len - tspi->cur_pos; read_bytes = consume; for (count = 0; count < tspi->curr_dma_words; count++) { u32 x = tspi->rx_dma_buf[count] & rx_mask; for (i = 0; (i < tspi->bytes_per_word); i++) for (i = 0; consume && (i < tspi->bytes_per_word); i++, consume--) *rx_buf++ = (x >> (i*8)) & 0xFF; } tspi->cur_rx_pos += read_bytes; } tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, Loading Loading @@ -470,22 +499,39 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len) return 0; } static int tegra_spi_start_dma_based_transfer( struct tegra_spi_data *tspi, struct spi_transfer *t) static int tegra_spi_flush_fifos(struct tegra_spi_data *tspi) { u32 val; unsigned int len; int ret = 0; unsigned long timeout = jiffies + HZ; u32 status; /* Make sure that Rx and Tx fifo are empty */ status = tegra_spi_readl(tspi, SPI_FIFO_STATUS); if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) { dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n", (unsigned)status); status |= SPI_RX_FIFO_FLUSH | SPI_TX_FIFO_FLUSH; tegra_spi_writel(tspi, status, SPI_FIFO_STATUS); while ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) { status = tegra_spi_readl(tspi, SPI_FIFO_STATUS); if (time_after(jiffies, timeout)) { dev_err(tspi->dev, "timeout waiting for fifo flush\n"); return -EIO; } udelay(1); } } return 0; } static int tegra_spi_start_dma_based_transfer( struct tegra_spi_data *tspi, struct spi_transfer *t) { u32 val; unsigned int len; int ret = 0; u8 dma_burst; struct dma_slave_config dma_sconfig = {0}; val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1); tegra_spi_writel(tspi, val, SPI_DMA_BLK); Loading @@ -496,12 +542,16 @@ static int tegra_spi_start_dma_based_transfer( len = tspi->curr_dma_words * 4; /* Set attention level based on length of transfer */ if (len & 0xF) if (len & 0xF) { val |= SPI_TX_TRIG_1 | SPI_RX_TRIG_1; else if (((len) >> 4) & 0x1) dma_burst = 1; } else if (((len) >> 4) & 0x1) { val |= SPI_TX_TRIG_4 | SPI_RX_TRIG_4; else dma_burst = 4; } else { val |= SPI_TX_TRIG_8 | SPI_RX_TRIG_8; dma_burst = 8; } if (tspi->cur_direction & DATA_DIR_TX) val |= SPI_IE_TX; Loading @@ -512,7 +562,18 @@ static int tegra_spi_start_dma_based_transfer( tegra_spi_writel(tspi, val, SPI_DMA_CTL); tspi->dma_control_reg = val; dma_sconfig.device_fc = true; if (tspi->cur_direction & DATA_DIR_TX) { dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO; dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_sconfig.dst_maxburst = dma_burst; ret = dmaengine_slave_config(tspi->tx_dma_chan, &dma_sconfig); if (ret < 0) { dev_err(tspi->dev, "DMA slave config failed: %d\n", ret); return ret; } tegra_spi_copy_client_txbuf_to_spi_txbuf(tspi, t); ret = tegra_spi_start_tx_dma(tspi, len); if (ret < 0) { Loading @@ -523,6 +584,16 @@ static int tegra_spi_start_dma_based_transfer( } if (tspi->cur_direction & DATA_DIR_RX) { dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO; dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_sconfig.src_maxburst = dma_burst; ret = dmaengine_slave_config(tspi->rx_dma_chan, &dma_sconfig); if (ret < 0) { dev_err(tspi->dev, "DMA slave config failed: %d\n", ret); return ret; } /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, tspi->dma_buf_size, DMA_FROM_DEVICE); Loading Loading @@ -582,7 +653,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, u32 *dma_buf; dma_addr_t dma_phys; int ret; struct dma_slave_config dma_sconfig; dma_chan = dma_request_slave_channel_reason(tspi->dev, dma_to_memory ? "rx" : "tx"); Loading @@ -602,19 +672,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, return -ENOMEM; } if (dma_to_memory) { dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO; dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_sconfig.src_maxburst = 0; } else { dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO; dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_sconfig.dst_maxburst = 0; } ret = dmaengine_slave_config(dma_chan, &dma_sconfig); if (ret) goto scrub; if (dma_to_memory) { tspi->rx_dma_chan = dma_chan; tspi->rx_dma_buf = dma_buf; Loading @@ -625,11 +682,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, tspi->tx_dma_phys = dma_phys; } return 0; scrub: dma_free_coherent(tspi->dev, tspi->dma_buf_size, dma_buf, dma_phys); dma_release_channel(dma_chan); return ret; } static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi, Loading Loading @@ -735,6 +787,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, if (tspi->is_packed) command1 |= SPI_PACKED; else command1 &= ~SPI_PACKED; command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN); tspi->cur_direction = 0; Loading @@ -753,6 +807,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n", tspi->def_command1_reg, (unsigned)command1); ret = tegra_spi_flush_fifos(tspi); if (ret < 0) return ret; if (total_fifo_words > SPI_FIFO_DEPTH) ret = tegra_spi_start_dma_based_transfer(tspi, t); else Loading Loading @@ -804,6 +861,19 @@ static void tegra_spi_transfer_delay(int delay) udelay(delay % 1000); } static void tegra_spi_transfer_end(struct spi_device *spi) { struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); int cs_val = (spi->mode & SPI_CS_HIGH) ? 0 : 1; if (cs_val) tspi->command1_reg |= SPI_CS_SW_VAL; else tspi->command1_reg &= ~SPI_CS_SW_VAL; tegra_spi_writel(tspi, tspi->command1_reg, SPI_COMMAND1); tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); } static int tegra_spi_transfer_one_message(struct spi_master *master, struct spi_message *msg) { Loading Loading @@ -843,7 +913,17 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, if (WARN_ON(ret == 0)) { dev_err(tspi->dev, "spi transfer timeout, err %d\n", ret); if (tspi->is_curr_dma_xfer && (tspi->cur_direction & DATA_DIR_TX)) dmaengine_terminate_all(tspi->tx_dma_chan); if (tspi->is_curr_dma_xfer && (tspi->cur_direction & DATA_DIR_RX)) dmaengine_terminate_all(tspi->rx_dma_chan); ret = -EIO; tegra_spi_flush_fifos(tspi); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); goto complete_xfer; } Loading @@ -856,8 +936,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, complete_xfer: if (ret < 0 || skip) { tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); goto exit; } else if (list_is_last(&xfer->transfer_list, Loading @@ -865,13 +944,11 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, if (xfer->cs_change) tspi->cs_control = spi; else { tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); } } else if (xfer->cs_change) { tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); } Loading @@ -894,11 +971,13 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); tegra_spi_flush_fifos(tspi); complete(&tspi->xfer_completion); spin_unlock_irqrestore(&tspi->lock, flags); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); complete(&tspi->xfer_completion); goto exit; return IRQ_HANDLED; } if (tspi->cur_direction & DATA_DIR_RX) Loading Loading @@ -966,11 +1045,12 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); tegra_spi_flush_fifos(tspi); complete(&tspi->xfer_completion); spin_unlock_irqrestore(&tspi->lock, flags); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); complete(&tspi->xfer_completion); spin_unlock_irqrestore(&tspi->lock, flags); return IRQ_HANDLED; } Loading Loading @@ -1072,27 +1152,19 @@ static int tegra_spi_probe(struct platform_device *pdev) spi_irq = platform_get_irq(pdev, 0); tspi->irq = spi_irq; ret = request_threaded_irq(tspi->irq, tegra_spi_isr, tegra_spi_isr_thread, IRQF_ONESHOT, dev_name(&pdev->dev), tspi); if (ret < 0) { dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", tspi->irq); goto exit_free_master; } tspi->clk = devm_clk_get(&pdev->dev, "spi"); if (IS_ERR(tspi->clk)) { dev_err(&pdev->dev, "can not get clock\n"); ret = PTR_ERR(tspi->clk); goto exit_free_irq; goto exit_free_master; } tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi"); if (IS_ERR(tspi->rst)) { dev_err(&pdev->dev, "can not get reset\n"); ret = PTR_ERR(tspi->rst); goto exit_free_irq; goto exit_free_master; } tspi->max_buf_size = SPI_FIFO_DEPTH << 2; Loading @@ -1100,7 +1172,7 @@ static int tegra_spi_probe(struct platform_device *pdev) ret = tegra_spi_init_dma_param(tspi, true); if (ret < 0) goto exit_free_irq; goto exit_free_master; ret = tegra_spi_init_dma_param(tspi, false); if (ret < 0) goto exit_rx_dma_free; Loading @@ -1122,18 +1194,32 @@ static int tegra_spi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret); goto exit_pm_disable; } reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); tspi->def_command1_reg = SPI_M_S; tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); pm_runtime_put(&pdev->dev); ret = request_threaded_irq(tspi->irq, tegra_spi_isr, tegra_spi_isr_thread, IRQF_ONESHOT, dev_name(&pdev->dev), tspi); if (ret < 0) { dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", tspi->irq); goto exit_pm_disable; } master->dev.of_node = pdev->dev.of_node; ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "can not register to master err %d\n", ret); goto exit_pm_disable; goto exit_free_irq; } return ret; exit_free_irq: free_irq(spi_irq, tspi); exit_pm_disable: pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) Loading @@ -1141,8 +1227,6 @@ static int tegra_spi_probe(struct platform_device *pdev) tegra_spi_deinit_dma_param(tspi, false); exit_rx_dma_free: tegra_spi_deinit_dma_param(tspi, true); exit_free_irq: free_irq(spi_irq, tspi); exit_free_master: spi_master_put(master); return ret; Loading drivers/spi/spi-tegra20-slink.c +9 −3 Original line number Diff line number Diff line Loading @@ -717,9 +717,6 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, command2 = tspi->command2_reg; command2 &= ~(SLINK_RXEN | SLINK_TXEN); tegra_slink_writel(tspi, command, SLINK_COMMAND); tspi->command_reg = command; tspi->cur_direction = 0; if (t->rx_buf) { command2 |= SLINK_RXEN; Loading @@ -729,9 +726,18 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, command2 |= SLINK_TXEN; tspi->cur_direction |= DATA_DIR_TX; } /* * Writing to the command2 register bevore the command register prevents * a spike in chip_select line 0. This selects the chip_select line * before changing the chip_select value. */ tegra_slink_writel(tspi, command2, SLINK_COMMAND2); tspi->command2_reg = command2; tegra_slink_writel(tspi, command, SLINK_COMMAND); tspi->command_reg = command; if (total_fifo_words > SLINK_FIFO_DEPTH) ret = tegra_slink_start_dma_based_transfer(tspi, t); else Loading Loading
drivers/spi/spi-fsl-lpspi.c +2 −2 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ #define CFGR1_PCSPOL BIT(8) #define CFGR1_NOSTALL BIT(3) #define CFGR1_MASTER BIT(0) #define FSR_RXCOUNT (BIT(16)|BIT(17)|BIT(18)) #define FSR_TXCOUNT (0xFF) #define RSR_RXEMPTY BIT(1) #define TCR_CPOL BIT(31) #define TCR_CPHA BIT(30) Loading Loading @@ -771,7 +771,7 @@ static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) } if (temp_SR & SR_MBF || readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_RXCOUNT) { readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_TXCOUNT) { writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR); fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); return IRQ_HANDLED; Loading
drivers/spi/spi-gpio.c +0 −1 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ * platform_device->driver_data ... points to spi_gpio * * spi->controller_state ... reserved for bitbang framework code * spi->controller_data ... holds chipselect GPIO * * spi->master->dev.driver_data ... points to spi_gpio->bitbang */ Loading
drivers/spi/spi-pic32.c +1 −1 Original line number Diff line number Diff line Loading @@ -559,7 +559,7 @@ static int pic32_spi_one_transfer(struct spi_master *master, dev_err(&spi->dev, "wait error/timedout\n"); if (dma_issued) { dmaengine_terminate_all(master->dma_rx); dmaengine_terminate_all(master->dma_rx); dmaengine_terminate_all(master->dma_tx); } ret = -ETIMEDOUT; } else { Loading
drivers/spi/spi-tegra114.c +146 −62 Original line number Diff line number Diff line Loading @@ -307,10 +307,16 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } tspi->cur_tx_pos += written_words * tspi->bytes_per_word; } else { unsigned int write_bytes; max_n_32bit = min(tspi->curr_dma_words, tx_empty_count); written_words = max_n_32bit; nbytes = written_words * tspi->bytes_per_word; if (nbytes > t->len - tspi->cur_pos) nbytes = t->len - tspi->cur_pos; write_bytes = nbytes; for (count = 0; count < max_n_32bit; count++) { u32 x = 0; Loading @@ -319,8 +325,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } tspi->cur_tx_pos += write_bytes; } tspi->cur_tx_pos += written_words * tspi->bytes_per_word; return written_words; } Loading @@ -344,20 +352,27 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf( for (i = 0; len && (i < 4); i++, len--) *rx_buf++ = (x >> i*8) & 0xFF; } tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; read_words += tspi->curr_dma_words; tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; u8 bytes_per_word = tspi->bytes_per_word; unsigned int read_bytes; len = rx_full_count * bytes_per_word; if (len > t->len - tspi->cur_pos) len = t->len - tspi->cur_pos; read_bytes = len; for (count = 0; count < rx_full_count; count++) { u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask; for (i = 0; (i < tspi->bytes_per_word); i++) for (i = 0; len && (i < bytes_per_word); i++, len--) *rx_buf++ = (x >> (i*8)) & 0xFF; } tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word; read_words += rx_full_count; tspi->cur_rx_pos += read_bytes; } return read_words; } Loading @@ -372,12 +387,17 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len); tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { unsigned int i; unsigned int count; u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos; unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; unsigned int write_bytes; if (consume > t->len - tspi->cur_pos) consume = t->len - tspi->cur_pos; write_bytes = consume; for (count = 0; count < tspi->curr_dma_words; count++) { u32 x = 0; Loading @@ -386,8 +406,9 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tspi->tx_dma_buf[count] = x; } tspi->cur_tx_pos += write_bytes; } tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word; /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys, Loading @@ -405,20 +426,28 @@ static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf( unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len); tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { unsigned int i; unsigned int count; unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos; u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; unsigned int read_bytes; if (consume > t->len - tspi->cur_pos) consume = t->len - tspi->cur_pos; read_bytes = consume; for (count = 0; count < tspi->curr_dma_words; count++) { u32 x = tspi->rx_dma_buf[count] & rx_mask; for (i = 0; (i < tspi->bytes_per_word); i++) for (i = 0; consume && (i < tspi->bytes_per_word); i++, consume--) *rx_buf++ = (x >> (i*8)) & 0xFF; } tspi->cur_rx_pos += read_bytes; } tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, Loading Loading @@ -470,22 +499,39 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len) return 0; } static int tegra_spi_start_dma_based_transfer( struct tegra_spi_data *tspi, struct spi_transfer *t) static int tegra_spi_flush_fifos(struct tegra_spi_data *tspi) { u32 val; unsigned int len; int ret = 0; unsigned long timeout = jiffies + HZ; u32 status; /* Make sure that Rx and Tx fifo are empty */ status = tegra_spi_readl(tspi, SPI_FIFO_STATUS); if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) { dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n", (unsigned)status); status |= SPI_RX_FIFO_FLUSH | SPI_TX_FIFO_FLUSH; tegra_spi_writel(tspi, status, SPI_FIFO_STATUS); while ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) { status = tegra_spi_readl(tspi, SPI_FIFO_STATUS); if (time_after(jiffies, timeout)) { dev_err(tspi->dev, "timeout waiting for fifo flush\n"); return -EIO; } udelay(1); } } return 0; } static int tegra_spi_start_dma_based_transfer( struct tegra_spi_data *tspi, struct spi_transfer *t) { u32 val; unsigned int len; int ret = 0; u8 dma_burst; struct dma_slave_config dma_sconfig = {0}; val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1); tegra_spi_writel(tspi, val, SPI_DMA_BLK); Loading @@ -496,12 +542,16 @@ static int tegra_spi_start_dma_based_transfer( len = tspi->curr_dma_words * 4; /* Set attention level based on length of transfer */ if (len & 0xF) if (len & 0xF) { val |= SPI_TX_TRIG_1 | SPI_RX_TRIG_1; else if (((len) >> 4) & 0x1) dma_burst = 1; } else if (((len) >> 4) & 0x1) { val |= SPI_TX_TRIG_4 | SPI_RX_TRIG_4; else dma_burst = 4; } else { val |= SPI_TX_TRIG_8 | SPI_RX_TRIG_8; dma_burst = 8; } if (tspi->cur_direction & DATA_DIR_TX) val |= SPI_IE_TX; Loading @@ -512,7 +562,18 @@ static int tegra_spi_start_dma_based_transfer( tegra_spi_writel(tspi, val, SPI_DMA_CTL); tspi->dma_control_reg = val; dma_sconfig.device_fc = true; if (tspi->cur_direction & DATA_DIR_TX) { dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO; dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_sconfig.dst_maxburst = dma_burst; ret = dmaengine_slave_config(tspi->tx_dma_chan, &dma_sconfig); if (ret < 0) { dev_err(tspi->dev, "DMA slave config failed: %d\n", ret); return ret; } tegra_spi_copy_client_txbuf_to_spi_txbuf(tspi, t); ret = tegra_spi_start_tx_dma(tspi, len); if (ret < 0) { Loading @@ -523,6 +584,16 @@ static int tegra_spi_start_dma_based_transfer( } if (tspi->cur_direction & DATA_DIR_RX) { dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO; dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_sconfig.src_maxburst = dma_burst; ret = dmaengine_slave_config(tspi->rx_dma_chan, &dma_sconfig); if (ret < 0) { dev_err(tspi->dev, "DMA slave config failed: %d\n", ret); return ret; } /* Make the dma buffer to read by dma */ dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, tspi->dma_buf_size, DMA_FROM_DEVICE); Loading Loading @@ -582,7 +653,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, u32 *dma_buf; dma_addr_t dma_phys; int ret; struct dma_slave_config dma_sconfig; dma_chan = dma_request_slave_channel_reason(tspi->dev, dma_to_memory ? "rx" : "tx"); Loading @@ -602,19 +672,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, return -ENOMEM; } if (dma_to_memory) { dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO; dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_sconfig.src_maxburst = 0; } else { dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO; dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_sconfig.dst_maxburst = 0; } ret = dmaengine_slave_config(dma_chan, &dma_sconfig); if (ret) goto scrub; if (dma_to_memory) { tspi->rx_dma_chan = dma_chan; tspi->rx_dma_buf = dma_buf; Loading @@ -625,11 +682,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, tspi->tx_dma_phys = dma_phys; } return 0; scrub: dma_free_coherent(tspi->dev, tspi->dma_buf_size, dma_buf, dma_phys); dma_release_channel(dma_chan); return ret; } static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi, Loading Loading @@ -735,6 +787,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, if (tspi->is_packed) command1 |= SPI_PACKED; else command1 &= ~SPI_PACKED; command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN); tspi->cur_direction = 0; Loading @@ -753,6 +807,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n", tspi->def_command1_reg, (unsigned)command1); ret = tegra_spi_flush_fifos(tspi); if (ret < 0) return ret; if (total_fifo_words > SPI_FIFO_DEPTH) ret = tegra_spi_start_dma_based_transfer(tspi, t); else Loading Loading @@ -804,6 +861,19 @@ static void tegra_spi_transfer_delay(int delay) udelay(delay % 1000); } static void tegra_spi_transfer_end(struct spi_device *spi) { struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); int cs_val = (spi->mode & SPI_CS_HIGH) ? 0 : 1; if (cs_val) tspi->command1_reg |= SPI_CS_SW_VAL; else tspi->command1_reg &= ~SPI_CS_SW_VAL; tegra_spi_writel(tspi, tspi->command1_reg, SPI_COMMAND1); tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); } static int tegra_spi_transfer_one_message(struct spi_master *master, struct spi_message *msg) { Loading Loading @@ -843,7 +913,17 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, if (WARN_ON(ret == 0)) { dev_err(tspi->dev, "spi transfer timeout, err %d\n", ret); if (tspi->is_curr_dma_xfer && (tspi->cur_direction & DATA_DIR_TX)) dmaengine_terminate_all(tspi->tx_dma_chan); if (tspi->is_curr_dma_xfer && (tspi->cur_direction & DATA_DIR_RX)) dmaengine_terminate_all(tspi->rx_dma_chan); ret = -EIO; tegra_spi_flush_fifos(tspi); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); goto complete_xfer; } Loading @@ -856,8 +936,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, complete_xfer: if (ret < 0 || skip) { tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); goto exit; } else if (list_is_last(&xfer->transfer_list, Loading @@ -865,13 +944,11 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, if (xfer->cs_change) tspi->cs_control = spi; else { tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); } } else if (xfer->cs_change) { tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); } Loading @@ -894,11 +971,13 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); tegra_spi_flush_fifos(tspi); complete(&tspi->xfer_completion); spin_unlock_irqrestore(&tspi->lock, flags); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); complete(&tspi->xfer_completion); goto exit; return IRQ_HANDLED; } if (tspi->cur_direction & DATA_DIR_RX) Loading Loading @@ -966,11 +1045,12 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); tegra_spi_flush_fifos(tspi); complete(&tspi->xfer_completion); spin_unlock_irqrestore(&tspi->lock, flags); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); complete(&tspi->xfer_completion); spin_unlock_irqrestore(&tspi->lock, flags); return IRQ_HANDLED; } Loading Loading @@ -1072,27 +1152,19 @@ static int tegra_spi_probe(struct platform_device *pdev) spi_irq = platform_get_irq(pdev, 0); tspi->irq = spi_irq; ret = request_threaded_irq(tspi->irq, tegra_spi_isr, tegra_spi_isr_thread, IRQF_ONESHOT, dev_name(&pdev->dev), tspi); if (ret < 0) { dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", tspi->irq); goto exit_free_master; } tspi->clk = devm_clk_get(&pdev->dev, "spi"); if (IS_ERR(tspi->clk)) { dev_err(&pdev->dev, "can not get clock\n"); ret = PTR_ERR(tspi->clk); goto exit_free_irq; goto exit_free_master; } tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi"); if (IS_ERR(tspi->rst)) { dev_err(&pdev->dev, "can not get reset\n"); ret = PTR_ERR(tspi->rst); goto exit_free_irq; goto exit_free_master; } tspi->max_buf_size = SPI_FIFO_DEPTH << 2; Loading @@ -1100,7 +1172,7 @@ static int tegra_spi_probe(struct platform_device *pdev) ret = tegra_spi_init_dma_param(tspi, true); if (ret < 0) goto exit_free_irq; goto exit_free_master; ret = tegra_spi_init_dma_param(tspi, false); if (ret < 0) goto exit_rx_dma_free; Loading @@ -1122,18 +1194,32 @@ static int tegra_spi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret); goto exit_pm_disable; } reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); tspi->def_command1_reg = SPI_M_S; tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); pm_runtime_put(&pdev->dev); ret = request_threaded_irq(tspi->irq, tegra_spi_isr, tegra_spi_isr_thread, IRQF_ONESHOT, dev_name(&pdev->dev), tspi); if (ret < 0) { dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", tspi->irq); goto exit_pm_disable; } master->dev.of_node = pdev->dev.of_node; ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "can not register to master err %d\n", ret); goto exit_pm_disable; goto exit_free_irq; } return ret; exit_free_irq: free_irq(spi_irq, tspi); exit_pm_disable: pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) Loading @@ -1141,8 +1227,6 @@ static int tegra_spi_probe(struct platform_device *pdev) tegra_spi_deinit_dma_param(tspi, false); exit_rx_dma_free: tegra_spi_deinit_dma_param(tspi, true); exit_free_irq: free_irq(spi_irq, tspi); exit_free_master: spi_master_put(master); return ret; Loading
drivers/spi/spi-tegra20-slink.c +9 −3 Original line number Diff line number Diff line Loading @@ -717,9 +717,6 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, command2 = tspi->command2_reg; command2 &= ~(SLINK_RXEN | SLINK_TXEN); tegra_slink_writel(tspi, command, SLINK_COMMAND); tspi->command_reg = command; tspi->cur_direction = 0; if (t->rx_buf) { command2 |= SLINK_RXEN; Loading @@ -729,9 +726,18 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, command2 |= SLINK_TXEN; tspi->cur_direction |= DATA_DIR_TX; } /* * Writing to the command2 register bevore the command register prevents * a spike in chip_select line 0. This selects the chip_select line * before changing the chip_select value. */ tegra_slink_writel(tspi, command2, SLINK_COMMAND2); tspi->command2_reg = command2; tegra_slink_writel(tspi, command, SLINK_COMMAND); tspi->command_reg = command; if (total_fifo_words > SLINK_FIFO_DEPTH) ret = tegra_slink_start_dma_based_transfer(tspi, t); else Loading