Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 #include <linux/kernel.h>
0003 #include <linux/module.h>
0004 #include <linux/slab.h>
0005 #include <linux/delay.h>
0006 #include <linux/ioport.h>
0007 #include <linux/mtd/mtd.h>
0008 #include <linux/platform_device.h>
0009 #include <linux/bcma/bcma.h>
0010 
0011 #include "bcm47xxsflash.h"
0012 
0013 MODULE_LICENSE("GPL");
0014 MODULE_DESCRIPTION("Serial flash driver for BCMA bus");
0015 
0016 static const char * const probes[] = { "bcm47xxpart", NULL };
0017 
0018 /**************************************************
0019  * Various helpers
0020  **************************************************/
0021 
0022 static void bcm47xxsflash_cmd(struct bcm47xxsflash *b47s, u32 opcode)
0023 {
0024     int i;
0025 
0026     b47s->cc_write(b47s, BCMA_CC_FLASHCTL, BCMA_CC_FLASHCTL_START | opcode);
0027     for (i = 0; i < 1000; i++) {
0028         if (!(b47s->cc_read(b47s, BCMA_CC_FLASHCTL) &
0029               BCMA_CC_FLASHCTL_BUSY))
0030             return;
0031         cpu_relax();
0032     }
0033     pr_err("Control command failed (timeout)!\n");
0034 }
0035 
0036 static int bcm47xxsflash_poll(struct bcm47xxsflash *b47s, int timeout)
0037 {
0038     unsigned long deadline = jiffies + timeout;
0039 
0040     do {
0041         switch (b47s->type) {
0042         case BCM47XXSFLASH_TYPE_ST:
0043             bcm47xxsflash_cmd(b47s, OPCODE_ST_RDSR);
0044             if (!(b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
0045                   SR_ST_WIP))
0046                 return 0;
0047             break;
0048         case BCM47XXSFLASH_TYPE_ATMEL:
0049             bcm47xxsflash_cmd(b47s, OPCODE_AT_STATUS);
0050             if (b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
0051                 SR_AT_READY)
0052                 return 0;
0053             break;
0054         }
0055 
0056         cpu_relax();
0057         udelay(1);
0058     } while (!time_after_eq(jiffies, deadline));
0059 
0060     pr_err("Timeout waiting for flash to be ready!\n");
0061 
0062     return -EBUSY;
0063 }
0064 
0065 /**************************************************
0066  * MTD ops
0067  **************************************************/
0068 
0069 static int bcm47xxsflash_erase(struct mtd_info *mtd, struct erase_info *erase)
0070 {
0071     struct bcm47xxsflash *b47s = mtd->priv;
0072 
0073     switch (b47s->type) {
0074     case BCM47XXSFLASH_TYPE_ST:
0075         bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN);
0076         b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr);
0077         /* Newer flashes have "sub-sectors" which can be erased
0078          * independently with a new command: ST_SSE. The ST_SE command
0079          * erases 64KB just as before.
0080          */
0081         if (b47s->blocksize < (64 * 1024))
0082             bcm47xxsflash_cmd(b47s, OPCODE_ST_SSE);
0083         else
0084             bcm47xxsflash_cmd(b47s, OPCODE_ST_SE);
0085         break;
0086     case BCM47XXSFLASH_TYPE_ATMEL:
0087         b47s->cc_write(b47s, BCMA_CC_FLASHADDR, erase->addr << 1);
0088         bcm47xxsflash_cmd(b47s, OPCODE_AT_PAGE_ERASE);
0089         break;
0090     }
0091 
0092     return bcm47xxsflash_poll(b47s, HZ);
0093 }
0094 
0095 static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
0096                   size_t *retlen, u_char *buf)
0097 {
0098     struct bcm47xxsflash *b47s = mtd->priv;
0099     size_t orig_len = len;
0100 
0101     /* Check address range */
0102     if ((from + len) > mtd->size)
0103         return -EINVAL;
0104 
0105     /* Read as much as possible using fast MMIO window */
0106     if (from < BCM47XXSFLASH_WINDOW_SZ) {
0107         size_t memcpy_len;
0108 
0109         memcpy_len = min(len, (size_t)(BCM47XXSFLASH_WINDOW_SZ - from));
0110         memcpy_fromio(buf, b47s->window + from, memcpy_len);
0111         from += memcpy_len;
0112         len -= memcpy_len;
0113         buf += memcpy_len;
0114     }
0115 
0116     /* Use indirect access for content out of the window */
0117     for (; len; len--) {
0118         b47s->cc_write(b47s, BCMA_CC_FLASHADDR, from++);
0119         bcm47xxsflash_cmd(b47s, OPCODE_ST_READ4B);
0120         *buf++ = b47s->cc_read(b47s, BCMA_CC_FLASHDATA);
0121     }
0122 
0123     *retlen = orig_len;
0124 
0125     return orig_len;
0126 }
0127 
0128 static int bcm47xxsflash_write_st(struct mtd_info *mtd, u32 offset, size_t len,
0129                   const u_char *buf)
0130 {
0131     struct bcm47xxsflash *b47s = mtd->priv;
0132     int written = 0;
0133 
0134     /* Enable writes */
0135     bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN);
0136 
0137     /* Write first byte */
0138     b47s->cc_write(b47s, BCMA_CC_FLASHADDR, offset);
0139     b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++);
0140 
0141     /* Program page */
0142     if (b47s->bcma_cc->core->id.rev < 20) {
0143         bcm47xxsflash_cmd(b47s, OPCODE_ST_PP);
0144         return 1; /* 1B written */
0145     }
0146 
0147     /* Program page and set CSA (on newer chips we can continue writing) */
0148     bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | OPCODE_ST_PP);
0149     offset++;
0150     len--;
0151     written++;
0152 
0153     while (len > 0) {
0154         /* Page boundary, another function call is needed */
0155         if ((offset & 0xFF) == 0)
0156             break;
0157 
0158         bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | *buf++);
0159         offset++;
0160         len--;
0161         written++;
0162     }
0163 
0164     /* All done, drop CSA & poll */
0165     b47s->cc_write(b47s, BCMA_CC_FLASHCTL, 0);
0166     udelay(1);
0167     if (bcm47xxsflash_poll(b47s, HZ / 10))
0168         pr_err("Flash rejected dropping CSA\n");
0169 
0170     return written;
0171 }
0172 
0173 static int bcm47xxsflash_write_at(struct mtd_info *mtd, u32 offset, size_t len,
0174                   const u_char *buf)
0175 {
0176     struct bcm47xxsflash *b47s = mtd->priv;
0177     u32 mask = b47s->blocksize - 1;
0178     u32 page = (offset & ~mask) << 1;
0179     u32 byte = offset & mask;
0180     int written = 0;
0181 
0182     /* If we don't overwrite whole page, read it to the buffer first */
0183     if (byte || (len < b47s->blocksize)) {
0184         int err;
0185 
0186         b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page);
0187         bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_LOAD);
0188         /* 250 us for AT45DB321B */
0189         err = bcm47xxsflash_poll(b47s, HZ / 1000);
0190         if (err) {
0191             pr_err("Timeout reading page 0x%X info buffer\n", page);
0192             return err;
0193         }
0194     }
0195 
0196     /* Change buffer content with our data */
0197     while (len > 0) {
0198         /* Page boundary, another function call is needed */
0199         if (byte == b47s->blocksize)
0200             break;
0201 
0202         b47s->cc_write(b47s, BCMA_CC_FLASHADDR, byte++);
0203         b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++);
0204         bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_WRITE);
0205         len--;
0206         written++;
0207     }
0208 
0209     /* Program page with the buffer content */
0210     b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page);
0211     bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_PROGRAM);
0212 
0213     return written;
0214 }
0215 
0216 static int bcm47xxsflash_write(struct mtd_info *mtd, loff_t to, size_t len,
0217                    size_t *retlen, const u_char *buf)
0218 {
0219     struct bcm47xxsflash *b47s = mtd->priv;
0220     int written;
0221 
0222     /* Writing functions can return without writing all passed data, for
0223      * example when the hardware is too old or when we git page boundary.
0224      */
0225     while (len > 0) {
0226         switch (b47s->type) {
0227         case BCM47XXSFLASH_TYPE_ST:
0228             written = bcm47xxsflash_write_st(mtd, to, len, buf);
0229             break;
0230         case BCM47XXSFLASH_TYPE_ATMEL:
0231             written = bcm47xxsflash_write_at(mtd, to, len, buf);
0232             break;
0233         default:
0234             BUG_ON(1);
0235         }
0236         if (written < 0) {
0237             pr_err("Error writing at offset 0x%llX\n", to);
0238             return written;
0239         }
0240         to += (loff_t)written;
0241         len -= written;
0242         *retlen += written;
0243         buf += written;
0244     }
0245 
0246     return 0;
0247 }
0248 
0249 static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s,
0250                    struct device *dev)
0251 {
0252     struct mtd_info *mtd = &b47s->mtd;
0253 
0254     mtd->priv = b47s;
0255     mtd->dev.parent = dev;
0256     mtd->name = "bcm47xxsflash";
0257 
0258     mtd->type = MTD_NORFLASH;
0259     mtd->flags = MTD_CAP_NORFLASH;
0260     mtd->size = b47s->size;
0261     mtd->erasesize = b47s->blocksize;
0262     mtd->writesize = 1;
0263     mtd->writebufsize = 1;
0264 
0265     mtd->_erase = bcm47xxsflash_erase;
0266     mtd->_read = bcm47xxsflash_read;
0267     mtd->_write = bcm47xxsflash_write;
0268 }
0269 
0270 /**************************************************
0271  * BCMA
0272  **************************************************/
0273 
0274 static int bcm47xxsflash_bcma_cc_read(struct bcm47xxsflash *b47s, u16 offset)
0275 {
0276     return bcma_cc_read32(b47s->bcma_cc, offset);
0277 }
0278 
0279 static void bcm47xxsflash_bcma_cc_write(struct bcm47xxsflash *b47s, u16 offset,
0280                     u32 value)
0281 {
0282     bcma_cc_write32(b47s->bcma_cc, offset, value);
0283 }
0284 
0285 static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
0286 {
0287     struct device *dev = &pdev->dev;
0288     struct bcma_sflash *sflash = dev_get_platdata(dev);
0289     struct bcm47xxsflash *b47s;
0290     struct resource *res;
0291     int err;
0292 
0293     b47s = devm_kzalloc(dev, sizeof(*b47s), GFP_KERNEL);
0294     if (!b47s)
0295         return -ENOMEM;
0296 
0297     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0298     if (!res) {
0299         dev_err(dev, "invalid resource\n");
0300         return -EINVAL;
0301     }
0302     if (!devm_request_mem_region(dev, res->start, resource_size(res),
0303                      res->name)) {
0304         dev_err(dev, "can't request region for resource %pR\n", res);
0305         return -EBUSY;
0306     }
0307 
0308     b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash);
0309     b47s->cc_read = bcm47xxsflash_bcma_cc_read;
0310     b47s->cc_write = bcm47xxsflash_bcma_cc_write;
0311 
0312     /*
0313      * On old MIPS devices cache was magically invalidated when needed,
0314      * allowing us to use cached access and gain some performance. Trying
0315      * the same on ARM based BCM53573 results in flash corruptions, we need
0316      * to use uncached access for it.
0317      *
0318      * It may be arch specific, but right now there is only 1 ARM SoC using
0319      * this driver, so let's follow Broadcom's reference code and check
0320      * ChipCommon revision.
0321      */
0322     if (b47s->bcma_cc->core->id.rev == 54)
0323         b47s->window = ioremap(res->start, resource_size(res));
0324     else
0325         b47s->window = ioremap_cache(res->start, resource_size(res));
0326     if (!b47s->window) {
0327         dev_err(dev, "ioremap failed for resource %pR\n", res);
0328         return -ENOMEM;
0329     }
0330 
0331     switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) {
0332     case BCMA_CC_FLASHT_STSER:
0333         b47s->type = BCM47XXSFLASH_TYPE_ST;
0334         break;
0335     case BCMA_CC_FLASHT_ATSER:
0336         b47s->type = BCM47XXSFLASH_TYPE_ATMEL;
0337         break;
0338     }
0339 
0340     b47s->blocksize = sflash->blocksize;
0341     b47s->numblocks = sflash->numblocks;
0342     b47s->size = sflash->size;
0343     bcm47xxsflash_fill_mtd(b47s, &pdev->dev);
0344 
0345     platform_set_drvdata(pdev, b47s);
0346 
0347     err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0);
0348     if (err) {
0349         pr_err("Failed to register MTD device: %d\n", err);
0350         iounmap(b47s->window);
0351         return err;
0352     }
0353 
0354     if (bcm47xxsflash_poll(b47s, HZ / 10))
0355         pr_warn("Serial flash busy\n");
0356 
0357     return 0;
0358 }
0359 
0360 static int bcm47xxsflash_bcma_remove(struct platform_device *pdev)
0361 {
0362     struct bcm47xxsflash *b47s = platform_get_drvdata(pdev);
0363 
0364     mtd_device_unregister(&b47s->mtd);
0365     iounmap(b47s->window);
0366 
0367     return 0;
0368 }
0369 
0370 static struct platform_driver bcma_sflash_driver = {
0371     .probe  = bcm47xxsflash_bcma_probe,
0372     .remove = bcm47xxsflash_bcma_remove,
0373     .driver = {
0374         .name = "bcma_sflash",
0375     },
0376 };
0377 
0378 /**************************************************
0379  * Init
0380  **************************************************/
0381 
0382 module_platform_driver(bcma_sflash_driver);