9a9c19417e0278d4a1ef382f06867965119ac38b
[openwrt.git] / target / linux / brcm47xx / patches-3.8 / 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,14 +1,35 @@
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 +#define NUM_RETRIES    3
33 +
34 +static struct resource ssb_sflash_resource = {
35 +       .name   = "ssb_sflash",
36 +       .start  = SSB_FLASH2,
37 +       .end    = 0,
38 +       .flags  = IORESOURCE_MEM | IORESOURCE_READONLY,
39 +};
40 +
41 +struct platform_device ssb_sflash_dev = {
42 +       .name           = "bcm47xx-sflash",
43 +       .resource       = &ssb_sflash_resource,
44 +       .num_resources  = 1,
45 +};
46 +
47  struct ssb_sflash_tbl_e {
48         char *name;
49         u32 id;
50 @@ -16,7 +37,7 @@ struct ssb_sflash_tbl_e {
51         u16 numblocks;
52  };
53  
54 -static struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = {
55 +static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = {
56         { "M25P20", 0x11, 0x10000, 4, },
57         { "M25P40", 0x12, 0x10000, 8, },
58  
59 @@ -27,7 +48,7 @@ static struct ssb_sflash_tbl_e ssb_sflas
60         { 0 },
61  };
62  
63 -static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = {
64 +static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = {
65         { "SST25WF512", 1, 0x1000, 16, },
66         { "SST25VF512", 0x48, 0x1000, 16, },
67         { "SST25WF010", 2, 0x1000, 32, },
68 @@ -45,7 +66,7 @@ static struct ssb_sflash_tbl_e ssb_sflas
69         { 0 },
70  };
71  
72 -static struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = {
73 +static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = {
74         { "AT45DB011", 0xc, 256, 512, },
75         { "AT45DB021", 0x14, 256, 1024, },
76         { "AT45DB041", 0x1c, 256, 2048, },
77 @@ -70,10 +91,186 @@ static void ssb_sflash_cmd(struct ssb_ch
78         pr_err("SFLASH control command failed (timeout)!\n");
79  }
80  
81 +static void ssb_sflash_write_u8(struct ssb_chipcommon *chipco, u32 offset, u8 byte)
82 +{
83 +       chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, offset);
84 +       chipco_write32(chipco, SSB_CHIPCO_FLASHDATA, byte);
85 +}
86 +
87 +/* Poll for command completion. Returns zero when complete. */
88 +static int ssb_sflash_poll(struct bcm47xxsflash *dev, u32 offset)
89 +{
90 +       struct ssb_chipcommon *chipco = dev->scc;
91 +
92 +       if (offset >= chipco->sflash.size)
93 +               return -22;
94 +
95 +       switch (chipco->capabilities & SSB_CHIPCO_CAP_FLASHT) {
96 +       case SSB_CHIPCO_FLASHT_STSER:
97 +               /* Check for ST Write In Progress bit */
98 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_RDSR);
99 +               return chipco_read32(chipco, SSB_CHIPCO_FLASHDATA)
100 +                               & SSB_CHIPCO_FLASHDATA_ST_WIP;
101 +       case SSB_CHIPCO_FLASHT_ATSER:
102 +               /* Check for Atmel Ready bit */
103 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_STATUS);
104 +               return !(chipco_read32(chipco, SSB_CHIPCO_FLASHDATA)
105 +                               & SSB_CHIPCO_FLASHDATA_AT_READY);
106 +       }
107 +
108 +       return 0;
109 +}
110 +
111 +
112 +static int sflash_st_write(struct bcm47xxsflash *dev, u32 offset, u32 len,
113 +                          const u8 *buf)
114 +{
115 +       int written = 1;
116 +       struct ssb_chipcommon *chipco = dev->scc;
117 +
118 +       /* Enable writes */
119 +       ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_WREN);
120 +       ssb_sflash_write_u8(chipco, offset, *buf++);
121 +       /* Issue a page program with CSA bit set */
122 +       ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_CSA | SSB_CHIPCO_FLASHCTL_ST_PP);
123 +       offset++;
124 +       len--;
125 +       while (len > 0) {
126 +               if ((offset & 255) == 0) {
127 +                       /* Page boundary, poll droping cs and return */
128 +                       chipco_write32(chipco, SSB_CHIPCO_FLASHCTL, 0);
129 +                       udelay(1);
130 +                       if (!ssb_sflash_poll(dev, offset)) {
131 +                               /* Flash rejected command */
132 +                               return -EAGAIN;
133 +                       }
134 +                       return written;
135 +               } else {
136 +                       /* Write single byte */
137 +                       ssb_sflash_cmd(chipco,
138 +                                       SSB_CHIPCO_FLASHCTL_ST_CSA |
139 +                                       *buf++);
140 +               }
141 +               written++;
142 +               offset++;
143 +               len--;
144 +       }
145 +       /* All done, drop cs & poll */
146 +       chipco_write32(chipco, SSB_CHIPCO_FLASHCTL, 0);
147 +       udelay(1);
148 +       if (!ssb_sflash_poll(dev, offset)) {
149 +               /* Flash rejected command */
150 +               return -EAGAIN;
151 +       }
152 +       return written;
153 +}
154 +
155 +static int sflash_at_write(struct bcm47xxsflash *dev, u32 offset, u32 len,
156 +                          const u8 *buf)
157 +{
158 +       struct ssb_chipcommon *chipco = dev->scc;
159 +       u32 page, byte, mask;
160 +       int ret = 0;
161 +
162 +       mask = dev->blocksize - 1;
163 +       page = (offset & ~mask) << 1;
164 +       byte = offset & mask;
165 +       /* Read main memory page into buffer 1 */
166 +       if (byte || (len < dev->blocksize)) {
167 +               int i = 100;
168 +               chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, page);
169 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_BUF1_LOAD);
170 +               /* 250 us for AT45DB321B */
171 +               while (i > 0 && ssb_sflash_poll(dev, offset)) {
172 +                       udelay(10);
173 +                       i--;
174 +               }
175 +               BUG_ON(!ssb_sflash_poll(dev, offset));
176 +       }
177 +       /* Write into buffer 1 */
178 +       for (ret = 0; (ret < (int)len) && (byte < dev->blocksize); ret++) {
179 +               ssb_sflash_write_u8(chipco, byte++, *buf++);
180 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_BUF1_WRITE);
181 +       }
182 +       /* Write buffer 1 into main memory page */
183 +       chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, page);
184 +       ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_BUF1_PROGRAM);
185 +
186 +       return ret;
187 +}
188 +
189 +/* Write len bytes starting at offset into buf. Returns number of bytes
190 + * written. Caller should poll for completion.
191 + */
192 +static int ssb_sflash_write(struct bcm47xxsflash *dev, u32 offset, u32 len,
193 +                     const u8 *buf)
194 +{
195 +       int ret = 0, tries = NUM_RETRIES;
196 +       struct ssb_chipcommon *chipco = dev->scc;
197 +
198 +       if (!len)
199 +               return 0;
200 +
201 +       if ((offset + len) > chipco->sflash.size)
202 +               return -EINVAL;
203 +
204 +       switch (chipco->capabilities & SSB_CHIPCO_CAP_FLASHT) {
205 +       case SSB_CHIPCO_FLASHT_STSER:
206 +               do {
207 +                       ret = sflash_st_write(dev, offset, len, buf);
208 +                       tries--;
209 +               } while (ret == -EAGAIN && tries > 0);
210 +
211 +               if (ret == -EAGAIN && tries == 0) {
212 +                       pr_info("ST Flash rejected write\n");
213 +                       ret = -EIO;
214 +               }
215 +               break;
216 +       case SSB_CHIPCO_FLASHT_ATSER:
217 +               ret = sflash_at_write(dev, offset, len, buf);
218 +               break;
219 +       }
220 +
221 +       return ret;
222 +}
223 +
224 +/* Erase a region. Returns number of bytes scheduled for erasure.
225 + * Caller should poll for completion.
226 + */
227 +static int ssb_sflash_erase(struct bcm47xxsflash *dev, u32 offset)
228 +{
229 +       struct ssb_chipcommon *chipco = dev->scc;
230 +
231 +       if (offset >= chipco->sflash.size)
232 +               return -EINVAL;
233 +
234 +       switch (chipco->capabilities & SSB_CHIPCO_CAP_FLASHT) {
235 +       case SSB_CHIPCO_FLASHT_STSER:
236 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_WREN);
237 +               chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, offset);
238 +               /* Newer flashes have "sub-sectors" which can be erased independently
239 +                * with a new command: ST_SSE. The ST_SE command erases 64KB just as
240 +                * before.
241 +                */
242 +               if (dev->blocksize < (64 * 1024))
243 +                       ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_SSE);
244 +               else
245 +                       ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_ST_SE);
246 +               return dev->blocksize;
247 +       case SSB_CHIPCO_FLASHT_ATSER:
248 +               chipco_write32(chipco, SSB_CHIPCO_FLASHADDR, offset << 1);
249 +               ssb_sflash_cmd(chipco, SSB_CHIPCO_FLASHCTL_AT_PAGE_ERASE);
250 +               return dev->blocksize;
251 +       }
252 +
253 +       return 0;
254 +}
255 +
256  /* Initialize serial flash access */
257  int ssb_sflash_init(struct ssb_chipcommon *cc)
258  {
259 -       struct ssb_sflash_tbl_e *e;
260 +       struct bcm47xxsflash *sflash = &cc->sflash;
261 +       const struct ssb_sflash_tbl_e *e;
262         u32 id, id2;
263  
264         switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) {
265 @@ -131,10 +328,26 @@ int ssb_sflash_init(struct ssb_chipcommo
266                 return -ENOTSUPP;
267         }
268  
269 -       pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n",
270 -               e->name, e->blocksize, e->numblocks);
271 -
272 -       pr_err("Serial flash support is not implemented yet!\n");
273 +       sflash->window = SSB_FLASH2;
274 +       sflash->blocksize = e->blocksize;
275 +       sflash->numblocks = e->numblocks;
276 +       sflash->size = sflash->blocksize * sflash->numblocks;
277 +       sflash->present = true;
278 +       sflash->poll = ssb_sflash_poll;
279 +       sflash->write = ssb_sflash_write;
280 +       sflash->erase = ssb_sflash_erase;
281 +       sflash->type = BCM47XX_SFLASH_SSB;
282 +       sflash->scc = cc;
283 +
284 +       pr_info("Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n",
285 +                 e->name, sflash->size / 1024, sflash->blocksize,
286 +                 sflash->numblocks);
287 +
288 +       /* Prepare platform device, but don't register it yet. It's too early,
289 +        * malloc (required by device_private_init) is not available yet. */
290 +       ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start +
291 +                                         sflash->size;
292 +       ssb_sflash_dev.dev.platform_data = sflash;
293  
294 -       return -ENOTSUPP;
295 +       return 0;
296  }
297 --- a/drivers/ssb/main.c
298 +++ b/drivers/ssb/main.c
299 @@ -549,6 +549,15 @@ static int ssb_devices_register(struct s
300                 dev_idx++;
301         }
302  
303 +#ifdef CONFIG_SSB_SFLASH
304 +       if (bus->chipco.sflash.present) {
305 +               err = platform_device_register(&ssb_sflash_dev);
306 +               if (err)
307 +                       ssb_printk(KERN_ERR PFX
308 +                                  "Error registering serial flash\n");
309 +       }
310 +#endif
311 +
312  #ifdef CONFIG_SSB_DRIVER_MIPS
313         if (bus->mipscore.pflash.present) {
314                 err = platform_device_register(&ssb_pflash_dev);
315 --- a/drivers/ssb/ssb_private.h
316 +++ b/drivers/ssb/ssb_private.h
317 @@ -220,6 +220,7 @@ extern u32 ssb_chipco_watchdog_timer_set
318  /* driver_chipcommon_sflash.c */
319  #ifdef CONFIG_SSB_SFLASH
320  int ssb_sflash_init(struct ssb_chipcommon *cc);
321 +extern struct platform_device ssb_sflash_dev;
322  #else
323  static inline int ssb_sflash_init(struct ssb_chipcommon *cc)
324  {
325 --- a/include/linux/ssb/ssb_driver_chipcommon.h
326 +++ b/include/linux/ssb/ssb_driver_chipcommon.h
327 @@ -13,6 +13,8 @@
328   * Licensed under the GPL version 2. See COPYING for details.
329   */
330  
331 +#include <linux/mtd/bcm47xxsflash.h>
332 +
333  /** ChipCommon core registers. **/
334  
335  #define SSB_CHIPCO_CHIPID              0x0000
336 @@ -121,6 +123,17 @@
337  #define  SSB_CHIPCO_FLASHCTL_BUSY      SSB_CHIPCO_FLASHCTL_START
338  #define SSB_CHIPCO_FLASHADDR           0x0044
339  #define SSB_CHIPCO_FLASHDATA           0x0048
340 +/* Status register bits for ST flashes */
341 +#define  SSB_CHIPCO_FLASHDATA_ST_WIP   0x01            /* Write In Progress */
342 +#define  SSB_CHIPCO_FLASHDATA_ST_WEL   0x02            /* Write Enable Latch */
343 +#define  SSB_CHIPCO_FLASHDATA_ST_BP_MASK       0x1c            /* Block Protect */
344 +#define  SSB_CHIPCO_FLASHDATA_ST_BP_SHIFT      2
345 +#define  SSB_CHIPCO_FLASHDATA_ST_SRWD  0x80            /* Status Register Write Disable */
346 +/* Status register bits for Atmel flashes */
347 +#define  SSB_CHIPCO_FLASHDATA_AT_READY 0x80
348 +#define  SSB_CHIPCO_FLASHDATA_AT_MISMATCH      0x40
349 +#define  SSB_CHIPCO_FLASHDATA_AT_ID_MASK       0x38
350 +#define  SSB_CHIPCO_FLASHDATA_AT_ID_SHIFT      3
351  #define SSB_CHIPCO_BCAST_ADDR          0x0050
352  #define SSB_CHIPCO_BCAST_DATA          0x0054
353  #define SSB_CHIPCO_GPIOPULLUP          0x0058          /* Rev >= 20 only */
354 @@ -503,7 +516,7 @@
355  #define SSB_CHIPCO_FLASHCTL_ST_PP      0x0302          /* Page Program */
356  #define SSB_CHIPCO_FLASHCTL_ST_SE      0x02D8          /* Sector Erase */
357  #define SSB_CHIPCO_FLASHCTL_ST_BE      0x00C7          /* Bulk Erase */
358 -#define SSB_CHIPCO_FLASHCTL_ST_DP      0x00B9          /* Deep Power-down */
359 +#define SSB_CHIPCO_FLASHCTL_ST_DP      0x00D9          /* Deep Power-down */
360  #define SSB_CHIPCO_FLASHCTL_ST_RES     0x03AB          /* Read Electronic Signature */
361  #define SSB_CHIPCO_FLASHCTL_ST_CSA     0x1000          /* Keep chip select asserted */
362  #define SSB_CHIPCO_FLASHCTL_ST_SSE     0x0220          /* Sub-sector Erase */
363 @@ -594,6 +607,9 @@ struct ssb_chipcommon {
364         struct ssb_chipcommon_pmu pmu;
365         u32 ticks_per_ms;
366         u32 max_timer_ms;
367 +#ifdef CONFIG_SSB_SFLASH
368 +       struct bcm47xxsflash sflash;
369 +#endif
370  };
371  
372  static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)