1 /***************************************************************************
2 * Copyright (C) 2007-2008 by unsik Kim <donari75@gmail.com> *
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. *
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. *
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 ***************************************************************************/
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
= {
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
= {
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
[] = {
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
;
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
);
80 if (addr
== PXA270_GAFR3_U
)
81 value
&= ~PXA270_GAFR3_U_RESERVED_BITS
;
83 ret
= target_write_u32(target
, addr
, value
);
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
);
97 if (addr
== PXA270_GPDR3
)
98 value
&= ~PXA270_GPDR3_RESERVED_BITS
;
100 ret
= target_write_u32(target
, addr
, value
);
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
;
110 mask
= 0x1u
<< (gpio
.num
& 0x1F);
113 addr
= PXA270_GPSR0
+ (gpio
.num
>> 5) * 4;
115 addr
= PXA270_GPCR0
+ (gpio
.num
>> 5) * 4;
117 ret
= target_read_u32(target
, addr
, &value
);
123 ret
= target_write_u32(target
, addr
, value
);
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
;
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
;
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
;
155 mask
= 3 << gpio
.num
* 2;
157 data
|= (1 << gpio
.num
* 2);
160 ret
= target_write_u32(target
, gpio_con
, data
);
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
;
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
;
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
;
189 ret
= target_write_u32(target
, gpio_dat
, data
);
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)
202 struct mflash_gpio_drv
*gpio_drv
= mflash_bank
->gpio_drv
;
204 ret
= gpio_drv
->set_gpio_to_output(mflash_bank
->rst_pin
);
208 ret
= gpio_drv
->set_gpio_output_val(mflash_bank
->rst_pin
, 1);
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
;
221 struct duration bench
;
222 duration_start(&bench
);
226 ret
= target_read_u8(target
, mg_task_reg
+ MG_REG_STATUS
, &status
);
230 if (status
& mg_io_rbit_status_busy
) {
231 if (wait_local
== mg_io_wait_bsy
)
234 switch (wait_local
) {
235 case mg_io_wait_not_bsy
:
237 case mg_io_wait_rdy_noerr
:
238 if (status
& mg_io_rbit_status_ready
)
241 case mg_io_wait_drq_noerr
:
242 if (status
& mg_io_rbit_status_data_req
)
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
);
255 LOG_ERROR("mflash: io error 0x%02x", error
);
260 switch (wait_local
) {
262 if (status
& mg_io_rbit_status_ready
)
266 if (status
& mg_io_rbit_status_data_req
)
274 ret
= duration_measure(&bench
);
276 t
= duration_elapsed(&bench
) * 1000.0;
278 LOG_ERROR("mflash: duration measurement failed: %d", ret
);
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
;
295 ret
= target_read_u8(target
, mg_task_reg
+ MG_REG_DRV_CTRL
, &value
);
300 value
|= (mg_io_rbit_devc_srst
);
302 value
&= ~mg_io_rbit_devc_srst
;
304 ret
= target_write_u8(target
, mg_task_reg
+ MG_REG_DRV_CTRL
, value
);
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
;
315 ret
= mg_dsk_wait(mg_io_wait_rdy_noerr
, MG_OEM_DISK_WAIT_TIME_NORMAL
);
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));
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
;
339 ret
= mg_dsk_io_cmd(0, 1, mg_io_cmd_identify
);
343 ret
= mg_dsk_wait(mg_io_wait_drq
, MG_OEM_DISK_WAIT_TIME_NORMAL
);
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
);
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)
371 ret
= mg_init_gpio();
379 ret
= mg_dsk_wait(mg_io_wait_bsy
, MG_OEM_DISK_WAIT_TIME_LONG
);
387 ret
= mg_dsk_wait(mg_io_wait_not_bsy
, MG_OEM_DISK_WAIT_TIME_LONG
);
391 ret
= mg_dsk_srst(1);
395 ret
= mg_dsk_wait(mg_io_wait_bsy
, MG_OEM_DISK_WAIT_TIME_LONG
);
399 ret
= mg_dsk_srst(0);
403 ret
= mg_dsk_wait(mg_io_wait_not_bsy
, MG_OEM_DISK_WAIT_TIME_LONG
);
407 LOG_INFO("mflash: reset ok");
412 static int mg_mflash_probe(void)
414 int ret
= mg_mflash_rst();
418 return mg_dsk_drv_info();
421 COMMAND_HANDLER(mg_probe_cmd
)
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
,
437 static int mg_mflash_do_read_sects(void *buff
, uint32_t sect_num
, uint32_t sect_cnt
)
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
);
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
);
458 ret
= target_read_memory(target
, address
, 2, MG_MFLASH_SECTOR_SIZE
/ 2, buff_ptr
);
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
);
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
;
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",
495 ret
= mg_mflash_do_read_sects(buff_ptr
, sect_num
, 256);
500 buff_ptr
+= 256 * MG_MFLASH_SECTOR_SIZE
;
504 LOG_DEBUG("mflash: sect num : %" PRIx32
" buff : %p",
506 return mg_mflash_do_read_sects(buff_ptr
, sect_num
, residue
);
512 static int mg_mflash_do_write_sects(void *buff
, uint32_t sect_num
, uint32_t sect_cnt
,
517 struct target
*target
= mflash_bank
->target
;
518 uint8_t *buff_ptr
= buff
;
520 ret
= mg_dsk_io_cmd(sect_num
, sect_cnt
, cmd
);
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
);
534 ret
= target_write_memory(target
, address
, 2, MG_MFLASH_SECTOR_SIZE
/ 2, buff_ptr
);
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
);
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
);
559 ret
= mg_dsk_wait(mg_io_wait_rdy
, MG_OEM_DISK_WAIT_TIME_LONG
);
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
;
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
,
576 ret
= mg_mflash_do_write_sects(buff_ptr
, sect_num
, 256, mg_io_cmd_write
);
581 buff_ptr
+= 256 * MG_MFLASH_SECTOR_SIZE
;
585 LOG_DEBUG("mflash: sect num : %" PRIu32
" buff : %p", sect_num
,
587 return mg_mflash_do_write_sects(buff_ptr
, sect_num
, residue
, mg_io_cmd_write
);
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
;
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);
612 if (end_addr
< next_sec_addr
) {
614 sect_buff
+ (cur_addr
& MG_MFLASH_SECTOR_SIZE_MASK
),
615 end_addr
- cur_addr
);
617 "mflash: copies %" PRIu32
" byte from sector offset 0x%8.8" PRIx32
"",
623 sect_buff
+ (cur_addr
& MG_MFLASH_SECTOR_SIZE_MASK
),
624 next_sec_addr
- cur_addr
);
626 "mflash: copies %" PRIu32
" byte from sector offset 0x%8.8" PRIx32
"",
627 next_sec_addr
- 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
) {
641 next_sec_addr
+= MG_MFLASH_SECTOR_SIZE
;
645 ret
= mg_mflash_read_sects(buff_ptr
, sect_num
, cnt
);
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);
660 memcpy(buff_ptr
, sect_buff
, end_addr
- cur_addr
);
661 LOG_DEBUG("mflash: copies %u byte", (unsigned)(end_addr
- cur_addr
));
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
;
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);
687 if (end_addr
< next_sec_addr
) {
688 memcpy(sect_buff
+ (cur_addr
& MG_MFLASH_SECTOR_SIZE_MASK
),
690 end_addr
- cur_addr
);
692 "mflash: copies %" PRIu32
" byte to sector offset 0x%8.8" PRIx32
"",
697 memcpy(sect_buff
+ (cur_addr
& MG_MFLASH_SECTOR_SIZE_MASK
),
699 next_sec_addr
- cur_addr
);
701 "mflash: copies %" PRIu32
" byte to sector offset 0x%8.8" PRIx32
"",
702 next_sec_addr
- 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);
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
) {
720 next_sec_addr
+= MG_MFLASH_SECTOR_SIZE
;
724 ret
= mg_mflash_write_sects(buff_ptr
, sect_num
, cnt
);
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);
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);
748 COMMAND_HANDLER(mg_write_cmd
)
750 uint32_t address
, cnt
, res
, i
;
752 struct fileio fileio
;
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
);
765 buffer
= malloc(MG_FILEIO_CHUNK
);
767 fileio_close(&fileio
);
770 int retval
= fileio_size(&fileio
, &filesize
);
771 if (retval
!= ERROR_OK
) {
772 fileio_close(&fileio
);
776 cnt
= filesize
/ MG_FILEIO_CHUNK
;
777 res
= filesize
% MG_FILEIO_CHUNK
;
779 struct duration bench
;
780 duration_start(&bench
);
783 for (i
= 0; i
< cnt
; i
++) {
784 ret
= fileio_read(&fileio
, MG_FILEIO_CHUNK
, buffer
, &buf_cnt
);
786 goto mg_write_cmd_err
;
787 ret
= mg_mflash_write(address
, buffer
, MG_FILEIO_CHUNK
);
789 goto mg_write_cmd_err
;
790 address
+= MG_FILEIO_CHUNK
;
794 ret
= fileio_read(&fileio
, res
, buffer
, &buf_cnt
);
796 goto mg_write_cmd_err
;
797 ret
= mg_mflash_write(address
, buffer
, res
);
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
));
809 fileio_close(&fileio
);
815 fileio_close(&fileio
);
820 COMMAND_HANDLER(mg_dump_cmd
)
822 uint32_t address
, size
, cnt
, res
, i
;
824 struct fileio fileio
;
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
);
837 buffer
= malloc(MG_FILEIO_CHUNK
);
839 fileio_close(&fileio
);
843 cnt
= size
/ MG_FILEIO_CHUNK
;
844 res
= size
% MG_FILEIO_CHUNK
;
846 struct duration bench
;
847 duration_start(&bench
);
850 for (i
= 0; i
< cnt
; i
++) {
851 ret
= mg_mflash_read(address
, buffer
, MG_FILEIO_CHUNK
);
853 goto mg_dump_cmd_err
;
854 ret
= fileio_write(&fileio
, MG_FILEIO_CHUNK
, buffer
, &size_written
);
856 goto mg_dump_cmd_err
;
857 address
+= MG_FILEIO_CHUNK
;
861 ret
= mg_mflash_read(address
, buffer
, res
);
863 goto mg_dump_cmd_err
;
864 ret
= fileio_write(&fileio
, res
, buffer
, &size_written
);
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
));
877 fileio_close(&fileio
);
883 fileio_close(&fileio
);
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
;
894 ret
= mg_dsk_wait(mg_io_wait_rdy_noerr
, MG_OEM_DISK_WAIT_TIME_NORMAL
);
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
);
906 static int mg_is_valid_pll(double XIN
, int N
, double CLK_OUT
, int NO
)
909 double v2
= CLK_OUT
* NO
;
911 if (v1
< 1000000 || v1
> 15000000 || v2
< 100000000 || v2
> 500000000)
912 return ERROR_MG_INVALID_PLL
;
917 static int mg_pll_get_M(unsigned short feedback_div
)
921 for (i
= 1, M
= 0; i
< 512; i
<<= 1, feedback_div
>>= 1)
922 M
+= (feedback_div
& 1) * i
;
927 static int mg_pll_get_N(unsigned char input_div
)
931 for (i
= 1, N
= 0; i
< 32; i
<<= 1, input_div
>>= 1)
932 N
+= (input_div
& 1) * i
;
937 static int mg_pll_get_NO(unsigned char output_div
)
941 for (i
= 0, NO
= 1; i
< 2; ++i
, output_div
>>= 1)
948 static double mg_do_calc_pll(double XIN
, mg_pll_t
*p_pll_val
, int is_approximate
)
957 if (is_approximate
) {
962 for (i
= 0; i
< MG_PLL_MAX_FEEDBACKDIV_VAL
; ++i
) {
965 for (j
= 0; j
< MG_PLL_MAX_INPUTDIV_VAL
; ++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
;
993 static double mg_calc_pll(double XIN
, mg_pll_t
*p_pll_val
)
997 CLK_OUT
= mg_do_calc_pll(XIN
, p_pll_val
, 0);
1000 return mg_do_calc_pll(XIN
, p_pll_val
, 1);
1005 static int mg_verify_interface(void)
1007 uint16_t buff
[MG_MFLASH_SECTOR_SIZE
>> 1];
1009 uint32_t address
= mflash_bank
->base
+ MG_BUFFER_OFFSET
;
1010 struct target
*target
= mflash_bank
->target
;
1013 for (j
= 0; j
< 10; j
++) {
1014 for (i
= 0; i
< MG_MFLASH_SECTOR_SIZE
>> 1; i
++)
1017 ret
= target_write_memory(target
, address
, 2,
1018 MG_MFLASH_SECTOR_SIZE
/ 2, (uint8_t *)buff
);
1019 if (ret
!= ERROR_OK
)
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
)
1029 for (i
= 0; i
< MG_MFLASH_SECTOR_SIZE
>> 1; i
++) {
1031 LOG_ERROR("mflash: verify interface fail");
1032 return ERROR_MG_INTERFACE
;
1037 LOG_INFO("mflash: verify interface ok");
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
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)
1171 ret
= mg_set_feature(mg_feature_id_transmode
, mg_feature_val_trans_vcmd
);
1172 if (ret
!= ERROR_OK
)
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
)
1181 ret
= mg_set_feature(mg_feature_id_transmode
, mg_feature_val_trans_default
);
1182 if (ret
!= ERROR_OK
)
1185 LOG_INFO("mflash: storage config ok");
1189 static int mg_boot_config(void)
1194 ret
= mg_set_feature(mg_feature_id_transmode
, mg_feature_val_trans_vcmd
);
1195 if (ret
!= ERROR_OK
)
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
)
1209 ret
= mg_set_feature(mg_feature_id_transmode
, mg_feature_val_trans_default
);
1210 if (ret
!= ERROR_OK
)
1213 LOG_INFO("mflash: boot config ok");
1217 static int mg_set_pll(mg_pll_t
*pll
)
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
)
1233 ret
= mg_mflash_do_write_sects(buff
, 0, 1, mg_vcmd_wr_pll
);
1234 if (ret
!= ERROR_OK
)
1237 ret
= mg_set_feature(mg_feature_id_transmode
, mg_feature_val_trans_default
);
1238 if (ret
!= ERROR_OK
)
1241 LOG_INFO("mflash: set pll ok");
1245 static int mg_erase_nand(void)
1249 ret
= mg_set_feature(mg_feature_id_transmode
, mg_feature_val_trans_vcmd
);
1250 if (ret
!= ERROR_OK
)
1253 ret
= mg_mflash_do_write_sects(NULL
, 0, 0, mg_vcmd_purge_nand
);
1254 if (ret
!= ERROR_OK
)
1257 ret
= mg_set_feature(mg_feature_id_transmode
, mg_feature_val_trans_default
);
1258 if (ret
!= ERROR_OK
)
1261 LOG_INFO("mflash: erase nand ok");
1265 COMMAND_HANDLER(mg_config_cmd
)
1271 ret
= mg_verify_interface();
1272 if (ret
!= ERROR_OK
)
1275 ret
= mg_mflash_rst();
1276 if (ret
!= ERROR_OK
)
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();
1286 return ERROR_COMMAND_NOTFOUND
;
1289 if (!strcmp(CMD_ARGV
[1], "pll")) {
1291 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[2], 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
);
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
,
1312 ret
= mg_erase_nand();
1313 if (ret
!= ERROR_OK
)
1316 return mg_set_pll(&pll
);
1318 return ERROR_COMMAND_NOTFOUND
;
1321 return ERROR_COMMAND_SYNTAX_ERROR
;
1325 static const struct command_registration mflash_exec_command_handlers
[] = {
1328 .handler
= mg_probe_cmd
,
1329 .mode
= COMMAND_EXEC
,
1330 .help
= "Detect bank configuration information",
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.",
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.",
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
)
1363 return register_commands(cmd_ctx
, NULL
, mflash_exec_command_handlers
);
1366 COMMAND_HANDLER(handle_mflash_init_command
)
1369 return ERROR_COMMAND_SYNTAX_ERROR
;
1371 static bool mflash_initialized
;
1372 if (mflash_initialized
) {
1373 LOG_INFO("'mflash init' has already been called");
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
;
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]);
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. */
1400 mflash_bank
->rst_pin
.num
= strtoul(CMD_ARGV
[2], &str
, 0);
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
;
1420 static const struct command_registration mflash_config_command_handlers
[] = {
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",
1430 .mode
= COMMAND_CONFIG
,
1431 .handler
= handle_mflash_init_command
,
1432 .help
= "initialize mflash devices",
1435 COMMAND_REGISTRATION_DONE
1437 static const struct command_registration mflash_command_handler
[] = {
1440 .mode
= COMMAND_ANY
,
1441 .help
= "mflash command group",
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
);