2a1fbe597eaf00c95ca7f03a628cd77ed14379a4
[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.h"
26 #include "time_support.h"
27 #include "fileio.h"
28 #include "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 command *mflash_cmd;
37
38 static struct mflash_bank *mflash_bank;
39
40 static struct mflash_gpio_drv pxa270_gpio = {
41 .name = "pxa270",
42 .set_gpio_to_output = pxa270_set_gpio_to_output,
43 .set_gpio_output_val = pxa270_set_gpio_output_val
44 };
45
46 static struct mflash_gpio_drv s3c2440_gpio = {
47 .name = "s3c2440",
48 .set_gpio_to_output = s3c2440_set_gpio_to_output,
49 .set_gpio_output_val = s3c2440_set_gpio_output_val
50 };
51
52 static struct mflash_gpio_drv *mflash_gpio[] =
53 {
54 &pxa270_gpio,
55 &s3c2440_gpio,
56 NULL
57 };
58
59 #define PXA270_GAFR0_L 0x40E00054
60 #define PXA270_GAFR3_U 0x40E00070
61 #define PXA270_GAFR3_U_RESERVED_BITS 0xfffc0000u
62 #define PXA270_GPDR0 0x40E0000C
63 #define PXA270_GPDR3 0x40E0010C
64 #define PXA270_GPDR3_RESERVED_BITS 0xfe000000u
65 #define PXA270_GPSR0 0x40E00018
66 #define PXA270_GPCR0 0x40E00024
67
68 static int pxa270_set_gpio_to_output (struct mflash_gpio_num gpio)
69 {
70 uint32_t addr, value, mask;
71 struct target *target = mflash_bank->target;
72 int ret;
73
74 /* remove alternate function. */
75 mask = 0x3u << (gpio.num & 0xF)*2;
76
77 addr = PXA270_GAFR0_L + (gpio.num >> 4) * 4;
78
79 if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
80 return ret;
81
82 value &= ~mask;
83 if (addr == PXA270_GAFR3_U)
84 value &= ~PXA270_GAFR3_U_RESERVED_BITS;
85
86 if ((ret = target_write_u32(target, addr, value)) != ERROR_OK)
87 return ret;
88
89 /* set direction to output */
90 mask = 0x1u << (gpio.num & 0x1F);
91
92 addr = PXA270_GPDR0 + (gpio.num >> 5) * 4;
93
94 if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
95 return ret;
96
97 value |= mask;
98 if (addr == PXA270_GPDR3)
99 value &= ~PXA270_GPDR3_RESERVED_BITS;
100
101 ret = target_write_u32(target, addr, value);
102 return ret;
103 }
104
105 static int pxa270_set_gpio_output_val (struct mflash_gpio_num gpio, uint8_t val)
106 {
107 uint32_t addr, value, mask;
108 struct target *target = mflash_bank->target;
109 int ret;
110
111 mask = 0x1u << (gpio.num & 0x1F);
112
113 if (val) {
114 addr = PXA270_GPSR0 + (gpio.num >> 5) * 4;
115 } else {
116 addr = PXA270_GPCR0 + (gpio.num >> 5) * 4;
117 }
118
119 if ((ret = target_read_u32(target, addr, &value)) != ERROR_OK)
120 return ret;
121
122 value |= mask;
123
124 ret = target_write_u32(target, addr, value);
125
126 return ret;
127 }
128
129 #define S3C2440_GPACON 0x56000000
130 #define S3C2440_GPADAT 0x56000004
131 #define S3C2440_GPJCON 0x560000d0
132 #define S3C2440_GPJDAT 0x560000d4
133
134 static int s3c2440_set_gpio_to_output (struct mflash_gpio_num gpio)
135 {
136 uint32_t data, mask, gpio_con;
137 struct target *target = mflash_bank->target;
138 int ret;
139
140 if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') {
141 gpio_con = S3C2440_GPACON + (gpio.port[0] - 'a') * 0x10;
142 } else if (gpio.port[0] == 'j') {
143 gpio_con = S3C2440_GPJCON;
144 } else {
145 LOG_ERROR("mflash: invalid port %d%s", gpio.num, gpio.port);
146 return ERROR_INVALID_ARGUMENTS;
147 }
148
149 ret = target_read_u32(target, gpio_con, &data);
150
151 if (ret == ERROR_OK) {
152 if (gpio.port[0] == 'a') {
153 mask = 1 << gpio.num;
154 data &= ~mask;
155 } else {
156 mask = 3 << gpio.num * 2;
157 data &= ~mask;
158 data |= (1 << gpio.num * 2);
159 }
160
161 ret = target_write_u32(target, gpio_con, data);
162 }
163 return ret;
164 }
165
166 static int s3c2440_set_gpio_output_val (struct mflash_gpio_num gpio, uint8_t val)
167 {
168 uint32_t data, mask, gpio_dat;
169 struct target *target = mflash_bank->target;
170 int ret;
171
172 if (gpio.port[0] >= 'a' && gpio.port[0] <= 'h') {
173 gpio_dat = S3C2440_GPADAT + (gpio.port[0] - 'a') * 0x10;
174 } else if (gpio.port[0] == 'j') {
175 gpio_dat = S3C2440_GPJDAT;
176 } else {
177 LOG_ERROR("mflash: invalid port %d%s", gpio.num, gpio.port);
178 return ERROR_INVALID_ARGUMENTS;
179 }
180
181 ret = target_read_u32(target, gpio_dat, &data);
182
183 if (ret == ERROR_OK) {
184 mask = 1 << gpio.num;
185 if (val)
186 data |= mask;
187 else
188 data &= ~mask;
189
190 ret = target_write_u32(target, gpio_dat, data);
191 }
192 return ret;
193 }
194
195 static int mg_hdrst(uint8_t level)
196 {
197 return mflash_bank->gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, level);
198 }
199
200 static int mg_init_gpio (void)
201 {
202 int ret;
203 struct mflash_gpio_drv *gpio_drv = mflash_bank->gpio_drv;
204
205 ret = gpio_drv->set_gpio_to_output(mflash_bank->rst_pin);
206 if (ret != ERROR_OK)
207 return ret;
208
209 ret = gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, 1);
210
211 return ret;
212 }
213
214 static int mg_dsk_wait(mg_io_type_wait wait, uint32_t time)
215 {
216 uint8_t status, error;
217 struct target *target = mflash_bank->target;
218 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
219 int ret;
220 long long t = 0;
221
222 struct duration bench;
223 duration_start(&bench);
224
225 while (time) {
226
227 ret = target_read_u8(target, mg_task_reg + MG_REG_STATUS, &status);
228 if (ret != ERROR_OK)
229 return ret;
230
231 if (status & mg_io_rbit_status_busy)
232 {
233 if (wait == mg_io_wait_bsy)
234 return ERROR_OK;
235 } else {
236 switch (wait)
237 {
238 case mg_io_wait_not_bsy:
239 return ERROR_OK;
240 case mg_io_wait_rdy_noerr:
241 if (status & mg_io_rbit_status_ready)
242 return ERROR_OK;
243 break;
244 case mg_io_wait_drq_noerr:
245 if (status & mg_io_rbit_status_data_req)
246 return ERROR_OK;
247 break;
248 default:
249 break;
250 }
251
252 /* Now we check the error condition! */
253 if (status & mg_io_rbit_status_error)
254 {
255 ret = target_read_u8(target, mg_task_reg + MG_REG_ERROR, &error);
256 if (ret != ERROR_OK)
257 return ret;
258
259 LOG_ERROR("mflash: io error 0x%02x", error);
260
261 return ERROR_MG_IO;
262 }
263
264 switch (wait)
265 {
266 case mg_io_wait_rdy:
267 if (status & mg_io_rbit_status_ready)
268 return ERROR_OK;
269
270 case mg_io_wait_drq:
271 if (status & mg_io_rbit_status_data_req)
272 return ERROR_OK;
273
274 default:
275 break;
276 }
277 }
278
279 ret = duration_measure(&bench);
280 if (ERROR_OK == ret)
281 t = duration_elapsed(&bench) * 1000.0;
282 else
283 LOG_ERROR("mflash: duration measurement failed: %d", ret);
284
285 if (t > time)
286 break;
287 }
288
289 LOG_ERROR("mflash: timeout occured");
290 return ERROR_MG_TIMEOUT;
291 }
292
293 static int mg_dsk_srst(uint8_t on)
294 {
295 struct target *target = mflash_bank->target;
296 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
297 uint8_t value;
298 int ret;
299
300 if ((ret = target_read_u8(target, mg_task_reg + MG_REG_DRV_CTRL, &value)) != ERROR_OK)
301 return ret;
302
303 if (on) {
304 value |= (mg_io_rbit_devc_srst);
305 } else {
306 value &= ~mg_io_rbit_devc_srst;
307 }
308
309 ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_CTRL, value);
310 return ret;
311 }
312
313 static int mg_dsk_io_cmd(uint32_t sect_num, uint32_t cnt, uint8_t cmd)
314 {
315 struct target *target = mflash_bank->target;
316 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
317 uint8_t value;
318 int ret;
319
320 ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL);
321 if (ret != ERROR_OK)
322 return ret;
323
324 value = mg_io_rval_dev_drv_master | mg_io_rval_dev_lba_mode |((sect_num >> 24) & 0xf);
325
326 ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_HEAD, value);
327 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, (uint8_t)cnt);
328 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_NUM, (uint8_t)sect_num);
329 ret |= target_write_u8(target, mg_task_reg + MG_REG_CYL_LOW, (uint8_t)(sect_num >> 8));
330 ret |= target_write_u8(target, mg_task_reg + MG_REG_CYL_HIGH, (uint8_t)(sect_num >> 16));
331
332 if (ret != ERROR_OK)
333 return ret;
334
335 return target_write_u8(target, mg_task_reg + MG_REG_COMMAND, cmd);
336 }
337
338 static int mg_dsk_drv_info(void)
339 {
340 struct target *target = mflash_bank->target;
341 uint32_t mg_buff = mflash_bank->base + MG_BUFFER_OFFSET;
342 int ret;
343
344 if ((ret = mg_dsk_io_cmd(0, 1, mg_io_cmd_identify)) != ERROR_OK)
345 return ret;
346
347 if ((ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL)) != ERROR_OK)
348 return ret;
349
350 LOG_INFO("mflash: read drive info");
351
352 if (! mflash_bank->drv_info)
353 mflash_bank->drv_info = malloc(sizeof(struct mg_drv_info));
354
355 target_read_memory(target, mg_buff, 2, 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 %zu byte from file %s "
755 "in %fs (%0.3f kB/s)", 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 int mflash_init_drivers(struct command_context *cmd_ctx)
1272 {
1273 if (mflash_bank) {
1274 register_command(cmd_ctx, mflash_cmd, "probe", mg_probe_cmd, COMMAND_EXEC, NULL);
1275 register_command(cmd_ctx, mflash_cmd, "write", mg_write_cmd, COMMAND_EXEC,
1276 "mflash write <num> <file> <address>");
1277 register_command(cmd_ctx, mflash_cmd, "dump", mg_dump_cmd, COMMAND_EXEC,
1278 "mflash dump <num> <file> <address> <size>");
1279 register_command(cmd_ctx, mflash_cmd, "config", mg_config_cmd,
1280 COMMAND_EXEC, "mflash config <num> <stage>");
1281 }
1282
1283 return ERROR_OK;
1284 }
1285
1286 COMMAND_HANDLER(mg_bank_cmd)
1287 {
1288 struct target *target;
1289 int i;
1290
1291 if (CMD_ARGC < 4)
1292 {
1293 return ERROR_COMMAND_SYNTAX_ERROR;
1294 }
1295
1296 if ((target = get_target(CMD_ARGV[3])) == NULL)
1297 {
1298 LOG_ERROR("target '%s' not defined", CMD_ARGV[3]);
1299 return ERROR_FAIL;
1300 }
1301
1302 mflash_bank = calloc(sizeof(struct mflash_bank), 1);
1303 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], mflash_bank->base);
1304 /// @todo Verify how this parsing should work, then document it.
1305 char *str;
1306 mflash_bank->rst_pin.num = strtoul(CMD_ARGV[2], &str, 0);
1307 if (*str)
1308 mflash_bank->rst_pin.port[0] = (uint16_t)tolower(str[0]);
1309
1310 mflash_bank->target = target;
1311
1312 for (i = 0; mflash_gpio[i] ; i++) {
1313 if (! strcmp(mflash_gpio[i]->name, CMD_ARGV[0])) {
1314 mflash_bank->gpio_drv = mflash_gpio[i];
1315 }
1316 }
1317
1318 if (! mflash_bank->gpio_drv) {
1319 LOG_ERROR("%s is unsupported soc", CMD_ARGV[0]);
1320 return ERROR_MG_UNSUPPORTED_SOC;
1321 }
1322
1323 return ERROR_OK;
1324 }
1325
1326 int mflash_register_commands(struct command_context *cmd_ctx)
1327 {
1328 mflash_cmd = register_command(cmd_ctx, NULL, "mflash", NULL, COMMAND_ANY, NULL);
1329 register_command(cmd_ctx, mflash_cmd, "bank", mg_bank_cmd, COMMAND_CONFIG,
1330 "mflash bank <soc> <base> <RST pin> <target #>");
1331 return ERROR_OK;
1332 }

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)