Commit da7c545b authored by Virgil-Adrian Teaca's avatar Virgil-Adrian Teaca Committed by Michael Karcher
Browse files

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: default avatarVirgil-Adrian Teaca <darkstarlinux@gmail.com>
Acked-by: default avatarMichael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
parent 2abab94c
......@@ -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
......
......@@ -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",
......
/*
* 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;
}
......@@ -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);
......
......@@ -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__ */
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment