]> git.ipfire.org Git - people/ms/u-boot.git/blob - common/cmd_onenand.c
Merge branch 'next' of git://git.denx.de/u-boot-avr32
[people/ms/u-boot.git] / common / cmd_onenand.c
1 /*
2 * U-Boot command for OneNAND support
3 *
4 * Copyright (C) 2005-2007 Samsung Electronics
5 * Kyungmin Park <kyungmin.park@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12 #include <common.h>
13 #include <command.h>
14
15 #include <linux/mtd/compat.h>
16 #include <linux/mtd/mtd.h>
17 #include <linux/mtd/onenand.h>
18
19 #include <asm/io.h>
20
21 extern struct mtd_info onenand_mtd;
22 extern struct onenand_chip onenand_chip;
23
24 int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
25 {
26 int ret = 0;
27
28 switch (argc) {
29 case 0:
30 case 1:
31 printf("Usage:\n%s\n", cmdtp->usage);
32 return 1;
33
34 case 2:
35 if (strncmp(argv[1], "open", 4) == 0) {
36 onenand_init();
37 return 0;
38 }
39 printf("%s\n", onenand_mtd.name);
40 return 0;
41
42 default:
43 /* At least 4 args */
44 if (strncmp(argv[1], "erase", 5) == 0) {
45 struct erase_info instr = {
46 .callback = NULL,
47 };
48 ulong start, end;
49 ulong block;
50 char *endtail;
51
52 if (strncmp(argv[2], "block", 5) == 0) {
53 start = simple_strtoul(argv[3], NULL, 10);
54 endtail = strchr(argv[3], '-');
55 end = simple_strtoul(endtail + 1, NULL, 10);
56 } else {
57 start = simple_strtoul(argv[2], NULL, 10);
58 end = simple_strtoul(argv[3], NULL, 10);
59
60 start >>= onenand_chip.erase_shift;
61 end >>= onenand_chip.erase_shift;
62 /* Don't include the end block */
63 end--;
64 }
65
66 if (!end || end < 0)
67 end = start;
68
69 printf("Erase block from %lu to %lu\n", start, end);
70
71 for (block = start; block <= end; block++) {
72 instr.addr = block << onenand_chip.erase_shift;
73 instr.len = 1 << onenand_chip.erase_shift;
74 ret = onenand_erase(&onenand_mtd, &instr);
75 if (ret) {
76 printf("erase failed %lu\n", block);
77 break;
78 }
79 }
80
81 return 0;
82 }
83
84 if (strncmp(argv[1], "read", 4) == 0) {
85 ulong addr = simple_strtoul(argv[2], NULL, 16);
86 ulong ofs = simple_strtoul(argv[3], NULL, 16);
87 size_t len = simple_strtoul(argv[4], NULL, 16);
88 size_t retlen = 0;
89 int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
90
91 if (oob)
92 onenand_read_oob(&onenand_mtd, ofs, len,
93 &retlen, (u_char *) addr);
94 else
95 onenand_read(&onenand_mtd, ofs, len, &retlen,
96 (u_char *) addr);
97 printf("Done\n");
98
99 return 0;
100 }
101
102 if (strncmp(argv[1], "write", 5) == 0) {
103 ulong addr = simple_strtoul(argv[2], NULL, 16);
104 ulong ofs = simple_strtoul(argv[3], NULL, 16);
105 size_t len = simple_strtoul(argv[4], NULL, 16);
106 size_t retlen = 0;
107
108 onenand_write(&onenand_mtd, ofs, len, &retlen,
109 (u_char *) addr);
110 printf("Done\n");
111
112 return 0;
113 }
114
115 if (strncmp(argv[1], "block", 5) == 0) {
116 ulong addr = simple_strtoul(argv[2], NULL, 16);
117 ulong block = simple_strtoul(argv[3], NULL, 10);
118 ulong page = simple_strtoul(argv[4], NULL, 10);
119 size_t len = simple_strtol(argv[5], NULL, 10);
120 size_t retlen = 0;
121 ulong ofs;
122 int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;
123
124 ofs = block << onenand_chip.erase_shift;
125 if (page)
126 ofs += page << onenand_chip.page_shift;
127
128 if (!len) {
129 if (oob)
130 len = 64;
131 else
132 len = 512;
133 }
134
135 if (oob)
136 onenand_read_oob(&onenand_mtd, ofs, len,
137 &retlen, (u_char *) addr);
138 else
139 onenand_read(&onenand_mtd, ofs, len, &retlen,
140 (u_char *) addr);
141 return 0;
142 }
143
144 break;
145 }
146
147 return 0;
148 }
149
150 U_BOOT_CMD(
151 onenand, 6, 1, do_onenand,
152 "onenand - OneNAND sub-system\n",
153 "info - show available OneNAND devices\n"
154 "onenand read[.oob] addr ofs len - read data at ofs with len to addr\n"
155 "onenand write addr ofs len - write data at ofs with len from addr\n"
156 "onenand erase saddr eaddr - erase block start addr to end addr\n"
157 "onenand block[.oob] addr block [page] [len] - "
158 "read data with (block [, page]) to addr"
159 );