Merge branch 'master' of git://git.denx.de/u-boot-spi

This commit is contained in:
Tom Rini 2015-04-28 07:28:43 -04:00
commit cc555bd4f4
14 changed files with 93 additions and 94 deletions

11
README
View file

@ -3096,17 +3096,6 @@ CBFS (Coreboot Filesystem) support
memories can be connected with a given cs line.
Currently Xilinx Zynq qspi supports these type of connections.
CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
enable the W#/Vpp signal to disable writing to the status
register on ST MICRON flashes like the N25Q128.
The status register write enable/disable bit, combined with
the W#/VPP signal provides hardware data protection for the
device as follows: When the enable/disable bit is set to 1,
and the W#/VPP signal is driven LOW, the status register
nonvolatile bits become read-only and the WRITE STATUS REGISTER
operation will not execute. The only way to exit this
hardware-protected mode is to drive W#/VPP HIGH.
- SystemACE Support:
CONFIG_SYSTEMACE

View file

@ -164,6 +164,8 @@ static int do_spi_flash_probe(int argc, char * const argv[])
static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
size_t len, const char *buf, char *cmp_buf, size_t *skipped)
{
char *ptr = (char *)buf;
debug("offset=%#x, sector_size=%#x, len=%#zx\n",
offset, flash->sector_size, len);
/* Read the entire sector so to allow for rewriting */
@ -179,16 +181,14 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
/* Erase the entire sector */
if (spi_flash_erase(flash, offset, flash->sector_size))
return "erase";
/* Write the initial part of the block from the source */
if (spi_flash_write(flash, offset, len, buf))
return "write";
/* If it's a partial sector, rewrite the existing part */
/* If it's a partial sector, copy the data into the temp-buffer */
if (len != flash->sector_size) {
/* Rewrite the original data to the end of the sector */
if (spi_flash_write(flash, offset + len,
flash->sector_size - len, &cmp_buf[len]))
return "write";
memcpy(cmp_buf, buf, len);
ptr = cmp_buf;
}
/* Write one complete sector */
if (spi_flash_write(flash, offset, flash->sector_size, ptr))
return "write";
return NULL;
}

View file

@ -97,10 +97,6 @@ enum {
#define STATUS_QEB_MXIC (1 << 6)
#define STATUS_PEC (1 << 7)
#ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
#define STATUS_SRWD (1 << 7) /* SR write protect */
#endif
/* Flash timeout values */
#define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ)
#define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ)
@ -123,7 +119,8 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
* @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO])
* @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id])
* @ext_jedec: Device ext_jedec ID
* @sector_size: Sector size of this device
* @sector_size: Isn't necessarily a sector size from vendor,
* the size listed here is what works with CMD_ERASE_64K
* @nr_sectors: No.of sectors on this device
* @e_rd_cmd: Enum list for read commands
* @flags: Important param, for flash specific behaviour

View file

@ -154,21 +154,17 @@ static void spi_flash_dual_flash(struct spi_flash *flash, u32 *addr)
}
#endif
int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
u8 cmd, u8 poll_bit)
{
struct spi_slave *spi = flash->spi;
unsigned long timebase;
unsigned long flags = SPI_XFER_BEGIN;
int ret;
u8 status;
u8 check_status = 0x0;
u8 poll_bit = STATUS_WIP;
u8 cmd = flash->poll_cmd;
if (cmd == CMD_FLAG_STATUS) {
poll_bit = STATUS_PEC;
if (cmd == CMD_FLAG_STATUS)
check_status = poll_bit;
}
#ifdef CONFIG_SF_DUAL_FLASH
if (spi->flags & SPI_XFER_U_PAGE)
@ -204,6 +200,28 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
return -1;
}
int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
{
struct spi_slave *spi = flash->spi;
int ret;
u8 poll_bit = STATUS_WIP;
u8 cmd = CMD_READ_STATUS;
ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
if (ret < 0)
return ret;
if (flash->poll_cmd == CMD_FLAG_STATUS) {
poll_bit = STATUS_PEC;
cmd = CMD_FLAG_STATUS;
ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
if (ret < 0)
return ret;
}
return 0;
}
int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
size_t cmd_len, const void *buf, size_t buf_len)
{

View file

@ -132,6 +132,9 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
flash->name = params->name;
flash->memory_map = spi->memory_map;
flash->dual_flash = flash->spi->option;
#ifdef CONFIG_DM_SPI_FLASH
flash->flags = params->flags;
#endif
/* Assign spi_flash ops */
#ifndef CONFIG_DM_SPI_FLASH
@ -184,6 +187,9 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
flash->erase_size = flash->sector_size;
}
/* Now erase size becomes valid sector size */
flash->sector_size = flash->erase_size;
/* Look for the fastest read cmd */
cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx);
if (cmd) {
@ -288,34 +294,6 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
}
#endif /* CONFIG_OF_CONTROL */
#ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
/* enable the W#/Vpp signal to disable writing to the status register */
static int spi_enable_wp_pin(struct spi_flash *flash)
{
u8 status;
int ret;
ret = spi_flash_cmd_read_status(flash, &status);
if (ret < 0)
return ret;
ret = spi_flash_cmd_write_status(flash, STATUS_SRWD);
if (ret < 0)
return ret;
ret = spi_flash_cmd_write_disable(flash);
if (ret < 0)
return ret;
return 0;
}
#else
static int spi_enable_wp_pin(struct spi_flash *flash)
{
return 0;
}
#endif
/**
* spi_flash_probe_slave() - Probe for a SPI flash device on a bus
*
@ -394,8 +372,6 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
}
#endif
if (spi_enable_wp_pin(flash))
puts("Enable WP pin failed\n");
/* Release spi bus */
spi_release_bus(spi);
@ -434,6 +410,8 @@ struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
struct spi_slave *bus;
bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
if (!bus)
return NULL;
return spi_flash_probe_tail(bus);
}
@ -444,6 +422,8 @@ struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
struct spi_slave *bus;
bus = spi_setup_slave_fdt(blob, slave_node, spi_node);
if (!bus)
return NULL;
return spi_flash_probe_tail(bus);
}
#endif
@ -469,6 +449,15 @@ int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
{
struct spi_flash *flash = dev_get_uclass_priv(dev);
#if defined(CONFIG_SPI_FLASH_SST)
if (flash->flags & SST_WR) {
if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
return sst_write_bp(flash, offset, len, buf);
else
return sst_write_wp(flash, offset, len, buf);
}
#endif
return spi_flash_cmd_write_ops(flash, offset, len, buf);
}

View file

@ -296,8 +296,9 @@ static int exynos_spi_probe(struct udevice *bus)
return 0;
}
static int exynos_spi_claim_bus(struct udevice *bus)
static int exynos_spi_claim_bus(struct udevice *dev)
{
struct udevice *bus = dev->parent;
struct exynos_spi_priv *priv = dev_get_priv(bus);
exynos_pinmux_config(priv->periph_id, PINMUX_FLAG_NONE);
@ -308,8 +309,9 @@ static int exynos_spi_claim_bus(struct udevice *bus)
return 0;
}
static int exynos_spi_release_bus(struct udevice *bus)
static int exynos_spi_release_bus(struct udevice *dev)
{
struct udevice *bus = dev->parent;
struct exynos_spi_priv *priv = dev_get_priv(bus);
spi_flush_fifo(priv->regs);

View file

@ -20,7 +20,7 @@
#include <asm/io.h>
#include "omap3_spi.h"
#define SPI_WAIT_TIMEOUT 3000000
#define SPI_WAIT_TIMEOUT 10
static void spi_reset(struct omap3_spi_slave *ds)
{
@ -227,7 +227,7 @@ int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp,
{
struct omap3_spi_slave *ds = to_omap3_spi(slave);
int i;
int timeout = SPI_WAIT_TIMEOUT;
ulong start;
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
/* Enable the channel */
@ -241,9 +241,10 @@ int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp,
for (i = 0; i < len; i++) {
/* wait till TX register is empty (TXS == 1) */
start = get_timer(0);
while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
OMAP3_MCSPI_CHSTAT_TXS)) {
if (--timeout <= 0) {
if (get_timer(start) > SPI_WAIT_TIMEOUT) {
printf("SPI TXS timed out, status=0x%08x\n",
readl(&ds->regs->channel[ds->slave.cs].chstat));
return -1;
@ -280,7 +281,7 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp,
{
struct omap3_spi_slave *ds = to_omap3_spi(slave);
int i;
int timeout = SPI_WAIT_TIMEOUT;
ulong start;
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
/* Enable the channel */
@ -295,10 +296,11 @@ int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp,
writel(0, &ds->regs->channel[ds->slave.cs].tx);
for (i = 0; i < len; i++) {
start = get_timer(0);
/* Wait till RX register contains data (RXS == 1) */
while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
OMAP3_MCSPI_CHSTAT_RXS)) {
if (--timeout <= 0) {
if (get_timer(start) > SPI_WAIT_TIMEOUT) {
printf("SPI RXS timed out, status=0x%08x\n",
readl(&ds->regs->channel[ds->slave.cs].chstat));
return -1;
@ -332,7 +334,7 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
const void *txp, void *rxp, unsigned long flags)
{
struct omap3_spi_slave *ds = to_omap3_spi(slave);
int timeout = SPI_WAIT_TIMEOUT;
ulong start;
int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
int irqstatus = readl(&ds->regs->irqstatus);
int i=0;
@ -350,9 +352,10 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
for (i=0; i < len; i++){
/* Write: wait for TX empty (TXS == 1)*/
irqstatus |= (1<< (4*(ds->slave.bus)));
start = get_timer(0);
while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
OMAP3_MCSPI_CHSTAT_TXS)) {
if (--timeout <= 0) {
if (get_timer(start) > SPI_WAIT_TIMEOUT) {
printf("SPI TXS timed out, status=0x%08x\n",
readl(&ds->regs->channel[ds->slave.cs].chstat));
return -1;
@ -368,9 +371,10 @@ int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
writel(((u8 *)txp)[i], tx);
/*Read: wait for RX containing data (RXS == 1)*/
start = get_timer(0);
while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
OMAP3_MCSPI_CHSTAT_RXS)) {
if (--timeout <= 0) {
if (get_timer(start) > SPI_WAIT_TIMEOUT) {
printf("SPI RXS timed out, status=0x%08x\n",
readl(&ds->regs->channel[ds->slave.cs].chstat));
return -1;

View file

@ -67,7 +67,7 @@ int spi_claim_bus(struct spi_slave *slave)
if (ret)
return ret;
return ops->claim_bus ? ops->claim_bus(bus) : 0;
return ops->claim_bus ? ops->claim_bus(dev) : 0;
}
void spi_release_bus(struct spi_slave *slave)
@ -77,7 +77,7 @@ void spi_release_bus(struct spi_slave *slave)
struct dm_spi_ops *ops = spi_get_ops(bus);
if (ops->release_bus)
ops->release_bus(bus);
ops->release_bus(dev);
}
int spi_xfer(struct spi_slave *slave, unsigned int bitlen,

View file

@ -153,8 +153,9 @@ static int tegra114_spi_probe(struct udevice *bus)
return 0;
}
static int tegra114_spi_claim_bus(struct udevice *bus)
static int tegra114_spi_claim_bus(struct udevice *dev)
{
struct udevice *bus = dev->parent;
struct tegra114_spi_priv *priv = dev_get_priv(bus);
struct spi_regs *regs = priv->regs;

View file

@ -125,8 +125,9 @@ static int tegra20_sflash_probe(struct udevice *bus)
return 0;
}
static int tegra20_sflash_claim_bus(struct udevice *bus)
static int tegra20_sflash_claim_bus(struct udevice *dev)
{
struct udevice *bus = dev->parent;
struct tegra20_sflash_priv *priv = dev_get_priv(bus);
struct spi_regs *regs = priv->regs;
u32 reg;

View file

@ -141,8 +141,9 @@ static int tegra30_spi_probe(struct udevice *bus)
return 0;
}
static int tegra30_spi_claim_bus(struct udevice *bus)
static int tegra30_spi_claim_bus(struct udevice *dev)
{
struct udevice *bus = dev->parent;
struct tegra30_spi_priv *priv = dev_get_priv(bus);
struct spi_regs *regs = priv->regs;
u32 reg;

View file

@ -227,9 +227,6 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
debug("spi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
slave->bus, slave->cs, bitlen, len, flags);
if (bitlen == 0)
return -1;
if (bitlen % 8) {
debug("spi_xfer: Non byte aligned SPI transfer\n");
return -1;

View file

@ -38,11 +38,12 @@
/* SPI RX operation modes */
#define SPI_OPM_RX_AS (1 << 0)
#define SPI_OPM_RX_DOUT (1 << 1)
#define SPI_OPM_RX_DIO (1 << 2)
#define SPI_OPM_RX_QOF (1 << 3)
#define SPI_OPM_RX_QIOF (1 << 4)
#define SPI_OPM_RX_EXTN (SPI_OPM_RX_AS | SPI_OPM_RX_DOUT | \
#define SPI_OPM_RX_AF (1 << 1)
#define SPI_OPM_RX_DOUT (1 << 2)
#define SPI_OPM_RX_DIO (1 << 3)
#define SPI_OPM_RX_QOF (1 << 4)
#define SPI_OPM_RX_QIOF (1 << 5)
#define SPI_OPM_RX_EXTN (SPI_OPM_RX_AS | SPI_OPM_RX_AF | SPI_OPM_RX_DOUT | \
SPI_OPM_RX_DIO | SPI_OPM_RX_QOF | \
SPI_OPM_RX_QIOF)
@ -385,12 +386,12 @@ struct dm_spi_ops {
* allowed to claim the same bus for several slaves without releasing
* the bus in between.
*
* @bus: The SPI slave
* @dev: The SPI slave
*
* Returns: 0 if the bus was claimed successfully, or a negative value
* if it wasn't.
*/
int (*claim_bus)(struct udevice *bus);
int (*claim_bus)(struct udevice *dev);
/**
* Release the SPI bus
@ -399,9 +400,9 @@ struct dm_spi_ops {
* all transfers have finished. It may disable any SPI hardware as
* appropriate.
*
* @bus: The SPI slave
* @dev: The SPI slave
*/
int (*release_bus)(struct udevice *bus);
int (*release_bus)(struct udevice *dev);
/**
* Set the word length for SPI transactions
@ -413,7 +414,7 @@ struct dm_spi_ops {
*
* Returns: 0 on success, -ve on failure.
*/
int (*set_wordlen)(struct udevice *bus, unsigned int wordlen);
int (*set_wordlen)(struct udevice *dev, unsigned int wordlen);
/**
* SPI transfer

View file

@ -62,11 +62,10 @@ struct spi_slave;
* return 0 - Success, 1 - Failure
*/
struct spi_flash {
struct spi_slave *spi;
#ifdef CONFIG_DM_SPI_FLASH
struct spi_slave *spi;
struct udevice *dev;
#else
struct spi_slave *spi;
u16 flags;
#endif
const char *name;
u8 dual_flash;
@ -91,13 +90,13 @@ struct spi_flash {
#ifndef CONFIG_DM_SPI_FLASH
/*
* These are not strictly needed for driver model, but keep them here
* whilt the transition is in progress.
* while the transition is in progress.
*
* Normally each driver would provide its own operations, but for
* SPI flash most chips use the same algorithms. One approach is
* to create a 'common' SPI flash device which knows how to talk
* to most devices, and then allow other drivers to be used instead
* if requird, perhaps with a way of scanning through the list to
* if required, perhaps with a way of scanning through the list to
* find the driver that matches the device.
*/
int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);