From 66ebf9c8ade087c8886777a235f05343b0b3fb4c Mon Sep 17 00:00:00 2001 From: Che-Liang Chiou Date: Thu, 10 Nov 2011 16:18:30 +0800 Subject: tegra: spi: add SFLASH and SLINK drivers BUG=chromium-os:21033 TEST=run `sf erase, write` and then `sf read` on seaboard verify the data it reads from SPI flash matches that it writes to Change-Id: I1b04afa4b54738cd93be29b70f428bdc3e6b234f Signed-off-by: Tom Warren Reviewed-on: https://gerrit.chromium.org/gerrit/11472 Commit-Ready: Che-Liang Chiou Reviewed-by: Che-Liang Chiou Tested-by: Che-Liang Chiou --- arch/arm/include/asm/arch-tegra/spi.h | 60 +++++++++++++++++++++++++++++++---- drivers/spi/tegra_spi.c | 59 +++++++++++++++++++++++----------- include/configs/seaboard.h | 1 + 3 files changed, 95 insertions(+), 25 deletions(-) diff --git a/arch/arm/include/asm/arch-tegra/spi.h b/arch/arm/include/asm/arch-tegra/spi.h index 7f5035d818f..6c14d732921 100644 --- a/arch/arm/include/asm/arch-tegra/spi.h +++ b/arch/arm/include/asm/arch-tegra/spi.h @@ -1,5 +1,5 @@ /* - * NVIDIA Tegra2 SPI-FLASH controller + * NVIDIA Tegra SPI (SPIFLASH & SLINK) controllers * * Copyright 2010-2011 NVIDIA Corporation * @@ -28,6 +28,20 @@ #include struct spi_tegra { +#ifdef CONFIG_USE_SLINK + 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 */ +#else /* CONFIG_USE_SFLASH */ u32 command; /* SPI_COMMAND_0 register */ u32 status; /* SPI_STATUS_0 register */ u32 rx_cmp; /* SPI_RX_CMP_0 register */ @@ -35,9 +49,45 @@ struct spi_tegra { u32 tx_fifo; /* SPI_TX_FIFO_0 register */ u32 rsvd[3]; /* offsets 0x14 to 0x1F reserved */ u32 rx_fifo; /* SPI_RX_FIFO_0 register */ - +#endif }; +#ifdef CONFIG_USE_SLINK +/* COMMAND */ +#define SPI_CMD_ENB (1 << 31) +#define SPI_CMD_GO (1 << 30) +#define SPI_CMD_M_S (1 << 28) +#define SPI_CMD_CK_SDA (1 << 21) +#define SPI_CMD_CS_POL (1 << 13) +#define SPI_CMD_CS_VAL (1 << 12) +#define SPI_CMD_CS_SOFT (1 << 11) +#define SPI_CMD_BIT_LENGTH (1 << 4) +/* COMMAND2 */ +#define SPI_CMD2_TXEN (1 << 30) +#define SPI_CMD2_RXEN (1 << 31) +#define SPI_CMD2_SS_EN (1 << 18) +#define SPI_CMD2_CS_ACTIVE_BETWEEN (1 << 17) +/* STATUS */ +#define SPI_STAT_BSY (1 << 31) +#define SPI_STAT_RDY (1 << 30) +#define SPI_STAT_ERR (1 << 29) +#define SPI_STAT_RXF_FLUSH (1 << 27) +#define SPI_STAT_TXF_FLUSH (1 << 26) +#define SPI_STAT_RXF_OVF (1 << 25) +#define SPI_STAT_TXF_UNR (1 << 24) +#define SPI_STAT_RXF_EMPTY (1 << 23) +#define SPI_STAT_RXF_FULL (1 << 22) +#define SPI_STAT_TXF_EMPTY (1 << 21) +#define SPI_STAT_TXF_FULL (1 << 20) +#define SPI_STAT_TXF_OVF (1 << 19) +#define SPI_STAT_RXF_UNR (1 << 18) +#define SPI_STAT_CUR_BLKCNT (1 << 15) +/* STATUS2 */ +#define SPI_STAT2_RXF_FULL_CNT (1 << 16) +#define SPI_STAT2_TXF_FULL_CNT (1 << 0) + +#else /* CONFIG_USE_SFLASH */ + #define SPI_CMD_GO (1 << 30) #define SPI_CMD_ACTIVE_SCLK (1 << 26) #define SPI_CMD_CK_SDA (1 << 21) @@ -53,7 +103,6 @@ struct spi_tegra { #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) @@ -67,10 +116,9 @@ struct spi_tegra { #define SPI_STAT_TXF_FULL (1 << 22) #define SPI_STAT_SEL_TXRX_N (1 << 16) #define SPI_STAT_CUR_BLKCNT (1 << 15) +#endif /* CONFIG_USE_SLINK */ -#define GMD_SEL_SFLASH_RANGE 31 : 30 -#define GMC_SEL_SFLASH_RANGE 3 : 2 - +#define SPI_CMD_BIT_LENGTH_MASK 0x0000001F #define SPI_TIMEOUT 1000 #endif /* _TEGRA_SPI_H_ */ diff --git a/drivers/spi/tegra_spi.c b/drivers/spi/tegra_spi.c index c69a63915c6..2d724acd262 100644 --- a/drivers/spi/tegra_spi.c +++ b/drivers/spi/tegra_spi.c @@ -24,21 +24,22 @@ #include #include -#include /* for NS16550_drain and NS16550_clear */ #include #include #include -#include -#include #include #include -#include #include + +#ifdef CONFIG_USE_SFLASH +#include /* for NS16550_drain and NS16550_clear */ +#include #include "uart-spi-fix.h" +#endif int spi_cs_is_valid(unsigned int bus, unsigned int cs) { - /* Tegra2 SPI-Flash - only 1 device ('bus/cs') */ + /* Tegra SPI - only 1 device ('bus/cs') */ if (bus > 0 && cs != 0) return 0; else @@ -62,7 +63,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, slave->cs = cs; /* - * Currently, Tegra2 SFLASH uses mode 0 & a 24MHz clock. + * Currently, Tegra SPI uses mode 0 & a 48MHz clock. * Use 'mode' and 'maz_hz' to change that here, if needed. */ @@ -78,9 +79,15 @@ void spi_init(void) { struct spi_tegra *spi = (struct spi_tegra *)TEGRA_SPI_BASE; u32 reg; + enum periph_id id; +#ifdef CONFIG_USE_SLINK + id = PERIPH_ID_SBC4; +#else + id = PERIPH_ID_SPI1; +#endif /* Change SPI clock to 48MHz, PLLP_OUT0 source */ - clock_start_periph_pll(PERIPH_ID_SPI1, CLOCK_ID_PERIPH, CLK_48M); + clock_start_periph_pll(id, CLOCK_ID_PERIPH, CLK_48M); /* Clear stale status here */ reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \ @@ -88,6 +95,13 @@ void spi_init(void) writel(reg, &spi->status); debug("spi_init: STATUS = %08x\n", readl(&spi->status)); +#ifdef CONFIG_USE_SLINK + /* Set master mode */ + reg = readl(&spi->command); + writel(reg | SPI_CMD_M_S, &spi->command); + debug("spi_init: COMMAND = %08x\n", readl(&spi->command)); +#endif + /* * Use sw-controlled CS, so we can clock in data after ReadID, etc. */ @@ -96,6 +110,7 @@ void spi_init(void) writel(reg | SPI_CMD_CS_SOFT, &spi->command); debug("spi_init: COMMAND = %08x\n", readl(&spi->command)); +#ifdef CONFIG_USE_SFLASH /* * SPI pins on Tegra2 are muxed - change pinmux last due to UART * issue. @@ -111,7 +126,8 @@ void spi_init(void) * spi_uart_switch(). */ pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH); -#endif +#endif /* CONFIG_SPI_UART_SWITCH */ +#endif /* CONFIG_USE_SFLASH */ } int spi_claim_bus(struct spi_slave *slave) @@ -134,8 +150,9 @@ void spi_cs_activate(struct spi_slave *slave) struct spi_tegra *spi = (struct spi_tegra *)TEGRA_SPI_BASE; u32 val; +#ifdef CONFIG_USE_SFLASH spi_enable(); - +#endif /* CS is negated on Tegra, so drive a 1 to get a 0 */ val = readl(&spi->command); writel(val | SPI_CMD_CS_VAL, &spi->command); @@ -168,11 +185,21 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, status = readl(&spi->status); writel(status, &spi->status); /* Clear all SPI events via R/W */ debug("spi_xfer entry: STATUS = %08x\n", status); - +#ifdef CONFIG_USE_SLINK + reg = readl(&spi->status2); + writel(reg, &spi->status2); /* Clear all STATUS2 events via R/W */ + debug("spi_xfer entry: STATUS2 = %08x\n", reg); + + debug("spi_xfer entry: COMMAND = %08x\n", readl(&spi->command)); + reg = readl(&spi->command2); + writel((reg |= (SPI_CMD2_TXEN | SPI_CMD2_RXEN)), &spi->command2); + writel((reg |= SPI_CMD2_SS_EN), &spi->command2); + debug("spi_xfer: COMMAND2 = %08x\n", readl(&spi->command2)); +#else /* SPIFLASH a la Tegra2 */ reg = readl(&spi->command); writel((reg |= (SPI_CMD_TXEN | SPI_CMD_RXEN)), &spi->command); debug("spi_xfer: COMMAND = %08x\n", readl(&spi->command)); - +#endif if (flags & SPI_XFER_BEGIN) spi_cs_activate(slave); @@ -189,8 +216,8 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, num_bytes -= bytes; if (dout) - dout += bytes; - bitlen -= bits; + dout += bytes; + bitlen -= bits; reg = readl(&spi->command); reg &= ~SPI_CMD_BIT_LENGTH_MASK; @@ -240,12 +267,6 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, (tmpdin & 0xff); tmpdin >>= 8; } -/* this is not the same! - for (i = 0; i < bytes; ++i) { - ((u8 *)din)[i] = (tmpdin >> 24); - tmpdin <<= 8; - } -*/ din += bytes; } } diff --git a/include/configs/seaboard.h b/include/configs/seaboard.h index cbb1d3b808a..3857a89d1e8 100644 --- a/include/configs/seaboard.h +++ b/include/configs/seaboard.h @@ -200,6 +200,7 @@ /* SPI */ #define CONFIG_TEGRA_SPI +#define CONFIG_USE_SFLASH /* T20 boards use SFLASH */ #define CONFIG_SPI_FLASH #define CONFIG_SPI_FLASH_WINBOND #define CONFIG_NEW_SPI_XFER -- cgit v1.2.3