ba5a5c2d1b723697d7f991a8064128ed40dce15d
[openwrt.git] / target / linux / brcm47xx / patches-3.3 / 023-ssb-add-serial-flash-support.patch
1 --- a/drivers/ssb/Kconfig
2 +++ b/drivers/ssb/Kconfig
3 @@ -137,6 +137,12 @@ config SSB_DRIVER_MIPS
4  
5           If unsure, say N
6  
7 +config SSB_SFLASH
8 +       bool
9 +       depends on SSB_DRIVER_MIPS
10 +       default y
11 +
12 +
13  # Assumption: We are on embedded, if we compile the MIPS core.
14  config SSB_EMBEDDED
15         bool
16 --- a/drivers/ssb/Makefile
17 +++ b/drivers/ssb/Makefile
18 @@ -11,6 +11,7 @@ ssb-$(CONFIG_SSB_SDIOHOST)            += sdio.o
19  # built-in drivers
20  ssb-y                                  += driver_chipcommon.o
21  ssb-y                                  += driver_chipcommon_pmu.o
22 +ssb-$(CONFIG_SSB_SFLASH)               += driver_chipcommon_sflash.o
23  ssb-$(CONFIG_SSB_DRIVER_MIPS)          += driver_mipscore.o
24  ssb-$(CONFIG_SSB_DRIVER_EXTIF)         += driver_extif.o
25  ssb-$(CONFIG_SSB_DRIVER_PCICORE)       += driver_pcicore.o
26 --- /dev/null
27 +++ b/drivers/ssb/driver_chipcommon_sflash.c
28 @@ -0,0 +1,451 @@
29 +/*
30 + * Broadcom SiliconBackplane chipcommon serial flash interface
31 + *
32 + * Copyright 2011, Jonas Gorski <jonas.gorski@gmail.com>
33 + * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
34 + * Copyright 2010, Broadcom Corporation
35 + *
36 + * Licensed under the GNU/GPL. See COPYING for details.
37 + */
38 +
39 +#include <linux/ssb/ssb.h>
40 +#include <linux/ssb/ssb_driver_chipcommon.h>
41 +#include <linux/delay.h>
42 +
43 +#include "ssb_private.h"
44 +
45 +#define NUM_RETRIES    3
46 +
47 +
48 +/* Issue a serial flash command */
49 +static inline void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode)
50 +{
51 +       chipco_write32(cc, SSB_CHIPCO_FLASHCTL,
52 +                       SSB_CHIPCO_FLASHCTL_START | opcode);
53 +       while (chipco_read32(cc, SSB_CHIPCO_FLASHCTL)
54 +                       & SSB_CHIPCO_FLASHCTL_BUSY)
55 +               ;
56 +}
57 +
58 +
59 +static inline void ssb_sflash_write_u8(struct ssb_chipcommon *cc,
60 +                                      u32 offset, u8 byte)
61 +{
62 +       chipco_write32(cc, SSB_CHIPCO_FLASHADDR, offset);
63 +       chipco_write32(cc, SSB_CHIPCO_FLASHDATA, byte);
64 +}
65 +
66 +/* Initialize serial flash access */
67 +int ssb_sflash_init(struct ssb_chipcommon *cc)
68 +{
69 +       u32 id, id2;
70 +
71 +       memset(&cc->sflash, 0, sizeof(struct ssb_sflash));
72 +
73 +       switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) {
74 +       case SSB_CHIPCO_FLASHT_STSER:
75 +               /* Probe for ST chips */
76 +               ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_DP);
77 +               chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 0);
78 +               ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES);
79 +               id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA);
80 +               cc->sflash.blocksize = 64 * 1024;
81 +               switch (id) {
82 +               case 0x11:
83 +                       /* ST M25P20 2 Mbit Serial Flash */
84 +                       cc->sflash.numblocks = 4;
85 +                       break;
86 +               case 0x12:
87 +                       /* ST M25P40 4 Mbit Serial Flash */
88 +                       cc->sflash.numblocks = 8;
89 +                       break;
90 +               case 0x13:
91 +                       /* ST M25P80 8 Mbit Serial Flash */
92 +                       cc->sflash.numblocks = 16;
93 +                       break;
94 +               case 0x14:
95 +                       /* ST M25P16 16 Mbit Serial Flash */
96 +                       cc->sflash.numblocks = 32;
97 +                       break;
98 +               case 0x15:
99 +                       /* ST M25P32 32 Mbit Serial Flash */
100 +                       cc->sflash.numblocks = 64;
101 +                       break;
102 +               case 0x16:
103 +                       /* ST M25P64 64 Mbit Serial Flash */
104 +                       cc->sflash.numblocks = 128;
105 +                       break;
106 +               case 0x17:
107 +                       /* ST M25FL128 128 Mbit Serial Flash */
108 +                       cc->sflash.numblocks = 256;
109 +                       break;
110 +               case 0xbf:
111 +                       /* All of the following flashes are SST with
112 +                        * 4KB subsectors. Others should be added but
113 +                        * We'll have to revamp the way we identify them
114 +                        * since RES is not eough to disambiguate them.
115 +                        */
116 +                       cc->sflash.blocksize = 4 * 1024;
117 +                       chipco_write32(cc, SSB_CHIPCO_FLASHADDR, 1);
118 +                       ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RES);
119 +                       id2 = chipco_read32(cc, SSB_CHIPCO_FLASHDATA);
120 +                       switch (id2) {
121 +                       case 1:
122 +                               /* SST25WF512 512 Kbit Serial Flash */
123 +                       case 0x48:
124 +                               /* SST25VF512 512 Kbit Serial Flash */
125 +                               cc->sflash.numblocks = 16;
126 +                               break;
127 +                       case 2:
128 +                               /* SST25WF010 1 Mbit Serial Flash */
129 +                       case 0x49:
130 +                               /* SST25VF010 1 Mbit Serial Flash */
131 +                               cc->sflash.numblocks = 32;
132 +                               break;
133 +                       case 3:
134 +                               /* SST25WF020 2 Mbit Serial Flash */
135 +                       case 0x43:
136 +                               /* SST25VF020 2 Mbit Serial Flash */
137 +                               cc->sflash.numblocks = 64;
138 +                               break;
139 +                       case 4:
140 +                               /* SST25WF040 4 Mbit Serial Flash */
141 +                       case 0x44:
142 +                               /* SST25VF040 4 Mbit Serial Flash */
143 +                       case 0x8d:
144 +                               /* SST25VF040B 4 Mbit Serial Flash */
145 +                               cc->sflash.numblocks = 128;
146 +                               break;
147 +                       case 5:
148 +                               /* SST25WF080 8 Mbit Serial Flash */
149 +                       case 0x8e:
150 +                               /* SST25VF080B 8 Mbit Serial Flash */
151 +                               cc->sflash.numblocks = 256;
152 +                               break;
153 +                       case 0x41:
154 +                               /* SST25VF016 16 Mbit Serial Flash */
155 +                               cc->sflash.numblocks = 512;
156 +                               break;
157 +                       case 0x4a:
158 +                               /* SST25VF032 32 Mbit Serial Flash */
159 +                               cc->sflash.numblocks = 1024;
160 +                               break;
161 +                       case 0x4b:
162 +                               /* SST25VF064 64 Mbit Serial Flash */
163 +                               cc->sflash.numblocks = 2048;
164 +                               break;
165 +                       }
166 +                       break;
167 +               }
168 +               break;
169 +
170 +       case SSB_CHIPCO_FLASHT_ATSER:
171 +               /* Probe for Atmel chips */
172 +               ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_STATUS);
173 +               id = chipco_read32(cc, SSB_CHIPCO_FLASHDATA) & 0x3c;
174 +               switch (id) {
175 +               case 0xc:
176 +                       /* Atmel AT45DB011 1Mbit Serial Flash */
177 +                       cc->sflash.blocksize = 256;
178 +                       cc->sflash.numblocks = 512;
179 +                       break;
180 +               case 0x14:
181 +                       /* Atmel AT45DB021 2Mbit Serial Flash */
182 +                       cc->sflash.blocksize = 256;
183 +                       cc->sflash.numblocks = 1024;
184 +                       break;
185 +               case 0x1c:
186 +                       /* Atmel AT45DB041 4Mbit Serial Flash */
187 +                       cc->sflash.blocksize = 256;
188 +                       cc->sflash.numblocks = 2048;
189 +                       break;
190 +               case 0x24:
191 +                       /* Atmel AT45DB081 8Mbit Serial Flash */
192 +                       cc->sflash.blocksize = 256;
193 +                       cc->sflash.numblocks = 4096;
194 +                       break;
195 +               case 0x2c:
196 +                       /* Atmel AT45DB161 16Mbit Serial Flash */
197 +                       cc->sflash.blocksize = 512;
198 +                       cc->sflash.numblocks = 4096;
199 +                       break;
200 +               case 0x34:
201 +                       /* Atmel AT45DB321 32Mbit Serial Flash */
202 +                       cc->sflash.blocksize = 512;
203 +                       cc->sflash.numblocks = 8192;
204 +                       break;
205 +               case 0x3c:
206 +                       /* Atmel AT45DB642 64Mbit Serial Flash */
207 +                       cc->sflash.blocksize = 1024;
208 +                       cc->sflash.numblocks = 8192;
209 +                       break;
210 +               }
211 +               break;
212 +       }
213 +
214 +       cc->sflash.size = cc->sflash.blocksize * cc->sflash.numblocks;
215 +
216 +       return cc->sflash.size ? 0 : -ENODEV;
217 +}
218 +
219 +/* Read len bytes starting at offset into buf. Returns number of bytes read. */
220 +int ssb_sflash_read(struct ssb_chipcommon *cc, u32 offset, u32 len, u8 *buf)
221 +{
222 +       u8 *from, *to;
223 +       u32 cnt, i;
224 +
225 +       if (!len)
226 +               return 0;
227 +
228 +       if ((offset + len) > cc->sflash.size)
229 +               return -EINVAL;
230 +
231 +       if ((len >= 4) && (offset & 3))
232 +               cnt = 4 - (offset & 3);
233 +       else if ((len >= 4) && ((u32)buf & 3))
234 +               cnt = 4 - ((u32)buf & 3);
235 +       else
236 +               cnt = len;
237 +
238 +
239 +       if (cc->dev->id.revision == 12)
240 +               from = (u8 *)KSEG1ADDR(SSB_FLASH2 + offset);
241 +       else
242 +               from = (u8 *)KSEG0ADDR(SSB_FLASH2 + offset);
243 +
244 +       to = (u8 *)buf;
245 +
246 +       if (cnt < 4) {
247 +               for (i = 0; i < cnt; i++) {
248 +                       *to = readb(from);
249 +                       from++;
250 +                       to++;
251 +               }
252 +               return cnt;
253 +       }
254 +
255 +       while (cnt >= 4) {
256 +               *(u32 *)to = readl(from);
257 +               from += 4;
258 +               to += 4;
259 +               cnt -= 4;
260 +       }
261 +
262 +       return len - cnt;
263 +}
264 +
265 +/* Poll for command completion. Returns zero when complete. */
266 +int ssb_sflash_poll(struct ssb_chipcommon *cc, u32 offset)
267 +{
268 +       if (offset >= cc->sflash.size)
269 +               return -22;
270 +
271 +       switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) {
272 +       case SSB_CHIPCO_FLASHT_STSER:
273 +               /* Check for ST Write In Progress bit */
274 +               ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_RDSR);
275 +               return chipco_read32(cc, SSB_CHIPCO_FLASHDATA)
276 +                               & SSB_CHIPCO_FLASHSTA_ST_WIP;
277 +       case SSB_CHIPCO_FLASHT_ATSER:
278 +               /* Check for Atmel Ready bit */
279 +               ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_STATUS);
280 +               return !(chipco_read32(cc, SSB_CHIPCO_FLASHDATA)
281 +                               & SSB_CHIPCO_FLASHSTA_AT_READY);
282 +       }
283 +
284 +       return 0;
285 +}
286 +
287 +
288 +static int sflash_st_write(struct ssb_chipcommon *cc, u32 offset, u32 len,
289 +                          const u8 *buf)
290 +{
291 +       struct ssb_bus *bus = cc->dev->bus;
292 +       int ret = 0;
293 +       bool is4712b0 = (bus->chip_id == 0x4712) && (bus->chip_rev == 3);
294 +       u32 mask;
295 +
296 +       /* Enable writes */
297 +       ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_WREN);
298 +       if (is4712b0) {
299 +               mask = 1 << 14;
300 +               ssb_sflash_write_u8(cc, offset, *buf++);
301 +               /* Set chip select */
302 +               chipco_set32(cc, SSB_CHIPCO_GPIOOUT, mask);
303 +               /* Issue a page program with the first byte */
304 +               ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_PP);
305 +               ret = 1;
306 +               offset++;
307 +               len--;
308 +               while (len > 0) {
309 +                       if ((offset & 255) == 0) {
310 +                               /* Page boundary, drop cs and return */
311 +                               chipco_mask32(cc, SSB_CHIPCO_GPIOOUT, ~mask);
312 +                               udelay(1);
313 +                               if (!ssb_sflash_poll(cc, offset)) {
314 +                                       /* Flash rejected command */
315 +                                       return -EAGAIN;
316 +                               }
317 +                               return ret;
318 +                       } else {
319 +                               /* Write single byte */
320 +                               ssb_sflash_cmd(cc, *buf++);
321 +                       }
322 +                       ret++;
323 +                       offset++;
324 +                       len--;
325 +               }
326 +               /* All done, drop cs */
327 +               chipco_mask32(cc, SSB_CHIPCO_GPIOOUT, ~mask);
328 +               udelay(1);
329 +               if (!ssb_sflash_poll(cc, offset)) {
330 +                       /* Flash rejected command */
331 +                       return -EAGAIN;
332 +               }
333 +       } else if (cc->dev->id.revision >= 20) {
334 +               ssb_sflash_write_u8(cc, offset, *buf++);
335 +               /* Issue a page program with CSA bit set */
336 +               ssb_sflash_cmd(cc,
337 +                               SSB_CHIPCO_FLASHCTL_ST_CSA |
338 +                               SSB_CHIPCO_FLASHCTL_ST_PP);
339 +               ret = 1;
340 +               offset++;
341 +               len--;
342 +               while (len > 0) {
343 +                       if ((offset & 255) == 0) {
344 +                               /* Page boundary, poll droping cs and return */
345 +                               chipco_write32(cc, SSB_CHIPCO_FLASHCTL, 0);
346 +                               udelay(1);
347 +                               if (!ssb_sflash_poll(cc, offset)) {
348 +                                       /* Flash rejected command */
349 +                                       return -EAGAIN;
350 +                               }
351 +                               return ret;
352 +                       } else {
353 +                               /* Write single byte */
354 +                               ssb_sflash_cmd(cc,
355 +                                               SSB_CHIPCO_FLASHCTL_ST_CSA |
356 +                                               *buf++);
357 +                       }
358 +                       ret++;
359 +                       offset++;
360 +                       len--;
361 +               }
362 +               /* All done, drop cs & poll */
363 +               chipco_write32(cc, SSB_CHIPCO_FLASHCTL, 0);
364 +               udelay(1);
365 +               if (!ssb_sflash_poll(cc, offset)) {
366 +                       /* Flash rejected command */
367 +                       return -EAGAIN;
368 +               }
369 +       } else {
370 +               ret = 1;
371 +               ssb_sflash_write_u8(cc, offset, *buf);
372 +               /* Page program */
373 +               ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_PP);
374 +       }
375 +       return ret;
376 +}
377 +
378 +static int sflash_at_write(struct ssb_chipcommon *cc, u32 offset, u32 len,
379 +                          const u8 *buf)
380 +{
381 +       struct ssb_sflash *sfl = &cc->sflash;
382 +       u32 page, byte, mask;
383 +       int ret = 0;
384 +       mask = sfl->blocksize - 1;
385 +       page = (offset & ~mask) << 1;
386 +       byte = offset & mask;
387 +       /* Read main memory page into buffer 1 */
388 +       if (byte || (len < sfl->blocksize)) {
389 +               int i = 100;
390 +               chipco_write32(cc, SSB_CHIPCO_FLASHADDR, page);
391 +               ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_BUF1_LOAD);
392 +               /* 250 us for AT45DB321B */
393 +               while (i > 0 && ssb_sflash_poll(cc, offset)) {
394 +                       udelay(10);
395 +                       i--;
396 +               }
397 +               BUG_ON(!ssb_sflash_poll(cc, offset));
398 +       }
399 +       /* Write into buffer 1 */
400 +       for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
401 +               ssb_sflash_write_u8(cc, byte++, *buf++);
402 +               ssb_sflash_cmd(cc,
403 +                               SSB_CHIPCO_FLASHCTL_AT_BUF1_WRITE);
404 +       }
405 +       /* Write buffer 1 into main memory page */
406 +       chipco_write32(cc, SSB_CHIPCO_FLASHADDR, page);
407 +       ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_BUF1_PROGRAM);
408 +
409 +       return ret;
410 +}
411 +
412 +/* Write len bytes starting at offset into buf. Returns number of bytes
413 + * written. Caller should poll for completion.
414 + */
415 +int ssb_sflash_write(struct ssb_chipcommon *cc, u32 offset, u32 len,
416 +                           const u8 *buf)
417 +{
418 +       struct ssb_sflash *sfl;
419 +       int ret = 0, tries = NUM_RETRIES;
420 +
421 +       if (!len)
422 +               return 0;
423 +
424 +       if ((offset + len) > cc->sflash.size)
425 +               return -EINVAL;
426 +
427 +       sfl = &cc->sflash;
428 +       switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) {
429 +       case SSB_CHIPCO_FLASHT_STSER:
430 +               do {
431 +                       ret = sflash_st_write(cc, offset, len, buf);
432 +                       tries--;
433 +               } while (ret == -EAGAIN && tries > 0);
434 +
435 +               if (ret == -EAGAIN && tries == 0) {
436 +                       pr_info("ST Flash rejected write\n");
437 +                       ret = -EIO;
438 +               }
439 +               break;
440 +       case SSB_CHIPCO_FLASHT_ATSER:
441 +               ret = sflash_at_write(cc, offset, len, buf);
442 +               break;
443 +       }
444 +
445 +       return ret;
446 +}
447 +
448 +/* Erase a region. Returns number of bytes scheduled for erasure.
449 + * Caller should poll for completion.
450 + */
451 +int ssb_sflash_erase(struct ssb_chipcommon *cc, u32 offset)
452 +{
453 +       struct ssb_sflash *sfl;
454 +
455 +       if (offset >= cc->sflash.size)
456 +               return -EINVAL;
457 +
458 +       sfl = &cc->sflash;
459 +       switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) {
460 +       case SSB_CHIPCO_FLASHT_STSER:
461 +               ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_WREN);
462 +               chipco_write32(cc, SSB_CHIPCO_FLASHADDR, offset);
463 +               /* Newer flashes have "sub-sectors" which can be erased
464 +                * independently with a new command: ST_SSE. The ST_SE command
465 +                * erases 64KB just as before.
466 +                */
467 +               if (sfl->blocksize < (64 * 1024))
468 +                       ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_SSE);
469 +               else
470 +                       ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_ST_SE);
471 +               return sfl->blocksize;
472 +       case SSB_CHIPCO_FLASHT_ATSER:
473 +               chipco_write32(cc, SSB_CHIPCO_FLASHADDR, offset << 1);
474 +               ssb_sflash_cmd(cc, SSB_CHIPCO_FLASHCTL_AT_PAGE_ERASE);
475 +               return sfl->blocksize;
476 +       }
477 +
478 +       return 0;
479 +}
480 --- a/drivers/ssb/driver_mipscore.c
481 +++ b/drivers/ssb/driver_mipscore.c
482 @@ -203,7 +203,13 @@ static void ssb_mips_flash_detect(struct
483         switch (bus->chipco.capabilities & SSB_CHIPCO_CAP_FLASHT) {
484         case SSB_CHIPCO_FLASHT_STSER:
485         case SSB_CHIPCO_FLASHT_ATSER:
486 +#ifdef CONFIG_SSB_SFLASH
487 +               pr_info("found serial flash.\n");
488 +               bus->chipco.flash_type = SSB_SFLASH;
489 +               ssb_sflash_init(&bus->chipco);
490 +#else
491                 pr_info("serial flash not supported.\n");
492 +#endif /* CONFIG_SSB_SFLASH */
493                 break;
494         case SSB_CHIPCO_FLASHT_PARA:
495                 pr_info("found parallel flash.\n");
496 --- a/drivers/ssb/ssb_private.h
497 +++ b/drivers/ssb/ssb_private.h
498 @@ -192,6 +192,10 @@ extern int ssb_devices_freeze(struct ssb
499  extern int ssb_devices_thaw(struct ssb_freeze_context *ctx);
500  
501  
502 +#ifdef CONFIG_SSB_SFLASH
503 +/* driver_chipcommon_sflash.c */
504 +int ssb_sflash_init(struct ssb_chipcommon *cc);
505 +#endif /* CONFIG_SSB_SFLASH */
506  
507  /* b43_pci_bridge.c */
508  #ifdef CONFIG_SSB_B43_PCI_BRIDGE
509 --- a/include/linux/ssb/ssb_driver_chipcommon.h
510 +++ b/include/linux/ssb/ssb_driver_chipcommon.h
511 @@ -503,8 +503,10 @@
512  #define SSB_CHIPCO_FLASHCTL_ST_PP      0x0302          /* Page Program */
513  #define SSB_CHIPCO_FLASHCTL_ST_SE      0x02D8          /* Sector Erase */
514  #define SSB_CHIPCO_FLASHCTL_ST_BE      0x00C7          /* Bulk Erase */
515 -#define SSB_CHIPCO_FLASHCTL_ST_DP      0x00B9          /* Deep Power-down */
516 -#define SSB_CHIPCO_FLASHCTL_ST_RSIG    0x03AB          /* Read Electronic Signature */
517 +#define SSB_CHIPCO_FLASHCTL_ST_DP      0x00D9          /* Deep Power-down */
518 +#define SSB_CHIPCO_FLASHCTL_ST_RES     0x03AB          /* Read Electronic Signature */
519 +#define SSB_CHIPCO_FLASHCTL_ST_CSA     0x1000          /* Keep chip select asserted */
520 +#define SSB_CHIPCO_FLASHCTL_ST_SSE     0x0220          /* Sub-sector Erase */
521  
522  /* Status register bits for ST flashes */
523  #define SSB_CHIPCO_FLASHSTA_ST_WIP     0x01            /* Write In Progress */
524 @@ -585,6 +587,7 @@ struct ssb_chipcommon_pmu {
525  #ifdef CONFIG_SSB_DRIVER_MIPS
526  enum ssb_flash_type {
527         SSB_PFLASH,
528 +       SSB_SFLASH,
529  };
530  
531  struct ssb_pflash {
532 @@ -592,6 +595,14 @@ struct ssb_pflash {
533         u32 window;
534         u32 window_size;
535  };
536 +
537 +#ifdef CONFIG_SSB_SFLASH
538 +struct ssb_sflash {
539 +       u32 blocksize;          /* Block size */
540 +       u32 numblocks;          /* Number of blocks */
541 +       u32 size;               /* Total size in bytes */
542 +};
543 +#endif /* CONFIG_SSB_SFLASH */
544  #endif /* CONFIG_SSB_DRIVER_MIPS */
545  
546  struct ssb_chipcommon {
547 @@ -605,6 +616,9 @@ struct ssb_chipcommon {
548         enum ssb_flash_type flash_type;
549         union {
550                 struct ssb_pflash pflash;
551 +#ifdef CONFIG_SSB_SFLASH
552 +               struct ssb_sflash sflash;
553 +#endif /* CONFIG_SSB_SFLASH */
554         };
555  #endif /* CONFIG_SSB_DRIVER_MIPS */
556  };
557 @@ -666,6 +680,16 @@ extern int ssb_chipco_serial_init(struct
558                                   struct ssb_serial_port *ports);
559  #endif /* CONFIG_SSB_SERIAL */
560  
561 +#ifdef CONFIG_SSB_SFLASH
562 +/* Chipcommon sflash support. */
563 +int ssb_sflash_read(struct ssb_chipcommon *cc, u32 offset, u32 len,
564 +                          u8 *buf);
565 +int ssb_sflash_poll(struct ssb_chipcommon *cc, u32 offset);
566 +int ssb_sflash_write(struct ssb_chipcommon *cc, u32 offset, u32 len,
567 +                           const u8 *buf);
568 +int ssb_sflash_erase(struct ssb_chipcommon *cc, u32 offset);
569 +#endif /* CONFIG_SSB_SFLASH */
570 +
571  /* PMU support */
572  extern void ssb_pmu_init(struct ssb_chipcommon *cc);
573