2010-02-15 10:03:33 -08:00
/*
* gpmc - nand . c
*
* Copyright ( C ) 2009 Texas Instruments
* Vimal Singh < vimalsingh @ ti . 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 .
*/
# include <linux/kernel.h>
# include <linux/platform_device.h>
# include <linux/io.h>
2011-01-28 15:42:03 +05:30
# include <linux/mtd/nand.h>
2010-02-15 10:03:33 -08:00
# include <asm/mach/flash.h>
# include <plat/nand.h>
# include <plat/board.h>
# include <plat/gpmc.h>
static struct omap_nand_platform_data * gpmc_nand_data ;
static struct resource gpmc_nand_resource = {
. flags = IORESOURCE_MEM ,
} ;
static struct platform_device gpmc_nand_device = {
. name = " omap2-nand " ,
. id = 0 ,
. num_resources = 1 ,
. resource = & gpmc_nand_resource ,
} ;
static int omap2_nand_gpmc_retime ( void )
{
struct gpmc_timings t ;
int err ;
2010-04-20 06:33:30 +00:00
if ( ! gpmc_nand_data - > gpmc_t )
return 0 ;
2010-02-15 10:03:33 -08:00
memset ( & t , 0 , sizeof ( t ) ) ;
2010-12-09 10:48:27 +02:00
t . sync_clk = gpmc_nand_data - > gpmc_t - > sync_clk ;
2010-02-15 10:03:33 -08:00
t . cs_on = gpmc_round_ns_to_ticks ( gpmc_nand_data - > gpmc_t - > cs_on ) ;
t . adv_on = gpmc_round_ns_to_ticks ( gpmc_nand_data - > gpmc_t - > adv_on ) ;
/* Read */
t . adv_rd_off = gpmc_round_ns_to_ticks (
gpmc_nand_data - > gpmc_t - > adv_rd_off ) ;
t . oe_on = t . adv_on ;
t . access = gpmc_round_ns_to_ticks ( gpmc_nand_data - > gpmc_t - > access ) ;
t . oe_off = gpmc_round_ns_to_ticks ( gpmc_nand_data - > gpmc_t - > oe_off ) ;
t . cs_rd_off = gpmc_round_ns_to_ticks ( gpmc_nand_data - > gpmc_t - > cs_rd_off ) ;
t . rd_cycle = gpmc_round_ns_to_ticks ( gpmc_nand_data - > gpmc_t - > rd_cycle ) ;
/* Write */
t . adv_wr_off = gpmc_round_ns_to_ticks (
gpmc_nand_data - > gpmc_t - > adv_wr_off ) ;
t . we_on = t . oe_on ;
if ( cpu_is_omap34xx ( ) ) {
t . wr_data_mux_bus = gpmc_round_ns_to_ticks (
gpmc_nand_data - > gpmc_t - > wr_data_mux_bus ) ;
t . wr_access = gpmc_round_ns_to_ticks (
gpmc_nand_data - > gpmc_t - > wr_access ) ;
}
t . we_off = gpmc_round_ns_to_ticks ( gpmc_nand_data - > gpmc_t - > we_off ) ;
t . cs_wr_off = gpmc_round_ns_to_ticks ( gpmc_nand_data - > gpmc_t - > cs_wr_off ) ;
t . wr_cycle = gpmc_round_ns_to_ticks ( gpmc_nand_data - > gpmc_t - > wr_cycle ) ;
/* Configure GPMC */
2011-01-28 15:42:03 +05:30
if ( gpmc_nand_data - > devsize = = NAND_BUSWIDTH_16 )
gpmc_cs_configure ( gpmc_nand_data - > cs , GPMC_CONFIG_DEV_SIZE , 1 ) ;
else
gpmc_cs_configure ( gpmc_nand_data - > cs , GPMC_CONFIG_DEV_SIZE , 0 ) ;
2010-07-09 09:14:45 +00:00
gpmc_cs_configure ( gpmc_nand_data - > cs ,
GPMC_CONFIG_DEV_TYPE , GPMC_DEVICETYPE_NAND ) ;
2010-02-15 10:03:33 -08:00
err = gpmc_cs_set_timings ( gpmc_nand_data - > cs , & t ) ;
if ( err )
return err ;
return 0 ;
}
int __init gpmc_nand_init ( struct omap_nand_platform_data * _nand_data )
{
int err = 0 ;
struct device * dev = & gpmc_nand_device . dev ;
gpmc_nand_data = _nand_data ;
2010-07-09 09:14:45 +00:00
gpmc_nand_data - > nand_setup = omap2_nand_gpmc_retime ;
2010-02-15 10:03:33 -08:00
gpmc_nand_device . dev . platform_data = gpmc_nand_data ;
err = gpmc_cs_request ( gpmc_nand_data - > cs , NAND_IO_SIZE ,
& gpmc_nand_data - > phys_base ) ;
if ( err < 0 ) {
dev_err ( dev , " Cannot request GPMC CS \n " ) ;
return err ;
}
2010-07-09 09:14:45 +00:00
/* Set timings in GPMC */
err = omap2_nand_gpmc_retime ( ) ;
2010-02-15 10:03:33 -08:00
if ( err < 0 ) {
2010-07-09 09:14:45 +00:00
dev_err ( dev , " Unable to set gpmc timings: %d \n " , err ) ;
2010-02-15 10:03:33 -08:00
return err ;
}
/* Enable RD PIN Monitoring Reg */
if ( gpmc_nand_data - > dev_ready ) {
2010-07-09 09:14:45 +00:00
gpmc_cs_configure ( gpmc_nand_data - > cs , GPMC_CONFIG_RDY_BSY , 1 ) ;
2010-02-15 10:03:33 -08:00
}
err = platform_device_register ( & gpmc_nand_device ) ;
if ( err < 0 ) {
dev_err ( dev , " Unable to register NAND device \n " ) ;
goto out_free_cs ;
}
return 0 ;
out_free_cs :
gpmc_cs_free ( gpmc_nand_data - > cs ) ;
return err ;
}