Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *  linux/drivers/mtd/onenand/generic.c
  3  *
  4  *  Copyright (c) 2005 Samsung Electronics
  5  *  Kyungmin Park <kyungmin.park@samsung.com>
  6  *
  7  * This program is free software; you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License version 2 as
  9  * published by the Free Software Foundation.
 10  *
 11  *  Overview:
 12  *   This is a device driver for the OneNAND flash for generic boards.
 13  */
 14 
 15 #include <linux/module.h>
 16 #include <linux/init.h>
 17 #include <linux/slab.h>
 18 #include <linux/platform_device.h>
 19 #include <linux/mtd/mtd.h>
 20 #include <linux/mtd/onenand.h>
 21 #include <linux/mtd/partitions.h>
 22 
 23 #include <asm/io.h>
 24 #include <asm/mach/flash.h>
 25 
 26 #define DRIVER_NAME     "onenand"
 27 
 28 
 29 #ifdef CONFIG_MTD_PARTITIONS
 30 static const char *part_probes[] = { "cmdlinepart", NULL,  };
 31 #endif
 32 
 33 struct onenand_info {
 34         struct mtd_info         mtd;
 35         struct mtd_partition    *parts;
 36         struct onenand_chip     onenand;
 37 };
 38 
 39 static int __devinit generic_onenand_probe(struct platform_device *pdev)
 40 {
 41         struct onenand_info *info;
 42         struct flash_platform_data *pdata = pdev->dev.platform_data;
 43         struct resource *res = pdev->resource;
 44         unsigned long size = res->end - res->start + 1;
 45         int err;
 46 
 47         info = kzalloc(sizeof(struct onenand_info), GFP_KERNEL);
 48         if (!info)
 49                 return -ENOMEM;
 50 
 51         if (!request_mem_region(res->start, size, pdev->dev.driver->name)) {
 52                 err = -EBUSY;
 53                 goto out_free_info;
 54         }
 55 
 56         info->onenand.base = ioremap(res->start, size);
 57         if (!info->onenand.base) {
 58                 err = -ENOMEM;
 59                 goto out_release_mem_region;
 60         }
 61 
 62         info->onenand.mmcontrol = pdata->mmcontrol;
 63         info->onenand.irq = platform_get_irq(pdev, 0);
 64 
 65         info->mtd.name = dev_name(&pdev->dev);
 66         info->mtd.priv = &info->onenand;
 67         info->mtd.owner = THIS_MODULE;
 68 
 69         if (onenand_scan(&info->mtd, 1)) {
 70                 err = -ENXIO;
 71                 goto out_iounmap;
 72         }
 73 
 74 #ifdef CONFIG_MTD_PARTITIONS
 75         err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
 76         if (err > 0)
 77                 add_mtd_partitions(&info->mtd, info->parts, err);
 78         else if (err <= 0 && pdata->parts)
 79                 add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
 80         else
 81 #endif
 82                 err = add_mtd_device(&info->mtd);
 83 
 84         platform_set_drvdata(pdev, info);
 85 
 86         return 0;
 87 
 88 out_iounmap:
 89         iounmap(info->onenand.base);
 90 out_release_mem_region:
 91         release_mem_region(res->start, size);
 92 out_free_info:
 93         kfree(info);
 94 
 95         return err;
 96 }
 97 
 98 static int __devexit generic_onenand_remove(struct platform_device *pdev)
 99 {
100         struct onenand_info *info = platform_get_drvdata(pdev);
101         struct resource *res = pdev->resource;
102         unsigned long size = res->end - res->start + 1;
103 
104         platform_set_drvdata(pdev, NULL);
105 
106         if (info) {
107                 if (info->parts)
108                         del_mtd_partitions(&info->mtd);
109                 else
110                         del_mtd_device(&info->mtd);
111 
112                 onenand_release(&info->mtd);
113                 release_mem_region(res->start, size);
114                 iounmap(info->onenand.base);
115                 kfree(info);
116         }
117 
118         return 0;
119 }
120 
121 static struct platform_driver generic_onenand_driver = {
122         .driver = {
123                 .name           = DRIVER_NAME,
124                 .owner          = THIS_MODULE,
125         },
126         .probe          = generic_onenand_probe,
127         .remove         = __devexit_p(generic_onenand_remove),
128 };
129 
130 MODULE_ALIAS(DRIVER_NAME);
131 
132 static int __init generic_onenand_init(void)
133 {
134         return platform_driver_register(&generic_onenand_driver);
135 }
136 
137 static void __exit generic_onenand_exit(void)
138 {
139         platform_driver_unregister(&generic_onenand_driver);
140 }
141 
142 module_init(generic_onenand_init);
143 module_exit(generic_onenand_exit);
144 
145 MODULE_LICENSE("GPL");
146 MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>");
147 MODULE_DESCRIPTION("Glue layer for OneNAND flash on generic boards");
148 
  This page was automatically generated by the LXR engine.