Root/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 
574

Archive Download this file



interactive