From ff1da6fb5fe50ac15dd988e81a782a4599102424 Mon Sep 17 00:00:00 2001 From: Allen Martin Date: Sat, 16 Mar 2013 18:58:03 +0000 Subject: tegra: spi: rename tegra SPI drivers Rename tegra SPI drivers to tegra20_flash and tegra20_slink in preparation for commonization and addition of tegra114_spi. Signed-off-by: Allen Martin Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- drivers/spi/tegra20_slink.c | 343 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 drivers/spi/tegra20_slink.c (limited to 'drivers/spi/tegra20_slink.c') diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c new file mode 100644 index 000000000..a6de4cec6 --- /dev/null +++ b/drivers/spi/tegra20_slink.c @@ -0,0 +1,343 @@ +/* + * NVIDIA Tegra SPI-SLINK controller + * + * Copyright (c) 2010-2013 NVIDIA Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +struct tegra_spi_ctrl { + struct slink_tegra *regs; + unsigned int freq; + unsigned int mode; + int periph_id; + int valid; +}; + +struct tegra_spi_slave { + struct spi_slave slave; + struct tegra_spi_ctrl *ctrl; +}; + +static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA_SLINK_CTRLS]; + +static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave) +{ + return container_of(slave, struct tegra_spi_slave, slave); +} + +int spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ + if (bus >= CONFIG_TEGRA_SLINK_CTRLS || cs > 3 || !spi_ctrls[bus].valid) + return 0; + else + return 1; +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + struct tegra_spi_slave *spi; + + debug("%s: bus: %u, cs: %u, max_hz: %u, mode: %u\n", __func__, + bus, cs, max_hz, mode); + + if (!spi_cs_is_valid(bus, cs)) { + printf("SPI error: unsupported bus %d / chip select %d\n", + bus, cs); + return NULL; + } + + if (max_hz > TEGRA_SPI_MAX_FREQ) { + printf("SPI error: unsupported frequency %d Hz. Max frequency" + " is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ); + return NULL; + } + + spi = malloc(sizeof(struct tegra_spi_slave)); + if (!spi) { + printf("SPI error: malloc of SPI structure failed\n"); + return NULL; + } + spi->slave.bus = bus; + spi->slave.cs = cs; + spi->ctrl = &spi_ctrls[bus]; + if (!spi->ctrl) { + printf("SPI error: could not find controller for bus %d\n", + bus); + return NULL; + } + + if (max_hz < spi->ctrl->freq) { + debug("%s: limiting frequency from %u to %u\n", __func__, + spi->ctrl->freq, max_hz); + spi->ctrl->freq = max_hz; + } + spi->ctrl->mode = mode; + + return &spi->slave; +} + +void spi_free_slave(struct spi_slave *slave) +{ + struct tegra_spi_slave *spi = to_tegra_spi(slave); + + free(spi); +} + +void spi_init(void) +{ + struct tegra_spi_ctrl *ctrl; + int i; +#ifdef CONFIG_OF_CONTROL + int node = 0; + int count; + int node_list[CONFIG_TEGRA_SLINK_CTRLS]; + + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi", + COMPAT_NVIDIA_TEGRA20_SLINK, + node_list, + CONFIG_TEGRA_SLINK_CTRLS); + for (i = 0; i < count; i++) { + ctrl = &spi_ctrls[i]; + node = node_list[i]; + + ctrl->regs = (struct slink_tegra *)fdtdec_get_addr(gd->fdt_blob, + node, "reg"); + if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) { + debug("%s: no slink register found\n", __func__); + continue; + } + ctrl->freq = fdtdec_get_int(gd->fdt_blob, node, + "spi-max-frequency", 0); + if (!ctrl->freq) { + debug("%s: no slink max frequency found\n", __func__); + continue; + } + + ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node); + if (ctrl->periph_id == PERIPH_ID_NONE) { + debug("%s: could not decode periph id\n", __func__); + continue; + } + ctrl->valid = 1; + + debug("%s: found controller at %p, freq = %u, periph_id = %d\n", + __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); + } +#else + for (i = 0; i < CONFIG_TEGRA_SLINK_CTRLS; i++) { + ctrl = &spi_ctrls[i]; + u32 base_regs[] = { + NV_PA_SLINK1_BASE, + NV_PA_SLINK2_BASE, + NV_PA_SLINK3_BASE, + NV_PA_SLINK4_BASE, + NV_PA_SLINK5_BASE, + NV_PA_SLINK6_BASE, + }; + int periph_ids[] = { + PERIPH_ID_SBC1, + PERIPH_ID_SBC2, + PERIPH_ID_SBC3, + PERIPH_ID_SBC4, + PERIPH_ID_SBC5, + PERIPH_ID_SBC6, + }; + ctrl->regs = (struct slink_tegra *)base_regs[i]; + ctrl->freq = TEGRA_SPI_MAX_FREQ; + ctrl->periph_id = periph_ids[i]; + ctrl->valid = 1; + + debug("%s: found controller at %p, freq = %u, periph_id = %d\n", + __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); + } +#endif +} + +int spi_claim_bus(struct spi_slave *slave) +{ + struct tegra_spi_slave *spi = to_tegra_spi(slave); + struct slink_tegra *regs = spi->ctrl->regs; + u32 reg; + + /* Change SPI clock to correct frequency, PLLP_OUT0 source */ + clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH, + spi->ctrl->freq); + + /* Clear stale status here */ + reg = SLINK_STAT_RDY | SLINK_STAT_RXF_FLUSH | SLINK_STAT_TXF_FLUSH | \ + SLINK_STAT_RXF_UNR | SLINK_STAT_TXF_OVF; + writel(reg, ®s->status); + debug("%s: STATUS = %08x\n", __func__, readl(®s->status)); + + /* Set master mode and sw controlled CS */ + reg = readl(®s->command); + reg |= SLINK_CMD_M_S | SLINK_CMD_CS_SOFT; + writel(reg, ®s->command); + debug("%s: COMMAND = %08x\n", __func__, readl(®s->command)); + + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ +} + +void spi_cs_activate(struct spi_slave *slave) +{ + struct tegra_spi_slave *spi = to_tegra_spi(slave); + struct slink_tegra *regs = spi->ctrl->regs; + + /* CS is negated on Tegra, so drive a 1 to get a 0 */ + setbits_le32(®s->command, SLINK_CMD_CS_VAL); +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + struct tegra_spi_slave *spi = to_tegra_spi(slave); + struct slink_tegra *regs = spi->ctrl->regs; + + /* CS is negated on Tegra, so drive a 0 to get a 1 */ + clrbits_le32(®s->command, SLINK_CMD_CS_VAL); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *data_out, void *data_in, unsigned long flags) +{ + struct tegra_spi_slave *spi = to_tegra_spi(slave); + struct slink_tegra *regs = spi->ctrl->regs; + u32 reg, tmpdout, tmpdin = 0; + const u8 *dout = data_out; + u8 *din = data_in; + int num_bytes; + int ret; + + debug("%s: slave %u:%u dout %p din %p bitlen %u\n", + __func__, slave->bus, slave->cs, dout, din, bitlen); + if (bitlen % 8) + return -1; + num_bytes = bitlen / 8; + + ret = 0; + + reg = readl(®s->status); + writel(reg, ®s->status); /* Clear all SPI events via R/W */ + debug("%s entry: STATUS = %08x\n", __func__, reg); + + reg = readl(®s->status2); + writel(reg, ®s->status2); /* Clear all STATUS2 events via R/W */ + debug("%s entry: STATUS2 = %08x\n", __func__, reg); + + debug("%s entry: COMMAND = %08x\n", __func__, readl(®s->command)); + + clrsetbits_le32(®s->command2, SLINK_CMD2_SS_EN_MASK, + SLINK_CMD2_TXEN | SLINK_CMD2_RXEN | + (slave->cs << SLINK_CMD2_SS_EN_SHIFT)); + debug("%s entry: COMMAND2 = %08x\n", __func__, readl(®s->command2)); + + if (flags & SPI_XFER_BEGIN) + spi_cs_activate(slave); + + /* handle data in 32-bit chunks */ + while (num_bytes > 0) { + int bytes; + int is_read = 0; + int tm, i; + + tmpdout = 0; + bytes = (num_bytes > 4) ? 4 : num_bytes; + + if (dout != NULL) { + for (i = 0; i < bytes; ++i) + tmpdout = (tmpdout << 8) | dout[i]; + dout += bytes; + } + + num_bytes -= bytes; + + clrsetbits_le32(®s->command, SLINK_CMD_BIT_LENGTH_MASK, + bytes * 8 - 1); + writel(tmpdout, ®s->tx_fifo); + setbits_le32(®s->command, SLINK_CMD_GO); + + /* + * Wait for SPI transmit FIFO to empty, or to time out. + * The RX FIFO status will be read and cleared last + */ + for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) { + u32 status; + + status = readl(®s->status); + + /* We can exit when we've had both RX and TX activity */ + if (is_read && (status & SLINK_STAT_TXF_EMPTY)) + break; + + if ((status & (SLINK_STAT_BSY | SLINK_STAT_RDY)) != + SLINK_STAT_RDY) + tm++; + + else if (!(status & SLINK_STAT_RXF_EMPTY)) { + tmpdin = readl(®s->rx_fifo); + is_read = 1; + + /* swap bytes read in */ + if (din != NULL) { + for (i = bytes - 1; i >= 0; --i) { + din[i] = tmpdin & 0xff; + tmpdin >>= 8; + } + din += bytes; + } + } + } + + if (tm >= SPI_TIMEOUT) + ret = tm; + + /* clear ACK RDY, etc. bits */ + writel(readl(®s->status), ®s->status); + } + + if (flags & SPI_XFER_END) + spi_cs_deactivate(slave); + + debug("%s: transfer ended. Value=%08x, status = %08x\n", + __func__, tmpdin, readl(®s->status)); + + if (ret) { + printf("%s: timeout during SPI transfer, tm %d\n", + __func__, ret); + return -1; + } + + return 0; +} -- cgit v1.2.3-70-g09d2 From 2a3c5bc29c621faf2f830c464cc395b3174800f1 Mon Sep 17 00:00:00 2001 From: Allen Martin Date: Sat, 16 Mar 2013 18:58:04 +0000 Subject: tegra: spi: remove non fdt support Remove non fdt support from tegra20 and tegra30 SPI drivers in preparation of new common fdt based SPI driver front end. Signed-off-by: Allen Martin Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- drivers/spi/tegra20_sflash.c | 12 ++++-------- drivers/spi/tegra20_slink.c | 29 ----------------------------- 2 files changed, 4 insertions(+), 37 deletions(-) (limited to 'drivers/spi/tegra20_slink.c') diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c index c6af30f0d..3b1b6f892 100644 --- a/drivers/spi/tegra20_sflash.c +++ b/drivers/spi/tegra20_sflash.c @@ -61,6 +61,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { struct tegra_spi_slave *spi; + int node; if (!spi_cs_is_valid(bus, cs)) { printf("SPI error: unsupported bus %d / chip select %d\n", @@ -81,9 +82,9 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, } spi->slave.bus = bus; spi->slave.cs = cs; -#ifdef CONFIG_OF_CONTROL - int node = fdtdec_next_compatible(gd->fdt_blob, 0, - COMPAT_NVIDIA_TEGRA20_SFLASH); + + node = fdtdec_next_compatible(gd->fdt_blob, 0, + COMPAT_NVIDIA_TEGRA20_SFLASH); if (node < 0) { debug("%s: cannot locate sflash node\n", __func__); return NULL; @@ -108,11 +109,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, debug("%s: could not decode periph id\n", __func__); return NULL; } -#else - spi->regs = (struct spi_tegra *)NV_PA_SPI_BASE; - spi->freq = TEGRA_SPI_MAX_FREQ; - spi->periph_id = PERIPH_ID_SPI1; -#endif if (max_hz < spi->freq) { debug("%s: limiting frequency from %u to %u\n", __func__, spi->freq, max_hz); diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c index a6de4cec6..c794054f0 100644 --- a/drivers/spi/tegra20_slink.c +++ b/drivers/spi/tegra20_slink.c @@ -116,7 +116,6 @@ void spi_init(void) { struct tegra_spi_ctrl *ctrl; int i; -#ifdef CONFIG_OF_CONTROL int node = 0; int count; int node_list[CONFIG_TEGRA_SLINK_CTRLS]; @@ -152,34 +151,6 @@ void spi_init(void) debug("%s: found controller at %p, freq = %u, periph_id = %d\n", __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); } -#else - for (i = 0; i < CONFIG_TEGRA_SLINK_CTRLS; i++) { - ctrl = &spi_ctrls[i]; - u32 base_regs[] = { - NV_PA_SLINK1_BASE, - NV_PA_SLINK2_BASE, - NV_PA_SLINK3_BASE, - NV_PA_SLINK4_BASE, - NV_PA_SLINK5_BASE, - NV_PA_SLINK6_BASE, - }; - int periph_ids[] = { - PERIPH_ID_SBC1, - PERIPH_ID_SBC2, - PERIPH_ID_SBC3, - PERIPH_ID_SBC4, - PERIPH_ID_SBC5, - PERIPH_ID_SBC6, - }; - ctrl->regs = (struct slink_tegra *)base_regs[i]; - ctrl->freq = TEGRA_SPI_MAX_FREQ; - ctrl->periph_id = periph_ids[i]; - ctrl->valid = 1; - - debug("%s: found controller at %p, freq = %u, periph_id = %d\n", - __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); - } -#endif } int spi_claim_bus(struct spi_slave *slave) -- cgit v1.2.3-70-g09d2 From 7a49ba6e5b81713c5c8f8275a7ecd1036ca583d4 Mon Sep 17 00:00:00 2001 From: Allen Martin Date: Sat, 16 Mar 2013 18:58:05 +0000 Subject: tegra: spi: pull register structs out of headers Move register structs from headers into .c files and use common name. This is in preparation of making common fdt front end for SPI drivers. Signed-off-by: Allen Martin Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/include/asm/arch-tegra20/tegra20_sflash.h | 45 -------------- arch/arm/include/asm/arch-tegra20/tegra20_slink.h | 54 ----------------- drivers/spi/tegra20_sflash.c | 53 +++++++++++++++-- drivers/spi/tegra20_slink.c | 68 +++++++++++++++++++--- 4 files changed, 110 insertions(+), 110 deletions(-) (limited to 'drivers/spi/tegra20_slink.c') diff --git a/arch/arm/include/asm/arch-tegra20/tegra20_sflash.h b/arch/arm/include/asm/arch-tegra20/tegra20_sflash.h index 26a840251..28775db2a 100644 --- a/arch/arm/include/asm/arch-tegra20/tegra20_sflash.h +++ b/arch/arm/include/asm/arch-tegra20/tegra20_sflash.h @@ -27,49 +27,4 @@ #include -struct spi_tegra { - u32 command; /* SPI_COMMAND_0 register */ - u32 status; /* SPI_STATUS_0 register */ - u32 rx_cmp; /* SPI_RX_CMP_0 register */ - u32 dma_ctl; /* SPI_DMA_CTL_0 register */ - u32 tx_fifo; /* SPI_TX_FIFO_0 register */ - u32 rsvd[3]; /* offsets 0x14 to 0x1F reserved */ - u32 rx_fifo; /* SPI_RX_FIFO_0 register */ -}; - -#define SPI_CMD_GO (1 << 30) -#define SPI_CMD_ACTIVE_SCLK_SHIFT 26 -#define SPI_CMD_ACTIVE_SCLK_MASK (3 << SPI_CMD_ACTIVE_SCLK_SHIFT) -#define SPI_CMD_CK_SDA (1 << 21) -#define SPI_CMD_ACTIVE_SDA_SHIFT 18 -#define SPI_CMD_ACTIVE_SDA_MASK (3 << SPI_CMD_ACTIVE_SDA_SHIFT) -#define SPI_CMD_CS_POL (1 << 16) -#define SPI_CMD_TXEN (1 << 15) -#define SPI_CMD_RXEN (1 << 14) -#define SPI_CMD_CS_VAL (1 << 13) -#define SPI_CMD_CS_SOFT (1 << 12) -#define SPI_CMD_CS_DELAY (1 << 9) -#define SPI_CMD_CS3_EN (1 << 8) -#define SPI_CMD_CS2_EN (1 << 7) -#define SPI_CMD_CS1_EN (1 << 6) -#define SPI_CMD_CS0_EN (1 << 5) -#define SPI_CMD_BIT_LENGTH (1 << 4) -#define SPI_CMD_BIT_LENGTH_MASK 0x0000001F - -#define SPI_STAT_BSY (1 << 31) -#define SPI_STAT_RDY (1 << 30) -#define SPI_STAT_RXF_FLUSH (1 << 29) -#define SPI_STAT_TXF_FLUSH (1 << 28) -#define SPI_STAT_RXF_UNR (1 << 27) -#define SPI_STAT_TXF_OVF (1 << 26) -#define SPI_STAT_RXF_EMPTY (1 << 25) -#define SPI_STAT_RXF_FULL (1 << 24) -#define SPI_STAT_TXF_EMPTY (1 << 23) -#define SPI_STAT_TXF_FULL (1 << 22) -#define SPI_STAT_SEL_TXRX_N (1 << 16) -#define SPI_STAT_CUR_BLKCNT (1 << 15) - -#define SPI_TIMEOUT 1000 -#define TEGRA_SPI_MAX_FREQ 52000000 - #endif /* _TEGRA20_SPI_H_ */ diff --git a/arch/arm/include/asm/arch-tegra20/tegra20_slink.h b/arch/arm/include/asm/arch-tegra20/tegra20_slink.h index afa9b3692..fe8b5347f 100644 --- a/arch/arm/include/asm/arch-tegra20/tegra20_slink.h +++ b/arch/arm/include/asm/arch-tegra20/tegra20_slink.h @@ -27,58 +27,4 @@ #include -struct slink_tegra { - u32 command; /* SLINK_COMMAND_0 register */ - u32 command2; /* SLINK_COMMAND2_0 reg */ - u32 status; /* SLINK_STATUS_0 register */ - u32 reserved; /* Reserved offset 0C */ - u32 mas_data; /* SLINK_MAS_DATA_0 reg */ - u32 slav_data; /* SLINK_SLAVE_DATA_0 reg */ - u32 dma_ctl; /* SLINK_DMA_CTL_0 register */ - u32 status2; /* SLINK_STATUS2_0 reg */ - u32 rsvd[56]; /* 0x20 to 0xFF reserved */ - u32 tx_fifo; /* SLINK_TX_FIFO_0 reg off 100h */ - u32 rsvd2[31]; /* 0x104 to 0x17F reserved */ - u32 rx_fifo; /* SLINK_RX_FIFO_0 reg off 180h */ -}; - -/* COMMAND */ -#define SLINK_CMD_ENB (1 << 31) -#define SLINK_CMD_GO (1 << 30) -#define SLINK_CMD_M_S (1 << 28) -#define SLINK_CMD_CK_SDA (1 << 21) -#define SLINK_CMD_CS_POL (1 << 13) -#define SLINK_CMD_CS_VAL (1 << 12) -#define SLINK_CMD_CS_SOFT (1 << 11) -#define SLINK_CMD_BIT_LENGTH (1 << 4) -#define SLINK_CMD_BIT_LENGTH_MASK 0x0000001F -/* COMMAND2 */ -#define SLINK_CMD2_TXEN (1 << 30) -#define SLINK_CMD2_RXEN (1 << 31) -#define SLINK_CMD2_SS_EN (1 << 18) -#define SLINK_CMD2_SS_EN_SHIFT 18 -#define SLINK_CMD2_SS_EN_MASK 0x000C0000 -#define SLINK_CMD2_CS_ACTIVE_BETWEEN (1 << 17) -/* STATUS */ -#define SLINK_STAT_BSY (1 << 31) -#define SLINK_STAT_RDY (1 << 30) -#define SLINK_STAT_ERR (1 << 29) -#define SLINK_STAT_RXF_FLUSH (1 << 27) -#define SLINK_STAT_TXF_FLUSH (1 << 26) -#define SLINK_STAT_RXF_OVF (1 << 25) -#define SLINK_STAT_TXF_UNR (1 << 24) -#define SLINK_STAT_RXF_EMPTY (1 << 23) -#define SLINK_STAT_RXF_FULL (1 << 22) -#define SLINK_STAT_TXF_EMPTY (1 << 21) -#define SLINK_STAT_TXF_FULL (1 << 20) -#define SLINK_STAT_TXF_OVF (1 << 19) -#define SLINK_STAT_RXF_UNR (1 << 18) -#define SLINK_STAT_CUR_BLKCNT (1 << 15) -/* STATUS2 */ -#define SLINK_STAT2_RXF_FULL_CNT (1 << 16) -#define SLINK_STAT2_TXF_FULL_CNT (1 << 0) - -#define SPI_TIMEOUT 1000 -#define TEGRA_SPI_MAX_FREQ 52000000 - #endif /* _TEGRA30_SPI_H_ */ diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c index 3b1b6f892..6e72c8ee5 100644 --- a/drivers/spi/tegra20_sflash.c +++ b/drivers/spi/tegra20_sflash.c @@ -35,9 +35,54 @@ DECLARE_GLOBAL_DATA_PTR; +#define SPI_CMD_GO (1 << 30) +#define SPI_CMD_ACTIVE_SCLK_SHIFT 26 +#define SPI_CMD_ACTIVE_SCLK_MASK (3 << SPI_CMD_ACTIVE_SCLK_SHIFT) +#define SPI_CMD_CK_SDA (1 << 21) +#define SPI_CMD_ACTIVE_SDA_SHIFT 18 +#define SPI_CMD_ACTIVE_SDA_MASK (3 << SPI_CMD_ACTIVE_SDA_SHIFT) +#define SPI_CMD_CS_POL (1 << 16) +#define SPI_CMD_TXEN (1 << 15) +#define SPI_CMD_RXEN (1 << 14) +#define SPI_CMD_CS_VAL (1 << 13) +#define SPI_CMD_CS_SOFT (1 << 12) +#define SPI_CMD_CS_DELAY (1 << 9) +#define SPI_CMD_CS3_EN (1 << 8) +#define SPI_CMD_CS2_EN (1 << 7) +#define SPI_CMD_CS1_EN (1 << 6) +#define SPI_CMD_CS0_EN (1 << 5) +#define SPI_CMD_BIT_LENGTH (1 << 4) +#define SPI_CMD_BIT_LENGTH_MASK 0x0000001F + +#define SPI_STAT_BSY (1 << 31) +#define SPI_STAT_RDY (1 << 30) +#define SPI_STAT_RXF_FLUSH (1 << 29) +#define SPI_STAT_TXF_FLUSH (1 << 28) +#define SPI_STAT_RXF_UNR (1 << 27) +#define SPI_STAT_TXF_OVF (1 << 26) +#define SPI_STAT_RXF_EMPTY (1 << 25) +#define SPI_STAT_RXF_FULL (1 << 24) +#define SPI_STAT_TXF_EMPTY (1 << 23) +#define SPI_STAT_TXF_FULL (1 << 22) +#define SPI_STAT_SEL_TXRX_N (1 << 16) +#define SPI_STAT_CUR_BLKCNT (1 << 15) + +#define SPI_TIMEOUT 1000 +#define TEGRA_SPI_MAX_FREQ 52000000 + +struct spi_regs { + u32 command; /* SPI_COMMAND_0 register */ + u32 status; /* SPI_STATUS_0 register */ + u32 rx_cmp; /* SPI_RX_CMP_0 register */ + u32 dma_ctl; /* SPI_DMA_CTL_0 register */ + u32 tx_fifo; /* SPI_TX_FIFO_0 register */ + u32 rsvd[3]; /* offsets 0x14 to 0x1F reserved */ + u32 rx_fifo; /* SPI_RX_FIFO_0 register */ +}; + struct tegra_spi_slave { struct spi_slave slave; - struct spi_tegra *regs; + struct spi_regs *regs; unsigned int freq; unsigned int mode; int periph_id; @@ -93,7 +138,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, debug("%s: sflash is disabled\n", __func__); return NULL; } - spi->regs = (struct spi_tegra *)fdtdec_get_addr(gd->fdt_blob, + spi->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); if ((fdt_addr_t)spi->regs == FDT_ADDR_T_NONE) { debug("%s: no sflash register found\n", __func__); @@ -136,7 +181,7 @@ void spi_init(void) int spi_claim_bus(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct spi_tegra *regs = spi->regs; + struct spi_regs *regs = spi->regs; u32 reg; /* Change SPI clock to correct frequency, PLLP_OUT0 source */ @@ -199,7 +244,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, void *data_in, unsigned long flags) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct spi_tegra *regs = spi->regs; + struct spi_regs *regs = spi->regs; u32 reg, tmpdout, tmpdin = 0; const u8 *dout = data_out; u8 *din = data_in; diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c index c794054f0..f3b096448 100644 --- a/drivers/spi/tegra20_slink.c +++ b/drivers/spi/tegra20_slink.c @@ -33,8 +33,62 @@ DECLARE_GLOBAL_DATA_PTR; +/* COMMAND */ +#define SLINK_CMD_ENB (1 << 31) +#define SLINK_CMD_GO (1 << 30) +#define SLINK_CMD_M_S (1 << 28) +#define SLINK_CMD_CK_SDA (1 << 21) +#define SLINK_CMD_CS_POL (1 << 13) +#define SLINK_CMD_CS_VAL (1 << 12) +#define SLINK_CMD_CS_SOFT (1 << 11) +#define SLINK_CMD_BIT_LENGTH (1 << 4) +#define SLINK_CMD_BIT_LENGTH_MASK 0x0000001F +/* COMMAND2 */ +#define SLINK_CMD2_TXEN (1 << 30) +#define SLINK_CMD2_RXEN (1 << 31) +#define SLINK_CMD2_SS_EN (1 << 18) +#define SLINK_CMD2_SS_EN_SHIFT 18 +#define SLINK_CMD2_SS_EN_MASK 0x000C0000 +#define SLINK_CMD2_CS_ACTIVE_BETWEEN (1 << 17) +/* STATUS */ +#define SLINK_STAT_BSY (1 << 31) +#define SLINK_STAT_RDY (1 << 30) +#define SLINK_STAT_ERR (1 << 29) +#define SLINK_STAT_RXF_FLUSH (1 << 27) +#define SLINK_STAT_TXF_FLUSH (1 << 26) +#define SLINK_STAT_RXF_OVF (1 << 25) +#define SLINK_STAT_TXF_UNR (1 << 24) +#define SLINK_STAT_RXF_EMPTY (1 << 23) +#define SLINK_STAT_RXF_FULL (1 << 22) +#define SLINK_STAT_TXF_EMPTY (1 << 21) +#define SLINK_STAT_TXF_FULL (1 << 20) +#define SLINK_STAT_TXF_OVF (1 << 19) +#define SLINK_STAT_RXF_UNR (1 << 18) +#define SLINK_STAT_CUR_BLKCNT (1 << 15) +/* STATUS2 */ +#define SLINK_STAT2_RXF_FULL_CNT (1 << 16) +#define SLINK_STAT2_TXF_FULL_CNT (1 << 0) + +#define SPI_TIMEOUT 1000 +#define TEGRA_SPI_MAX_FREQ 52000000 + +struct spi_regs { + u32 command; /* SLINK_COMMAND_0 register */ + u32 command2; /* SLINK_COMMAND2_0 reg */ + u32 status; /* SLINK_STATUS_0 register */ + u32 reserved; /* Reserved offset 0C */ + u32 mas_data; /* SLINK_MAS_DATA_0 reg */ + u32 slav_data; /* SLINK_SLAVE_DATA_0 reg */ + u32 dma_ctl; /* SLINK_DMA_CTL_0 register */ + u32 status2; /* SLINK_STATUS2_0 reg */ + u32 rsvd[56]; /* 0x20 to 0xFF reserved */ + u32 tx_fifo; /* SLINK_TX_FIFO_0 reg off 100h */ + u32 rsvd2[31]; /* 0x104 to 0x17F reserved */ + u32 rx_fifo; /* SLINK_RX_FIFO_0 reg off 180h */ +}; + struct tegra_spi_ctrl { - struct slink_tegra *regs; + struct spi_regs *regs; unsigned int freq; unsigned int mode; int periph_id; @@ -128,8 +182,8 @@ void spi_init(void) ctrl = &spi_ctrls[i]; node = node_list[i]; - ctrl->regs = (struct slink_tegra *)fdtdec_get_addr(gd->fdt_blob, - node, "reg"); + ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob, + node, "reg"); if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) { debug("%s: no slink register found\n", __func__); continue; @@ -156,7 +210,7 @@ void spi_init(void) int spi_claim_bus(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct slink_tegra *regs = spi->ctrl->regs; + struct spi_regs *regs = spi->ctrl->regs; u32 reg; /* Change SPI clock to correct frequency, PLLP_OUT0 source */ @@ -185,7 +239,7 @@ void spi_release_bus(struct spi_slave *slave) void spi_cs_activate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct slink_tegra *regs = spi->ctrl->regs; + struct spi_regs *regs = spi->ctrl->regs; /* CS is negated on Tegra, so drive a 1 to get a 0 */ setbits_le32(®s->command, SLINK_CMD_CS_VAL); @@ -194,7 +248,7 @@ void spi_cs_activate(struct spi_slave *slave) void spi_cs_deactivate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct slink_tegra *regs = spi->ctrl->regs; + struct spi_regs *regs = spi->ctrl->regs; /* CS is negated on Tegra, so drive a 0 to get a 1 */ clrbits_le32(®s->command, SLINK_CMD_CS_VAL); @@ -204,7 +258,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, void *data_in, unsigned long flags) { struct tegra_spi_slave *spi = to_tegra_spi(slave); - struct slink_tegra *regs = spi->ctrl->regs; + struct spi_regs *regs = spi->ctrl->regs; u32 reg, tmpdout, tmpdin = 0; const u8 *dout = data_out; u8 *din = data_in; -- cgit v1.2.3-70-g09d2 From 78f47b7353ebe1f243203dcc1ce0a2a374c08a40 Mon Sep 17 00:00:00 2001 From: Allen Martin Date: Sat, 16 Mar 2013 18:58:07 +0000 Subject: spi: add common fdt SPI driver interface Add a common interface to fdt based SPI drivers. Each driver is represented by a table entry in fdt_spi_drivers[]. If there are multiple SPI drivers in the table, the first driver to return success from spi_init() will be registered as the SPI driver. Signed-off-by: Allen Martin Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/include/asm/arch-tegra20/tegra20_sflash.h | 11 ++ arch/arm/include/asm/arch-tegra20/tegra20_slink.h | 11 ++ board/nvidia/common/board.c | 2 +- drivers/spi/Makefile | 1 + drivers/spi/fdt_spi.c | 171 +++++++++++++++++++++ drivers/spi/tegra20_sflash.c | 41 ++--- drivers/spi/tegra20_slink.c | 29 ++-- include/configs/tegra-common-post.h | 4 + 8 files changed, 224 insertions(+), 46 deletions(-) create mode 100644 drivers/spi/fdt_spi.c (limited to 'drivers/spi/tegra20_slink.c') diff --git a/arch/arm/include/asm/arch-tegra20/tegra20_sflash.h b/arch/arm/include/asm/arch-tegra20/tegra20_sflash.h index 28775db2a..e8cc68c6e 100644 --- a/arch/arm/include/asm/arch-tegra20/tegra20_sflash.h +++ b/arch/arm/include/asm/arch-tegra20/tegra20_sflash.h @@ -27,4 +27,15 @@ #include +int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs); +struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode); +void tegra20_spi_free_slave(struct spi_slave *slave); +int tegra20_spi_init(int *node_list, int count); +int tegra20_spi_claim_bus(struct spi_slave *slave); +void tegra20_spi_cs_activate(struct spi_slave *slave); +void tegra20_spi_cs_deactivate(struct spi_slave *slave); +int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *data_out, void *data_in, unsigned long flags); + #endif /* _TEGRA20_SPI_H_ */ diff --git a/arch/arm/include/asm/arch-tegra20/tegra20_slink.h b/arch/arm/include/asm/arch-tegra20/tegra20_slink.h index fe8b5347f..5aa74ddd6 100644 --- a/arch/arm/include/asm/arch-tegra20/tegra20_slink.h +++ b/arch/arm/include/asm/arch-tegra20/tegra20_slink.h @@ -27,4 +27,15 @@ #include +int tegra30_spi_init(int *node_list, int count); +int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs); +struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode); +void tegra30_spi_free_slave(struct spi_slave *slave); +int tegra30_spi_claim_bus(struct spi_slave *slave); +void tegra30_spi_cs_activate(struct spi_slave *slave); +void tegra30_spi_cs_deactivate(struct spi_slave *slave); +int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *data_out, void *data_in, unsigned long flags); + #endif /* _TEGRA30_SPI_H_ */ diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index 87a418bc6..8d7a22765 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -132,7 +132,7 @@ int board_init(void) clock_init(); clock_verify(); -#if defined(CONFIG_TEGRA20_SFLASH) || defined(CONFIG_TEGRA20_SLINK) +#ifdef CONFIG_FDT_SPI pin_mux_spi(); spi_init(); #endif diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 78e3d3d56..3762d59dd 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -46,6 +46,7 @@ COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o COBJS-$(CONFIG_SH_SPI) += sh_spi.o COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o +COBJS-$(CONFIG_FDT_SPI) += fdt_spi.o COBJS-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o COBJS-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o diff --git a/drivers/spi/fdt_spi.c b/drivers/spi/fdt_spi.c new file mode 100644 index 000000000..c6ae719d6 --- /dev/null +++ b/drivers/spi/fdt_spi.c @@ -0,0 +1,171 @@ +/* + * Common fdt based SPI driver front end + * + * Copyright (c) 2013 NVIDIA Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +struct fdt_spi_driver { + int compat; + int max_ctrls; + int (*init)(int *node_list, int count); + int (*claim_bus)(struct spi_slave *slave); + int (*release_bus)(struct spi_slave *slave); + int (*cs_is_valid)(unsigned int bus, unsigned int cs); + struct spi_slave *(*setup_slave)(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode); + void (*free_slave)(struct spi_slave *slave); + void (*cs_activate)(struct spi_slave *slave); + void (*cs_deactivate)(struct spi_slave *slave); + int (*xfer)(struct spi_slave *slave, unsigned int bitlen, + const void *data_out, void *data_in, unsigned long flags); +}; + +static struct fdt_spi_driver fdt_spi_drivers[] = { +#ifdef CONFIG_TEGRA20_SFLASH + { + .compat = COMPAT_NVIDIA_TEGRA20_SFLASH, + .max_ctrls = 1, + .init = tegra20_spi_init, + .claim_bus = tegra20_spi_claim_bus, + .cs_is_valid = tegra20_spi_cs_is_valid, + .setup_slave = tegra20_spi_setup_slave, + .free_slave = tegra20_spi_free_slave, + .cs_activate = tegra20_spi_cs_activate, + .cs_deactivate = tegra20_spi_cs_deactivate, + .xfer = tegra20_spi_xfer, + }, +#endif +#ifdef CONFIG_TEGRA20_SLINK + { + .compat = COMPAT_NVIDIA_TEGRA20_SLINK, + .max_ctrls = CONFIG_TEGRA_SLINK_CTRLS, + .init = tegra30_spi_init, + .claim_bus = tegra30_spi_claim_bus, + .cs_is_valid = tegra30_spi_cs_is_valid, + .setup_slave = tegra30_spi_setup_slave, + .free_slave = tegra30_spi_free_slave, + .cs_activate = tegra30_spi_cs_activate, + .cs_deactivate = tegra30_spi_cs_deactivate, + .xfer = tegra30_spi_xfer, + }, +#endif +}; + +static struct fdt_spi_driver *driver; + +int spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ + if (!driver) + return 0; + else if (!driver->cs_is_valid) + return 1; + else + return driver->cs_is_valid(bus, cs); +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + if (!driver || !driver->setup_slave) + return NULL; + + return driver->setup_slave(bus, cs, max_hz, mode); +} + +void spi_free_slave(struct spi_slave *slave) +{ + if (driver && driver->free_slave) + return driver->free_slave(slave); +} + +static int spi_init_driver(struct fdt_spi_driver *driver) +{ + int count; + int node_list[driver->max_ctrls]; + + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi", + driver->compat, + node_list, + driver->max_ctrls); + return driver->init(node_list, count); +} + +void spi_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(fdt_spi_drivers); i++) { + driver = &fdt_spi_drivers[i]; + if (!spi_init_driver(driver)) + break; + } + if (i == ARRAY_SIZE(fdt_spi_drivers)) + driver = NULL; +} + +int spi_claim_bus(struct spi_slave *slave) +{ + if (!driver) + return 1; + if (!driver->claim_bus) + return 0; + + return driver->claim_bus(slave); +} + +void spi_release_bus(struct spi_slave *slave) +{ + if (driver && driver->release_bus) + driver->release_bus(slave); +} + +void spi_cs_activate(struct spi_slave *slave) +{ + if (driver && driver->cs_activate) + driver->cs_activate(slave); +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + if (driver && driver->cs_deactivate) + driver->cs_deactivate(slave); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *data_out, void *data_in, unsigned long flags) +{ + if (!driver || !driver->xfer) + return -1; + + return driver->xfer(slave, bitlen, data_out, data_in, flags); +} diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c index bb1e57d5e..a4e6c9aa3 100644 --- a/drivers/spi/tegra20_sflash.c +++ b/drivers/spi/tegra20_sflash.c @@ -101,7 +101,7 @@ static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave) return container_of(slave, struct tegra_spi_slave, slave); } -int spi_cs_is_valid(unsigned int bus, unsigned int cs) +int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs) { /* Tegra20 SPI-Flash - only 1 device ('bus/cs') */ if (bus != 0 || cs != 0) @@ -110,8 +110,8 @@ int spi_cs_is_valid(unsigned int bus, unsigned int cs) return 1; } -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) +struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) { struct tegra_spi_slave *spi; @@ -151,25 +151,20 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, return &spi->slave; } -void spi_free_slave(struct spi_slave *slave) +void tegra20_spi_free_slave(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); free(spi); } -void spi_init(void) +int tegra20_spi_init(int *node_list, int count) { struct tegra_spi_ctrl *ctrl; int i; int node = 0; - int count; - int node_list[1]; + int found = 0; - count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi", - COMPAT_NVIDIA_TEGRA20_SFLASH, - node_list, - 1); for (i = 0; i < count; i++) { ctrl = &spi_ctrls[i]; node = node_list[i]; @@ -193,13 +188,15 @@ void spi_init(void) continue; } ctrl->valid = 1; + found = 1; debug("%s: found controller at %p, freq = %u, periph_id = %d\n", __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); } + return !found; } -int spi_claim_bus(struct spi_slave *slave) +int tegra20_spi_claim_bus(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); struct spi_regs *regs = spi->ctrl->regs; @@ -213,7 +210,7 @@ int spi_claim_bus(struct spi_slave *slave) reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \ SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF; writel(reg, ®s->status); - debug("spi_init: STATUS = %08x\n", readl(®s->status)); + debug("%s: STATUS = %08x\n", __func__, readl(®s->status)); /* * Use sw-controlled CS, so we can clock in data after ReadID, etc. @@ -223,7 +220,7 @@ int spi_claim_bus(struct spi_slave *slave) reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT; clrsetbits_le32(®s->command, SPI_CMD_ACTIVE_SCLK_MASK | SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg); - debug("spi_init: COMMAND = %08x\n", readl(®s->command)); + debug("%s: COMMAND = %08x\n", __func__, readl(®s->command)); /* * SPI pins on Tegra20 are muxed - change pinmux later due to UART @@ -236,17 +233,7 @@ int spi_claim_bus(struct spi_slave *slave) return 0; } -void spi_release_bus(struct spi_slave *slave) -{ - /* - * We can't release UART_DISABLE and set pinmux to UART4 here since - * some code (e,g, spi_flash_probe) uses printf() while the SPI - * bus is held. That is arguably bad, but it has the advantage of - * already being in the source tree. - */ -} - -void spi_cs_activate(struct spi_slave *slave) +void tegra20_spi_cs_activate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); struct spi_regs *regs = spi->ctrl->regs; @@ -255,7 +242,7 @@ void spi_cs_activate(struct spi_slave *slave) setbits_le32(®s->command, SPI_CMD_CS_VAL); } -void spi_cs_deactivate(struct spi_slave *slave) +void tegra20_spi_cs_deactivate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); struct spi_regs *regs = spi->ctrl->regs; @@ -264,7 +251,7 @@ void spi_cs_deactivate(struct spi_slave *slave) clrbits_le32(®s->command, SPI_CMD_CS_VAL); } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, +int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, void *data_in, unsigned long flags) { struct tegra_spi_slave *spi = to_tegra_spi(slave); diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c index f3b096448..2ef2eb849 100644 --- a/drivers/spi/tegra20_slink.c +++ b/drivers/spi/tegra20_slink.c @@ -107,7 +107,7 @@ static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave) return container_of(slave, struct tegra_spi_slave, slave); } -int spi_cs_is_valid(unsigned int bus, unsigned int cs) +int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs) { if (bus >= CONFIG_TEGRA_SLINK_CTRLS || cs > 3 || !spi_ctrls[bus].valid) return 0; @@ -115,7 +115,7 @@ int spi_cs_is_valid(unsigned int bus, unsigned int cs) return 1; } -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, +struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { struct tegra_spi_slave *spi; @@ -159,25 +159,20 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, return &spi->slave; } -void spi_free_slave(struct spi_slave *slave) +void tegra30_spi_free_slave(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); free(spi); } -void spi_init(void) +int tegra30_spi_init(int *node_list, int count) { struct tegra_spi_ctrl *ctrl; int i; int node = 0; - int count; - int node_list[CONFIG_TEGRA_SLINK_CTRLS]; + int found = 0; - count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi", - COMPAT_NVIDIA_TEGRA20_SLINK, - node_list, - CONFIG_TEGRA_SLINK_CTRLS); for (i = 0; i < count; i++) { ctrl = &spi_ctrls[i]; node = node_list[i]; @@ -201,13 +196,15 @@ void spi_init(void) continue; } ctrl->valid = 1; + found = 1; debug("%s: found controller at %p, freq = %u, periph_id = %d\n", __func__, ctrl->regs, ctrl->freq, ctrl->periph_id); } + return !found; } -int spi_claim_bus(struct spi_slave *slave) +int tegra30_spi_claim_bus(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); struct spi_regs *regs = spi->ctrl->regs; @@ -232,11 +229,7 @@ int spi_claim_bus(struct spi_slave *slave) return 0; } -void spi_release_bus(struct spi_slave *slave) -{ -} - -void spi_cs_activate(struct spi_slave *slave) +void tegra30_spi_cs_activate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); struct spi_regs *regs = spi->ctrl->regs; @@ -245,7 +238,7 @@ void spi_cs_activate(struct spi_slave *slave) setbits_le32(®s->command, SLINK_CMD_CS_VAL); } -void spi_cs_deactivate(struct spi_slave *slave) +void tegra30_spi_cs_deactivate(struct spi_slave *slave) { struct tegra_spi_slave *spi = to_tegra_spi(slave); struct spi_regs *regs = spi->ctrl->regs; @@ -254,7 +247,7 @@ void spi_cs_deactivate(struct spi_slave *slave) clrbits_le32(®s->command, SLINK_CMD_CS_VAL); } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, +int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, void *data_in, unsigned long flags) { struct tegra_spi_slave *spi = to_tegra_spi(slave); diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h index f2a70b1a3..d967a75b3 100644 --- a/include/configs/tegra-common-post.h +++ b/include/configs/tegra-common-post.h @@ -150,6 +150,10 @@ MEM_LAYOUT_ENV_SETTINGS \ BOOTCMDS_COMMON +#if defined(CONFIG_TEGRA20_SFLASH) || defined(CONFIG_TEGRA20_SLINK) +#define CONFIG_FDT_SPI +#endif + /* overrides for SPL build here */ #ifdef CONFIG_SPL_BUILD -- cgit v1.2.3-70-g09d2