blob: f8faeb33a249a4b0747a7e5da853c90097cb1f49 [file] [log] [blame]
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2012 Virgil-Adrian Teaca
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
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +000020/* Driver for serial programmers compatible with SI-Prog or AJAWe.
21 *
22 * See http://www.lancos.com/siprogsch.html for SI-Prog schematics and instructions.
23 * See http://www.ajawe.pl/ajawe0208.htm for AJAWe serial programmer documentation.
24 *
25 * Pin layout for SI-Prog-like hardware:
26 *
27 * MOSI <-------< DTR
28 * MISO >-------> CTS
29 * SCK <---+---< RTS
30 * +---> DSR
31 * CS# <-------< TXD
32 *
33 * and for the AJAWe serial programmer:
34 *
35 * MOSI <-------< DTR
36 * MISO >-------> CTS
37 * SCK <-------< RTS
38 * CS# <-------< TXD
39 *
40 * DCE >-------> DSR
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000041 */
42
43#include <stdlib.h>
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +000044#include <strings.h>
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000045#include <string.h>
46
47#include "flash.h"
48#include "programmer.h"
49
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000050enum pony_type {
51 TYPE_SI_PROG,
52 TYPE_SERBANG,
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +000053 TYPE_AJAWE
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000054};
55
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +000056/* Pins for master->slave direction */
57static int pony_negate_cs = 1;
58static int pony_negate_sck = 0;
59static int pony_negate_mosi = 0;
60/* Pins for slave->master direction */
61static int pony_negate_miso = 0;
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000062
63static void pony_bitbang_set_cs(int val)
64{
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +000065 if (pony_negate_cs)
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000066 val ^= 1;
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +000067
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000068 sp_set_pin(PIN_TXD, val);
69}
70
71static void pony_bitbang_set_sck(int val)
72{
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +000073 if (pony_negate_sck)
74 val ^= 1;
75
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000076 sp_set_pin(PIN_RTS, val);
77}
78
79static void pony_bitbang_set_mosi(int val)
80{
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +000081 if (pony_negate_mosi)
82 val ^= 1;
83
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000084 sp_set_pin(PIN_DTR, val);
85}
86
87static int pony_bitbang_get_miso(void)
88{
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +000089 int tmp = sp_get_pin(PIN_CTS);
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000090
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +000091 if (pony_negate_miso)
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000092 tmp ^= 1;
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +000093
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +000094 return tmp;
95}
96
97static const struct bitbang_spi_master bitbang_spi_master_pony = {
98 .type = BITBANG_SPI_MASTER_PONY,
99 .set_cs = pony_bitbang_set_cs,
100 .set_sck = pony_bitbang_set_sck,
101 .set_mosi = pony_bitbang_set_mosi,
102 .get_miso = pony_bitbang_get_miso,
103 .half_period = 0,
104};
105
Carl-Daniel Hailfinger8b6690c2016-03-13 16:24:09 +0000106static int pony_spi_shutdown(void *data)
107{
108 /* Shut down serial port communication */
109 int ret = serialport_shutdown(NULL);
110 if (ret)
111 msg_pdbg("Pony SPI shutdown failed.\n");
112 else
113 msg_pdbg("Pony SPI shutdown completed.\n");
114
115 return ret;
116}
117
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000118int pony_spi_init(void)
119{
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000120 int i, data_out;
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000121 char *arg = NULL;
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000122 enum pony_type type = TYPE_SI_PROG;
123 char *name;
124 int have_device = 0;
125 int have_prog = 0;
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000126
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000127 /* The parameter is in format "dev=/dev/device,type=serbang" */
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000128 arg = extract_programmer_param("dev");
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000129 if (arg && strlen(arg)) {
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000130 sp_fd = sp_openserport(arg, 9600);
Stefan Tauneracfc4c62012-11-30 16:46:45 +0000131 if (sp_fd == SER_INV_FD) {
Niklas Söderlund2a95e872012-07-30 19:42:33 +0000132 free(arg);
133 return 1;
134 }
Carl-Daniel Hailfinger8b6690c2016-03-13 16:24:09 +0000135 if (register_shutdown(pony_spi_shutdown, NULL) != 0) {
136 free(arg);
137 serialport_shutdown(NULL);
138 return 1;
139 }
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000140 have_device++;
141 }
142 free(arg);
143
144 if (!have_device) {
145 msg_perr("Error: No valid device specified.\n"
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000146 "Use flashrom -p pony_spi:dev=/dev/device[,type=name]\n");
147 return 1;
148 }
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000149
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000150 arg = extract_programmer_param("type");
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000151 if (arg && !strcasecmp(arg, "serbang")) {
152 type = TYPE_SERBANG;
153 } else if (arg && !strcasecmp(arg, "si_prog")) {
154 type = TYPE_SI_PROG;
155 } else if (arg && !strcasecmp( arg, "ajawe")) {
156 type = TYPE_AJAWE;
157 } else if (arg && !strlen(arg)) {
158 msg_perr("Error: Missing argument for programmer type.\n");
159 free(arg);
Stefan Reinauerbbdde552014-04-26 16:11:30 +0000160 return 1;
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000161 } else if (arg){
162 msg_perr("Error: Invalid programmer type specified.\n");
163 free(arg);
164 return 1;
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000165 }
166 free(arg);
167
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000168 /*
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000169 * Configure the serial port pins, depending on the used programmer.
170 */
171 switch (type) {
172 case TYPE_AJAWE:
173 pony_negate_cs = 1;
174 pony_negate_sck = 1;
175 pony_negate_mosi = 1;
176 pony_negate_miso = 1;
177 name = "AJAWe";
178 break;
179 case TYPE_SERBANG:
180 pony_negate_cs = 0;
181 pony_negate_sck = 0;
182 pony_negate_mosi = 0;
183 pony_negate_miso = 1;
184 name = "serbang";
185 break;
186 default:
187 case TYPE_SI_PROG:
188 pony_negate_cs = 1;
189 pony_negate_sck = 0;
190 pony_negate_mosi = 0;
191 pony_negate_miso = 0;
192 name = "SI-Prog";
193 break;
194 }
195 msg_pdbg("Using %s programmer pinout.\n", name);
196
197 /*
198 * Detect if there is a compatible hardware programmer connected.
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000199 */
200 pony_bitbang_set_cs(1);
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000201 pony_bitbang_set_sck(1);
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000202 pony_bitbang_set_mosi(1);
203
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000204 switch (type) {
205 case TYPE_AJAWE:
206 have_prog = 1;
207 break;
208 case TYPE_SI_PROG:
209 case TYPE_SERBANG:
210 default:
211 have_prog = 1;
212 /* We toggle RTS/SCK a few times and see if DSR changes too. */
213 for (i = 1; i <= 10; i++) {
214 data_out = i & 1;
215 sp_set_pin(PIN_RTS, data_out);
216 programmer_delay(1000);
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000217
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000218 /* If DSR does not change, we are not connected to what we think */
219 if (data_out != sp_get_pin(PIN_DSR)) {
220 have_prog = 0;
221 break;
222 }
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000223 }
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000224 break;
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000225 }
226
227 if (!have_prog) {
Virgil-Adrian Teacadabca202012-09-01 21:32:04 +0000228 msg_perr("No programmer compatible with %s detected.\n", name);
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000229 return 1;
230 }
231
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000232 if (register_spi_bitbang_master(&bitbang_spi_master_pony)) {
Virgil-Adrian Teacada7c5452012-04-30 23:11:06 +0000233 return 1;
234 }
235 return 0;
236}