Commit 8b906a9f authored by Tom Rini's avatar Tom Rini
Browse files

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

parents 3c47f2f4 1e7133e9
......@@ -164,13 +164,13 @@ init_fnc_t *init_sequence_r[] = {
#ifndef CONFIG_SYS_NO_FLASH
flash_init_r,
#endif
#ifdef CONFIG_SPI
init_func_spi;
#endif
env_relocate_r,
#ifdef CONFIG_PCI
pci_init_r,
#endif
#ifdef CONFIG_SPI
init_func_spi,
#endif
env_relocate_r,
stdio_init,
jumptable_init_r,
console_init_r,
......
......@@ -21,4 +21,15 @@
chosen { };
memory { device_type = "memory"; reg = <0 0>; };
spi {
#address-cells = <1>;
#size-cells = <0>;
compatible = "intel,ich9";
spi-flash@0 {
reg = <0>;
compatible = "winbond,w25q64", "spi-flash";
memory-map = <0xff800000 0x00800000>;
};
};
};
......@@ -369,8 +369,8 @@ static void spi_test_next_stage(struct test_info *test)
* @param vbuf Verification buffer
* @return 0 if ok, -1 on error
*/
static int spi_flash_test(struct spi_flash *flash, char *buf, ulong len,
ulong offset, char *vbuf)
static int spi_flash_test(struct spi_flash *flash, uint8_t *buf, ulong len,
ulong offset, uint8_t *vbuf)
{
struct test_info test;
int i;
......@@ -431,9 +431,9 @@ static int do_spi_flash_test(int argc, char * const argv[])
{
unsigned long offset;
unsigned long len;
char *buf = (char *)CONFIG_SYS_TEXT_BASE;
uint8_t *buf = (uint8_t *)CONFIG_SYS_TEXT_BASE;
char *endp;
char *vbuf;
uint8_t *vbuf;
int ret;
offset = simple_strtoul(argv[1], &endp, 16);
......
......@@ -480,15 +480,13 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
return NULL;
}
asf = malloc(sizeof(struct atmel_spi_flash));
asf = spi_flash_alloc(struct atmel_spi_flash, spi, params->name);
if (!asf) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
asf->params = params;
asf->flash.spi = spi;
asf->flash.name = params->name;
/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;
......@@ -513,7 +511,6 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
asf->flash.erase = dataflash_erase_at45;
page_size += 1 << (params->l2_page_size - 5);
} else {
asf->flash.read = spi_flash_cmd_read_fast;
asf->flash.write = dataflash_write_p2;
asf->flash.erase = dataflash_erase_p2;
}
......@@ -524,9 +521,6 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
case DF_FAMILY_AT26F:
case DF_FAMILY_AT26DF:
asf->flash.read = spi_flash_cmd_read_fast;
asf->flash.write = spi_flash_cmd_write_multi;
asf->flash.erase = spi_flash_cmd_erase;
asf->flash.page_size = page_size;
asf->flash.sector_size = 4096;
/* clear SPRL# bit for locked flash */
......
......@@ -46,18 +46,12 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
return NULL;
}
flash = malloc(sizeof(*flash));
flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
flash->spi = spi;
flash->name = params->name;
flash->write = spi_flash_cmd_write_multi;
flash->erase = spi_flash_cmd_erase;
flash->read = spi_flash_cmd_read_fast;
flash->page_size = 256;
flash->sector_size = 256 * 16 * 16;
flash->size = 256 * 16
......
......@@ -97,18 +97,12 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
return NULL;
}
flash = malloc(sizeof(*flash));
flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
flash->spi = spi;
flash->name = params->name;
flash->write = spi_flash_cmd_write_multi;
flash->erase = spi_flash_cmd_erase;
flash->read = spi_flash_cmd_read_fast;
flash->page_size = 256;
flash->sector_size = 256 * 16 * 16;
flash->size = flash->sector_size * params->nr_blocks;
......
......@@ -284,15 +284,13 @@ struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode)
return NULL;
found:
sn = malloc(sizeof(*sn));
sn = spi_flash_alloc(struct ramtron_spi_fram, spi, params->name);
if (!sn) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
sn->params = params;
sn->flash.spi = spi;
sn->flash.name = params->name;
sn->flash.write = ramtron_write;
sn->flash.read = ramtron_read;
......
......@@ -128,18 +128,12 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
return NULL;
}
flash = malloc(sizeof(*flash));
flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
flash->spi = spi;
flash->name = params->name;
flash->write = spi_flash_cmd_write_multi;
flash->erase = spi_flash_cmd_erase;
flash->read = spi_flash_cmd_read_fast;
flash->page_size = 256;
flash->sector_size = 256 * params->pages_per_sector;
flash->size = flash->sector_size * params->nr_sectors;
......
......@@ -8,6 +8,7 @@
*/
#include <common.h>
#include <fdtdec.h>
#include <malloc.h>
#include <spi.h>
#include <spi_flash.h>
......@@ -15,6 +16,8 @@
#include "spi_flash_internal.h"
DECLARE_GLOBAL_DATA_PTR;
static void spi_flash_addr(u32 addr, u8 *cmd)
{
/* cmd[0] is actual command */
......@@ -87,6 +90,9 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
if (flash->spi->max_write_size)
chunk_len = min(chunk_len, flash->spi->max_write_size);
cmd[1] = page_addr >> 8;
cmd[2] = page_addr;
cmd[3] = byte_addr;
......@@ -111,8 +117,11 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
if (ret)
break;
page_addr++;
byte_addr = 0;
byte_addr += chunk_len;
if (byte_addr == page_size) {
page_addr++;
byte_addr = 0;
}
}
debug("SF: program %s %zu bytes @ %#x\n",
......@@ -140,6 +149,10 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
{
u8 cmd[5];
/* Handle memory-mapped SPI */
if (flash->memory_map)
memcpy(data, flash->memory_map + offset, len);
cmd[0] = CMD_READ_ARRAY_FAST;
spi_flash_addr(offset, cmd);
cmd[4] = 0x00;
......@@ -269,6 +282,34 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
return 0;
}
#ifdef CONFIG_OF_CONTROL
int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
{
fdt_addr_t addr;
fdt_size_t size;
int node;
/* If there is no node, do nothing */
node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
if (node < 0)
return 0;
addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
if (addr == FDT_ADDR_T_NONE) {
debug("%s: Cannot decode address\n", __func__);
return 0;
}
if (flash->size != size) {
debug("%s: Memory map must cover entire device\n", __func__);
return -1;
}
flash->memory_map = (void *)addr;
return 0;
}
#endif /* CONFIG_OF_CONTROL */
/*
* The following table holds all device probe functions
*
......@@ -385,9 +426,18 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
goto err_manufacturer_probe;
}
#ifdef CONFIG_OF_CONTROL
if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
debug("SF: FDT decode error\n");
goto err_manufacturer_probe;
}
#endif
printf("SF: Detected %s with page size ", flash->name);
print_size(flash->sector_size, ", total ");
print_size(flash->size, "\n");
print_size(flash->size, "");
if (flash->memory_map)
printf(", mapped at %p", flash->memory_map);
puts("\n");
spi_release_bus(spi);
......@@ -401,6 +451,31 @@ err_claim_bus:
return NULL;
}
void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi,
const char *name)
{
struct spi_flash *flash;
void *ptr;
ptr = malloc(size);
if (!ptr) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
memset(ptr, '\0', size);
flash = (struct spi_flash *)(ptr + offset);
/* Set up some basic fields - caller will sort out sizes */
flash->spi = spi;
flash->name = name;
flash->read = spi_flash_cmd_read_fast;
flash->write = spi_flash_cmd_write_multi;
flash->erase = spi_flash_cmd_erase;
return flash;
}
void spi_flash_free(struct spi_flash *flash)
{
spi_free_slave(flash->spi);
......
......@@ -203,22 +203,16 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
return NULL;
}
stm = malloc(sizeof(*stm));
stm = spi_flash_alloc(struct sst_spi_flash, spi, params->name);
if (!stm) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
stm->params = params;
stm->flash.spi = spi;
stm->flash.name = params->name;
if (stm->params->flags & SST_FEAT_WP)
stm->flash.write = sst_write_wp;
else
stm->flash.write = spi_flash_cmd_write_multi;
stm->flash.erase = spi_flash_cmd_erase;
stm->flash.read = spi_flash_cmd_read_fast;
stm->flash.page_size = 256;
stm->flash.sector_size = 4096;
stm->flash.size = stm->flash.sector_size * params->nr_sectors;
......
......@@ -176,18 +176,12 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
return NULL;
}
flash = malloc(sizeof(*flash));
flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
flash->spi = spi;
flash->name = params->name;
flash->write = spi_flash_cmd_write_multi;
flash->erase = spi_flash_cmd_erase;
flash->read = spi_flash_cmd_read_fast;
flash->page_size = 256;
flash->sector_size = 256 * params->pages_per_sector;
flash->size = flash->sector_size * params->nr_sectors;
......
......@@ -92,18 +92,12 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
return NULL;
}
flash = malloc(sizeof(*flash));
flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
flash->spi = spi;
flash->name = params->name;
flash->write = spi_flash_cmd_write_multi;
flash->erase = spi_flash_cmd_erase;
flash->read = spi_flash_cmd_read_fast;
flash->page_size = 256;
flash->sector_size = 4096;
flash->size = 4096 * 16 * params->nr_blocks;
......
......@@ -25,6 +25,9 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libspi.o
# There are many options which enable SPI, so make this library available
COBJS-y += spi.o
COBJS-$(CONFIG_ALTERA_SPI) += altera_spi.o
COBJS-$(CONFIG_ANDES_SPI) += andes_spi.o
COBJS-$(CONFIG_ARMADA100_SPI) += armada100_spi.o
......@@ -36,6 +39,7 @@ COBJS-$(CONFIG_CF_SPI) += cf_spi.o
COBJS-$(CONFIG_CF_QSPI) += cf_qspi.o
COBJS-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
COBJS-$(CONFIG_EXYNOS_SPI) += exynos_spi.o
COBJS-$(CONFIG_ICH_SPI) += ich.o
COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
......
......@@ -83,12 +83,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (!spi_cs_is_valid(bus, cs))
return NULL;
altspi = malloc(sizeof(*altspi));
altspi = spi_alloc_slave(struct altera_spi_slave, bus, cs);
if (!altspi)
return NULL;
altspi->slave.bus = bus;
altspi->slave.cs = cs;
altspi->base = altera_spi_base_list[bus];
debug("%s: bus:%i cs:%i base:%lx\n", __func__,
bus, cs, altspi->base);
......
......@@ -53,12 +53,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (!spi_cs_is_valid(bus, cs))
return NULL;
ds = malloc(sizeof(*ds));
ds = spi_alloc_slave(struct andes_spi_slave, bus, cs);
if (!ds)
return NULL;
ds->slave.bus = bus;
ds->slave.cs = cs;
ds->regs = (struct andes_spi_regs *)CONFIG_SYS_SPI_BASE;
/*
......
......@@ -120,12 +120,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
{
struct armd_spi_slave *pss;
pss = malloc(sizeof(*pss));
pss = spi_alloc_slave(struct armd_spi_slave, bus, cs);
if (!pss)
return NULL;
pss->slave.bus = bus;
pss->slave.cs = cs;
pss->spi_reg = (struct ssp_reg *)SSP_REG_BASE(CONFIG_SYS_SSP_PORT);
pss->cr0 = SSCR0_MOTO | SSCR0_DATASIZE(DEFAULT_WORD_LEN) | SSCR0_SSE;
......
......@@ -84,12 +84,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (mode & SPI_CPOL)
csrx |= ATMEL_SPI_CSRx_CPOL;
as = malloc(sizeof(struct atmel_spi_slave));
as = spi_alloc_slave(struct atmel_spi_slave, bus, cs);
if (!as)
return NULL;
as->slave.bus = bus;
as->slave.cs = cs;
as->regs = regs;
as->mr = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS
#if defined(CONFIG_AT91SAM9X5) || defined(CONFIG_AT91SAM9M10G45)
......
......@@ -182,12 +182,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
default: return NULL;
}
bss = malloc(sizeof(*bss));
bss = spi_alloc_slave(struct bfin_spi_slave, bus, cs);
if (!bss)
return NULL;
bss->slave.bus = bus;
bss->slave.cs = cs;
bss->mmr_base = (void *)mmr_base;
bss->ctl = SPE | MSTR | TDBR_CORE;
if (mode & SPI_CPHA) bss->ctl |= CPHA;
......
......@@ -178,12 +178,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
return NULL;
}
bss = malloc(sizeof(*bss));
bss = spi_alloc_slave(struct bfin_spi_slave, bus, cs);
if (!bss)
return NULL;
bss->slave.bus = bus;
bss->slave.cs = cs;
bss->regs = (struct bfin_spi_regs *)reg_base;
bss->control = SPI_CTL_EN | SPI_CTL_MSTR;
if (mode & SPI_CPHA)
......
......@@ -120,13 +120,11 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (!spi_cs_is_valid(bus, cs))
return NULL;
dev = malloc(sizeof(struct cf_qspi_slave));
dev = spi_alloc_slave(struct cf_qspi_slave, bus, cs);
if (!dev)
return NULL;
/* Initialize to known value */
dev->slave.bus = bus;
dev->slave.cs = cs;
dev->regs = (qspi_t *)MMAP_QSPI;
dev->qmr = 0;
dev->qwr = 0;
......
......@@ -330,12 +330,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (!spi_cs_is_valid(bus, cs))
return NULL;
cfslave = malloc(sizeof(struct cf_spi_slave));
cfslave = spi_alloc_slave(struct cf_spi_slave, bus, cs);
if (!cfslave)
return NULL;
cfslave->slave.bus = bus;
cfslave->slave.cs = cs;
cfslave->baudrate = max_hz;
/* specific setup */
......
......@@ -44,12 +44,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (!spi_cs_is_valid(bus, cs))
return NULL;
ds = malloc(sizeof(*ds));
ds = spi_alloc_slave(struct davinci_spi_slave, bus, cs);
if (!ds)
return NULL;
ds->slave.bus = bus;
ds->slave.cs = cs;
ds->regs = (struct davinci_spi_regs *)CONFIG_SYS_SPI_BASE;
ds->freq = max_hz;
......
......@@ -89,15 +89,13 @@ struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
return NULL;
}
spi_slave = malloc(sizeof(*spi_slave));
spi_slave = spi_alloc_slave(struct exynos_spi_slave, busnum, cs);
if (!spi_slave) {
debug("%s: Could not allocate spi_slave\n", __func__);
return NULL;
}
bus = &spi_bus[busnum];
spi_slave->slave.bus = busnum;
spi_slave->slave.cs = cs;
spi_slave->regs = bus->regs;
spi_slave->mode = mode;
spi_slave->periph_id = bus->periph_id;
......
......@@ -79,12 +79,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (!spi_cs_is_valid(bus, cs))
return NULL;
fsl = malloc(sizeof(struct fsl_spi_slave));
fsl = spi_alloc_slave(struct fsl_spi_slave, bus, cs);
if (!fsl)
return NULL;
fsl->slave.bus = bus;
fsl->slave.cs = cs;
fsl->mode = mode;
fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN;
......
/*
* Copyright (c) 2011-12 The Chromium OS Authors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* 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
*
* This file is derived from the flashrom project.
*/
#include <common.h>
#include <malloc.h>
#include <spi.h>
#include <pci.h>
#include <pci_ids.h>
#include <asm/io.h>
#include "ich.h"
#define SPI_OPCODE_WREN 0x06
#define SPI_OPCODE_FAST_READ 0x0b
struct ich_ctlr {
pci_dev_t dev; /* PCI device number */
int ich_version; /* Controller version, 7 or 9 */
int ichspi_lock;
int locked;