Root/target/linux/brcm47xx/patches-3.2/0013-bcma-add-serial-flash-support-to-bcma.patch

1From a62940e988526c881966a8c72cc28c95fca89f3c Mon Sep 17 00:00:00 2001
2From: Hauke Mehrtens <hauke@hauke-m.de>
3Date: Sun, 17 Jul 2011 14:53:07 +0200
4Subject: [PATCH 13/26] bcma: add serial flash support to bcma
5
6
7Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
8---
9 drivers/bcma/Kconfig | 5 +
10 drivers/bcma/Makefile | 1 +
11 drivers/bcma/bcma_private.h | 5 +
12 drivers/bcma/driver_chipcommon_sflash.c | 555 +++++++++++++++++++++++++++
13 drivers/bcma/driver_mips.c | 8 +-
14 include/linux/bcma/bcma_driver_chipcommon.h | 24 ++
15 6 files changed, 597 insertions(+), 1 deletions(-)
16 create mode 100644 drivers/bcma/driver_chipcommon_sflash.c
17
18--- a/drivers/bcma/Kconfig
19+++ b/drivers/bcma/Kconfig
20@@ -38,6 +38,11 @@ config BCMA_HOST_SOC
21     bool
22     depends on BCMA_DRIVER_MIPS
23 
24+config BCMA_SFLASH
25+ bool
26+ depends on BCMA_DRIVER_MIPS
27+ default y
28+
29 config BCMA_DRIVER_MIPS
30     bool "BCMA Broadcom MIPS core driver"
31     depends on BCMA && MIPS
32--- a/drivers/bcma/Makefile
33+++ b/drivers/bcma/Makefile
34@@ -1,5 +1,6 @@
35 bcma-y += main.o scan.o core.o sprom.o
36 bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
37+bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o
38 bcma-y += driver_pci.o
39 bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
40 bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
41--- a/drivers/bcma/bcma_private.h
42+++ b/drivers/bcma/bcma_private.h
43@@ -41,6 +41,11 @@ void bcma_chipco_serial_init(struct bcma
44 u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
45 u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
46 
47+#ifdef CONFIG_BCMA_SFLASH
48+/* driver_chipcommon_sflash.c */
49+int bcma_sflash_init(struct bcma_drv_cc *cc);
50+#endif /* CONFIG_BCMA_SFLASH */
51+
52 #ifdef CONFIG_BCMA_HOST_PCI
53 /* host_pci.c */
54 extern int __init bcma_host_pci_init(void);
55--- /dev/null
56+++ b/drivers/bcma/driver_chipcommon_sflash.c
57@@ -0,0 +1,555 @@
58+/*
59+ * Broadcom SiliconBackplane chipcommon serial flash interface
60+ *
61+ * Copyright 2011, Jonas Gorski <jonas.gorski@gmail.com>
62+ * Copyright 2010, Broadcom Corporation
63+ *
64+ * Licensed under the GNU/GPL. See COPYING for details.
65+ */
66+
67+#include <linux/bcma/bcma.h>
68+#include <linux/bcma/bcma_driver_chipcommon.h>
69+#include <linux/delay.h>
70+
71+#include "bcma_private.h"
72+
73+#define NUM_RETRIES 3
74+
75+
76+/* Issue a serial flash command */
77+static inline void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
78+{
79+ bcma_cc_write32(cc, BCMA_CC_FLASHCTL,
80+ BCMA_CC_FLASHCTL_START | opcode);
81+ while (bcma_cc_read32(cc, BCMA_CC_FLASHCTL) & BCMA_CC_FLASHCTL_BUSY)
82+ ;
83+}
84+
85+
86+static inline void bcma_sflash_write_u8(struct bcma_drv_cc *cc,
87+ u32 offset, u8 byte)
88+{
89+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, offset);
90+ bcma_cc_write32(cc, BCMA_CC_FLASHDATA, byte);
91+}
92+
93+/* Initialize serial flash access */
94+int bcma_sflash_init(struct bcma_drv_cc *cc)
95+{
96+ u32 id, id2;
97+
98+ memset(&cc->sflash, 0, sizeof(struct bcma_sflash));
99+
100+ switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
101+ case BCMA_CC_FLASHT_STSER:
102+ /* Probe for ST chips */
103+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_DP);
104+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 0);
105+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
106+ id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
107+ cc->sflash.blocksize = 64 * 1024;
108+ switch (id) {
109+ case 0x11:
110+ /* ST M25P20 2 Mbit Serial Flash */
111+ cc->sflash.numblocks = 4;
112+ break;
113+ case 0x12:
114+ /* ST M25P40 4 Mbit Serial Flash */
115+ cc->sflash.numblocks = 8;
116+ break;
117+ case 0x13:
118+ /* ST M25P80 8 Mbit Serial Flash */
119+ cc->sflash.numblocks = 16;
120+ break;
121+ case 0x14:
122+ /* ST M25P16 16 Mbit Serial Flash */
123+ cc->sflash.numblocks = 32;
124+ break;
125+ case 0x15:
126+ /* ST M25P32 32 Mbit Serial Flash */
127+ cc->sflash.numblocks = 64;
128+ break;
129+ case 0x16:
130+ /* ST M25P64 64 Mbit Serial Flash */
131+ cc->sflash.numblocks = 128;
132+ break;
133+ case 0x17:
134+ /* ST M25FL128 128 Mbit Serial Flash */
135+ cc->sflash.numblocks = 256;
136+ break;
137+ case 0xbf:
138+ /* All of the following flashes are SST with
139+ * 4KB subsectors. Others should be added but
140+ * We'll have to revamp the way we identify them
141+ * since RES is not eough to disambiguate them.
142+ */
143+ cc->sflash.blocksize = 4 * 1024;
144+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 1);
145+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
146+ id2 = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
147+ switch (id2) {
148+ case 1:
149+ /* SST25WF512 512 Kbit Serial Flash */
150+ case 0x48:
151+ /* SST25VF512 512 Kbit Serial Flash */
152+ cc->sflash.numblocks = 16;
153+ break;
154+ case 2:
155+ /* SST25WF010 1 Mbit Serial Flash */
156+ case 0x49:
157+ /* SST25VF010 1 Mbit Serial Flash */
158+ cc->sflash.numblocks = 32;
159+ break;
160+ case 3:
161+ /* SST25WF020 2 Mbit Serial Flash */
162+ case 0x43:
163+ /* SST25VF020 2 Mbit Serial Flash */
164+ cc->sflash.numblocks = 64;
165+ break;
166+ case 4:
167+ /* SST25WF040 4 Mbit Serial Flash */
168+ case 0x44:
169+ /* SST25VF040 4 Mbit Serial Flash */
170+ case 0x8d:
171+ /* SST25VF040B 4 Mbit Serial Flash */
172+ cc->sflash.numblocks = 128;
173+ break;
174+ case 5:
175+ /* SST25WF080 8 Mbit Serial Flash */
176+ case 0x8e:
177+ /* SST25VF080B 8 Mbit Serial Flash */
178+ cc->sflash.numblocks = 256;
179+ break;
180+ case 0x41:
181+ /* SST25VF016 16 Mbit Serial Flash */
182+ cc->sflash.numblocks = 512;
183+ break;
184+ case 0x4a:
185+ /* SST25VF032 32 Mbit Serial Flash */
186+ cc->sflash.numblocks = 1024;
187+ break;
188+ case 0x4b:
189+ /* SST25VF064 64 Mbit Serial Flash */
190+ cc->sflash.numblocks = 2048;
191+ break;
192+ }
193+ break;
194+ }
195+ break;
196+
197+ case BCMA_CC_FLASHT_ATSER:
198+ /* Probe for Atmel chips */
199+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS);
200+ id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA) & 0x3c;
201+ switch (id) {
202+ case 0xc:
203+ /* Atmel AT45DB011 1Mbit Serial Flash */
204+ cc->sflash.blocksize = 256;
205+ cc->sflash.numblocks = 512;
206+ break;
207+ case 0x14:
208+ /* Atmel AT45DB021 2Mbit Serial Flash */
209+ cc->sflash.blocksize = 256;
210+ cc->sflash.numblocks = 1024;
211+ break;
212+ case 0x1c:
213+ /* Atmel AT45DB041 4Mbit Serial Flash */
214+ cc->sflash.blocksize = 256;
215+ cc->sflash.numblocks = 2048;
216+ break;
217+ case 0x24:
218+ /* Atmel AT45DB081 8Mbit Serial Flash */
219+ cc->sflash.blocksize = 256;
220+ cc->sflash.numblocks = 4096;
221+ break;
222+ case 0x2c:
223+ /* Atmel AT45DB161 16Mbit Serial Flash */
224+ cc->sflash.blocksize = 512;
225+ cc->sflash.numblocks = 4096;
226+ break;
227+ case 0x34:
228+ /* Atmel AT45DB321 32Mbit Serial Flash */
229+ cc->sflash.blocksize = 512;
230+ cc->sflash.numblocks = 8192;
231+ break;
232+ case 0x3c:
233+ /* Atmel AT45DB642 64Mbit Serial Flash */
234+ cc->sflash.blocksize = 1024;
235+ cc->sflash.numblocks = 8192;
236+ break;
237+ }
238+ break;
239+ }
240+
241+ cc->sflash.size = cc->sflash.blocksize * cc->sflash.numblocks;
242+
243+ return cc->sflash.size ? 0 : -ENODEV;
244+}
245+
246+/* Read len bytes starting at offset into buf. Returns number of bytes read. */
247+int bcma_sflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len,
248+ u8 *buf)
249+{
250+ u8 *from, *to;
251+ u32 cnt, i;
252+
253+ if (!len)
254+ return 0;
255+
256+ if ((offset + len) > cc->sflash.size)
257+ return -EINVAL;
258+
259+ if ((len >= 4) && (offset & 3))
260+ cnt = 4 - (offset & 3);
261+ else if ((len >= 4) && ((u32)buf & 3))
262+ cnt = 4 - ((u32)buf & 3);
263+ else
264+ cnt = len;
265+
266+
267+ if (cc->core->id.rev == 12)
268+ from = (u8 *)KSEG1ADDR(BCMA_FLASH2 + offset);
269+ else
270+ from = (u8 *)KSEG0ADDR(BCMA_FLASH2 + offset);
271+
272+ to = (u8 *)buf;
273+
274+ if (cnt < 4) {
275+ for (i = 0; i < cnt; i++) {
276+ *to = readb(from);
277+ from++;
278+ to++;
279+ }
280+ return cnt;
281+ }
282+
283+ while (cnt >= 4) {
284+ *(u32 *)to = readl(from);
285+ from += 4;
286+ to += 4;
287+ cnt -= 4;
288+ }
289+
290+ return len - cnt;
291+}
292+
293+/* Poll for command completion. Returns zero when complete. */
294+int bcma_sflash_poll(struct bcma_drv_cc *cc, u32 offset)
295+{
296+ if (offset >= cc->sflash.size)
297+ return -22;
298+
299+ switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
300+ case BCMA_CC_FLASHT_STSER:
301+ /* Check for ST Write In Progress bit */
302+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RDSR);
303+ return bcma_cc_read32(cc, BCMA_CC_FLASHDATA)
304+ & BCMA_CC_FLASHDATA_ST_WIP;
305+ case BCMA_CC_FLASHT_ATSER:
306+ /* Check for Atmel Ready bit */
307+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS);
308+ return !(bcma_cc_read32(cc, BCMA_CC_FLASHDATA)
309+ & BCMA_CC_FLASHDATA_AT_READY);
310+ }
311+
312+ return 0;
313+}
314+
315+
316+static int sflash_st_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
317+ const u8 *buf)
318+{
319+ struct bcma_bus *bus = cc->core->bus;
320+ int ret = 0;
321+ bool is4712b0 = (bus->chipinfo.id == 0x4712) && (bus->chipinfo.rev == 3);
322+ u32 mask;
323+
324+
325+ /* Enable writes */
326+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_WREN);
327+ if (is4712b0) {
328+ mask = 1 << 14;
329+ bcma_sflash_write_u8(cc, offset, *buf++);
330+ /* Set chip select */
331+ bcma_cc_set32(cc, BCMA_CC_GPIOOUT, mask);
332+ /* Issue a page program with the first byte */
333+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_PP);
334+ ret = 1;
335+ offset++;
336+ len--;
337+ while (len > 0) {
338+ if ((offset & 255) == 0) {
339+ /* Page boundary, drop cs and return */
340+ bcma_cc_mask32(cc, BCMA_CC_GPIOOUT, ~mask);
341+ udelay(1);
342+ if (!bcma_sflash_poll(cc, offset)) {
343+ /* Flash rejected command */
344+ return -EAGAIN;
345+ }
346+ return ret;
347+ } else {
348+ /* Write single byte */
349+ bcma_sflash_cmd(cc, *buf++);
350+ }
351+ ret++;
352+ offset++;
353+ len--;
354+ }
355+ /* All done, drop cs */
356+ bcma_cc_mask32(cc, BCMA_CC_GPIOOUT, ~mask);
357+ udelay(1);
358+ if (!bcma_sflash_poll(cc, offset)) {
359+ /* Flash rejected command */
360+ return -EAGAIN;
361+ }
362+ } else if (cc->core->id.rev >= 20) {
363+ bcma_sflash_write_u8(cc, offset, *buf++);
364+ /* Issue a page program with CSA bit set */
365+ bcma_sflash_cmd(cc,
366+ BCMA_CC_FLASHCTL_ST_CSA |
367+ BCMA_CC_FLASHCTL_ST_PP);
368+ ret = 1;
369+ offset++;
370+ len--;
371+ while (len > 0) {
372+ if ((offset & 255) == 0) {
373+ /* Page boundary, poll droping cs and return */
374+ bcma_cc_write32(cc, BCMA_CC_FLASHCTL, 0);
375+ udelay(1);
376+ if (!bcma_sflash_poll(cc, offset)) {
377+ /* Flash rejected command */
378+ return -EAGAIN;
379+ }
380+ return ret;
381+ } else {
382+ /* Write single byte */
383+ bcma_sflash_cmd(cc,
384+ BCMA_CC_FLASHCTL_ST_CSA |
385+ *buf++);
386+ }
387+ ret++;
388+ offset++;
389+ len--;
390+ }
391+ /* All done, drop cs & poll */
392+ bcma_cc_write32(cc, BCMA_CC_FLASHCTL, 0);
393+ udelay(1);
394+ if (!bcma_sflash_poll(cc, offset)) {
395+ /* Flash rejected command */
396+ return -EAGAIN;
397+ }
398+ } else {
399+ ret = 1;
400+ bcma_sflash_write_u8(cc, offset, *buf);
401+ /* Page program */
402+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_PP);
403+ }
404+ return ret;
405+}
406+
407+static int sflash_at_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
408+ const u8 *buf)
409+{
410+ struct bcma_sflash *sfl = &cc->sflash;
411+ u32 page, byte, mask;
412+ int ret = 0;
413+ mask = sfl->blocksize - 1;
414+ page = (offset & ~mask) << 1;
415+ byte = offset & mask;
416+ /* Read main memory page into buffer 1 */
417+ if (byte || (len < sfl->blocksize)) {
418+ int i = 100;
419+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, page);
420+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_BUF1_LOAD);
421+ /* 250 us for AT45DB321B */
422+ while (i > 0 && bcma_sflash_poll(cc, offset)) {
423+ udelay(10);
424+ i--;
425+ }
426+ BUG_ON(!bcma_sflash_poll(cc, offset));
427+ }
428+ /* Write into buffer 1 */
429+ for (ret = 0; (ret < (int)len) && (byte < sfl->blocksize); ret++) {
430+ bcma_sflash_write_u8(cc, byte++, *buf++);
431+ bcma_sflash_cmd(cc,
432+ BCMA_CC_FLASHCTL_AT_BUF1_WRITE);
433+ }
434+ /* Write buffer 1 into main memory page */
435+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, page);
436+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_BUF1_PROGRAM);
437+
438+ return ret;
439+}
440+
441+/* Write len bytes starting at offset into buf. Returns number of bytes
442+ * written. Caller should poll for completion.
443+ */
444+int bcma_sflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
445+ const u8 *buf)
446+{
447+ struct bcma_sflash *sfl;
448+ int ret = 0, tries = NUM_RETRIES;
449+
450+ if (!len)
451+ return 0;
452+
453+ if ((offset + len) > cc->sflash.size)
454+ return -EINVAL;
455+
456+ sfl = &cc->sflash;
457+ switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
458+ case BCMA_CC_FLASHT_STSER:
459+ do {
460+ ret = sflash_st_write(cc, offset, len, buf);
461+ tries--;
462+ } while (ret == -EAGAIN && tries > 0);
463+
464+ if (ret == -EAGAIN && tries == 0) {
465+ pr_info("ST Flash rejected write\n");
466+ ret = -EIO;
467+ }
468+ break;
469+ case BCMA_CC_FLASHT_ATSER:
470+ ret = sflash_at_write(cc, offset, len, buf);
471+ break;
472+ }
473+
474+ return ret;
475+}
476+
477+/* Erase a region. Returns number of bytes scheduled for erasure.
478+ * Caller should poll for completion.
479+ */
480+int bcma_sflash_erase(struct bcma_drv_cc *cc, u32 offset)
481+{
482+ struct bcma_sflash *sfl;
483+
484+ if (offset >= cc->sflash.size)
485+ return -EINVAL;
486+
487+ sfl = &cc->sflash;
488+ switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
489+ case BCMA_CC_FLASHT_STSER:
490+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_WREN);
491+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, offset);
492+ /* Newer flashes have "sub-sectors" which can be erased independently
493+ * with a new command: ST_SSE. The ST_SE command erases 64KB just as
494+ * before.
495+ */
496+ bcma_sflash_cmd(cc, (sfl->blocksize < (64 * 1024)) ? BCMA_CC_FLASHCTL_ST_SSE : BCMA_CC_FLASHCTL_ST_SE);
497+ return sfl->blocksize;
498+ case BCMA_CC_FLASHT_ATSER:
499+ bcma_cc_write32(cc, BCMA_CC_FLASHADDR, offset << 1);
500+ bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_PAGE_ERASE);
501+ return sfl->blocksize;
502+ }
503+
504+ return 0;
505+}
506+
507+/*
508+ * writes the appropriate range of flash, a NULL buf simply erases
509+ * the region of flash
510+ */
511+int bcma_sflash_commit(struct bcma_drv_cc *cc, u32 offset, u32 len,
512+ const u8 *buf)
513+{
514+ struct bcma_sflash *sfl;
515+ u8 *block = NULL, *cur_ptr, *blk_ptr;
516+ u32 blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder;
517+ u32 blk_offset, blk_len, copied;
518+ int bytes, ret = 0;
519+
520+ /* Check address range */
521+ if (len <= 0)
522+ return 0;
523+
524+ sfl = &cc->sflash;
525+ if ((offset + len) > sfl->size)
526+ return -EINVAL;
527+
528+ blocksize = sfl->blocksize;
529+ mask = blocksize - 1;
530+
531+ /* Allocate a block of mem */
532+ block = kmalloc(blocksize, GFP_KERNEL);
533+ if (!block)
534+ return -ENOMEM;
535+
536+ while (len) {
537+ /* Align offset */
538+ cur_offset = offset & ~mask;
539+ cur_length = blocksize;
540+ cur_ptr = block;
541+
542+ remainder = blocksize - (offset & mask);
543+ if (len < remainder)
544+ cur_retlen = len;
545+ else
546+ cur_retlen = remainder;
547+
548+ /* buf == NULL means erase only */
549+ if (buf) {
550+ /* Copy existing data into holding block if necessary */
551+ if ((offset & mask) || (len < blocksize)) {
552+ blk_offset = cur_offset;
553+ blk_len = cur_length;
554+ blk_ptr = cur_ptr;
555+
556+ /* Copy entire block */
557+ while (blk_len) {
558+ copied = bcma_sflash_read(cc,
559+ blk_offset,
560+ blk_len, blk_ptr);
561+ blk_offset += copied;
562+ blk_len -= copied;
563+ blk_ptr += copied;
564+ }
565+ }
566+
567+ /* Copy input data into holding block */
568+ memcpy(cur_ptr + (offset & mask), buf, cur_retlen);
569+ }
570+
571+ /* Erase block */
572+ ret = bcma_sflash_erase(cc, cur_offset);
573+ if (ret < 0)
574+ goto done;
575+
576+ while (bcma_sflash_poll(cc, cur_offset));
577+
578+ /* buf == NULL means erase only */
579+ if (!buf) {
580+ offset += cur_retlen;
581+ len -= cur_retlen;
582+ continue;
583+ }
584+
585+ /* Write holding block */
586+ while (cur_length > 0) {
587+ bytes = bcma_sflash_write(cc, cur_offset,
588+ cur_length, cur_ptr);
589+
590+ if (bytes < 0) {
591+ ret = bytes;
592+ goto done;
593+ }
594+
595+ while (bcma_sflash_poll(cc, cur_offset))
596+ ;
597+
598+ cur_offset += bytes;
599+ cur_length -= bytes;
600+ cur_ptr += bytes;
601+ }
602+
603+ offset += cur_retlen;
604+ len -= cur_retlen;
605+ buf += cur_retlen;
606+ }
607+
608+ ret = len;
609+done:
610+ kfree(block);
611+ return ret;
612+}
613--- a/drivers/bcma/driver_mips.c
614+++ b/drivers/bcma/driver_mips.c
615@@ -185,7 +185,13 @@ static void bcma_core_mips_flash_detect(
616     switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
617     case BCMA_CC_FLASHT_STSER:
618     case BCMA_CC_FLASHT_ATSER:
619- pr_err("Serial flash not supported.\n");
620+#ifdef CONFIG_BCMA_SFLASH
621+ pr_info("found serial flash.\n");
622+ bus->drv_cc.flash_type = BCMA_SFLASH;
623+ bcma_sflash_init(&bus->drv_cc);
624+#else
625+ pr_info("serial flash not supported.\n");
626+#endif /* CONFIG_BCMA_SFLASH */
627         break;
628     case BCMA_CC_FLASHT_PARA:
629         pr_info("found parallel flash.\n");
630--- a/include/linux/bcma/bcma_driver_chipcommon.h
631+++ b/include/linux/bcma/bcma_driver_chipcommon.h
632@@ -375,6 +375,7 @@ struct bcma_chipcommon_pmu {
633 #ifdef CONFIG_BCMA_DRIVER_MIPS
634 enum bcma_flash_type {
635     BCMA_PFLASH,
636+ BCMA_SFLASH,
637 };
638 
639 struct bcma_pflash {
640@@ -383,6 +384,14 @@ struct bcma_pflash {
641     u32 window_size;
642 };
643 
644+#ifdef CONFIG_BCMA_SFLASH
645+struct bcma_sflash {
646+ u32 blocksize; /* Block size */
647+ u32 numblocks; /* Number of blocks */
648+ u32 size; /* Total size in bytes */
649+};
650+#endif /* CONFIG_BCMA_SFLASH */
651+
652 struct bcma_serial_port {
653     void *regs;
654     unsigned long clockspeed;
655@@ -405,6 +414,9 @@ struct bcma_drv_cc {
656     enum bcma_flash_type flash_type;
657     union {
658         struct bcma_pflash pflash;
659+#ifdef CONFIG_BCMA_SFLASH
660+ struct bcma_sflash sflash;
661+#endif /* CONFIG_BCMA_SFLASH */
662     };
663 
664     int nr_serial_ports;
665@@ -459,4 +471,16 @@ extern void bcma_chipco_chipctl_maskset(
666 extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc,
667                        u32 offset, u32 mask, u32 set);
668 
669+#ifdef CONFIG_BCMA_SFLASH
670+/* Chipcommon sflash support. */
671+int bcma_sflash_read(struct bcma_drv_cc *cc, u32 offset, u32 len,
672+ u8 *buf);
673+int bcma_sflash_poll(struct bcma_drv_cc *cc, u32 offset);
674+int bcma_sflash_write(struct bcma_drv_cc *cc, u32 offset, u32 len,
675+ const u8 *buf);
676+int bcma_sflash_erase(struct bcma_drv_cc *cc, u32 offset);
677+int bcma_sflash_commit(struct bcma_drv_cc *cc, u32 offset, u32 len,
678+ const u8 *buf);
679+#endif /* CONFIG_BCMA_SFLASH */
680+
681 #endif /* LINUX_BCMA_DRIVER_CC_H_ */
682

Archive Download this file



interactive