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 MODULE_LICENSE("GPL"); 9 MODULE_DESCRIPTION("Serial flash driver for BCMA bus"); 10 11 static const char *probes[] = { "bcm47xxpart", NULL }; 12 13 static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len, 14 size_t *retlen, u_char *buf) 15 { 16 struct bcma_sflash *sflash = mtd->priv; 17 18 /* Check address range */ 19 if ((from + len) > mtd->size) 20 return -EINVAL; 21 22 memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(sflash->window + from), 23 len); 24 25 return len; 26 } 27 28 static void bcm47xxsflash_fill_mtd(struct bcma_sflash *sflash, 29 struct mtd_info *mtd) 30 { 31 mtd->priv = sflash; 32 mtd->name = "bcm47xxsflash"; 33 mtd->owner = THIS_MODULE; 34 mtd->type = MTD_ROM; 35 mtd->size = sflash->size; 36 mtd->_read = bcm47xxsflash_read; 37 38 /* TODO: implement writing support and verify/change following code */ 39 mtd->flags = MTD_CAP_ROM; 40 mtd->writebufsize = mtd->writesize = 1; 41 } 42 43 static int bcm47xxsflash_probe(struct platform_device *pdev) 44 { 45 struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); 46 int err; 47 48 sflash->mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); 49 if (!sflash->mtd) { 50 err = -ENOMEM; 51 goto out; 52 } 53 bcm47xxsflash_fill_mtd(sflash, sflash->mtd); 54 55 err = mtd_device_parse_register(sflash->mtd, probes, NULL, NULL, 0); 56 if (err) { 57 pr_err("Failed to register MTD device: %d\n", err); 58 goto err_dev_reg; 59 } 60 61 return 0; 62 63 err_dev_reg: 64 kfree(sflash->mtd); 65 out: 66 return err; 67 } 68 69 static int bcm47xxsflash_remove(struct platform_device *pdev) 70 { 71 struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); 72 73 mtd_device_unregister(sflash->mtd); 74 kfree(sflash->mtd); 75 76 return 0; 77 } 78 79 static struct platform_driver bcma_sflash_driver = { 80 .remove = bcm47xxsflash_remove, 81 .driver = { 82 .name = "bcma_sflash", 83 .owner = THIS_MODULE, 84 }, 85 }; 86 87 static int __init bcm47xxsflash_init(void) 88 { 89 int err; 90 91 err = platform_driver_probe(&bcma_sflash_driver, bcm47xxsflash_probe); 92 if (err) 93 pr_err("Failed to register BCMA serial flash driver: %d\n", 94 err); 95 96 return err; 97 } 98 99 static void __exit bcm47xxsflash_exit(void) 100 { 101 platform_driver_unregister(&bcma_sflash_driver); 102 } 103 104 module_init(bcm47xxsflash_init); 105 module_exit(bcm47xxsflash_exit); 106