kernel: update bcma and ssb to master-2013-01-09 from wireless-testing
[openwrt/staging/mkresin.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 @@ -503,7 +516,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 @@ -594,6 +607,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)