mflash: factor init to 'mflash init'
[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 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 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(struct mg_drv_info));
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 COMMAND_HANDLER(mg_probe_cmd)
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 struct target *target = mflash_bank->target;
429 uint8_t *buff_ptr = buff;
430
431 if ((ret = mg_dsk_io_cmd(sect_num, sect_cnt, mg_io_cmd_read)) != ERROR_OK)
432 return ret;
433
434 address = mflash_bank->base + MG_BUFFER_OFFSET;
435
436 struct duration bench;
437 duration_start(&bench);
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 ret = duration_measure(&bench);
457 if ((ERROR_OK == ret) && (duration_elapsed(&bench) > 3)) {
458 LOG_INFO("mflash: read %" PRIu32 "'th sectors", sect_num + i);
459 duration_start(&bench);
460 }
461 }
462
463 return mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
464 }
465
466 static int mg_mflash_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
467 {
468 uint32_t quotient, residue, i;
469 uint8_t *buff_ptr = buff;
470 int ret = ERROR_OK;
471
472 quotient = sect_cnt >> 8;
473 residue = sect_cnt % 256;
474
475 for (i = 0; i < quotient; i++) {
476 LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p",
477 sect_num, buff_ptr);
478 ret = mg_mflash_do_read_sects(buff_ptr, sect_num, 256);
479 if (ret != ERROR_OK)
480 return ret;
481
482 sect_num += 256;
483 buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
484 }
485
486 if (residue) {
487 LOG_DEBUG("mflash: sect num : %" PRIx32 " buff : %p",
488 sect_num, buff_ptr);
489 return mg_mflash_do_read_sects(buff_ptr, sect_num, residue);
490 }
491
492 return ret;
493 }
494
495 static int mg_mflash_do_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt,
496 mg_io_type_cmd cmd)
497 {
498 uint32_t i, address;
499 int ret;
500 struct target *target = mflash_bank->target;
501 uint8_t *buff_ptr = buff;
502
503 if ((ret = mg_dsk_io_cmd(sect_num, sect_cnt, cmd)) != ERROR_OK)
504 return ret;
505
506 address = mflash_bank->base + MG_BUFFER_OFFSET;
507
508 struct duration bench;
509 duration_start(&bench);
510
511 for (i = 0; i < sect_cnt; i++) {
512 ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
513 if (ret != ERROR_OK)
514 return ret;
515
516 ret = target_write_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
517 if (ret != ERROR_OK)
518 return ret;
519
520 buff_ptr += MG_MFLASH_SECTOR_SIZE;
521
522 ret = target_write_u8(target, mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND, mg_io_cmd_confirm_write);
523 if (ret != ERROR_OK)
524 return ret;
525
526 LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector write", sect_num + i, (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
527
528 ret = duration_measure(&bench);
529 if ((ERROR_OK == ret) && (duration_elapsed(&bench) > 3)) {
530 LOG_INFO("mflash: wrote %" PRIu32 "'th sectors", sect_num + i);
531 duration_start(&bench);
532 }
533 }
534
535 if (cmd == mg_io_cmd_write)
536 ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
537 else
538 ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_LONG);
539
540 return ret;
541 }
542
543 static int mg_mflash_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
544 {
545 uint32_t quotient, residue, i;
546 uint8_t *buff_ptr = buff;
547 int ret = ERROR_OK;
548
549 quotient = sect_cnt >> 8;
550 residue = sect_cnt % 256;
551
552 for (i = 0; i < quotient; i++) {
553 LOG_DEBUG("mflash: sect num : %" PRIu32 "buff : %p", sect_num,
554 buff_ptr);
555 ret = mg_mflash_do_write_sects(buff_ptr, sect_num, 256, mg_io_cmd_write);
556 if (ret != ERROR_OK)
557 return ret;
558
559 sect_num += 256;
560 buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
561 }
562
563 if (residue) {
564 LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p", sect_num,
565 buff_ptr);
566 return mg_mflash_do_write_sects(buff_ptr, sect_num, residue, mg_io_cmd_write);
567 }
568
569 return ret;
570 }
571
572 static int mg_mflash_read (uint32_t addr, uint8_t *buff, uint32_t len)
573 {
574 uint8_t *buff_ptr = buff;
575 uint8_t sect_buff[MG_MFLASH_SECTOR_SIZE];
576 uint32_t cur_addr, next_sec_addr, end_addr, cnt, sect_num;
577 int ret = ERROR_OK;
578
579 cnt = 0;
580 cur_addr = addr;
581 end_addr = addr + len;
582
583 if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {
584
585 next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;
586 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
587 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
588 if (ret != ERROR_OK)
589 return ret;
590
591 if (end_addr < next_sec_addr) {
592 memcpy(buff_ptr, sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), end_addr - cur_addr);
593 LOG_DEBUG("mflash: copies %" PRIu32 " byte from sector offset 0x%8.8" PRIx32 "", end_addr - cur_addr, cur_addr);
594 cur_addr = end_addr;
595 } else {
596 memcpy(buff_ptr, sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), next_sec_addr - cur_addr);
597 LOG_DEBUG("mflash: copies %" PRIu32 " byte from sector offset 0x%8.8" PRIx32 "", next_sec_addr - cur_addr, cur_addr);
598 buff_ptr += (next_sec_addr - cur_addr);
599 cur_addr = next_sec_addr;
600 }
601 }
602
603 if (cur_addr < end_addr) {
604
605 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
606 next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;
607
608 while (next_sec_addr <= end_addr) {
609 cnt++;
610 next_sec_addr += MG_MFLASH_SECTOR_SIZE;
611 }
612
613 if (cnt)
614 if ((ret = mg_mflash_read_sects(buff_ptr, sect_num, cnt)) != ERROR_OK)
615 return ret;
616
617 buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;
618 cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;
619
620 if (cur_addr < end_addr) {
621
622 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
623 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
624 if (ret != ERROR_OK)
625 return ret;
626
627 memcpy(buff_ptr, sect_buff, end_addr - cur_addr);
628 LOG_DEBUG("mflash: copies %u byte", (unsigned)(end_addr - cur_addr));
629
630 }
631 }
632
633 return ret;
634 }
635
636 static int mg_mflash_write(uint32_t addr, uint8_t *buff, uint32_t len)
637 {
638 uint8_t *buff_ptr = buff;
639 uint8_t sect_buff[MG_MFLASH_SECTOR_SIZE];
640 uint32_t cur_addr, next_sec_addr, end_addr, cnt, sect_num;
641 int ret = ERROR_OK;
642
643 cnt = 0;
644 cur_addr = addr;
645 end_addr = addr + len;
646
647 if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {
648
649 next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;
650 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
651 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
652 if (ret != ERROR_OK)
653 return ret;
654
655 if (end_addr < next_sec_addr) {
656 memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), buff_ptr, end_addr - cur_addr);
657 LOG_DEBUG("mflash: copies %" PRIu32 " byte to sector offset 0x%8.8" PRIx32 "", end_addr - cur_addr, cur_addr);
658 cur_addr = end_addr;
659 } else {
660 memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK), buff_ptr, next_sec_addr - cur_addr);
661 LOG_DEBUG("mflash: copies %" PRIu32 " byte to sector offset 0x%8.8" PRIx32 "", next_sec_addr - cur_addr, cur_addr);
662 buff_ptr += (next_sec_addr - cur_addr);
663 cur_addr = next_sec_addr;
664 }
665
666 ret = mg_mflash_write_sects(sect_buff, sect_num, 1);
667 if (ret != ERROR_OK)
668 return ret;
669 }
670
671 if (cur_addr < end_addr) {
672
673 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
674 next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;
675
676 while (next_sec_addr <= end_addr) {
677 cnt++;
678 next_sec_addr += MG_MFLASH_SECTOR_SIZE;
679 }
680
681 if (cnt)
682 if ((ret = mg_mflash_write_sects(buff_ptr, sect_num, cnt)) != ERROR_OK)
683 return ret;
684
685 buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;
686 cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;
687
688 if (cur_addr < end_addr) {
689
690 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
691 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
692 if (ret != ERROR_OK)
693 return ret;
694
695 memcpy(sect_buff, buff_ptr, end_addr - cur_addr);
696 LOG_DEBUG("mflash: copies %" PRIu32 " byte", end_addr - cur_addr);
697 ret = mg_mflash_write_sects(sect_buff, sect_num, 1);
698 }
699 }
700
701 return ret;
702 }
703
704 COMMAND_HANDLER(mg_write_cmd)
705 {
706 uint32_t address, cnt, res, i;
707 uint8_t *buffer;
708 struct fileio fileio;
709 int ret;
710
711 if (CMD_ARGC != 3) {
712 return ERROR_COMMAND_SYNTAX_ERROR;
713 }
714
715 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
716
717 ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY);
718 if (ret != ERROR_OK)
719 return ret;
720
721 buffer = malloc(MG_FILEIO_CHUNK);
722 if (!buffer) {
723 fileio_close(&fileio);
724 return ERROR_FAIL;
725 }
726
727 cnt = fileio.size / MG_FILEIO_CHUNK;
728 res = fileio.size % MG_FILEIO_CHUNK;
729
730 struct duration bench;
731 duration_start(&bench);
732
733 size_t buf_cnt;
734 for (i = 0; i < cnt; i++) {
735 if ((ret = fileio_read(&fileio, MG_FILEIO_CHUNK, buffer, &buf_cnt)) !=
736 ERROR_OK)
737 goto mg_write_cmd_err;
738 if ((ret = mg_mflash_write(address, buffer, MG_FILEIO_CHUNK)) != ERROR_OK)
739 goto mg_write_cmd_err;
740 address += MG_FILEIO_CHUNK;
741 }
742
743 if (res) {
744 if ((ret = fileio_read(&fileio, res, buffer, &buf_cnt)) != ERROR_OK)
745 goto mg_write_cmd_err;
746 if ((ret = mg_mflash_write(address, buffer, res)) != ERROR_OK)
747 goto mg_write_cmd_err;
748 }
749
750 if (duration_measure(&bench) == ERROR_OK)
751 {
752 command_print(CMD_CTX, "wrote %zu byte from file %s "
753 "in %fs (%0.3f kB/s)", fileio.size, CMD_ARGV[1],
754 duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
755 }
756
757 free(buffer);
758 fileio_close(&fileio);
759
760 return ERROR_OK;
761
762 mg_write_cmd_err:
763 free(buffer);
764 fileio_close(&fileio);
765
766 return ret;
767 }
768
769 COMMAND_HANDLER(mg_dump_cmd)
770 {
771 uint32_t address, size, cnt, res, i;
772 uint8_t *buffer;
773 struct fileio fileio;
774 int ret;
775
776 if (CMD_ARGC != 4) {
777 return ERROR_COMMAND_SYNTAX_ERROR;
778 }
779
780 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
781 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], size);
782
783 ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_WRITE, FILEIO_BINARY);
784 if (ret != ERROR_OK)
785 return ret;
786
787 buffer = malloc(MG_FILEIO_CHUNK);
788 if (!buffer) {
789 fileio_close(&fileio);
790 return ERROR_FAIL;
791 }
792
793 cnt = size / MG_FILEIO_CHUNK;
794 res = size % MG_FILEIO_CHUNK;
795
796 struct duration bench;
797 duration_start(&bench);
798
799 size_t size_written;
800 for (i = 0; i < cnt; i++) {
801 if ((ret = mg_mflash_read(address, buffer, MG_FILEIO_CHUNK)) != ERROR_OK)
802 goto mg_dump_cmd_err;
803 if ((ret = fileio_write(&fileio, MG_FILEIO_CHUNK, buffer, &size_written))
804 != ERROR_OK)
805 goto mg_dump_cmd_err;
806 address += MG_FILEIO_CHUNK;
807 }
808
809 if (res) {
810 if ((ret = mg_mflash_read(address, buffer, res)) != ERROR_OK)
811 goto mg_dump_cmd_err;
812 if ((ret = fileio_write(&fileio, res, buffer, &size_written)) != ERROR_OK)
813 goto mg_dump_cmd_err;
814 }
815
816 if (duration_measure(&bench) == ERROR_OK)
817 {
818 command_print(CMD_CTX, "dump image (address 0x%8.8" PRIx32 " "
819 "size %" PRIu32 ") to file %s in %fs (%0.3f kB/s)",
820 address, size, CMD_ARGV[1],
821 duration_elapsed(&bench), duration_kbps(&bench, size));
822 }
823
824 free(buffer);
825 fileio_close(&fileio);
826
827 return ERROR_OK;
828
829 mg_dump_cmd_err:
830 free(buffer);
831 fileio_close(&fileio);
832
833 return ret;
834 }
835
836 static int mg_set_feature(mg_feature_id feature, mg_feature_val config)
837 {
838 struct target *target = mflash_bank->target;
839 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
840 int ret;
841
842 if ((ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL))
843 != ERROR_OK)
844 return ret;
845
846 ret = target_write_u8(target, mg_task_reg + MG_REG_FEATURE, feature);
847 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, config);
848 ret |= target_write_u8(target, mg_task_reg + MG_REG_COMMAND,
849 mg_io_cmd_set_feature);
850
851 return ret;
852 }
853
854 static int mg_is_valid_pll(double XIN, int N, double CLK_OUT, int NO)
855 {
856 double v1 = XIN / N;
857 double v2 = CLK_OUT * NO;
858
859 if (v1 <1000000 || v1 > 15000000 || v2 < 100000000 || v2 > 500000000)
860 return ERROR_MG_INVALID_PLL;
861
862 return ERROR_OK;
863 }
864
865 static int mg_pll_get_M(unsigned short feedback_div)
866 {
867 int i, M;
868
869 for (i = 1, M = 0; i < 512; i <<= 1, feedback_div >>= 1)
870 M += (feedback_div & 1) * i;
871
872 return M + 2;
873 }
874
875 static int mg_pll_get_N(unsigned char input_div)
876 {
877 int i, N;
878
879 for (i = 1, N = 0; i < 32; i <<= 1, input_div >>= 1)
880 N += (input_div & 1) * i;
881
882 return N + 2;
883 }
884
885 static int mg_pll_get_NO(unsigned char output_div)
886 {
887 int i, NO;
888
889 for (i = 0, NO = 1; i < 2; ++i, output_div >>= 1)
890 if (output_div & 1)
891 NO = NO << 1;
892
893 return NO;
894 }
895
896 static double mg_do_calc_pll(double XIN, mg_pll_t * p_pll_val, int is_approximate)
897 {
898 unsigned short i;
899 unsigned char j, k;
900 int M, N, NO;
901 double CLK_OUT;
902 double DIV = 1;
903 double ROUND = 0;
904
905 if (is_approximate) {
906 DIV = 1000000;
907 ROUND = 500000;
908 }
909
910 for (i = 0; i < MG_PLL_MAX_FEEDBACKDIV_VAL ; ++i) {
911 M = mg_pll_get_M(i);
912
913 for (j = 0; j < MG_PLL_MAX_INPUTDIV_VAL ; ++j) {
914 N = mg_pll_get_N(j);
915
916 for (k = 0; k < MG_PLL_MAX_OUTPUTDIV_VAL ; ++k) {
917 NO = mg_pll_get_NO(k);
918
919 CLK_OUT = XIN * ((double)M / N) / NO;
920
921 if ((int)((CLK_OUT + ROUND) / DIV)
922 == (int)(MG_PLL_CLK_OUT / DIV)) {
923 if (mg_is_valid_pll(XIN, N, CLK_OUT, NO) == ERROR_OK)
924 {
925 p_pll_val->lock_cyc = (int)(XIN * MG_PLL_STD_LOCKCYCLE / MG_PLL_STD_INPUTCLK);
926 p_pll_val->feedback_div = i;
927 p_pll_val->input_div = j;
928 p_pll_val->output_div = k;
929
930 return CLK_OUT;
931 }
932 }
933 }
934 }
935 }
936
937 return 0;
938 }
939
940 static double mg_calc_pll(double XIN, mg_pll_t *p_pll_val)
941 {
942 double CLK_OUT;
943
944 CLK_OUT = mg_do_calc_pll(XIN, p_pll_val, 0);
945
946 if (!CLK_OUT)
947 return mg_do_calc_pll(XIN, p_pll_val, 1);
948 else
949 return CLK_OUT;
950 }
951
952 static int mg_verify_interface(void)
953 {
954 uint16_t buff[MG_MFLASH_SECTOR_SIZE >> 1];
955 uint16_t i, j;
956 uint32_t address = mflash_bank->base + MG_BUFFER_OFFSET;
957 struct target *target = mflash_bank->target;
958 int ret;
959
960 for (j = 0; j < 10; j++) {
961 for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++)
962 buff[i] = i;
963
964 ret = target_write_memory(target, address, 2,
965 MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
966 if (ret != ERROR_OK)
967 return ret;
968
969 memset(buff, 0xff, MG_MFLASH_SECTOR_SIZE);
970
971 ret = target_read_memory(target, address, 2,
972 MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
973 if (ret != ERROR_OK)
974 return ret;
975
976 for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++) {
977 if (buff[i] != i) {
978 LOG_ERROR("mflash: verify interface fail");
979 return ERROR_MG_INTERFACE;
980 }
981 }
982 }
983
984 LOG_INFO("mflash: verify interface ok");
985 return ret;
986 }
987
988 static const char g_strSEG_SerialNum[20] = {
989 'G','m','n','i','-','e','e','S','g','a','e','l',
990 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
991 };
992
993 static const char g_strSEG_FWRev[8] = {
994 'F','X','L','T','2','v','0','.'
995 };
996
997 static const char g_strSEG_ModelNum[40] = {
998 'F','X','A','L','H','S','2',0x20,'0','0','s','7',
999 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
1000 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
1001 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
1002 };
1003
1004 static void mg_gen_ataid(mg_io_type_drv_info *pSegIdDrvInfo)
1005 {
1006 /* b15 is ATA device(0) , b7 is Removable Media Device */
1007 pSegIdDrvInfo->general_configuration = 0x045A;
1008 /* 128MB : Cylinder=> 977 , Heads=> 8 , Sectors=> 32
1009 * 256MB : Cylinder=> 980 , Heads=> 16 , Sectors=> 32
1010 * 384MB : Cylinder=> 745 , Heads=> 16 , Sectors=> 63
1011 */
1012 pSegIdDrvInfo->number_of_cylinders = 0x02E9;
1013 pSegIdDrvInfo->reserved1 = 0x0;
1014 pSegIdDrvInfo->number_of_heads = 0x10;
1015 pSegIdDrvInfo->unformatted_bytes_per_track = 0x0;
1016 pSegIdDrvInfo->unformatted_bytes_per_sector = 0x0;
1017 pSegIdDrvInfo->sectors_per_track = 0x3F;
1018 pSegIdDrvInfo->vendor_unique1[0] = 0x000B;
1019 pSegIdDrvInfo->vendor_unique1[1] = 0x7570;
1020 pSegIdDrvInfo->vendor_unique1[2] = 0x8888;
1021
1022 memcpy(pSegIdDrvInfo->serial_number, (void *)g_strSEG_SerialNum,20);
1023 /* 0x2 : dual buffer */
1024 pSegIdDrvInfo->buffer_type = 0x2;
1025 /* buffer size : 2KB */
1026 pSegIdDrvInfo->buffer_sector_size = 0x800;
1027 pSegIdDrvInfo->number_of_ecc_bytes = 0;
1028
1029 memcpy(pSegIdDrvInfo->firmware_revision, (void *)g_strSEG_FWRev,8);
1030
1031 memcpy(pSegIdDrvInfo->model_number, (void *)g_strSEG_ModelNum,40);
1032
1033 pSegIdDrvInfo->maximum_block_transfer = 0x4;
1034 pSegIdDrvInfo->vendor_unique2 = 0x0;
1035 pSegIdDrvInfo->dword_io = 0x00;
1036 /* b11 : IORDY support(PIO Mode 4), b10 : Disable/Enbale IORDY
1037 * b9 : LBA support, b8 : DMA mode support
1038 */
1039 pSegIdDrvInfo->capabilities = 0x1 << 9;
1040
1041 pSegIdDrvInfo->reserved2 = 0x4000;
1042 pSegIdDrvInfo->vendor_unique3 = 0x00;
1043 /* PIOMode-2 support */
1044 pSegIdDrvInfo->pio_cycle_timing_mode = 0x02;
1045 pSegIdDrvInfo->vendor_unique4 = 0x00;
1046 /* MultiWord-2 support */
1047 pSegIdDrvInfo->dma_cycle_timing_mode = 0x00;
1048 /* b1 : word64~70 is valid
1049 * b0 : word54~58 are valid and reflect the current numofcyls,heads,sectors
1050 * b2 : If device supports Ultra DMA , set to one to vaildate word88
1051 */
1052 pSegIdDrvInfo->translation_fields_valid = (0x1 << 1) | (0x1 << 0);
1053 pSegIdDrvInfo->number_of_current_cylinders = 0x02E9;
1054 pSegIdDrvInfo->number_of_current_heads = 0x10;
1055 pSegIdDrvInfo->current_sectors_per_track = 0x3F;
1056 pSegIdDrvInfo->current_sector_capacity_lo = 0x7570;
1057 pSegIdDrvInfo->current_sector_capacity_hi = 0x000B;
1058
1059 pSegIdDrvInfo->multi_sector_count = 0x04;
1060 /* b8 : Multiple secotr setting valid , b[7:0] num of secotrs per block */
1061 pSegIdDrvInfo->multi_sector_setting_valid = 0x01;
1062 pSegIdDrvInfo->total_user_addressable_sectors_lo = 0x7570;
1063 pSegIdDrvInfo->total_user_addressable_sectors_hi = 0x000B;
1064 pSegIdDrvInfo->single_dma_modes_supported = 0x00;
1065 pSegIdDrvInfo->single_dma_transfer_active = 0x00;
1066 /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
1067 pSegIdDrvInfo->multi_dma_modes_supported = (0x1 << 0);
1068 /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
1069 pSegIdDrvInfo->multi_dma_transfer_active = (0x1 << 0);
1070 /* b0 : PIO Mode-3 support, b1 : PIO Mode-4 support */
1071 pSegIdDrvInfo->adv_pio_mode = 0x00;
1072 /* 480(0x1E0)nsec for Multi-word DMA mode0
1073 * 150(0x96) nsec for Multi-word DMA mode1
1074 * 120(0x78) nsec for Multi-word DMA mode2
1075 */
1076 pSegIdDrvInfo->min_dma_cyc = 0x1E0;
1077 pSegIdDrvInfo->recommend_dma_cyc = 0x1E0;
1078 pSegIdDrvInfo->min_pio_cyc_no_iordy = 0x1E0;
1079 pSegIdDrvInfo->min_pio_cyc_with_iordy = 0x1E0;
1080 memset((void *)pSegIdDrvInfo->reserved3, 0x00, 22);
1081 /* b7 : ATA/ATAPI-7 ,b6 : ATA/ATAPI-6 ,b5 : ATA/ATAPI-5,b4 : ATA/ATAPI-4 */
1082 pSegIdDrvInfo->major_ver_num = 0x7E;
1083 /* 0x1C : ATA/ATAPI-6 T13 1532D revision1 */
1084 pSegIdDrvInfo->minor_ver_num = 0x19;
1085 /* NOP/READ BUFFER/WRITE BUFFER/Power management feature set support */
1086 pSegIdDrvInfo->feature_cmd_set_suprt0 = 0x7068;
1087 /* Features/command set is valid/Advanced Pwr management/CFA feature set
1088 * not support
1089 */
1090 pSegIdDrvInfo->feature_cmd_set_suprt1 = 0x400C;
1091 pSegIdDrvInfo->feature_cmd_set_suprt2 = 0x4000;
1092 /* READ/WRITE BUFFER/PWR Management enable */
1093 pSegIdDrvInfo->feature_cmd_set_en0 = 0x7000;
1094 /* CFA feature is disabled / Advancde power management disable */
1095 pSegIdDrvInfo->feature_cmd_set_en1 = 0x0;
1096 pSegIdDrvInfo->feature_cmd_set_en2 = 0x4000;
1097 pSegIdDrvInfo->reserved4 = 0x0;
1098 /* 0x1 * 2minutes */
1099 pSegIdDrvInfo->req_time_for_security_er_done = 0x19;
1100 pSegIdDrvInfo->req_time_for_enhan_security_er_done = 0x19;
1101 /* Advanced power management level 1 */
1102 pSegIdDrvInfo->adv_pwr_mgm_lvl_val = 0x0;
1103 pSegIdDrvInfo->reserved5 = 0x0;
1104 memset((void *)pSegIdDrvInfo->reserved6, 0x00, 68);
1105 /* Security mode feature is disabled */
1106 pSegIdDrvInfo->security_stas = 0x0;
1107 memset((void *)pSegIdDrvInfo->vendor_uniq_bytes, 0x00, 62);
1108 /* CFA power mode 1 support in maximum 200mA */
1109 pSegIdDrvInfo->cfa_pwr_mode = 0x0100;
1110 memset((void *)pSegIdDrvInfo->reserved7, 0x00, 190);
1111 }
1112
1113 static int mg_storage_config(void)
1114 {
1115 uint8_t buff[512];
1116 int ret;
1117
1118 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1119 != ERROR_OK)
1120 return ret;
1121
1122 mg_gen_ataid((mg_io_type_drv_info *)buff);
1123
1124 if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_stgdrvinfo))
1125 != ERROR_OK)
1126 return ret;
1127
1128 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1129 != ERROR_OK)
1130 return ret;
1131
1132 LOG_INFO("mflash: storage config ok");
1133 return ret;
1134 }
1135
1136 static int mg_boot_config(void)
1137 {
1138 uint8_t buff[512];
1139 int ret;
1140
1141 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1142 != ERROR_OK)
1143 return ret;
1144
1145 memset(buff, 0xff, 512);
1146
1147 buff[0] = mg_op_mode_snd; /* operation mode */
1148 buff[1] = MG_UNLOCK_OTP_AREA;
1149 buff[2] = 4; /* boot size */
1150 *((uint32_t *)(buff + 4)) = 0; /* XIP size */
1151
1152 if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_xipinfo))
1153 != ERROR_OK)
1154 return ret;
1155
1156 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1157 != ERROR_OK)
1158 return ret;
1159
1160 LOG_INFO("mflash: boot config ok");
1161 return ret;
1162 }
1163
1164 static int mg_set_pll(mg_pll_t *pll)
1165 {
1166 uint8_t buff[512];
1167 int ret;
1168
1169 memset(buff, 0xff, 512);
1170 /* PLL Lock cycle and Feedback 9bit Divider */
1171 memcpy(buff, &pll->lock_cyc, sizeof(uint32_t));
1172 memcpy(buff + 4, &pll->feedback_div, sizeof(uint16_t));
1173 buff[6] = pll->input_div; /* PLL Input 5bit Divider */
1174 buff[7] = pll->output_div; /* PLL Output Divider */
1175
1176 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1177 != ERROR_OK)
1178 return ret;
1179
1180 if ((ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_wr_pll))
1181 != ERROR_OK)
1182 return ret;
1183
1184 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1185 != ERROR_OK)
1186 return ret;
1187
1188 LOG_INFO("mflash: set pll ok");
1189 return ret;
1190 }
1191
1192 static int mg_erase_nand(void)
1193 {
1194 int ret;
1195
1196 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd))
1197 != ERROR_OK)
1198 return ret;
1199
1200 if ((ret = mg_mflash_do_write_sects(NULL, 0, 0, mg_vcmd_purge_nand))
1201 != ERROR_OK)
1202 return ret;
1203
1204 if ((ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default))
1205 != ERROR_OK)
1206 return ret;
1207
1208 LOG_INFO("mflash: erase nand ok");
1209 return ret;
1210 }
1211
1212 COMMAND_HANDLER(mg_config_cmd)
1213 {
1214 double fin, fout;
1215 mg_pll_t pll;
1216 int ret;
1217
1218 if ((ret = mg_verify_interface()) != ERROR_OK)
1219 return ret;
1220
1221 if ((ret = mg_mflash_rst()) != ERROR_OK)
1222 return ret;
1223
1224 switch (CMD_ARGC) {
1225 case 2:
1226 if (!strcmp(CMD_ARGV[1], "boot"))
1227 return mg_boot_config();
1228 else if (!strcmp(CMD_ARGV[1], "storage"))
1229 return mg_storage_config();
1230 else
1231 return ERROR_COMMAND_NOTFOUND;
1232 break;
1233 case 3:
1234 if (!strcmp(CMD_ARGV[1], "pll")) {
1235 unsigned long freq;
1236 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], freq);
1237 fin = freq;
1238
1239 if (fin > MG_PLL_CLK_OUT) {
1240 LOG_ERROR("mflash: input freq. is too large");
1241 return ERROR_MG_INVALID_OSC;
1242 }
1243
1244 fout = mg_calc_pll(fin, &pll);
1245
1246 if (!fout) {
1247 LOG_ERROR("mflash: cannot generate valid pll");
1248 return ERROR_MG_INVALID_PLL;
1249 }
1250
1251 LOG_INFO("mflash: Fout=%" PRIu32 " Hz, feedback=%u,"
1252 "indiv=%u, outdiv=%u, lock=%u",
1253 (uint32_t)fout, pll.feedback_div,
1254 pll.input_div, pll.output_div,
1255 pll.lock_cyc);
1256
1257 if ((ret = mg_erase_nand()) != ERROR_OK)
1258 return ret;
1259
1260 return mg_set_pll(&pll);
1261 } else
1262 return ERROR_COMMAND_NOTFOUND;
1263 break;
1264 default:
1265 return ERROR_COMMAND_SYNTAX_ERROR;
1266 }
1267 }
1268
1269 static const struct command_registration mflash_exec_command_handlers[] = {
1270 {
1271 .name = "probe",
1272 .handler = &mg_probe_cmd,
1273 .mode = COMMAND_EXEC,
1274 .help = "Detect bank configuration information",
1275 },
1276 {
1277 .name = "write",
1278 .handler = &mg_write_cmd,
1279 .mode = COMMAND_EXEC,
1280 .usage = "<num> <file> <address>",
1281 .help = "Write a file at the specified address",
1282 },
1283 {
1284 .name = "dump",
1285 .handler = &mg_dump_cmd,
1286 .mode = COMMAND_EXEC,
1287 .usage = "<num> <file> <address> <size>",
1288 .help = "Dump to a file from the specified address",
1289 },
1290 {
1291 .name = "config",
1292 .handler = &mg_config_cmd,
1293 .mode = COMMAND_EXEC,
1294 .usage = "<num> <stage>",
1295 .help = "Dump to a file from the specified address",
1296 },
1297 COMMAND_REGISTRATION_DONE
1298 };
1299
1300 int mflash_init_drivers(struct command_context *cmd_ctx)
1301 {
1302 if (!mflash_bank)
1303 return ERROR_OK;
1304 return register_commands(cmd_ctx, NULL, mflash_exec_command_handlers);
1305 }
1306
1307 COMMAND_HANDLER(handle_mflash_init_command)
1308 {
1309 if (CMD_ARGC != 0)
1310 return ERROR_COMMAND_SYNTAX_ERROR;
1311
1312 static bool mflash_initialized = false;
1313 if (mflash_initialized)
1314 {
1315 LOG_INFO("'mflash init' has already been called");
1316 return ERROR_OK;
1317 }
1318 mflash_initialized = true;
1319
1320 LOG_DEBUG("Initializing mflash devices...");
1321 return mflash_init_drivers(CMD_CTX);
1322 }
1323
1324 COMMAND_HANDLER(mg_bank_cmd)
1325 {
1326 struct target *target;
1327 int i;
1328
1329 if (CMD_ARGC < 4)
1330 {
1331 return ERROR_COMMAND_SYNTAX_ERROR;
1332 }
1333
1334 if ((target = get_target(CMD_ARGV[3])) == NULL)
1335 {
1336 LOG_ERROR("target '%s' not defined", CMD_ARGV[3]);
1337 return ERROR_FAIL;
1338 }
1339
1340 mflash_bank = calloc(sizeof(struct mflash_bank), 1);
1341 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], mflash_bank->base);
1342 /// @todo Verify how this parsing should work, then document it.
1343 char *str;
1344 mflash_bank->rst_pin.num = strtoul(CMD_ARGV[2], &str, 0);
1345 if (*str)
1346 mflash_bank->rst_pin.port[0] = (uint16_t)tolower(str[0]);
1347
1348 mflash_bank->target = target;
1349
1350 for (i = 0; mflash_gpio[i] ; i++) {
1351 if (! strcmp(mflash_gpio[i]->name, CMD_ARGV[0])) {
1352 mflash_bank->gpio_drv = mflash_gpio[i];
1353 }
1354 }
1355
1356 if (! mflash_bank->gpio_drv) {
1357 LOG_ERROR("%s is unsupported soc", CMD_ARGV[0]);
1358 return ERROR_MG_UNSUPPORTED_SOC;
1359 }
1360
1361 return ERROR_OK;
1362 }
1363
1364 static const struct command_registration mflash_config_command_handlers[] = {
1365 {
1366 .name = "bank",
1367 .handler = &mg_bank_cmd,
1368 .mode = COMMAND_CONFIG,
1369 .help = "configure a mflash device bank",
1370 .usage = "<soc> <base> <RST pin> <target #>",
1371 },
1372 {
1373 .name = "init",
1374 .mode = COMMAND_CONFIG,
1375 .handler = &handle_mflash_init_command,
1376 .help = "initialize mflash devices",
1377 },
1378 COMMAND_REGISTRATION_DONE
1379 };
1380 static const struct command_registration mflash_command_handler[] = {
1381 {
1382 .name = "mflash",
1383 .mode = COMMAND_ANY,
1384 .help = "mflash command group",
1385 .chain = mflash_config_command_handlers,
1386 },
1387 COMMAND_REGISTRATION_DONE
1388 };
1389 int mflash_register_commands(struct command_context *cmd_ctx)
1390 {
1391 return register_commands(cmd_ctx, NULL, mflash_command_handler);
1392 }

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)