xref: /openbmc/linux/drivers/mtd/devices/bcm47xxsflash.c (revision f1a7c9d350339e8a81cda9469ba9a591fb9c9a3b)
15fe42d5bSRafał Miłecki #include <linux/kernel.h>
25fe42d5bSRafał Miłecki #include <linux/module.h>
35fe42d5bSRafał Miłecki #include <linux/slab.h>
45fe42d5bSRafał Miłecki #include <linux/mtd/mtd.h>
55fe42d5bSRafał Miłecki #include <linux/platform_device.h>
65fe42d5bSRafał Miłecki #include <linux/bcma/bcma.h>
75fe42d5bSRafał Miłecki 
8a2f74a7dSRafał Miłecki #include "bcm47xxsflash.h"
9a2f74a7dSRafał Miłecki 
105fe42d5bSRafał Miłecki MODULE_LICENSE("GPL");
115fe42d5bSRafał Miłecki MODULE_DESCRIPTION("Serial flash driver for BCMA bus");
125fe42d5bSRafał Miłecki 
135fe42d5bSRafał Miłecki static const char *probes[] = { "bcm47xxpart", NULL };
145fe42d5bSRafał Miłecki 
155fe42d5bSRafał Miłecki static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
165fe42d5bSRafał Miłecki 			      size_t *retlen, u_char *buf)
175fe42d5bSRafał Miłecki {
18a2f74a7dSRafał Miłecki 	struct bcm47xxsflash *b47s = mtd->priv;
195fe42d5bSRafał Miłecki 
205fe42d5bSRafał Miłecki 	/* Check address range */
215fe42d5bSRafał Miłecki 	if ((from + len) > mtd->size)
225fe42d5bSRafał Miłecki 		return -EINVAL;
235fe42d5bSRafał Miłecki 
24a2f74a7dSRafał Miłecki 	memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(b47s->window + from),
255fe42d5bSRafał Miłecki 		      len);
2660aca067SHauke Mehrtens 	*retlen = len;
275fe42d5bSRafał Miłecki 
285fe42d5bSRafał Miłecki 	return len;
295fe42d5bSRafał Miłecki }
305fe42d5bSRafał Miłecki 
31a2f74a7dSRafał Miłecki static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s)
325fe42d5bSRafał Miłecki {
33a2f74a7dSRafał Miłecki 	struct mtd_info *mtd = &b47s->mtd;
34a2f74a7dSRafał Miłecki 
35a2f74a7dSRafał Miłecki 	mtd->priv = b47s;
365fe42d5bSRafał Miłecki 	mtd->name = "bcm47xxsflash";
375fe42d5bSRafał Miłecki 	mtd->owner = THIS_MODULE;
385fe42d5bSRafał Miłecki 	mtd->type = MTD_ROM;
39a2f74a7dSRafał Miłecki 	mtd->size = b47s->size;
405fe42d5bSRafał Miłecki 	mtd->_read = bcm47xxsflash_read;
415fe42d5bSRafał Miłecki 
425fe42d5bSRafał Miłecki 	/* TODO: implement writing support and verify/change following code */
435fe42d5bSRafał Miłecki 	mtd->flags = MTD_CAP_ROM;
445fe42d5bSRafał Miłecki 	mtd->writebufsize = mtd->writesize = 1;
455fe42d5bSRafał Miłecki }
465fe42d5bSRafał Miłecki 
47*f1a7c9d3SRafał Miłecki /**************************************************
48*f1a7c9d3SRafał Miłecki  * BCMA
49*f1a7c9d3SRafał Miłecki  **************************************************/
50*f1a7c9d3SRafał Miłecki 
51*f1a7c9d3SRafał Miłecki static int bcm47xxsflash_bcma_probe(struct platform_device *pdev)
525fe42d5bSRafał Miłecki {
535fe42d5bSRafał Miłecki 	struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
54a2f74a7dSRafał Miłecki 	struct bcm47xxsflash *b47s;
555fe42d5bSRafał Miłecki 	int err;
565fe42d5bSRafał Miłecki 
57a2f74a7dSRafał Miłecki 	b47s = kzalloc(sizeof(*b47s), GFP_KERNEL);
58a2f74a7dSRafał Miłecki 	if (!b47s) {
595fe42d5bSRafał Miłecki 		err = -ENOMEM;
605fe42d5bSRafał Miłecki 		goto out;
615fe42d5bSRafał Miłecki 	}
62a2f74a7dSRafał Miłecki 	sflash->priv = b47s;
635fe42d5bSRafał Miłecki 
64a2f74a7dSRafał Miłecki 	b47s->window = sflash->window;
65a2f74a7dSRafał Miłecki 	b47s->blocksize = sflash->blocksize;
66a2f74a7dSRafał Miłecki 	b47s->numblocks = sflash->numblocks;
67a2f74a7dSRafał Miłecki 	b47s->size = sflash->size;
68a2f74a7dSRafał Miłecki 	bcm47xxsflash_fill_mtd(b47s);
69a2f74a7dSRafał Miłecki 
70a2f74a7dSRafał Miłecki 	err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0);
715fe42d5bSRafał Miłecki 	if (err) {
725fe42d5bSRafał Miłecki 		pr_err("Failed to register MTD device: %d\n", err);
735fe42d5bSRafał Miłecki 		goto err_dev_reg;
745fe42d5bSRafał Miłecki 	}
755fe42d5bSRafał Miłecki 
765fe42d5bSRafał Miłecki 	return 0;
775fe42d5bSRafał Miłecki 
785fe42d5bSRafał Miłecki err_dev_reg:
79a2f74a7dSRafał Miłecki 	kfree(&b47s->mtd);
805fe42d5bSRafał Miłecki out:
815fe42d5bSRafał Miłecki 	return err;
825fe42d5bSRafał Miłecki }
835fe42d5bSRafał Miłecki 
84*f1a7c9d3SRafał Miłecki static int bcm47xxsflash_bcma_remove(struct platform_device *pdev)
855fe42d5bSRafał Miłecki {
865fe42d5bSRafał Miłecki 	struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
87a2f74a7dSRafał Miłecki 	struct bcm47xxsflash *b47s = sflash->priv;
885fe42d5bSRafał Miłecki 
89a2f74a7dSRafał Miłecki 	mtd_device_unregister(&b47s->mtd);
90a2f74a7dSRafał Miłecki 	kfree(b47s);
915fe42d5bSRafał Miłecki 
925fe42d5bSRafał Miłecki 	return 0;
935fe42d5bSRafał Miłecki }
945fe42d5bSRafał Miłecki 
955fe42d5bSRafał Miłecki static struct platform_driver bcma_sflash_driver = {
96*f1a7c9d3SRafał Miłecki 	.probe	= bcm47xxsflash_bcma_probe,
97*f1a7c9d3SRafał Miłecki 	.remove = bcm47xxsflash_bcma_remove,
985fe42d5bSRafał Miłecki 	.driver = {
995fe42d5bSRafał Miłecki 		.name = "bcma_sflash",
1005fe42d5bSRafał Miłecki 		.owner = THIS_MODULE,
1015fe42d5bSRafał Miłecki 	},
1025fe42d5bSRafał Miłecki };
1035fe42d5bSRafał Miłecki 
104*f1a7c9d3SRafał Miłecki /**************************************************
105*f1a7c9d3SRafał Miłecki  * Init
106*f1a7c9d3SRafał Miłecki  **************************************************/
107*f1a7c9d3SRafał Miłecki 
1085fe42d5bSRafał Miłecki static int __init bcm47xxsflash_init(void)
1095fe42d5bSRafał Miłecki {
1105fe42d5bSRafał Miłecki 	int err;
1115fe42d5bSRafał Miłecki 
1122d13dc3bSHauke Mehrtens 	err = platform_driver_register(&bcma_sflash_driver);
1135fe42d5bSRafał Miłecki 	if (err)
1145fe42d5bSRafał Miłecki 		pr_err("Failed to register BCMA serial flash driver: %d\n",
1155fe42d5bSRafał Miłecki 		       err);
1165fe42d5bSRafał Miłecki 
1175fe42d5bSRafał Miłecki 	return err;
1185fe42d5bSRafał Miłecki }
1195fe42d5bSRafał Miłecki 
1205fe42d5bSRafał Miłecki static void __exit bcm47xxsflash_exit(void)
1215fe42d5bSRafał Miłecki {
1225fe42d5bSRafał Miłecki 	platform_driver_unregister(&bcma_sflash_driver);
1235fe42d5bSRafał Miłecki }
1245fe42d5bSRafał Miłecki 
1255fe42d5bSRafał Miłecki module_init(bcm47xxsflash_init);
1265fe42d5bSRafał Miłecki module_exit(bcm47xxsflash_exit);
127