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