- Fixes '[+]=' whitespace
[openocd.git] / src / flash / mflash.c
1 /***************************************************************************
2 * Copyright (C) 2007-2008 by unsik Kim <donari75@gmail.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 "mflash.h"
25 #include "time_support.h"
26 #include "fileio.h"
27 #include "log.h"
28
29
30 static int s3c2440_set_gpio_to_output (mflash_gpio_num_t gpio);
31 static int s3c2440_set_gpio_output_val (mflash_gpio_num_t gpio, uint8_t val);
32 static int pxa270_set_gpio_to_output (mflash_gpio_num_t gpio);
33 static int pxa270_set_gpio_output_val (mflash_gpio_num_t gpio, uint8_t val);
34
35 static command_t *mflash_cmd;
36
37 static mflash_bank_t *mflash_bank;
38
39 static mflash_gpio_drv_t pxa270_gpio = {
40 .name = "pxa270",
41 .set_gpio_to_output = pxa270_set_gpio_to_output,
42 .set_gpio_output_val = pxa270_set_gpio_output_val
43 };
44
45 static mflash_gpio_drv_t s3c2440_gpio = {
46 .name = "s3c2440",
47 .set_gpio_to_output = s3c2440_set_gpio_to_output,
48 .set_gpio_output_val = s3c2440_set_gpio_output_val
49 };
50
51 static mflash_gpio_drv_t *mflash_gpio[] =
52 {
53 &pxa270_gpio,
54 &s3c2440_gpio,
55 NULL
56 };
57
58 #define PXA270_GAFR0_L 0x40E00054
59 #define PXA270_GAFR3_U 0x40E00070
60 #define PXA270_GAFR3_U_RESERVED_BITS 0xfffc0000u
61 #define PXA270_GPDR0 0x40E0000C
62 #define PXA270_GPDR3 0x40E0010C
63 #define PXA270_GPDR3_RESERVED_BITS 0xfe000000u
64 #define PXA270_GPSR0 0x40E00018
65 #define PXA270_GPCR0 0x40E00024
66
67 static int pxa270_set_gpio_to_output (mflash_gpio_num_t gpio)
68 {
69 uint32_t addr, value, mask;
70 target_t *target = mflash_bank->target;
71 int ret;
72
73 /* remove alternate function. */
74 mask = 0x3u << (gpio.num & 0xF)*2;
75
76 addr = PXA270_GAFR0_L + (gpio.num >> 4) * 4;
77
78 if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
79 return ret;
80
81 value &= ~mask;
82 if (addr == PXA270_GAFR3_U)
83 value &= ~PXA270_GAFR3_U_RESERVED_BITS;
84
85 if ((ret = target_write_u32(target, addr, value)) != ERROR_OK)
86 return ret;
87
88 /* set direction to output */
89 mask = 0x1u << (gpio.num & 0x1F);
90
91 addr = PXA270_GPDR0 + (gpio.num >> 5) * 4;
92
93 if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
94 return ret;
95
96 value |= mask;
97 if (addr == PXA270_GPDR3)
98 value &= ~PXA270_GPDR3_RESERVED_BITS;
99
100 ret = target_write_u32(target, addr, value);
101 return ret;
102 }
103
104 static int pxa270_set_gpio_output_val (mflash_gpio_num_t gpio, uint8_t val)
105 {
106 uint32_t addr, value, mask;
107 target_t *target = mflash_bank->target;
108 int ret;
109
110 mask = 0x1u << (gpio.num & 0x1F);
111
112 if (val) {
113 addr = PXA270_GPSR0 + (gpio.num >> 5) * 4;
114 } else {
115 addr = PXA270_GPCR0 + (gpio.num >> 5) * 4;
116 }
117
118 if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
119 return ret;
120
121 value |= mask;
122
123 ret = target_write_u32(target, addr, value);
124
125 return ret;
126 }
127
128 #define S3C2440_GPACON 0x56000000
129 #define S3C2440_GPADAT 0x56000004
130 #define S3C2440_GPJCON 0x560000d0
131 #define S3C2440_GPJDAT 0x560000d4
132
133 static int s3c2440_set_gpio_to_output (mflash_gpio_num_t gpio)
134 {
135 uint32_t data, mask, gpio_con;
136 target_t *target = mflash_bank->target;
137 int ret;
138
139 if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') {
140 gpio_con = S3C2440_GPACON + (gpio.port[0] - 'a') * 0x10;
141 } else if (gpio.port[0] == 'j') {
142 gpio_con = S3C2440_GPJCON;
143 } else {
144 LOG_ERROR("mflash: invalid port %d%s", gpio.num, gpio.port);
145 return ERROR_INVALID_ARGUMENTS;
146 }
147
148 ret = target_read_u32(target, gpio_con, &data);
149
150 if (ret == ERROR_OK) {
151 if (gpio.port[0] == 'a') {
152 mask = 1 << gpio.num;
153 data &= ~mask;
154 } else {
155 mask = 3 << gpio.num * 2;
156 data &= ~mask;
157 data |= (1 << gpio.num * 2);
158 }
159
160 ret = target_write_u32(target, gpio_con, data);
161 }
162 return ret;
163 }
164
165 static int s3c2440_set_gpio_output_val (mflash_gpio_num_t gpio, uint8_t val)
166 {
167 uint32_t data, mask, gpio_dat;
168 target_t *target = mflash_bank->target;
169 int ret;
170
171 if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') {
172 gpio_dat = S3C2440_GPADAT + (gpio.port[0] - 'a') * 0x10;
173 } else if (gpio.port[0] == 'j') {
174 gpio_dat = S3C2440_GPJDAT;
175 } else {
176 LOG_ERROR("mflash: invalid port %d%s", gpio.num, gpio.port);
177 return ERROR_INVALID_ARGUMENTS;
178 }
179
180 ret = target_read_u32(target, gpio_dat, &data);
181
182 if (ret == ERROR_OK) {
183 mask = 1 << gpio.num;
184 if (val)
185 data |= mask;
186 else
187 data &= ~mask;
188
189 ret = target_write_u32(target, gpio_dat, data);
190 }
191 return ret;
192 }
193
194 static int mg_hdrst(uint8_t level)
195 {
196 return mflash_bank->gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, level);
197 }
198
199 static int mg_init_gpio (void)
200 {
201 int ret;
202 mflash_gpio_drv_t *gpio_drv = mflash_bank->gpio_drv;
203
204 ret = gpio_drv->set_gpio_to_output(mflash_bank->rst_pin);
205 if (ret != ERROR_OK)
206 return ret;
207
208 ret = gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, 1);
209
210 return ret;
211 }
212
213 static int mg_dsk_wait(mg_io_type_wait wait, uint32_t time)
214 {
215 uint8_t status, error;
216 target_t *target = mflash_bank->target;
217 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
218 duration_t duration;
219 int ret;
220 long long t=0;
221
222 duration_start_measure(&duration);
223
224 while (time) {
225
226 ret = target_read_u8(target, mg_task_reg + MG_REG_STATUS, &status);
227 if (ret != ERROR_OK)
228 return ret;
229
230 if (status & mg_io_rbit_status_busy)
231 {
232 if (wait == mg_io_wait_bsy)
233 return ERROR_OK;
234 } else {
235 switch (wait)
236 {
237 case mg_io_wait_not_bsy:
238 return ERROR_OK;
239 case mg_io_wait_rdy_noerr:
240 if (status & mg_io_rbit_status_ready)
241 return ERROR_OK;
242 break;
243 case mg_io_wait_drq_noerr:
244 if (status & mg_io_rbit_status_data_req)
245 return ERROR_OK;
246 break;
247 default:
248 break;
249 }
250
251 /* Now we check the error condition! */
252 if (status & mg_io_rbit_status_error)
253 {
254 ret = target_read_u8(target, mg_task_reg + MG_REG_ERROR, &error);
255 if (ret != ERROR_OK)
256 return ret;
257
258 LOG_ERROR("mflash: io error 0x%02x", error);
259
260 return ERROR_MG_IO;
261 }
262
263 switch (wait)
264 {
265 case mg_io_wait_rdy:
266 if (status & mg_io_rbit_status_ready)
267 return ERROR_OK;
268
269 case mg_io_wait_drq:
270 if (status & mg_io_rbit_status_data_req)
271 return ERROR_OK;
272
273 default:
274 break;
275 }
276 }
277
278 duration_stop_measure(&duration, NULL);
279
280 t=duration.duration.tv_usec/1000;
281 t += duration.duration.tv_sec*1000;
282
283 if (t > time)
284 break;
285 }
286
287 LOG_ERROR("mflash: timeout occured");
288 return ERROR_MG_TIMEOUT;
289 }
290
291 static int mg_dsk_srst(uint8_t on)
292 {
293 target_t *target = mflash_bank->target;
294 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
295 uint8_t value;
296 int ret;
297
298 if ((ret = target_read_u8(target, mg_task_reg + MG_REG_DRV_CTRL, &value)) != ERROR_OK)
299 return ret;
300
301 if (on) {
302 value |= (mg_io_rbit_devc_srst);
303 } else {
304 value &= ~mg_io_rbit_devc_srst;
305 }
306
307 ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_CTRL, value);
308 return ret;
309 }
310
311 static int mg_dsk_io_cmd(uint32_t sect_num, uint32_t cnt, uint8_t cmd)
312 {
313 target_t *target = mflash_bank->target;
314 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
315 uint8_t value;
316 int ret;
317
318 ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL);
319 if (ret != ERROR_OK)
320 return ret;
321
322 value = mg_io_rval_dev_drv_master | mg_io_rval_dev_lba_mode |((sect_num >> 24) & 0xf);
323
324 ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_HEAD, value);
325 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, (uint8_t)cnt);
326 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_NUM, (uint8_t)sect_num);
327 ret |= target_write_u8(target, mg_task_reg + MG_REG_CYL_LOW, (uint8_t)(sect_num >> 8));
328 ret |= target_write_u8(target, mg_task_reg + MG_REG_CYL_HIGH, (uint8_t)(sect_num >> 16));
329
330 if (ret != ERROR_OK)
331 return ret;
332
333 return target_write_u8(target, mg_task_reg + MG_REG_COMMAND, cmd);
334 }
335
336 static int mg_dsk_drv_info(void)
337 {
338 target_t *target = mflash_bank->target;
339 uint32_t mg_buff = mflash_bank->base + MG_BUFFER_OFFSET;
340 int ret;
341
342 if ((ret = mg_dsk_io_cmd(0, 1, mg_io_cmd_identify)) != ERROR_OK)
343 return ret;
344
345 if ((ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL)) != ERROR_OK)
346 return ret;
347
348 LOG_INFO("mflash: read drive info");
349
350 if (! mflash_bank->drv_info)
351 mflash_bank->drv_info = malloc(sizeof(mg_drv_info_t));
352
353 target_read_memory(target, mg_buff, 2, sizeof(mg_io_type_drv_info) >> 1,
354 (uint8_t *)&mflash_bank->drv_info->drv_id);
355 if (ret != ERROR_OK)
356 return ret;
357
358 mflash_bank->drv_info->tot_sects = (uint32_t)(mflash_bank->drv_info->drv_id.total_user_addressable_sectors_hi << 16)
359 + mflash_bank->drv_info->drv_id.total_user_addressable_sectors_lo;
360
361 return target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_read);
362 }
363
364 static int mg_mflash_rst(void)
365 {
366 int ret;
367
368 if ((ret = mg_init_gpio()) != ERROR_OK)
369 return ret;
370
371 if ((ret = mg_hdrst(0)) != ERROR_OK)
372 return ret;
373
374 if ((ret = mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG)) != ERROR_OK)
375 return ret;
376
377 if ((ret = mg_hdrst(1)) != ERROR_OK)
378 return ret;
379
380 if ((ret = mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG)) != ERROR_OK)
381 return ret;
382
383 if ((ret = mg_dsk_srst(1)) != ERROR_OK)
384 return ret;
385
386 if ((ret = mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG)) != ERROR_OK)
387 return ret;
388
389 if ((ret = mg_dsk_srst(0)) != ERROR_OK)
390 return ret;
391
392 if ((ret = mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG)) != ERROR_OK)
393 return ret;
394
395 LOG_INFO("mflash: reset ok");
396
397 return ERROR_OK;
398 }
399
400 static int mg_mflash_probe(void)
401 {
402 int ret;
403
404 if ((ret = mg_mflash_rst()) != ERROR_OK)
405 return ret;
406
407 return mg_dsk_drv_info();
408 }
409
410 static int mg_probe_cmd(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
411 {
412 int ret;
413
414 ret = mg_mflash_probe();
415
416 if (ret == ERROR_OK) {
417 command_print(cmd_ctx, "mflash (total %" PRIu32 " sectors) found at 0x%8.8" PRIx32 "",
418 mflash_bank->drv_info->tot_sects, mflash_bank->base );
419 }
420
421 return ret;
422 }
423
424 static int mg_mflash_do_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
425 {
426 uint32_t i, address;
427 int ret;
428 target_t *target = mflash_bank->target;
429 uint8_t *buff_ptr = buff;
430 duration_t duration;
431
432 if ((ret = mg_dsk_io_cmd(sect_num, sect_cnt, mg_io_cmd_read)) != ERROR_OK )
433 return ret;
434
435 address = mflash_bank->base + MG_BUFFER_OFFSET;
436
437 duration_start_measure(&duration);
438
439 for (i = 0; i < sect_cnt; i++) {
440 ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
441 if (ret != ERROR_OK)
442 return ret;
443
444 ret = target_read_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
445 if (ret != ERROR_OK)
446 return ret;
447
448 buff_ptr += MG_MFLASH_SECTOR_SIZE;
449
450 ret = target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_read);
451 if (ret != ERROR_OK)
452 return ret;
453
454 LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector read", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
455
456 duration_stop_measure(&duration, NULL);
457
458 if ((duration.duration.tv_sec * 1000 + duration.duration.tv_usec / 1000) > 3000) {
459 LOG_INFO("mflash: read %" PRIu32 "'th sectors", sect_num + i);
460 duration_start_measure(&duration);
461 }
462 }
463
464 return mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
465 }
466
467 static int mg_mflash_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
468 {
469 uint32_t quotient, residue, i;
470 uint8_t *buff_ptr = buff;
471 int ret = ERROR_OK;
472
473 quotient = sect_cnt >> 8;
474 residue = sect_cnt % 256;
475
476 for (i = 0; i < quotient; i++) {
477 LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : 0x%0lx", sect_num,
478 (unsigned long)buff_ptr);
479 ret = mg_mflash_do_read_sects(buff_ptr, sect_num, 256);
480 if (ret != ERROR_OK)
481 return ret;
482
483 sect_num += 256;
484 buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
485 }
486
487 if (residue) {
488 LOG_DEBUG("mflash: sect num : %" PRIx32 " buff : %0lx", sect_num,
489 (unsigned long)buff_ptr);
490 return mg_mflash_do_read_sects(buff_ptr, sect_num, residue);
491 }
492
493 return ret;
494 }
495
496 static int mg_mflash_do_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt,
497 mg_io_type_cmd cmd)
498 {
499 uint32_t i, address;
500 int ret;
501 target_t *target = mflash_bank->target;
502 uint8_t *buff_ptr = buff;
503 duration_t duration;
504
505 if ((ret = mg_dsk_io_cmd(sect_num, sect_cnt, cmd)) != ERROR_OK )
506 return ret;
507
508 address = mflash_bank->base + MG_BUFFER_OFFSET;
509
510 duration_start_measure(&duration);
511
512 for (i = 0; i < sect_cnt; i++) {
513 ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
514 if (ret != ERROR_OK)
515 return ret;
516
517 ret = target_write_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
518 if (ret != ERROR_OK)
519 return ret;
520
521 buff_ptr += MG_MFLASH_SECTOR_SIZE;
522
523 ret = target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_write);
524 if (ret != ERROR_OK)
525 return ret;
526
527 LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector write", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
528
529 duration_stop_measure(&duration, NULL);
530
531 if ((duration.duration.tv_sec * 1000 + duration.duration.tv_usec / 1000) > 3000) {
532 LOG_INFO("mflash: wrote %" PRIu32 "'th sectors", sect_num + i);
533 duration_start_measure(&duration);
534 }
535 }
536
537 if (cmd == mg_io_cmd_write)
538 ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
539 else
540 ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_LONG);
541
542 return ret;
543 }
544
545 static int mg_mflash_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
546 {
547 uint32_t quotient, residue, i;
548 uint8_t *buff_ptr = buff;
549 int ret = ERROR_OK;
550
551 quotient = sect_cnt >> 8;
552 residue = sect_cnt % 256;
553
554 for (i = 0; i < quotient; i++) {
555 LOG_DEBUG("mflash: sect num : %" PRIu32 "buff : %p", sect_num,
556 buff_ptr);
557 ret = mg_mflash_do_write_sects(buff_ptr, sect_num, 256, mg_io_cmd_write);
558 if (ret != ERROR_OK)
559 return ret;
560
561 sect_num += 256;
562 buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
563 }
564
565 if (residue) {
566 LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p", sect_num,
567 buff_ptr);
568 return mg_mflash_do_write_sects(buff_ptr, sect_num, residue, mg_io_cmd_write);
569 }
570
571 return ret;
572 }
573
574 static int mg_mflash_read (uint32_t addr, uint8_t *buff, uint32_t len)
575 {
576 uint8_t *buff_ptr = buff;
577 uint8_t sect_buff[MG_MFLASH_SECTOR_SIZE];
578 uint32_t cur_addr, next_sec_addr, end_addr, cnt, sect_num;
579 int ret = ERROR_OK;
580
581 cnt = 0;
582 cur_addr = addr;
583 end_addr = addr + len;
584
585 if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {
586
587 next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;
588 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
589 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
590 if (ret != ERROR_OK)
591 return ret;
592
593 if (end_addr < next_sec_addr) {
594 memcpy(buff_ptr, sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), end_addr - cur_addr);
595 LOG_DEBUG("mflash: copies %" PRIu32 " byte from sector offset 0x%8.8" PRIx32 "", end_addr - cur_addr, cur_addr);
596 cur_addr = end_addr;
597 } else {
598 memcpy(buff_ptr, sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), next_sec_addr - cur_addr);
599 LOG_DEBUG("mflash: copies %" PRIu32 " byte from sector offset 0x%8.8" PRIx32 "", next_sec_addr - cur_addr, cur_addr);
600 buff_ptr += (next_sec_addr - cur_addr);
601 cur_addr = next_sec_addr;
602 }
603 }
604
605 if (cur_addr < end_addr) {
606
607 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
608 next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;
609
610 while (next_sec_addr <= end_addr) {
611 cnt++;
612 next_sec_addr += MG_MFLASH_SECTOR_SIZE;
613 }
614
615 if (cnt)
616 if ((ret = mg_mflash_read_sects(buff_ptr, sect_num, cnt)) != ERROR_OK)
617 return ret;
618
619 buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;
620 cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;
621
622 if (cur_addr < end_addr) {
623
624 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
625 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
626 if (ret != ERROR_OK)
627 return ret;
628
629 memcpy(buff_ptr, sect_buff, end_addr - cur_addr);
630 LOG_DEBUG("mflash: copies %u byte", (unsigned)(end_addr - cur_addr));
631
632 }
633 }
634
635 return ret;
636 }
637
638 static int mg_mflash_write(uint32_t addr, uint8_t *buff, uint32_t len)
639 {
640 uint8_t *buff_ptr = buff;
641 uint8_t sect_buff[MG_MFLASH_SECTOR_SIZE];
642 uint32_t cur_addr, next_sec_addr, end_addr, cnt, sect_num;
643 int ret = ERROR_OK;
644
645 cnt = 0;
646 cur_addr = addr;
647 end_addr = addr + len;
648
649 if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {
650
651 next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;
652 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
653 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
654 if (ret != ERROR_OK)
655 return ret;
656
657 if (end_addr < next_sec_addr) {
658 memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), buff_ptr, end_addr - cur_addr);
659 LOG_DEBUG("mflash: copies %" PRIu32 " byte to sector offset 0x%8.8" PRIx32 "", end_addr - cur_addr, cur_addr);
660 cur_addr = end_addr;
661 } else {
662 memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), buff_ptr, next_sec_addr - cur_addr);
663 LOG_DEBUG("mflash: copies %" PRIu32 " byte to sector offset 0x%8.8" PRIx32 "", next_sec_addr - cur_addr, cur_addr);
664 buff_ptr += (next_sec_addr - cur_addr);
665 cur_addr = next_sec_addr;
666 }
667
668 ret = mg_mflash_write_sects(sect_buff, sect_num, 1);
669 if (ret != ERROR_OK)
670 return ret;
671 }
672
673 if (cur_addr < end_addr) {
674
675 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
676 next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;
677
678 while (next_sec_addr <= end_addr) {
679 cnt++;
680 next_sec_addr += MG_MFLASH_SECTOR_SIZE;
681 }
682
683 if (cnt)
684 if ((ret = mg_mflash_write_sects(buff_ptr, sect_num, cnt)) != ERROR_OK)
685 return ret;
686
687 buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;
688 cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;
689
690 if (cur_addr < end_addr) {
691
692 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
693 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
694 if (ret != ERROR_OK)
695 return ret;
696
697 memcpy(sect_buff, buff_ptr, end_addr - cur_addr);
698 LOG_DEBUG("mflash: copies %" PRIu32 " byte", end_addr - cur_addr);
699 ret = mg_mflash_write_sects(sect_buff, sect_num, 1);
700 }
701 }
702
703 return ret;
704 }
705
706 static int mg_write_cmd(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
707 {
708 uint32_t address, buf_cnt, cnt, res, i;
709 uint8_t *buffer;
710 fileio_t fileio;
711 duration_t duration;
712 char *duration_text;
713 int ret;
714
715 if (argc != 3) {
716 return ERROR_COMMAND_SYNTAX_ERROR;
717 }
718
719 address = strtoul(args[2], NULL, 0);
720
721 ret = fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY);
722 if (ret != ERROR_OK)
723 return ret;
724
725 buffer = malloc(MG_FILEIO_CHUNK);
726 if (!buffer) {
727 fileio_close(&fileio);
728 return ERROR_FAIL;
729 }
730
731 cnt = fileio.size / MG_FILEIO_CHUNK;
732 res = fileio.size % MG_FILEIO_CHUNK;
733
734 duration_start_measure(&duration);
735
736 for (i = 0; i < cnt; i++) {
737 if ((ret = fileio_read(&fileio, MG_FILEIO_CHUNK, buffer, &buf_cnt)) !=
738 ERROR_OK)
739 goto mg_write_cmd_err;
740 if ((ret = mg_mflash_write(address, buffer, MG_FILEIO_CHUNK)) != ERROR_OK)
741 goto mg_write_cmd_err;
742 address += MG_FILEIO_CHUNK;
743 }
744
745 if (res) {
746 if ((ret = fileio_read(&fileio, res, buffer, &buf_cnt)) != ERROR_OK)
747 goto mg_write_cmd_err;
748 if ((ret = mg_mflash_write(address, buffer, res)) != ERROR_OK)
749 goto mg_write_cmd_err;
750 }
751
752 duration_stop_measure(&duration, &duration_text);
753
754 command_print(cmd_ctx, "wrote %lli byte from file %s in %s (%f kB/s)",
755 fileio.size, args[1], duration_text,
756 (float)fileio.size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));
757
758 free(duration_text);
759 free(buffer);
760 fileio_close(&fileio);
761
762 return ERROR_OK;
763
764 mg_write_cmd_err:
765 duration_stop_measure(&duration, &duration_text);
766 free(duration_text);
767 free(buffer);
768 fileio_close(&fileio);
769
770 return ret;
771 }
772
773 static int mg_dump_cmd(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
774 {
775 uint32_t address, size_written, size, cnt, res, i;
776 uint8_t *buffer;
777 fileio_t fileio;
778 duration_t duration;
779 char *duration_text;
780 int ret;
781
782 if (argc != 4) {
783 return ERROR_COMMAND_SYNTAX_ERROR;
784 }
785
786 address = strtoul(args[2], NULL, 0);
787 size = strtoul(args[3], NULL, 0);
788
789 ret = fileio_open(&fileio, args[1], FILEIO_WRITE, FILEIO_BINARY);
790 if (ret != ERROR_OK)
791 return ret;
792
793 buffer = malloc(MG_FILEIO_CHUNK);
794 if (!buffer) {
795 fileio_close(&fileio);
796 return ERROR_FAIL;
797 }
798
799 cnt = size / MG_FILEIO_CHUNK;
800 res = size % MG_FILEIO_CHUNK;
801
802 duration_start_measure(&duration);
803
804 for (i = 0; i < cnt; i++) {
805 if ((ret = mg_mflash_read(address, buffer, MG_FILEIO_CHUNK)) != ERROR_OK)
806 goto mg_dump_cmd_err;
807 if ((ret = fileio_write(&fileio, MG_FILEIO_CHUNK, buffer, &size_written))
808 != ERROR_OK)
809 goto mg_dump_cmd_err;
810 address += MG_FILEIO_CHUNK;
811 }
812
813 if (res) {
814 if ((ret = mg_mflash_read(address, buffer, res)) != ERROR_OK)
815 goto mg_dump_cmd_err;
816 if ((ret = fileio_write(&fileio, res, buffer, &size_written)) != ERROR_OK)
817 goto mg_dump_cmd_err;
818 }
819
820 duration_stop_measure(&duration, &duration_text);
821
822 command_print(cmd_ctx, "dump image (address 0x%8.8" PRIx32 " size %" PRIu32 ") to file %s in %s (%f kB/s)",
823 address, size, args[1], duration_text,
824 (float)size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));
825
826 free(duration_text);
827 free(buffer);
828 fileio_close(&fileio);
829
830 return ERROR_OK;
831
832 mg_dump_cmd_err:
833 duration_stop_measure(&duration, &duration_text);
834 free(duration_text);
835 free(buffer);
836 fileio_close(&fileio);
837
838 return ret;
839 }
840
841 static int mg_set_feature(mg_feature_id feature, mg_feature_val config)
842 {
843 target_t *target = mflash_bank->target;
844 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
845 int ret;
846
847 if ((ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL))
848 != ERROR_OK)
849 return ret;
850
851 ret = target_write_u8(target, mg_task_reg + MG_REG_FEATURE, feature);
852 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, config);
853 ret |= target_write_u8(target, mg_task_reg + MG_REG_COMMAND,
854 mg_io_cmd_set_feature);
855
856 return ret;
857 }
858
859 static int mg_is_valid_pll(double XIN, int N, double CLK_OUT, int NO)
860 {
861 double v1 = XIN / N;
862 double v2 = CLK_OUT * NO;
863
864 if (v1 <1000000 || v1 > 15000000 || v2 < 100000000 || v2 > 500000000)
865 return ERROR_MG_INVALID_PLL;
866
867 return ERROR_OK;
868 }
869
870 static int mg_pll_get_M(unsigned short feedback_div)
871 {
872 int i, M;
873
874 for (i = 1, M=0; i < 512; i <<= 1, feedback_div >>= 1)
875 M += (feedback_div & 1) * i;
876
877 return M + 2;
878 }
879
880 static int mg_pll_get_N(unsigned char input_div)
881 {
882 int i, N;
883
884 for (i = 1, N = 0; i < 32; i <<= 1, input_div >>= 1)
885 N += (input_div & 1) * i;
886
887 return N + 2;
888 }
889
890 static int mg_pll_get_NO(unsigned char output_div)
891 {
892 int i, NO;
893
894 for (i = 0, NO = 1; i < 2; ++i, output_div >>= 1)
895 if (output_div & 1)
896 NO = NO << 1;
897
898 return NO;
899 }
900
901 static double mg_do_calc_pll(double XIN, mg_pll_t * p_pll_val, int is_approximate)
902 {
903 unsigned short i;
904 unsigned char j, k;
905 int M, N, NO;
906 double CLK_OUT;
907 double DIV = 1;
908 double ROUND = 0;
909
910 if (is_approximate) {
911 DIV = 1000000;
912 ROUND = 500000;
913 }
914
915 for (i = 0; i < MG_PLL_MAX_FEEDBACKDIV_VAL ; ++i) {
916 M = mg_pll_get_M(i);
917
918 for (j = 0; j < MG_PLL_MAX_INPUTDIV_VAL ; ++j) {
919 N = mg_pll_get_N(j);
920
921 for (k = 0; k < MG_PLL_MAX_OUTPUTDIV_VAL ; ++k) {
922 NO = mg_pll_get_NO(k);
923
924 CLK_OUT = XIN * ((double)M / N) / NO;
925
926 if ((int)((CLK_OUT+ROUND) / DIV)
927 == (int)(MG_PLL_CLK_OUT / DIV)) {
928 if (mg_is_valid_pll(XIN, N, CLK_OUT, NO) == ERROR_OK)
929 {
930 p_pll_val->lock_cyc = (int)(XIN * MG_PLL_STD_LOCKCYCLE / MG_PLL_STD_INPUTCLK);
931 p_pll_val->feedback_div = i;
932 p_pll_val->input_div = j;
933 p_pll_val->output_div = k;
934
935 return CLK_OUT;
936 }
937 }
938 }
939 }
940 }
941
942 return 0;
943 }
944
945 static double mg_calc_pll(double XIN, mg_pll_t *p_pll_val)
946 {
947 double CLK_OUT;
948
949 CLK_OUT = mg_do_calc_pll(XIN, p_pll_val, 0);
950
951 if (!CLK_OUT)
952 return mg_do_calc_pll(XIN, p_pll_val, 1);
953 else
954 return CLK_OUT;
955 }
956
957 static int mg_verify_interface(void)
958 {
959 uint16_t buff[MG_MFLASH_SECTOR_SIZE >> 1];
960 uint16_t i, j;
961 uint32_t address = mflash_bank->base + MG_BUFFER_OFFSET;
962 target_t *target = mflash_bank->target;
963 int ret;
964
965 for (j = 0; j < 10; j++) {
966 for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++)
967 buff[i] = i;
968
969 ret = target_write_memory(target, address, 2,
970 MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
971 if (ret != ERROR_OK)
972 return ret;
973
974 memset(buff, 0xff, MG_MFLASH_SECTOR_SIZE);
975
976 ret = target_read_memory(target, address, 2,
977 MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
978 if (ret != ERROR_OK)
979 return ret;
980
981 for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++) {
982 if (buff[i] != i) {
983 LOG_ERROR("mflash: verify interface fail");
984 return ERROR_MG_INTERFACE;
985 }
986 }
987 }
988
989 LOG_INFO("mflash: verify interface ok");
990 return ret;
991 }
992
993 static const char g_strSEG_SerialNum[20] = {
994 'G','m','n','i','-','e','e','S','g','a','e','l',
995 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
996 };
997
998 static const char g_strSEG_FWRev[8] = {
999 'F','X','L','T','2','v','0','.'
1000 };
1001
1002 static const char g_strSEG_ModelNum[40] = {
1003 'F','X','A','L','H','S','2',0x20,'0','0','s','7',
1004 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
1005 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
1006 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
1007 };
1008
1009 static void mg_gen_ataid(mg_io_type_drv_info *pSegIdDrvInfo)
1010 {
1011 /* b15 is ATA device(0) , b7 is Removable Media Device */
1012 pSegIdDrvInfo->general_configuration = 0x045A;
1013 /* 128MB : Cylinder=> 977 , Heads=> 8 , Sectors=> 32
1014 * 256MB : Cylinder=> 980 , Heads=> 16 , Sectors=> 32
1015 * 384MB : Cylinder=> 745 , Heads=> 16 , Sectors=> 63
1016 */
1017 pSegIdDrvInfo->number_of_cylinders = 0x02E9;
1018 pSegIdDrvInfo->reserved1 = 0x0;
1019 pSegIdDrvInfo->number_of_heads = 0x10;
1020 pSegIdDrvInfo->unformatted_bytes_per_track = 0x0;
1021 pSegIdDrvInfo->unformatted_bytes_per_sector = 0x0;
1022 pSegIdDrvInfo->sectors_per_track = 0x3F;
1023 pSegIdDrvInfo->vendor_unique1[0] = 0x000B;
1024 pSegIdDrvInfo->vendor_unique1[1] = 0x7570;
1025 pSegIdDrvInfo->vendor_unique1[2] = 0x8888;
1026
1027 memcpy(pSegIdDrvInfo->serial_number, (void *)g_strSEG_SerialNum,20);
1028 /* 0x2 : dual buffer */
1029 pSegIdDrvInfo->buffer_type = 0x2;
1030 /* buffer size : 2KB */
1031 pSegIdDrvInfo->buffer_sector_size = 0x800;
1032 pSegIdDrvInfo->number_of_ecc_bytes = 0;
1033
1034 memcpy(pSegIdDrvInfo->firmware_revision, (void *)g_strSEG_FWRev,8);
1035
1036 memcpy(pSegIdDrvInfo->model_number, (void *)g_strSEG_ModelNum,40);
1037
1038 pSegIdDrvInfo->maximum_block_transfer = 0x4;
1039 pSegIdDrvInfo->vendor_unique2 = 0x0;
1040 pSegIdDrvInfo->dword_io = 0x00;
1041 /* b11 : IORDY support(PIO Mode 4), b10 : Disable/Enbale IORDY
1042 * b9 : LBA support, b8 : DMA mode support
1043 */
1044 pSegIdDrvInfo->capabilities = 0x1 << 9;
1045
1046 pSegIdDrvInfo->reserved2 = 0x4000;
1047 pSegIdDrvInfo->vendor_unique3 = 0x00;
1048 /* PIOMode-2 support */
1049 pSegIdDrvInfo->pio_cycle_timing_mode = 0x02;
1050 pSegIdDrvInfo->vendor_unique4 = 0x00;
1051 /* MultiWord-2 support */
1052 pSegIdDrvInfo->dma_cycle_timing_mode = 0x00;
1053 /* b1 : word64~70 is valid
1054 * b0 : word54~58 are valid and reflect the current numofcyls,heads,sectors
1055 * b2 : If device supports Ultra DMA , set to one to vaildate word88
1056 */
1057 pSegIdDrvInfo->translation_fields_valid = (0x1 << 1) | (0x1 << 0);
1058 pSegIdDrvInfo->number_of_current_cylinders = 0x02E9;
1059 pSegIdDrvInfo->number_of_current_heads = 0x10;
1060 pSegIdDrvInfo->current_sectors_per_track = 0x3F;
1061 pSegIdDrvInfo->current_sector_capacity_lo = 0x7570;
1062 pSegIdDrvInfo->current_sector_capacity_hi = 0x000B;
1063
1064 pSegIdDrvInfo->multi_sector_count = 0x04;
1065 /* b8 : Multiple secotr setting valid , b[7:0] num of secotrs per block */
1066 pSegIdDrvInfo->multi_sector_setting_valid = 0x01;
1067 pSegIdDrvInfo->total_user_addressable_sectors_lo = 0x7570;
1068 pSegIdDrvInfo->total_user_addressable_sectors_hi = 0x000B;
1069 pSegIdDrvInfo->single_dma_modes_supported = 0x00;
1070 pSegIdDrvInfo->single_dma_transfer_active = 0x00;
1071 /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
1072 pSegIdDrvInfo->multi_dma_modes_supported = (0x1 << 0);
1073 /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
1074 pSegIdDrvInfo->multi_dma_transfer_active = (0x1 << 0);
1075 /* b0 : PIO Mode-3 support, b1 : PIO Mode-4 support */
1076 pSegIdDrvInfo->adv_pio_mode = 0x00;
1077 /* 480(0x1E0)nsec for Multi-word DMA mode0
1078 * 150(0x96) nsec for Multi-word DMA mode1
1079 * 120(0x78) nsec for Multi-word DMA mode2
1080 */
1081 pSegIdDrvInfo->min_dma_cyc = 0x1E0;
1082 pSegIdDrvInfo->recommend_dma_cyc = 0x1E0;
1083 pSegIdDrvInfo->min_pio_cyc_no_iordy = 0x1E0;
1084 pSegIdDrvInfo->min_pio_cyc_with_iordy = 0x1E0;
1085 memset((void *)pSegIdDrvInfo->reserved3, 0x00, 22);
1086 /* b7 : ATA/ATAPI-7 ,b6 : ATA/ATAPI-6 ,b5 : ATA/ATAPI-5,b4 : ATA/ATAPI-4 */
1087 pSegIdDrvInfo->major_ver_num = 0x7E;
1088 /* 0x1C : ATA/ATAPI-6 T13 1532D revision1 */
1089 pSegIdDrvInfo->minor_ver_num = 0x19;
1090 /* NOP/READ BUFFER/WRITE BUFFER/Power management feature set support */
1091 pSegIdDrvInfo->feature_cmd_set_suprt0 = 0x7068;
1092 /* Features/command set is valid/Advanced Pwr management/CFA feature set
1093 * not support
1094 */
1095 pSegIdDrvInfo->feature_cmd_set_suprt1 = 0x400C;
1096 pSegIdDrvInfo->feature_cmd_set_suprt2 = 0x4000;
1097 /* READ/WRITE BUFFER/PWR Management enable */
1098 pSegIdDrvInfo->feature_cmd_set_en0 = 0x7000;
1099 /* CFA feature is disabled / Advancde power management disable */
1100 pSegIdDrvInfo->feature_cmd_set_en1 = 0x0;
1101 pSegIdDrvInfo->feature_cmd_set_en2 = 0x4000;
1102 pSegIdDrvInfo->reserved4 = 0x0;
1103 /* 0x1 * 2minutes */
1104 pSegIdDrvInfo->req_time_for_security_er_done = 0x19;
1105 pSegIdDrvInfo->req_time_for_enhan_security_er_done = 0x19;
1106 /* Advanced power management level 1 */
1107 pSegIdDrvInfo->adv_pwr_mgm_lvl_val = 0x0;
1108 pSegIdDrvInfo->reserved5 = 0x0;
1109 memset((void *)pSegIdDrvInfo->reserved6, 0x00, 68);
1110 /* Security mode feature is disabled */
1111 pSegIdDrvInfo->security_stas = 0x0;
1112 memset((void *)pSegIdDrvInfo->vendor_uniq_bytes, 0x00, 62);
1113 /* CFA power mode 1 support in maximum 200mA */
1114 pSegIdDrvInfo->cfa_pwr_mode = 0x0100;
1115 memset((void *)pSegIdDrvInfo->reserved7, 0x00, 190);
1116 }
1117
1118 static int mg_storage_config(void)
1119 {
1120 uint8_t buff[512];
1121 int ret;
1122
1123 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1124 != ERROR_OK)
1125 return ret;
1126
1127 mg_gen_ataid((mg_io_type_drv_info *)buff);
1128
1129 if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_stgdrvinfo))
1130 != ERROR_OK)
1131 return ret;
1132
1133 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1134 != ERROR_OK)
1135 return ret;
1136
1137 LOG_INFO("mflash: storage config ok");
1138 return ret;
1139 }
1140
1141 static int mg_boot_config(void)
1142 {
1143 uint8_t buff[512];
1144 int ret;
1145
1146 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1147 != ERROR_OK)
1148 return ret;
1149
1150 memset(buff, 0xff, 512);
1151
1152 buff[0] = mg_op_mode_snd; /* operation mode */
1153 buff[1] = MG_UNLOCK_OTP_AREA;
1154 buff[2] = 4; /* boot size */
1155 *((uint32_t *)(buff + 4)) = 0; /* XIP size */
1156
1157 if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_xipinfo))
1158 != ERROR_OK)
1159 return ret;
1160
1161 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1162 != ERROR_OK)
1163 return ret;
1164
1165 LOG_INFO("mflash: boot config ok");
1166 return ret;
1167 }
1168
1169 static int mg_set_pll(mg_pll_t *pll)
1170 {
1171 uint8_t buff[512];
1172 int ret;
1173
1174 memset(buff, 0xff, 512);
1175 /* PLL Lock cycle and Feedback 9bit Divider */
1176 memcpy(buff, &pll->lock_cyc, sizeof(uint32_t));
1177 memcpy(buff + 4, &pll->feedback_div, sizeof(uint16_t));
1178 buff[6] = pll->input_div; /* PLL Input 5bit Divider */
1179 buff[7] = pll->output_div; /* PLL Output Divider */
1180
1181 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1182 != ERROR_OK)
1183 return ret;
1184
1185 if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_wr_pll))
1186 != ERROR_OK)
1187 return ret;
1188
1189 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1190 != ERROR_OK)
1191 return ret;
1192
1193 LOG_INFO("mflash: set pll ok");
1194 return ret;
1195 }
1196
1197 static int mg_erase_nand(void)
1198 {
1199 int ret;
1200
1201 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1202 != ERROR_OK)
1203 return ret;
1204
1205 if ((ret = mg_mflash_do_write_sects(NULL, 0, 0, mg_vcmd_purge_nand))
1206 != ERROR_OK)
1207 return ret;
1208
1209 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1210 != ERROR_OK)
1211 return ret;
1212
1213 LOG_INFO("mflash: erase nand ok");
1214 return ret;
1215 }
1216
1217 int mg_config_cmd(struct command_context_s *cmd_ctx, char *cmd,
1218 char **args, int argc)
1219 {
1220 double fin, fout;
1221 mg_pll_t pll;
1222 int ret;
1223
1224 if ((ret = mg_verify_interface()) != ERROR_OK)
1225 return ret;
1226
1227 if ((ret = mg_mflash_rst()) != ERROR_OK)
1228 return ret;
1229
1230 switch (argc) {
1231 case 2:
1232 if (!strcmp(args[1], "boot"))
1233 return mg_boot_config();
1234 else if (!strcmp(args[1], "storage"))
1235 return mg_storage_config();
1236 else
1237 return ERROR_COMMAND_NOTFOUND;
1238 break;
1239 case 3:
1240 if (!strcmp(args[1], "pll")) {
1241 fin = strtoul(args[2], NULL, 0);
1242
1243 if (fin > MG_PLL_CLK_OUT) {
1244 LOG_ERROR("mflash: input freq. is too large");
1245 return ERROR_MG_INVALID_OSC;
1246 }
1247
1248 fout = mg_calc_pll(fin, &pll);
1249
1250 if (!fout) {
1251 LOG_ERROR("mflash: cannot generate valid pll");
1252 return ERROR_MG_INVALID_PLL;
1253 }
1254
1255 LOG_INFO("mflash: Fout=%" PRIu32 " Hz, feedback=%u,"
1256 "indiv=%u, outdiv=%u, lock=%u",
1257 (uint32_t)fout, pll.feedback_div,
1258 pll.input_div, pll.output_div,
1259 pll.lock_cyc);
1260
1261 if ((ret = mg_erase_nand()) != ERROR_OK)
1262 return ret;
1263
1264 return mg_set_pll(&pll);
1265 } else
1266 return ERROR_COMMAND_NOTFOUND;
1267 break;
1268 default:
1269 return ERROR_COMMAND_SYNTAX_ERROR;
1270 }
1271 }
1272
1273 int mflash_init_drivers(struct command_context_s *cmd_ctx)
1274 {
1275 if (mflash_bank) {
1276 register_command(cmd_ctx, mflash_cmd, "probe", mg_probe_cmd, COMMAND_EXEC, NULL);
1277 register_command(cmd_ctx, mflash_cmd, "write", mg_write_cmd, COMMAND_EXEC,
1278 "mflash write <num> <file> <address>");
1279 register_command(cmd_ctx, mflash_cmd, "dump", mg_dump_cmd, COMMAND_EXEC,
1280 "mflash dump <num> <file> <address> <size>");
1281 register_command(cmd_ctx, mflash_cmd, "config", mg_config_cmd,
1282 COMMAND_EXEC, "mflash config <num> <stage>");
1283 }
1284
1285 return ERROR_OK;
1286 }
1287
1288 static int mg_bank_cmd(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1289 {
1290 target_t *target;
1291 char *str;
1292 int i;
1293
1294 if (argc < 4)
1295 {
1296 return ERROR_COMMAND_SYNTAX_ERROR;
1297 }
1298
1299 if ((target = get_target(args[3])) == NULL)
1300 {
1301 LOG_ERROR("target '%s' not defined", args[3]);
1302 return ERROR_FAIL;
1303 }
1304
1305 mflash_bank = calloc(sizeof(mflash_bank_t), 1);
1306 mflash_bank->base = strtoul(args[1], NULL, 0);
1307 mflash_bank->rst_pin.num = strtoul(args[2], &str, 0);
1308 if (*str)
1309 mflash_bank->rst_pin.port[0] = (uint16_t)tolower(str[0]);
1310
1311 mflash_bank->target = target;
1312
1313 for (i = 0; mflash_gpio[i] ; i++) {
1314 if (! strcmp(mflash_gpio[i]->name, args[0])) {
1315 mflash_bank->gpio_drv = mflash_gpio[i];
1316 }
1317 }
1318
1319 if (! mflash_bank->gpio_drv) {
1320 LOG_ERROR("%s is unsupported soc", args[0]);
1321 return ERROR_MG_UNSUPPORTED_SOC;
1322 }
1323
1324 return ERROR_OK;
1325 }
1326
1327 int mflash_register_commands(struct command_context_s *cmd_ctx)
1328 {
1329 mflash_cmd = register_command(cmd_ctx, NULL, "mflash", NULL, COMMAND_ANY, NULL);
1330 register_command(cmd_ctx, mflash_cmd, "bank", mg_bank_cmd, COMMAND_CONFIG,
1331 "mflash bank <soc> <base> <RST pin> <target #>");
1332 return ERROR_OK;
1333 }

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)