tegra124: clean-ups for SPI driver
This addresses comments made in the first round of code reviews for the SPI driver and does a few minor clean-up tasks. It also adds better error handling in tegra_spi_cbfs_read() for the first transfer (sending the read command and address). BUG=none BRANCH=none TEST=built and booted on nyan Change-Id: I8ee85a6e815e4a65a6e3beb4fb51d7660bed2ff8 Reviewed-on: https://chromium-review.googlesource.com/173599 Reviewed-by: David Hendricks <dhendrix@chromium.org> Tested-by: David Hendricks <dhendrix@chromium.org> Commit-Queue: David James <davidjames@chromium.org>
This commit is contained in:
parent
d706bb70f4
commit
1e2f9fd442
2 changed files with 38 additions and 67 deletions
|
|
@ -127,14 +127,19 @@ struct tegra_spi_regs {
|
|||
u32 rx_data; /* 0x01c: SPI_RX_DATA */
|
||||
u32 dma_ctl; /* 0x020: SPI_DMA_CTL */
|
||||
u32 dma_blk; /* 0x024: SPI_DMA_BLK */
|
||||
u8 rsvd[0xe0]; /* 0x028-0x107: reserved */
|
||||
u32 rsvd[56]; /* 0x028-0x107: reserved */
|
||||
u32 tx_fifo; /* 0x108: SPI_FIFO1 */
|
||||
u8 rsvd2[0x7c]; /* 0x10c-0x187 reserved */
|
||||
u32 rsvd2[31]; /* 0x10c-0x187 reserved */
|
||||
u32 rx_fifo; /* 0x188: SPI_FIFO2 */
|
||||
u32 spare_ctl; /* 0x18c: SPI_SPARE_CTRL */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct tegra_spi_channel tegra_spi_channels[TEGRA124_NUM_SPI_CHANNELS] = {
|
||||
struct tegra_spi_channel {
|
||||
struct spi_slave slave;
|
||||
struct tegra_spi_regs *regs;
|
||||
};
|
||||
|
||||
static struct tegra_spi_channel tegra_spi_channels[] = {
|
||||
/*
|
||||
* Note: Tegra pinmux must be setup for corresponding SPI channel in
|
||||
* order for its registers to be accessible. If pinmux has not been
|
||||
|
|
@ -169,8 +174,13 @@ struct tegra_spi_channel tegra_spi_channels[TEGRA124_NUM_SPI_CHANNELS] = {
|
|||
},
|
||||
};
|
||||
|
||||
void spi_init(void)
|
||||
static void flush_fifos(struct tegra_spi_regs *regs)
|
||||
{
|
||||
setbits_le32(®s->fifo_status, SPI_FIFO_STATUS_RX_FIFO_FLUSH |
|
||||
SPI_FIFO_STATUS_TX_FIFO_FLUSH);
|
||||
while (read32(®s->fifo_status) &
|
||||
(SPI_FIFO_STATUS_RX_FIFO_FLUSH | SPI_FIFO_STATUS_TX_FIFO_FLUSH))
|
||||
;
|
||||
}
|
||||
|
||||
void tegra_spi_init(unsigned int bus)
|
||||
|
|
@ -190,39 +200,18 @@ void tegra_spi_init(unsigned int bus)
|
|||
SPI_CMD1_CS_SW_HW | SPI_CMD1_CS_SW_VAL);
|
||||
|
||||
/* 8-bit transfers, unpacked mode, most significant bit first */
|
||||
clrbits_le32(®s->command1, SPI_CMD1_BIT_LEN_MASK | SPI_CMD1_PACKED);
|
||||
clrbits_le32(®s->command1,
|
||||
SPI_CMD1_BIT_LEN_MASK | SPI_CMD1_PACKED);
|
||||
setbits_le32(®s->command1, 7 << SPI_CMD1_BIT_LEN_SHIFT);
|
||||
|
||||
/* flush FIFOs */
|
||||
setbits_le32(®s->fifo_status, SPI_FIFO_STATUS_RX_FIFO_FLUSH |
|
||||
SPI_FIFO_STATUS_TX_FIFO_FLUSH);
|
||||
while (read32(®s->fifo_status) &
|
||||
(SPI_FIFO_STATUS_RX_FIFO_FLUSH | SPI_FIFO_STATUS_TX_FIFO_FLUSH))
|
||||
;
|
||||
flush_fifos(regs);
|
||||
}
|
||||
printk(BIOS_INFO, "Tegra SPI bus %d initialized.\n", bus);
|
||||
|
||||
}
|
||||
|
||||
static struct tegra_spi_channel * const to_tegra_spi(int bus) {
|
||||
int i;
|
||||
struct tegra_spi_channel *channel = NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tegra_spi_channels); i++) {
|
||||
if (tegra_spi_channels[i].slave.bus == bus)
|
||||
channel = &tegra_spi_channels[i];
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
|
||||
{
|
||||
if (cs < 0 || cs > 3)
|
||||
return 0;
|
||||
if (!to_tegra_spi(bus))
|
||||
return 0;
|
||||
return 1;
|
||||
return &tegra_spi_channels[bus - 1];
|
||||
}
|
||||
|
||||
void spi_cs_activate(struct spi_slave *slave)
|
||||
|
|
@ -264,19 +253,19 @@ static void print_fifo_status(struct tegra_spi_channel *spi)
|
|||
{
|
||||
u32 status = read32(&spi->regs->fifo_status);
|
||||
|
||||
printk(BIOS_DEBUG, "Raw FIFO status: 0x%08x\n", status);
|
||||
printk(BIOS_INFO, "Raw FIFO status: 0x%08x\n", status);
|
||||
if (status & SPI_FIFO_STATUS_TX_FIFO_OVF)
|
||||
printk(BIOS_DEBUG, "\tTx overflow detected\n");
|
||||
printk(BIOS_INFO, "\tTx overflow detected\n");
|
||||
if (status & SPI_FIFO_STATUS_TX_FIFO_UNR)
|
||||
printk(BIOS_DEBUG, "\tTx underrun detected\n");
|
||||
printk(BIOS_INFO, "\tTx underrun detected\n");
|
||||
if (status & SPI_FIFO_STATUS_RX_FIFO_OVF)
|
||||
printk(BIOS_DEBUG, "\tRx overflow detected\n");
|
||||
printk(BIOS_INFO, "\tRx overflow detected\n");
|
||||
if (status & SPI_FIFO_STATUS_RX_FIFO_UNR)
|
||||
printk(BIOS_DEBUG, "\tRx underrun detected\n");
|
||||
printk(BIOS_INFO, "\tRx underrun detected\n");
|
||||
|
||||
printk(BIOS_DEBUG, "TX_FIFO: 0x%08x, TX_DATA: 0x%08x\n",
|
||||
printk(BIOS_INFO, "TX_FIFO: 0x%08x, TX_DATA: 0x%08x\n",
|
||||
read32(&spi->regs->tx_fifo), read32(&spi->regs->tx_data));
|
||||
printk(BIOS_DEBUG, "RX_FIFO: 0x%08x, RX_DATA: 0x%08x\n",
|
||||
printk(BIOS_INFO, "RX_FIFO: 0x%08x, RX_DATA: 0x%08x\n",
|
||||
read32(&spi->regs->rx_fifo), read32(&spi->regs->rx_data));
|
||||
}
|
||||
|
||||
|
|
@ -293,8 +282,8 @@ static void clear_fifo_status(struct tegra_spi_channel *spi)
|
|||
static void dump_regs(struct tegra_spi_channel *spi,
|
||||
struct apb_dma_channel *dma)
|
||||
{
|
||||
printk(BIOS_DEBUG, "DMA regs:\n");
|
||||
printk(BIOS_DEBUG, "\tahb_ptr: 0x%08x\n"
|
||||
printk(BIOS_INFO, "DMA regs:\n"
|
||||
"\tahb_ptr: 0x%08x\n"
|
||||
"\tapb_ptr: 0x%08x\n"
|
||||
"\tahb_seq: 0x%08x\n"
|
||||
"\tapb_seq: 0x%08x\n"
|
||||
|
|
@ -312,8 +301,8 @@ static void dump_regs(struct tegra_spi_channel *spi,
|
|||
read32(&dma->regs->wcount),
|
||||
read32(&dma->regs->dma_byte_sta),
|
||||
read32(&dma->regs->word_transfer));
|
||||
printk(BIOS_DEBUG, "SPI regs:\n");
|
||||
printk(BIOS_DEBUG, "\tdma_blk: 0x%08x\n"
|
||||
printk(BIOS_INFO, "SPI regs:\n"
|
||||
"\tdma_blk: 0x%08x\n"
|
||||
"\tcommand1: 0x%08x\n"
|
||||
"\tdma_ctl: 0x%08x\n"
|
||||
"\ttrans_status: 0x%08x\n",
|
||||
|
|
@ -334,7 +323,7 @@ int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bitsout,
|
|||
ASSERT(bitsout % 8 == 0 && bitsin % 8 == 0);
|
||||
|
||||
/* tegra bus numbers start at 1 */
|
||||
ASSERT(slave->bus >= 1 && slave->bus <= TEGRA124_NUM_SPI_CHANNELS);
|
||||
ASSERT(slave->bus >= 1 && slave->bus <= ARRAY_SIZE(tegra_spi_channels));
|
||||
|
||||
dma = dma_claim();
|
||||
if (!dma) {
|
||||
|
|
@ -342,14 +331,8 @@ int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bitsout,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* flush FIFOs */
|
||||
setbits_le32(&spi->regs->fifo_status, SPI_FIFO_STATUS_RX_FIFO_FLUSH |
|
||||
SPI_FIFO_STATUS_TX_FIFO_FLUSH);
|
||||
while (read32(&spi->regs->fifo_status) & (SPI_FIFO_STATUS_RX_FIFO_FLUSH |
|
||||
SPI_FIFO_STATUS_TX_FIFO_FLUSH))
|
||||
;
|
||||
flush_fifos(spi->regs);
|
||||
|
||||
/* A few common parameters used for both transmit and receive */
|
||||
/* APB bus width = 8-bits, address wrap for each word */
|
||||
clrbits_le32(&dma->regs->apb_seq, 0x7 << 28);
|
||||
/* AHB 1 word burst, bus width = 32 bits (fixed in hardware),
|
||||
|
|
@ -435,7 +418,8 @@ int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bitsout,
|
|||
/* set DMA bit in SPI_DMA_CTL to start */
|
||||
setbits_le32(&spi->regs->dma_ctl, SPI_DMA_CTL_DMA);
|
||||
|
||||
/* start APBDMA after SPI DMA so we don't read empty bytes from Rx FIFO */
|
||||
/* start APBDMA after SPI DMA so we don't read empty bytes
|
||||
* from Rx FIFO */
|
||||
dma_start(dma);
|
||||
|
||||
/* FIXME: delay loops should be "thread" friendly */
|
||||
|
|
@ -525,8 +509,12 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
|
|||
spi_cs_activate(spi->slave);
|
||||
|
||||
if (spi_xfer(spi->slave, spi_read_cmd,
|
||||
sizeof(spi_read_cmd) * 8, NULL, 0) < 0)
|
||||
sizeof(spi_read_cmd) * 8, NULL, 0) < 0) {
|
||||
ret = -1;
|
||||
printk(BIOS_ERR, "SPI failed to transfer %u bytes\n",
|
||||
sizeof(spi_read_cmd));
|
||||
goto tegra_spi_cbfs_read_exit;
|
||||
}
|
||||
|
||||
while (count > 0) {
|
||||
unsigned int remaining;
|
||||
|
|
|
|||
|
|
@ -18,23 +18,6 @@
|
|||
#define __NVIDIA_TEGRA124_SPI_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <spi-generic.h>
|
||||
|
||||
struct tegra_spi_channel {
|
||||
struct spi_slave slave;
|
||||
struct tegra_spi_regs *regs;
|
||||
|
||||
/*
|
||||
* max transfer size and dma_buf address will be set by
|
||||
* mainboard-specific code, depending on the requirements for
|
||||
* the device connected
|
||||
*/
|
||||
unsigned int max_transfer_size;
|
||||
void *dma_buf;
|
||||
};
|
||||
|
||||
#define TEGRA124_NUM_SPI_CHANNELS 6
|
||||
extern struct tegra_spi_channel tegra_spi_channels[];
|
||||
|
||||
struct cbfs_media;
|
||||
int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue