#include "target.h" less wildly
[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, buf_cnt, cnt, res, i;
709 uint8_t *buffer;
710 struct fileio fileio;
711 int ret;
712
713 if (argc != 3) {
714 return ERROR_COMMAND_SYNTAX_ERROR;
715 }
716
717 COMMAND_PARSE_NUMBER(u32, args[2], address);
718
719 ret = fileio_open(&fileio, args[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 for (i = 0; i < cnt; i++) {
736 if ((ret = fileio_read(&fileio, MG_FILEIO_CHUNK, buffer, &buf_cnt)) !=
737 ERROR_OK)
738 goto mg_write_cmd_err;
739 if ((ret = mg_mflash_write(address, buffer, MG_FILEIO_CHUNK)) != ERROR_OK)
740 goto mg_write_cmd_err;
741 address += MG_FILEIO_CHUNK;
742 }
743
744 if (res) {
745 if ((ret = fileio_read(&fileio, res, buffer, &buf_cnt)) != ERROR_OK)
746 goto mg_write_cmd_err;
747 if ((ret = mg_mflash_write(address, buffer, res)) != ERROR_OK)
748 goto mg_write_cmd_err;
749 }
750
751 if (duration_measure(&bench) == ERROR_OK)
752 {
753 command_print(cmd_ctx, "wrote %lli byte from file %s "
754 "in %fs (%0.3f kB/s)", fileio.size, args[1],
755 duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
756 }
757
758 free(buffer);
759 fileio_close(&fileio);
760
761 return ERROR_OK;
762
763 mg_write_cmd_err:
764 free(buffer);
765 fileio_close(&fileio);
766
767 return ret;
768 }
769
770 COMMAND_HANDLER(mg_dump_cmd)
771 {
772 uint32_t address, size_written, size, cnt, res, i;
773 uint8_t *buffer;
774 struct fileio fileio;
775 int ret;
776
777 if (argc != 4) {
778 return ERROR_COMMAND_SYNTAX_ERROR;
779 }
780
781 COMMAND_PARSE_NUMBER(u32, args[2], address);
782 COMMAND_PARSE_NUMBER(u32, args[3], size);
783
784 ret = fileio_open(&fileio, args[1], FILEIO_WRITE, FILEIO_BINARY);
785 if (ret != ERROR_OK)
786 return ret;
787
788 buffer = malloc(MG_FILEIO_CHUNK);
789 if (!buffer) {
790 fileio_close(&fileio);
791 return ERROR_FAIL;
792 }
793
794 cnt = size / MG_FILEIO_CHUNK;
795 res = size % MG_FILEIO_CHUNK;
796
797 struct duration bench;
798 duration_start(&bench);
799
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, args[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 (argc) {
1225 case 2:
1226 if (!strcmp(args[1], "boot"))
1227 return mg_boot_config();
1228 else if (!strcmp(args[1], "storage"))
1229 return mg_storage_config();
1230 else
1231 return ERROR_COMMAND_NOTFOUND;
1232 break;
1233 case 3:
1234 if (!strcmp(args[1], "pll")) {
1235 unsigned long freq;
1236 COMMAND_PARSE_NUMBER(ulong, args[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 int mflash_init_drivers(struct command_context *cmd_ctx)
1270 {
1271 if (mflash_bank) {
1272 register_command(cmd_ctx, mflash_cmd, "probe", mg_probe_cmd, COMMAND_EXEC, NULL);
1273 register_command(cmd_ctx, mflash_cmd, "write", mg_write_cmd, COMMAND_EXEC,
1274 "mflash write <num> <file> <address>");
1275 register_command(cmd_ctx, mflash_cmd, "dump", mg_dump_cmd, COMMAND_EXEC,
1276 "mflash dump <num> <file> <address> <size>");
1277 register_command(cmd_ctx, mflash_cmd, "config", mg_config_cmd,
1278 COMMAND_EXEC, "mflash config <num> <stage>");
1279 }
1280
1281 return ERROR_OK;
1282 }
1283
1284 COMMAND_HANDLER(mg_bank_cmd)
1285 {
1286 struct target *target;
1287 int i;
1288
1289 if (argc < 4)
1290 {
1291 return ERROR_COMMAND_SYNTAX_ERROR;
1292 }
1293
1294 if ((target = get_target(args[3])) == NULL)
1295 {
1296 LOG_ERROR("target '%s' not defined", args[3]);
1297 return ERROR_FAIL;
1298 }
1299
1300 mflash_bank = calloc(sizeof(struct mflash_bank), 1);
1301 COMMAND_PARSE_NUMBER(u32, args[1], mflash_bank->base);
1302 /// @todo Verify how this parsing should work, then document it.
1303 char *str;
1304 mflash_bank->rst_pin.num = strtoul(args[2], &str, 0);
1305 if (*str)
1306 mflash_bank->rst_pin.port[0] = (uint16_t)tolower(str[0]);
1307
1308 mflash_bank->target = target;
1309
1310 for (i = 0; mflash_gpio[i] ; i++) {
1311 if (! strcmp(mflash_gpio[i]->name, args[0])) {
1312 mflash_bank->gpio_drv = mflash_gpio[i];
1313 }
1314 }
1315
1316 if (! mflash_bank->gpio_drv) {
1317 LOG_ERROR("%s is unsupported soc", args[0]);
1318 return ERROR_MG_UNSUPPORTED_SOC;
1319 }
1320
1321 return ERROR_OK;
1322 }
1323
1324 int mflash_register_commands(struct command_context *cmd_ctx)
1325 {
1326 mflash_cmd = register_command(cmd_ctx, NULL, "mflash", NULL, COMMAND_ANY, NULL);
1327 register_command(cmd_ctx, mflash_cmd, "bank", mg_bank_cmd, COMMAND_CONFIG,
1328 "mflash bank <soc> <base> <RST pin> <target #>");
1329 return ERROR_OK;
1330 }

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)