1dfb35dc21459fb95c068cdf631a3a88990d5b96
[openwrt.git] / target / linux / brcm47xx / patches-3.6 / 060-ssb-add-serial-flash-driver.patch
1 --- a/drivers/ssb/Kconfig
2 +++ b/drivers/ssb/Kconfig
3 @@ -139,7 +139,7 @@ config SSB_DRIVER_MIPS
4  
5  config SSB_SFLASH
6         bool "SSB serial flash support"
7 -       depends on SSB_DRIVER_MIPS && BROKEN
8 +       depends on SSB_DRIVER_MIPS
9         default y
10  
11  # Assumption: We are on embedded, if we compile the MIPS core.
12 --- a/drivers/ssb/driver_chipcommon_sflash.c
13 +++ b/drivers/ssb/driver_chipcommon_sflash.c
14 @@ -1,18 +1,395 @@
15  /*
16   * Sonics Silicon Backplane
17   * ChipCommon serial flash interface
18 + * Copyright 2011, Jonas Gorski <jonas.gorski@gmail.com>
19 + * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
20 + * Copyright 2010, Broadcom Corporation
21   *
22   * Licensed under the GNU/GPL. See COPYING for details.
23   */
24  
25 +#include <linux/platform_device.h>
26 +#include <linux/delay.h>
27  #include <linux/ssb/ssb.h>
28 +#include <linux/ssb/ssb_driver_chipcommon.h>
29  
30  #include "ssb_private.h"
31  
32 -/* Initialize serial flash access */
33 -int ssb_sflash_init(struct ssb_chipcommon *cc)
34 +#define NUM_RETRIES    3
35 +
36 +static struct resource ssb_sflash_resource = {
37 +       .name   = "ssb_sflash",
38 +       .start  = SSB_FLASH2,
39 +       .end    = 0,
40 +       .flags  = IORESOURCE_MEM | IORESOURCE_READONLY,
41 +};
42 +
43 +struct platform_device ssb_sflash_dev = {
44 +       .name           = "bcm47xx-sflash",
45 +       .resource       = &ssb_sflash_resource,
46 +       .num_resources  = 1,
47 +};
48 +
49 +struct ssb_sflash_tbl_e {
50 +       char *name;
51 +       u32 id;
52 +       u32 blocksize;
53 +       u16 numblocks;
54 +};
55 +
56 +static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = {
57 +       { "M25P20", 0x11, 0x10000, 4, },
58 +       { "M25P40", 0x12, 0x10000, 8, },
59 +
60 +       { "M25P16", 0x14, 0x10000, 32, },
61 +       { "M25P32", 0x14, 0x10000, 64, },
62 +       { "M25P64", 0x16, 0x10000, 128, },
63 +       { "M25FL128", 0x17, 0x10000, 256, },
64 +       { 0 },
65 +};
66 +
67 +static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = {
68 +       { "SST25WF512", 1, 0x1000, 16, },
69 +       { "SST25VF512", 0x48, 0x1000, 16, },
70 +       { "SST25WF010", 2, 0x1000, 32, },
71 +       { "SST25VF010", 0x49, 0x1000, 32, },
72 +       { "SST25WF020", 3, 0x1000, 64, },
73 +       { "SST25VF020", 0x43, 0x1000, 64, },
74 +       { "SST25WF040", 4, 0x1000, 128, },
75 +       { "SST25VF040", 0x44, 0x1000, 128, },
76 +       { "SST25VF040B", 0x8d, 0x1000, 128, },
77 +       { "SST25WF080", 5, 0x1000, 256, },
78 +       { "SST25VF080B", 0x8e, 0x1000, 256, },
79 +       { "SST25VF016", 0x41, 0x1000, 512, },
80 +       { "SST25VF032", 0x4a, 0x1000, 1024, },
81 +       { "SST25VF064", 0x4b, 0x1000, 2048, },
82 +       { 0 },
83 +};
84 +
85 +static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = {
86 +       { "AT45DB011", 0xc, 256, 512, },
87 +       { "AT45DB021", 0x14, 256, 1024, },
88 +       { "AT45DB041", 0x1c, 256, 2048, },
89 +       { "AT45DB081", 0x24, 256, 4096, },
90 +       { "AT45DB161", 0x2c, 512, 4096, },
91 +       { "AT45DB321", 0x34, 512, 8192, },
92 +       { "AT45DB642", 0x3c, 1024, 8192, },
93 +       { 0 },
94 +};
95 +
96 +static void ssb_sflash_cmd(struct ssb_chipcommon *chipco, u32 opcode)
97 +{
98 +       int i;
99 +       chipco_write32(chipco, SSB_CHIPCO_FLASHCTL,
100 +                       SSB_CHIPCO_FLASHCTL_START | opcode);
101 +       for (i = 0; i < 1000; i++) {
102 +               if (!(chipco_read32(chipco, SSB_CHIPCO_FLASHCTL) &
103 +                     SSB_CHIPCO_FLASHCTL_BUSY))
104 +                       return;
105 +               cpu_relax();
106 +       }
107 +       pr_err("SFLASH control command failed (timeout)!\n");
108 +}
109 +
110 +static void ssb_sflash_write_u8(struct ssb_chipcommon *chipco, u32 offset, u8 byte)
111 +{
112 +       chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, offset);
113 +       chipco_write32(chipco, SSB_CHIPCO_FLASHDATA, byte);
114 +}
115 +
116 +/* Read len bytes starting at offset into buf. Returns number of bytes read. */
117 +static int ssb_sflash_read(struct bcm47xx_sflash *dev, u32 offset, u32 len, u8 *buf)
118 +{
119 +       u8 *from, *to;
120 +       u32 cnt, i;
121 +       struct ssb_chipcommon *chipco = dev->scc;
122 +
123 +       if (!len)
124 +               return 0;
125 +
126 +       if ((offset + len) > chipco->sflash.size)
127 +               return -EINVAL;
128 +
129 +       if ((len >= 4) && (offset & 3))
130 +               cnt = 4 - (offset & 3);
131 +       else if ((len >= 4) && ((u32)buf & 3))
132 +               cnt = 4 - ((u32)buf & 3);
133 +       else
134 +               cnt = len;
135 +
136 +       from = (u8 *)KSEG0ADDR(SSB_FLASH2 + offset);
137 +
138 +       to = (u8 *)buf;
139 +
140 +       if (cnt < 4) {
141 +               for (i = 0; i < cnt; i++) {
142 +                       *to = readb(from);
143 +                       from++;
144 +                       to++;
145 +               }
146 +               return cnt;
147 +       }
148 +
149 +       while (cnt >= 4) {
150 +               *(u32 *)to = readl(from);
151 +               from += 4;
152 +               to += 4;
153 +               cnt -= 4;
154 +       }
155 +
156 +       return len - cnt;
157 +}
158 +
159 +/* Poll for command completion. Returns zero when complete. */
160 +static int ssb_sflash_poll(struct bcm47xx_sflash *dev, u32 offset)
161  {
162 -       pr_err("Serial flash support is not implemented yet!\n");
163 +       struct ssb_chipcommon *chipco = dev->scc;
164 +
165 +       if (offset >= chipco->sflash.size)
166 +               return -22;
167 +
168 +       switch (chipco->capabilities & SSB_CHIPCO_CAP_FLASHT) {
169 +       case SSB_CHIPCO_FLASHT_STSER:
170 +               /* Check for ST Write In Progress bit */
171 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_RDSR);
172 +               return chipco_read32(chipco, SSB_CHIPCO_FLASHDATA)
173 +                               & SSB_CHIPCO_FLASHDATA_ST_WIP;
174 +       case SSB_CHIPCO_FLASHT_ATSER:
175 +               /* Check for Atmel Ready bit */
176 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_STATUS);
177 +               return !(chipco_read32(chipco, SSB_CHIPCO_FLASHDATA)
178 +                               & SSB_CHIPCO_FLASHDATA_AT_READY);
179 +       }
180 +
181 +       return 0;
182 +}
183 +
184 +
185 +static int sflash_st_write(struct bcm47xx_sflash *dev, u32 offset, u32 len,
186 +                          const u8 *buf)
187 +{
188 +       int written = 1;
189 +       struct ssb_chipcommon *chipco = dev->scc;
190 +
191 +       /* Enable writes */
192 +       ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_WREN);
193 +       ssb_sflash_write_u8(chipco, offset, *buf++);
194 +       /* Issue a page program with CSA bit set */
195 +       ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_CSA | SSB_CHIPCO_FLASHCTL_ST_PP);
196 +       offset++;
197 +       len--;
198 +       while (len > 0) {
199 +               if ((offset & 255) == 0) {
200 +                       /* Page boundary, poll droping cs and return */
201 +                       chipco_write32(chipco, SSB_CHIPCO_FLASHCTL, 0);
202 +                       udelay(1);
203 +                       if (!ssb_sflash_poll(dev, offset)) {
204 +                               /* Flash rejected command */
205 +                               return -EAGAIN;
206 +                       }
207 +                       return written;
208 +               } else {
209 +                       /* Write single byte */
210 +                       ssb_sflash_cmd(chipco,
211 +                                       SSB_CHIPCO_FLASHCTL_ST_CSA |
212 +                                       *buf++);
213 +               }
214 +               written++;
215 +               offset++;
216 +               len--;
217 +       }
218 +       /* All done, drop cs & poll */
219 +       chipco_write32(chipco, SSB_CHIPCO_FLASHCTL, 0);
220 +       udelay(1);
221 +       if (!ssb_sflash_poll(dev, offset)) {
222 +               /* Flash rejected command */
223 +               return -EAGAIN;
224 +       }
225 +       return written;
226 +}
227 +
228 +static int sflash_at_write(struct bcm47xx_sflash *dev, u32 offset, u32 len,
229 +                          const u8 *buf)
230 +{
231 +       struct ssb_chipcommon *chipco = dev->scc;
232 +       u32 page, byte, mask;
233 +       int ret = 0;
234 +
235 +       mask = dev->blocksize - 1;
236 +       page = (offset & ~mask) << 1;
237 +       byte = offset & mask;
238 +       /* Read main memory page into buffer 1 */
239 +       if (byte || (len < dev->blocksize)) {
240 +               int i = 100;
241 +               chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, page);
242 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_BUF1_LOAD);
243 +               /* 250 us for AT45DB321B */
244 +               while (i > 0 && ssb_sflash_poll(dev, offset)) {
245 +                       udelay(10);
246 +                       i--;
247 +               }
248 +               BUG_ON(!ssb_sflash_poll(dev, offset));
249 +       }
250 +       /* Write into buffer 1 */
251 +       for (ret = 0; (ret < (int)len) && (byte < dev->blocksize); ret++) {
252 +               ssb_sflash_write_u8(chipco, byte++, *buf++);
253 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_BUF1_WRITE);
254 +       }
255 +       /* Write buffer 1 into main memory page */
256 +       chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, page);
257 +       ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_BUF1_PROGRAM);
258 +
259 +       return ret;
260 +}
261 +
262 +/* Write len bytes starting at offset into buf. Returns number of bytes
263 + * written. Caller should poll for completion.
264 + */
265 +static int ssb_sflash_write(struct bcm47xx_sflash *dev, u32 offset, u32 len,
266 +                     const u8 *buf)
267 +{
268 +       int ret = 0, tries = NUM_RETRIES;
269 +       struct ssb_chipcommon *chipco = dev->scc;
270 +
271 +       if (!len)
272 +               return 0;
273 +
274 +       if ((offset + len) > chipco->sflash.size)
275 +               return -EINVAL;
276 +
277 +       switch (chipco->capabilities & SSB_CHIPCO_CAP_FLASHT) {
278 +       case SSB_CHIPCO_FLASHT_STSER:
279 +               do {
280 +                       ret = sflash_st_write(dev, offset, len, buf);
281 +                       tries--;
282 +               } while (ret == -EAGAIN && tries > 0);
283 +
284 +               if (ret == -EAGAIN && tries == 0) {
285 +                       pr_info("ST Flash rejected write\n");
286 +                       ret = -EIO;
287 +               }
288 +               break;
289 +       case SSB_CHIPCO_FLASHT_ATSER:
290 +               ret = sflash_at_write(dev, offset, len, buf);
291 +               break;
292 +       }
293 +
294 +       return ret;
295 +}
296 +
297 +/* Erase a region. Returns number of bytes scheduled for erasure.
298 + * Caller should poll for completion.
299 + */
300 +static int ssb_sflash_erase(struct bcm47xx_sflash *dev, u32 offset)
301 +{
302 +       struct ssb_chipcommon *chipco = dev->scc;
303 +
304 +       if (offset >= chipco->sflash.size)
305 +               return -EINVAL;
306 +
307 +       switch (chipco->capabilities & SSB_CHIPCO_CAP_FLASHT) {
308 +       case SSB_CHIPCO_FLASHT_STSER:
309 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_WREN);
310 +               chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, offset);
311 +               /* Newer flashes have "sub-sectors" which can be erased independently
312 +                * with a new command: ST_SSE. The ST_SE command erases 64KB just as
313 +                * before.
314 +                */
315 +               if (dev->blocksize < (64 * 1024))
316 +                       ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_SSE);
317 +               else
318 +                       ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_SE);
319 +               return dev->blocksize;
320 +       case SSB_CHIPCO_FLASHT_ATSER:
321 +               chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, offset << 1);
322 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_PAGE_ERASE);
323 +               return dev->blocksize;
324 +       }
325 +
326 +       return 0;
327 +}
328 +
329 +/* Initialize serial flash achipcoess */
330 +int ssb_sflash_init(struct ssb_chipcommon *chipco)
331 +{
332 +       struct bcm47xx_sflash *sflash = &chipco->sflash;
333 +       const struct ssb_sflash_tbl_e *e;
334 +       u32 id, id2;
335 +
336 +       switch (chipco->capabilities & SSB_CHIPCO_CAP_FLASHT) {
337 +       case SSB_CHIPCO_FLASHT_STSER:
338 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_DP);
339 +
340 +               chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, 0);
341 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_RES);
342 +               id = chipco_read32(chipco, SSB_CHIPCO_FLASHDATA);
343 +
344 +               chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, 1);
345 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_RES);
346 +               id2 = chipco_read32(chipco, SSB_CHIPCO_FLASHDATA);
347 +
348 +               switch (id) {
349 +               case 0xbf:
350 +                       for (e = ssb_sflash_sst_tbl; e->name; e++) {
351 +                               if (e->id == id2)
352 +                                       break;
353 +                       }
354 +                       break;
355 +               case 0x13:
356 +                       return -ENOTSUPP;
357 +               default:
358 +                       for (e = ssb_sflash_st_tbl; e->name; e++) {
359 +                               if (e->id == id)
360 +                                       break;
361 +                       }
362 +                       break;
363 +               }
364 +               if (!e->name) {
365 +                       pr_err("Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", id, id2);
366 +                       return -ENOTSUPP;
367 +               }
368 +
369 +               break;
370 +       case SSB_CHIPCO_FLASHT_ATSER:
371 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_STATUS);
372 +               id = chipco_read32(chipco, SSB_CHIPCO_FLASHDATA) & 0x3c;
373 +
374 +               for (e = ssb_sflash_at_tbl; e->name; e++) {
375 +                       if (e->id == id)
376 +                               break;
377 +               }
378 +               if (!e->name) {
379 +                       pr_err("Unsupported Atmel serial flash (id: 0x%X)\n", id);
380 +                       return -ENOTSUPP;
381 +               }
382 +
383 +               break;
384 +       default:
385 +               pr_err("Unsupported flash type\n");
386 +               return -ENOTSUPP;
387 +       }
388 +
389 +       sflash->window = SSB_FLASH2;
390 +       sflash->blocksize = e->blocksize;
391 +       sflash->numblocks = e->numblocks;
392 +       sflash->size = sflash->blocksize * sflash->numblocks;
393 +       sflash->present = true;
394 +       sflash->read = ssb_sflash_read;
395 +       sflash->poll = ssb_sflash_poll;
396 +       sflash->write = ssb_sflash_write;
397 +       sflash->erase = ssb_sflash_erase;
398 +       sflash->type = BCM47XX_SFLASH_SSB;
399 +       sflash->scc = chipco;
400 +
401 +       pr_info("Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n",
402 +                 e->name, sflash->size / 1024, sflash->blocksize,
403 +                 sflash->numblocks);
404 +
405 +       /* Prepare platform device, but don't register it yet. It's too early,
406 +        * malloc (required by device_private_init) is not available yet. */
407 +       ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start +
408 +                                         sflash->size;
409 +       ssb_sflash_dev.dev.platform_data = sflash;
410  
411 -       return -ENOTSUPP;
412 +       return 0;
413  }
414 --- a/drivers/ssb/main.c
415 +++ b/drivers/ssb/main.c
416 @@ -19,6 +19,7 @@
417  #include <linux/ssb/ssb_driver_gige.h>
418  #include <linux/dma-mapping.h>
419  #include <linux/pci.h>
420 +#include <linux/platform_device.h>
421  #include <linux/mmc/sdio_func.h>
422  #include <linux/slab.h>
423  
424 @@ -540,6 +541,15 @@ static int ssb_devices_register(struct s
425                 dev_idx++;
426         }
427  
428 +#ifdef CONFIG_SSB_SFLASH
429 +       if (bus->chipco.sflash.present) {
430 +               err = platform_device_register(&ssb_sflash_dev);
431 +               if (err)
432 +                       ssb_printk(KERN_ERR PFX
433 +                                  "Error registering serial flash\n");
434 +       }
435 +#endif
436 +
437         return 0;
438  error:
439         /* Unwind the already registered devices. */
440 --- a/drivers/ssb/ssb_private.h
441 +++ b/drivers/ssb/ssb_private.h
442 @@ -220,6 +220,7 @@ extern u32 ssb_chipco_watchdog_timer_set
443  /* driver_chipcommon_sflash.c */
444  #ifdef CONFIG_SSB_SFLASH
445  int ssb_sflash_init(struct ssb_chipcommon *cc);
446 +extern struct platform_device ssb_sflash_dev;
447  #else
448  static inline int ssb_sflash_init(struct ssb_chipcommon *cc)
449  {
450 --- a/include/linux/ssb/ssb_driver_chipcommon.h
451 +++ b/include/linux/ssb/ssb_driver_chipcommon.h
452 @@ -13,6 +13,8 @@
453   * Licensed under the GPL version 2. See COPYING for details.
454   */
455  
456 +#include <linux/mtd/bcm47xx_sflash.h>
457 +
458  /** ChipCommon core registers. **/
459  
460  #define SSB_CHIPCO_CHIPID              0x0000
461 @@ -121,6 +123,17 @@
462  #define  SSB_CHIPCO_FLASHCTL_BUSY      SSB_CHIPCO_FLASHCTL_START
463  #define SSB_CHIPCO_FLASHADDR           0x0044
464  #define SSB_CHIPCO_FLASHDATA           0x0048
465 +/* Status register bits for ST flashes */
466 +#define  SSB_CHIPCO_FLASHDATA_ST_WIP   0x01            /* Write In Progress */
467 +#define  SSB_CHIPCO_FLASHDATA_ST_WEL   0x02            /* Write Enable Latch */
468 +#define  SSB_CHIPCO_FLASHDATA_ST_BP_MASK       0x1c            /* Block Protect */
469 +#define  SSB_CHIPCO_FLASHDATA_ST_BP_SHIFT      2
470 +#define  SSB_CHIPCO_FLASHDATA_ST_SRWD  0x80            /* Status Register Write Disable */
471 +/* Status register bits for Atmel flashes */
472 +#define  SSB_CHIPCO_FLASHDATA_AT_READY 0x80
473 +#define  SSB_CHIPCO_FLASHDATA_AT_MISMATCH      0x40
474 +#define  SSB_CHIPCO_FLASHDATA_AT_ID_MASK       0x38
475 +#define  SSB_CHIPCO_FLASHDATA_AT_ID_SHIFT      3
476  #define SSB_CHIPCO_BCAST_ADDR          0x0050
477  #define SSB_CHIPCO_BCAST_DATA          0x0054
478  #define SSB_CHIPCO_GPIOPULLUP          0x0058          /* Rev >= 20 only */
479 @@ -504,7 +517,7 @@
480  #define SSB_CHIPCO_FLASHCTL_ST_PP      0x0302          /* Page Program */
481  #define SSB_CHIPCO_FLASHCTL_ST_SE      0x02D8          /* Sector Erase */
482  #define SSB_CHIPCO_FLASHCTL_ST_BE      0x00C7          /* Bulk Erase */
483 -#define SSB_CHIPCO_FLASHCTL_ST_DP      0x00B9          /* Deep Power-down */
484 +#define SSB_CHIPCO_FLASHCTL_ST_DP      0x00D9          /* Deep Power-down */
485  #define SSB_CHIPCO_FLASHCTL_ST_RES     0x03AB          /* Read Electronic Signature */
486  #define SSB_CHIPCO_FLASHCTL_ST_CSA     0x1000          /* Keep chip select asserted */
487  #define SSB_CHIPCO_FLASHCTL_ST_SSE     0x0220          /* Sub-sector Erase */
488 @@ -595,6 +608,9 @@ struct ssb_chipcommon {
489         struct ssb_chipcommon_pmu pmu;
490         u32 ticks_per_ms;
491         u32 max_timer_ms;
492 +#ifdef CONFIG_SSB_SFLASH
493 +       struct bcm47xx_sflash sflash;
494 +#endif
495  };
496  
497  static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)