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