linux/drivers/mtd/devices/bcm47xxsflash.c
<<
>>
Prefs
   1#include <linux/kernel.h>
   2#include <linux/module.h>
   3#include <linux/slab.h>
   4#include <linux/mtd/mtd.h>
   5#include <linux/platform_device.h>
   6#include <linux/bcma/bcma.h>
   7
   8#include "bcm47xxsflash.h"
   9
  10MODULE_LICENSE("GPL");
  11MODULE_DESCRIPTION("Serial flash driver for BCMA bus");
  12
  13static const char * const probes[] = { "bcm47xxpart", NULL };
  14
  15static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
  16                              size_t *retlen, u_char *buf)
  17{
  18        struct bcm47xxsflash *b47s = mtd->priv;
  19
  20        /* Check address range */
  21        if ((from + len) > mtd->size)
  22                return -EINVAL;
  23
  24        memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(b47s->window + from),
  25                      len);
  26        *retlen = len;
  27
  28        return len;
  29}
  30
  31static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s)
  32{
  33        struct mtd_info *mtd = &b47s->mtd;
  34
  35        mtd->priv = b47s;
  36        mtd->name = "bcm47xxsflash";
  37        mtd->owner = THIS_MODULE;
  38        mtd->type = MTD_ROM;
  39        mtd->size = b47s->size;
  40        mtd->_read = bcm47xxsflash_read;
  41
  42        /* TODO: implement writing support and verify/change following code */
  43        mtd->flags = MTD_CAP_ROM;
  44        mtd->writebufsize = mtd->writesize = 1;
  45}
  46
  47/**************************************************
  48 * BCMA
  49 **************************************************/
  50
  51static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
  52{
  53        struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
  54        struct bcm47xxsflash *b47s;
  55        int err;
  56
  57        b47s = kzalloc(sizeof(*b47s), GFP_KERNEL);
  58        if (!b47s) {
  59                err = -ENOMEM;
  60                goto out;
  61        }
  62        sflash->priv = b47s;
  63
  64        b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash);
  65
  66        switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) {
  67        case BCMA_CC_FLASHT_STSER:
  68                b47s->type = BCM47XXSFLASH_TYPE_ST;
  69                break;
  70        case BCMA_CC_FLASHT_ATSER:
  71                b47s->type = BCM47XXSFLASH_TYPE_ATMEL;
  72                break;
  73        }
  74
  75        b47s->window = sflash->window;
  76        b47s->blocksize = sflash->blocksize;
  77        b47s->numblocks = sflash->numblocks;
  78        b47s->size = sflash->size;
  79        bcm47xxsflash_fill_mtd(b47s);
  80
  81        err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0);
  82        if (err) {
  83                pr_err("Failed to register MTD device: %d\n", err);
  84                goto err_dev_reg;
  85        }
  86
  87        return 0;
  88
  89err_dev_reg:
  90        kfree(&b47s->mtd);
  91out:
  92        return err;
  93}
  94
  95static int bcm47xxsflash_bcma_remove(struct platform_device *pdev)
  96{
  97        struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
  98        struct bcm47xxsflash *b47s = sflash->priv;
  99
 100        mtd_device_unregister(&b47s->mtd);
 101        kfree(b47s);
 102
 103        return 0;
 104}
 105
 106static struct platform_driver bcma_sflash_driver = {
 107        .probe  = bcm47xxsflash_bcma_probe,
 108        .remove = bcm47xxsflash_bcma_remove,
 109        .driver = {
 110                .name = "bcma_sflash",
 111                .owner = THIS_MODULE,
 112        },
 113};
 114
 115/**************************************************
 116 * Init
 117 **************************************************/
 118
 119static int __init bcm47xxsflash_init(void)
 120{
 121        int err;
 122
 123        err = platform_driver_register(&bcma_sflash_driver);
 124        if (err)
 125                pr_err("Failed to register BCMA serial flash driver: %d\n",
 126                       err);
 127
 128        return err;
 129}
 130
 131static void __exit bcm47xxsflash_exit(void)
 132{
 133        platform_driver_unregister(&bcma_sflash_driver);
 134}
 135
 136module_init(bcm47xxsflash_init);
 137module_exit(bcm47xxsflash_exit);
 138