NAND: add the ability to directly write yaffs image
[platform/kernel/u-boot.git] / common / cmd_sf.c
1 /*
2  * Command for accessing SPI flash.
3  *
4  * Copyright (C) 2008 Atmel Corporation
5  * Licensed under the GPL-2 or later.
6  */
7
8 #include <common.h>
9 #include <spi_flash.h>
10
11 #include <asm/io.h>
12
13 #ifndef CONFIG_SF_DEFAULT_SPEED
14 # define CONFIG_SF_DEFAULT_SPEED        1000000
15 #endif
16 #ifndef CONFIG_SF_DEFAULT_MODE
17 # define CONFIG_SF_DEFAULT_MODE         SPI_MODE_3
18 #endif
19
20 static struct spi_flash *flash;
21
22 static int do_spi_flash_probe(int argc, char * const argv[])
23 {
24         unsigned int bus = 0;
25         unsigned int cs;
26         unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
27         unsigned int mode = CONFIG_SF_DEFAULT_MODE;
28         char *endp;
29         struct spi_flash *new;
30
31         if (argc < 2)
32                 goto usage;
33
34         cs = simple_strtoul(argv[1], &endp, 0);
35         if (*argv[1] == 0 || (*endp != 0 && *endp != ':'))
36                 goto usage;
37         if (*endp == ':') {
38                 if (endp[1] == 0)
39                         goto usage;
40
41                 bus = cs;
42                 cs = simple_strtoul(endp + 1, &endp, 0);
43                 if (*endp != 0)
44                         goto usage;
45         }
46
47         if (argc >= 3) {
48                 speed = simple_strtoul(argv[2], &endp, 0);
49                 if (*argv[2] == 0 || *endp != 0)
50                         goto usage;
51         }
52         if (argc >= 4) {
53                 mode = simple_strtoul(argv[3], &endp, 16);
54                 if (*argv[3] == 0 || *endp != 0)
55                         goto usage;
56         }
57
58         new = spi_flash_probe(bus, cs, speed, mode);
59         if (!new) {
60                 printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
61                 return 1;
62         }
63
64         if (flash)
65                 spi_flash_free(flash);
66         flash = new;
67
68         printf("%u KiB %s at %u:%u is now current device\n",
69                         flash->size >> 10, flash->name, bus, cs);
70
71         return 0;
72
73 usage:
74         puts("Usage: sf probe [bus:]cs [hz] [mode]\n");
75         return 1;
76 }
77
78 static int do_spi_flash_read_write(int argc, char * const argv[])
79 {
80         unsigned long addr;
81         unsigned long offset;
82         unsigned long len;
83         void *buf;
84         char *endp;
85         int ret;
86
87         if (argc < 4)
88                 goto usage;
89
90         addr = simple_strtoul(argv[1], &endp, 16);
91         if (*argv[1] == 0 || *endp != 0)
92                 goto usage;
93         offset = simple_strtoul(argv[2], &endp, 16);
94         if (*argv[2] == 0 || *endp != 0)
95                 goto usage;
96         len = simple_strtoul(argv[3], &endp, 16);
97         if (*argv[3] == 0 || *endp != 0)
98                 goto usage;
99
100         buf = map_physmem(addr, len, MAP_WRBACK);
101         if (!buf) {
102                 puts("Failed to map physical memory\n");
103                 return 1;
104         }
105
106         if (strcmp(argv[0], "read") == 0)
107                 ret = spi_flash_read(flash, offset, len, buf);
108         else
109                 ret = spi_flash_write(flash, offset, len, buf);
110
111         unmap_physmem(buf, len);
112
113         if (ret) {
114                 printf("SPI flash %s failed\n", argv[0]);
115                 return 1;
116         }
117
118         return 0;
119
120 usage:
121         printf("Usage: sf %s addr offset len\n", argv[0]);
122         return 1;
123 }
124
125 static int do_spi_flash_erase(int argc, char * const argv[])
126 {
127         unsigned long offset;
128         unsigned long len;
129         char *endp;
130         int ret;
131
132         if (argc < 3)
133                 goto usage;
134
135         offset = simple_strtoul(argv[1], &endp, 16);
136         if (*argv[1] == 0 || *endp != 0)
137                 goto usage;
138         len = simple_strtoul(argv[2], &endp, 16);
139         if (*argv[2] == 0 || *endp != 0)
140                 goto usage;
141
142         ret = spi_flash_erase(flash, offset, len);
143         if (ret) {
144                 printf("SPI flash %s failed\n", argv[0]);
145                 return 1;
146         }
147
148         return 0;
149
150 usage:
151         puts("Usage: sf erase offset len\n");
152         return 1;
153 }
154
155 static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
156 {
157         const char *cmd;
158
159         /* need at least two arguments */
160         if (argc < 2)
161                 goto usage;
162
163         cmd = argv[1];
164
165         if (strcmp(cmd, "probe") == 0)
166                 return do_spi_flash_probe(argc - 1, argv + 1);
167
168         /* The remaining commands require a selected device */
169         if (!flash) {
170                 puts("No SPI flash selected. Please run `sf probe'\n");
171                 return 1;
172         }
173
174         if (strcmp(cmd, "read") == 0 || strcmp(cmd, "write") == 0)
175                 return do_spi_flash_read_write(argc - 1, argv + 1);
176         if (strcmp(cmd, "erase") == 0)
177                 return do_spi_flash_erase(argc - 1, argv + 1);
178
179 usage:
180         return cmd_usage(cmdtp);
181 }
182
183 U_BOOT_CMD(
184         sf,     5,      1,      do_spi_flash,
185         "SPI flash sub-system",
186         "probe [bus:]cs [hz] [mode]     - init flash device on given SPI bus\n"
187         "                                 and chip select\n"
188         "sf read addr offset len        - read `len' bytes starting at\n"
189         "                                 `offset' to memory at `addr'\n"
190         "sf write addr offset len       - write `len' bytes from memory\n"
191         "                                 at `addr' to flash at `offset'\n"
192         "sf erase offset len            - erase `len' bytes from `offset'"
193 );