Stefan Reinauer has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/54944 )
Change subject: Add support for TerribleFire TF530 SPI controller ......................................................................
Add support for TerribleFire TF530 SPI controller
Change-Id: I109eec4dec89650bb80d3d1da905d33f65f60f5a Signed-off-by: Stefan Reinauer stefan.reinauer@coreboot.org --- M Makefile M programmer.h A tf530_spi.c 3 files changed, 188 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/44/54944/1
diff --git a/Makefile b/Makefile index c486c12..0026898 100644 --- a/Makefile +++ b/Makefile @@ -138,6 +138,7 @@ ifeq ($(TARGET_OS), AmigaOS) override CPPFLAGS += -m68000 -mcrt=clib2 override LIBS += -mcrt=clib2 -lamiga -lm -lunix +override CONFIG_TF530_SPI = yes # Bus Pirate, Serprog and PonyProg are not supported under AmigaOS (missing serial support). ifeq ($(CONFIG_BUSPIRATE_SPI), yes) UNSUPPORTED_FEATURES += CONFIG_BUSPIRATE_SPI=yes @@ -1207,6 +1208,11 @@ PROGRAMMER_OBJS += jlink_spi.o endif
+ifeq ($(CONFIG_TF530_SPI), yes) +FEATURE_CFLAGS += -D'CONFIG_TF530_SPI=1' +PROGRAMMER_OBJS += tf530_spi.o +endif + ifeq ($(CONFIG_NI845X_SPI), yes) FEATURE_CFLAGS += -D'CONFIG_NI845X_SPI=1'
diff --git a/programmer.h b/programmer.h index 790fcc8..cbb5977 100644 --- a/programmer.h +++ b/programmer.h @@ -112,6 +112,9 @@ #if CONFIG_LINUX_SPI == 1 PROGRAMMER_LINUX_SPI, #endif +#if CONFIG_TF530_SPI == 1 + PROGRAMMER_TF530_SPI, +#endif #if CONFIG_USBBLASTER_SPI == 1 PROGRAMMER_USBBLASTER_SPI, #endif @@ -559,6 +562,11 @@ int linux_spi_init(void); #endif
+/* tf530_spi.c */ +#if CONFIG_TF530_SPI == 1 +int tf53x_spi_init(void); +#endif + /* dediprog.c */ #if CONFIG_DEDIPROG == 1 int dediprog_init(void); diff --git a/tf530_spi.c b/tf530_spi.c new file mode 100644 index 0000000..76a7e43 --- /dev/null +++ b/tf530_spi.c @@ -0,0 +1,174 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2019 Steven J Leary + * + * 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; version 2 of the License. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if CONFIG_TF530_SPI == 1 + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <errno.h> +#include <ctype.h> +#include "flash.h" +#include "chipdrivers.h" +#include "programmer.h" +#include "spi.h" + +#include <exec/resident.h> +#include <exec/errors.h> +#include <exec/memory.h> +#include <exec/lists.h> +#include <exec/alerts.h> +#include <exec/tasks.h> +#include <exec/io.h> +#include <exec/execbase.h> + +#include <libraries/expansion.h> + +#include <devices/trackdisk.h> +#include <devices/timer.h> +#include <devices/scsidisk.h> + +#include <dos/filehandler.h> + +#include <proto/exec.h> +#include <proto/disk.h> +#include <proto/expansion.h> + +struct TF53xSDRegs { + volatile uint8_t ctrl; // Control register + volatile uint8_t unused1; // padding + volatile uint8_t unused2; // padding + volatile uint8_t unused3; // padding + volatile uint8_t data; // data +}; + +static struct ConfigDev *cd = NULL; + +#define TF53x_CTRL_CS0 1 +#define TF53x_CTRL_CS1 2 +#define TF53x_CTRL_BUSY 4 +#define TF53x_CTRL_CS2 8 + +static void spi_send_byte(struct TF53xSDRegs *port, uint8_t value) +{ + uint8_t busy = 0; + + while (busy == 0) { + busy = port->ctrl & TF53x_CTRL_BUSY; + } + + port->data = value; +} + +inline uint8_t spi_recv_byte(struct TF53xSDRegs *port) +{ + uint8_t busy = 0; + + while (busy == 0) { + busy = port->ctrl & TF53x_CTRL_BUSY; + } + + return port->data; +} + +static void spi_cs_unassert(struct TF53xSDRegs *port) +{ + uint8_t current = port->ctrl; + port->ctrl = current | TF53x_CTRL_CS0 | \ + TF53x_CTRL_CS1 | TF53x_CTRL_CS2 | TF53x_CTRL_BUSY; +} + +static void spi_cs_assert(struct TF53xSDRegs *port) +{ + uint8_t current = port->ctrl; + port->ctrl = current & (~TF53x_CTRL_CS2); +} + +static int tf53x_spi_shutdown(void *data) +{ + return 0; +} + +static int tf53x_spi_send_command(const struct flashctx *flash, + unsigned int writecnt, + unsigned int readcnt, + const unsigned char *txbuf, + unsigned char *rxbuf) +{ + struct TF53xSDRegs *port = cd->cd_BoardAddr; + + spi_cs_assert(port); + + for (unsigned int i = 0; i < writecnt; i++) { + spi_send_byte(port, txbuf[i]); + } + + /* read the dummy byte and make sure + * the compiler doesnt optimize it away */ + uint8_t volatile dummy = spi_recv_byte(port); + dummy; + + for (unsigned int i = 0; i < readcnt; i++) { + rxbuf[i] = spi_recv_byte(port); + } + + spi_cs_unassert(port); + + return 0; +} + +static const struct spi_master spi_master_tf53x = { + .features = SPI_MASTER_4BA, + .max_data_read = 256, + .max_data_write = 256, + .command = tf53x_spi_send_command, + .multicommand = default_spi_send_multicommand, + .read = default_spi_read, + .write_256 = default_spi_write_256, + .write_aai = default_spi_write_aai, +}; + +int tf53x_spi_init(void) +{ + struct Library *ExpansionBase = NULL; + + if ((ExpansionBase = (struct Library *) + OpenLibrary((unsigned char *)"expansion.library", 0L)) == NULL) { + return 0; + } + + if (cd = (struct ConfigDev *) FindConfigDev(cd, 0x13D8, 0x81)) { + msg_cinfo("\nTF530 SPI found in autoconfig chain.\n"); + CloseLibrary(ExpansionBase); + } else { + msg_perr("\nTF530 SPI not found in autoconfig chain.\n"); + CloseLibrary(ExpansionBase); + return -1; + } + + if (register_shutdown(tf53x_spi_shutdown, NULL)) + return 1; + + register_spi_master(&spi_master_tf53x, NULL); + + return 0; +} + +#endif // CONFIG_TF530_SPI == 1