doxygen: use correct comment syntax
[openocd/andreasf.git] / src / flash / mflash.c
blobbf61a11495fdf3d319bea530eb4f1a58072230d5
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 ***************************************************************************/
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 mg_io_type_cmd 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 return retval;
776 cnt = filesize / MG_FILEIO_CHUNK;
777 res = filesize % MG_FILEIO_CHUNK;
779 struct duration bench;
780 duration_start(&bench);
782 size_t buf_cnt;
783 for (i = 0; i < cnt; i++) {
784 ret = fileio_read(&fileio, MG_FILEIO_CHUNK, buffer, &buf_cnt);
785 if (ret != ERROR_OK)
786 goto mg_write_cmd_err;
787 ret = mg_mflash_write(address, buffer, MG_FILEIO_CHUNK);
788 if (ret != ERROR_OK)
789 goto mg_write_cmd_err;
790 address += MG_FILEIO_CHUNK;
793 if (res) {
794 ret = fileio_read(&fileio, res, buffer, &buf_cnt);
795 if (ret != ERROR_OK)
796 goto mg_write_cmd_err;
797 ret = mg_mflash_write(address, buffer, res);
798 if (ret != ERROR_OK)
799 goto mg_write_cmd_err;
802 if (duration_measure(&bench) == ERROR_OK) {
803 command_print(CMD_CTX, "wrote %ld bytes from file %s "
804 "in %fs (%0.3f kB/s)", (long)filesize, CMD_ARGV[1],
805 duration_elapsed(&bench), duration_kbps(&bench, filesize));
808 free(buffer);
809 fileio_close(&fileio);
811 return ERROR_OK;
813 mg_write_cmd_err:
814 free(buffer);
815 fileio_close(&fileio);
817 return ret;
820 COMMAND_HANDLER(mg_dump_cmd)
822 uint32_t address, size, cnt, res, i;
823 uint8_t *buffer;
824 struct fileio fileio;
825 int ret;
827 if (CMD_ARGC != 4)
828 return ERROR_COMMAND_SYNTAX_ERROR;
830 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
831 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], size);
833 ret = fileio_open(&fileio, CMD_ARGV[1], FILEIO_WRITE, FILEIO_BINARY);
834 if (ret != ERROR_OK)
835 return ret;
837 buffer = malloc(MG_FILEIO_CHUNK);
838 if (!buffer) {
839 fileio_close(&fileio);
840 return ERROR_FAIL;
843 cnt = size / MG_FILEIO_CHUNK;
844 res = size % MG_FILEIO_CHUNK;
846 struct duration bench;
847 duration_start(&bench);
849 size_t size_written;
850 for (i = 0; i < cnt; i++) {
851 ret = mg_mflash_read(address, buffer, MG_FILEIO_CHUNK);
852 if (ret != ERROR_OK)
853 goto mg_dump_cmd_err;
854 ret = fileio_write(&fileio, MG_FILEIO_CHUNK, buffer, &size_written);
855 if (ret != ERROR_OK)
856 goto mg_dump_cmd_err;
857 address += MG_FILEIO_CHUNK;
860 if (res) {
861 ret = mg_mflash_read(address, buffer, res);
862 if (ret != ERROR_OK)
863 goto mg_dump_cmd_err;
864 ret = fileio_write(&fileio, res, buffer, &size_written);
865 if (ret != ERROR_OK)
866 goto mg_dump_cmd_err;
869 if (duration_measure(&bench) == ERROR_OK) {
870 command_print(CMD_CTX, "dump image (address 0x%8.8" PRIx32 " "
871 "size %" PRIu32 ") to file %s in %fs (%0.3f kB/s)",
872 address, size, CMD_ARGV[1],
873 duration_elapsed(&bench), duration_kbps(&bench, size));
876 free(buffer);
877 fileio_close(&fileio);
879 return ERROR_OK;
881 mg_dump_cmd_err:
882 free(buffer);
883 fileio_close(&fileio);
885 return ret;
888 static int mg_set_feature(mg_feature_id feature, mg_feature_val config)
890 struct target *target = mflash_bank->target;
891 uint32_t mg_task_reg = mflash_bank->base + MG_REG_OFFSET;
892 int ret;
894 ret = mg_dsk_wait(mg_io_wait_rdy_noerr, MG_OEM_DISK_WAIT_TIME_NORMAL);
895 if (ret != ERROR_OK)
896 return ret;
898 ret = target_write_u8(target, mg_task_reg + MG_REG_FEATURE, feature);
899 ret |= target_write_u8(target, mg_task_reg + MG_REG_SECT_CNT, config);
900 ret |= target_write_u8(target, mg_task_reg + MG_REG_COMMAND,
901 mg_io_cmd_set_feature);
903 return ret;
906 static int mg_is_valid_pll(double XIN, int N, double CLK_OUT, int NO)
908 double v1 = XIN / N;
909 double v2 = CLK_OUT * NO;
911 if (v1 < 1000000 || v1 > 15000000 || v2 < 100000000 || v2 > 500000000)
912 return ERROR_MG_INVALID_PLL;
914 return ERROR_OK;
917 static int mg_pll_get_M(unsigned short feedback_div)
919 int i, M;
921 for (i = 1, M = 0; i < 512; i <<= 1, feedback_div >>= 1)
922 M += (feedback_div & 1) * i;
924 return M + 2;
927 static int mg_pll_get_N(unsigned char input_div)
929 int i, N;
931 for (i = 1, N = 0; i < 32; i <<= 1, input_div >>= 1)
932 N += (input_div & 1) * i;
934 return N + 2;
937 static int mg_pll_get_NO(unsigned char output_div)
939 int i, NO;
941 for (i = 0, NO = 1; i < 2; ++i, output_div >>= 1)
942 if (output_div & 1)
943 NO = NO << 1;
945 return NO;
948 static double mg_do_calc_pll(double XIN, mg_pll_t *p_pll_val, int is_approximate)
950 unsigned short i;
951 unsigned char j, k;
952 int M, N, NO;
953 double CLK_OUT;
954 double DIV = 1;
955 double ROUND = 0;
957 if (is_approximate) {
958 DIV = 1000000;
959 ROUND = 500000;
962 for (i = 0; i < MG_PLL_MAX_FEEDBACKDIV_VAL; ++i) {
963 M = mg_pll_get_M(i);
965 for (j = 0; j < MG_PLL_MAX_INPUTDIV_VAL; ++j) {
966 N = mg_pll_get_N(j);
968 for (k = 0; k < MG_PLL_MAX_OUTPUTDIV_VAL; ++k) {
969 NO = mg_pll_get_NO(k);
971 CLK_OUT = XIN * ((double)M / N) / NO;
973 if ((int)((CLK_OUT + ROUND) / DIV)
974 == (int)(MG_PLL_CLK_OUT / DIV)) {
975 if (mg_is_valid_pll(XIN, N, CLK_OUT, NO) == ERROR_OK) {
976 p_pll_val->lock_cyc =
977 (int)(XIN * MG_PLL_STD_LOCKCYCLE /
978 MG_PLL_STD_INPUTCLK);
979 p_pll_val->feedback_div = i;
980 p_pll_val->input_div = j;
981 p_pll_val->output_div = k;
983 return CLK_OUT;
990 return 0;
993 static double mg_calc_pll(double XIN, mg_pll_t *p_pll_val)
995 double CLK_OUT;
997 CLK_OUT = mg_do_calc_pll(XIN, p_pll_val, 0);
999 if (!CLK_OUT)
1000 return mg_do_calc_pll(XIN, p_pll_val, 1);
1001 else
1002 return CLK_OUT;
1005 static int mg_verify_interface(void)
1007 uint16_t buff[MG_MFLASH_SECTOR_SIZE >> 1];
1008 uint16_t i, j;
1009 uint32_t address = mflash_bank->base + MG_BUFFER_OFFSET;
1010 struct target *target = mflash_bank->target;
1011 int ret;
1013 for (j = 0; j < 10; j++) {
1014 for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++)
1015 buff[i] = i;
1017 ret = target_write_memory(target, address, 2,
1018 MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
1019 if (ret != ERROR_OK)
1020 return ret;
1022 memset(buff, 0xff, MG_MFLASH_SECTOR_SIZE);
1024 ret = target_read_memory(target, address, 2,
1025 MG_MFLASH_SECTOR_SIZE / 2, (uint8_t *)buff);
1026 if (ret != ERROR_OK)
1027 return ret;
1029 for (i = 0; i < MG_MFLASH_SECTOR_SIZE >> 1; i++) {
1030 if (buff[i] != i) {
1031 LOG_ERROR("mflash: verify interface fail");
1032 return ERROR_MG_INTERFACE;
1037 LOG_INFO("mflash: verify interface ok");
1038 return ret;
1041 static const char g_strSEG_SerialNum[20] = {
1042 'G', 'm', 'n', 'i', '-', 'e', 'e', 'S', 'g', 'a', 'e', 'l',
1043 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
1046 static const char g_strSEG_FWRev[8] = {
1047 'F', 'X', 'L', 'T', '2', 'v', '0', '.'
1050 static const char g_strSEG_ModelNum[40] = {
1051 'F', 'X', 'A', 'L', 'H', 'S', '2', 0x20, '0', '0', 's', '7',
1052 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1053 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1054 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
1057 static void mg_gen_ataid(mg_io_type_drv_info *pSegIdDrvInfo)
1059 /* b15 is ATA device(0) , b7 is Removable Media Device */
1060 pSegIdDrvInfo->general_configuration = 0x045A;
1061 /* 128MB : Cylinder=> 977 , Heads=> 8 , Sectors=> 32
1062 * 256MB : Cylinder=> 980 , Heads=> 16 , Sectors=> 32
1063 * 384MB : Cylinder=> 745 , Heads=> 16 , Sectors=> 63
1065 pSegIdDrvInfo->number_of_cylinders = 0x02E9;
1066 pSegIdDrvInfo->reserved1 = 0x0;
1067 pSegIdDrvInfo->number_of_heads = 0x10;
1068 pSegIdDrvInfo->unformatted_bytes_per_track = 0x0;
1069 pSegIdDrvInfo->unformatted_bytes_per_sector = 0x0;
1070 pSegIdDrvInfo->sectors_per_track = 0x3F;
1071 pSegIdDrvInfo->vendor_unique1[0] = 0x000B;
1072 pSegIdDrvInfo->vendor_unique1[1] = 0x7570;
1073 pSegIdDrvInfo->vendor_unique1[2] = 0x8888;
1075 memcpy(pSegIdDrvInfo->serial_number, (void *)g_strSEG_SerialNum, 20);
1076 /* 0x2 : dual buffer */
1077 pSegIdDrvInfo->buffer_type = 0x2;
1078 /* buffer size : 2KB */
1079 pSegIdDrvInfo->buffer_sector_size = 0x800;
1080 pSegIdDrvInfo->number_of_ecc_bytes = 0;
1082 memcpy(pSegIdDrvInfo->firmware_revision, (void *)g_strSEG_FWRev, 8);
1084 memcpy(pSegIdDrvInfo->model_number, (void *)g_strSEG_ModelNum, 40);
1086 pSegIdDrvInfo->maximum_block_transfer = 0x4;
1087 pSegIdDrvInfo->vendor_unique2 = 0x0;
1088 pSegIdDrvInfo->dword_io = 0x00;
1089 /* b11 : IORDY support(PIO Mode 4), b10 : Disable/Enbale IORDY
1090 * b9 : LBA support, b8 : DMA mode support
1092 pSegIdDrvInfo->capabilities = 0x1 << 9;
1094 pSegIdDrvInfo->reserved2 = 0x4000;
1095 pSegIdDrvInfo->vendor_unique3 = 0x00;
1096 /* PIOMode-2 support */
1097 pSegIdDrvInfo->pio_cycle_timing_mode = 0x02;
1098 pSegIdDrvInfo->vendor_unique4 = 0x00;
1099 /* MultiWord-2 support */
1100 pSegIdDrvInfo->dma_cycle_timing_mode = 0x00;
1101 /* b1 : word64~70 is valid
1102 * b0 : word54~58 are valid and reflect the current numofcyls,heads,sectors
1103 * b2 : If device supports Ultra DMA , set to one to vaildate word88
1105 pSegIdDrvInfo->translation_fields_valid = (0x1 << 1) | (0x1 << 0);
1106 pSegIdDrvInfo->number_of_current_cylinders = 0x02E9;
1107 pSegIdDrvInfo->number_of_current_heads = 0x10;
1108 pSegIdDrvInfo->current_sectors_per_track = 0x3F;
1109 pSegIdDrvInfo->current_sector_capacity_lo = 0x7570;
1110 pSegIdDrvInfo->current_sector_capacity_hi = 0x000B;
1112 pSegIdDrvInfo->multi_sector_count = 0x04;
1113 /* b8 : Multiple secotr setting valid , b[7:0] num of secotrs per block */
1114 pSegIdDrvInfo->multi_sector_setting_valid = 0x01;
1115 pSegIdDrvInfo->total_user_addressable_sectors_lo = 0x7570;
1116 pSegIdDrvInfo->total_user_addressable_sectors_hi = 0x000B;
1117 pSegIdDrvInfo->single_dma_modes_supported = 0x00;
1118 pSegIdDrvInfo->single_dma_transfer_active = 0x00;
1119 /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
1120 pSegIdDrvInfo->multi_dma_modes_supported = (0x1 << 0);
1121 /* b2 :Multi-word DMA mode 2, b1 : Multi-word DMA mode 1 */
1122 pSegIdDrvInfo->multi_dma_transfer_active = (0x1 << 0);
1123 /* b0 : PIO Mode-3 support, b1 : PIO Mode-4 support */
1124 pSegIdDrvInfo->adv_pio_mode = 0x00;
1125 /* 480(0x1E0)nsec for Multi-word DMA mode0
1126 * 150(0x96) nsec for Multi-word DMA mode1
1127 * 120(0x78) nsec for Multi-word DMA mode2
1129 pSegIdDrvInfo->min_dma_cyc = 0x1E0;
1130 pSegIdDrvInfo->recommend_dma_cyc = 0x1E0;
1131 pSegIdDrvInfo->min_pio_cyc_no_iordy = 0x1E0;
1132 pSegIdDrvInfo->min_pio_cyc_with_iordy = 0x1E0;
1133 memset((void *)pSegIdDrvInfo->reserved3, 0x00, 22);
1134 /* b7 : ATA/ATAPI-7 ,b6 : ATA/ATAPI-6 ,b5 : ATA/ATAPI-5,b4 : ATA/ATAPI-4 */
1135 pSegIdDrvInfo->major_ver_num = 0x7E;
1136 /* 0x1C : ATA/ATAPI-6 T13 1532D revision1 */
1137 pSegIdDrvInfo->minor_ver_num = 0x19;
1138 /* NOP/READ BUFFER/WRITE BUFFER/Power management feature set support */
1139 pSegIdDrvInfo->feature_cmd_set_suprt0 = 0x7068;
1140 /* Features/command set is valid/Advanced Pwr management/CFA feature set
1141 * not support
1143 pSegIdDrvInfo->feature_cmd_set_suprt1 = 0x400C;
1144 pSegIdDrvInfo->feature_cmd_set_suprt2 = 0x4000;
1145 /* READ/WRITE BUFFER/PWR Management enable */
1146 pSegIdDrvInfo->feature_cmd_set_en0 = 0x7000;
1147 /* CFA feature is disabled / Advancde power management disable */
1148 pSegIdDrvInfo->feature_cmd_set_en1 = 0x0;
1149 pSegIdDrvInfo->feature_cmd_set_en2 = 0x4000;
1150 pSegIdDrvInfo->reserved4 = 0x0;
1151 /* 0x1 * 2minutes */
1152 pSegIdDrvInfo->req_time_for_security_er_done = 0x19;
1153 pSegIdDrvInfo->req_time_for_enhan_security_er_done = 0x19;
1154 /* Advanced power management level 1 */
1155 pSegIdDrvInfo->adv_pwr_mgm_lvl_val = 0x0;
1156 pSegIdDrvInfo->reserved5 = 0x0;
1157 memset((void *)pSegIdDrvInfo->reserved6, 0x00, 68);
1158 /* Security mode feature is disabled */
1159 pSegIdDrvInfo->security_stas = 0x0;
1160 memset((void *)pSegIdDrvInfo->vendor_uniq_bytes, 0x00, 62);
1161 /* CFA power mode 1 support in maximum 200mA */
1162 pSegIdDrvInfo->cfa_pwr_mode = 0x0100;
1163 memset((void *)pSegIdDrvInfo->reserved7, 0x00, 190);
1166 static int mg_storage_config(void)
1168 uint8_t buff[512];
1169 int ret;
1171 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
1172 if (ret != ERROR_OK)
1173 return ret;
1175 mg_gen_ataid((mg_io_type_drv_info *)(void *)buff);
1177 ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_stgdrvinfo);
1178 if (ret != ERROR_OK)
1179 return ret;
1181 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
1182 if (ret != ERROR_OK)
1183 return ret;
1185 LOG_INFO("mflash: storage config ok");
1186 return ret;
1189 static int mg_boot_config(void)
1191 uint8_t buff[512];
1192 int ret;
1194 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
1195 if (ret != ERROR_OK)
1196 return ret;
1198 memset(buff, 0xff, 512);
1200 buff[0] = mg_op_mode_snd; /* operation mode */
1201 buff[1] = MG_UNLOCK_OTP_AREA;
1202 buff[2] = 4; /* boot size */
1203 *((uint32_t *)(void *)(buff + 4)) = 0; /* XIP size */
1205 ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_update_xipinfo);
1206 if (ret != ERROR_OK)
1207 return ret;
1209 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
1210 if (ret != ERROR_OK)
1211 return ret;
1213 LOG_INFO("mflash: boot config ok");
1214 return ret;
1217 static int mg_set_pll(mg_pll_t *pll)
1219 uint8_t buff[512];
1220 int ret;
1222 memset(buff, 0xff, 512);
1223 /* PLL Lock cycle and Feedback 9bit Divider */
1224 memcpy(buff, &pll->lock_cyc, sizeof(uint32_t));
1225 memcpy(buff + 4, &pll->feedback_div, sizeof(uint16_t));
1226 buff[6] = pll->input_div; /* PLL Input 5bit Divider */
1227 buff[7] = pll->output_div; /* PLL Output Divider */
1229 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
1230 if (ret != ERROR_OK)
1231 return ret;
1233 ret = mg_mflash_do_write_sects(buff, 0, 1, mg_vcmd_wr_pll);
1234 if (ret != ERROR_OK)
1235 return ret;
1237 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
1238 if (ret != ERROR_OK)
1239 return ret;
1241 LOG_INFO("mflash: set pll ok");
1242 return ret;
1245 static int mg_erase_nand(void)
1247 int ret;
1249 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_vcmd);
1250 if (ret != ERROR_OK)
1251 return ret;
1253 ret = mg_mflash_do_write_sects(NULL, 0, 0, mg_vcmd_purge_nand);
1254 if (ret != ERROR_OK)
1255 return ret;
1257 ret = mg_set_feature(mg_feature_id_transmode, mg_feature_val_trans_default);
1258 if (ret != ERROR_OK)
1259 return ret;
1261 LOG_INFO("mflash: erase nand ok");
1262 return ret;
1265 COMMAND_HANDLER(mg_config_cmd)
1267 double fin, fout;
1268 mg_pll_t pll;
1269 int ret;
1271 ret = mg_verify_interface();
1272 if (ret != ERROR_OK)
1273 return ret;
1275 ret = mg_mflash_rst();
1276 if (ret != ERROR_OK)
1277 return ret;
1279 switch (CMD_ARGC) {
1280 case 2:
1281 if (!strcmp(CMD_ARGV[1], "boot"))
1282 return mg_boot_config();
1283 else if (!strcmp(CMD_ARGV[1], "storage"))
1284 return mg_storage_config();
1285 else
1286 return ERROR_COMMAND_NOTFOUND;
1287 break;
1288 case 3:
1289 if (!strcmp(CMD_ARGV[1], "pll")) {
1290 unsigned long freq;
1291 COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], freq);
1292 fin = freq;
1294 if (fin > MG_PLL_CLK_OUT) {
1295 LOG_ERROR("mflash: input freq. is too large");
1296 return ERROR_MG_INVALID_OSC;
1299 fout = mg_calc_pll(fin, &pll);
1301 if (!fout) {
1302 LOG_ERROR("mflash: cannot generate valid pll");
1303 return ERROR_MG_INVALID_PLL;
1306 LOG_INFO("mflash: Fout=%" PRIu32 " Hz, feedback=%u,"
1307 "indiv=%u, outdiv=%u, lock=%u",
1308 (uint32_t)fout, pll.feedback_div,
1309 pll.input_div, pll.output_div,
1310 pll.lock_cyc);
1312 ret = mg_erase_nand();
1313 if (ret != ERROR_OK)
1314 return ret;
1316 return mg_set_pll(&pll);
1317 } else
1318 return ERROR_COMMAND_NOTFOUND;
1319 break;
1320 default:
1321 return ERROR_COMMAND_SYNTAX_ERROR;
1325 static const struct command_registration mflash_exec_command_handlers[] = {
1327 .name = "probe",
1328 .handler = mg_probe_cmd,
1329 .mode = COMMAND_EXEC,
1330 .help = "Detect bank configuration information",
1333 .name = "write",
1334 .handler = mg_write_cmd,
1335 .mode = COMMAND_EXEC,
1336 /* FIXME bank_num is unused */
1337 .usage = "bank_num filename address",
1338 .help = "Write binary file at the specified address.",
1341 .name = "dump",
1342 .handler = mg_dump_cmd,
1343 .mode = COMMAND_EXEC,
1344 /* FIXME bank_num is unused */
1345 .usage = "bank_num filename address size",
1346 .help = "Write specified number of bytes from a binary file "
1347 "to the specified, address.",
1350 .name = "config",
1351 .handler = mg_config_cmd,
1352 .mode = COMMAND_EXEC,
1353 .help = "Configure MFLASH options.",
1354 .usage = "('boot'|'storage'|'pll' frequency)",
1356 COMMAND_REGISTRATION_DONE
1359 static int mflash_init_drivers(struct command_context *cmd_ctx)
1361 if (!mflash_bank)
1362 return ERROR_OK;
1363 return register_commands(cmd_ctx, NULL, mflash_exec_command_handlers);
1366 COMMAND_HANDLER(handle_mflash_init_command)
1368 if (CMD_ARGC != 0)
1369 return ERROR_COMMAND_SYNTAX_ERROR;
1371 static bool mflash_initialized;
1372 if (mflash_initialized) {
1373 LOG_INFO("'mflash init' has already been called");
1374 return ERROR_OK;
1376 mflash_initialized = true;
1378 LOG_DEBUG("Initializing mflash devices...");
1379 return mflash_init_drivers(CMD_CTX);
1382 COMMAND_HANDLER(mg_bank_cmd)
1384 struct target *target;
1385 int i;
1387 if (CMD_ARGC < 4)
1388 return ERROR_COMMAND_SYNTAX_ERROR;
1390 target = get_target(CMD_ARGV[3]);
1391 if (target == NULL) {
1392 LOG_ERROR("target '%s' not defined", CMD_ARGV[3]);
1393 return ERROR_FAIL;
1396 mflash_bank = calloc(sizeof(struct mflash_bank), 1);
1397 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], mflash_bank->base);
1398 /** @todo Verify how this parsing should work, then document it. */
1399 char *str;
1400 mflash_bank->rst_pin.num = strtoul(CMD_ARGV[2], &str, 0);
1401 if (*str)
1402 mflash_bank->rst_pin.port[0] = (uint16_t)
1403 tolower((unsigned)str[0]);
1405 mflash_bank->target = target;
1407 for (i = 0; mflash_gpio[i]; i++) {
1408 if (!strcmp(mflash_gpio[i]->name, CMD_ARGV[0]))
1409 mflash_bank->gpio_drv = mflash_gpio[i];
1412 if (!mflash_bank->gpio_drv) {
1413 LOG_ERROR("%s is unsupported soc", CMD_ARGV[0]);
1414 return ERROR_MG_UNSUPPORTED_SOC;
1417 return ERROR_OK;
1420 static const struct command_registration mflash_config_command_handlers[] = {
1422 .name = "bank",
1423 .handler = mg_bank_cmd,
1424 .mode = COMMAND_CONFIG,
1425 .help = "configure a mflash device bank",
1426 .usage = "soc_type base_addr pin_id target",
1429 .name = "init",
1430 .mode = COMMAND_CONFIG,
1431 .handler = handle_mflash_init_command,
1432 .help = "initialize mflash devices",
1433 .usage = ""
1435 COMMAND_REGISTRATION_DONE
1437 static const struct command_registration mflash_command_handler[] = {
1439 .name = "mflash",
1440 .mode = COMMAND_ANY,
1441 .help = "mflash command group",
1442 .usage = "",
1443 .chain = mflash_config_command_handlers,
1445 COMMAND_REGISTRATION_DONE
1447 int mflash_register_commands(struct command_context *cmd_ctx)
1449 return register_commands(cmd_ctx, NULL, mflash_command_handler);