summaryrefslogtreecommitdiffstats
path: root/rayer_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'rayer_spi.c')
-rw-r--r--rayer_spi.c302
1 files changed, 182 insertions, 120 deletions
diff --git a/rayer_spi.c b/rayer_spi.c
index 8e869e66d..27caf2be1 100644
--- a/rayer_spi.c
+++ b/rayer_spi.c
@@ -22,14 +22,13 @@
* most OS parport drivers will perform many unnecessary accesses although
* this driver just treats the parallel port as a GPIO set.
*/
-#if defined(__i386__) || defined(__x86_64__)
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include "flash.h"
#include "programmer.h"
-#include "hwaccess.h"
+#include "hwaccess_x86_io.h"
/* We have two sets of pins, out and in. The numbers for both sets are
* independent and are bitshift values, not real pin numbers.
@@ -48,10 +47,18 @@ struct rayer_pinout {
uint8_t sck_bit;
uint8_t mosi_bit;
uint8_t miso_bit;
- void (*preinit)(const void *);
+ void (*preinit)(void *);
int (*shutdown)(void *);
};
+struct rayer_spi_data {
+ uint16_t lpt_iobase;
+ /* Cached value of last byte sent. */
+ uint8_t lpt_outbyte;
+
+ const struct rayer_pinout *pinout;
+};
+
static const struct rayer_pinout rayer_spipgm = {
.cs_bit = 5,
.sck_bit = 6,
@@ -59,8 +66,28 @@ static const struct rayer_pinout rayer_spipgm = {
.miso_bit = 6,
};
-static void dlc5_preinit(const void *);
-static int dlc5_shutdown(void *);
+static void dlc5_preinit(void *spi_data)
+{
+ struct rayer_spi_data *data = spi_data;
+
+ msg_pdbg("dlc5_preinit\n");
+ /* Assert pin 6 to receive MISO. */
+ data->lpt_outbyte |= (1<<4);
+ OUTB(data->lpt_outbyte, data->lpt_iobase);
+}
+
+static int dlc5_shutdown(void *spi_data)
+{
+ struct rayer_spi_data *data = spi_data;
+
+ msg_pdbg("dlc5_shutdown\n");
+ /* De-assert pin 6 to force MISO low. */
+ data->lpt_outbyte &= ~(1<<4);
+ OUTB(data->lpt_outbyte, data->lpt_iobase);
+
+ free(data);
+ return 0;
+}
static const struct rayer_pinout xilinx_dlc5 = {
.cs_bit = 2,
@@ -71,8 +98,26 @@ static const struct rayer_pinout xilinx_dlc5 = {
.shutdown = dlc5_shutdown,
};
-static void byteblaster_preinit(const void *);
-static int byteblaster_shutdown(void *);
+static void byteblaster_preinit(void *spi_data)
+{
+ struct rayer_spi_data *data = spi_data;
+
+ msg_pdbg("byteblaster_preinit\n");
+ /* Assert #EN signal. */
+ OUTB(2, data->lpt_iobase + 2 );
+}
+
+static int byteblaster_shutdown(void *spi_data)
+{
+ struct rayer_spi_data *data = spi_data;
+
+ msg_pdbg("byteblaster_shutdown\n");
+ /* De-Assert #EN signal. */
+ OUTB(0, data->lpt_iobase + 2 );
+
+ free(data);
+ return 0;
+}
static const struct rayer_pinout altera_byteblastermv = {
.cs_bit = 1,
@@ -83,8 +128,28 @@ static const struct rayer_pinout altera_byteblastermv = {
.shutdown = byteblaster_shutdown,
};
-static void stk200_preinit(const void *);
-static int stk200_shutdown(void *);
+static void stk200_preinit(void *spi_data)
+{
+ struct rayer_spi_data *data = spi_data;
+
+ msg_pdbg("stk200_init\n");
+ /* Assert #EN signals, set LED signal. */
+ data->lpt_outbyte = (1 << 6) ;
+ OUTB(data->lpt_outbyte, data->lpt_iobase);
+}
+
+static int stk200_shutdown(void *spi_data)
+{
+ struct rayer_spi_data *data = spi_data;
+
+ msg_pdbg("stk200_shutdown\n");
+ /* Assert #EN signals, clear LED signal. */
+ data->lpt_outbyte = (1 << 2) | (1 << 3);
+ OUTB(data->lpt_outbyte, data->lpt_iobase);
+
+ free(data);
+ return 0;
+}
static const struct rayer_pinout atmel_stk200 = {
.cs_bit = 7,
@@ -109,72 +174,99 @@ static const struct rayer_pinout spi_tt = {
.miso_bit = 7,
};
-static const struct rayer_programmer rayer_spi_types[] = {
- {"rayer", NT, "RayeR SPIPGM", &rayer_spipgm},
- {"xilinx", NT, "Xilinx Parallel Cable III (DLC 5)", &xilinx_dlc5},
- {"byteblastermv", OK, "Altera ByteBlasterMV", &altera_byteblastermv},
- {"stk200", NT, "Atmel STK200/300 adapter", &atmel_stk200},
- {"wiggler", OK, "Wiggler LPT", &wiggler_lpt},
- {"spi_tt", NT, "SPI Tiny Tools (SPI_TT LPT)", &spi_tt},
- {0},
-};
-
-static const struct rayer_pinout *pinout = NULL;
-
-static uint16_t lpt_iobase;
-
-/* Cached value of last byte sent. */
-static uint8_t lpt_outbyte;
-
-static void rayer_bitbang_set_cs(int val)
+static void rayer_bitbang_set_cs(int val, void *spi_data)
{
- lpt_outbyte &= ~(1 << pinout->cs_bit);
- lpt_outbyte |= (val << pinout->cs_bit);
- OUTB(lpt_outbyte, lpt_iobase);
+ struct rayer_spi_data *data = spi_data;
+
+ data->lpt_outbyte &= ~(1 << data->pinout->cs_bit);
+ data->lpt_outbyte |= (val << data->pinout->cs_bit);
+ OUTB(data->lpt_outbyte, data->lpt_iobase);
}
-static void rayer_bitbang_set_sck(int val)
+static void rayer_bitbang_set_sck(int val, void *spi_data)
{
- lpt_outbyte &= ~(1 << pinout->sck_bit);
- lpt_outbyte |= (val << pinout->sck_bit);
- OUTB(lpt_outbyte, lpt_iobase);
+ struct rayer_spi_data *data = spi_data;
+
+ data->lpt_outbyte &= ~(1 << data->pinout->sck_bit);
+ data->lpt_outbyte |= (val << data->pinout->sck_bit);
+ OUTB(data->lpt_outbyte, data->lpt_iobase);
}
-static void rayer_bitbang_set_mosi(int val)
+static void rayer_bitbang_set_mosi(int val, void *spi_data)
{
- lpt_outbyte &= ~(1 << pinout->mosi_bit);
- lpt_outbyte |= (val << pinout->mosi_bit);
- OUTB(lpt_outbyte, lpt_iobase);
+ struct rayer_spi_data *data = spi_data;
+
+ data->lpt_outbyte &= ~(1 << data->pinout->mosi_bit);
+ data->lpt_outbyte |= (val << data->pinout->mosi_bit);
+ OUTB(data->lpt_outbyte, data->lpt_iobase);
}
-static int rayer_bitbang_get_miso(void)
+static int rayer_bitbang_get_miso(void *spi_data)
{
+ struct rayer_spi_data *data = spi_data;
uint8_t tmp;
- tmp = INB(lpt_iobase + 1) ^ 0x80; // bit.7 inverted
- tmp = (tmp >> pinout->miso_bit) & 0x1;
+ tmp = INB(data->lpt_iobase + 1) ^ 0x80; // bit.7 inverted
+ tmp = (tmp >> data->pinout->miso_bit) & 0x1;
return tmp;
}
+static int rayer_shutdown(void *spi_data)
+{
+ free(spi_data);
+ return 0;
+}
+
static const struct bitbang_spi_master bitbang_spi_master_rayer = {
- .set_cs = rayer_bitbang_set_cs,
- .set_sck = rayer_bitbang_set_sck,
- .set_mosi = rayer_bitbang_set_mosi,
- .get_miso = rayer_bitbang_get_miso,
- .half_period = 0,
+ .set_cs = rayer_bitbang_set_cs,
+ .set_sck = rayer_bitbang_set_sck,
+ .set_mosi = rayer_bitbang_set_mosi,
+ .get_miso = rayer_bitbang_get_miso,
+ .half_period = 0,
};
-int rayer_spi_init(void)
+static const struct rayer_programmer *find_progtype(const char *prog_type)
{
+ static const struct rayer_programmer rayer_spi_types[] = {
+ {"rayer", NT, "RayeR SPIPGM", &rayer_spipgm},
+ {"xilinx", NT, "Xilinx Parallel Cable III (DLC 5)", &xilinx_dlc5},
+ {"byteblastermv", OK, "Altera ByteBlasterMV", &altera_byteblastermv},
+ {"stk200", NT, "Atmel STK200/300 adapter", &atmel_stk200},
+ {"wiggler", OK, "Wiggler LPT", &wiggler_lpt},
+ {"spi_tt", NT, "SPI Tiny Tools (SPI_TT LPT)", &spi_tt},
+ {0},
+ };
+ if (!prog_type)
+ return &rayer_spi_types[0];
+
const struct rayer_programmer *prog = rayer_spi_types;
- char *arg = NULL;
+ for (; prog->type != NULL; prog++) {
+ if (strcasecmp(prog_type, prog->type) == 0) {
+ break;
+ }
+ }
+
+ if (!prog->type) {
+ msg_perr("Error: Invalid device type specified.\n");
+ return NULL;
+ }
+
+ return prog;
+}
+
+static int get_params(const struct programmer_cfg *cfg, uint16_t *lpt_iobase,
+ const struct rayer_programmer **prog)
+{
+ /* Pick a default value for the I/O base. */
+ *lpt_iobase = 0x378;
+ /* no programmer type specified. */
+ *prog = NULL;
/* Non-default port requested? */
- arg = extract_programmer_param("iobase");
+ char *arg = extract_programmer_param_str(cfg, "iobase");
if (arg) {
char *endptr = NULL;
- unsigned long tmp;
- tmp = strtoul(arg, &endptr, 0);
+ unsigned long tmp = strtoul(arg, &endptr, 0);
/* Port 0, port >0x10000, unaligned ports and garbage strings
* are rejected.
*/
@@ -188,98 +280,68 @@ int rayer_spi_init(void)
"given was invalid.\nIt must be a multiple of "
"0x4 and lie between 0x100 and 0xfffc.\n");
free(arg);
- return 1;
+ return -1;
} else {
- lpt_iobase = (uint16_t)tmp;
+ *lpt_iobase = (uint16_t)tmp;
msg_pinfo("Non-default I/O base requested. This will "
"not change the hardware settings.\n");
}
- } else {
- /* Pick a default value for the I/O base. */
- lpt_iobase = 0x378;
+ free(arg);
}
+
+ arg = extract_programmer_param_str(cfg, "type");
+ *prog = find_progtype(arg);
free(arg);
+ return *prog ? 0 : -1;
+}
+
+static int rayer_spi_init(const struct programmer_cfg *cfg)
+{
+ const struct rayer_programmer *prog;
+ struct rayer_pinout *pinout = NULL;
+ uint16_t lpt_iobase;
+
+ if (get_params(cfg, &lpt_iobase, &prog) < 0)
+ return 1;
+
msg_pdbg("Using address 0x%x as I/O base for parallel port access.\n",
lpt_iobase);
- arg = extract_programmer_param("type");
- if (arg) {
- for (; prog->type != NULL; prog++) {
- if (strcasecmp(arg, prog->type) == 0) {
- break;
- }
- }
- if (prog->type == NULL) {
- msg_perr("Error: Invalid device type specified.\n");
- free(arg);
- return 1;
- }
- free(arg);
- }
msg_pinfo("Using %s pinout.\n", prog->description);
pinout = (struct rayer_pinout *)prog->dev_data;
if (rget_io_perms())
return 1;
+ struct rayer_spi_data *data = calloc(1, sizeof(*data));
+ if (!data) {
+ msg_perr("Unable to allocate space for SPI master data\n");
+ return 1;
+ }
+ data->pinout = pinout;
+ data->lpt_iobase = lpt_iobase;
/* Get the initial value before writing to any line. */
- lpt_outbyte = INB(lpt_iobase);
+ data->lpt_outbyte = INB(lpt_iobase);
if (pinout->shutdown)
- register_shutdown(pinout->shutdown, (void*)pinout);
+ register_shutdown(pinout->shutdown, data);
+ else
+ register_shutdown(rayer_shutdown, data);
+
if (pinout->preinit)
- pinout->preinit(pinout);
+ pinout->preinit(data);
- if (register_spi_bitbang_master(&bitbang_spi_master_rayer))
+ if (register_spi_bitbang_master(&bitbang_spi_master_rayer, data))
return 1;
return 0;
}
-static void byteblaster_preinit(const void *data){
- msg_pdbg("byteblaster_preinit\n");
- /* Assert #EN signal. */
- OUTB(2, lpt_iobase + 2 );
-}
-
-static int byteblaster_shutdown(void *data){
- msg_pdbg("byteblaster_shutdown\n");
- /* De-Assert #EN signal. */
- OUTB(0, lpt_iobase + 2 );
- return 0;
-}
-
-static void stk200_preinit(const void *data) {
- msg_pdbg("stk200_init\n");
- /* Assert #EN signals, set LED signal. */
- lpt_outbyte = (1 << 6) ;
- OUTB(lpt_outbyte, lpt_iobase);
-}
-
-static int stk200_shutdown(void *data) {
- msg_pdbg("stk200_shutdown\n");
- /* Assert #EN signals, clear LED signal. */
- lpt_outbyte = (1 << 2) | (1 << 3);
- OUTB(lpt_outbyte, lpt_iobase);
- return 0;
-}
-
-static void dlc5_preinit(const void *data) {
- msg_pdbg("dlc5_preinit\n");
- /* Assert pin 6 to receive MISO. */
- lpt_outbyte |= (1<<4);
- OUTB(lpt_outbyte, lpt_iobase);
-}
-
-static int dlc5_shutdown(void *data) {
- msg_pdbg("dlc5_shutdown\n");
- /* De-assert pin 6 to force MISO low. */
- lpt_outbyte &= ~(1<<4);
- OUTB(lpt_outbyte, lpt_iobase);
- return 0;
-}
-
-#else
-#error PCI port I/O access is not supported on this architecture yet.
-#endif
+const struct programmer_entry programmer_rayer_spi = {
+ .name = "rayer_spi",
+ .type = OTHER,
+ /* FIXME */
+ .devs.note = "RayeR parallel port programmer\n",
+ .init = rayer_spi_init,
+};