2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2005-09-09 10:39:50 +04:00
/*
* Copyright ( c ) 2005 Samsung Electronics
* Kyungmin Park < kyungmin . park @ samsung . com >
*
* Overview :
* This is a device driver for the OneNAND flash for generic boards .
*/
# include <linux/module.h>
2006-01-08 12:02:05 +03:00
# include <linux/slab.h>
2005-12-16 05:17:29 +03:00
# include <linux/platform_device.h>
2005-09-09 10:39:50 +04:00
# include <linux/mtd/mtd.h>
# include <linux/mtd/onenand.h>
# include <linux/mtd/partitions.h>
2015-08-11 06:07:05 +03:00
# include <linux/io.h>
2005-09-09 10:39:50 +04:00
2009-09-18 23:51:44 +04:00
/*
* Note : Driver name and platform data format have been updated !
*
* This version of the driver is named " onenand-flash " and takes struct
* onenand_platform_data as platform data . The old ARM - specific version
* with the name " onenand " used to take struct flash_platform_data .
*/
# define DRIVER_NAME "onenand-flash"
2005-09-09 10:39:50 +04:00
struct onenand_info {
struct mtd_info mtd ;
struct onenand_chip onenand ;
} ;
2012-11-19 22:23:07 +04:00
static int generic_onenand_probe ( struct platform_device * pdev )
2005-09-09 10:39:50 +04:00
{
struct onenand_info * info ;
2013-07-30 12:18:53 +04:00
struct onenand_platform_data * pdata = dev_get_platdata ( & pdev - > dev ) ;
2005-09-09 10:39:50 +04:00
struct resource * res = pdev - > resource ;
2009-09-18 23:51:44 +04:00
unsigned long size = resource_size ( res ) ;
2005-09-09 10:39:50 +04:00
int err ;
2006-11-15 22:10:29 +03:00
info = kzalloc ( sizeof ( struct onenand_info ) , GFP_KERNEL ) ;
2005-09-09 10:39:50 +04:00
if ( ! info )
return - ENOMEM ;
2009-09-18 23:51:44 +04:00
if ( ! request_mem_region ( res - > start , size , dev_name ( & pdev - > dev ) ) ) {
2005-09-09 10:39:50 +04:00
err = - EBUSY ;
goto out_free_info ;
}
info - > onenand . base = ioremap ( res - > start , size ) ;
if ( ! info - > onenand . base ) {
err = - ENOMEM ;
goto out_release_mem_region ;
}
2013-09-20 23:44:26 +04:00
info - > onenand . mmcontrol = pdata ? pdata - > mmcontrol : NULL ;
2022-01-04 19:26:58 +03:00
err = platform_get_irq ( pdev , 0 ) ;
if ( err < 0 )
goto out_iounmap ;
info - > onenand . irq = err ;
2005-09-09 10:39:50 +04:00
2015-06-10 23:39:10 +03:00
info - > mtd . dev . parent = & pdev - > dev ;
2005-09-09 10:39:50 +04:00
info - > mtd . priv = & info - > onenand ;
if ( onenand_scan ( & info - > mtd , 1 ) ) {
err = - ENXIO ;
goto out_iounmap ;
}
2018-07-13 12:27:32 +03:00
err = mtd_device_register ( & info - > mtd , pdata ? pdata - > parts : NULL ,
pdata ? pdata - > nr_parts : 0 ) ;
2005-09-09 10:39:50 +04:00
2009-02-06 18:40:12 +03:00
platform_set_drvdata ( pdev , info ) ;
2005-09-09 10:39:50 +04:00
return 0 ;
out_iounmap :
iounmap ( info - > onenand . base ) ;
out_release_mem_region :
release_mem_region ( res - > start , size ) ;
out_free_info :
kfree ( info ) ;
return err ;
}
2023-04-11 14:38:16 +03:00
static void generic_onenand_remove ( struct platform_device * pdev )
2005-09-09 10:39:50 +04:00
{
2009-02-06 18:40:12 +03:00
struct onenand_info * info = platform_get_drvdata ( pdev ) ;
2005-09-09 10:39:50 +04:00
struct resource * res = pdev - > resource ;
2009-09-18 23:51:44 +04:00
unsigned long size = resource_size ( res ) ;
2005-09-09 10:39:50 +04:00
if ( info ) {
onenand_release ( & info - > mtd ) ;
release_mem_region ( res - > start , size ) ;
iounmap ( info - > onenand . base ) ;
kfree ( info ) ;
}
}
2009-02-06 18:40:12 +03:00
static struct platform_driver generic_onenand_driver = {
. driver = {
. name = DRIVER_NAME ,
} ,
2005-09-09 10:39:50 +04:00
. probe = generic_onenand_probe ,
2023-04-11 14:38:16 +03:00
. remove_new = generic_onenand_remove ,
2005-09-09 10:39:50 +04:00
} ;
2011-11-27 16:45:03 +04:00
module_platform_driver ( generic_onenand_driver ) ;
2005-09-09 10:39:50 +04:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Kyungmin Park <kyungmin.park@samsung.com> " ) ;
MODULE_DESCRIPTION ( " Glue layer for OneNAND flash on generic boards " ) ;
2011-11-27 16:45:03 +04:00
MODULE_ALIAS ( " platform: " DRIVER_NAME ) ;