]>
Commit | Line | Data |
---|---|---|
d7e8ce10 KP |
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 | #ifdef CONFIG_CMD_ONENAND | |
16 | ||
17 | #include <linux/mtd/compat.h> | |
18 | #include <linux/mtd/mtd.h> | |
19 | #include <linux/mtd/onenand.h> | |
20 | ||
21 | #include <asm/io.h> | |
22 | ||
23 | extern struct mtd_info onenand_mtd; | |
24 | extern struct onenand_chip onenand_chip; | |
25 | ||
26 | int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) | |
27 | { | |
28 | int ret = 0; | |
29 | ||
30 | switch (argc) { | |
31 | case 0: | |
32 | case 1: | |
33 | printf("Usage:\n%s\n", cmdtp->usage); | |
34 | return 1; | |
35 | ||
36 | case 2: | |
37 | if (strncmp(argv[1], "open", 4) == 0) { | |
38 | onenand_init(); | |
39 | return 0; | |
40 | } | |
41 | onenand_print_device_info(onenand_chip.device_id, 1); | |
42 | return 0; | |
43 | ||
44 | default: | |
45 | /* At least 4 args */ | |
46 | if (strncmp(argv[1], "erase", 5) == 0) { | |
47 | struct erase_info instr; | |
48 | ulong start, end; | |
49 | ulong block; | |
50 | ||
51 | start = simple_strtoul(argv[2], NULL, 10); | |
52 | end = simple_strtoul(argv[3], NULL, 10); | |
53 | start -= (unsigned long)onenand_chip.base; | |
54 | end -= (unsigned long)onenand_chip.base; | |
55 | ||
56 | if (!end || end < 0) | |
57 | end = start; | |
58 | ||
59 | printf("Erase block from %d to %d\n", start, end); | |
60 | ||
61 | for (block = start; block <= end; block++) { | |
62 | instr.addr = block << onenand_chip.erase_shift; | |
63 | instr.len = 1 << onenand_chip.erase_shift; | |
64 | ret = onenand_erase(&onenand_mtd, &instr); | |
65 | if (ret) { | |
66 | printf("erase failed %d\n", block); | |
67 | break; | |
68 | } | |
69 | } | |
70 | ||
71 | return 0; | |
72 | } | |
73 | ||
74 | if (strncmp(argv[1], "read", 4) == 0) { | |
75 | ulong addr = simple_strtoul(argv[2], NULL, 16); | |
76 | ulong ofs = simple_strtoul(argv[3], NULL, 16); | |
77 | size_t len = simple_strtoul(argv[4], NULL, 16); | |
78 | size_t retlen = 0; | |
79 | int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1; | |
80 | ||
81 | ofs -= (unsigned long)onenand_chip.base; | |
82 | ||
83 | if (oob) | |
84 | onenand_read_oob(&onenand_mtd, ofs, len, | |
85 | &retlen, (u_char *) addr); | |
86 | else | |
87 | onenand_read(&onenand_mtd, ofs, len, &retlen, | |
88 | (u_char *) addr); | |
89 | printf("Done\n"); | |
90 | ||
91 | return 0; | |
92 | } | |
93 | ||
94 | if (strncmp(argv[1], "write", 5) == 0) { | |
95 | ulong addr = simple_strtoul(argv[2], NULL, 16); | |
96 | ulong ofs = simple_strtoul(argv[3], NULL, 16); | |
97 | size_t len = simple_strtoul(argv[4], NULL, 16); | |
98 | size_t retlen = 0; | |
99 | ||
100 | ofs -= (unsigned long)onenand_chip.base; | |
101 | ||
102 | onenand_write(&onenand_mtd, ofs, len, &retlen, | |
103 | (u_char *) addr); | |
104 | printf("Done\n"); | |
105 | ||
106 | return 0; | |
107 | } | |
108 | ||
109 | if (strncmp(argv[1], "block", 5) == 0) { | |
110 | ulong addr = simple_strtoul(argv[2], NULL, 16); | |
111 | ulong block = simple_strtoul(argv[3], NULL, 10); | |
112 | ulong page = simple_strtoul(argv[4], NULL, 10); | |
113 | size_t len = simple_strtol(argv[5], NULL, 10); | |
114 | size_t retlen = 0; | |
115 | ulong ofs; | |
116 | int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1; | |
117 | ||
118 | ofs = block << onenand_chip.erase_shift; | |
119 | if (page) | |
120 | ofs += page << onenand_chip.page_shift; | |
121 | ||
122 | if (!len) { | |
123 | if (oob) | |
124 | len = 64; | |
125 | else | |
126 | len = 512; | |
127 | } | |
128 | ||
129 | if (oob) | |
130 | onenand_read_oob(&onenand_mtd, ofs, len, | |
131 | &retlen, (u_char *) addr); | |
132 | else | |
133 | onenand_read(&onenand_mtd, ofs, len, &retlen, | |
134 | (u_char *) addr); | |
135 | return 0; | |
136 | } | |
137 | ||
138 | break; | |
139 | } | |
140 | ||
141 | return 0; | |
142 | } | |
143 | ||
144 | U_BOOT_CMD( | |
145 | onenand, 6, 1, do_onenand, | |
146 | "onenand - OneNAND sub-system\n", | |
147 | "info - show available OneNAND devices\n" | |
148 | "onenand read[.oob] addr ofs len - read data at ofs with len to addr\n" | |
149 | "onenand write addr ofs len - write data at ofs with len from addr\n" | |
150 | "onenand erase saddr eaddr - erase block start addr to end addr\n" | |
151 | "onenand block[.oob] addr block [page] [len] - " | |
152 | "read data with (block [, page]) to addr" | |
153 | ); | |
154 | ||
155 | #endif /* CONFIG_CMD_ONENAND */ |