flashrom 

flashrom Svn Source Tree

Root/trunk/rayer_spi.c

1/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009,2010 Carl-Daniel Hailfinger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20/* Driver for various LPT adapters.
21 *
22 * This driver uses non-portable direct I/O port accesses which won't work on
23 * any non-x86 platform, and even on x86 there is a high chance there will be
24 * collisions with any loaded parallel port drivers.
25 * The big advantage of direct port I/O is OS independence and speed because
26 * most OS parport drivers will perform many unnecessary accesses although
27 * this driver just treats the parallel port as a GPIO set.
28 */
29#if defined(__i386__) || defined(__x86_64__)
30
31#include <stdlib.h>
32#include <strings.h>
33#include <string.h>
34#include "flash.h"
35#include "programmer.h"
36#include "hwaccess.h"
37
38/* We have two sets of pins, out and in. The numbers for both sets are
39 * independent and are bitshift values, not real pin numbers.
40 * Default settings are for the RayeR hardware.
41 */
42
43struct rayer_programmer {
44const char *type;
45const enum test_state status;
46const char *description;
47const void *dev_data;
48};
49
50struct rayer_pinout {
51uint8_t cs_bit;
52uint8_t sck_bit;
53uint8_t mosi_bit;
54uint8_t miso_bit;
55void (*preinit)(const void *);
56int (*shutdown)(void *);
57};
58
59static const struct rayer_pinout rayer_spipgm = {
60.cs_bit = 5,
61.sck_bit = 6,
62.mosi_bit = 7,
63.miso_bit = 6,
64};
65
66static void dlc5_preinit(const void *);
67static int dlc5_shutdown(void *);
68
69static const struct rayer_pinout xilinx_dlc5 = {
70.cs_bit = 2,
71.sck_bit = 1,
72.mosi_bit = 0,
73.miso_bit = 4,
74.preinit = dlc5_preinit,
75.shutdown = dlc5_shutdown,
76};
77
78static void byteblaster_preinit(const void *);
79static int byteblaster_shutdown(void *);
80
81static const struct rayer_pinout altera_byteblastermv = {
82.cs_bit = 1,
83.sck_bit = 0,
84.mosi_bit = 6,
85.miso_bit = 7,
86.preinit = byteblaster_preinit,
87.shutdown = byteblaster_shutdown,
88};
89
90static void stk200_preinit(const void *);
91static int stk200_shutdown(void *);
92
93static const struct rayer_pinout atmel_stk200 = {
94.cs_bit = 7,
95.sck_bit = 4,
96.mosi_bit = 5,
97.miso_bit = 6,
98.preinit = stk200_preinit,
99.shutdown = stk200_shutdown,
100};
101
102static const struct rayer_pinout wiggler_lpt = {
103.cs_bit = 1,
104.sck_bit = 2,
105.mosi_bit = 3,
106.miso_bit = 7,
107};
108
109static const struct rayer_pinout spi_tt = {
110.cs_bit = 2,
111.sck_bit = 0,
112.mosi_bit = 4,
113.miso_bit = 7,
114};
115
116static const struct rayer_programmer rayer_spi_types[] = {
117{"rayer",NT,"RayeR SPIPGM",&rayer_spipgm},
118{"xilinx",NT,"Xilinx Parallel Cable III (DLC 5)",&xilinx_dlc5},
119{"byteblastermv",OK,"Altera ByteBlasterMV",&altera_byteblastermv},
120{"stk200",NT,"Atmel STK200/300 adapter",&atmel_stk200},
121{"wiggler",OK,"Wiggler LPT",&wiggler_lpt},
122{"spi_tt",NT,"SPI Tiny Tools (SPI_TT LPT)",&spi_tt},
123{0},
124};
125
126static const struct rayer_pinout *pinout = NULL;
127
128static uint16_t lpt_iobase;
129
130/* Cached value of last byte sent. */
131static uint8_t lpt_outbyte;
132
133static void rayer_bitbang_set_cs(int val)
134{
135lpt_outbyte &= ~(1 << pinout->cs_bit);
136lpt_outbyte |= (val << pinout->cs_bit);
137OUTB(lpt_outbyte, lpt_iobase);
138}
139
140static void rayer_bitbang_set_sck(int val)
141{
142lpt_outbyte &= ~(1 << pinout->sck_bit);
143lpt_outbyte |= (val << pinout->sck_bit);
144OUTB(lpt_outbyte, lpt_iobase);
145}
146
147static void rayer_bitbang_set_mosi(int val)
148{
149lpt_outbyte &= ~(1 << pinout->mosi_bit);
150lpt_outbyte |= (val << pinout->mosi_bit);
151OUTB(lpt_outbyte, lpt_iobase);
152}
153
154static int rayer_bitbang_get_miso(void)
155{
156uint8_t tmp;
157
158tmp = INB(lpt_iobase + 1) ^ 0x80; // bit.7 inverted
159tmp = (tmp >> pinout->miso_bit) & 0x1;
160return tmp;
161}
162
163static const struct bitbang_spi_master bitbang_spi_master_rayer = {
164.type = BITBANG_SPI_MASTER_RAYER,
165.set_cs = rayer_bitbang_set_cs,
166.set_sck = rayer_bitbang_set_sck,
167.set_mosi = rayer_bitbang_set_mosi,
168.get_miso = rayer_bitbang_get_miso,
169.half_period = 0,
170};
171
172int rayer_spi_init(void)
173{
174const struct rayer_programmer *prog = rayer_spi_types;
175char *arg = NULL;
176
177/* Non-default port requested? */
178arg = extract_programmer_param("iobase");
179if (arg) {
180char *endptr = NULL;
181unsigned long tmp;
182tmp = strtoul(arg, &endptr, 0);
183/* Port 0, port >0x10000, unaligned ports and garbage strings
184 * are rejected.
185 */
186if (!tmp || (tmp >= 0x10000) || (tmp & 0x3) ||
187 (*endptr != '\0')) {
188/* Using ports below 0x100 is a really bad idea, and
189 * should only be done if no port between 0x100 and
190 * 0xfffc works due to routing issues.
191 */
192msg_perr("Error: iobase= specified, but the I/O base "
193 "given was invalid.\nIt must be a multiple of "
194 "0x4 and lie between 0x100 and 0xfffc.\n");
195free(arg);
196return 1;
197} else {
198lpt_iobase = (uint16_t)tmp;
199msg_pinfo("Non-default I/O base requested. This will "
200 "not change the hardware settings.\n");
201}
202} else {
203/* Pick a default value for the I/O base. */
204lpt_iobase = 0x378;
205}
206free(arg);
207
208msg_pdbg("Using address 0x%x as I/O base for parallel port access.\n",
209 lpt_iobase);
210
211arg = extract_programmer_param("type");
212if (arg) {
213for (; prog->type != NULL; prog++) {
214if (strcasecmp(arg, prog->type) == 0) {
215break;
216}
217}
218if (prog->type == NULL) {
219msg_perr("Error: Invalid device type specified.\n");
220free(arg);
221return 1;
222}
223free(arg);
224}
225msg_pinfo("Using %s pinout.\n", prog->description);
226pinout = (struct rayer_pinout *)prog->dev_data;
227
228if (rget_io_perms())
229return 1;
230
231/* Get the initial value before writing to any line. */
232lpt_outbyte = INB(lpt_iobase);
233
234if (pinout->shutdown)
235register_shutdown(pinout->shutdown, (void*)pinout);
236if (pinout->preinit)
237pinout->preinit(pinout);
238
239if (register_spi_bitbang_master(&bitbang_spi_master_rayer))
240return 1;
241
242return 0;
243}
244
245static void byteblaster_preinit(const void *data){
246msg_pdbg("byteblaster_preinit\n");
247/* Assert #EN signal. */
248OUTB(2, lpt_iobase + 2 );
249}
250
251static int byteblaster_shutdown(void *data){
252msg_pdbg("byteblaster_shutdown\n");
253/* De-Assert #EN signal. */
254OUTB(0, lpt_iobase + 2 );
255return 0;
256}
257
258static void stk200_preinit(const void *data) {
259msg_pdbg("stk200_init\n");
260/* Assert #EN signals, set LED signal. */
261lpt_outbyte = (1 << 6) ;
262OUTB(lpt_outbyte, lpt_iobase);
263}
264
265static int stk200_shutdown(void *data) {
266msg_pdbg("stk200_shutdown\n");
267/* Assert #EN signals, clear LED signal. */
268lpt_outbyte = (1 << 2) | (1 << 3);
269OUTB(lpt_outbyte, lpt_iobase);
270return 0;
271}
272
273static void dlc5_preinit(const void *data) {
274msg_pdbg("dlc5_preinit\n");
275/* Assert pin 6 to receive MISO. */
276lpt_outbyte |= (1<<4);
277OUTB(lpt_outbyte, lpt_iobase);
278}
279
280static int dlc5_shutdown(void *data) {
281msg_pdbg("dlc5_shutdown\n");
282/* De-assert pin 6 to force MISO low. */
283lpt_outbyte &= ~(1<<4);
284OUTB(lpt_outbyte, lpt_iobase);
285return 0;
286}
287
288#else
289#error PCI port I/O access is not supported on this architecture yet.
290#endif

Archive Download this file

Revision: HEAD