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/slab.h> 17#include <linux/platform_device.h> 18#include <linux/mtd/mtd.h> 19#include <linux/mtd/onenand.h> 20#include <linux/mtd/partitions.h> 21#include <asm/io.h> 22 23/* 24 * Note: Driver name and platform data format have been updated! 25 * 26 * This version of the driver is named "onenand-flash" and takes struct 27 * onenand_platform_data as platform data. The old ARM-specific version 28 * with the name "onenand" used to take struct flash_platform_data. 29 */ 30#define DRIVER_NAME "onenand-flash" 31 32struct onenand_info { 33 struct mtd_info mtd; 34 struct onenand_chip onenand; 35}; 36 37static int generic_onenand_probe(struct platform_device *pdev) 38{ 39 struct onenand_info *info; 40 struct onenand_platform_data *pdata = dev_get_platdata(&pdev->dev); 41 struct resource *res = pdev->resource; 42 unsigned long size = resource_size(res); 43 int err; 44 45 info = kzalloc(sizeof(struct onenand_info), GFP_KERNEL); 46 if (!info) 47 return -ENOMEM; 48 49 if (!request_mem_region(res->start, size, dev_name(&pdev->dev))) { 50 err = -EBUSY; 51 goto out_free_info; 52 } 53 54 info->onenand.base = ioremap(res->start, size); 55 if (!info->onenand.base) { 56 err = -ENOMEM; 57 goto out_release_mem_region; 58 } 59 60 info->onenand.mmcontrol = pdata ? pdata->mmcontrol : NULL; 61 info->onenand.irq = platform_get_irq(pdev, 0); 62 63 info->mtd.name = dev_name(&pdev->dev); 64 info->mtd.priv = &info->onenand; 65 info->mtd.owner = THIS_MODULE; 66 67 if (onenand_scan(&info->mtd, 1)) { 68 err = -ENXIO; 69 goto out_iounmap; 70 } 71 72 err = mtd_device_parse_register(&info->mtd, NULL, NULL, 73 pdata ? pdata->parts : NULL, 74 pdata ? pdata->nr_parts : 0); 75 76 platform_set_drvdata(pdev, info); 77 78 return 0; 79 80out_iounmap: 81 iounmap(info->onenand.base); 82out_release_mem_region: 83 release_mem_region(res->start, size); 84out_free_info: 85 kfree(info); 86 87 return err; 88} 89 90static int generic_onenand_remove(struct platform_device *pdev) 91{ 92 struct onenand_info *info = platform_get_drvdata(pdev); 93 struct resource *res = pdev->resource; 94 unsigned long size = resource_size(res); 95 96 if (info) { 97 onenand_release(&info->mtd); 98 release_mem_region(res->start, size); 99 iounmap(info->onenand.base); 100 kfree(info); 101 } 102 103 return 0; 104} 105 106static struct platform_driver generic_onenand_driver = { 107 .driver = { 108 .name = DRIVER_NAME, 109 }, 110 .probe = generic_onenand_probe, 111 .remove = generic_onenand_remove, 112}; 113 114module_platform_driver(generic_onenand_driver); 115 116MODULE_LICENSE("GPL"); 117MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); 118MODULE_DESCRIPTION("Glue layer for OneNAND flash on generic boards"); 119MODULE_ALIAS("platform:" DRIVER_NAME); 120