build: cleanup src/jtag/drivers directory
[openocd.git] / src / jtag / drivers / versaloon / versaloon.c
1 /***************************************************************************
2 * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "versaloon_include.h"
28 #include "versaloon.h"
29 #include "versaloon_internal.h"
30 #include "usbtoxxx/usbtoxxx.h"
31
32 uint8_t *versaloon_buf;
33 uint8_t *versaloon_cmd_buf;
34 uint16_t versaloon_buf_size;
35
36 struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER];
37 uint16_t versaloon_pending_idx;
38
39 usb_dev_handle *versaloon_usb_device_handle;
40 static uint32_t versaloon_usb_to = VERSALOON_TIMEOUT;
41
42 RESULT versaloon_init(void);
43 RESULT versaloon_fini(void);
44 RESULT versaloon_get_target_voltage(uint16_t *voltage);
45 RESULT versaloon_set_target_voltage(uint16_t voltage);
46 RESULT versaloon_delay_ms(uint16_t ms);
47 RESULT versaloon_delay_us(uint16_t us);
48
49 struct versaloon_interface_t versaloon_interface = {
50 .init = versaloon_init,
51 .fini = versaloon_fini,
52 { /* adaptors */
53 { /* target_voltage */
54 .get = versaloon_get_target_voltage,
55 .set = versaloon_set_target_voltage,
56 },
57 { /* gpio */
58 .init = usbtogpio_init,
59 .fini = usbtogpio_fini,
60 .config = usbtogpio_config,
61 .out = usbtogpio_out,
62 .in = usbtogpio_in,
63 },
64 { /* delay */
65 .delayms = versaloon_delay_ms,
66 .delayus = versaloon_delay_us,
67 },
68 { /* swd */
69 .init = usbtoswd_init,
70 .fini = usbtoswd_fini,
71 .config = usbtoswd_config,
72 .seqout = usbtoswd_seqout,
73 .seqin = usbtoswd_seqin,
74 .transact = usbtoswd_transact,
75 },
76 { /* jtag_raw */
77 .init = usbtojtagraw_init,
78 .fini = usbtojtagraw_fini,
79 .config = usbtojtagraw_config,
80 .execute = usbtojtagraw_execute,
81 },
82 .peripheral_commit = usbtoxxx_execute_command,
83 },
84 { /* usb_setting */
85 .vid = VERSALOON_VID,
86 .pid = VERSALOON_PID,
87 .ep_out = VERSALOON_OUTP,
88 .ep_in = VERSALOON_INP,
89 .interface = VERSALOON_IFACE,
90 .serialstring = NULL,
91 .buf_size = 256,
92 }
93 };
94
95 /* programmer_cmd */
96 static uint32_t versaloon_pending_id;
97 static versaloon_callback_t versaloon_callback;
98 static void *versaloon_extra_data;
99 static struct versaloon_want_pos_t *versaloon_want_pos;
100
101 void versaloon_set_pending_id(uint32_t id)
102 {
103 versaloon_pending_id = id;
104 }
105 void versaloon_set_callback(versaloon_callback_t callback)
106 {
107 versaloon_callback = callback;
108 }
109 void versaloon_set_extra_data(void *p)
110 {
111 versaloon_extra_data = p;
112 }
113
114 void versaloon_free_want_pos(void)
115 {
116 uint16_t i;
117 struct versaloon_want_pos_t *tmp, *free_tmp;
118
119 tmp = versaloon_want_pos;
120 while (tmp != NULL) {
121 free_tmp = tmp;
122 tmp = tmp->next;
123 free(free_tmp);
124 }
125 versaloon_want_pos = NULL;
126
127 for (i = 0; i < dimof(versaloon_pending); i++) {
128 tmp = versaloon_pending[i].pos;
129 while (tmp != NULL) {
130 free_tmp = tmp;
131 tmp = tmp->next;
132 free(free_tmp);
133 }
134 versaloon_pending[i].pos = NULL;
135 }
136 }
137
138 RESULT versaloon_add_want_pos(uint16_t offset, uint16_t size, uint8_t *buff)
139 {
140 struct versaloon_want_pos_t *new_pos = NULL;
141
142 new_pos = (struct versaloon_want_pos_t *)malloc(sizeof(*new_pos));
143 if (NULL == new_pos) {
144 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
145 return ERRCODE_NOT_ENOUGH_MEMORY;
146 }
147 new_pos->offset = offset;
148 new_pos->size = size;
149 new_pos->buff = buff;
150 new_pos->next = NULL;
151
152 if (NULL == versaloon_want_pos)
153 versaloon_want_pos = new_pos;
154 else {
155 struct versaloon_want_pos_t *tmp = versaloon_want_pos;
156
157 while (tmp->next != NULL)
158 tmp = tmp->next;
159 tmp->next = new_pos;
160 }
161
162 return ERROR_OK;
163 }
164
165 RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie,
166 uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect)
167 {
168 #if PARAM_CHECK
169 if (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER) {
170 LOG_BUG(ERRMSG_INVALID_INDEX, versaloon_pending_idx,
171 "versaloon pending data");
172 return ERROR_FAIL;
173 }
174 #endif
175
176 versaloon_pending[versaloon_pending_idx].type = type;
177 versaloon_pending[versaloon_pending_idx].cmd = cmd;
178 versaloon_pending[versaloon_pending_idx].actual_data_size = actual_szie;
179 versaloon_pending[versaloon_pending_idx].want_data_pos = want_pos;
180 versaloon_pending[versaloon_pending_idx].want_data_size = want_size;
181 versaloon_pending[versaloon_pending_idx].data_buffer = buffer;
182 versaloon_pending[versaloon_pending_idx].collect = collect;
183 versaloon_pending[versaloon_pending_idx].id = versaloon_pending_id;
184 versaloon_pending_id = 0;
185 versaloon_pending[versaloon_pending_idx].extra_data = versaloon_extra_data;
186 versaloon_extra_data = NULL;
187 versaloon_pending[versaloon_pending_idx].callback = versaloon_callback;
188 versaloon_callback = NULL;
189 versaloon_pending[versaloon_pending_idx].pos = versaloon_want_pos;
190 versaloon_want_pos = NULL;
191 versaloon_pending_idx++;
192
193 return ERROR_OK;
194 }
195
196 RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen)
197 {
198 int ret;
199
200 #if PARAM_CHECK
201 if (NULL == versaloon_buf) {
202 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
203 return ERRCODE_INVALID_BUFFER;
204 }
205 if ((0 == out_len) || (out_len > versaloon_interface.usb_setting.buf_size)) {
206 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
207 return ERRCODE_INVALID_PARAMETER;
208 }
209 #endif
210
211 ret = usb_bulk_write(versaloon_usb_device_handle,
212 versaloon_interface.usb_setting.ep_out, (char *)versaloon_buf,
213 out_len, versaloon_usb_to);
214 if (ret != out_len) {
215 LOG_ERROR(ERRMSG_FAILURE_OPERATION_ERRSTRING, "send usb data",
216 usb_strerror());
217 return ERRCODE_FAILURE_OPERATION;
218 }
219
220 if (inlen != NULL) {
221 ret = usb_bulk_read(versaloon_usb_device_handle,
222 versaloon_interface.usb_setting.ep_in, (char *)versaloon_buf,
223 versaloon_interface.usb_setting.buf_size, versaloon_usb_to);
224 if (ret > 0) {
225 *inlen = (uint16_t)ret;
226 return ERROR_OK;
227 } else {
228 LOG_ERROR(ERRMSG_FAILURE_OPERATION_ERRSTRING, "receive usb data",
229 usb_strerror());
230 return ERROR_FAIL;
231 }
232 } else
233 return ERROR_OK;
234 }
235
236 #define VERSALOON_RETRY_CNT 10
237 RESULT versaloon_init(void)
238 {
239 uint16_t ret = 0;
240 uint8_t retry;
241 uint32_t timeout_tmp;
242
243 /* malloc temporary buffer */
244 versaloon_buf =
245 (uint8_t *)malloc(versaloon_interface.usb_setting.buf_size);
246 if (NULL == versaloon_buf) {
247 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
248 return ERRCODE_NOT_ENOUGH_MEMORY;
249 }
250
251 /* connect to versaloon */
252 timeout_tmp = versaloon_usb_to;
253 /* not output error message when connectting */
254 /* 100ms delay when connect */
255 versaloon_usb_to = 100;
256 for (retry = 0; retry < VERSALOON_RETRY_CNT; retry++) {
257 versaloon_buf[0] = VERSALOON_GET_INFO;
258 if ((ERROR_OK == versaloon_send_command(1, &ret)) && (ret >= 3))
259 break;
260 }
261 versaloon_usb_to = timeout_tmp;
262 if (VERSALOON_RETRY_CNT == retry) {
263 versaloon_fini();
264 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
265 return ERRCODE_FAILURE_OPERATION;
266 }
267
268 versaloon_buf[ret] = 0;
269 versaloon_buf_size = versaloon_buf[0] + (versaloon_buf[1] << 8);
270 versaloon_interface.usb_setting.buf_size = versaloon_buf_size;
271 LOG_INFO("%s", versaloon_buf + 2);
272
273 /* free temporary buffer */
274 free(versaloon_buf);
275 versaloon_buf = NULL;
276
277 versaloon_buf =
278 (uint8_t *)malloc(versaloon_interface.usb_setting.buf_size);
279 if (NULL == versaloon_buf) {
280 versaloon_fini();
281 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
282 return ERRCODE_NOT_ENOUGH_MEMORY;
283 }
284 versaloon_cmd_buf =
285 (uint8_t *)malloc(versaloon_interface.usb_setting.buf_size - 3);
286 if (NULL == versaloon_cmd_buf) {
287 versaloon_fini();
288 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
289 return ERRCODE_NOT_ENOUGH_MEMORY;
290 }
291 if (ERROR_OK != usbtoxxx_init()) {
292 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "initialize usbtoxxx");
293 return ERROR_FAIL;
294 }
295 return versaloon_get_target_voltage(&ret);
296 }
297
298 RESULT versaloon_fini(void)
299 {
300 if (versaloon_usb_device_handle != NULL) {
301 usbtoxxx_fini();
302 versaloon_free_want_pos();
303
304 versaloon_usb_device_handle = NULL;
305
306 if (versaloon_buf != NULL) {
307 free(versaloon_buf);
308 versaloon_buf = NULL;
309 }
310 if (versaloon_cmd_buf != NULL) {
311 free(versaloon_cmd_buf);
312 versaloon_cmd_buf = NULL;
313 }
314 }
315
316 return ERROR_OK;
317 }
318
319 RESULT versaloon_set_target_voltage(uint16_t voltage)
320 {
321 usbtopwr_init(0);
322 usbtopwr_config(0);
323 usbtopwr_output(0, voltage);
324 usbtopwr_fini(0);
325
326 return usbtoxxx_execute_command();
327 }
328
329 RESULT versaloon_get_target_voltage(uint16_t *voltage)
330 {
331 uint16_t inlen;
332
333 #if PARAM_CHECK
334 if (NULL == versaloon_buf) {
335 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
336 return ERRCODE_INVALID_BUFFER;
337 }
338 if (NULL == voltage) {
339 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
340 return ERRCODE_INVALID_PARAMETER;
341 }
342 #endif
343
344 versaloon_buf[0] = VERSALOON_GET_TVCC;
345
346 if ((ERROR_OK != versaloon_send_command(1, &inlen)) || (inlen != 2)) {
347 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
348 return ERRCODE_FAILURE_OPERATION;
349 } else {
350 *voltage = versaloon_buf[0] + (versaloon_buf[1] << 8);
351 return ERROR_OK;
352 }
353 }
354
355 RESULT versaloon_delay_ms(uint16_t ms)
356 {
357 return usbtodelay_delay(ms | 0x8000);
358 }
359
360 RESULT versaloon_delay_us(uint16_t us)
361 {
362 return usbtodelay_delay(us & 0x7FFF);
363 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)