]> git.sur5r.net Git - u-boot/blob - drivers/mtd/spi/eon.c
Merge branch 'next' of git://www.denx.de/git/u-boot-cfi-flash into next
[u-boot] / drivers / mtd / spi / eon.c
1 /*
2  * (C) Copyright 2010, ucRobotics Inc.
3  * Author: Chong Huang <chuang@ucrobotics.com>
4  * Licensed under the GPL-2 or later.
5  */
6
7 #include <common.h>
8 #include <malloc.h>
9 #include <spi_flash.h>
10
11 #include "spi_flash_internal.h"
12
13 /* EN25Q128-specific commands */
14 #define CMD_EN25Q128_WREN       0x06    /* Write Enable */
15 #define CMD_EN25Q128_WRDI       0x04    /* Write Disable */
16 #define CMD_EN25Q128_RDSR       0x05    /* Read Status Register */
17 #define CMD_EN25Q128_WRSR       0x01    /* Write Status Register */
18 #define CMD_EN25Q128_READ       0x03    /* Read Data Bytes */
19 #define CMD_EN25Q128_FAST_READ  0x0b    /* Read Data Bytes at Higher Speed */
20 #define CMD_EN25Q128_PP         0x02    /* Page Program */
21 #define CMD_EN25Q128_SE         0x20    /* Sector Erase */
22 #define CMD_EN25Q128_BE         0xd8    /* Block Erase */
23 #define CMD_EN25Q128_DP         0xb9    /* Deep Power-down */
24 #define CMD_EN25Q128_RES        0xab    /* Release from DP, and Read Signature */
25
26 #define EON_ID_EN25Q128         0x18
27
28 #define EON_SR_WIP              (1 << 0)        /* Write-in-Progress */
29
30 struct eon_spi_flash_params {
31         u8 idcode1;
32         u16 page_size;
33         u16 pages_per_sector;
34         u16 sectors_per_block;
35         u16 nr_sectors;
36         const char *name;
37 };
38
39 /* spi_flash needs to be first so upper layers can free() it */
40 struct eon_spi_flash {
41         struct spi_flash flash;
42         const struct eon_spi_flash_params *params;
43 };
44
45 static inline struct eon_spi_flash *to_eon_spi_flash(struct spi_flash *flash)
46 {
47         return container_of(flash, struct eon_spi_flash, flash);
48 }
49
50 static const struct eon_spi_flash_params eon_spi_flash_table[] = {
51         {
52                 .idcode1 = EON_ID_EN25Q128,
53                 .page_size = 256,
54                 .pages_per_sector = 16,
55                 .sectors_per_block = 16,
56                 .nr_sectors = 4096,
57                 .name = "EN25Q128",
58         },
59 };
60
61 static int eon_wait_ready(struct spi_flash *flash, unsigned long timeout)
62 {
63         struct spi_slave *spi = flash->spi;
64         unsigned long timebase;
65         int ret;
66         u8 cmd = CMD_EN25Q128_RDSR;
67         u8 status;
68
69         ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
70         if (ret) {
71                 debug("SF: Failed to send command %02x: %d\n", cmd, ret);
72                 return ret;
73         }
74
75         timebase = get_timer(0);
76         do {
77                 ret = spi_xfer(spi, 8, NULL, &status, 0);
78                 if (ret)
79                         return -1;
80
81                 if ((status & EON_SR_WIP) == 0)
82                         break;
83
84         } while (get_timer(timebase) < timeout);
85
86         spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
87
88         if ((status & EON_SR_WIP) == 0)
89                 return 0;
90
91         /* Timed out */
92         return -1;
93 }
94
95 static int eon_read_fast(struct spi_flash *flash,
96                          u32 offset, size_t len, void *buf)
97 {
98         struct eon_spi_flash *eon = to_eon_spi_flash(flash);
99         unsigned long page_addr;
100         unsigned long page_size;
101         u8 cmd[5];
102
103         page_size = eon->params->page_size;
104         page_addr = offset / page_size;
105
106         cmd[0] = CMD_READ_ARRAY_FAST;
107         cmd[1] = page_addr >> 8;
108         cmd[2] = page_addr;
109         cmd[3] = offset % page_size;
110         cmd[4] = 0x00;
111
112         return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
113 }
114
115 static int eon_write(struct spi_flash *flash,
116                      u32 offset, size_t len, const void *buf)
117 {
118         struct eon_spi_flash *eon = to_eon_spi_flash(flash);
119         unsigned long page_addr;
120         unsigned long byte_addr;
121         unsigned long page_size;
122         size_t chunk_len;
123         size_t actual;
124         int ret;
125         u8 cmd[4];
126
127         page_size = eon->params->page_size;
128         page_addr = offset / page_size;
129         byte_addr = offset % page_size;
130
131         ret = spi_claim_bus(flash->spi);
132         if (ret) {
133                 debug("SF: Unable to claim SPI bus\n");
134                 return ret;
135         }
136
137         ret = 0;
138         for (actual = 0; actual < len; actual += chunk_len) {
139                 chunk_len = min(len - actual, page_size - byte_addr);
140
141                 cmd[0] = CMD_EN25Q128_PP;
142                 cmd[1] = page_addr >> 8;
143                 cmd[2] = page_addr;
144                 cmd[3] = byte_addr;
145
146                 debug
147                     ("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %d\n",
148                      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
149
150                 ret = spi_flash_cmd(flash->spi, CMD_EN25Q128_WREN, NULL, 0);
151                 if (ret < 0) {
152                         debug("SF: Enabling Write failed\n");
153                         break;
154                 }
155
156                 ret = spi_flash_cmd_write(flash->spi, cmd, 4,
157                                           buf + actual, chunk_len);
158                 if (ret < 0) {
159                         debug("SF: EON Page Program failed\n");
160                         break;
161                 }
162
163                 ret = eon_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
164                 if (ret < 0) {
165                         debug("SF: EON page programming timed out\n");
166                         break;
167                 }
168
169                 page_addr++;
170                 byte_addr = 0;
171         }
172
173         debug("SF: EON: Successfully programmed %u bytes @ 0x%x\n",
174               len, offset);
175
176         spi_release_bus(flash->spi);
177         return ret;
178 }
179
180 int eon_erase(struct spi_flash *flash, u32 offset, size_t len)
181 {
182         /* block erase */
183         struct eon_spi_flash *eon = to_eon_spi_flash(flash);
184         unsigned long block_size;
185         size_t actual;
186         int ret;
187         u8 cmd[4];
188
189
190         block_size = eon->params->page_size * eon->params->pages_per_sector
191                * eon->params->sectors_per_block;
192
193         if (offset % block_size || len % block_size) {
194                 debug("SF: Erase offset/length not multiple of block size\n");
195                 return -1;
196         }
197
198         len /= block_size;
199         cmd[0] = CMD_EN25Q128_BE;
200         cmd[2] = 0x00;
201         cmd[3] = 0x00;
202
203         ret = spi_claim_bus(flash->spi);
204         if (ret) {
205                 debug("SF: Unable to claim SPI bus\n");
206                 return ret;
207         }
208
209         ret = 0;
210         for (actual = 0; actual < len; actual++) {
211                 cmd[1] = (offset / block_size) + actual;
212                 ret = spi_flash_cmd(flash->spi, CMD_EN25Q128_WREN, NULL, 0);
213                 if (ret < 0) {
214                         debug("SF: Enabling Write failed\n");
215                         break;
216                 }
217
218                 ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
219                 if (ret < 0) {
220                         debug("SF: EON page erase failed\n");
221                         break;
222                 }
223
224                 ret = eon_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
225                 if (ret < 0) {
226                         debug("SF: EON page erase timed out\n");
227                         break;
228                 }
229         }
230
231         debug("SF: EON: Successfully erased %u bytes @ 0x%x\n",
232               len * block_size, offset);
233
234         spi_release_bus(flash->spi);
235         return ret;
236 }
237
238 struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
239 {
240         const struct eon_spi_flash_params *params;
241         struct eon_spi_flash *eon;
242         unsigned int i;
243
244         for (i = 0; i < ARRAY_SIZE(eon_spi_flash_table); ++i) {
245                 params = &eon_spi_flash_table[i];
246                 if (params->idcode1 == idcode[2])
247                         break;
248         }
249
250         if (i == ARRAY_SIZE(eon_spi_flash_table)) {
251                 debug("SF: Unsupported EON ID %02x\n", idcode[1]);
252                 return NULL;
253         }
254
255         eon = malloc(sizeof(*eon));
256         if (!eon) {
257                 debug("SF: Failed to allocate memory\n");
258                 return NULL;
259         }
260
261         eon->params = params;
262         eon->flash.spi = spi;
263         eon->flash.name = params->name;
264
265         eon->flash.write = eon_write;
266         eon->flash.erase = eon_erase;
267         eon->flash.read = eon_read_fast;
268         eon->flash.size = params->page_size * params->pages_per_sector
269             * params->nr_sectors;
270
271         debug("SF: Detected %s with page size %u, total %u bytes\n",
272               params->name, params->page_size, eon->flash.size);
273
274         return &eon->flash;
275 }