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