MFLASH: help/usage updates
[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 <target/target.h>
26 #include <helper/time_support.h>
27 #include <helper/fileio.h>
28 #include <helper/log.h>
29
30
31 static int s3c2440_set_gpio_to_output (struct mflash_gpio_num gpio);
32 static int s3c2440_set_gpio_output_val (struct mflash_gpio_num gpio, uint8_t val);
33 static int pxa270_set_gpio_to_output (struct mflash_gpio_num gpio);
34 static int pxa270_set_gpio_output_val (struct mflash_gpio_num gpio, uint8_t val);
35
36 static struct mflash_bank *mflash_bank;
37
38 static struct mflash_gpio_drv pxa270_gpio = {
39 .name = "pxa270",
40 .set_gpio_to_output = pxa270_set_gpio_to_output,
41 .set_gpio_output_val = pxa270_set_gpio_output_val
42 };
43
44 static struct mflash_gpio_drv s3c2440_gpio = {
45 .name = "s3c2440",
46 .set_gpio_to_output = s3c2440_set_gpio_to_output,
47 .set_gpio_output_val = s3c2440_set_gpio_output_val
48 };
49
50 static struct mflash_gpio_drv *mflash_gpio[] =
51 {
52 &pxa270_gpio,
53 &s3c2440_gpio,
54 NULL
55 };
56
57 #define PXA270_GAFR0_L 0x40E00054
58 #define PXA270_GAFR3_U 0x40E00070
59 #define PXA270_GAFR3_U_RESERVED_BITS 0xfffc0000u
60 #define PXA270_GPDR0 0x40E0000C
61 #define PXA270_GPDR3 0x40E0010C
62 #define PXA270_GPDR3_RESERVED_BITS 0xfe000000u
63 #define PXA270_GPSR0 0x40E00018
64 #define PXA270_GPCR0 0x40E00024
65
66 static int pxa270_set_gpio_to_output (struct mflash_gpio_num gpio)
67 {
68 uint32_t addr, value, mask;
69 struct target *target = mflash_bank->target;
70 int ret;
71
72 /* remove alternate function. */
73 mask = 0x3u << (gpio.num & 0xF)*2;
74
75 addr = PXA270_GAFR0_L + (gpio.num >> 4) * 4;
76
77 if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
78 return ret;
79
80 value &= ~mask;
81 if (addr == PXA270_GAFR3_U)
82 value &= ~PXA270_GAFR3_U_RESERVED_BITS;
83
84 if ((ret = target_write_u32(target, addr, value)) != ERROR_OK)
85 return ret;
86
87 /* set direction to output */
88 mask = 0x1u << (gpio.num & 0x1F);
89
90 addr = PXA270_GPDR0 + (gpio.num >> 5) * 4;
91
92 if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
93 return ret;
94
95 value |= mask;
96 if (addr == PXA270_GPDR3)
97 value &= ~PXA270_GPDR3_RESERVED_BITS;
98
99 ret = target_write_u32(target, addr, value);
100 return ret;
101 }
102
103 static int pxa270_set_gpio_output_val (struct mflash_gpio_num gpio, uint8_t val)
104 {
105 uint32_t addr, value, mask;
106 struct target *target = mflash_bank->target;
107 int ret;
108
109 mask = 0x1u << (gpio.num & 0x1F);
110
111 if (val) {
112 addr = PXA270_GPSR0 + (gpio.num >> 5) * 4;
113 } else {
114 addr = PXA270_GPCR0 + (gpio.num >> 5) * 4;
115 }
116
117 if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
118 return ret;
119
120 value |= mask;
121
122 ret = target_write_u32(target, addr, value);
123
124 return ret;
125 }
126
127 #define S3C2440_GPACON 0x56000000
128 #define S3C2440_GPADAT 0x56000004
129 #define S3C2440_GPJCON 0x560000d0
130 #define S3C2440_GPJDAT 0x560000d4
131
132 static int s3c2440_set_gpio_to_output (struct mflash_gpio_num gpio)
133 {
134 uint32_t data, mask, gpio_con;
135 struct target *target = mflash_bank->target;
136 int ret;
137
138 if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') {
139 gpio_con = S3C2440_GPACON + (gpio.port[0] - 'a') * 0x10;
140 } else if (gpio.port[0] == 'j') {
141 gpio_con = S3C2440_GPJCON;
142 } else {
143 LOG_ERROR("mflash: invalid port %d%s", gpio.num, gpio.port);
144 return ERROR_INVALID_ARGUMENTS;
145 }
146
147 ret = target_read_u32(target, gpio_con, &data);
148
149 if (ret == ERROR_OK) {
150 if (gpio.port[0] == 'a') {
151 mask = 1 << gpio.num;
152 data &= ~mask;
153 } else {
154 mask = 3 << gpio.num * 2;
155 data &= ~mask;
156 data |= (1 << gpio.num * 2);
157 }
158
159 ret = target_write_u32(target, gpio_con, data);
160 }
161 return ret;
162 }
163
164 static int s3c2440_set_gpio_output_val (struct mflash_gpio_num gpio, uint8_t val)
165 {
166 uint32_t data, mask, gpio_dat;
167 struct target *target = mflash_bank->target;
168 int ret;
169
170 if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') {
171 gpio_dat = S3C2440_GPADAT + (gpio.port[0] - 'a') * 0x10;
172 } else if (gpio.port[0] == 'j') {
173 gpio_dat = S3C2440_GPJDAT;
174 } else {
175 LOG_ERROR("mflash: invalid port %d%s", gpio.num, gpio.port);
176 return ERROR_INVALID_ARGUMENTS;
177 }
178
179 ret = target_read_u32(target, gpio_dat, &data);
180
181 if (ret == ERROR_OK) {
182 mask = 1 << gpio.num;
183 if (val)
184 data |= mask;
185 else
186 data &= ~mask;
187
188 ret = target_write_u32(target, gpio_dat, data);
189 }
190 return ret;
191 }
192
193 static int mg_hdrst(uint8_t level)
194 {
195 return mflash_bank->gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, level);
196 }
197
198 static int mg_init_gpio (void)
199 {
200 int ret;
201 struct mflash_gpio_drv *gpio_drv = mflash_bank->gpio_drv;
202
203 ret = gpio_drv->set_gpio_to_output(mflash_bank->rst_pin);
204 if (ret != ERROR_OK)
205 return ret;
206
207 ret = gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, 1);
208
209 return ret;
210 }
211
212 static int mg_dsk_wait(mg_io_type_wait wait, uint32_t time)
213 {
214 uint8_t status, error;
215 struct target *target = mflash_bank->target;
216 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
217 int ret;
218 long long t = 0;
219
220 struct duration bench;
221 duration_start(&bench);
222
223 while (time) {
224
225 ret = target_read_u8(target, mg_task_reg + MG_REG_STATUS, &status);
226 if (ret != ERROR_OK)
227 return ret;
228
229 if (status & mg_io_rbit_status_busy)
230 {
231 if (wait == mg_io_wait_bsy)
232 return ERROR_OK;
233 } else {
234 switch (wait)
235 {
236 case mg_io_wait_not_bsy:
237 return ERROR_OK;
238 case mg_io_wait_rdy_noerr:
239 if (status & mg_io_rbit_status_ready)
240 return ERROR_OK;
241 break;
242 case mg_io_wait_drq_noerr:
243 if (status & mg_io_rbit_status_data_req)
244 return ERROR_OK;
245 break;
246 default:
247 break;
248 }
249
250 /* Now we check the error condition! */
251 if (status & mg_io_rbit_status_error)
252 {
253 ret = target_read_u8(target, mg_task_reg + MG_REG_ERROR, &error);
254 if (ret != ERROR_OK)
255 return ret;
256
257 LOG_ERROR("mflash: io error 0x%02x", error);
258
259 return ERROR_MG_IO;
260 }
261
262 switch (wait)
263 {
264 case mg_io_wait_rdy:
265 if (status & mg_io_rbit_status_ready)
266 return ERROR_OK;
267
268 case mg_io_wait_drq:
269 if (status & mg_io_rbit_status_data_req)
270 return ERROR_OK;
271
272 default:
273 break;
274 }
275 }
276
277 ret = duration_measure(&bench);
278 if (ERROR_OK == ret)
279 t = duration_elapsed(&bench) * 1000.0;
280 else
281 LOG_ERROR("mflash: duration measurement failed: %d", ret);
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 struct target *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 struct target *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 struct target *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 ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
346 if (ret != ERROR_OK)
347 return ret;
348
349 LOG_INFO("mflash: read drive info");
350
351 if (! mflash_bank->drv_info)
352 mflash_bank->drv_info = malloc(sizeof(struct mg_drv_info));
353
354 ret = target_read_memory(target, mg_buff, 2,
355 sizeof(mg_io_type_drv_info) >> 1,
356 (uint8_t *)&mflash_bank->drv_info->drv_id);
357 if (ret != ERROR_OK)
358 return ret;
359
360 mflash_bank->drv_info->tot_sects = (uint32_t)(mflash_bank->drv_info->drv_id.total_user_addressable_sectors_hi << 16)
361 + mflash_bank->drv_info->drv_id.total_user_addressable_sectors_lo;
362
363 return target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_read);
364 }
365
366 static int mg_mflash_rst(void)
367 {
368 int ret;
369
370 if ((ret = mg_init_gpio()) != ERROR_OK)
371 return ret;
372
373 if ((ret = mg_hdrst(0)) != ERROR_OK)
374 return ret;
375
376 if ((ret = mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG)) != ERROR_OK)
377 return ret;
378
379 if ((ret = mg_hdrst(1)) != ERROR_OK)
380 return ret;
381
382 if ((ret = mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG)) != ERROR_OK)
383 return ret;
384
385 if ((ret = mg_dsk_srst(1)) != ERROR_OK)
386 return ret;
387
388 if ((ret = mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG)) != ERROR_OK)
389 return ret;
390
391 if ((ret = mg_dsk_srst(0)) != ERROR_OK)
392 return ret;
393
394 if ((ret = mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG)) != ERROR_OK)
395 return ret;
396
397 LOG_INFO("mflash: reset ok");
398
399 return ERROR_OK;
400 }
401
402 static int mg_mflash_probe(void)
403 {
404 int ret;
405
406 if ((ret = mg_mflash_rst()) != ERROR_OK)
407 return ret;
408
409 return mg_dsk_drv_info();
410 }
411
412 COMMAND_HANDLER(mg_probe_cmd)
413 {
414 int ret;
415
416 ret = mg_mflash_probe();
417
418 if (ret == ERROR_OK) {
419 command_print(CMD_CTX, "mflash (total %" PRIu32 " sectors) found at 0x%8.8" PRIx32 "",
420 mflash_bank->drv_info->tot_sects, mflash_bank->base);
421 }
422
423 return ret;
424 }
425
426 static int mg_mflash_do_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
427 {
428 uint32_t i, address;
429 int ret;
430 struct target *target = mflash_bank->target;
431 uint8_t *buff_ptr = buff;
432
433 if ((ret = mg_dsk_io_cmd(sect_num, sect_cnt, mg_io_cmd_read)) != ERROR_OK)
434 return ret;
435
436 address = mflash_bank->base + MG_BUFFER_OFFSET;
437
438 struct duration bench;
439 duration_start(&bench);
440
441 for (i = 0; i < sect_cnt; i++) {
442 ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
443 if (ret != ERROR_OK)
444 return ret;
445
446 ret = target_read_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
447 if (ret != ERROR_OK)
448 return ret;
449
450 buff_ptr += MG_MFLASH_SECTOR_SIZE;
451
452 ret = target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_read);
453 if (ret != ERROR_OK)
454 return ret;
455
456 LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector read", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
457
458 ret = duration_measure(&bench);
459 if ((ERROR_OK == ret) && (duration_elapsed(&bench) > 3)) {
460 LOG_INFO("mflash: read %" PRIu32 "'th sectors", sect_num + i);
461 duration_start(&bench);
462 }
463 }
464
465 return mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
466 }
467
468 static int mg_mflash_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
469 {
470 uint32_t quotient, residue, i;
471 uint8_t *buff_ptr = buff;
472 int ret = ERROR_OK;
473
474 quotient = sect_cnt >> 8;
475 residue = sect_cnt % 256;
476
477 for (i = 0; i < quotient; i++) {
478 LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p",
479 sect_num, buff_ptr);
480 ret = mg_mflash_do_read_sects(buff_ptr, sect_num, 256);
481 if (ret != ERROR_OK)
482 return ret;
483
484 sect_num += 256;
485 buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
486 }
487
488 if (residue) {
489 LOG_DEBUG("mflash: sect num : %" PRIx32 " buff : %p",
490 sect_num, buff_ptr);
491 return mg_mflash_do_read_sects(buff_ptr, sect_num, residue);
492 }
493
494 return ret;
495 }
496
497 static int mg_mflash_do_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt,
498 mg_io_type_cmd cmd)
499 {
500 uint32_t i, address;
501 int ret;
502 struct target *target = mflash_bank->target;
503 uint8_t *buff_ptr = buff;
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 struct duration bench;
511 duration_start(&bench);
512
513 for (i = 0; i < sect_cnt; i++) {
514 ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
515 if (ret != ERROR_OK)
516 return ret;
517
518 ret = target_write_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
519 if (ret != ERROR_OK)
520 return ret;
521
522 buff_ptr += MG_MFLASH_SECTOR_SIZE;
523
524 ret = target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_write);
525 if (ret != ERROR_OK)
526 return ret;
527
528 LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector write", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
529
530 ret = duration_measure(&bench);
531 if ((ERROR_OK == ret) && (duration_elapsed(&bench) > 3)) {
532 LOG_INFO("mflash: wrote %" PRIu32 "'th sectors", sect_num + i);
533 duration_start(&bench);
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 COMMAND_HANDLER(mg_write_cmd)
707 {
708 uint32_t address, cnt, res, i;
709 uint8_t *buffer;
710 struct fileio fileio;
711 int ret;
712
713 if (CMD_ARGC != 3) {
714 return ERROR_COMMAND_SYNTAX_ERROR;
715 }
716
717 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
718
719 ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY);
720 if (ret != ERROR_OK)
721 return ret;
722
723 buffer = malloc(MG_FILEIO_CHUNK);
724 if (!buffer) {
725 fileio_close(&fileio);
726 return ERROR_FAIL;
727 }
728
729 cnt = fileio.size / MG_FILEIO_CHUNK;
730 res = fileio.size % MG_FILEIO_CHUNK;
731
732 struct duration bench;
733 duration_start(&bench);
734
735 size_t buf_cnt;
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 if (duration_measure(&bench) == ERROR_OK)
753 {
754 command_print(CMD_CTX, "wrote %ld bytes from file %s "
755 "in %fs (%0.3f kB/s)", (long)fileio.size, CMD_ARGV[1],
756 duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
757 }
758
759 free(buffer);
760 fileio_close(&fileio);
761
762 return ERROR_OK;
763
764 mg_write_cmd_err:
765 free(buffer);
766 fileio_close(&fileio);
767
768 return ret;
769 }
770
771 COMMAND_HANDLER(mg_dump_cmd)
772 {
773 uint32_t address, size, cnt, res, i;
774 uint8_t *buffer;
775 struct fileio fileio;
776 int ret;
777
778 if (CMD_ARGC != 4) {
779 return ERROR_COMMAND_SYNTAX_ERROR;
780 }
781
782 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
783 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], size);
784
785 ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_WRITE, FILEIO_BINARY);
786 if (ret != ERROR_OK)
787 return ret;
788
789 buffer = malloc(MG_FILEIO_CHUNK);
790 if (!buffer) {
791 fileio_close(&fileio);
792 return ERROR_FAIL;
793 }
794
795 cnt = size / MG_FILEIO_CHUNK;
796 res = size % MG_FILEIO_CHUNK;
797
798 struct duration bench;
799 duration_start(&bench);
800
801 size_t size_written;
802 for (i = 0; i < cnt; i++) {
803 if ((ret = mg_mflash_read(address, buffer, MG_FILEIO_CHUNK)) != ERROR_OK)
804 goto mg_dump_cmd_err;
805 if ((ret = fileio_write(&fileio, MG_FILEIO_CHUNK, buffer, &size_written))
806 != ERROR_OK)
807 goto mg_dump_cmd_err;
808 address += MG_FILEIO_CHUNK;
809 }
810
811 if (res) {
812 if ((ret = mg_mflash_read(address, buffer, res)) != ERROR_OK)
813 goto mg_dump_cmd_err;
814 if ((ret = fileio_write(&fileio, res, buffer, &size_written)) != ERROR_OK)
815 goto mg_dump_cmd_err;
816 }
817
818 if (duration_measure(&bench) == ERROR_OK)
819 {
820 command_print(CMD_CTX, "dump image (address 0x%8.8" PRIx32 " "
821 "size %" PRIu32 ") to file %s in %fs (%0.3f kB/s)",
822 address, size, CMD_ARGV[1],
823 duration_elapsed(&bench), duration_kbps(&bench, size));
824 }
825
826 free(buffer);
827 fileio_close(&fileio);
828
829 return ERROR_OK;
830
831 mg_dump_cmd_err:
832 free(buffer);
833 fileio_close(&fileio);
834
835 return ret;
836 }
837
838 static int mg_set_feature(mg_feature_id feature, mg_feature_val config)
839 {
840 struct target *target = mflash_bank->target;
841 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
842 int ret;
843
844 if ((ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL))
845 != ERROR_OK)
846 return ret;
847
848 ret = target_write_u8(target, mg_task_reg + MG_REG_FEATURE, feature);
849 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, config);
850 ret |= target_write_u8(target, mg_task_reg + MG_REG_COMMAND,
851 mg_io_cmd_set_feature);
852
853 return ret;
854 }
855
856 static int mg_is_valid_pll(double XIN, int N, double CLK_OUT, int NO)
857 {
858 double v1 = XIN / N;
859 double v2 = CLK_OUT * NO;
860
861 if (v1 <1000000 || v1 > 15000000 || v2 < 100000000 || v2 > 500000000)
862 return ERROR_MG_INVALID_PLL;
863
864 return ERROR_OK;
865 }
866
867 static int mg_pll_get_M(unsigned short feedback_div)
868 {
869 int i, M;
870
871 for (i = 1, M = 0; i < 512; i <<= 1, feedback_div >>= 1)
872 M += (feedback_div & 1) * i;
873
874 return M + 2;
875 }
876
877 static int mg_pll_get_N(unsigned char input_div)
878 {
879 int i, N;
880
881 for (i = 1, N = 0; i < 32; i <<= 1, input_div >>= 1)
882 N += (input_div & 1) * i;
883
884 return N + 2;
885 }
886
887 static int mg_pll_get_NO(unsigned char output_div)
888 {
889 int i, NO;
890
891 for (i = 0, NO = 1; i < 2; ++i, output_div >>= 1)
892 if (output_div & 1)
893 NO = NO << 1;
894
895 return NO;
896 }
897
898 static double mg_do_calc_pll(double XIN, mg_pll_t * p_pll_val, int is_approximate)
899 {
900 unsigned short i;
901 unsigned char j, k;
902 int M, N, NO;
903 double CLK_OUT;
904 double DIV = 1;
905 double ROUND = 0;
906
907 if (is_approximate) {
908 DIV = 1000000;
909 ROUND = 500000;
910 }
911
912 for (i = 0; i < MG_PLL_MAX_FEEDBACKDIV_VAL ; ++i) {
913 M = mg_pll_get_M(i);
914
915 for (j = 0; j < MG_PLL_MAX_INPUTDIV_VAL ; ++j) {
916 N = mg_pll_get_N(j);
917
918 for (k = 0; k < MG_PLL_MAX_OUTPUTDIV_VAL ; ++k) {
919 NO = mg_pll_get_NO(k);
920
921 CLK_OUT = XIN * ((double)M / N) / NO;
922
923 if ((int)((CLK_OUT + ROUND) / DIV)
924 == (int)(MG_PLL_CLK_OUT / DIV)) {
925 if (mg_is_valid_pll(XIN, N, CLK_OUT, NO) == ERROR_OK)
926 {
927 p_pll_val->lock_cyc = (int)(XIN * MG_PLL_STD_LOCKCYCLE / MG_PLL_STD_INPUTCLK);
928 p_pll_val->feedback_div = i;
929 p_pll_val->input_div = j;
930 p_pll_val->output_div = k;
931
932 return CLK_OUT;
933 }
934 }
935 }
936 }
937 }
938
939 return 0;
940 }
941
942 static double mg_calc_pll(double XIN, mg_pll_t *p_pll_val)
943 {
944 double CLK_OUT;
945
946 CLK_OUT = mg_do_calc_pll(XIN, p_pll_val, 0);
947
948 if (!CLK_OUT)
949 return mg_do_calc_pll(XIN, p_pll_val, 1);
950 else
951 return CLK_OUT;
952 }
953
954 static int mg_verify_interface(void)
955 {
956 uint16_t buff[MG_MFLASH_SECTOR_SIZE >> 1];
957 uint16_t i, j;
958 uint32_t address = mflash_bank->base + MG_BUFFER_OFFSET;
959 struct target *target = mflash_bank->target;
960 int ret;
961
962 for (j = 0; j < 10; j++) {
963 for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++)
964 buff[i] = i;
965
966 ret = target_write_memory(target, address, 2,
967 MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
968 if (ret != ERROR_OK)
969 return ret;
970
971 memset(buff, 0xff, MG_MFLASH_SECTOR_SIZE);
972
973 ret = target_read_memory(target, address, 2,
974 MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
975 if (ret != ERROR_OK)
976 return ret;
977
978 for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++) {
979 if (buff[i] != i) {
980 LOG_ERROR("mflash: verify interface fail");
981 return ERROR_MG_INTERFACE;
982 }
983 }
984 }
985
986 LOG_INFO("mflash: verify interface ok");
987 return ret;
988 }
989
990 static const char g_strSEG_SerialNum[20] = {
991 'G','m','n','i','-','e','e','S','g','a','e','l',
992 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
993 };
994
995 static const char g_strSEG_FWRev[8] = {
996 'F','X','L','T','2','v','0','.'
997 };
998
999 static const char g_strSEG_ModelNum[40] = {
1000 'F','X','A','L','H','S','2',0x20,'0','0','s','7',
1001 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
1002 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
1003 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
1004 };
1005
1006 static void mg_gen_ataid(mg_io_type_drv_info *pSegIdDrvInfo)
1007 {
1008 /* b15 is ATA device(0) , b7 is Removable Media Device */
1009 pSegIdDrvInfo->general_configuration = 0x045A;
1010 /* 128MB : Cylinder=> 977 , Heads=> 8 , Sectors=> 32
1011 * 256MB : Cylinder=> 980 , Heads=> 16 , Sectors=> 32
1012 * 384MB : Cylinder=> 745 , Heads=> 16 , Sectors=> 63
1013 */
1014 pSegIdDrvInfo->number_of_cylinders = 0x02E9;
1015 pSegIdDrvInfo->reserved1 = 0x0;
1016 pSegIdDrvInfo->number_of_heads = 0x10;
1017 pSegIdDrvInfo->unformatted_bytes_per_track = 0x0;
1018 pSegIdDrvInfo->unformatted_bytes_per_sector = 0x0;
1019 pSegIdDrvInfo->sectors_per_track = 0x3F;
1020 pSegIdDrvInfo->vendor_unique1[0] = 0x000B;
1021 pSegIdDrvInfo->vendor_unique1[1] = 0x7570;
1022 pSegIdDrvInfo->vendor_unique1[2] = 0x8888;
1023
1024 memcpy(pSegIdDrvInfo->serial_number, (void *)g_strSEG_SerialNum,20);
1025 /* 0x2 : dual buffer */
1026 pSegIdDrvInfo->buffer_type = 0x2;
1027 /* buffer size : 2KB */
1028 pSegIdDrvInfo->buffer_sector_size = 0x800;
1029 pSegIdDrvInfo->number_of_ecc_bytes = 0;
1030
1031 memcpy(pSegIdDrvInfo->firmware_revision, (void *)g_strSEG_FWRev,8);
1032
1033 memcpy(pSegIdDrvInfo->model_number, (void *)g_strSEG_ModelNum,40);
1034
1035 pSegIdDrvInfo->maximum_block_transfer = 0x4;
1036 pSegIdDrvInfo->vendor_unique2 = 0x0;
1037 pSegIdDrvInfo->dword_io = 0x00;
1038 /* b11 : IORDY support(PIO Mode 4), b10 : Disable/Enbale IORDY
1039 * b9 : LBA support, b8 : DMA mode support
1040 */
1041 pSegIdDrvInfo->capabilities = 0x1 << 9;
1042
1043 pSegIdDrvInfo->reserved2 = 0x4000;
1044 pSegIdDrvInfo->vendor_unique3 = 0x00;
1045 /* PIOMode-2 support */
1046 pSegIdDrvInfo->pio_cycle_timing_mode = 0x02;
1047 pSegIdDrvInfo->vendor_unique4 = 0x00;
1048 /* MultiWord-2 support */
1049 pSegIdDrvInfo->dma_cycle_timing_mode = 0x00;
1050 /* b1 : word64~70 is valid
1051 * b0 : word54~58 are valid and reflect the current numofcyls,heads,sectors
1052 * b2 : If device supports Ultra DMA , set to one to vaildate word88
1053 */
1054 pSegIdDrvInfo->translation_fields_valid = (0x1 << 1) | (0x1 << 0);
1055 pSegIdDrvInfo->number_of_current_cylinders = 0x02E9;
1056 pSegIdDrvInfo->number_of_current_heads = 0x10;
1057 pSegIdDrvInfo->current_sectors_per_track = 0x3F;
1058 pSegIdDrvInfo->current_sector_capacity_lo = 0x7570;
1059 pSegIdDrvInfo->current_sector_capacity_hi = 0x000B;
1060
1061 pSegIdDrvInfo->multi_sector_count = 0x04;
1062 /* b8 : Multiple secotr setting valid , b[7:0] num of secotrs per block */
1063 pSegIdDrvInfo->multi_sector_setting_valid = 0x01;
1064 pSegIdDrvInfo->total_user_addressable_sectors_lo = 0x7570;
1065 pSegIdDrvInfo->total_user_addressable_sectors_hi = 0x000B;
1066 pSegIdDrvInfo->single_dma_modes_supported = 0x00;
1067 pSegIdDrvInfo->single_dma_transfer_active = 0x00;
1068 /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
1069 pSegIdDrvInfo->multi_dma_modes_supported = (0x1 << 0);
1070 /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
1071 pSegIdDrvInfo->multi_dma_transfer_active = (0x1 << 0);
1072 /* b0 : PIO Mode-3 support, b1 : PIO Mode-4 support */
1073 pSegIdDrvInfo->adv_pio_mode = 0x00;
1074 /* 480(0x1E0)nsec for Multi-word DMA mode0
1075 * 150(0x96) nsec for Multi-word DMA mode1
1076 * 120(0x78) nsec for Multi-word DMA mode2
1077 */
1078 pSegIdDrvInfo->min_dma_cyc = 0x1E0;
1079 pSegIdDrvInfo->recommend_dma_cyc = 0x1E0;
1080 pSegIdDrvInfo->min_pio_cyc_no_iordy = 0x1E0;
1081 pSegIdDrvInfo->min_pio_cyc_with_iordy = 0x1E0;
1082 memset((void *)pSegIdDrvInfo->reserved3, 0x00, 22);
1083 /* b7 : ATA/ATAPI-7 ,b6 : ATA/ATAPI-6 ,b5 : ATA/ATAPI-5,b4 : ATA/ATAPI-4 */
1084 pSegIdDrvInfo->major_ver_num = 0x7E;
1085 /* 0x1C : ATA/ATAPI-6 T13 1532D revision1 */
1086 pSegIdDrvInfo->minor_ver_num = 0x19;
1087 /* NOP/READ BUFFER/WRITE BUFFER/Power management feature set support */
1088 pSegIdDrvInfo->feature_cmd_set_suprt0 = 0x7068;
1089 /* Features/command set is valid/Advanced Pwr management/CFA feature set
1090 * not support
1091 */
1092 pSegIdDrvInfo->feature_cmd_set_suprt1 = 0x400C;
1093 pSegIdDrvInfo->feature_cmd_set_suprt2 = 0x4000;
1094 /* READ/WRITE BUFFER/PWR Management enable */
1095 pSegIdDrvInfo->feature_cmd_set_en0 = 0x7000;
1096 /* CFA feature is disabled / Advancde power management disable */
1097 pSegIdDrvInfo->feature_cmd_set_en1 = 0x0;
1098 pSegIdDrvInfo->feature_cmd_set_en2 = 0x4000;
1099 pSegIdDrvInfo->reserved4 = 0x0;
1100 /* 0x1 * 2minutes */
1101 pSegIdDrvInfo->req_time_for_security_er_done = 0x19;
1102 pSegIdDrvInfo->req_time_for_enhan_security_er_done = 0x19;
1103 /* Advanced power management level 1 */
1104 pSegIdDrvInfo->adv_pwr_mgm_lvl_val = 0x0;
1105 pSegIdDrvInfo->reserved5 = 0x0;
1106 memset((void *)pSegIdDrvInfo->reserved6, 0x00, 68);
1107 /* Security mode feature is disabled */
1108 pSegIdDrvInfo->security_stas = 0x0;
1109 memset((void *)pSegIdDrvInfo->vendor_uniq_bytes, 0x00, 62);
1110 /* CFA power mode 1 support in maximum 200mA */
1111 pSegIdDrvInfo->cfa_pwr_mode = 0x0100;
1112 memset((void *)pSegIdDrvInfo->reserved7, 0x00, 190);
1113 }
1114
1115 static int mg_storage_config(void)
1116 {
1117 uint8_t buff[512];
1118 int ret;
1119
1120 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1121 != ERROR_OK)
1122 return ret;
1123
1124 mg_gen_ataid((mg_io_type_drv_info *)buff);
1125
1126 if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_stgdrvinfo))
1127 != ERROR_OK)
1128 return ret;
1129
1130 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1131 != ERROR_OK)
1132 return ret;
1133
1134 LOG_INFO("mflash: storage config ok");
1135 return ret;
1136 }
1137
1138 static int mg_boot_config(void)
1139 {
1140 uint8_t buff[512];
1141 int ret;
1142
1143 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1144 != ERROR_OK)
1145 return ret;
1146
1147 memset(buff, 0xff, 512);
1148
1149 buff[0] = mg_op_mode_snd; /* operation mode */
1150 buff[1] = MG_UNLOCK_OTP_AREA;
1151 buff[2] = 4; /* boot size */
1152 *((uint32_t *)(buff + 4)) = 0; /* XIP size */
1153
1154 if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_xipinfo))
1155 != ERROR_OK)
1156 return ret;
1157
1158 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1159 != ERROR_OK)
1160 return ret;
1161
1162 LOG_INFO("mflash: boot config ok");
1163 return ret;
1164 }
1165
1166 static int mg_set_pll(mg_pll_t *pll)
1167 {
1168 uint8_t buff[512];
1169 int ret;
1170
1171 memset(buff, 0xff, 512);
1172 /* PLL Lock cycle and Feedback 9bit Divider */
1173 memcpy(buff, &pll->lock_cyc, sizeof(uint32_t));
1174 memcpy(buff + 4, &pll->feedback_div, sizeof(uint16_t));
1175 buff[6] = pll->input_div; /* PLL Input 5bit Divider */
1176 buff[7] = pll->output_div; /* PLL Output Divider */
1177
1178 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1179 != ERROR_OK)
1180 return ret;
1181
1182 if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_wr_pll))
1183 != ERROR_OK)
1184 return ret;
1185
1186 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1187 != ERROR_OK)
1188 return ret;
1189
1190 LOG_INFO("mflash: set pll ok");
1191 return ret;
1192 }
1193
1194 static int mg_erase_nand(void)
1195 {
1196 int ret;
1197
1198 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1199 != ERROR_OK)
1200 return ret;
1201
1202 if ((ret = mg_mflash_do_write_sects(NULL, 0, 0, mg_vcmd_purge_nand))
1203 != ERROR_OK)
1204 return ret;
1205
1206 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1207 != ERROR_OK)
1208 return ret;
1209
1210 LOG_INFO("mflash: erase nand ok");
1211 return ret;
1212 }
1213
1214 COMMAND_HANDLER(mg_config_cmd)
1215 {
1216 double fin, fout;
1217 mg_pll_t pll;
1218 int ret;
1219
1220 if ((ret = mg_verify_interface()) != ERROR_OK)
1221 return ret;
1222
1223 if ((ret = mg_mflash_rst()) != ERROR_OK)
1224 return ret;
1225
1226 switch (CMD_ARGC) {
1227 case 2:
1228 if (!strcmp(CMD_ARGV[1], "boot"))
1229 return mg_boot_config();
1230 else if (!strcmp(CMD_ARGV[1], "storage"))
1231 return mg_storage_config();
1232 else
1233 return ERROR_COMMAND_NOTFOUND;
1234 break;
1235 case 3:
1236 if (!strcmp(CMD_ARGV[1], "pll")) {
1237 unsigned long freq;
1238 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], freq);
1239 fin = freq;
1240
1241 if (fin > MG_PLL_CLK_OUT) {
1242 LOG_ERROR("mflash: input freq. is too large");
1243 return ERROR_MG_INVALID_OSC;
1244 }
1245
1246 fout = mg_calc_pll(fin, &pll);
1247
1248 if (!fout) {
1249 LOG_ERROR("mflash: cannot generate valid pll");
1250 return ERROR_MG_INVALID_PLL;
1251 }
1252
1253 LOG_INFO("mflash: Fout=%" PRIu32 " Hz, feedback=%u,"
1254 "indiv=%u, outdiv=%u, lock=%u",
1255 (uint32_t)fout, pll.feedback_div,
1256 pll.input_div, pll.output_div,
1257 pll.lock_cyc);
1258
1259 if ((ret = mg_erase_nand()) != ERROR_OK)
1260 return ret;
1261
1262 return mg_set_pll(&pll);
1263 } else
1264 return ERROR_COMMAND_NOTFOUND;
1265 break;
1266 default:
1267 return ERROR_COMMAND_SYNTAX_ERROR;
1268 }
1269 }
1270
1271 static const struct command_registration mflash_exec_command_handlers[] = {
1272 {
1273 .name = "probe",
1274 .handler = mg_probe_cmd,
1275 .mode = COMMAND_EXEC,
1276 .help = "Detect bank configuration information",
1277 },
1278 {
1279 .name = "write",
1280 .handler = mg_write_cmd,
1281 .mode = COMMAND_EXEC,
1282 /* FIXME bank_num is unused */
1283 .usage = "bank_num filename address",
1284 .help = "Write binary file at the specified address.",
1285 },
1286 {
1287 .name = "dump",
1288 .handler = mg_dump_cmd,
1289 .mode = COMMAND_EXEC,
1290 /* FIXME bank_num is unused */
1291 .usage = "bank_num filename address size",
1292 .help = "Write specified number of bytes from a binary file "
1293 "to the specified, address.",
1294 },
1295 {
1296 .name = "config",
1297 .handler = mg_config_cmd,
1298 .mode = COMMAND_EXEC,
1299 .help = "Configure MFLASH options.",
1300 .usage = "('boot'|'storage'|'pll' frequency)",
1301 },
1302 COMMAND_REGISTRATION_DONE
1303 };
1304
1305 int mflash_init_drivers(struct command_context *cmd_ctx)
1306 {
1307 if (!mflash_bank)
1308 return ERROR_OK;
1309 return register_commands(cmd_ctx, NULL, mflash_exec_command_handlers);
1310 }
1311
1312 COMMAND_HANDLER(handle_mflash_init_command)
1313 {
1314 if (CMD_ARGC != 0)
1315 return ERROR_COMMAND_SYNTAX_ERROR;
1316
1317 static bool mflash_initialized = false;
1318 if (mflash_initialized)
1319 {
1320 LOG_INFO("'mflash init' has already been called");
1321 return ERROR_OK;
1322 }
1323 mflash_initialized = true;
1324
1325 LOG_DEBUG("Initializing mflash devices...");
1326 return mflash_init_drivers(CMD_CTX);
1327 }
1328
1329 COMMAND_HANDLER(mg_bank_cmd)
1330 {
1331 struct target *target;
1332 int i;
1333
1334 if (CMD_ARGC < 4)
1335 {
1336 return ERROR_COMMAND_SYNTAX_ERROR;
1337 }
1338
1339 if ((target = get_target(CMD_ARGV[3])) == NULL)
1340 {
1341 LOG_ERROR("target '%s' not defined", CMD_ARGV[3]);
1342 return ERROR_FAIL;
1343 }
1344
1345 mflash_bank = calloc(sizeof(struct mflash_bank), 1);
1346 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], mflash_bank->base);
1347 /// @todo Verify how this parsing should work, then document it.
1348 char *str;
1349 mflash_bank->rst_pin.num = strtoul(CMD_ARGV[2], &str, 0);
1350 if (*str)
1351 mflash_bank->rst_pin.port[0] = (uint16_t)
1352 tolower((unsigned)str[0]);
1353
1354 mflash_bank->target = target;
1355
1356 for (i = 0; mflash_gpio[i] ; i++) {
1357 if (! strcmp(mflash_gpio[i]->name, CMD_ARGV[0])) {
1358 mflash_bank->gpio_drv = mflash_gpio[i];
1359 }
1360 }
1361
1362 if (! mflash_bank->gpio_drv) {
1363 LOG_ERROR("%s is unsupported soc", CMD_ARGV[0]);
1364 return ERROR_MG_UNSUPPORTED_SOC;
1365 }
1366
1367 return ERROR_OK;
1368 }
1369
1370 static const struct command_registration mflash_config_command_handlers[] = {
1371 {
1372 .name = "bank",
1373 .handler = mg_bank_cmd,
1374 .mode = COMMAND_CONFIG,
1375 .help = "configure a mflash device bank",
1376 .usage = "soc_type base_addr pin_id target",
1377 },
1378 {
1379 .name = "init",
1380 .mode = COMMAND_CONFIG,
1381 .handler = handle_mflash_init_command,
1382 .help = "initialize mflash devices",
1383 },
1384 COMMAND_REGISTRATION_DONE
1385 };
1386 static const struct command_registration mflash_command_handler[] = {
1387 {
1388 .name = "mflash",
1389 .mode = COMMAND_ANY,
1390 .help = "mflash command group",
1391 .chain = mflash_config_command_handlers,
1392 },
1393 COMMAND_REGISTRATION_DONE
1394 };
1395 int mflash_register_commands(struct command_context *cmd_ctx)
1396 {
1397 return register_commands(cmd_ctx, NULL, mflash_command_handler);
1398 }

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)