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

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)