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