Remove unnecessary casts
[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 * 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 = malloc(versaloon_interface.usb_setting.buf_size);
245 if (NULL == versaloon_buf) {
246 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
247 return ERRCODE_NOT_ENOUGH_MEMORY;
248 }
249
250 /* connect to versaloon */
251 timeout_tmp = versaloon_usb_to;
252 /* not output error message when connectting */
253 /* 100ms delay when connect */
254 versaloon_usb_to = 100;
255 for (retry = 0; retry < VERSALOON_RETRY_CNT; retry++) {
256 versaloon_buf[0] = VERSALOON_GET_INFO;
257 if ((ERROR_OK == versaloon_send_command(1, &ret)) && (ret >= 3))
258 break;
259 }
260 versaloon_usb_to = timeout_tmp;
261 if (VERSALOON_RETRY_CNT == retry) {
262 versaloon_fini();
263 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
264 return ERRCODE_FAILURE_OPERATION;
265 }
266
267 versaloon_buf[ret] = 0;
268 versaloon_buf_size = versaloon_buf[0] + (versaloon_buf[1] << 8);
269 versaloon_interface.usb_setting.buf_size = versaloon_buf_size;
270 LOG_INFO("%s", versaloon_buf + 2);
271
272 /* free temporary buffer */
273 free(versaloon_buf);
274 versaloon_buf = NULL;
275
276 versaloon_buf = malloc(versaloon_interface.usb_setting.buf_size);
277 if (NULL == versaloon_buf) {
278 versaloon_fini();
279 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
280 return ERRCODE_NOT_ENOUGH_MEMORY;
281 }
282 versaloon_cmd_buf = malloc(versaloon_interface.usb_setting.buf_size - 3);
283 if (NULL == versaloon_cmd_buf) {
284 versaloon_fini();
285 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
286 return ERRCODE_NOT_ENOUGH_MEMORY;
287 }
288 if (ERROR_OK != usbtoxxx_init()) {
289 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "initialize usbtoxxx");
290 return ERROR_FAIL;
291 }
292 return versaloon_get_target_voltage(&ret);
293 }
294
295 RESULT versaloon_fini(void)
296 {
297 if (versaloon_usb_device_handle != NULL) {
298 usbtoxxx_fini();
299 versaloon_free_want_pos();
300
301 versaloon_usb_device_handle = NULL;
302
303 if (versaloon_buf != NULL) {
304 free(versaloon_buf);
305 versaloon_buf = NULL;
306 }
307 if (versaloon_cmd_buf != NULL) {
308 free(versaloon_cmd_buf);
309 versaloon_cmd_buf = NULL;
310 }
311 }
312
313 return ERROR_OK;
314 }
315
316 RESULT versaloon_set_target_voltage(uint16_t voltage)
317 {
318 usbtopwr_init(0);
319 usbtopwr_config(0);
320 usbtopwr_output(0, voltage);
321 usbtopwr_fini(0);
322
323 return usbtoxxx_execute_command();
324 }
325
326 RESULT versaloon_get_target_voltage(uint16_t *voltage)
327 {
328 uint16_t inlen;
329
330 #if PARAM_CHECK
331 if (NULL == versaloon_buf) {
332 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
333 return ERRCODE_INVALID_BUFFER;
334 }
335 if (NULL == voltage) {
336 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
337 return ERRCODE_INVALID_PARAMETER;
338 }
339 #endif
340
341 versaloon_buf[0] = VERSALOON_GET_TVCC;
342
343 if ((ERROR_OK != versaloon_send_command(1, &inlen)) || (inlen != 2)) {
344 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
345 return ERRCODE_FAILURE_OPERATION;
346 } else {
347 *voltage = versaloon_buf[0] + (versaloon_buf[1] << 8);
348 return ERROR_OK;
349 }
350 }
351
352 RESULT versaloon_delay_ms(uint16_t ms)
353 {
354 return usbtodelay_delay(ms | 0x8000);
355 }
356
357 RESULT versaloon_delay_us(uint16_t us)
358 {
359 return usbtodelay_delay(us & 0x7FFF);
360 }