]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_sf.c
d571f60c04874bdfea4589d99a9bd1410d3f1b89
[karo-tx-uboot.git] / common / cmd_sf.c
1 /*
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
18 static struct spi_flash *flash;
19
20 static 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) {
51                 mode = simple_strtoul(argv[3], &endp, 16);
52                 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
71 usage:
72         puts("Usage: sf probe [bus:]cs [hz] [mode]\n");
73         return 1;
74 }
75
76 static 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
118 usage:
119         printf("Usage: sf %s addr offset len\n", argv[0]);
120         return 1;
121 }
122
123 static 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
148 usage:
149         puts("Usage: sf erase offset len\n");
150         return 1;
151 }
152
153 static 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
177 usage:
178         cmd_usage(cmdtp);
179         return 1;
180 }
181
182 U_BOOT_CMD(
183         sf,     5,      1,      do_spi_flash,
184         "SPI flash sub-system",
185         "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"
191         "sf erase offset len            - erase `len' bytes from `offset'"
192 );