mirror of
https://review.coreboot.org/flashrom.git
synced 2025-07-01 06:01:16 +02:00
Add serial port bitbanging code
This adds the pony_spi driver which supports the SI_Prog adapter, which is commonly used for SPI chips with PonyProg 2000, and a custom adapter called "SERBANG" which differs in the logic of two pins. Corresponding to flashrom svn r1525. Signed-off-by: Virgil-Adrian Teaca <darkstarlinux@gmail.com> Acked-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
This commit is contained in:

committed by
Michael Karcher

parent
2abab94c18
commit
da7c545b06
13
Makefile
13
Makefile
@ -292,6 +292,9 @@ CONFIG_SERPROG ?= yes
|
||||
# RayeR SPIPGM hardware support
|
||||
CONFIG_RAYER_SPI ?= yes
|
||||
|
||||
# PonyProg2000 SPI hardware support
|
||||
CONFIG_PONY_SPI ?= yes
|
||||
|
||||
# Always enable 3Com NICs for now.
|
||||
CONFIG_NIC3COM ?= yes
|
||||
|
||||
@ -348,6 +351,9 @@ CONFIG_PRINT_WIKI ?= no
|
||||
ifeq ($(CONFIG_RAYER_SPI), yes)
|
||||
override CONFIG_BITBANG_SPI = yes
|
||||
else
|
||||
ifeq ($(CONFIG_PONY_SPI), yes)
|
||||
override CONFIG_BITBANG_SPI = yes
|
||||
else
|
||||
ifeq ($(CONFIG_INTERNAL), yes)
|
||||
override CONFIG_BITBANG_SPI = yes
|
||||
else
|
||||
@ -362,6 +368,7 @@ endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERNAL), yes)
|
||||
FEATURE_CFLAGS += -D'CONFIG_INTERNAL=1'
|
||||
@ -388,6 +395,12 @@ PROGRAMMER_OBJS += rayer_spi.o
|
||||
NEED_PCI := yes
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PONY_SPI), yes)
|
||||
FEATURE_CFLAGS += -D'CONFIG_PONY_SPI=1'
|
||||
PROGRAMMER_OBJS += pony_spi.o
|
||||
NEED_SERIAL := yes
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BITBANG_SPI), yes)
|
||||
FEATURE_CFLAGS += -D'CONFIG_BITBANG_SPI=1'
|
||||
PROGRAMMER_OBJS += bitbang_spi.o
|
||||
|
10
flashrom.c
10
flashrom.c
@ -201,6 +201,16 @@ const struct programmer_entry programmer_table[] = {
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CONFIG_PONY_SPI == 1
|
||||
{
|
||||
.name = "pony_spi",
|
||||
.init = pony_spi_init,
|
||||
.map_flash_region = fallback_map,
|
||||
.unmap_flash_region = fallback_unmap,
|
||||
.delay = internal_delay,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if CONFIG_NICINTEL == 1
|
||||
{
|
||||
.name = "nicintel",
|
||||
|
160
pony_spi.c
Normal file
160
pony_spi.c
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* This file is part of the flashrom project.
|
||||
*
|
||||
* Copyright (C) 2012 Virgil-Adrian Teaca
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Driver for the SI-Prog like hardware by Lancos.com.
|
||||
* See http://www.lancos.com/siprogsch.html for schematics and instructions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "flash.h"
|
||||
#include "programmer.h"
|
||||
|
||||
/* We have:
|
||||
|
||||
MOSI -----> DTR
|
||||
MISO -----> CTS
|
||||
SCK --+--> RTS
|
||||
+--> DSR
|
||||
CS# -----> TXD
|
||||
|
||||
*/
|
||||
|
||||
enum pony_type {
|
||||
TYPE_SI_PROG,
|
||||
TYPE_SERBANG,
|
||||
};
|
||||
|
||||
/* The hardware programmer used. */
|
||||
static enum pony_type pony_type = TYPE_SI_PROG;
|
||||
|
||||
static void pony_bitbang_set_cs(int val)
|
||||
{
|
||||
if (pony_type == TYPE_SI_PROG)
|
||||
{
|
||||
/* CS# is negated by the SI-Prog programmer. */
|
||||
val ^= 1;
|
||||
}
|
||||
sp_set_pin(PIN_TXD, val);
|
||||
}
|
||||
|
||||
static void pony_bitbang_set_sck(int val)
|
||||
{
|
||||
sp_set_pin(PIN_RTS, val);
|
||||
}
|
||||
|
||||
static void pony_bitbang_set_mosi(int val)
|
||||
{
|
||||
sp_set_pin(PIN_DTR, val);
|
||||
}
|
||||
|
||||
static int pony_bitbang_get_miso(void)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
tmp = sp_get_pin(PIN_CTS);
|
||||
|
||||
if (pony_type == TYPE_SERBANG)
|
||||
{
|
||||
/* MISO is negated by the SERBANG programmer. */
|
||||
tmp ^= 1;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static const struct bitbang_spi_master bitbang_spi_master_pony = {
|
||||
.type = BITBANG_SPI_MASTER_PONY,
|
||||
.set_cs = pony_bitbang_set_cs,
|
||||
.set_sck = pony_bitbang_set_sck,
|
||||
.set_mosi = pony_bitbang_set_mosi,
|
||||
.get_miso = pony_bitbang_get_miso,
|
||||
.half_period = 0,
|
||||
};
|
||||
|
||||
int pony_spi_init(void)
|
||||
{
|
||||
char *arg = NULL;
|
||||
int i, data_in, data_out, have_device = 0;
|
||||
int have_prog = 1;
|
||||
|
||||
/* The parameter is on format "dev=/dev/device,type=serbang" */
|
||||
arg = extract_programmer_param("dev");
|
||||
|
||||
if (arg && strlen(arg)) {
|
||||
sp_fd = sp_openserport( arg, 9600 );
|
||||
have_device++;
|
||||
}
|
||||
free(arg);
|
||||
|
||||
if (!have_device) {
|
||||
msg_perr("Error: No valid device specified.\n"
|
||||
"Use flashrom -p pony_spi:dev=/dev/device\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* Register the shutdown callback. */
|
||||
if (register_shutdown(serialport_shutdown, NULL)) {
|
||||
return 1;
|
||||
}
|
||||
arg = extract_programmer_param("type");
|
||||
|
||||
if (arg) {
|
||||
if (!strcasecmp( arg, "serbang")) {
|
||||
pony_type = TYPE_SERBANG;
|
||||
} else if (!strcasecmp( arg, "si_prog") ) {
|
||||
pony_type = TYPE_SI_PROG;
|
||||
} else {
|
||||
msg_perr("Error: Invalid programmer type specified.\n");
|
||||
free(arg);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
free(arg);
|
||||
|
||||
msg_pdbg("Using the %s programmer.\n", ((pony_type == TYPE_SI_PROG ) ? "SI-Prog" : "SERBANG"));
|
||||
/*
|
||||
* Detect if there is a SI-Prog compatible programmer connected.
|
||||
*/
|
||||
pony_bitbang_set_cs(1);
|
||||
pony_bitbang_set_mosi(1);
|
||||
|
||||
/* We toggle SCK while we keep MOSI and CS# on. */
|
||||
for (i = 1; i <= 10; ++i) {
|
||||
data_out = i & 1;
|
||||
sp_set_pin(PIN_RTS, data_out);
|
||||
programmer_delay( 1000 );
|
||||
data_in = sp_get_pin(PIN_DSR);
|
||||
|
||||
if (data_out != data_in) {
|
||||
have_prog = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_prog) {
|
||||
msg_perr( "No SI-Prog compatible hardware detected.\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bitbang_spi_init(&bitbang_spi_master_pony)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
6
print.c
6
print.c
@ -507,6 +507,12 @@ void print_supported(void)
|
||||
/* FIXME */
|
||||
msg_ginfo("RayeR parallel port programmer\n");
|
||||
#endif
|
||||
#if CONFIG_PONY_SPI == 1
|
||||
msg_ginfo("\nSupported devices for the %s programmer:\n",
|
||||
programmer_table[PROGRAMMER_PONY_SPI].name);
|
||||
/* FIXME */
|
||||
msg_ginfo("SI-Prog and SERBANG serial port programmer\n");
|
||||
#endif
|
||||
#if CONFIG_NICINTEL == 1
|
||||
msg_ginfo("\nSupported devices for the %s programmer:\n",
|
||||
programmer_table[PROGRAMMER_NICINTEL].name);
|
||||
|
40
programmer.h
40
programmer.h
@ -69,6 +69,9 @@ enum programmer {
|
||||
#if CONFIG_RAYER_SPI == 1
|
||||
PROGRAMMER_RAYER_SPI,
|
||||
#endif
|
||||
#if CONFIG_PONY_SPI == 1
|
||||
PROGRAMMER_PONY_SPI,
|
||||
#endif
|
||||
#if CONFIG_NICINTEL == 1
|
||||
PROGRAMMER_NICINTEL,
|
||||
#endif
|
||||
@ -110,6 +113,9 @@ enum bitbang_spi_master_type {
|
||||
#if CONFIG_RAYER_SPI == 1
|
||||
BITBANG_SPI_MASTER_RAYER,
|
||||
#endif
|
||||
#if CONFIG_PONY_SPI == 1
|
||||
BITBANG_SPI_MASTER_PONY,
|
||||
#endif
|
||||
#if CONFIG_NICINTEL_SPI == 1
|
||||
BITBANG_SPI_MASTER_NICINTEL,
|
||||
#endif
|
||||
@ -430,6 +436,11 @@ void print_supported_usbdevs(const struct usbdev_status *devs);
|
||||
int rayer_spi_init(void);
|
||||
#endif
|
||||
|
||||
/* pony_spi.c */
|
||||
#if CONFIG_PONY_SPI == 1
|
||||
int pony_spi_init(void);
|
||||
#endif
|
||||
|
||||
/* bitbang_spi.c */
|
||||
int bitbang_spi_init(const struct bitbang_spi_master *master);
|
||||
|
||||
@ -492,7 +503,7 @@ enum spi_controller {
|
||||
#if CONFIG_DEDIPROG == 1
|
||||
SPI_CONTROLLER_DEDIPROG,
|
||||
#endif
|
||||
#if CONFIG_OGP_SPI == 1 || CONFIG_NICINTEL_SPI == 1 || CONFIG_RAYER_SPI == 1 || (CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__)))
|
||||
#if CONFIG_OGP_SPI == 1 || CONFIG_NICINTEL_SPI == 1 || CONFIG_RAYER_SPI == 1 || CONFIG_PONY_SPI == 1 || (CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__)))
|
||||
SPI_CONTROLLER_BITBANG,
|
||||
#endif
|
||||
#if CONFIG_LINUX_SPI == 1
|
||||
@ -636,4 +647,31 @@ int serialport_shutdown(void *data);
|
||||
int serialport_write(unsigned char *buf, unsigned int writecnt);
|
||||
int serialport_read(unsigned char *buf, unsigned int readcnt);
|
||||
|
||||
/* Serial port/pin mapping:
|
||||
|
||||
1 CD <-
|
||||
2 RXD <-
|
||||
3 TXD ->
|
||||
4 DTR ->
|
||||
5 GND --
|
||||
6 DSR <-
|
||||
7 RTS ->
|
||||
8 CTS <-
|
||||
9 RI <-
|
||||
*/
|
||||
enum SP_PIN {
|
||||
PIN_CD = 1,
|
||||
PIN_RXD,
|
||||
PIN_TXD,
|
||||
PIN_DTR,
|
||||
PIN_GND,
|
||||
PIN_DSR,
|
||||
PIN_RTS,
|
||||
PIN_CTS,
|
||||
PIN_RI,
|
||||
};
|
||||
|
||||
void sp_set_pin(enum SP_PIN pin, int val);
|
||||
int sp_get_pin(enum SP_PIN pin);
|
||||
|
||||
#endif /* !__PROGRAMMER_H__ */
|
||||
|
55
serial.c
55
serial.c
@ -32,6 +32,9 @@
|
||||
#include <conio.h>
|
||||
#else
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#include "flash.h"
|
||||
#include "programmer.h"
|
||||
@ -172,6 +175,58 @@ fdtype sp_openserport(char *dev, unsigned int baud)
|
||||
#endif
|
||||
}
|
||||
|
||||
void sp_set_pin(enum SP_PIN pin, int val) {
|
||||
#ifdef _WIN32
|
||||
DWORD ctl;
|
||||
|
||||
if(pin == PIN_TXD) {
|
||||
ctl = val ? SETBREAK: CLRBREAK;
|
||||
}
|
||||
else if(pin == PIN_DTR) {
|
||||
ctl = val ? SETDTR: CLRDTR;
|
||||
}
|
||||
else {
|
||||
ctl = val ? SETRTS: CLRRTS;
|
||||
}
|
||||
EscapeCommFunction(sp_fd, ctl);
|
||||
#else
|
||||
int ctl, s;
|
||||
|
||||
if(pin == PIN_TXD) {
|
||||
ioctl(sp_fd, val ? TIOCSBRK : TIOCCBRK, 0);
|
||||
}
|
||||
else {
|
||||
s = (pin == PIN_DTR) ? TIOCM_DTR : TIOCM_RTS;
|
||||
ioctl(sp_fd, TIOCMGET, &ctl);
|
||||
|
||||
if (val) {
|
||||
ctl |= s;
|
||||
}
|
||||
else {
|
||||
ctl &= ~s;
|
||||
}
|
||||
ioctl(sp_fd, TIOCMSET, &ctl);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int sp_get_pin(enum SP_PIN pin) {
|
||||
int s;
|
||||
#ifdef _WIN32
|
||||
DWORD ctl;
|
||||
|
||||
s = (pin == PIN_CTS) ? MS_CTS_ON : MS_DSR_ON;
|
||||
GetCommModemStatus(sp_fd, &ctl);
|
||||
#else
|
||||
int ctl;
|
||||
s = (pin == PIN_CTS) ? TIOCM_CTS : TIOCM_DSR;
|
||||
ioctl(sp_fd, TIOCMGET, &ctl);
|
||||
#endif
|
||||
|
||||
return ((ctl & s) ? 1 : 0);
|
||||
|
||||
}
|
||||
|
||||
void sp_flush_incoming(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
Reference in New Issue
Block a user