Version:  2.0.40 2.2.26 2.4.37 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8

Linux/drivers/mtd/devices/bcm47xxsflash.c

  1 #include <linux/kernel.h>
  2 #include <linux/module.h>
  3 #include <linux/slab.h>
  4 #include <linux/delay.h>
  5 #include <linux/ioport.h>
  6 #include <linux/mtd/mtd.h>
  7 #include <linux/platform_device.h>
  8 #include <linux/bcma/bcma.h>
  9 
 10 #include "bcm47xxsflash.h"
 11 
 12 MODULE_LICENSE("GPL");
 13 MODULE_DESCRIPTION("Serial flash driver for BCMA bus");
 14 
 15 static const char * const probes[] = { "bcm47xxpart", NULL };
 16 
 17 /**************************************************
 18  * Various helpers
 19  **************************************************/
 20 
 21 static void bcm47xxsflash_cmd(struct bcm47xxsflash *b47s, u32 opcode)
 22 {
 23         int i;
 24 
 25         b47s->cc_write(b47s, BCMA_CC_FLASHCTL, BCMA_CC_FLASHCTL_START | opcode);
 26         for (i = 0; i < 1000; i++) {
 27                 if (!(b47s->cc_read(b47s, BCMA_CC_FLASHCTL) &
 28                       BCMA_CC_FLASHCTL_BUSY))
 29                         return;
 30                 cpu_relax();
 31         }
 32         pr_err("Control command failed (timeout)!\n");
 33 }
 34 
 35 static int bcm47xxsflash_poll(struct bcm47xxsflash *b47s, int timeout)
 36 {
 37         unsigned long deadline = jiffies + timeout;
 38 
 39         do {
 40                 switch (b47s->type) {
 41                 case BCM47XXSFLASH_TYPE_ST:
 42                         bcm47xxsflash_cmd(b47s, OPCODE_ST_RDSR);
 43                         if (!(b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
 44                               SR_ST_WIP))
 45                                 return 0;
 46                         break;
 47                 case BCM47XXSFLASH_TYPE_ATMEL:
 48                         bcm47xxsflash_cmd(b47s, OPCODE_AT_STATUS);
 49                         if (b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
 50                             SR_AT_READY)
 51                                 return 0;
 52                         break;
 53                 }
 54 
 55                 cpu_relax();
 56                 udelay(1);
 57         } while (!time_after_eq(jiffies, deadline));
 58 
 59         pr_err("Timeout waiting for flash to be ready!\n");
 60 
 61         return -EBUSY;
 62 }
 63 
 64 /**************************************************
 65  * MTD ops
 66  **************************************************/
 67 
 68 static int bcm47xxsflash_erase(struct mtd_info *mtd, struct erase_info *erase)
 69 {
 70         struct bcm47xxsflash *b47s = mtd->priv;
 71         int err;
 72 
 73         switch (b47s->type) {
 74         case BCM47XXSFLASH_TYPE_ST:
 75                 bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN);
 76                 b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr);
 77                 /* Newer flashes have "sub-sectors" which can be erased
 78                  * independently with a new command: ST_SSE. The ST_SE command
 79                  * erases 64KB just as before.
 80                  */
 81                 if (b47s->blocksize < (64 * 1024))
 82                         bcm47xxsflash_cmd(b47s, OPCODE_ST_SSE);
 83                 else
 84                         bcm47xxsflash_cmd(b47s, OPCODE_ST_SE);
 85                 break;
 86         case BCM47XXSFLASH_TYPE_ATMEL:
 87                 b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr << 1);
 88                 bcm47xxsflash_cmd(b47s, OPCODE_AT_PAGE_ERASE);
 89                 break;
 90         }
 91 
 92         err = bcm47xxsflash_poll(b47s, HZ);
 93         if (err)
 94                 erase->state = MTD_ERASE_FAILED;
 95         else
 96                 erase->state = MTD_ERASE_DONE;
 97 
 98         if (erase->callback)
 99                 erase->callback(erase);
100 
101         return err;
102 }
103 
104 static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
105                               size_t *retlen, u_char *buf)
106 {
107         struct bcm47xxsflash *b47s = mtd->priv;
108 
109         /* Check address range */
110         if ((from + len) > mtd->size)
111                 return -EINVAL;
112 
113         memcpy_fromio(buf, b47s->window + from, len);
114         *retlen = len;
115 
116         return len;
117 }
118 
119 static int bcm47xxsflash_write_st(struct mtd_info *mtd, u32 offset, size_t len,
120                                   const u_char *buf)
121 {
122         struct bcm47xxsflash *b47s = mtd->priv;
123         int written = 0;
124 
125         /* Enable writes */
126         bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN);
127 
128         /* Write first byte */
129         b47s->cc_write(b47s, BCMA_CC_FLASHADDR, offset);
130         b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++);
131 
132         /* Program page */
133         if (b47s->bcma_cc->core->id.rev < 20) {
134                 bcm47xxsflash_cmd(b47s, OPCODE_ST_PP);
135                 return 1; /* 1B written */
136         }
137 
138         /* Program page and set CSA (on newer chips we can continue writing) */
139         bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | OPCODE_ST_PP);
140         offset++;
141         len--;
142         written++;
143 
144         while (len > 0) {
145                 /* Page boundary, another function call is needed */
146                 if ((offset & 0xFF) == 0)
147                         break;
148 
149                 bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | *buf++);
150                 offset++;
151                 len--;
152                 written++;
153         }
154 
155         /* All done, drop CSA & poll */
156         b47s->cc_write(b47s, BCMA_CC_FLASHCTL, 0);
157         udelay(1);
158         if (bcm47xxsflash_poll(b47s, HZ / 10))
159                 pr_err("Flash rejected dropping CSA\n");
160 
161         return written;
162 }
163 
164 static int bcm47xxsflash_write_at(struct mtd_info *mtd, u32 offset, size_t len,
165                                   const u_char *buf)
166 {
167         struct bcm47xxsflash *b47s = mtd->priv;
168         u32 mask = b47s->blocksize - 1;
169         u32 page = (offset & ~mask) << 1;
170         u32 byte = offset & mask;
171         int written = 0;
172 
173         /* If we don't overwrite whole page, read it to the buffer first */
174         if (byte || (len < b47s->blocksize)) {
175                 int err;
176 
177                 b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page);
178                 bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_LOAD);
179                 /* 250 us for AT45DB321B */
180                 err = bcm47xxsflash_poll(b47s, HZ / 1000);
181                 if (err) {
182                         pr_err("Timeout reading page 0x%X info buffer\n", page);
183                         return err;
184                 }
185         }
186 
187         /* Change buffer content with our data */
188         while (len > 0) {
189                 /* Page boundary, another function call is needed */
190                 if (byte == b47s->blocksize)
191                         break;
192 
193                 b47s->cc_write(b47s, BCMA_CC_FLASHADDR, byte++);
194                 b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++);
195                 bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_WRITE);
196                 len--;
197                 written++;
198         }
199 
200         /* Program page with the buffer content */
201         b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page);
202         bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_PROGRAM);
203 
204         return written;
205 }
206 
207 static int bcm47xxsflash_write(struct mtd_info *mtd, loff_t to, size_t len,
208                                size_t *retlen, const u_char *buf)
209 {
210         struct bcm47xxsflash *b47s = mtd->priv;
211         int written;
212 
213         /* Writing functions can return without writing all passed data, for
214          * example when the hardware is too old or when we git page boundary.
215          */
216         while (len > 0) {
217                 switch (b47s->type) {
218                 case BCM47XXSFLASH_TYPE_ST:
219                         written = bcm47xxsflash_write_st(mtd, to, len, buf);
220                         break;
221                 case BCM47XXSFLASH_TYPE_ATMEL:
222                         written = bcm47xxsflash_write_at(mtd, to, len, buf);
223                         break;
224                 default:
225                         BUG_ON(1);
226                 }
227                 if (written < 0) {
228                         pr_err("Error writing at offset 0x%llX\n", to);
229                         return written;
230                 }
231                 to += (loff_t)written;
232                 len -= written;
233                 *retlen += written;
234                 buf += written;
235         }
236 
237         return 0;
238 }
239 
240 static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s,
241                                    struct device *dev)
242 {
243         struct mtd_info *mtd = &b47s->mtd;
244 
245         mtd->priv = b47s;
246         mtd->dev.parent = dev;
247         mtd->name = "bcm47xxsflash";
248 
249         mtd->type = MTD_NORFLASH;
250         mtd->flags = MTD_CAP_NORFLASH;
251         mtd->size = b47s->size;
252         mtd->erasesize = b47s->blocksize;
253         mtd->writesize = 1;
254         mtd->writebufsize = 1;
255 
256         mtd->_erase = bcm47xxsflash_erase;
257         mtd->_read = bcm47xxsflash_read;
258         mtd->_write = bcm47xxsflash_write;
259 }
260 
261 /**************************************************
262  * BCMA
263  **************************************************/
264 
265 static int bcm47xxsflash_bcma_cc_read(struct bcm47xxsflash *b47s, u16 offset)
266 {
267         return bcma_cc_read32(b47s->bcma_cc, offset);
268 }
269 
270 static void bcm47xxsflash_bcma_cc_write(struct bcm47xxsflash *b47s, u16 offset,
271                                         u32 value)
272 {
273         bcma_cc_write32(b47s->bcma_cc, offset, value);
274 }
275 
276 static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
277 {
278         struct device *dev = &pdev->dev;
279         struct bcma_sflash *sflash = dev_get_platdata(dev);
280         struct bcm47xxsflash *b47s;
281         struct resource *res;
282         int err;
283 
284         b47s = devm_kzalloc(dev, sizeof(*b47s), GFP_KERNEL);
285         if (!b47s)
286                 return -ENOMEM;
287         sflash->priv = b47s;
288 
289         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
290         if (!res) {
291                 dev_err(dev, "invalid resource\n");
292                 return -EINVAL;
293         }
294         if (!devm_request_mem_region(dev, res->start, resource_size(res),
295                                      res->name)) {
296                 dev_err(dev, "can't request region for resource %pR\n", res);
297                 return -EBUSY;
298         }
299         b47s->window = ioremap_cache(res->start, resource_size(res));
300         if (!b47s->window) {
301                 dev_err(dev, "ioremap failed for resource %pR\n", res);
302                 return -ENOMEM;
303         }
304 
305         b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash);
306         b47s->cc_read = bcm47xxsflash_bcma_cc_read;
307         b47s->cc_write = bcm47xxsflash_bcma_cc_write;
308 
309         switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) {
310         case BCMA_CC_FLASHT_STSER:
311                 b47s->type = BCM47XXSFLASH_TYPE_ST;
312                 break;
313         case BCMA_CC_FLASHT_ATSER:
314                 b47s->type = BCM47XXSFLASH_TYPE_ATMEL;
315                 break;
316         }
317 
318         b47s->blocksize = sflash->blocksize;
319         b47s->numblocks = sflash->numblocks;
320         b47s->size = sflash->size;
321         bcm47xxsflash_fill_mtd(b47s, &pdev->dev);
322 
323         err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0);
324         if (err) {
325                 pr_err("Failed to register MTD device: %d\n", err);
326                 iounmap(b47s->window);
327                 return err;
328         }
329 
330         if (bcm47xxsflash_poll(b47s, HZ / 10))
331                 pr_warn("Serial flash busy\n");
332 
333         return 0;
334 }
335 
336 static int bcm47xxsflash_bcma_remove(struct platform_device *pdev)
337 {
338         struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
339         struct bcm47xxsflash *b47s = sflash->priv;
340 
341         mtd_device_unregister(&b47s->mtd);
342         iounmap(b47s->window);
343 
344         return 0;
345 }
346 
347 static struct platform_driver bcma_sflash_driver = {
348         .probe  = bcm47xxsflash_bcma_probe,
349         .remove = bcm47xxsflash_bcma_remove,
350         .driver = {
351                 .name = "bcma_sflash",
352         },
353 };
354 
355 /**************************************************
356  * Init
357  **************************************************/
358 
359 module_platform_driver(bcma_sflash_driver);
360 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us