Makefile.am: fix adding contrib directory for dist
[openocd.git] / src / flash / mflash.c
blobea1673f09d47282e7d4d5d7775df188c8491e251
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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "mflash.h"
25 #include <target/target.h>
26 #include <helper/time_support.h>
27 #include <helper/fileio.h>
28 #include <helper/log.h>
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);
35 static struct mflash_bank *mflash_bank;
37 static struct mflash_gpio_drv pxa270_gpio = {
38 .name = "pxa270",
39 .set_gpio_to_output = pxa270_set_gpio_to_output,
40 .set_gpio_output_val = pxa270_set_gpio_output_val
43 static struct mflash_gpio_drv s3c2440_gpio = {
44 .name = "s3c2440",
45 .set_gpio_to_output = s3c2440_set_gpio_to_output,
46 .set_gpio_output_val = s3c2440_set_gpio_output_val
49 static struct mflash_gpio_drv *mflash_gpio[] = {
50 &pxa270_gpio,
51 &s3c2440_gpio,
52 NULL
55 #define PXA270_GAFR0_L 0x40E00054
56 #define PXA270_GAFR3_U 0x40E00070
57 #define PXA270_GAFR3_U_RESERVED_BITS 0xfffc0000u
58 #define PXA270_GPDR0 0x40E0000C
59 #define PXA270_GPDR3 0x40E0010C
60 #define PXA270_GPDR3_RESERVED_BITS 0xfe000000u
61 #define PXA270_GPSR0 0x40E00018
62 #define PXA270_GPCR0 0x40E00024
64 static int pxa270_set_gpio_to_output(struct mflash_gpio_num gpio)
66 uint32_t addr, value, mask;
67 struct target *target = mflash_bank->target;
68 int ret;
70 /* remove alternate function. */
71 mask = 0x3u << (gpio.num & 0xF)*2;
73 addr = PXA270_GAFR0_L + (gpio.num >> 4) * 4;
75 ret = target_read_u32(target, addr, &value);
76 if (ret != ERROR_OK)
77 return ret;
79 value &= ~mask;
80 if (addr == PXA270_GAFR3_U)
81 value &= ~PXA270_GAFR3_U_RESERVED_BITS;
83 ret = target_write_u32(target, addr, value);
84 if (ret != ERROR_OK)
85 return ret;
87 /* set direction to output */
88 mask = 0x1u << (gpio.num & 0x1F);
90 addr = PXA270_GPDR0 + (gpio.num >> 5) * 4;
92 ret = target_read_u32(target, addr, &value);
93 if (ret != ERROR_OK)
94 return ret;
96 value |= mask;
97 if (addr == PXA270_GPDR3)
98 value &= ~PXA270_GPDR3_RESERVED_BITS;
100 ret = target_write_u32(target, addr, value);
101 return ret;
104 static int pxa270_set_gpio_output_val(struct mflash_gpio_num gpio, uint8_t val)
106 uint32_t addr, value, mask;
107 struct target *target = mflash_bank->target;
108 int ret;
110 mask = 0x1u << (gpio.num & 0x1F);
112 if (val)
113 addr = PXA270_GPSR0 + (gpio.num >> 5) * 4;
114 else
115 addr = PXA270_GPCR0 + (gpio.num >> 5) * 4;
117 ret = target_read_u32(target, addr, &value);
118 if (ret != ERROR_OK)
119 return ret;
121 value |= mask;
123 ret = target_write_u32(target, addr, value);
125 return ret;
128 #define S3C2440_GPACON 0x56000000
129 #define S3C2440_GPADAT 0x56000004
130 #define S3C2440_GPJCON 0x560000d0
131 #define S3C2440_GPJDAT 0x560000d4
133 static int s3c2440_set_gpio_to_output(struct mflash_gpio_num gpio)
135 uint32_t data, mask, gpio_con;
136 struct target *target = mflash_bank->target;
137 int ret;
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_COMMAND_SYNTAX_ERROR;
148 ret = target_read_u32(target, gpio_con, &data);
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);
160 ret = target_write_u32(target, gpio_con, data);
162 return ret;
165 static int s3c2440_set_gpio_output_val(struct mflash_gpio_num gpio, uint8_t val)
167 uint32_t data, mask, gpio_dat;
168 struct target *target = mflash_bank->target;
169 int ret;
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_COMMAND_SYNTAX_ERROR;
180 ret = target_read_u32(target, gpio_dat, &data);
182 if (ret == ERROR_OK) {
183 mask = 1 << gpio.num;
184 if (val)
185 data |= mask;
186 else
187 data &= ~mask;
189 ret = target_write_u32(target, gpio_dat, data);
191 return ret;
194 static int mg_hdrst(uint8_t level)
196 return mflash_bank->gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, level);
199 static int mg_init_gpio(void)
201 int ret;
202 struct mflash_gpio_drv *gpio_drv = mflash_bank->gpio_drv;
204 ret = gpio_drv->set_gpio_to_output(mflash_bank->rst_pin);
205 if (ret != ERROR_OK)
206 return ret;
208 ret = gpio_drv->set_gpio_output_val(mflash_bank->rst_pin, 1);
210 return ret;
213 static int mg_dsk_wait(mg_io_type_wait wait_local, uint32_t time_var)
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;
221 struct duration bench;
222 duration_start(&bench);
224 while (time_var) {
226 ret = target_read_u8(target, mg_task_reg + MG_REG_STATUS, &status);
227 if (ret != ERROR_OK)
228 return ret;
230 if (status & mg_io_rbit_status_busy) {
231 if (wait_local == mg_io_wait_bsy)
232 return ERROR_OK;
233 } else {
234 switch (wait_local) {
235 case mg_io_wait_not_bsy:
236 return ERROR_OK;
237 case mg_io_wait_rdy_noerr:
238 if (status & mg_io_rbit_status_ready)
239 return ERROR_OK;
240 break;
241 case mg_io_wait_drq_noerr:
242 if (status & mg_io_rbit_status_data_req)
243 return ERROR_OK;
244 break;
245 default:
246 break;
249 /* Now we check the error condition! */
250 if (status & mg_io_rbit_status_error) {
251 ret = target_read_u8(target, mg_task_reg + MG_REG_ERROR, &error);
252 if (ret != ERROR_OK)
253 return ret;
255 LOG_ERROR("mflash: io error 0x%02x", error);
257 return ERROR_MG_IO;
260 switch (wait_local) {
261 case mg_io_wait_rdy:
262 if (status & mg_io_rbit_status_ready)
263 return ERROR_OK;
265 case mg_io_wait_drq:
266 if (status & mg_io_rbit_status_data_req)
267 return ERROR_OK;
269 default:
270 break;
274 ret = duration_measure(&bench);
275 if (ERROR_OK == ret)
276 t = duration_elapsed(&bench) * 1000.0;
277 else
278 LOG_ERROR("mflash: duration measurement failed: %d", ret);
280 if (t > time_var)
281 break;
284 LOG_ERROR("mflash: timeout occured");
285 return ERROR_MG_TIMEOUT;
288 static int mg_dsk_srst(uint8_t on)
290 struct target *target = mflash_bank->target;
291 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
292 uint8_t value;
293 int ret;
295 ret = target_read_u8(target, mg_task_reg + MG_REG_DRV_CTRL, &value);
296 if (ret != ERROR_OK)
297 return ret;
299 if (on)
300 value |= (mg_io_rbit_devc_srst);
301 else
302 value &= ~mg_io_rbit_devc_srst;
304 ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_CTRL, value);
305 return ret;
308 static int mg_dsk_io_cmd(uint32_t sect_num, uint32_t cnt, uint8_t cmd)
310 struct target *target = mflash_bank->target;
311 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
312 uint8_t value;
313 int ret;
315 ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL);
316 if (ret != ERROR_OK)
317 return ret;
319 value = mg_io_rval_dev_drv_master | mg_io_rval_dev_lba_mode | ((sect_num >> 24) & 0xf);
321 ret = target_write_u8(target, mg_task_reg + MG_REG_DRV_HEAD, value);
322 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, (uint8_t)cnt);
323 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_NUM, (uint8_t)sect_num);
324 ret |= target_write_u8(target, mg_task_reg + MG_REG_CYL_LOW, (uint8_t)(sect_num >> 8));
325 ret |= target_write_u8(target, mg_task_reg + MG_REG_CYL_HIGH, (uint8_t)(sect_num >> 16));
327 if (ret != ERROR_OK)
328 return ret;
330 return target_write_u8(target, mg_task_reg + MG_REG_COMMAND, cmd);
333 static int mg_dsk_drv_info(void)
335 struct target *target = mflash_bank->target;
336 uint32_t mg_buff = mflash_bank->base + MG_BUFFER_OFFSET;
337 int ret;
339 ret = mg_dsk_io_cmd(0, 1, mg_io_cmd_identify);
340 if (ret != ERROR_OK)
341 return ret;
343 ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
344 if (ret != ERROR_OK)
345 return ret;
347 LOG_INFO("mflash: read drive info");
349 if (!mflash_bank->drv_info)
350 mflash_bank->drv_info = malloc(sizeof(struct mg_drv_info));
352 ret = target_read_memory(target, mg_buff, 2,
353 sizeof(mg_io_type_drv_info) >> 1,
354 (uint8_t *)&mflash_bank->drv_info->drv_id);
355 if (ret != ERROR_OK)
356 return ret;
358 mflash_bank->drv_info->tot_sects =
359 (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;
362 return target_write_u8(target,
363 mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND,
364 mg_io_cmd_confirm_read);
367 static int mg_mflash_rst(void)
369 int ret;
371 ret = mg_init_gpio();
372 if (ret != ERROR_OK)
373 return ret;
375 ret = mg_hdrst(0);
376 if (ret != ERROR_OK)
377 return ret;
379 ret = mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG);
380 if (ret != ERROR_OK)
381 return ret;
383 ret = mg_hdrst(1);
384 if (ret != ERROR_OK)
385 return ret;
387 ret = mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG);
388 if (ret != ERROR_OK)
389 return ret;
391 ret = mg_dsk_srst(1);
392 if (ret != ERROR_OK)
393 return ret;
395 ret = mg_dsk_wait(mg_io_wait_bsy, MG_OEM_DISK_WAIT_TIME_LONG);
396 if (ret != ERROR_OK)
397 return ret;
399 ret = mg_dsk_srst(0);
400 if (ret != ERROR_OK)
401 return ret;
403 ret = mg_dsk_wait(mg_io_wait_not_bsy, MG_OEM_DISK_WAIT_TIME_LONG);
404 if (ret != ERROR_OK)
405 return ret;
407 LOG_INFO("mflash: reset ok");
409 return ERROR_OK;
412 static int mg_mflash_probe(void)
414 int ret = mg_mflash_rst();
415 if (ret != ERROR_OK)
416 return ret;
418 return mg_dsk_drv_info();
421 COMMAND_HANDLER(mg_probe_cmd)
423 int ret;
425 ret = mg_mflash_probe();
427 if (ret == ERROR_OK) {
428 command_print(CMD_CTX,
429 "mflash (total %" PRIu32 " sectors) found at 0x%8.8" PRIx32 "",
430 mflash_bank->drv_info->tot_sects,
431 mflash_bank->base);
434 return ret;
437 static int mg_mflash_do_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
439 uint32_t i, address;
440 int ret;
441 struct target *target = mflash_bank->target;
442 uint8_t *buff_ptr = buff;
444 ret = mg_dsk_io_cmd(sect_num, sect_cnt, mg_io_cmd_read);
445 if (ret != ERROR_OK)
446 return ret;
448 address = mflash_bank->base + MG_BUFFER_OFFSET;
450 struct duration bench;
451 duration_start(&bench);
453 for (i = 0; i < sect_cnt; i++) {
454 ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
455 if (ret != ERROR_OK)
456 return ret;
458 ret = target_read_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
459 if (ret != ERROR_OK)
460 return ret;
462 buff_ptr += MG_MFLASH_SECTOR_SIZE;
464 ret = target_write_u8(target,
465 mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND,
466 mg_io_cmd_confirm_read);
467 if (ret != ERROR_OK)
468 return ret;
470 LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector read", sect_num + i,
471 (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
473 ret = duration_measure(&bench);
474 if ((ERROR_OK == ret) && (duration_elapsed(&bench) > 3)) {
475 LOG_INFO("mflash: read %" PRIu32 "'th sectors", sect_num + i);
476 duration_start(&bench);
480 return mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
483 static int mg_mflash_read_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
485 uint32_t quotient, residue, i;
486 uint8_t *buff_ptr = buff;
487 int ret = ERROR_OK;
489 quotient = sect_cnt >> 8;
490 residue = sect_cnt % 256;
492 for (i = 0; i < quotient; i++) {
493 LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p",
494 sect_num, buff_ptr);
495 ret = mg_mflash_do_read_sects(buff_ptr, sect_num, 256);
496 if (ret != ERROR_OK)
497 return ret;
499 sect_num += 256;
500 buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
503 if (residue) {
504 LOG_DEBUG("mflash: sect num : %" PRIx32 " buff : %p",
505 sect_num, buff_ptr);
506 return mg_mflash_do_read_sects(buff_ptr, sect_num, residue);
509 return ret;
512 static int mg_mflash_do_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt,
513 uint8_t cmd)
515 uint32_t i, address;
516 int ret;
517 struct target *target = mflash_bank->target;
518 uint8_t *buff_ptr = buff;
520 ret = mg_dsk_io_cmd(sect_num, sect_cnt, cmd);
521 if (ret != ERROR_OK)
522 return ret;
524 address = mflash_bank->base + MG_BUFFER_OFFSET;
526 struct duration bench;
527 duration_start(&bench);
529 for (i = 0; i < sect_cnt; i++) {
530 ret = mg_dsk_wait(mg_io_wait_drq, MG_OEM_DISK_WAIT_TIME_NORMAL);
531 if (ret != ERROR_OK)
532 return ret;
534 ret = target_write_memory(target, address, 2, MG_MFLASH_SECTOR_SIZE / 2, buff_ptr);
535 if (ret != ERROR_OK)
536 return ret;
538 buff_ptr += MG_MFLASH_SECTOR_SIZE;
540 ret = target_write_u8(target,
541 mflash_bank->base + MG_REG_OFFSET + MG_REG_COMMAND,
542 mg_io_cmd_confirm_write);
543 if (ret != ERROR_OK)
544 return ret;
546 LOG_DEBUG("mflash: %" PRIu32 " (0x%8.8" PRIx32 ") sector write", sect_num + i,
547 (sect_num + i) * MG_MFLASH_SECTOR_SIZE);
549 ret = duration_measure(&bench);
550 if ((ERROR_OK == ret) && (duration_elapsed(&bench) > 3)) {
551 LOG_INFO("mflash: wrote %" PRIu32 "'th sectors", sect_num + i);
552 duration_start(&bench);
556 if (cmd == mg_io_cmd_write)
557 ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_NORMAL);
558 else
559 ret = mg_dsk_wait(mg_io_wait_rdy, MG_OEM_DISK_WAIT_TIME_LONG);
561 return ret;
564 static int mg_mflash_write_sects(void *buff, uint32_t sect_num, uint32_t sect_cnt)
566 uint32_t quotient, residue, i;
567 uint8_t *buff_ptr = buff;
568 int ret = ERROR_OK;
570 quotient = sect_cnt >> 8;
571 residue = sect_cnt % 256;
573 for (i = 0; i < quotient; i++) {
574 LOG_DEBUG("mflash: sect num : %" PRIu32 "buff : %p", sect_num,
575 buff_ptr);
576 ret = mg_mflash_do_write_sects(buff_ptr, sect_num, 256, mg_io_cmd_write);
577 if (ret != ERROR_OK)
578 return ret;
580 sect_num += 256;
581 buff_ptr += 256 * MG_MFLASH_SECTOR_SIZE;
584 if (residue) {
585 LOG_DEBUG("mflash: sect num : %" PRIu32 " buff : %p", sect_num,
586 buff_ptr);
587 return mg_mflash_do_write_sects(buff_ptr, sect_num, residue, mg_io_cmd_write);
590 return ret;
593 static int mg_mflash_read(uint32_t addr, uint8_t *buff, uint32_t len)
595 uint8_t *buff_ptr = buff;
596 uint8_t sect_buff[MG_MFLASH_SECTOR_SIZE];
597 uint32_t cur_addr, next_sec_addr, end_addr, cnt, sect_num;
598 int ret = ERROR_OK;
600 cnt = 0;
601 cur_addr = addr;
602 end_addr = addr + len;
604 if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {
606 next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;
607 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
608 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
609 if (ret != ERROR_OK)
610 return ret;
612 if (end_addr < next_sec_addr) {
613 memcpy(buff_ptr,
614 sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK),
615 end_addr - cur_addr);
616 LOG_DEBUG(
617 "mflash: copies %" PRIu32 " byte from sector offset 0x%8.8" PRIx32 "",
618 end_addr - cur_addr,
619 cur_addr);
620 cur_addr = end_addr;
621 } else {
622 memcpy(buff_ptr,
623 sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK),
624 next_sec_addr - cur_addr);
625 LOG_DEBUG(
626 "mflash: copies %" PRIu32 " byte from sector offset 0x%8.8" PRIx32 "",
627 next_sec_addr - cur_addr,
628 cur_addr);
629 buff_ptr += (next_sec_addr - cur_addr);
630 cur_addr = next_sec_addr;
634 if (cur_addr < end_addr) {
636 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
637 next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;
639 while (next_sec_addr <= end_addr) {
640 cnt++;
641 next_sec_addr += MG_MFLASH_SECTOR_SIZE;
644 if (cnt) {
645 ret = mg_mflash_read_sects(buff_ptr, sect_num, cnt);
646 if (ret != ERROR_OK)
647 return ret;
650 buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;
651 cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;
653 if (cur_addr < end_addr) {
655 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
656 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
657 if (ret != ERROR_OK)
658 return ret;
660 memcpy(buff_ptr, sect_buff, end_addr - cur_addr);
661 LOG_DEBUG("mflash: copies %u byte", (unsigned)(end_addr - cur_addr));
665 return ret;
668 static int mg_mflash_write(uint32_t addr, uint8_t *buff, uint32_t len)
670 uint8_t *buff_ptr = buff;
671 uint8_t sect_buff[MG_MFLASH_SECTOR_SIZE];
672 uint32_t cur_addr, next_sec_addr, end_addr, cnt, sect_num;
673 int ret = ERROR_OK;
675 cnt = 0;
676 cur_addr = addr;
677 end_addr = addr + len;
679 if (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK) {
681 next_sec_addr = (cur_addr + MG_MFLASH_SECTOR_SIZE) & ~MG_MFLASH_SECTOR_SIZE_MASK;
682 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
683 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
684 if (ret != ERROR_OK)
685 return ret;
687 if (end_addr < next_sec_addr) {
688 memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK),
689 buff_ptr,
690 end_addr - cur_addr);
691 LOG_DEBUG(
692 "mflash: copies %" PRIu32 " byte to sector offset 0x%8.8" PRIx32 "",
693 end_addr - cur_addr,
694 cur_addr);
695 cur_addr = end_addr;
696 } else {
697 memcpy(sect_buff + (cur_addr & MG_MFLASH_SECTOR_SIZE_MASK),
698 buff_ptr,
699 next_sec_addr - cur_addr);
700 LOG_DEBUG(
701 "mflash: copies %" PRIu32 " byte to sector offset 0x%8.8" PRIx32 "",
702 next_sec_addr - cur_addr,
703 cur_addr);
704 buff_ptr += (next_sec_addr - cur_addr);
705 cur_addr = next_sec_addr;
708 ret = mg_mflash_write_sects(sect_buff, sect_num, 1);
709 if (ret != ERROR_OK)
710 return ret;
713 if (cur_addr < end_addr) {
715 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
716 next_sec_addr = cur_addr + MG_MFLASH_SECTOR_SIZE;
718 while (next_sec_addr <= end_addr) {
719 cnt++;
720 next_sec_addr += MG_MFLASH_SECTOR_SIZE;
723 if (cnt) {
724 ret = mg_mflash_write_sects(buff_ptr, sect_num, cnt);
725 if (ret != ERROR_OK)
726 return ret;
729 buff_ptr += cnt * MG_MFLASH_SECTOR_SIZE;
730 cur_addr += cnt * MG_MFLASH_SECTOR_SIZE;
732 if (cur_addr < end_addr) {
734 sect_num = cur_addr >> MG_MFLASH_SECTOR_SIZE_SHIFT;
735 ret = mg_mflash_read_sects(sect_buff, sect_num, 1);
736 if (ret != ERROR_OK)
737 return ret;
739 memcpy(sect_buff, buff_ptr, end_addr - cur_addr);
740 LOG_DEBUG("mflash: copies %" PRIu32 " byte", end_addr - cur_addr);
741 ret = mg_mflash_write_sects(sect_buff, sect_num, 1);
745 return ret;
748 COMMAND_HANDLER(mg_write_cmd)
750 uint32_t address, cnt, res, i;
751 uint8_t *buffer;
752 struct fileio fileio;
753 int ret;
755 if (CMD_ARGC != 3)
756 return ERROR_COMMAND_SYNTAX_ERROR;
758 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
760 ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY);
761 if (ret != ERROR_OK)
762 return ret;
764 int filesize;
765 buffer = malloc(MG_FILEIO_CHUNK);
766 if (!buffer) {
767 fileio_close(&fileio);
768 return ERROR_FAIL;
770 int retval = fileio_size(&fileio, &filesize);
771 if (retval != ERROR_OK) {
772 fileio_close(&fileio);
773 free(buffer);
774 return retval;
777 cnt = filesize / MG_FILEIO_CHUNK;
778 res = filesize % MG_FILEIO_CHUNK;
780 struct duration bench;
781 duration_start(&bench);
783 size_t buf_cnt;
784 for (i = 0; i < cnt; i++) {
785 ret = fileio_read(&fileio, MG_FILEIO_CHUNK, buffer, &buf_cnt);
786 if (ret != ERROR_OK)
787 goto mg_write_cmd_err;
788 ret = mg_mflash_write(address, buffer, MG_FILEIO_CHUNK);
789 if (ret != ERROR_OK)
790 goto mg_write_cmd_err;
791 address += MG_FILEIO_CHUNK;
794 if (res) {
795 ret = fileio_read(&fileio, res, buffer, &buf_cnt);
796 if (ret != ERROR_OK)
797 goto mg_write_cmd_err;
798 ret = mg_mflash_write(address, buffer, res);
799 if (ret != ERROR_OK)
800 goto mg_write_cmd_err;
803 if (duration_measure(&bench) == ERROR_OK) {
804 command_print(CMD_CTX, "wrote %ld bytes from file %s "
805 "in %fs (%0.3f kB/s)", (long)filesize, CMD_ARGV[1],
806 duration_elapsed(&bench), duration_kbps(&bench, filesize));
809 free(buffer);
810 fileio_close(&fileio);
812 return ERROR_OK;
814 mg_write_cmd_err:
815 free(buffer);
816 fileio_close(&fileio);
818 return ret;
821 COMMAND_HANDLER(mg_dump_cmd)
823 uint32_t address, size, cnt, res, i;
824 uint8_t *buffer;
825 struct fileio fileio;
826 int ret;
828 if (CMD_ARGC != 4)
829 return ERROR_COMMAND_SYNTAX_ERROR;
831 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
832 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], size);
834 ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_WRITE, FILEIO_BINARY);
835 if (ret != ERROR_OK)
836 return ret;
838 buffer = malloc(MG_FILEIO_CHUNK);
839 if (!buffer) {
840 fileio_close(&fileio);
841 return ERROR_FAIL;
844 cnt = size / MG_FILEIO_CHUNK;
845 res = size % MG_FILEIO_CHUNK;
847 struct duration bench;
848 duration_start(&bench);
850 size_t size_written;
851 for (i = 0; i < cnt; i++) {
852 ret = mg_mflash_read(address, buffer, MG_FILEIO_CHUNK);
853 if (ret != ERROR_OK)
854 goto mg_dump_cmd_err;
855 ret = fileio_write(&fileio, MG_FILEIO_CHUNK, buffer, &size_written);
856 if (ret != ERROR_OK)
857 goto mg_dump_cmd_err;
858 address += MG_FILEIO_CHUNK;
861 if (res) {
862 ret = mg_mflash_read(address, buffer, res);
863 if (ret != ERROR_OK)
864 goto mg_dump_cmd_err;
865 ret = fileio_write(&fileio, res, buffer, &size_written);
866 if (ret != ERROR_OK)
867 goto mg_dump_cmd_err;
870 if (duration_measure(&bench) == ERROR_OK) {
871 command_print(CMD_CTX, "dump image (address 0x%8.8" PRIx32 " "
872 "size %" PRIu32 ") to file %s in %fs (%0.3f kB/s)",
873 address, size, CMD_ARGV[1],
874 duration_elapsed(&bench), duration_kbps(&bench, size));
877 free(buffer);
878 fileio_close(&fileio);
880 return ERROR_OK;
882 mg_dump_cmd_err:
883 free(buffer);
884 fileio_close(&fileio);
886 return ret;
889 static int mg_set_feature(mg_feature_id feature, mg_feature_val config)
891 struct target *target = mflash_bank->target;
892 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
893 int ret;
895 ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL);
896 if (ret != ERROR_OK)
897 return ret;
899 ret = target_write_u8(target, mg_task_reg + MG_REG_FEATURE, feature);
900 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, config);
901 ret |= target_write_u8(target, mg_task_reg + MG_REG_COMMAND,
902 mg_io_cmd_set_feature);
904 return ret;
907 static int mg_is_valid_pll(double XIN, int N, double CLK_OUT, int NO)
909 double v1 = XIN / N;
910 double v2 = CLK_OUT * NO;
912 if (v1 < 1000000 || v1 > 15000000 || v2 < 100000000 || v2 > 500000000)
913 return ERROR_MG_INVALID_PLL;
915 return ERROR_OK;
918 static int mg_pll_get_M(unsigned short feedback_div)
920 int i, M;
922 for (i = 1, M = 0; i < 512; i <<= 1, feedback_div >>= 1)
923 M += (feedback_div & 1) * i;
925 return M + 2;
928 static int mg_pll_get_N(unsigned char input_div)
930 int i, N;
932 for (i = 1, N = 0; i < 32; i <<= 1, input_div >>= 1)
933 N += (input_div & 1) * i;
935 return N + 2;
938 static int mg_pll_get_NO(unsigned char output_div)
940 int i, NO;
942 for (i = 0, NO = 1; i < 2; ++i, output_div >>= 1)
943 if (output_div & 1)
944 NO = NO << 1;
946 return NO;
949 static double mg_do_calc_pll(double XIN, mg_pll_t *p_pll_val, int is_approximate)
951 unsigned short i;
952 unsigned char j, k;
953 int M, N, NO;
954 double CLK_OUT;
955 double DIV = 1;
956 double ROUND = 0;
958 if (is_approximate) {
959 DIV = 1000000;
960 ROUND = 500000;
963 for (i = 0; i < MG_PLL_MAX_FEEDBACKDIV_VAL; ++i) {
964 M = mg_pll_get_M(i);
966 for (j = 0; j < MG_PLL_MAX_INPUTDIV_VAL; ++j) {
967 N = mg_pll_get_N(j);
969 for (k = 0; k < MG_PLL_MAX_OUTPUTDIV_VAL; ++k) {
970 NO = mg_pll_get_NO(k);
972 CLK_OUT = XIN * ((double)M / N) / NO;
974 if ((int)((CLK_OUT + ROUND) / DIV)
975 == (int)(MG_PLL_CLK_OUT / DIV)) {
976 if (mg_is_valid_pll(XIN, N, CLK_OUT, NO) == ERROR_OK) {
977 p_pll_val->lock_cyc =
978 (int)(XIN * MG_PLL_STD_LOCKCYCLE /
979 MG_PLL_STD_INPUTCLK);
980 p_pll_val->feedback_div = i;
981 p_pll_val->input_div = j;
982 p_pll_val->output_div = k;
984 return CLK_OUT;
991 return 0;
994 static double mg_calc_pll(double XIN, mg_pll_t *p_pll_val)
996 double CLK_OUT;
998 CLK_OUT = mg_do_calc_pll(XIN, p_pll_val, 0);
1000 if (!CLK_OUT)
1001 return mg_do_calc_pll(XIN, p_pll_val, 1);
1002 else
1003 return CLK_OUT;
1006 static int mg_verify_interface(void)
1008 uint16_t buff[MG_MFLASH_SECTOR_SIZE >> 1];
1009 uint16_t i, j;
1010 uint32_t address = mflash_bank->base + MG_BUFFER_OFFSET;
1011 struct target *target = mflash_bank->target;
1012 int ret;
1014 for (j = 0; j < 10; j++) {
1015 for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++)
1016 buff[i] = i;
1018 ret = target_write_memory(target, address, 2,
1019 MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
1020 if (ret != ERROR_OK)
1021 return ret;
1023 memset(buff, 0xff, MG_MFLASH_SECTOR_SIZE);
1025 ret = target_read_memory(target, address, 2,
1026 MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
1027 if (ret != ERROR_OK)
1028 return ret;
1030 for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++) {
1031 if (buff[i] != i) {
1032 LOG_ERROR("mflash: verify interface fail");
1033 return ERROR_MG_INTERFACE;
1038 LOG_INFO("mflash: verify interface ok");
1039 return ret;
1042 static const char g_strSEG_SerialNum[20] = {
1043 'G', 'm', 'n', 'i', '-', 'e', 'e', 'S', 'g', 'a', 'e', 'l',
1044 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
1047 static const char g_strSEG_FWRev[8] = {
1048 'F', 'X', 'L', 'T', '2', 'v', '0', '.'
1051 static const char g_strSEG_ModelNum[40] = {
1052 'F', 'X', 'A', 'L', 'H', 'S', '2', 0x20, '0', '0', 's', '7',
1053 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1054 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1055 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
1058 static void mg_gen_ataid(mg_io_type_drv_info *pSegIdDrvInfo)
1060 /* b15 is ATA device(0) , b7 is Removable Media Device */
1061 pSegIdDrvInfo->general_configuration = 0x045A;
1062 /* 128MB : Cylinder=> 977 , Heads=> 8 , Sectors=> 32
1063 * 256MB : Cylinder=> 980 , Heads=> 16 , Sectors=> 32
1064 * 384MB : Cylinder=> 745 , Heads=> 16 , Sectors=> 63
1066 pSegIdDrvInfo->number_of_cylinders = 0x02E9;
1067 pSegIdDrvInfo->reserved1 = 0x0;
1068 pSegIdDrvInfo->number_of_heads = 0x10;
1069 pSegIdDrvInfo->unformatted_bytes_per_track = 0x0;
1070 pSegIdDrvInfo->unformatted_bytes_per_sector = 0x0;
1071 pSegIdDrvInfo->sectors_per_track = 0x3F;
1072 pSegIdDrvInfo->vendor_unique1[0] = 0x000B;
1073 pSegIdDrvInfo->vendor_unique1[1] = 0x7570;
1074 pSegIdDrvInfo->vendor_unique1[2] = 0x8888;
1076 memcpy(pSegIdDrvInfo->serial_number, g_strSEG_SerialNum, 20);
1077 /* 0x2 : dual buffer */
1078 pSegIdDrvInfo->buffer_type = 0x2;
1079 /* buffer size : 2KB */
1080 pSegIdDrvInfo->buffer_sector_size = 0x800;
1081 pSegIdDrvInfo->number_of_ecc_bytes = 0;
1083 memcpy(pSegIdDrvInfo->firmware_revision, g_strSEG_FWRev, 8);
1085 memcpy(pSegIdDrvInfo->model_number, g_strSEG_ModelNum, 40);
1087 pSegIdDrvInfo->maximum_block_transfer = 0x4;
1088 pSegIdDrvInfo->vendor_unique2 = 0x0;
1089 pSegIdDrvInfo->dword_io = 0x00;
1090 /* b11 : IORDY support(PIO Mode 4), b10 : Disable/Enbale IORDY
1091 * b9 : LBA support, b8 : DMA mode support
1093 pSegIdDrvInfo->capabilities = 0x1 << 9;
1095 pSegIdDrvInfo->reserved2 = 0x4000;
1096 pSegIdDrvInfo->vendor_unique3 = 0x00;
1097 /* PIOMode-2 support */
1098 pSegIdDrvInfo->pio_cycle_timing_mode = 0x02;
1099 pSegIdDrvInfo->vendor_unique4 = 0x00;
1100 /* MultiWord-2 support */
1101 pSegIdDrvInfo->dma_cycle_timing_mode = 0x00;
1102 /* b1 : word64~70 is valid
1103 * b0 : word54~58 are valid and reflect the current numofcyls,heads,sectors
1104 * b2 : If device supports Ultra DMA , set to one to vaildate word88
1106 pSegIdDrvInfo->translation_fields_valid = (0x1 << 1) | (0x1 << 0);
1107 pSegIdDrvInfo->number_of_current_cylinders = 0x02E9;
1108 pSegIdDrvInfo->number_of_current_heads = 0x10;
1109 pSegIdDrvInfo->current_sectors_per_track = 0x3F;
1110 pSegIdDrvInfo->current_sector_capacity_lo = 0x7570;
1111 pSegIdDrvInfo->current_sector_capacity_hi = 0x000B;
1113 pSegIdDrvInfo->multi_sector_count = 0x04;
1114 /* b8 : Multiple secotr setting valid , b[7:0] num of secotrs per block */
1115 pSegIdDrvInfo->multi_sector_setting_valid = 0x01;
1116 pSegIdDrvInfo->total_user_addressable_sectors_lo = 0x7570;
1117 pSegIdDrvInfo->total_user_addressable_sectors_hi = 0x000B;
1118 pSegIdDrvInfo->single_dma_modes_supported = 0x00;
1119 pSegIdDrvInfo->single_dma_transfer_active = 0x00;
1120 /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
1121 pSegIdDrvInfo->multi_dma_modes_supported = (0x1 << 0);
1122 /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
1123 pSegIdDrvInfo->multi_dma_transfer_active = (0x1 << 0);
1124 /* b0 : PIO Mode-3 support, b1 : PIO Mode-4 support */
1125 pSegIdDrvInfo->adv_pio_mode = 0x00;
1126 /* 480(0x1E0)nsec for Multi-word DMA mode0
1127 * 150(0x96) nsec for Multi-word DMA mode1
1128 * 120(0x78) nsec for Multi-word DMA mode2
1130 pSegIdDrvInfo->min_dma_cyc = 0x1E0;
1131 pSegIdDrvInfo->recommend_dma_cyc = 0x1E0;
1132 pSegIdDrvInfo->min_pio_cyc_no_iordy = 0x1E0;
1133 pSegIdDrvInfo->min_pio_cyc_with_iordy = 0x1E0;
1134 memset(pSegIdDrvInfo->reserved3, 0x00, 22);
1135 /* b7 : ATA/ATAPI-7 ,b6 : ATA/ATAPI-6 ,b5 : ATA/ATAPI-5,b4 : ATA/ATAPI-4 */
1136 pSegIdDrvInfo->major_ver_num = 0x7E;
1137 /* 0x1C : ATA/ATAPI-6 T13 1532D revision1 */
1138 pSegIdDrvInfo->minor_ver_num = 0x19;
1139 /* NOP/READ BUFFER/WRITE BUFFER/Power management feature set support */
1140 pSegIdDrvInfo->feature_cmd_set_suprt0 = 0x7068;
1141 /* Features/command set is valid/Advanced Pwr management/CFA feature set
1142 * not support
1144 pSegIdDrvInfo->feature_cmd_set_suprt1 = 0x400C;
1145 pSegIdDrvInfo->feature_cmd_set_suprt2 = 0x4000;
1146 /* READ/WRITE BUFFER/PWR Management enable */
1147 pSegIdDrvInfo->feature_cmd_set_en0 = 0x7000;
1148 /* CFA feature is disabled / Advancde power management disable */
1149 pSegIdDrvInfo->feature_cmd_set_en1 = 0x0;
1150 pSegIdDrvInfo->feature_cmd_set_en2 = 0x4000;
1151 pSegIdDrvInfo->reserved4 = 0x0;
1152 /* 0x1 * 2minutes */
1153 pSegIdDrvInfo->req_time_for_security_er_done = 0x19;
1154 pSegIdDrvInfo->req_time_for_enhan_security_er_done = 0x19;
1155 /* Advanced power management level 1 */
1156 pSegIdDrvInfo->adv_pwr_mgm_lvl_val = 0x0;
1157 pSegIdDrvInfo->reserved5 = 0x0;
1158 memset(pSegIdDrvInfo->reserved6, 0x00, 68);
1159 /* Security mode feature is disabled */
1160 pSegIdDrvInfo->security_stas = 0x0;
1161 memset(pSegIdDrvInfo->vendor_uniq_bytes, 0x00, 62);
1162 /* CFA power mode 1 support in maximum 200mA */
1163 pSegIdDrvInfo->cfa_pwr_mode = 0x0100;
1164 memset(pSegIdDrvInfo->reserved7, 0x00, 190);
1167 static int mg_storage_config(void)
1169 uint8_t buff[512];
1170 int ret;
1172 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
1173 if (ret != ERROR_OK)
1174 return ret;
1176 mg_gen_ataid((mg_io_type_drv_info *)(void *)buff);
1178 ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_stgdrvinfo);
1179 if (ret != ERROR_OK)
1180 return ret;
1182 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
1183 if (ret != ERROR_OK)
1184 return ret;
1186 LOG_INFO("mflash: storage config ok");
1187 return ret;
1190 static int mg_boot_config(void)
1192 uint8_t buff[512];
1193 int ret;
1195 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
1196 if (ret != ERROR_OK)
1197 return ret;
1199 memset(buff, 0xff, 512);
1201 buff[0] = mg_op_mode_snd; /* operation mode */
1202 buff[1] = MG_UNLOCK_OTP_AREA;
1203 buff[2] = 4; /* boot size */
1204 *((uint32_t *)(void *)(buff + 4)) = 0; /* XIP size */
1206 ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_xipinfo);
1207 if (ret != ERROR_OK)
1208 return ret;
1210 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
1211 if (ret != ERROR_OK)
1212 return ret;
1214 LOG_INFO("mflash: boot config ok");
1215 return ret;
1218 static int mg_set_pll(mg_pll_t *pll)
1220 uint8_t buff[512];
1221 int ret;
1223 memset(buff, 0xff, 512);
1224 /* PLL Lock cycle and Feedback 9bit Divider */
1225 memcpy(buff, &pll->lock_cyc, sizeof(uint32_t));
1226 memcpy(buff + 4, &pll->feedback_div, sizeof(uint16_t));
1227 buff[6] = pll->input_div; /* PLL Input 5bit Divider */
1228 buff[7] = pll->output_div; /* PLL Output Divider */
1230 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
1231 if (ret != ERROR_OK)
1232 return ret;
1234 ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_wr_pll);
1235 if (ret != ERROR_OK)
1236 return ret;
1238 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
1239 if (ret != ERROR_OK)
1240 return ret;
1242 LOG_INFO("mflash: set pll ok");
1243 return ret;
1246 static int mg_erase_nand(void)
1248 int ret;
1250 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
1251 if (ret != ERROR_OK)
1252 return ret;
1254 ret = mg_mflash_do_write_sects(NULL, 0, 0, mg_vcmd_purge_nand);
1255 if (ret != ERROR_OK)
1256 return ret;
1258 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
1259 if (ret != ERROR_OK)
1260 return ret;
1262 LOG_INFO("mflash: erase nand ok");
1263 return ret;
1266 COMMAND_HANDLER(mg_config_cmd)
1268 double fin, fout;
1269 mg_pll_t pll;
1270 int ret;
1272 ret = mg_verify_interface();
1273 if (ret != ERROR_OK)
1274 return ret;
1276 ret = mg_mflash_rst();
1277 if (ret != ERROR_OK)
1278 return ret;
1280 switch (CMD_ARGC) {
1281 case 2:
1282 if (!strcmp(CMD_ARGV[1], "boot"))
1283 return mg_boot_config();
1284 else if (!strcmp(CMD_ARGV[1], "storage"))
1285 return mg_storage_config();
1286 else
1287 return ERROR_COMMAND_NOTFOUND;
1288 break;
1289 case 3:
1290 if (!strcmp(CMD_ARGV[1], "pll")) {
1291 unsigned long freq;
1292 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], freq);
1293 fin = freq;
1295 if (fin > MG_PLL_CLK_OUT) {
1296 LOG_ERROR("mflash: input freq. is too large");
1297 return ERROR_MG_INVALID_OSC;
1300 fout = mg_calc_pll(fin, &pll);
1302 if (!fout) {
1303 LOG_ERROR("mflash: cannot generate valid pll");
1304 return ERROR_MG_INVALID_PLL;
1307 LOG_INFO("mflash: Fout=%" PRIu32 " Hz, feedback=%u,"
1308 "indiv=%u, outdiv=%u, lock=%u",
1309 (uint32_t)fout, pll.feedback_div,
1310 pll.input_div, pll.output_div,
1311 pll.lock_cyc);
1313 ret = mg_erase_nand();
1314 if (ret != ERROR_OK)
1315 return ret;
1317 return mg_set_pll(&pll);
1318 } else
1319 return ERROR_COMMAND_NOTFOUND;
1320 break;
1321 default:
1322 return ERROR_COMMAND_SYNTAX_ERROR;
1326 static const struct command_registration mflash_exec_command_handlers[] = {
1328 .name = "probe",
1329 .handler = mg_probe_cmd,
1330 .mode = COMMAND_EXEC,
1331 .help = "Detect bank configuration information",
1334 .name = "write",
1335 .handler = mg_write_cmd,
1336 .mode = COMMAND_EXEC,
1337 /* FIXME bank_num is unused */
1338 .usage = "bank_num filename address",
1339 .help = "Write binary file at the specified address.",
1342 .name = "dump",
1343 .handler = mg_dump_cmd,
1344 .mode = COMMAND_EXEC,
1345 /* FIXME bank_num is unused */
1346 .usage = "bank_num filename address size",
1347 .help = "Write specified number of bytes from a binary file "
1348 "to the specified, address.",
1351 .name = "config",
1352 .handler = mg_config_cmd,
1353 .mode = COMMAND_EXEC,
1354 .help = "Configure MFLASH options.",
1355 .usage = "('boot'|'storage'|'pll' frequency)",
1357 COMMAND_REGISTRATION_DONE
1360 static int mflash_init_drivers(struct command_context *cmd_ctx)
1362 if (!mflash_bank)
1363 return ERROR_OK;
1364 return register_commands(cmd_ctx, NULL, mflash_exec_command_handlers);
1367 COMMAND_HANDLER(handle_mflash_init_command)
1369 if (CMD_ARGC != 0)
1370 return ERROR_COMMAND_SYNTAX_ERROR;
1372 static bool mflash_initialized;
1373 if (mflash_initialized) {
1374 LOG_INFO("'mflash init' has already been called");
1375 return ERROR_OK;
1377 mflash_initialized = true;
1379 LOG_DEBUG("Initializing mflash devices...");
1380 return mflash_init_drivers(CMD_CTX);
1383 COMMAND_HANDLER(mg_bank_cmd)
1385 struct target *target;
1386 int i;
1388 if (CMD_ARGC < 4)
1389 return ERROR_COMMAND_SYNTAX_ERROR;
1391 target = get_target(CMD_ARGV[3]);
1392 if (target == NULL) {
1393 LOG_ERROR("target '%s' not defined", CMD_ARGV[3]);
1394 return ERROR_FAIL;
1397 mflash_bank = calloc(sizeof(struct mflash_bank), 1);
1398 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], mflash_bank->base);
1399 /** @todo Verify how this parsing should work, then document it. */
1400 char *str;
1401 mflash_bank->rst_pin.num = strtoul(CMD_ARGV[2], &str, 0);
1402 if (*str)
1403 mflash_bank->rst_pin.port[0] = (uint16_t)
1404 tolower((unsigned)str[0]);
1406 mflash_bank->target = target;
1408 for (i = 0; mflash_gpio[i]; i++) {
1409 if (!strcmp(mflash_gpio[i]->name, CMD_ARGV[0]))
1410 mflash_bank->gpio_drv = mflash_gpio[i];
1413 if (!mflash_bank->gpio_drv) {
1414 LOG_ERROR("%s is unsupported soc", CMD_ARGV[0]);
1415 return ERROR_MG_UNSUPPORTED_SOC;
1418 return ERROR_OK;
1421 static const struct command_registration mflash_config_command_handlers[] = {
1423 .name = "bank",
1424 .handler = mg_bank_cmd,
1425 .mode = COMMAND_CONFIG,
1426 .help = "configure a mflash device bank",
1427 .usage = "soc_type base_addr pin_id target",
1430 .name = "init",
1431 .mode = COMMAND_CONFIG,
1432 .handler = handle_mflash_init_command,
1433 .help = "initialize mflash devices",
1434 .usage = ""
1436 COMMAND_REGISTRATION_DONE
1438 static const struct command_registration mflash_command_handler[] = {
1440 .name = "mflash",
1441 .mode = COMMAND_ANY,
1442 .help = "mflash command group",
1443 .usage = "",
1444 .chain = mflash_config_command_handlers,
1446 COMMAND_REGISTRATION_DONE
1448 int mflash_register_commands(struct command_context *cmd_ctx)
1450 return register_commands(cmd_ctx, NULL, mflash_command_handler);