Commit e1a7d167 authored by Mark Brown's avatar Mark Brown

Merge branch 'spi-5.1' into spi-5.2

parents 9fda6693 a026525d
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
#define CFGR1_PCSPOL BIT(8) #define CFGR1_PCSPOL BIT(8)
#define CFGR1_NOSTALL BIT(3) #define CFGR1_NOSTALL BIT(3)
#define CFGR1_MASTER BIT(0) #define CFGR1_MASTER BIT(0)
#define FSR_RXCOUNT (BIT(16)|BIT(17)|BIT(18)) #define FSR_TXCOUNT (0xFF)
#define RSR_RXEMPTY BIT(1) #define RSR_RXEMPTY BIT(1)
#define TCR_CPOL BIT(31) #define TCR_CPOL BIT(31)
#define TCR_CPHA BIT(30) #define TCR_CPHA BIT(30)
...@@ -771,7 +771,7 @@ static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) ...@@ -771,7 +771,7 @@ static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id)
} }
if (temp_SR & SR_MBF || 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); writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR);
fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE);
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
* platform_device->driver_data ... points to spi_gpio * platform_device->driver_data ... points to spi_gpio
* *
* spi->controller_state ... reserved for bitbang framework code * spi->controller_state ... reserved for bitbang framework code
* spi->controller_data ... holds chipselect GPIO
* *
* spi->master->dev.driver_data ... points to spi_gpio->bitbang * spi->master->dev.driver_data ... points to spi_gpio->bitbang
*/ */
......
...@@ -559,7 +559,7 @@ static int pic32_spi_one_transfer(struct spi_master *master, ...@@ -559,7 +559,7 @@ static int pic32_spi_one_transfer(struct spi_master *master,
dev_err(&spi->dev, "wait error/timedout\n"); dev_err(&spi->dev, "wait error/timedout\n");
if (dma_issued) { if (dma_issued) {
dmaengine_terminate_all(master->dma_rx); dmaengine_terminate_all(master->dma_rx);
dmaengine_terminate_all(master->dma_rx); dmaengine_terminate_all(master->dma_tx);
} }
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
} else { } else {
......
...@@ -307,10 +307,16 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( ...@@ -307,10 +307,16 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
x |= (u32)(*tx_buf++) << (i * 8); x |= (u32)(*tx_buf++) << (i * 8);
tegra_spi_writel(tspi, x, SPI_TX_FIFO); tegra_spi_writel(tspi, x, SPI_TX_FIFO);
} }
tspi->cur_tx_pos += written_words * tspi->bytes_per_word;
} else { } else {
unsigned int write_bytes;
max_n_32bit = min(tspi->curr_dma_words, tx_empty_count); max_n_32bit = min(tspi->curr_dma_words, tx_empty_count);
written_words = max_n_32bit; written_words = max_n_32bit;
nbytes = written_words * tspi->bytes_per_word; 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++) { for (count = 0; count < max_n_32bit; count++) {
u32 x = 0; u32 x = 0;
...@@ -319,8 +325,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( ...@@ -319,8 +325,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
x |= (u32)(*tx_buf++) << (i * 8); x |= (u32)(*tx_buf++) << (i * 8);
tegra_spi_writel(tspi, x, SPI_TX_FIFO); 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; return written_words;
} }
...@@ -344,20 +352,27 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf( ...@@ -344,20 +352,27 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
for (i = 0; len && (i < 4); i++, len--) for (i = 0; len && (i < 4); i++, len--)
*rx_buf++ = (x >> i*8) & 0xFF; *rx_buf++ = (x >> i*8) & 0xFF;
} }
tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
read_words += tspi->curr_dma_words; read_words += tspi->curr_dma_words;
tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
} else { } else {
u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; 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++) { for (count = 0; count < rx_full_count; count++) {
u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask; 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; *rx_buf++ = (x >> (i*8)) & 0xFF;
} }
tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word;
read_words += rx_full_count; read_words += rx_full_count;
tspi->cur_rx_pos += read_bytes;
} }
return read_words; return read_words;
} }
...@@ -372,12 +387,17 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( ...@@ -372,12 +387,17 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len); 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 { } else {
unsigned int i; unsigned int i;
unsigned int count; unsigned int count;
u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos; u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word; 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++) { for (count = 0; count < tspi->curr_dma_words; count++) {
u32 x = 0; u32 x = 0;
...@@ -386,8 +406,9 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( ...@@ -386,8 +406,9 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
x |= (u32)(*tx_buf++) << (i * 8); x |= (u32)(*tx_buf++) << (i * 8);
tspi->tx_dma_buf[count] = x; 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 */ /* Make the dma buffer to read by dma */
dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys, dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys,
...@@ -405,20 +426,28 @@ static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf( ...@@ -405,20 +426,28 @@ static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf(
unsigned len = tspi->curr_dma_words * tspi->bytes_per_word; unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len); 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 { } else {
unsigned int i; unsigned int i;
unsigned int count; unsigned int count;
unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos; unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
u32 rx_mask = ((u32)1 << t->bits_per_word) - 1; 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++) { for (count = 0; count < tspi->curr_dma_words; count++) {
u32 x = tspi->rx_dma_buf[count] & rx_mask; 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; *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 */ /* Make the dma buffer to read by dma */
dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
...@@ -470,22 +499,39 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len) ...@@ -470,22 +499,39 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len)
return 0; return 0;
} }
static int tegra_spi_start_dma_based_transfer( static int tegra_spi_flush_fifos(struct tegra_spi_data *tspi)
struct tegra_spi_data *tspi, struct spi_transfer *t)
{ {
u32 val; unsigned long timeout = jiffies + HZ;
unsigned int len;
int ret = 0;
u32 status; u32 status;
/* Make sure that Rx and Tx fifo are empty */
status = tegra_spi_readl(tspi, SPI_FIFO_STATUS); status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) { if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n", status |= SPI_RX_FIFO_FLUSH | SPI_TX_FIFO_FLUSH;
(unsigned)status); 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; 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); val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1);
tegra_spi_writel(tspi, val, SPI_DMA_BLK); tegra_spi_writel(tspi, val, SPI_DMA_BLK);
...@@ -496,12 +542,16 @@ static int tegra_spi_start_dma_based_transfer( ...@@ -496,12 +542,16 @@ static int tegra_spi_start_dma_based_transfer(
len = tspi->curr_dma_words * 4; len = tspi->curr_dma_words * 4;
/* Set attention level based on length of transfer */ /* Set attention level based on length of transfer */
if (len & 0xF) if (len & 0xF) {
val |= SPI_TX_TRIG_1 | SPI_RX_TRIG_1; 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; val |= SPI_TX_TRIG_4 | SPI_RX_TRIG_4;
else dma_burst = 4;
} else {
val |= SPI_TX_TRIG_8 | SPI_RX_TRIG_8; val |= SPI_TX_TRIG_8 | SPI_RX_TRIG_8;
dma_burst = 8;
}
if (tspi->cur_direction & DATA_DIR_TX) if (tspi->cur_direction & DATA_DIR_TX)
val |= SPI_IE_TX; val |= SPI_IE_TX;
...@@ -512,7 +562,18 @@ static int tegra_spi_start_dma_based_transfer( ...@@ -512,7 +562,18 @@ static int tegra_spi_start_dma_based_transfer(
tegra_spi_writel(tspi, val, SPI_DMA_CTL); tegra_spi_writel(tspi, val, SPI_DMA_CTL);
tspi->dma_control_reg = val; tspi->dma_control_reg = val;
dma_sconfig.device_fc = true;
if (tspi->cur_direction & DATA_DIR_TX) { 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); tegra_spi_copy_client_txbuf_to_spi_txbuf(tspi, t);
ret = tegra_spi_start_tx_dma(tspi, len); ret = tegra_spi_start_tx_dma(tspi, len);
if (ret < 0) { if (ret < 0) {
...@@ -523,6 +584,16 @@ static int tegra_spi_start_dma_based_transfer( ...@@ -523,6 +584,16 @@ static int tegra_spi_start_dma_based_transfer(
} }
if (tspi->cur_direction & DATA_DIR_RX) { 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 */ /* Make the dma buffer to read by dma */
dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
tspi->dma_buf_size, DMA_FROM_DEVICE); tspi->dma_buf_size, DMA_FROM_DEVICE);
...@@ -582,7 +653,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, ...@@ -582,7 +653,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi,
u32 *dma_buf; u32 *dma_buf;
dma_addr_t dma_phys; dma_addr_t dma_phys;
int ret; int ret;
struct dma_slave_config dma_sconfig;
dma_chan = dma_request_slave_channel_reason(tspi->dev, dma_chan = dma_request_slave_channel_reason(tspi->dev,
dma_to_memory ? "rx" : "tx"); dma_to_memory ? "rx" : "tx");
...@@ -602,19 +672,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, ...@@ -602,19 +672,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi,
return -ENOMEM; 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) { if (dma_to_memory) {
tspi->rx_dma_chan = dma_chan; tspi->rx_dma_chan = dma_chan;
tspi->rx_dma_buf = dma_buf; tspi->rx_dma_buf = dma_buf;
...@@ -625,11 +682,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, ...@@ -625,11 +682,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi,
tspi->tx_dma_phys = dma_phys; tspi->tx_dma_phys = dma_phys;
} }
return 0; 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, static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
...@@ -735,6 +787,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, ...@@ -735,6 +787,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi,
if (tspi->is_packed) if (tspi->is_packed)
command1 |= SPI_PACKED; command1 |= SPI_PACKED;
else
command1 &= ~SPI_PACKED;
command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN); command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN);
tspi->cur_direction = 0; tspi->cur_direction = 0;
...@@ -753,6 +807,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, ...@@ -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", dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n",
tspi->def_command1_reg, (unsigned)command1); tspi->def_command1_reg, (unsigned)command1);
ret = tegra_spi_flush_fifos(tspi);
if (ret < 0)
return ret;
if (total_fifo_words > SPI_FIFO_DEPTH) if (total_fifo_words > SPI_FIFO_DEPTH)
ret = tegra_spi_start_dma_based_transfer(tspi, t); ret = tegra_spi_start_dma_based_transfer(tspi, t);
else else
...@@ -804,6 +861,19 @@ static void tegra_spi_transfer_delay(int delay) ...@@ -804,6 +861,19 @@ static void tegra_spi_transfer_delay(int delay)
udelay(delay % 1000); 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, static int tegra_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg) struct spi_message *msg)
{ {
...@@ -843,7 +913,17 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, ...@@ -843,7 +913,17 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
if (WARN_ON(ret == 0)) { if (WARN_ON(ret == 0)) {
dev_err(tspi->dev, dev_err(tspi->dev,
"spi transfer timeout, err %d\n", ret); "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; ret = -EIO;
tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
goto complete_xfer; goto complete_xfer;
} }
...@@ -856,8 +936,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, ...@@ -856,8 +936,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
complete_xfer: complete_xfer:
if (ret < 0 || skip) { if (ret < 0 || skip) {
tegra_spi_writel(tspi, tspi->def_command1_reg, tegra_spi_transfer_end(spi);
SPI_COMMAND1);
tegra_spi_transfer_delay(xfer->delay_usecs); tegra_spi_transfer_delay(xfer->delay_usecs);
goto exit; goto exit;
} else if (list_is_last(&xfer->transfer_list, } else if (list_is_last(&xfer->transfer_list,
...@@ -865,13 +944,11 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, ...@@ -865,13 +944,11 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
if (xfer->cs_change) if (xfer->cs_change)
tspi->cs_control = spi; tspi->cs_control = spi;
else { else {
tegra_spi_writel(tspi, tspi->def_command1_reg, tegra_spi_transfer_end(spi);
SPI_COMMAND1);
tegra_spi_transfer_delay(xfer->delay_usecs); tegra_spi_transfer_delay(xfer->delay_usecs);
} }
} else if (xfer->cs_change) { } else if (xfer->cs_change) {
tegra_spi_writel(tspi, tspi->def_command1_reg, tegra_spi_transfer_end(spi);
SPI_COMMAND1);
tegra_spi_transfer_delay(xfer->delay_usecs); tegra_spi_transfer_delay(xfer->delay_usecs);
} }
...@@ -894,11 +971,13 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) ...@@ -894,11 +971,13 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi)
tspi->status_reg); tspi->status_reg);
dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n",
tspi->command1_reg, tspi->dma_control_reg); 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); reset_control_assert(tspi->rst);
udelay(2); udelay(2);
reset_control_deassert(tspi->rst); reset_control_deassert(tspi->rst);
complete(&tspi->xfer_completion); return IRQ_HANDLED;
goto exit;
} }
if (tspi->cur_direction & DATA_DIR_RX) if (tspi->cur_direction & DATA_DIR_RX)
...@@ -966,11 +1045,12 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi) ...@@ -966,11 +1045,12 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi)
tspi->status_reg); tspi->status_reg);
dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n",
tspi->command1_reg, tspi->dma_control_reg); 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); reset_control_assert(tspi->rst);
udelay(2); udelay(2);
reset_control_deassert(tspi->rst); reset_control_deassert(tspi->rst);
complete(&tspi->xfer_completion);
spin_unlock_irqrestore(&tspi->lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1072,27 +1152,19 @@ static int tegra_spi_probe(struct platform_device *pdev) ...@@ -1072,27 +1152,19 @@ static int tegra_spi_probe(struct platform_device *pdev)
spi_irq = platform_get_irq(pdev, 0); spi_irq = platform_get_irq(pdev, 0);
tspi->irq = spi_irq; 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"); tspi->clk = devm_clk_get(&pdev->dev, "spi");
if (IS_ERR(tspi->clk)) { if (IS_ERR(tspi->clk)) {
dev_err(&pdev->dev, "can not get clock\n"); dev_err(&pdev->dev, "can not get clock\n");
ret = PTR_ERR(tspi->clk); ret = PTR_ERR(tspi->clk);
goto exit_free_irq; goto exit_free_master;
} }
tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi"); tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi");
if (IS_ERR(tspi->rst)) { if (IS_ERR(tspi->rst)) {
dev_err(&pdev->dev, "can not get reset\n"); dev_err(&pdev->dev, "can not get reset\n");
ret = PTR_ERR(tspi->rst); ret = PTR_ERR(tspi->rst);
goto exit_free_irq; goto exit_free_master;
} }
tspi->max_buf_size = SPI_FIFO_DEPTH << 2; tspi->max_buf_size = SPI_FIFO_DEPTH << 2;
...@@ -1100,7 +1172,7 @@ static int tegra_spi_probe(struct platform_device *pdev) ...@@ -1100,7 +1172,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
ret = tegra_spi_init_dma_param(tspi, true); ret = tegra_spi_init_dma_param(tspi, true);
if (ret < 0) if (ret < 0)
goto exit_free_irq; goto exit_free_master;
ret = tegra_spi_init_dma_param(tspi, false); ret = tegra_spi_init_dma_param(tspi, false);
if (ret < 0) if (ret < 0)
goto exit_rx_dma_free; goto exit_rx_dma_free;
...@@ -1122,18 +1194,32 @@ static int tegra_spi_probe(struct platform_device *pdev) ...@@ -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); dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
goto exit_pm_disable; goto exit_pm_disable;
} }
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
tspi->def_command1_reg = SPI_M_S; tspi->def_command1_reg = SPI_M_S;
tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
pm_runtime_put(&pdev->dev); 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; master->dev.of_node = pdev->dev.of_node;
ret = devm_spi_register_master(&pdev->dev, master); ret = devm_spi_register_master(&pdev->dev, master);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "can not register to master err %d\n", ret); dev_err(&pdev->dev, "can not register to master err %d\n", ret);
goto exit_pm_disable; goto exit_free_irq;
} }
return ret; return ret;
exit_free_irq:
free_irq(spi_irq, tspi);
exit_pm_disable: exit_pm_disable:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev)) if (!pm_runtime_status_suspended(&pdev->dev))
...@@ -1141,8 +1227,6 @@ static int tegra_spi_probe(struct platform_device *pdev) ...@@ -1141,8 +1227,6 @@ static int tegra_spi_probe(struct platform_device *pdev)
tegra_spi_deinit_dma_param(tspi, false); tegra_spi_deinit_dma_param(tspi, false);
exit_rx_dma_free: exit_rx_dma_free:
tegra_spi_deinit_dma_param(tspi, true); tegra_spi_deinit_dma_param(tspi, true);
exit_free_irq:
free_irq(spi_irq, tspi);
exit_free_master: exit_free_master:
spi_master_put(master); spi_master_put(master);
return ret; return ret;
......
...@@ -717,9 +717,6 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, ...@@ -717,9 +717,6 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
command2 = tspi->command2_reg; command2 = tspi->command2_reg;
command2 &= ~(SLINK_RXEN | SLINK_TXEN); command2 &= ~(SLINK_RXEN | SLINK_TXEN);
tegra_slink_writel(tspi, command, SLINK_COMMAND);
tspi->command_reg = command;
tspi->cur_direction = 0; tspi->cur_direction = 0;
if (t->rx_buf) { if (t->rx_buf) {
command2 |= SLINK_RXEN; command2 |= SLINK_RXEN;
...@@ -729,9 +726,18 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi, ...@@ -729,9 +726,18 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
command2 |= SLINK_TXEN; command2 |= SLINK_TXEN;
tspi->cur_direction |= DATA_DIR_TX; 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); tegra_slink_writel(tspi, command2, SLINK_COMMAND2);
tspi->command2_reg = command2; tspi->command2_reg = command2;
tegra_slink_writel(tspi, command, SLINK_COMMAND);
tspi->command_reg = command;
if (total_fifo_words > SLINK_FIFO_DEPTH) if (total_fifo_words > SLINK_FIFO_DEPTH)
ret = tegra_slink_start_dma_based_transfer(tspi, t); ret = tegra_slink_start_dma_based_transfer(tspi, t);
else else
......
...@@ -1299,18 +1299,27 @@ static void pch_free_dma_buf(struct pch_spi_board_data *board_dat, ...@@ -1299,18 +1299,27 @@ static void pch_free_dma_buf(struct pch_spi_board_data *board_dat,
dma->rx_buf_virt, dma->rx_buf_dma); dma->rx_buf_virt, dma->rx_buf_dma);
} }
static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat, static int pch_alloc_dma_buf(struct pch_spi_board_data *board_dat,
struct pch_spi_data *data) struct pch_spi_data *data)
{ {
struct pch_spi_dma_ctrl *dma; struct pch_spi_dma_ctrl *dma;
int ret;
dma = &data->dma; dma = &data->dma;
ret = 0;
/* Get Consistent memory for Tx DMA */ /* Get Consistent memory for Tx DMA */
dma->tx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev, dma->tx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev,
PCH_BUF_SIZE, &dma->tx_buf_dma, GFP_KERNEL); PCH_BUF_SIZE, &dma->tx_buf_dma, GFP_KERNEL);
if (!dma->tx_buf_virt)
ret = -ENOMEM;
/* Get Consistent memory for Rx DMA */ /* Get Consistent memory for Rx DMA */
dma->rx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev, dma->rx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev,
PCH_BUF_SIZE, &dma->rx_buf_dma, GFP_KERNEL); PCH_BUF_SIZE, &dma->rx_buf_dma, GFP_KERNEL);
if (!dma->rx_buf_virt)
ret = -ENOMEM;
return ret;
} }
static int pch_spi_pd_probe(struct platform_device *plat_dev) static int pch_spi_pd_probe(struct platform_device *plat_dev)
...@@ -1387,7 +1396,9 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev) ...@@ -1387,7 +1396,9 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
if (use_dma) { if (use_dma) {
dev_info(&plat_dev->dev, "Use DMA for data transfers\n"); dev_info(&plat_dev->dev, "Use DMA for data transfers\n");
pch_alloc_dma_buf(board_dat, data); ret = pch_alloc_dma_buf(board_dat, data);
if (ret)
goto err_spi_register_master;
} }
ret = spi_register_master(master); ret = spi_register_master(master);
......
...@@ -2199,6 +2199,8 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr) ...@@ -2199,6 +2199,8 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr)
*/ */
cs[i] = devm_gpiod_get_index_optional(dev, "cs", i, cs[i] = devm_gpiod_get_index_optional(dev, "cs", i,
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR(cs[i]))
return PTR_ERR(cs[i]);
if (cs[i]) { if (cs[i]) {
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment