2010-02-15 21:03:33 +03:00
/*
2011-02-15 13:57:31 +03:00
* board - flash . c
2010-02-15 21:03:33 +03:00
* Modified from mach - omap2 / board - 3430 sdp - flash . c
*
* Copyright ( C ) 2009 Nokia Corporation
* 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/mtd/physmap.h>
# include <linux/io.h>
2012-08-28 04:43:01 +04:00
# include <plat/cpu.h>
2010-02-15 21:03:33 +03:00
# include <plat/gpmc.h>
# include <plat/nand.h>
# include <plat/onenand.h>
# include <plat/tc.h>
2010-10-08 20:58:35 +04:00
# include "board-flash.h"
2010-02-15 21:03:33 +03:00
# define REG_FPGA_REV 0x10
# define REG_FPGA_DIP_SWITCH_INPUT2 0x60
# define MAX_SUPPORTED_GPMC_CONFIG 3
# define DEBUG_BASE 0x08000000 /* debug board */
/* various memory sizes */
# define FLASH_SIZE_SDPV1 SZ_64M /* NOR flash (64 Meg aligned) */
# define FLASH_SIZE_SDPV2 SZ_128M /* NOR flash (256 Meg aligned) */
2010-07-09 18:27:47 +04:00
static struct physmap_flash_data board_nor_data = {
2010-02-15 21:03:33 +03:00
. width = 2 ,
} ;
2010-07-09 18:27:47 +04:00
static struct resource board_nor_resource = {
2010-02-15 21:03:33 +03:00
. flags = IORESOURCE_MEM ,
} ;
2010-07-09 18:27:47 +04:00
static struct platform_device board_nor_device = {
2010-02-15 21:03:33 +03:00
. name = " physmap-flash " ,
. id = 0 ,
. dev = {
2010-07-09 18:27:47 +04:00
. platform_data = & board_nor_data ,
2010-02-15 21:03:33 +03:00
} ,
. num_resources = 1 ,
2010-07-09 18:27:47 +04:00
. resource = & board_nor_resource ,
2010-02-15 21:03:33 +03:00
} ;
static void
2010-07-09 18:27:47 +04:00
__init board_nor_init ( struct mtd_partition * nor_parts , u8 nr_parts , u8 cs )
2010-02-15 21:03:33 +03:00
{
int err ;
2010-07-09 18:27:47 +04:00
board_nor_data . parts = nor_parts ;
board_nor_data . nr_parts = nr_parts ;
2010-02-15 21:03:33 +03:00
/* Configure start address and size of NOR device */
if ( omap_rev ( ) > = OMAP3430_REV_ES1_0 ) {
err = gpmc_cs_request ( cs , FLASH_SIZE_SDPV2 - 1 ,
2010-07-09 18:27:47 +04:00
( unsigned long * ) & board_nor_resource . start ) ;
board_nor_resource . end = board_nor_resource . start
2010-02-15 21:03:33 +03:00
+ FLASH_SIZE_SDPV2 - 1 ;
} else {
err = gpmc_cs_request ( cs , FLASH_SIZE_SDPV1 - 1 ,
2010-07-09 18:27:47 +04:00
( unsigned long * ) & board_nor_resource . start ) ;
board_nor_resource . end = board_nor_resource . start
2010-02-15 21:03:33 +03:00
+ FLASH_SIZE_SDPV1 - 1 ;
}
if ( err < 0 ) {
2011-02-15 13:57:32 +03:00
pr_err ( " NOR: Can't request GPMC CS \n " ) ;
2010-02-15 21:03:33 +03:00
return ;
}
2010-07-09 18:27:47 +04:00
if ( platform_device_register ( & board_nor_device ) < 0 )
2011-02-15 13:57:32 +03:00
pr_err ( " Unable to register NOR device \n " ) ;
2010-02-15 21:03:33 +03:00
}
# if defined(CONFIG_MTD_ONENAND_OMAP2) || \
defined ( CONFIG_MTD_ONENAND_OMAP2_MODULE )
static struct omap_onenand_platform_data board_onenand_data = {
. dma_channel = - 1 , /* disable DMA in OMAP OneNAND driver */
} ;
2012-05-10 01:19:14 +04:00
void
2010-07-09 18:27:47 +04:00
__init board_onenand_init ( struct mtd_partition * onenand_parts ,
u8 nr_parts , u8 cs )
2010-02-15 21:03:33 +03:00
{
board_onenand_data . cs = cs ;
2010-07-09 18:27:47 +04:00
board_onenand_data . parts = onenand_parts ;
board_onenand_data . nr_parts = nr_parts ;
2010-02-15 21:03:33 +03:00
gpmc_onenand_init ( & board_onenand_data ) ;
}
# endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */
# if defined(CONFIG_MTD_NAND_OMAP2) || \
defined ( CONFIG_MTD_NAND_OMAP2_MODULE )
/* Note that all values in this struct are in nanoseconds */
static struct gpmc_timings nand_timings = {
. sync_clk = 0 ,
. cs_on = 0 ,
. cs_rd_off = 36 ,
. cs_wr_off = 36 ,
. adv_on = 6 ,
. adv_rd_off = 24 ,
. adv_wr_off = 36 ,
. we_off = 30 ,
. oe_off = 48 ,
. access = 54 ,
. rd_cycle = 72 ,
. wr_cycle = 72 ,
. wr_access = 30 ,
. wr_data_mux_bus = 0 ,
} ;
2010-07-09 18:27:47 +04:00
static struct omap_nand_platform_data board_nand_data = {
2010-02-15 21:03:33 +03:00
. gpmc_t = & nand_timings ,
} ;
2010-07-09 18:27:47 +04:00
void
2011-01-28 13:12:03 +03:00
__init board_nand_init ( struct mtd_partition * nand_parts ,
u8 nr_parts , u8 cs , int nand_type )
2010-02-15 21:03:33 +03:00
{
2010-07-09 18:27:47 +04:00
board_nand_data . cs = cs ;
board_nand_data . parts = nand_parts ;
2011-01-28 13:12:03 +03:00
board_nand_data . nr_parts = nr_parts ;
board_nand_data . devsize = nand_type ;
2010-02-15 21:03:33 +03:00
2011-01-28 13:12:08 +03:00
board_nand_data . ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT ;
2010-07-09 18:27:47 +04:00
gpmc_nand_init ( & board_nand_data ) ;
2010-02-15 21:03:33 +03:00
}
# endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
/**
* get_gpmc0_type - Reads the FPGA DIP_SWITCH_INPUT_REGISTER2 to get
* the various cs values .
*/
static u8 get_gpmc0_type ( void )
{
u8 cs = 0 ;
void __iomem * fpga_map_addr ;
fpga_map_addr = ioremap ( DEBUG_BASE , 4096 ) ;
if ( ! fpga_map_addr )
return - ENOMEM ;
if ( ! ( __raw_readw ( fpga_map_addr + REG_FPGA_REV ) ) )
/* we dont have an DEBUG FPGA??? */
/* Depend on #defines!! default to strata boot return param */
goto unmap ;
/* S8-DIP-OFF = 1, S8-DIP-ON = 0 */
cs = __raw_readw ( fpga_map_addr + REG_FPGA_DIP_SWITCH_INPUT2 ) & 0xf ;
/* ES2.0 SDP's onwards 4 dip switches are provided for CS */
if ( omap_rev ( ) > = OMAP3430_REV_ES1_0 )
/* change (S8-1:4=DS-2:0) to (S8-4:1=DS-2:0) */
cs = ( ( cs & 8 ) > > 3 ) | ( ( cs & 4 ) > > 1 ) |
( ( cs & 2 ) < < 1 ) | ( ( cs & 1 ) < < 3 ) ;
else
/* change (S8-1:3=DS-2:0) to (S8-3:1=DS-2:0) */
cs = ( ( cs & 4 ) > > 2 ) | ( cs & 2 ) | ( ( cs & 1 ) < < 2 ) ;
unmap :
iounmap ( fpga_map_addr ) ;
return cs ;
}
/**
2011-02-15 13:57:31 +03:00
* board_flash_init - Identify devices connected to GPMC and register .
2010-02-15 21:03:33 +03:00
*
* @ return - void .
*/
2012-02-20 21:43:30 +04:00
void __init board_flash_init ( struct flash_partitions partition_info [ ] ,
2011-01-28 13:12:03 +03:00
char chip_sel_board [ ] [ GPMC_CS_NUM ] , int nand_type )
2010-02-15 21:03:33 +03:00
{
u8 cs = 0 ;
u8 norcs = GPMC_CS_NUM + 1 ;
u8 nandcs = GPMC_CS_NUM + 1 ;
u8 onenandcs = GPMC_CS_NUM + 1 ;
u8 idx ;
unsigned char * config_sel = NULL ;
/* REVISIT: Is this return correct idx for 2430 SDP?
* for which cs configuration matches for 2430 SDP ?
*/
idx = get_gpmc0_type ( ) ;
if ( idx > = MAX_SUPPORTED_GPMC_CONFIG ) {
2011-02-15 13:57:32 +03:00
pr_err ( " %s: Invalid chip select: %d \n " , __func__ , cs ) ;
2010-02-15 21:03:33 +03:00
return ;
}
2010-07-09 18:27:47 +04:00
config_sel = ( unsigned char * ) ( chip_sel_board [ idx ] ) ;
2010-02-15 21:03:33 +03:00
while ( cs < GPMC_CS_NUM ) {
switch ( config_sel [ cs ] ) {
case PDC_NOR :
if ( norcs > GPMC_CS_NUM )
norcs = cs ;
break ;
case PDC_NAND :
if ( nandcs > GPMC_CS_NUM )
nandcs = cs ;
break ;
case PDC_ONENAND :
if ( onenandcs > GPMC_CS_NUM )
onenandcs = cs ;
break ;
} ;
cs + + ;
}
if ( norcs > GPMC_CS_NUM )
2011-02-15 13:57:32 +03:00
pr_err ( " NOR: Unable to find configuration in GPMC \n " ) ;
2010-02-15 21:03:33 +03:00
else
2010-07-09 18:27:47 +04:00
board_nor_init ( partition_info [ 0 ] . parts ,
partition_info [ 0 ] . nr_parts , norcs ) ;
2010-02-15 21:03:33 +03:00
if ( onenandcs > GPMC_CS_NUM )
2011-02-15 13:57:32 +03:00
pr_err ( " OneNAND: Unable to find configuration in GPMC \n " ) ;
2010-02-15 21:03:33 +03:00
else
2010-07-09 18:27:47 +04:00
board_onenand_init ( partition_info [ 1 ] . parts ,
partition_info [ 1 ] . nr_parts , onenandcs ) ;
2010-02-15 21:03:33 +03:00
if ( nandcs > GPMC_CS_NUM )
2011-02-15 13:57:32 +03:00
pr_err ( " NAND: Unable to find configuration in GPMC \n " ) ;
2010-02-15 21:03:33 +03:00
else
2010-07-09 18:27:47 +04:00
board_nand_init ( partition_info [ 2 ] . parts ,
2011-01-28 13:12:03 +03:00
partition_info [ 2 ] . nr_parts , nandcs , nand_type ) ;
2010-02-15 21:03:33 +03:00
}