Hi List, this patch adds support for the Linux SPI subsystem. See http://www.kernel.org/doc/Documentation/spi/spidev for a short introduction.
Usage is as follows: flashrom -p linux_spi:dev=/dev/spidevX.Y where X is the bus number, and Y device. It accepts an optional parameter 'speed' which allows to set the SPI CLK speed in KHz. I'm using a AVR32 Board (http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4102) to program my ThinkPad X60, but it should work on every Linux system. Signed-off-by: Sven Schnelle <[email protected]>
Index: Makefile =================================================================== --- Makefile (revision 1261) +++ Makefile (working copy) @@ -152,6 +152,8 @@ # Always enable Bus Pirate SPI for now. CONFIG_BUSPIRATE_SPI ?= yes +CONFIG_LINUX_SPI ?= yes + # Disable Dediprog SF100 until support is complete and tested. CONFIG_DEDIPROG ?= no @@ -280,6 +282,11 @@ NEED_SERIAL := yes endif +ifeq ($(CONFIG_LINUX_SPI), yes) +FEATURE_CFLAGS += -D'CONFIG_LINUX_SPI=1' +PROGRAMMER_OBJS += linux_spi.o +endif + ifeq ($(CONFIG_DEDIPROG), yes) FEATURE_CFLAGS += -D'CONFIG_DEDIPROG=1' FEATURE_LIBS += -lusb Index: linux_spi.c =================================================================== --- linux_spi.c (revision 0) +++ linux_spi.c (revision 0) @@ -0,0 +1,111 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2011 Sven Schnelle <[email protected]> + * + * 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 + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/fcntl.h> +#include <errno.h> +#include <ctype.h> +#include <unistd.h> +#include "flash.h" +#include "chipdrivers.h" +#include "programmer.h" +#include "spi.h" + +#include <linux/spi/spidev.h> +#include <sys/ioctl.h> + +static int fd = -1; + +int linux_spi_init(void) +{ + char *p, *endp, *dev; + int speed = 0; + + dev = extract_programmer_param("dev"); + if (!dev || !strlen(dev)) { + msg_perr("No spi device given. Use flashrom -p " + "linux_spi:dev=/dev/spidevX.Y\n"); + return 1; + } + + p = extract_programmer_param("speed"); + if (p && strlen(p)) { + speed = strtoul(p, &endp, 10) * 1024; + if (p == endp) { + msg_perr("%s: invalid clock: %s\n", __func__, p); + return 1; + } + } + + if ((fd = open(dev, O_RDWR)) == -1) { + msg_perr("%s: failed to open %s: %s\n", __func__, + dev, strerror(errno)); + return 1; + } + + if (speed > 0 && ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) == -1) { + msg_perr("%s: failed to set speed %dHz: %s\n", + __func__, speed, strerror(errno)); + close(fd); + return 1; + } + + buses_supported = CHIP_BUSTYPE_SPI; + spi_controller = SPI_CONTROLLER_LINUX; + return 0; +} + +int linux_spi_shutdown(void) +{ + if (fd != -1) { + close(fd); + fd = -1; + } + return 0; +} + +int linux_spi_send_command(unsigned int writecnt, unsigned int readcnt, + const unsigned char *txbuf, unsigned char *rxbuf) +{ + struct spi_ioc_transfer msg[2] = { + { .tx_buf = (unsigned long)txbuf, .len = writecnt }, + { .rx_buf = (unsigned long)rxbuf, .len = readcnt } + }; + + if (fd == -1) + return -1; + + if (ioctl(fd, SPI_IOC_MESSAGE(2), msg) == -1) { + msg_cerr("%s: ioctl: %s\n", __func__, strerror(errno)); + return -1; + } + return 0; +} + +int linux_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) +{ + return spi_read_chunked(flash, buf, start, len, 12); +} + +int linux_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int len) +{ + return spi_write_chunked(flash, buf, start, len, 12); +} Index: spi.c =================================================================== --- spi.c (revision 1261) +++ spi.c (working copy) @@ -155,6 +155,14 @@ }, #endif +#if CONFIG_LINUX_SPI == 1 + { /* SPI_CONTROLLER_LINUX */ + .command = linux_spi_send_command, + .multicommand = default_spi_send_multicommand, + .read = linux_spi_read, + .write_256 = linux_spi_write_256, + }, +#endif {}, /* This entry corresponds to SPI_CONTROLLER_INVALID. */ }; Index: flashrom.c =================================================================== --- flashrom.c (revision 1261) +++ flashrom.c (working copy) @@ -102,6 +102,9 @@ #if CONFIG_SATAMV == 1 PROGRAMMER_SATAMV #endif +#if CONFIG_LINUX_SPI == 1 + PROGRAMMER_LINUX_SPI +#endif ; #endif @@ -483,6 +486,24 @@ }, #endif +#if CONFIG_LINUX_SPI == 1 + { + .name = "linux_spi", + .init = linux_spi_init, + .shutdown = linux_spi_shutdown, + .map_flash_region = fallback_map, + .unmap_flash_region = fallback_unmap, + .chip_readb = noop_chip_readb, + .chip_readw = fallback_chip_readw, + .chip_readl = fallback_chip_readl, + .chip_readn = fallback_chip_readn, + .chip_writeb = noop_chip_writeb, + .chip_writew = fallback_chip_writew, + .chip_writel = fallback_chip_writel, + .chip_writen = fallback_chip_writen, + .delay = internal_delay, + }, +#endif {}, /* This entry corresponds to PROGRAMMER_INVALID. */ }; Index: programmer.h =================================================================== --- programmer.h (revision 1261) +++ programmer.h (working copy) @@ -82,6 +82,9 @@ #if CONFIG_SATAMV == 1 PROGRAMMER_SATAMV, #endif +#if CONFIG_LINUX_SPI == 1 + PROGRAMMER_LINUX_SPI, +#endif PROGRAMMER_INVALID /* This must always be the last entry. */ }; @@ -492,6 +495,14 @@ int buspirate_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); int buspirate_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int len); +/* linux_spi.c */ +int linux_spi_init(void); +int linux_spi_shutdown(void); +int linux_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr); +int linux_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len); +int linux_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int len); + + /* dediprog.c */ int dediprog_init(void); int dediprog_shutdown(void); @@ -551,6 +562,9 @@ #if CONFIG_OGP_SPI == 1 SPI_CONTROLLER_OGP, #endif +#if CONFIG_LINUX_SPI == 1 + SPI_CONTROLLER_LINUX, +#endif SPI_CONTROLLER_INVALID /* This must always be the last entry. */ }; extern const int spi_programmer_count;
_______________________________________________ flashrom mailing list [email protected] http://www.flashrom.org/mailman/listinfo/flashrom
