]> git.sur5r.net Git - openocd/blob - src/jtag/drivers/versaloon/versaloon.c
update files to correct FSF address
[openocd] / 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  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 }