123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- /*
- * This file is part of the flashrom project.
- *
- * Copyright (C) 2009,2010 Carl-Daniel Hailfinger
- *
- * 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 various LPT adapters.
- *
- * This driver uses non-portable direct I/O port accesses which won't work on
- * any non-x86 platform, and even on x86 there is a high chance there will be
- * collisions with any loaded parallel port drivers.
- * The big advantage of direct port I/O is OS independence and speed because
- * 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"
- /* We have two sets of pins, out and in. The numbers for both sets are
- * independent and are bitshift values, not real pin numbers.
- * Default settings are for the RayeR hardware.
- */
- struct rayer_programmer {
- const char *type;
- const enum test_state status;
- const char *description;
- const void *dev_data;
- };
- struct rayer_pinout {
- uint8_t cs_bit;
- uint8_t sck_bit;
- uint8_t mosi_bit;
- uint8_t miso_bit;
- void (*preinit)(const void *);
- int (*shutdown)(void *);
- };
- static const struct rayer_pinout rayer_spipgm = {
- .cs_bit = 5,
- .sck_bit = 6,
- .mosi_bit = 7,
- .miso_bit = 6,
- };
- static void dlc5_preinit(const void *);
- static int dlc5_shutdown(void *);
- static const struct rayer_pinout xilinx_dlc5 = {
- .cs_bit = 2,
- .sck_bit = 1,
- .mosi_bit = 0,
- .miso_bit = 4,
- .preinit = dlc5_preinit,
- .shutdown = dlc5_shutdown,
- };
- static void byteblaster_preinit(const void *);
- static int byteblaster_shutdown(void *);
- static const struct rayer_pinout altera_byteblastermv = {
- .cs_bit = 1,
- .sck_bit = 0,
- .mosi_bit = 6,
- .miso_bit = 7,
- .preinit = byteblaster_preinit,
- .shutdown = byteblaster_shutdown,
- };
- static void stk200_preinit(const void *);
- static int stk200_shutdown(void *);
- static const struct rayer_pinout atmel_stk200 = {
- .cs_bit = 7,
- .sck_bit = 4,
- .mosi_bit = 5,
- .miso_bit = 6,
- .preinit = stk200_preinit,
- .shutdown = stk200_shutdown,
- };
- static const struct rayer_pinout wiggler_lpt = {
- .cs_bit = 1,
- .sck_bit = 2,
- .mosi_bit = 3,
- .miso_bit = 7,
- };
- static const struct rayer_pinout spi_tt = {
- .cs_bit = 2,
- .sck_bit = 0,
- .mosi_bit = 4,
- .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)
- {
- lpt_outbyte &= ~(1 << pinout->cs_bit);
- lpt_outbyte |= (val << pinout->cs_bit);
- OUTB(lpt_outbyte, lpt_iobase);
- }
- static void rayer_bitbang_set_sck(int val)
- {
- lpt_outbyte &= ~(1 << pinout->sck_bit);
- lpt_outbyte |= (val << pinout->sck_bit);
- OUTB(lpt_outbyte, lpt_iobase);
- }
- static void rayer_bitbang_set_mosi(int val)
- {
- lpt_outbyte &= ~(1 << pinout->mosi_bit);
- lpt_outbyte |= (val << pinout->mosi_bit);
- OUTB(lpt_outbyte, lpt_iobase);
- }
- static int rayer_bitbang_get_miso(void)
- {
- uint8_t tmp;
- tmp = INB(lpt_iobase + 1) ^ 0x80; // bit.7 inverted
- tmp = (tmp >> pinout->miso_bit) & 0x1;
- return tmp;
- }
- static const struct bitbang_spi_master bitbang_spi_master_rayer = {
- .type = 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,
- };
- int rayer_spi_init(void)
- {
- const struct rayer_programmer *prog = rayer_spi_types;
- char *arg = NULL;
- /* Non-default port requested? */
- arg = extract_programmer_param("iobase");
- if (arg) {
- char *endptr = NULL;
- unsigned long tmp;
- tmp = strtoul(arg, &endptr, 0);
- /* Port 0, port >0x10000, unaligned ports and garbage strings
- * are rejected.
- */
- if (!tmp || (tmp >= 0x10000) || (tmp & 0x3) ||
- (*endptr != '\0')) {
- /* Using ports below 0x100 is a really bad idea, and
- * should only be done if no port between 0x100 and
- * 0xfffc works due to routing issues.
- */
- msg_perr("Error: iobase= specified, but the I/O base "
- "given was invalid.\nIt must be a multiple of "
- "0x4 and lie between 0x100 and 0xfffc.\n");
- free(arg);
- return 1;
- } else {
- 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);
-
- 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;
- /* Get the initial value before writing to any line. */
- lpt_outbyte = INB(lpt_iobase);
- if (pinout->shutdown)
- register_shutdown(pinout->shutdown, (void*)pinout);
- if (pinout->preinit)
- pinout->preinit(pinout);
- if (register_spi_bitbang_master(&bitbang_spi_master_rayer))
- 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
|