2007-05-06 19:31:18 +04:00
/*
* Generic NAND driver
*
* Author : Vitaly Wool < vitalywool @ gmail . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
*/
2014-01-03 11:16:28 +09:00
# include <linux/err.h>
2007-05-06 19:31:18 +04:00
# include <linux/io.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/slab.h>
# include <linux/mtd/mtd.h>
# include <linux/mtd/nand.h>
# include <linux/mtd/partitions.h>
struct plat_nand_data {
struct nand_chip chip ;
struct mtd_info mtd ;
void __iomem * io_base ;
} ;
2012-03-28 11:13:05 -07:00
static const char * part_probe_types [ ] = { " cmdlinepart " , NULL } ;
2007-05-06 19:31:18 +04:00
/*
* Probe for the NAND device .
*/
2012-11-19 13:23:07 -05:00
static int plat_nand_probe ( struct platform_device * pdev )
2007-05-06 19:31:18 +04:00
{
2013-07-30 17:18:33 +09:00
struct platform_nand_data * pdata = dev_get_platdata ( & pdev - > dev ) ;
2012-04-30 19:30:46 +02:00
struct mtd_part_parser_data ppdata ;
2007-05-06 19:31:18 +04:00
struct plat_nand_data * data ;
2009-10-19 19:45:29 -04:00
struct resource * res ;
2012-03-28 11:13:05 -07:00
const char * * part_types ;
2009-10-19 19:45:29 -04:00
int err = 0 ;
2012-07-22 08:59:57 +02:00
if ( ! pdata ) {
dev_err ( & pdev - > dev , " platform_nand_data is missing \n " ) ;
return - EINVAL ;
}
2010-08-12 03:53:55 +01:00
if ( pdata - > chip . nr_chips < 1 ) {
dev_err ( & pdev - > dev , " invalid number of chips specified \n " ) ;
return - EINVAL ;
}
2007-05-06 19:31:18 +04:00
/* Allocate memory for the device structure (and zero it) */
2014-01-03 11:16:28 +09:00
data = devm_kzalloc ( & pdev - > dev , sizeof ( struct plat_nand_data ) ,
GFP_KERNEL ) ;
2014-01-03 11:17:29 +09:00
if ( ! data )
2007-05-06 19:31:18 +04:00
return - ENOMEM ;
2014-01-07 21:38:12 +08:00
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
2014-01-03 11:16:28 +09:00
data - > io_base = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( data - > io_base ) )
return PTR_ERR ( data - > io_base ) ;
2007-05-06 19:31:18 +04:00
data - > chip . priv = & data ;
data - > mtd . priv = & data - > chip ;
data - > mtd . owner = THIS_MODULE ;
2009-01-06 10:44:38 -08:00
data - > mtd . name = dev_name ( & pdev - > dev ) ;
2007-05-06 19:31:18 +04:00
data - > chip . IO_ADDR_R = data - > io_base ;
data - > chip . IO_ADDR_W = data - > io_base ;
data - > chip . cmd_ctrl = pdata - > ctrl . cmd_ctrl ;
data - > chip . dev_ready = pdata - > ctrl . dev_ready ;
data - > chip . select_chip = pdata - > ctrl . select_chip ;
2009-05-11 19:28:01 +01:00
data - > chip . write_buf = pdata - > ctrl . write_buf ;
data - > chip . read_buf = pdata - > ctrl . read_buf ;
2012-04-30 19:30:47 +02:00
data - > chip . read_byte = pdata - > ctrl . read_byte ;
2007-05-06 19:31:18 +04:00
data - > chip . chip_delay = pdata - > chip . chip_delay ;
data - > chip . options | = pdata - > chip . options ;
2011-05-31 16:31:22 -07:00
data - > chip . bbt_options | = pdata - > chip . bbt_options ;
2007-05-06 19:31:18 +04:00
data - > chip . ecc . hwctl = pdata - > ctrl . hwcontrol ;
data - > chip . ecc . layout = pdata - > chip . ecclayout ;
data - > chip . ecc . mode = NAND_ECC_SOFT ;
platform_set_drvdata ( pdev , data ) ;
2009-05-12 13:46:58 -07:00
/* Handle any platform specific setup */
if ( pdata - > ctrl . probe ) {
2009-10-19 19:45:29 -04:00
err = pdata - > ctrl . probe ( pdev ) ;
if ( err )
2009-05-12 13:46:58 -07:00
goto out ;
}
2011-03-30 22:57:33 -03:00
/* Scan to find existence of the device */
2010-07-28 07:36:54 +02:00
if ( nand_scan ( & data - > mtd , pdata - > chip . nr_chips ) ) {
2009-10-19 19:45:29 -04:00
err = - ENXIO ;
2007-05-06 19:31:18 +04:00
goto out ;
}
2012-03-28 11:13:05 -07:00
part_types = pdata - > chip . part_probe_types ? : part_probe_types ;
2012-04-30 19:30:46 +02:00
ppdata . of_node = pdev - > dev . of_node ;
err = mtd_device_parse_register ( & data - > mtd , part_types , & ppdata ,
mtd: do not use plain 0 as NULL
The first 3 arguments of 'mtd_device_parse_register()' are pointers,
but many callers pass '0' instead of 'NULL'. Fix this globally. Thanks
to coccinelle for making it easy to do with the following semantic patch:
@@
expression mtd, types, parser_data, parts, nr_parts;
@@
(
-mtd_device_parse_register(mtd, 0, parser_data, parts, nr_parts)
+mtd_device_parse_register(mtd, NULL, parser_data, parts, nr_parts)
|
-mtd_device_parse_register(mtd, types, 0, parts, nr_parts)
+mtd_device_parse_register(mtd, types, NULL, parts, nr_parts)
|
-mtd_device_parse_register(mtd, types, parser_data, 0, nr_parts)
+mtd_device_parse_register(mtd, types, parser_data, NULL, nr_parts)
)
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
2012-03-09 19:24:26 +02:00
pdata - > chip . partitions ,
pdata - > chip . nr_partitions ) ;
2007-05-06 19:31:18 +04:00
2009-10-19 19:45:29 -04:00
if ( ! err )
return err ;
2007-05-06 19:31:18 +04:00
nand_release ( & data - > mtd ) ;
out :
2009-05-12 13:46:58 -07:00
if ( pdata - > ctrl . remove )
pdata - > ctrl . remove ( pdev ) ;
2009-10-19 19:45:29 -04:00
return err ;
2007-05-06 19:31:18 +04:00
}
/*
* Remove a NAND device .
*/
2012-11-19 13:26:04 -05:00
static int plat_nand_remove ( struct platform_device * pdev )
2007-05-06 19:31:18 +04:00
{
struct plat_nand_data * data = platform_get_drvdata ( pdev ) ;
2013-07-30 17:18:33 +09:00
struct platform_nand_data * pdata = dev_get_platdata ( & pdev - > dev ) ;
2007-05-06 19:31:18 +04:00
nand_release ( & data - > mtd ) ;
2009-05-12 13:46:58 -07:00
if ( pdata - > ctrl . remove )
pdata - > ctrl . remove ( pdev ) ;
2007-05-06 19:31:18 +04:00
return 0 ;
}
2012-04-30 19:30:46 +02:00
static const struct of_device_id plat_nand_match [ ] = {
{ . compatible = " gen_nand " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , plat_nand_match ) ;
2007-05-06 19:31:18 +04:00
static struct platform_driver plat_nand_driver = {
2012-04-30 19:30:46 +02:00
. probe = plat_nand_probe ,
2012-11-19 13:21:24 -05:00
. remove = plat_nand_remove ,
2012-04-30 19:30:46 +02:00
. driver = {
. name = " gen_nand " ,
. owner = THIS_MODULE ,
. of_match_table = plat_nand_match ,
2007-05-06 19:31:18 +04:00
} ,
} ;
2011-11-27 20:45:03 +08:00
module_platform_driver ( plat_nand_driver ) ;
2007-05-06 19:31:18 +04:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Vitaly Wool " ) ;
MODULE_DESCRIPTION ( " Simple generic NAND driver " ) ;
2008-04-18 13:44:27 -07:00
MODULE_ALIAS ( " platform:gen_nand " ) ;