0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/slab.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/mtd/mtd.h>
0014 #include <linux/mtd/onenand.h>
0015 #include <linux/mtd/partitions.h>
0016 #include <linux/io.h>
0017
0018
0019
0020
0021
0022
0023
0024
0025 #define DRIVER_NAME "onenand-flash"
0026
0027 struct onenand_info {
0028 struct mtd_info mtd;
0029 struct onenand_chip onenand;
0030 };
0031
0032 static int generic_onenand_probe(struct platform_device *pdev)
0033 {
0034 struct onenand_info *info;
0035 struct onenand_platform_data *pdata = dev_get_platdata(&pdev->dev);
0036 struct resource *res = pdev->resource;
0037 unsigned long size = resource_size(res);
0038 int err;
0039
0040 info = kzalloc(sizeof(struct onenand_info), GFP_KERNEL);
0041 if (!info)
0042 return -ENOMEM;
0043
0044 if (!request_mem_region(res->start, size, dev_name(&pdev->dev))) {
0045 err = -EBUSY;
0046 goto out_free_info;
0047 }
0048
0049 info->onenand.base = ioremap(res->start, size);
0050 if (!info->onenand.base) {
0051 err = -ENOMEM;
0052 goto out_release_mem_region;
0053 }
0054
0055 info->onenand.mmcontrol = pdata ? pdata->mmcontrol : NULL;
0056
0057 err = platform_get_irq(pdev, 0);
0058 if (err < 0)
0059 goto out_iounmap;
0060
0061 info->onenand.irq = err;
0062
0063 info->mtd.dev.parent = &pdev->dev;
0064 info->mtd.priv = &info->onenand;
0065
0066 if (onenand_scan(&info->mtd, 1)) {
0067 err = -ENXIO;
0068 goto out_iounmap;
0069 }
0070
0071 err = mtd_device_register(&info->mtd, pdata ? pdata->parts : NULL,
0072 pdata ? pdata->nr_parts : 0);
0073
0074 platform_set_drvdata(pdev, info);
0075
0076 return 0;
0077
0078 out_iounmap:
0079 iounmap(info->onenand.base);
0080 out_release_mem_region:
0081 release_mem_region(res->start, size);
0082 out_free_info:
0083 kfree(info);
0084
0085 return err;
0086 }
0087
0088 static int generic_onenand_remove(struct platform_device *pdev)
0089 {
0090 struct onenand_info *info = platform_get_drvdata(pdev);
0091 struct resource *res = pdev->resource;
0092 unsigned long size = resource_size(res);
0093
0094 if (info) {
0095 onenand_release(&info->mtd);
0096 release_mem_region(res->start, size);
0097 iounmap(info->onenand.base);
0098 kfree(info);
0099 }
0100
0101 return 0;
0102 }
0103
0104 static struct platform_driver generic_onenand_driver = {
0105 .driver = {
0106 .name = DRIVER_NAME,
0107 },
0108 .probe = generic_onenand_probe,
0109 .remove = generic_onenand_remove,
0110 };
0111
0112 module_platform_driver(generic_onenand_driver);
0113
0114 MODULE_LICENSE("GPL");
0115 MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
0116 MODULE_DESCRIPTION("Glue layer for OneNAND flash on generic boards");
0117 MODULE_ALIAS("platform:" DRIVER_NAME);