2009-01-09 03:46:40 +03:00
/*
* Octeon Bootbus flash setup
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
* Copyright ( C ) 2007 , 2008 Cavium Networks
*/
# include <linux/kernel.h>
2015-03-05 17:31:31 +03:00
# include <linux/module.h>
2015-03-05 17:31:30 +03:00
# include <linux/semaphore.h>
2009-01-09 03:46:40 +03:00
# include <linux/mtd/mtd.h>
# include <linux/mtd/map.h>
2015-03-05 17:31:31 +03:00
# include <linux/of_platform.h>
2009-01-09 03:46:40 +03:00
# include <linux/mtd/partitions.h>
# include <asm/octeon/octeon.h>
static struct map_info flash_map ;
static struct mtd_info * mymtd ;
static const char * part_probe_types [ ] = {
" cmdlinepart " ,
# ifdef CONFIG_MTD_REDBOOT_PARTS
" RedBoot " ,
# endif
NULL
} ;
2015-03-05 17:31:30 +03:00
static map_word octeon_flash_map_read ( struct map_info * map , unsigned long ofs )
{
map_word r ;
down ( & octeon_bootbus_sem ) ;
r = inline_map_read ( map , ofs ) ;
up ( & octeon_bootbus_sem ) ;
return r ;
}
static void octeon_flash_map_write ( struct map_info * map , const map_word datum ,
unsigned long ofs )
{
down ( & octeon_bootbus_sem ) ;
inline_map_write ( map , datum , ofs ) ;
up ( & octeon_bootbus_sem ) ;
}
static void octeon_flash_map_copy_from ( struct map_info * map , void * to ,
unsigned long from , ssize_t len )
{
down ( & octeon_bootbus_sem ) ;
inline_map_copy_from ( map , to , from , len ) ;
up ( & octeon_bootbus_sem ) ;
}
static void octeon_flash_map_copy_to ( struct map_info * map , unsigned long to ,
const void * from , ssize_t len )
{
down ( & octeon_bootbus_sem ) ;
inline_map_copy_to ( map , to , from , len ) ;
up ( & octeon_bootbus_sem ) ;
}
2009-01-09 03:46:40 +03:00
/**
* Module / driver initialization .
*
* Returns Zero on success
*/
2015-03-05 17:31:31 +03:00
static int octeon_flash_probe ( struct platform_device * pdev )
2009-01-09 03:46:40 +03:00
{
2015-03-05 17:31:31 +03:00
union cvmx_mio_boot_reg_cfgx region_cfg ;
u32 cs ;
int r ;
struct device_node * np = pdev - > dev . of_node ;
r = of_property_read_u32 ( np , " reg " , & cs ) ;
if ( r )
return r ;
2009-01-09 03:46:40 +03:00
/*
* Read the bootbus region 0 setup to determine the base
* address of the flash .
*/
2015-03-05 17:31:31 +03:00
region_cfg . u64 = cvmx_read_csr ( CVMX_MIO_BOOT_REG_CFGX ( cs ) ) ;
2009-01-09 03:46:40 +03:00
if ( region_cfg . s . en ) {
/*
* The bootloader always takes the flash and sets its
* address so the entire flash fits below
* 0x1fc00000 . This way the flash aliases to
* 0x1fc00000 for booting . Software can access the
* full flash at the true address , while core boot can
* access 4 MB .
*/
/* Use this name so old part lines work */
flash_map . name = " phys_mapped_flash " ;
flash_map . phys = region_cfg . s . base < < 16 ;
flash_map . size = 0x1fc00000 - flash_map . phys ;
2012-09-05 23:19:48 +04:00
/* 8-bit bus (0 + 1) or 16-bit bus (1 + 1) */
flash_map . bankwidth = region_cfg . s . width + 1 ;
2009-01-09 03:46:40 +03:00
flash_map . virt = ioremap ( flash_map . phys , flash_map . size ) ;
pr_notice ( " Bootbus flash: Setting flash for %luMB flash at "
2009-03-30 16:49:41 +04:00
" 0x%08llx \n " , flash_map . size > > 20 , flash_map . phys ) ;
2015-03-05 17:31:30 +03:00
WARN_ON ( ! map_bankwidth_supported ( flash_map . bankwidth ) ) ;
flash_map . read = octeon_flash_map_read ;
flash_map . write = octeon_flash_map_write ;
flash_map . copy_from = octeon_flash_map_copy_from ;
flash_map . copy_to = octeon_flash_map_copy_to ;
2009-01-09 03:46:40 +03:00
mymtd = do_map_probe ( " cfi_probe " , & flash_map ) ;
if ( mymtd ) {
mymtd - > owner = THIS_MODULE ;
2011-11-10 21:59:45 +04:00
mtd_device_parse_register ( mymtd , part_probe_types ,
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 21:24:26 +04:00
NULL , NULL , 0 ) ;
2009-01-09 03:46:40 +03:00
} else {
pr_err ( " Failed to register MTD device for flash \n " ) ;
}
}
return 0 ;
}
2015-03-05 17:31:31 +03:00
static const struct of_device_id of_flash_match [ ] = {
{
. compatible = " cfi-flash " ,
} ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , of_flash_match ) ;
static struct platform_driver of_flash_driver = {
. driver = {
. name = " octeon-of-flash " ,
. of_match_table = of_flash_match ,
} ,
. probe = octeon_flash_probe ,
} ;
static int octeon_flash_init ( void )
{
return platform_driver_register ( & of_flash_driver ) ;
}
late_initcall ( octeon_flash_init ) ;
MODULE_LICENSE ( " GPL " ) ;