2018-12-28 00:32:24 -08:00
// SPDX-License-Identifier: GPL-2.0
2007-05-14 15:59:09 +09:00
/*
* arch / sh / kernel / machvec . c
*
* The SuperH machine vector setup handlers , yanked from setup . c
*
* Copyright ( C ) 1999 Niibe Yutaka
* Copyright ( C ) 2002 - 2007 Paul Mundt
*/
# include <linux/init.h>
# include <linux/string.h>
# include <asm/machvec.h>
# include <asm/sections.h>
2009-09-28 15:05:41 +09:00
# include <asm/addrspace.h>
2008-09-04 18:53:58 +09:00
# include <asm/setup.h>
2007-05-14 15:59:09 +09:00
# include <asm/io.h>
# include <asm/irq.h>
2020-08-06 14:35:11 +02:00
# include <asm/processor.h>
2007-05-14 15:59:09 +09:00
# define MV_NAME_SIZE 32
# define for_each_mv(mv) \
2022-09-07 16:40:44 -07:00
for ( ( mv ) = ( struct sh_machine_vector * ) __machvec_start ; \
( mv ) & & ( unsigned long ) ( mv ) < ( unsigned long ) __machvec_end ; \
2007-05-14 15:59:09 +09:00
( mv ) + + )
static struct sh_machine_vector * __init get_mv_byname ( const char * name )
{
struct sh_machine_vector * mv ;
for_each_mv ( mv )
2007-05-15 15:19:34 +09:00
if ( strcasecmp ( name , mv - > mv_name ) = = 0 )
2007-05-14 15:59:09 +09:00
return mv ;
return NULL ;
}
2007-05-15 15:38:30 +09:00
static unsigned int __initdata machvec_selected ;
2007-05-14 15:59:09 +09:00
static int __init early_parse_mv ( char * from )
{
char mv_name [ MV_NAME_SIZE ] = " " ;
char * mv_end ;
char * mv_comma ;
int mv_len ;
struct sh_machine_vector * mvp ;
mv_end = strchr ( from , ' ' ) ;
if ( mv_end = = NULL )
mv_end = from + strlen ( from ) ;
mv_comma = strchr ( from , ' , ' ) ;
mv_len = mv_end - from ;
if ( mv_len > ( MV_NAME_SIZE - 1 ) )
mv_len = MV_NAME_SIZE - 1 ;
memcpy ( mv_name , from , mv_len ) ;
mv_name [ mv_len ] = ' \0 ' ;
from = mv_end ;
2007-05-15 15:38:30 +09:00
machvec_selected = 1 ;
/* Boot with the generic vector */
if ( strcmp ( mv_name , " generic " ) = = 0 )
return 0 ;
2007-05-15 15:19:34 +09:00
mvp = get_mv_byname ( mv_name ) ;
if ( unlikely ( ! mvp ) ) {
2020-06-17 16:36:39 +02:00
pr_info ( " Available vectors: \n \n \t '%s', " , sh_mv . mv_name ) ;
2007-05-15 15:19:34 +09:00
for_each_mv ( mvp )
2020-06-17 16:36:39 +02:00
pr_cont ( " '%s', " , mvp - > mv_name ) ;
pr_cont ( " \n \n " ) ;
2007-05-15 15:19:34 +09:00
panic ( " Failed to select machvec '%s' -- halting. \n " ,
mv_name ) ;
} else
sh_mv = * mvp ;
2007-05-14 15:59:09 +09:00
return 0 ;
}
early_param ( " sh_mv " , early_parse_mv ) ;
void __init sh_mv_setup ( void )
{
2007-05-15 15:19:34 +09:00
/*
* Only overload the machvec if one hasn ' t been selected on
* the command line with sh_mv =
*/
2007-05-15 15:38:30 +09:00
if ( ! machvec_selected ) {
2007-05-15 15:19:34 +09:00
unsigned long machvec_size ;
2022-09-07 16:40:44 -07:00
machvec_size = ( ( unsigned long ) __machvec_end -
( unsigned long ) __machvec_start ) ;
2007-05-15 15:19:34 +09:00
2007-08-07 19:13:23 +09:00
/*
* Sanity check for machvec section alignment . Ensure
* __initmv hasn ' t been misused .
*/
if ( machvec_size % sizeof ( struct sh_machine_vector ) )
panic ( " machvec misaligned, invalid __initmv use? " ) ;
2007-05-15 15:19:34 +09:00
/*
* If the machvec hasn ' t been preselected , use the first
* vector ( usually the only one ) from . machvec . init .
*/
if ( machvec_size > = sizeof ( struct sh_machine_vector ) )
2022-09-07 16:40:44 -07:00
sh_mv = * ( struct sh_machine_vector * ) __machvec_start ;
2007-05-15 15:19:34 +09:00
}
2020-06-17 16:36:39 +02:00
pr_notice ( " Booting machvec: %s \n " , get_system_type ( ) ) ;
2007-05-15 15:19:34 +09:00
2007-05-14 15:59:09 +09:00
/*
* Manually walk the vec , fill in anything that the board hasn ' t yet
* by hand , wrapping to the generic implementation .
*/
# define mv_set(elem) do { \
if ( ! sh_mv . mv_ # # elem ) \
sh_mv . mv_ # # elem = generic_ # # elem ; \
} while ( 0 )
mv_set ( irq_demux ) ;
2009-05-28 11:51:51 +00:00
mv_set ( mode_pins ) ;
2010-05-10 15:39:05 +09:00
mv_set ( mem_init ) ;
2007-05-14 15:59:09 +09:00
}